grafana/public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.test.tsx
Torkel Ödegaard 9d6c8f8512
PanelEdit: v8 Panel Edit UX (#32124)
* Initial commit

* Progress

* Update

* Progress

* updates

* Minor fix

* fixed ts issue

* fixed e2e tests

* More explorations

* Making progress

* Panel options and field options unified

* With nested categories

* Starting to find something

* fix paddings

* Progress

* Breakthrough ux layout

* Progress

* Updates

* New way of composing options with search

* added regex search

* Refactoring to react note tree

* Show overrides

* Adding overrides radio button support

* Added popular view

* Separate stat/gauge/bargauge options into value options and display options

* Initial work on getting library panels into viz picker flow

* Fixed issues switching to panel library panel

* Move search input put of LibraryPanelsView

* Changing design again to have content inside boxes

* Style updates

* Refactoring to fix scroll issue

* Option category naming

* Fixed FilterInput issue

* Updated snapshots

* Fix padding

* Updated viz picker design

* Unify library panel an viz picker card

* Updated card with delete action

* Major refactoring back to an object model instead of searching and filtering react node tree

* More refactoring

* Show option category in label when searching

* Nice logic for categories rendering when searching or when only child

* Make getSuggestions more lazy for DataLinksEditor

* Add missing repeat options and handle conditional options

* Prepping options category to be more flexibly and control state from outside

* Added option count to search result

* Minor style tweak

* Added button to close viz picker

* Rewrote overrides to enable searching overrides

* New search engine and tests

* Searching overrides works

* Hide radio buttons while searching

* Added angular options back

* Added memoize for all options so they are not rebuilt for every search key stroke

* Added back support for category counters

* Started unit test work

* Refactoring and base popular options list

* Initial update to e2e test, more coming to add e2e test for search features

* Minor fix

* Review updates

* Fixing category open states

* Unit test progress

* Do not show visualization list mode radio button if library panels is not enabled

* Use boolean

* More unit tests

* Increase library panels per page count and give search focus when switching list mode

* field config change test and search test

* Feedback updates

* Minor tweaks

* Minor refactorings

* More minimal override collapse state
2021-03-25 08:33:13 +01:00

200 lines
6.2 KiB
TypeScript

import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import {
FieldConfigSource,
LoadingState,
PanelData,
standardEditorsRegistry,
standardFieldConfigEditorRegistry,
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { OptionsPaneOptions } from './OptionsPaneOptions';
import { DashboardModel, PanelModel } from '../../state';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getStandardFieldConfigs, getStandardOptionEditors } from '@grafana/ui';
standardEditorsRegistry.setInit(getStandardOptionEditors);
standardFieldConfigEditorRegistry.setInit(getStandardFieldConfigs);
const mockStore = configureMockStore<any, any>();
const OptionsPaneSelector = selectors.components.PanelEditor.OptionsPane;
class OptionsPaneOptionsTestScenario {
onFieldConfigsChange = jest.fn();
onPanelOptionsChanged = jest.fn();
onPanelConfigChange = jest.fn();
panelData: PanelData = {
series: [],
state: LoadingState.Done,
timeRange: {} as any,
};
plugin = getPanelPlugin({
id: 'TestPanel',
}).useFieldConfig({
standardOptions: {},
useCustomConfig: (b) => {
b.addBooleanSwitch({
name: 'CustomBool',
path: 'CustomBool',
})
.addBooleanSwitch({
name: 'HiddenFromDef',
path: 'HiddenFromDef',
hideFromDefaults: true,
})
.addTextInput({
name: 'TextPropWithCategory',
path: 'TextPropWithCategory',
settings: {
placeholder: 'CustomTextPropPlaceholder',
},
category: ['Axis'],
});
},
});
panel = new PanelModel({
title: 'Test title',
type: this.plugin.meta.id,
fieldConfig: {
defaults: {
max: 100,
thresholds: {
mode: 'absolute',
steps: [
{ value: -Infinity, color: 'green' },
{ value: 100, color: 'green' },
],
},
},
overrides: [],
},
options: {},
});
dashboard = new DashboardModel({});
store = mockStore({
dashboard: { panels: [] },
templating: {
variables: {},
},
});
render() {
render(
<Provider store={this.store}>
<OptionsPaneOptions
data={this.panelData}
plugin={this.plugin}
panel={this.panel}
dashboard={this.dashboard}
onFieldConfigsChange={this.onFieldConfigsChange}
onPanelConfigChange={this.onPanelConfigChange}
onPanelOptionsChanged={this.onPanelOptionsChanged}
/>
</Provider>
);
}
}
describe('OptionsPaneOptions', () => {
it('should render panel frame options', async () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
expect(screen.getByLabelText(OptionsPaneSelector.fieldLabel('Panel options Title'))).toBeInTheDocument();
});
it('should render all categories', async () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
expect(screen.getByRole('heading', { name: /Panel options/ })).toBeInTheDocument();
expect(screen.getByRole('heading', { name: /Standard options/ })).toBeInTheDocument();
expect(screen.getByRole('heading', { name: /Thresholds/ })).toBeInTheDocument();
expect(screen.getByRole('heading', { name: /TestPanel/ })).toBeInTheDocument();
});
it('should render custom options', () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
expect(screen.getByLabelText(OptionsPaneSelector.fieldLabel('TestPanel CustomBool'))).toBeInTheDocument();
});
it('should not render options that are marked as hidden from defaults', () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
expect(screen.queryByLabelText(OptionsPaneSelector.fieldLabel('TestPanel HiddenFromDef'))).not.toBeInTheDocument();
});
it('should create categories for field options with category', () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
expect(screen.getByRole('heading', { name: /Axis/ })).toBeInTheDocument();
});
it('should not render categories with hidden fields only', () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.plugin = getPanelPlugin({
id: 'TestPanel',
}).useFieldConfig({
standardOptions: {},
useCustomConfig: (b) => {
b.addBooleanSwitch({
name: 'CustomBool',
path: 'CustomBool',
hideFromDefaults: true,
category: ['Axis'],
});
},
});
scenario.render();
expect(screen.queryByRole('heading', { name: /Axis/ })).not.toBeInTheDocument();
});
it('should call onPanelConfigChange when updating title', () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
const input = screen.getByDisplayValue(scenario.panel.title);
fireEvent.change(input, { target: { value: 'New' } });
fireEvent.blur(input);
expect(scenario.onPanelConfigChange).toHaveBeenCalledWith('title', 'New');
});
it('should call onFieldConfigsChange when updating field config', () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
const input = screen.getByPlaceholderText('CustomTextPropPlaceholder');
fireEvent.change(input, { target: { value: 'New' } });
fireEvent.blur(input);
const newFieldConfig: FieldConfigSource = scenario.panel.fieldConfig;
newFieldConfig.defaults.custom = { TextPropWithCategory: 'New' };
expect(scenario.onFieldConfigsChange).toHaveBeenCalledWith(newFieldConfig);
});
it('should only render hits when search query specified', async () => {
const scenario = new OptionsPaneOptionsTestScenario();
scenario.render();
const input = screen.getByPlaceholderText('Search options');
fireEvent.change(input, { target: { value: 'TextPropWithCategory' } });
fireEvent.blur(input);
expect(screen.queryByLabelText(OptionsPaneSelector.fieldLabel('Panel options Title'))).not.toBeInTheDocument();
expect(screen.getByLabelText(OptionsPaneSelector.fieldLabel('Axis TextPropWithCategory'))).toBeInTheDocument();
});
});