From d27d646a95b56cb6aae87b2656ac62277b112a94 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 19 Aug 2024 15:48:17 -0600 Subject: [PATCH 1/7] Refactor control settings functional tests into unit tests --- .../components/control_panel.test.tsx | 99 +++++++++++++++++++ .../components/control_panel.tsx | 9 +- .../get_control_group_factory.tsx | 6 ++ 3 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx diff --git a/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx new file mode 100644 index 0000000000000..73a716fbadc38 --- /dev/null +++ b/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useImperativeHandle } from 'react'; +import { BehaviorSubject } from 'rxjs'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ControlPanel } from './control_panel'; +import { registry as presentationUtilServicesRegistry } from '@kbn/presentation-util-plugin/public/services/plugin_services.story'; +import { pluginServices as presentationUtilPluginServices } from '@kbn/presentation-util-plugin/public/services'; +import { ControlStyle, ControlWidth } from '../../..'; + +describe('render', () => { + let mockApi = {}; + const Component = React.forwardRef((_, ref) => { + // expose the api into the imperative handle + useImperativeHandle(ref, () => mockApi, []); + + return
; + }) as any; + + beforeAll(() => { + presentationUtilServicesRegistry.start({}); + presentationUtilPluginServices.setRegistry(presentationUtilServicesRegistry); + presentationUtilPluginServices.getServices().uiActions.getTriggerCompatibleActions = jest + .fn() + .mockImplementation(() => { + return [ + { + isCompatible: jest.fn().mockResolvedValue(true), + id: 'testAction', + MenuItem: () =>
test1
, + }, + ]; + }); + }); + + beforeEach(() => { + mockApi = {}; + }); + + describe('control width', () => { + test('defaults to medium and grow enabled', async () => { + const controlPanel = render(); + await waitFor(() => { + const controlFrame = controlPanel.getByTestId('control-frame'); + expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--medium') + expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--grow') + }); + }); + + test('should use small class when using small width', async () => { + mockApi = { + uuid: 'control1', + width: new BehaviorSubject('small') + }; + const controlPanel = render(); + await waitFor(() => { + const controlFrame = controlPanel.getByTestId('control-frame'); + expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--small') + }); + }); + }); + + describe('label position', () => { + test('should use one line layout class when using one line layout', async () => { + mockApi = { + uuid: 'control1', + parentApi: { + labelPosition: new BehaviorSubject('oneLine') + } + }; + const controlPanel = render(); + await waitFor(() => { + const floatingActions = controlPanel.getByTestId('presentationUtil__floatingActions__control1'); + expect(floatingActions.getAttribute('class')).toContain('controlFrameFloatingActions--oneLine') + }); + }); + + test('should use two line layout class when using two line layout', async () => { + mockApi = { + uuid: 'control1', + parentApi: { + labelPosition: new BehaviorSubject('twoLine') + } + }; + const controlPanel = render(); + await waitFor(() => { + const floatingActions = controlPanel.getByTestId('presentationUtil__floatingActions__control1'); + expect(floatingActions.getAttribute('class')).toContain('controlFrameFloatingActions--twoLine') + }); + }); + }); +}); \ No newline at end of file diff --git a/src/plugins/controls/public/react_controls/control_group/components/control_panel.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_panel.tsx index b83b0b464b5c5..9ed24904f25cd 100644 --- a/src/plugins/controls/public/react_controls/control_group/components/control_panel.tsx +++ b/src/plugins/controls/public/react_controls/control_group/components/control_panel.tsx @@ -27,7 +27,7 @@ import { useBatchedOptionalPublishingSubjects, } from '@kbn/presentation-publishing'; import { FloatingActions } from '@kbn/presentation-util-plugin/public'; -import { DEFAULT_CONTROL_WIDTH } from '../../../../common'; +import { DEFAULT_CONTROL_GROW, DEFAULT_CONTROL_WIDTH } from '../../../../common'; import { ControlPanelProps, DefaultControlApi } from '../../controls/types'; import { ControlError } from './control_error'; @@ -121,17 +121,18 @@ export const ControlPanel = { + if (initialState.width) { + width.next(initialState.width); + } + if (typeof initialState.grow === 'boolean') { + grow.next(initialState.grow); + } api.addNewPanel({ panelType: controlType, initialState: controlInputTransform!( From 0c7067f0a674df1b293077f4b355a93d2f885d64 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 21 Aug 2024 09:09:31 -0600 Subject: [PATCH 2/7] revert changes to control group factory --- .../control_group/get_control_group_factory.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx b/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx index a5e246d80c3e3..ee241dcfea0fc 100644 --- a/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx +++ b/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx @@ -181,12 +181,6 @@ export const getControlGroupEmbeddableFactory = (services: { dataViewId: controlsManager.api.lastUsedDataViewId$.value, }, onSave: ({ type: controlType, state: initialState }) => { - if (initialState.width) { - width.next(initialState.width); - } - if (typeof initialState.grow === 'boolean') { - grow.next(initialState.grow); - } api.addNewPanel({ panelType: controlType, initialState: controlInputTransform!( From 7e96c24566ac0f82431c96ccdad5410679ff54ff Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 21 Aug 2024 11:16:38 -0600 Subject: [PATCH 3/7] test artifacts --- .../controls/common/control_group_settings.ts | 68 +------------------ .../controls/common/index.ts | 1 - .../dashboard/current/kibana.json | 50 ++++++++++++++ 3 files changed, 52 insertions(+), 67 deletions(-) diff --git a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts index 80a8bc8148977..0cdeb45be9aac 100644 --- a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts +++ b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts @@ -12,7 +12,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const find = getService('find'); const queryBar = getService('queryBar'); const filterBar = getService('filterBar'); const testSubjects = getService('testSubjects'); @@ -22,65 +21,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'timePicker', ]); - describe('Dashboard control group settings', () => { + describe.only('Dashboard control group settings', () => { before(async () => { - await dashboard.navigateToApp(); - await dashboard.gotoDashboardLandingPage(); - await dashboard.clickNewDashboard(); - await timePicker.setDefaultDataRange(); - await dashboard.saveDashboard('Test Control Group Settings'); - }); - - it('adjust layout of controls', async () => { - await dashboard.switchToEditMode(); - await dashboardControls.createControl({ - controlType: OPTIONS_LIST_CONTROL, - dataViewTitle: 'animals-*', - fieldName: 'sound.keyword', - }); - await dashboardControls.adjustControlsLayout('twoLine'); - const controlGroupWrapper = await testSubjects.find('controls-group-wrapper'); - expect(await controlGroupWrapper.elementHasClass('controlsWrapper--twoLine')).to.be(true); - }); - - describe('apply new default width and grow', async () => { - it('defaults to medium width and grow enabled', async () => { - await dashboardControls.openCreateControlFlyout(); - const mediumWidthButton = await testSubjects.find('control-editor-width-medium'); - expect(await mediumWidthButton.elementHasClass('euiButtonGroupButton-isSelected')).to.be( - true - ); - const growSwitch = await testSubjects.find('control-editor-grow-switch'); - expect(await growSwitch.getAttribute('aria-checked')).to.be('true'); - await testSubjects.click('control-editor-cancel'); - }); - - it('sets default to width and grow of last created control', async () => { - await dashboardControls.createControl({ - controlType: OPTIONS_LIST_CONTROL, - dataViewTitle: 'animals-*', - fieldName: 'name.keyword', - width: 'small', - grow: false, - }); - - const controlIds = await dashboardControls.getAllControlIds(); - const firstControl = await find.byXPath(`//div[@data-control-id="${controlIds[0]}"]`); - expect(await firstControl.elementHasClass('controlFrameWrapper--medium')).to.be(true); - expect(await firstControl.getAttribute('class')).not.to.contain('euiFlexItem-growZero'); - const secondControl = await find.byXPath(`//div[@data-control-id="${controlIds[1]}"]`); - expect(await secondControl.elementHasClass('controlFrameWrapper--small')).to.be(true); - expect(await secondControl.getAttribute('class')).to.contain('euiFlexItem-growZero'); - - await dashboardControls.openCreateControlFlyout(); - const smallWidthButton = await testSubjects.find('control-editor-width-small'); - expect(await smallWidthButton.elementHasClass('euiButtonGroupButton-isSelected')).to.be( - true - ); - const growSwitch = await testSubjects.find('control-editor-grow-switch'); - expect(await growSwitch.getAttribute('aria-checked')).to.be('false'); - await testSubjects.click('control-editor-cancel'); - }); + await dashboard.loadSavedDashboard('control group settings test dashboard'); }); describe('filtering settings', async () => { @@ -106,13 +49,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; before(async () => { - await dashboardControls.createControl({ - controlType: RANGE_SLIDER_CONTROL, - dataViewTitle: 'animals-*', - fieldName: 'weightLbs', - }); - await dashboard.clickQuickSave(); - firstOptionsListId = (await dashboardControls.getAllControlIds())[0]; await dashboardControls.optionsListWaitForLoading(firstOptionsListId); await dashboardControls.optionsListOpenPopover(firstOptionsListId); diff --git a/test/functional/apps/dashboard_elements/controls/common/index.ts b/test/functional/apps/dashboard_elements/controls/common/index.ts index c5fb1621e61f3..58c9a3dcb80fe 100644 --- a/test/functional/apps/dashboard_elements/controls/common/index.ts +++ b/test/functional/apps/dashboard_elements/controls/common/index.ts @@ -26,7 +26,6 @@ export default function ({ loadTestFile, getService, getPageObjects }: FtrProvid defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', }); - // enable the controls lab and navigate to the dashboard listing page to start await dashboard.navigateToApp(); await dashboard.preserveCrossAppState(); } diff --git a/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json b/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json index 500443f11900a..8889df0b5a16c 100644 --- a/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json +++ b/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json @@ -3175,3 +3175,53 @@ "coreMigrationVersion": "8.8.0", "typeMigrationVersion": "8.9.0" } + +{ + "id": "153e3302-1b37-4c45-9b11-91deec40ab47", + "type": "dashboard", + "namespaces": [ + "default" + ], + "updated_at": "2024-08-21T15:17:25.029Z", + "created_at": "2024-08-21T15:17:25.029Z", + "version": "WzI4OCwxXQ==", + "attributes": { + "version": 2, + "controlGroupInput": { + "controlStyle": "oneLine", + "chainingSystem": "HIERARCHICAL", + "showApplySelections": false, + "panelsJSON": "{\"bcb81550-0843-44ea-9020-6c1ebf3228ac\":{\"type\":\"optionsListControl\",\"order\":0,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"bcb81550-0843-44ea-9020-6c1ebf3228ac\",\"fieldName\":\"sound.keyword\",\"title\":\"sound.keyword\",\"grow\":true,\"width\":\"medium\",\"searchTechnique\":\"prefix\",\"enhancements\":{}}},\"15925456-9e12-4b08-b2e6-4ae6ac27114d\":{\"type\":\"optionsListControl\",\"order\":1,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"15925456-9e12-4b08-b2e6-4ae6ac27114d\",\"fieldName\":\"weightLbs\",\"title\":\"weightLbs\",\"grow\":true,\"width\":\"medium\",\"searchTechnique\":\"exact\",\"enhancements\":{}}}}", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}" + }, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "description": "", + "refreshInterval": { + "pause": true, + "value": 60000 + }, + "timeRestore": true, + "optionsJSON": "{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}", + "panelsJSON": "[]", + "timeFrom": "2018-01-01T00:00:00.000Z", + "title": "control group settings test dashboard", + "timeTo": "2018-04-13T00:00:00.000Z" + }, + "references": [ + { + "name": "controlGroup_bcb81550-0843-44ea-9020-6c1ebf3228ac:optionsListDataView", + "type": "index-pattern", + "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c" + }, + { + "name": "controlGroup_15925456-9e12-4b08-b2e6-4ae6ac27114d:optionsListDataView", + "type": "index-pattern", + "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c" + } + ], + "managed": false, + "coreMigrationVersion": "8.8.0", + "typeMigrationVersion": "10.2.0" +} From 1f3749b6c71f3acc659bb1d4d2d309f41b44e73e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 21 Aug 2024 11:34:58 -0600 Subject: [PATCH 4/7] stub out control group editor tests --- .../components/control_group_editor.test.tsx | 19 ++++++++ .../{ => components}/control_group_editor.tsx | 12 ++--- .../open_edit_control_group_flyout.tsx | 2 +- .../controls/common/control_group_settings.ts | 45 +++---------------- 4 files changed, 31 insertions(+), 47 deletions(-) create mode 100644 src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx rename src/plugins/controls/public/react_controls/control_group/{ => components}/control_group_editor.tsx (96%) diff --git a/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx new file mode 100644 index 0000000000000..463e380aab08f --- /dev/null +++ b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ControlGroupEditor } from './control_group_editor'; + +describe('render', () => { + test('should not display delete all controls button when there are no controls', () => { + + }); + + test('should display delete all controls button when there are controls', () => { + + }); +}); \ No newline at end of file diff --git a/src/plugins/controls/public/react_controls/control_group/control_group_editor.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx similarity index 96% rename from src/plugins/controls/public/react_controls/control_group/control_group_editor.tsx rename to src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx index 9c8ca5b52b0ae..f730cb0383f81 100644 --- a/src/plugins/controls/public/react_controls/control_group/control_group_editor.tsx +++ b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx @@ -27,11 +27,11 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing'; -import { ControlStyle, ParentIgnoreSettings } from '../..'; +import { ControlStyle, ParentIgnoreSettings } from '../../..'; -import { ControlStateManager } from '../controls/types'; -import { ControlGroupStrings } from './control_group_strings'; -import { ControlGroupApi, ControlGroupEditorState } from './types'; +import { ControlStateManager } from '../../controls/types'; +import { ControlGroupStrings } from '../control_group_strings'; +import { ControlGroupApi, ControlGroupEditorState } from '../types'; const CONTROL_LAYOUT_OPTIONS = [ { @@ -46,7 +46,7 @@ const CONTROL_LAYOUT_OPTIONS = [ }, ]; -interface EditControlGroupProps { +interface Props { onCancel: () => void; onSave: () => void; onDeleteAll: () => void; @@ -60,7 +60,7 @@ export const ControlGroupEditor = ({ onDeleteAll, stateManager, api, -}: EditControlGroupProps) => { +}: Props) => { const [ children, selectedLabelPosition, diff --git a/src/plugins/controls/public/react_controls/control_group/open_edit_control_group_flyout.tsx b/src/plugins/controls/public/react_controls/control_group/open_edit_control_group_flyout.tsx index 06ab4c063b5c0..c636d37ade6b2 100644 --- a/src/plugins/controls/public/react_controls/control_group/open_edit_control_group_flyout.tsx +++ b/src/plugins/controls/public/react_controls/control_group/open_edit_control_group_flyout.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { BehaviorSubject } from 'rxjs'; import { ControlStateManager } from '../controls/types'; -import { ControlGroupEditor } from './control_group_editor'; +import { ControlGroupEditor } from './components/control_group_editor'; import { ControlGroupApi, ControlGroupEditorState } from './types'; export const openEditControlGroupFlyout = ( diff --git a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts index 0cdeb45be9aac..a88c5ca44f95b 100644 --- a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts +++ b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { OPTIONS_LIST_CONTROL, RANGE_SLIDER_CONTROL } from '@kbn/controls-plugin/common'; +import { OPTIONS_LIST_CONTROL } from '@kbn/controls-plugin/common'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../ftr_provider_context'; @@ -24,6 +24,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe.only('Dashboard control group settings', () => { before(async () => { await dashboard.loadSavedDashboard('control group settings test dashboard'); + await dashboard.switchToEditMode(); }); describe('filtering settings', async () => { @@ -49,12 +50,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; before(async () => { - firstOptionsListId = (await dashboardControls.getAllControlIds())[0]; + const controlIds = await dashboardControls.getAllControlIds(); + firstOptionsListId = controlIds[0]; await dashboardControls.optionsListWaitForLoading(firstOptionsListId); await dashboardControls.optionsListOpenPopover(firstOptionsListId); beforeCount = await dashboardControls.optionsListPopoverGetAvailableOptionsCount(); - rangeSliderId = (await dashboardControls.getAllControlIds())[2]; + rangeSliderId = controlIds[1]; beforeRange = await getRange(); }); @@ -108,39 +110,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('flyout only show settings that are relevant', async () => { - before(async () => { - await dashboard.switchToEditMode(); - }); - - it('when no controls', async () => { - await dashboardControls.deleteAllControls(); - await dashboardControls.openControlGroupSettingsFlyout(); - await testSubjects.missingOrFail('delete-all-controls-button'); - }); - - it('when at least one control', async () => { - await dashboardControls.createControl({ - controlType: OPTIONS_LIST_CONTROL, - dataViewTitle: 'animals-*', - fieldName: 'sound.keyword', - }); - await dashboardControls.openControlGroupSettingsFlyout(); - await testSubjects.existOrFail('delete-all-controls-button'); - }); - - afterEach(async () => { - await testSubjects.click('euiFlyoutCloseButton'); - if (await testSubjects.exists('confirmModalConfirmButton')) { - await testSubjects.click('confirmModalConfirmButton'); - } - }); - - after(async () => { - await dashboardControls.deleteAllControls(); - }); - }); - describe('control group settings flyout closes', async () => { it('on save', async () => { await dashboardControls.openControlGroupSettingsFlyout(); @@ -163,10 +132,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboard.gotoDashboardLandingPage(); await testSubjects.missingOrFail('control-group-settings-flyout'); }); - - after(async () => { - await dashboard.loadSavedDashboard('Test Control Group Settings'); - }); }); }); } From ff033266f0b49be2c739d1f805f4727cdfa12896 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 21 Aug 2024 14:32:00 -0600 Subject: [PATCH 5/7] ControlGroupEditor test --- .../components/control_group_editor.test.tsx | 37 ++++++++++++++++-- .../components/control_group_editor.tsx | 8 +--- .../components/control_panel.test.tsx | 39 +++++++++++-------- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx index 463e380aab08f..99feed42d0857 100644 --- a/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx +++ b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.test.tsx @@ -6,14 +6,45 @@ * Side Public License, v 1. */ +import React from 'react'; +import { BehaviorSubject } from 'rxjs'; +import { render } from '@testing-library/react'; import { ControlGroupEditor } from './control_group_editor'; +import { ControlGroupApi, ControlStyle, ParentIgnoreSettings } from '../../..'; +import { ControlGroupChainingSystem, DEFAULT_CONTROL_STYLE } from '../../../../common'; +import { DefaultControlApi } from '../../controls/types'; describe('render', () => { - test('should not display delete all controls button when there are no controls', () => { + const children$ = new BehaviorSubject<{ [key: string]: DefaultControlApi }>({}); + const props = { + api: { + children$, + } as unknown as ControlGroupApi, + onCancel: () => {}, + onSave: () => {}, + onDeleteAll: () => {}, + stateManager: { + chainingSystem: new BehaviorSubject('HIERARCHICAL'), + labelPosition: new BehaviorSubject(DEFAULT_CONTROL_STYLE), + autoApplySelections: new BehaviorSubject(true), + ignoreParentSettings: new BehaviorSubject(undefined), + }, + }; + beforeEach(() => { + children$.next({}); }); - test('should display delete all controls button when there are controls', () => { + test('should not display delete all controls button when there are no controls', () => { + const editor = render(); + expect(editor.queryByTestId('delete-all-controls-button')).not.toBeInTheDocument(); + }); + test('should display delete all controls button when there are controls', () => { + children$.next({ + alpha: {} as unknown as DefaultControlApi, + }); + const editor = render(); + expect(editor.queryByTestId('delete-all-controls-button')).toBeInTheDocument(); }); -}); \ No newline at end of file +}); diff --git a/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx index f730cb0383f81..a65c8c1ac5bba 100644 --- a/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx +++ b/src/plugins/controls/public/react_controls/control_group/components/control_group_editor.tsx @@ -54,13 +54,7 @@ interface Props { api: ControlGroupApi; // controls must always have a parent API } -export const ControlGroupEditor = ({ - onCancel, - onSave, - onDeleteAll, - stateManager, - api, -}: Props) => { +export const ControlGroupEditor = ({ onCancel, onSave, onDeleteAll, stateManager, api }: Props) => { const [ children, selectedLabelPosition, diff --git a/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx b/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx index 73a716fbadc38..34d3f344b1a81 100644 --- a/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx +++ b/src/plugins/controls/public/react_controls/control_group/components/control_panel.test.tsx @@ -8,8 +8,7 @@ import React, { useImperativeHandle } from 'react'; import { BehaviorSubject } from 'rxjs'; -import { render, screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { render, waitFor } from '@testing-library/react'; import { ControlPanel } from './control_panel'; import { registry as presentationUtilServicesRegistry } from '@kbn/presentation-util-plugin/public/services/plugin_services.story'; import { pluginServices as presentationUtilPluginServices } from '@kbn/presentation-util-plugin/public/services'; @@ -49,20 +48,20 @@ describe('render', () => { const controlPanel = render(); await waitFor(() => { const controlFrame = controlPanel.getByTestId('control-frame'); - expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--medium') - expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--grow') + expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--medium'); + expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--grow'); }); }); test('should use small class when using small width', async () => { mockApi = { uuid: 'control1', - width: new BehaviorSubject('small') + width: new BehaviorSubject('small'), }; const controlPanel = render(); await waitFor(() => { const controlFrame = controlPanel.getByTestId('control-frame'); - expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--small') + expect(controlFrame.getAttribute('class')).toContain('controlFrameWrapper--small'); }); }); }); @@ -72,28 +71,36 @@ describe('render', () => { mockApi = { uuid: 'control1', parentApi: { - labelPosition: new BehaviorSubject('oneLine') - } + labelPosition: new BehaviorSubject('oneLine'), + }, }; const controlPanel = render(); await waitFor(() => { - const floatingActions = controlPanel.getByTestId('presentationUtil__floatingActions__control1'); - expect(floatingActions.getAttribute('class')).toContain('controlFrameFloatingActions--oneLine') + const floatingActions = controlPanel.getByTestId( + 'presentationUtil__floatingActions__control1' + ); + expect(floatingActions.getAttribute('class')).toContain( + 'controlFrameFloatingActions--oneLine' + ); }); }); - + test('should use two line layout class when using two line layout', async () => { mockApi = { uuid: 'control1', parentApi: { - labelPosition: new BehaviorSubject('twoLine') - } + labelPosition: new BehaviorSubject('twoLine'), + }, }; const controlPanel = render(); await waitFor(() => { - const floatingActions = controlPanel.getByTestId('presentationUtil__floatingActions__control1'); - expect(floatingActions.getAttribute('class')).toContain('controlFrameFloatingActions--twoLine') + const floatingActions = controlPanel.getByTestId( + 'presentationUtil__floatingActions__control1' + ); + expect(floatingActions.getAttribute('class')).toContain( + 'controlFrameFloatingActions--twoLine' + ); }); }); }); -}); \ No newline at end of file +}); From bd35621c0cc3d354bbd07e2479083394d238a456 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 21 Aug 2024 14:54:58 -0600 Subject: [PATCH 6/7] finish test clean up --- .../controls/common/control_group_settings.ts | 24 ++----------------- .../dashboard/current/kibana.json | 10 ++++---- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts index a88c5ca44f95b..41cae38917974 100644 --- a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts +++ b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts @@ -6,9 +6,7 @@ * Side Public License, v 1. */ -import { OPTIONS_LIST_CONTROL } from '@kbn/controls-plugin/common'; import expect from '@kbn/expect'; - import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { @@ -28,10 +26,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); describe('filtering settings', async () => { - let firstOptionsListId: string; + const firstOptionsListId = 'bcb81550-0843-44ea-9020-6c1ebf3228ac'; let beforeCount: number; - let rangeSliderId: string; + const rangeSliderId = '15925456-9e12-4b08-b2e6-4ae6ac27114d'; let beforeRange: number; const getRange = async () => { @@ -50,13 +48,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; before(async () => { - const controlIds = await dashboardControls.getAllControlIds(); - firstOptionsListId = controlIds[0]; await dashboardControls.optionsListWaitForLoading(firstOptionsListId); await dashboardControls.optionsListOpenPopover(firstOptionsListId); beforeCount = await dashboardControls.optionsListPopoverGetAvailableOptionsCount(); - rangeSliderId = controlIds[1]; beforeRange = await getRange(); }); @@ -111,21 +106,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); describe('control group settings flyout closes', async () => { - it('on save', async () => { - await dashboardControls.openControlGroupSettingsFlyout(); - await dashboard.saveDashboard('Test Control Group Settings', { - saveAsNew: false, - exitFromEditMode: false, - }); - await testSubjects.missingOrFail('control-group-settings-flyout'); - }); - - it('on view mode change', async () => { - await dashboardControls.openControlGroupSettingsFlyout(); - await dashboard.clickCancelOutOfEditMode(); - await testSubjects.missingOrFail('control-group-settings-flyout'); - }); - it('when navigating away from dashboard', async () => { await dashboard.switchToEditMode(); await dashboardControls.openControlGroupSettingsFlyout(); diff --git a/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json b/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json index 8889df0b5a16c..a89dcf714dfc3 100644 --- a/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json +++ b/test/functional/fixtures/kbn_archiver/dashboard/current/kibana.json @@ -3182,16 +3182,16 @@ "namespaces": [ "default" ], - "updated_at": "2024-08-21T15:17:25.029Z", - "created_at": "2024-08-21T15:17:25.029Z", - "version": "WzI4OCwxXQ==", + "updated_at": "2024-08-21T20:48:22.388Z", + "created_at": "2024-08-21T20:46:21.250Z", + "version": "WzQ4MCwxXQ==", "attributes": { "version": 2, "controlGroupInput": { "controlStyle": "oneLine", "chainingSystem": "HIERARCHICAL", "showApplySelections": false, - "panelsJSON": "{\"bcb81550-0843-44ea-9020-6c1ebf3228ac\":{\"type\":\"optionsListControl\",\"order\":0,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"bcb81550-0843-44ea-9020-6c1ebf3228ac\",\"fieldName\":\"sound.keyword\",\"title\":\"sound.keyword\",\"grow\":true,\"width\":\"medium\",\"searchTechnique\":\"prefix\",\"enhancements\":{}}},\"15925456-9e12-4b08-b2e6-4ae6ac27114d\":{\"type\":\"optionsListControl\",\"order\":1,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"15925456-9e12-4b08-b2e6-4ae6ac27114d\",\"fieldName\":\"weightLbs\",\"title\":\"weightLbs\",\"grow\":true,\"width\":\"medium\",\"searchTechnique\":\"exact\",\"enhancements\":{}}}}", + "panelsJSON": "{\"bcb81550-0843-44ea-9020-6c1ebf3228ac\":{\"type\":\"optionsListControl\",\"order\":0,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"bcb81550-0843-44ea-9020-6c1ebf3228ac\",\"fieldName\":\"sound.keyword\",\"title\":\"sound.keyword\",\"grow\":true,\"width\":\"medium\",\"searchTechnique\":\"prefix\",\"enhancements\":{}}},\"15925456-9e12-4b08-b2e6-4ae6ac27114d\":{\"type\":\"rangeSliderControl\",\"order\":1,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"fieldName\":\"weightLbs\",\"title\":\"weightLbs\",\"searchTechnique\":\"exact\",\"id\":\"15925456-9e12-4b08-b2e6-4ae6ac27114d\",\"enhancements\":{}}}}", "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}" }, "kibanaSavedObjectMeta": { @@ -3216,7 +3216,7 @@ "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c" }, { - "name": "controlGroup_15925456-9e12-4b08-b2e6-4ae6ac27114d:optionsListDataView", + "name": "controlGroup_15925456-9e12-4b08-b2e6-4ae6ac27114d:rangeSliderDataView", "type": "index-pattern", "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c" } From d7d2a2ec7ed5331cf6dc13d124eea7f51f07b159 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 21 Aug 2024 15:16:37 -0600 Subject: [PATCH 7/7] remove .only --- .../controls/common/control_group_settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts index 41cae38917974..c82c16ae240f9 100644 --- a/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts +++ b/test/functional/apps/dashboard_elements/controls/common/control_group_settings.ts @@ -19,7 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'timePicker', ]); - describe.only('Dashboard control group settings', () => { + describe('Dashboard control group settings', () => { before(async () => { await dashboard.loadSavedDashboard('control group settings test dashboard'); await dashboard.switchToEditMode();