ui/resize_checker 👉 src/plugins/kibana_utils (#44750)

* Moved ResizeChecker to kibana_utils.

* Removed ResizeChecker from __LEGACY.
This commit is contained in:
sainthkh 2019-11-17 23:22:03 +09:00 committed by Liza Katz
parent 18e587fbfe
commit d7f2ebc308
19 changed files with 223 additions and 253 deletions

View file

@ -62,10 +62,6 @@ describe('Legacy (Ace) Console Editor Component Smoke Test', () => {
updateCurrentState: () => {},
},
},
// eslint-disable-next-line
ResizeChecker: function() {
return { on: () => {} };
},
docLinkVersion: 'NA',
};
editor = mount(

View file

@ -63,7 +63,6 @@ const DEFAULT_INPUT_VALUE = `GET _search
function _Editor({ previousStateLocation = 'stored' }: EditorProps) {
const {
services: { history, notifications },
ResizeChecker,
docLinkVersion,
} = useAppContext();
@ -130,7 +129,6 @@ function _Editor({ previousStateLocation = 'stored' }: EditorProps) {
mappings.retrieveAutoCompleteInfo();
const unsubscribeResizer = subscribeResizeChecker(
ResizeChecker,
editorRef.current!,
editorInstanceRef.current
);

View file

@ -31,7 +31,6 @@ function _EditorOuput() {
const editorInstanceRef = useRef<null | any>(null);
const {
services: { settings },
ResizeChecker,
} = useAppContext();
const dispatch = useEditorActionContext();
@ -42,11 +41,7 @@ function _EditorOuput() {
const editor$ = $(editorRef.current!);
editorInstanceRef.current = initializeOutput(editor$, settings);
editorInstanceRef.current.update('');
const unsubscribe = subscribeResizeChecker(
ResizeChecker,
editorRef.current!,
editorInstanceRef.current
);
const unsubscribe = subscribeResizeChecker(editorRef.current!, editorInstanceRef.current);
dispatch({ type: 'setOutputEditor', value: editorInstanceRef.current });

View file

@ -45,7 +45,6 @@ const CHILD_ELEMENT_PREFIX = 'historyReq';
export function ConsoleHistory({ close }: Props) {
const {
services: { history },
ResizeChecker,
} = useAppContext();
const dispatch = useEditorActionContext();
@ -200,7 +199,6 @@ export function ConsoleHistory({ close }: Props) {
<HistoryViewer
settings={readOnlySettings}
req={viewingReq}
ResizeChecker={ResizeChecker}
/>
</div>

View file

@ -31,10 +31,9 @@ import { applyCurrentSettings } from '../console_editor/apply_editor_settings';
interface Props {
settings: DevToolsSettings;
req: any | null;
ResizeChecker: any;
}
export function HistoryViewer({ settings, ResizeChecker, req }: Props) {
export function HistoryViewer({ settings, req }: Props) {
const divRef = useRef<HTMLDivElement | null>(null);
const viewerRef = useRef<any | null>(null);
@ -43,7 +42,7 @@ export function HistoryViewer({ settings, ResizeChecker, req }: Props) {
viewerRef.current = viewer;
viewer.renderer.setShowPrintMargin(false);
viewer.$blockScrolling = Infinity;
const unsubscribe = subscribeResizeChecker(ResizeChecker, divRef.current!, viewer);
const unsubscribe = subscribeResizeChecker(divRef.current!, viewer);
return () => unsubscribe();
}, []);

View file

@ -16,9 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ResizeChecker } from '../../../../../../../../../plugins/kibana_utils/public';
export function subscribeResizeChecker(ResizeChecker: any, $el: any, ...editors: any[]) {
const checker = new ResizeChecker($el);
export function subscribeResizeChecker(el: HTMLElement, ...editors: any[]) {
const checker = new ResizeChecker(el);
checker.on('resize', () =>
editors.forEach(e => {
e.resize();

View file

@ -29,7 +29,6 @@ interface ContextValue {
notifications: NotificationsSetup;
};
docLinkVersion: string;
ResizeChecker: any;
}
interface ContextProps {

View file

@ -32,10 +32,9 @@ export function legacyBackDoorToSettings() {
export function boot(deps: {
docLinkVersion: string;
I18nContext: any;
ResizeChecker: any;
notifications: NotificationsSetup;
}) {
const { I18nContext, ResizeChecker, notifications, docLinkVersion } = deps;
const { I18nContext, notifications, docLinkVersion } = deps;
const storage = createStorage({
engine: window.localStorage,
@ -51,7 +50,6 @@ export function boot(deps: {
value={{
docLinkVersion,
services: { storage, history, settings, notifications },
ResizeChecker,
}}
>
<EditorContextProvider settings={settings.toJSON()}>

View file

@ -26,7 +26,6 @@ import 'brace/mode/text';
/* eslint-disable @kbn/eslint/no-restricted-paths */
import { npSetup, npStart } from 'ui/new_platform';
import { I18nContext } from 'ui/i18n';
import { ResizeChecker } from 'ui/resize_checker';
/* eslint-enable @kbn/eslint/no-restricted-paths */
export interface XPluginSet {
@ -34,7 +33,6 @@ export interface XPluginSet {
feature_catalogue: FeatureCatalogueSetup;
__LEGACY: {
I18nContext: any;
ResizeChecker: any;
};
}
@ -48,7 +46,6 @@ pluginInstance.setup(npSetup.core, {
...npSetup.plugins,
__LEGACY: {
I18nContext,
ResizeChecker,
},
});
pluginInstance.start(npStart.core);

View file

@ -30,7 +30,7 @@ export class ConsoleUIPlugin implements Plugin<any, any> {
async setup({ notifications }: CoreSetup, pluginSet: XPluginSet) {
const {
__LEGACY: { I18nContext, ResizeChecker },
__LEGACY: { I18nContext },
devTools,
feature_catalogue,
} = pluginSet;
@ -62,7 +62,6 @@ export class ConsoleUIPlugin implements Plugin<any, any> {
boot({
docLinkVersion: ctx.core.docLinks.DOC_LINK_VERSION,
I18nContext,
ResizeChecker,
notifications,
}),
element

View file

@ -1,208 +0,0 @@
/*
* 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 $ from 'jquery';
import { delay } from 'bluebird';
import expect from '@kbn/expect';
import sinon from 'sinon';
import ngMock from 'ng_mock';
import NoDigestPromises from 'test_utils/no_digest_promises';
import { ResizeChecker } from '../resize_checker';
import EventEmitter from 'events';
describe('Resize Checker', () => {
NoDigestPromises.activateForSuite();
const teardown = [];
let setup;
beforeEach(ngMock.module('kibana'));
beforeEach(() => {
setup = () => {
const createEl = () => {
const el = $('<div>').appendTo('body').get(0);
teardown.push(() => $(el).remove());
return el;
};
const createChecker = el => {
const checker = new ResizeChecker(el);
teardown.push(() => checker.destroy());
return checker;
};
const createListener = () => {
let resolveFirstCallPromise;
const listener = sinon.spy(() => resolveFirstCallPromise());
listener.firstCallPromise = new Promise(resolve => (resolveFirstCallPromise = resolve));
return listener;
};
return { createEl, createChecker, createListener };
};
});
afterEach(() => {
teardown.splice(0).forEach(fn => {
fn();
});
});
describe('construction', () => {
it('accepts a jQuery wrapped element', () => {
const { createChecker } = setup();
createChecker($('<div>'));
});
});
describe('events', () => {
it('is an event emitter', () => {
const { createEl, createChecker } = setup();
const checker = createChecker(createEl());
expect(checker).to.be.a(EventEmitter);
});
it('emits a "resize" event asynchronously', async () => {
const { createEl, createChecker, createListener } = setup();
const el = createEl();
const checker = createChecker(el);
const listener = createListener();
checker.on('resize', listener);
$(el).height(100);
sinon.assert.notCalled(listener);
await listener.firstCallPromise;
sinon.assert.calledOnce(listener);
});
});
describe('enable/disabled state', () => {
it('should not trigger events while disabled', async () => {
const { createEl, createListener } = setup();
const el = createEl();
const checker = new ResizeChecker(el, { disabled: true });
const listener = createListener();
checker.on('resize', listener);
expect(listener.notCalled).to.be(true);
$(el).height(100);
await delay(1000);
expect(listener.notCalled).to.be(true);
});
it('should trigger resize events after calling enable', async () => {
const { createEl, createListener } = setup();
const el = createEl();
const checker = new ResizeChecker(el, { disabled: true });
const listener = createListener();
checker.on('resize', listener);
expect(listener.notCalled).to.be(true);
checker.enable();
$(el).height(100);
await listener.firstCallPromise;
expect(listener.calledOnce).to.be(true);
});
it('should not trigger the first time after enable when the size does not change', async () => {
const { createEl, createListener } = setup();
const el = createEl();
const checker = new ResizeChecker(el, { disabled: true });
const listener = createListener();
checker.on('resize', listener);
expect(listener.notCalled).to.be(true);
$(el).height(250);
checker.enable();
$(el).height(250);
await delay(1000);
expect(listener.notCalled).to.be(true);
});
});
describe('#modifySizeWithoutTriggeringResize()', () => {
it(`does not emit "resize" events caused by the block`, async () => {
const { createChecker, createEl, createListener } = setup();
const el = createEl();
const checker = createChecker(el);
const listener = createListener();
checker.on('resize', listener);
checker.modifySizeWithoutTriggeringResize(() => {
$(el).height(100);
});
await delay(1000);
sinon.assert.notCalled(listener);
});
it('does emit "resize" when modification is made between the block and resize notification', async () => {
const { createChecker, createEl, createListener } = setup();
const el = createEl();
const checker = createChecker(el);
const listener = createListener();
checker.on('resize', listener);
checker.modifySizeWithoutTriggeringResize(() => {
$(el).height(100);
});
sinon.assert.notCalled(listener);
$(el).height(200);
await listener.firstCallPromise;
sinon.assert.calledOnce(listener);
});
});
describe('#destroy()', () => {
it('destroys internal observer instance', () => {
const { createChecker, createEl, createListener } = setup();
const checker = createChecker(createEl());
createListener();
checker.destroy();
expect(!checker._observer).to.be(true);
});
it('does not emit future resize events', async () => {
const { createChecker, createEl, createListener } = setup();
const el = createEl();
const checker = createChecker(el);
const listener = createListener();
checker.on('resize', listener);
checker.destroy();
$(el).height(100);
await delay(1000);
sinon.assert.notCalled(listener);
});
});
});

View file

@ -22,7 +22,7 @@ import * as Rx from 'rxjs';
import { debounceTime, filter, share, switchMap } from 'rxjs/operators';
import { PersistedState } from '../../persisted_state';
import { ResizeChecker } from '../../resize_checker';
import { ResizeChecker } from '../../../../../plugins/kibana_utils/public';
import { Vis, VisualizationController } from '../../vis';
import { getUpdateStatus } from '../../vis/update_status';

View file

@ -21,6 +21,7 @@ export * from './core';
export * from './errors';
export * from './store';
export * from './parse';
export * from './resize_checker';
export * from './render_complete';
export * from './store';
export * from './errors';

View file

@ -0,0 +1,199 @@
/*
* 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 { ResizeChecker } from './resize_checker';
import { EventEmitter } from 'events';
// If you want to know why these mocks are created,
// please check: https://github.com/elastic/kibana/pull/44750
jest.mock('resize-observer-polyfill');
import ResizeObserver from 'resize-observer-polyfill';
class MockElement {
public clientWidth: number;
public clientHeight: number;
private onResize: any;
constructor() {
this.clientHeight = 0;
this.clientWidth = 0;
this.onResize = null;
}
public addEventListener(name: string, listener: any) {
this.onResize = listener;
}
public dispatchEvent(name: string) {
if (this.onResize) {
this.onResize();
}
}
public removeEventListener(name: string, listener: any) {
this.onResize = null;
}
}
(ResizeObserver as any).mockImplementation(function(this: any, callback: any) {
this.observe = function(el: MockElement) {
el.addEventListener('resize', callback);
};
this.disconnect = function() {};
this.unobserve = function(el: MockElement) {
el.removeEventListener('resize', callback);
};
});
describe('Resize Checker', () => {
describe('events', () => {
it('is an event emitter', () => {
const el = new MockElement();
const checker = new ResizeChecker(el as any);
expect(checker).toBeInstanceOf(EventEmitter);
});
it('emits a "resize" event', done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any);
const listener = jest.fn();
checker.on('resize', listener);
el.clientHeight = 100;
el.dispatchEvent('resize');
setTimeout(() => {
expect(listener.mock.calls.length).toBe(1);
done();
}, 100);
});
});
describe('enable/disabled state', () => {
it('should not trigger events while disabled', done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
const listener = jest.fn();
checker.on('resize', listener);
expect(listener).not.toBeCalled();
el.clientHeight = 100;
el.dispatchEvent('resize');
setTimeout(() => {
expect(listener).not.toBeCalled();
done();
}, 100);
});
it('should trigger resize events after calling enable', done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
const listener = jest.fn();
checker.on('resize', listener);
expect(listener).not.toBeCalled();
checker.enable();
el.clientHeight = 100;
el.dispatchEvent('resize');
setTimeout(() => {
expect(listener).toBeCalled();
done();
}, 100);
});
it('should not trigger the first time after enable when the size does not change', done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
const listener = jest.fn();
checker.on('resize', listener);
expect(listener).not.toBeCalled();
el.clientHeight = 100;
checker.enable();
el.clientHeight = 100;
setTimeout(() => {
expect(listener).not.toBeCalled();
done();
}, 100);
});
});
describe('#modifySizeWithoutTriggeringResize()', () => {
it(`does not emit "resize" events caused by the block`, done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
const listener = jest.fn();
checker.on('resize', listener);
checker.modifySizeWithoutTriggeringResize(() => {
el.clientHeight = 100;
});
el.dispatchEvent('resize');
setTimeout(() => {
expect(listener).not.toBeCalled();
done();
}, 1000);
});
it('does emit "resize" when modification is made between the block and resize notification', done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
const listener = jest.fn();
checker.on('resize', listener);
checker.modifySizeWithoutTriggeringResize(() => {
el.clientHeight = 100;
});
el.dispatchEvent('resize');
expect(listener).not.toBeCalled();
el.clientHeight = 200;
el.dispatchEvent('resize');
setTimeout(() => {
expect(listener).not.toBeCalled();
done();
}, 100);
});
});
describe('#destroy()', () => {
it('destroys internal observer instance', () => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
checker.destroy();
expect(!(checker as any).observer).toBe(true);
});
it('does not emit future resize events', done => {
const el = new MockElement();
const checker = new ResizeChecker(el as any, { disabled: true });
const listener = jest.fn();
checker.on('resize', listener);
checker.destroy();
el.clientHeight = 100;
el.dispatchEvent('resize');
setTimeout(() => {
expect(listener).not.toBeCalled();
done();
}, 100);
});
});
});

View file

@ -18,22 +18,9 @@
*/
import { EventEmitter } from 'events';
import $ from 'jquery';
import { isEqual } from 'lodash';
import ResizeObserver from 'resize-observer-polyfill';
function validateElArg(el: HTMLElement) {
// the ResizeChecker historically accepted jquery elements,
// so we wrap in jQuery then extract the element
const $el = $(el);
if ($el.length !== 1) {
throw new TypeError('ResizeChecker must be constructed with a single DOM element.');
}
return $el.get(0);
}
function getSize(el: HTMLElement): [number, number] {
return [el.clientWidth, el.clientHeight];
}
@ -50,7 +37,7 @@ export class ResizeChecker extends EventEmitter {
constructor(el: HTMLElement, args: { disabled?: boolean } = {}) {
super();
this.el = validateElArg(el);
this.el = el;
this.observer = new ResizeObserver(() => {
if (this.expectedSize) {

View file

@ -35,6 +35,8 @@ GET _search
export default function({ getService, getPageObjects }: FtrProviderContext) {
const retry = getService('retry');
const log = getService('log');
const find = getService('find');
const browser = getService('browser');
const PageObjects = getPageObjects(['common', 'console']);
describe('console app', function describeIndexTests() {
@ -81,5 +83,14 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
expect(await PageObjects.console.getRequestFontSize()).to.be('24px');
});
});
it('should resize the editor', async () => {
const editor = await find.byCssSelector('.conApp');
await browser.setWindowSize(1300, 1100);
const initialSize = await editor.getSize();
await browser.setWindowSize(1000, 1100);
const afterSize = await editor.getSize();
expect(initialSize.width).to.be.greaterThan(afterSize.width);
});
});
}

View file

@ -6,7 +6,7 @@
import _ from 'lodash';
import React from 'react';
import { ResizeChecker } from 'ui/resize_checker';
import { ResizeChecker } from '../../../../../../../../src/plugins/kibana_utils/public';
import {
syncLayerOrderForSingleLayer,
removeOrphanedSourcesAndLayers,

View file

@ -32,7 +32,7 @@ import {
import chrome from 'ui/chrome';
import { toastNotifications } from 'ui/notify';
import { ResizeChecker } from 'ui/resize_checker';
import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public';
import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../common/constants/search';
import { parseInterval } from '../../common/util/parse_interval';