Skip to content

Commit

Permalink
Merge branch 'master' into fix/form-lib-memoize
Browse files Browse the repository at this point in the history
  • Loading branch information
elasticmachine authored Jul 13, 2020
2 parents 5fbb648 + f4b4dc5 commit 923471f
Show file tree
Hide file tree
Showing 26 changed files with 912 additions and 331 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"**/@types/hoist-non-react-statics": "^3.3.1",
"**/@types/chai": "^4.2.11",
"**/cypress/@types/lodash": "^4.14.155",
"**/cypress/lodash": "^4.15.19",
"**/typescript": "3.9.5",
"**/graphql-toolkit/lodash": "^4.17.15",
"**/hoist-non-react-statics": "^3.3.2",
Expand Down Expand Up @@ -255,7 +256,6 @@
"redux-actions": "^2.6.5",
"redux-thunk": "^2.3.0",
"regenerator-runtime": "^0.13.3",
"regression": "2.0.1",
"request": "^2.88.0",
"require-in-the-middle": "^5.0.2",
"reselect": "^4.0.0",
Expand Down Expand Up @@ -407,7 +407,7 @@
"babel-eslint": "^10.0.3",
"babel-jest": "^25.5.1",
"babel-plugin-istanbul": "^6.0.0",
"backport": "5.4.6",
"backport": "5.5.1",
"chai": "3.5.0",
"chance": "1.0.18",
"cheerio": "0.22.0",
Expand Down
7 changes: 6 additions & 1 deletion scripts/backport.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@
*/

require('../src/setup_node_env/node_version_validator');
var process = require('process');

// forward command line args to backport
var args = process.argv.slice(2);

var backport = require('backport');
backport.run();
backport.run({}, args);
4 changes: 2 additions & 2 deletions src/plugins/data/common/field_formats/converters/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
} from '../types';

const templateMatchRE = /{{([\s\S]+?)}}/g;
const whitelistUrlSchemes = ['http://', 'https://'];
const allowedUrlSchemes = ['http://', 'https://'];

const URL_TYPES = [
{
Expand Down Expand Up @@ -161,7 +161,7 @@ export class UrlFormat extends FieldFormat {

return this.generateImgHtml(url, imageLabel);
default:
const inWhitelist = whitelistUrlSchemes.some((scheme) => url.indexOf(scheme) === 0);
const inWhitelist = allowedUrlSchemes.some((scheme) => url.indexOf(scheme) === 0);
if (!inWhitelist && !parsedUrl) {
return url;
}
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1991,7 +1991,7 @@ export const UI_SETTINGS: {
// src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:40:60 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:41:60 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:53:5 - (ae-forgotten-export) The symbol "createFiltersFromRangeSelectAction" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:61:5 - (ae-forgotten-export) The symbol "IndexPatternSelectProps" needs to be exported by the entry point index.d.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { BaseStateContainer } from '../../../../kibana_utils/public';
import { QuerySetup, QueryStart } from '../query_service';
import { QueryState, QueryStateChange } from './types';
import { FilterStateStore, COMPARE_ALL_OPTIONS, compareFilters } from '../../../common';
import { validateTimeRange } from '../timefilter';

/**
* Helper to setup two-way syncing of global data and a state container
Expand Down Expand Up @@ -159,9 +160,9 @@ export const connectToQueryState = <S extends QueryState>(
// cloneDeep is required because services are mutating passed objects
// and state in state container is frozen
if (syncConfig.time) {
const time = state.time || timefilter.getTimeDefaults();
const time = validateTimeRange(state.time) ? state.time : timefilter.getTimeDefaults();
if (!_.isEqual(time, timefilter.getTime())) {
timefilter.setTime(_.cloneDeep(time));
timefilter.setTime(_.cloneDeep(time!));
}
}

Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/public/query/timefilter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ export { Timefilter, TimefilterContract } from './timefilter';
export { TimeHistory, TimeHistoryContract } from './time_history';
export { changeTimeFilter, convertRangeFilterToTimeRangeString } from './lib/change_time_filter';
export { extractTimeFilter } from './lib/extract_time_filter';
export { validateTimeRange } from './lib/validate_timerange';
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,37 @@
* specific language governing permissions and limitations
* under the License.
*/
import { PluginInitializerContext } from 'kibana/public';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { npStart, npSetup } from 'ui/new_platform';
import {
TableVisPlugin,
TablePluginSetupDependencies,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../../plugins/vis_type_table/public/plugin';

const plugins: Readonly<TablePluginSetupDependencies> = {
expressions: npSetup.plugins.expressions,
visualizations: npSetup.plugins.visualizations,
};
import { validateTimeRange } from './validate_timerange';

const pluginInstance = new TableVisPlugin({} as PluginInitializerContext);
describe('Validate timerange', () => {
test('Validate no range', () => {
const ok = validateTimeRange();

export const setup = pluginInstance.setup(npSetup.core, plugins);
export const start = pluginInstance.start(npStart.core, {
data: npStart.plugins.data,
kibanaLegacy: npStart.plugins.kibanaLegacy,
expect(ok).toBe(false);
});
test('normal range', () => {
const ok = validateTimeRange({
to: 'now',
from: 'now-7d',
});

expect(ok).toBe(true);
});
test('bad from time', () => {
const ok = validateTimeRange({
to: 'nowa',
from: 'now-7d',
});

expect(ok).toBe(false);
});
test('bad to time', () => {
const ok = validateTimeRange({
to: 'now',
from: 'nowa-7d',
});

expect(ok).toBe(false);
});
});
28 changes: 28 additions & 0 deletions src/plugins/data/public/query/timefilter/lib/validate_timerange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import dateMath from '@elastic/datemath';
import { TimeRange } from '../../../../common';

export function validateTimeRange(time?: TimeRange): boolean {
if (!time) return false;
const momentDateFrom = dateMath.parse(time.from);
const momentDateTo = dateMath.parse(time.to);
return !!(momentDateFrom && momentDateFrom.isValid() && momentDateTo && momentDateTo.isValid());
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function findAll<T extends SavedObjectAttributes>(
savedObjectsClient: ISavedObjectsRepository,
opts: SavedObjectsFindOptions
): Promise<Array<SavedObject<T>>> {
const { page = 1, perPage = 100, ...options } = opts;
const { page = 1, perPage = 10000, ...options } = opts;
const { saved_objects: savedObjects, total } = await savedObjectsClient.find<T>({
...options,
page,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ describe('hash unhash url', () => {
expect(mockStorage.length).toBe(3);
});

it('hashes only whitelisted properties', () => {
it('hashes only allow-listed properties', () => {
const stateParamKey1 = '_g';
const stateParamValue1 = '(yes:!t)';
const stateParamKey2 = '_a';
Expand Down Expand Up @@ -227,7 +227,7 @@ describe('hash unhash url', () => {
);
});

it('unhashes only whitelisted properties', () => {
it('un-hashes only allow-listed properties', () => {
const stateParamKey1 = '_g';
const stateParamValueHashed1 = 'h@4e60e02';
const state1 = { yes: true };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const hashUrl = createQueryReplacer(hashQuery);

// naive hack, but this allows to decouple these utils from AppState, GlobalState for now
// when removing AppState, GlobalState and migrating to IState containers,
// need to make sure that apps explicitly passing this whitelist to hash
// need to make sure that apps explicitly passing this allow-list to hash
const __HACK_HARDCODED_LEGACY_HASHABLE_PARAMS = ['_g', '_a', '_s'];
function createQueryMapper(queryParamMapper: (q: string) => string | null) {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { createInteractionPositionTracker } from './open_context_menu';
import { fireEvent } from '@testing-library/dom';

let targetEl: Element;
const top = 100;
const left = 100;
const right = 200;
const bottom = 200;
beforeEach(() => {
targetEl = document.createElement('div');
jest.spyOn(targetEl, 'getBoundingClientRect').mockImplementation(() => ({
top,
left,
right,
bottom,
width: right - left,
height: bottom - top,
x: left,
y: top,
toJSON: () => {},
}));
document.body.append(targetEl);
});
afterEach(() => {
targetEl.remove();
});

test('should use last clicked element position if mouse position is outside target element', () => {
const { resolveLastPosition } = createInteractionPositionTracker();

fireEvent.click(targetEl, { clientX: 0, clientY: 0 });
const { x, y } = resolveLastPosition();

expect(y).toBe(bottom);
expect(x).toBe(left + (right - left) / 2);
});

test('should use mouse position if mouse inside clicked element', () => {
const { resolveLastPosition } = createInteractionPositionTracker();

const mouseX = 150;
const mouseY = 150;
fireEvent.click(targetEl, { clientX: mouseX, clientY: mouseY });

const { x, y } = resolveLastPosition();

expect(y).toBe(mouseX);
expect(x).toBe(mouseY);
});

test('should use position of previous element, if latest element is no longer in DOM', () => {
const { resolveLastPosition } = createInteractionPositionTracker();

const detachedElement = document.createElement('div');
const spy = jest.spyOn(detachedElement, 'getBoundingClientRect');

fireEvent.click(targetEl);
fireEvent.click(detachedElement);

const { x, y } = resolveLastPosition();

expect(y).toBe(bottom);
expect(x).toBe(left + (right - left) / 2);
expect(spy).not.toBeCalled();
});
Loading

0 comments on commit 923471f

Please sign in to comment.