mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
[Chore] Dashboard: Tests for dashboard's add content buttons and menu (#66233)
* add tests for empty dashboard page * add tests for AddPanelButton * export default components * test +Add menu in dashboard page * use userEvent instead of firing an event on the DOM itself * fix test to match new analytic events
This commit is contained in:
@@ -10,7 +10,7 @@ export const smokeTestScenario = {
|
|||||||
scenario: () => {
|
scenario: () => {
|
||||||
// wait for time to be set to account for any layout shift
|
// wait for time to be set to account for any layout shift
|
||||||
e2e().contains('2020-01-01 00:00:00 to 2020-01-01 06:00:00').should('be.visible');
|
e2e().contains('2020-01-01 00:00:00 to 2020-01-01 06:00:00').should('be.visible');
|
||||||
e2e.components.PageToolbar.itemButton('Add panel button').click();
|
e2e.components.PageToolbar.itemButton('Add button').click();
|
||||||
e2e.components.PageToolbar.itemButton('Add new visualization menu item').click();
|
e2e.components.PageToolbar.itemButton('Add new visualization menu item').click();
|
||||||
|
|
||||||
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ e2e.scenario({
|
|||||||
|
|
||||||
// TODO: Try and use e2e.flows.addPanel() instead of block below
|
// TODO: Try and use e2e.flows.addPanel() instead of block below
|
||||||
try {
|
try {
|
||||||
e2e.components.PageToolbar.itemButton('Add panel button').should('be.visible');
|
e2e.components.PageToolbar.itemButton('Add button').should('be.visible');
|
||||||
e2e.components.PageToolbar.itemButton('Add panel button').click();
|
e2e.components.PageToolbar.itemButton('Add button').click();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Depending on the screen size, the "Add panel" button might be hidden
|
// Depending on the screen size, the "Add panel" button might be hidden
|
||||||
e2e.components.PageToolbar.item('Show more items').click();
|
e2e.components.PageToolbar.item('Show more items').click();
|
||||||
e2e.components.PageToolbar.item('Add panel button').last().click();
|
e2e.components.PageToolbar.item('Add button').last().click();
|
||||||
}
|
}
|
||||||
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').should('be.visible');
|
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').should('be.visible');
|
||||||
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').click();
|
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').click();
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ export const addDashboard = (config?: Partial<AddDashboardConfig>) => {
|
|||||||
e2e.pages.SaveDashboardAsModal.newName().clear().type(title, { force: true });
|
e2e.pages.SaveDashboardAsModal.newName().clear().type(title, { force: true });
|
||||||
e2e.pages.SaveDashboardAsModal.save().click();
|
e2e.pages.SaveDashboardAsModal.save().click();
|
||||||
e2e.flows.assertSuccessNotification();
|
e2e.flows.assertSuccessNotification();
|
||||||
e2e.pages.AddDashboard.addNewPanel().should('be.visible');
|
e2e.pages.AddDashboard.itemButton('Create new panel button').should('be.visible');
|
||||||
|
|
||||||
e2e().logToConsole('Added dashboard with title:', title);
|
e2e().logToConsole('Added dashboard with title:', title);
|
||||||
|
|
||||||
|
|||||||
@@ -92,12 +92,12 @@ export const configurePanel = (config: PartialAddPanelConfig | PartialEditPanelC
|
|||||||
e2e.components.Panels.Panel.headerItems('Edit').click();
|
e2e.components.Panels.Panel.headerItems('Edit').click();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
e2e.components.PageToolbar.itemButton('Add panel button').should('be.visible');
|
e2e.components.PageToolbar.itemButton('Add button').should('be.visible');
|
||||||
e2e.components.PageToolbar.itemButton('Add panel button').click();
|
e2e.components.PageToolbar.itemButton('Add button').click();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Depending on the screen size, the "Add panel" button might be hidden
|
// Depending on the screen size, the "Add" button might be hidden
|
||||||
e2e.components.PageToolbar.item('Show more items').click();
|
e2e.components.PageToolbar.item('Show more items').click();
|
||||||
e2e.components.PageToolbar.item('Add panel button').last().click();
|
e2e.components.PageToolbar.item('Add button').last().click();
|
||||||
}
|
}
|
||||||
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').should('be.visible');
|
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').should('be.visible');
|
||||||
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').click();
|
e2e.pages.AddDashboard.itemButton('Add new visualization menu item').click();
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { defaultDashboard } from '@grafana/schema';
|
||||||
|
|
||||||
|
import { createDashboardModelFixture } from '../../state/__fixtures__/dashboardFixtures';
|
||||||
|
|
||||||
|
import AddPanelButton, { Props } from './AddPanelButton';
|
||||||
|
jest.mock('./AddPanelMenu', () => ({
|
||||||
|
...jest.requireActual('./AddPanelMenu'),
|
||||||
|
__esModule: true,
|
||||||
|
default: () => <div>Menu</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
function setup(options?: Partial<Props>) {
|
||||||
|
const props = {
|
||||||
|
dashboard: createDashboardModelFixture(defaultDashboard),
|
||||||
|
};
|
||||||
|
const { rerender } = render(<AddPanelButton dashboard={props.dashboard} />);
|
||||||
|
|
||||||
|
return rerender;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders button', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.getByRole('button', { name: 'Add' })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders button without menu when menu is not open', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.queryByText('Menu')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders button with menu when menu is open', async () => {
|
||||||
|
const user = userEvent.setup();
|
||||||
|
setup();
|
||||||
|
|
||||||
|
await user.click(screen.getByRole('button', { name: 'Add' }));
|
||||||
|
|
||||||
|
expect(screen.queryByText('Menu')).toBeInTheDocument();
|
||||||
|
});
|
||||||
@@ -7,13 +7,13 @@ import { Dropdown, Button, useTheme2, Icon } from '@grafana/ui';
|
|||||||
import { Trans } from 'app/core/internationalization';
|
import { Trans } from 'app/core/internationalization';
|
||||||
import { DashboardModel } from 'app/features/dashboard/state';
|
import { DashboardModel } from 'app/features/dashboard/state';
|
||||||
|
|
||||||
import { AddPanelMenu } from './AddPanelMenu';
|
import AddPanelMenu from './AddPanelMenu';
|
||||||
|
|
||||||
interface Props {
|
export interface Props {
|
||||||
dashboard: DashboardModel;
|
dashboard: DashboardModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AddPanelButton = ({ dashboard }: Props) => {
|
const AddPanelButton = ({ dashboard }: Props) => {
|
||||||
const styles = getStyles(useTheme2());
|
const styles = getStyles(useTheme2());
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ export const AddPanelButton = ({ dashboard }: Props) => {
|
|||||||
size="lg"
|
size="lg"
|
||||||
fill="text"
|
fill="text"
|
||||||
className={cx(styles.button, styles.buttonIcon, styles.buttonText)}
|
className={cx(styles.button, styles.buttonIcon, styles.buttonText)}
|
||||||
data-testid={selectors.components.PageToolbar.itemButton('Add panel button')}
|
data-testid={selectors.components.PageToolbar.itemButton('Add button')}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="dashboard.toolbar.add">Add</Trans>
|
<Trans i18nKey="dashboard.toolbar.add">Add</Trans>
|
||||||
<Icon name={isMenuOpen ? 'angle-up' : 'angle-down'} size="lg" />
|
<Icon name={isMenuOpen ? 'angle-up' : 'angle-down'} size="lg" />
|
||||||
@@ -38,6 +38,8 @@ export const AddPanelButton = ({ dashboard }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default AddPanelButton;
|
||||||
|
|
||||||
function getStyles(theme: GrafanaTheme2) {
|
function getStyles(theme: GrafanaTheme2) {
|
||||||
return {
|
return {
|
||||||
button: css({
|
button: css({
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { PluginType } from '@grafana/data';
|
||||||
|
import { locationService, reportInteraction } from '@grafana/runtime';
|
||||||
|
import { defaultDashboard } from '@grafana/schema';
|
||||||
|
import { createDashboardModelFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures';
|
||||||
|
import {
|
||||||
|
onCreateNewPanel,
|
||||||
|
onCreateNewRow,
|
||||||
|
onAddLibraryPanel,
|
||||||
|
getCopiedPanelPlugin,
|
||||||
|
} from 'app/features/dashboard/utils/dashboard';
|
||||||
|
|
||||||
|
import AddPanelMenu from './AddPanelMenu';
|
||||||
|
|
||||||
|
jest.mock('app/types', () => ({
|
||||||
|
...jest.requireActual('app/types'),
|
||||||
|
useDispatch: () => jest.fn(),
|
||||||
|
useSelector: () => jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('@grafana/runtime', () => ({
|
||||||
|
...jest.requireActual('@grafana/runtime'),
|
||||||
|
locationService: {
|
||||||
|
partial: jest.fn(),
|
||||||
|
},
|
||||||
|
reportInteraction: jest.fn(),
|
||||||
|
config: {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('app/features/dashboard/utils/dashboard', () => ({
|
||||||
|
onCreateNewPanel: jest.fn(),
|
||||||
|
onCreateNewRow: jest.fn(),
|
||||||
|
onAddLibraryPanel: jest.fn(),
|
||||||
|
getCopiedPanelPlugin: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
const props = {
|
||||||
|
dashboard: createDashboardModelFixture(defaultDashboard),
|
||||||
|
};
|
||||||
|
const { rerender } = render(<AddPanelMenu dashboard={props.dashboard} />);
|
||||||
|
|
||||||
|
return rerender;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders menu list with correct menu items', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.getByText('visualization', { exact: false })).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('row', { exact: false })).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('library', { exact: false })).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('paste panel', { exact: false })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders with all buttons enabled except paste a panel', () => {
|
||||||
|
// getCopiedPanelPluginMock().mockReset();
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.getByText('visualization', { exact: false })).not.toBeDisabled();
|
||||||
|
expect(screen.getByText('row', { exact: false })).not.toBeDisabled();
|
||||||
|
expect(screen.getByText('library', { exact: false })).not.toBeDisabled();
|
||||||
|
expect(screen.getByText('paste panel', { exact: false })).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders with all buttons enabled', () => {
|
||||||
|
(getCopiedPanelPlugin as jest.Mock).mockReturnValue({
|
||||||
|
id: 'someid',
|
||||||
|
name: 'nameofit',
|
||||||
|
type: PluginType.panel,
|
||||||
|
info: {
|
||||||
|
author: {
|
||||||
|
name: 'author name',
|
||||||
|
},
|
||||||
|
description: 'description',
|
||||||
|
links: [],
|
||||||
|
logos: {
|
||||||
|
small: 'small',
|
||||||
|
large: 'large',
|
||||||
|
},
|
||||||
|
updated: 'updated',
|
||||||
|
version: 'version',
|
||||||
|
},
|
||||||
|
module: 'module',
|
||||||
|
baseUrl: 'url',
|
||||||
|
sort: 2,
|
||||||
|
defaults: { gridPos: { w: 200, h: 100 }, title: 'some title' },
|
||||||
|
});
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.getByText('visualization', { exact: false })).not.toBeDisabled();
|
||||||
|
expect(screen.getByText('row', { exact: false })).not.toBeDisabled();
|
||||||
|
expect(screen.getByText('library', { exact: false })).not.toBeDisabled();
|
||||||
|
expect(screen.getByText('paste panel', { exact: false })).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates new visualization when clicked on menu item Visualization', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByRole('menuitem', { name: 'Visualization' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reportInteraction).toHaveBeenCalledWith('dashboards_toolbar_add_clicked', { item: 'add_visualization' });
|
||||||
|
expect(locationService.partial).toHaveBeenCalled();
|
||||||
|
expect(onCreateNewPanel).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates new row when clicked on menu item Row', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByRole('menuitem', { name: 'Row' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reportInteraction).toHaveBeenCalledWith('dashboards_toolbar_add_clicked', { item: 'add_row' });
|
||||||
|
expect(locationService.partial).not.toHaveBeenCalled();
|
||||||
|
expect(onCreateNewRow).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a library panel when clicked on menu item Import from library', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByRole('menuitem', { name: 'Import from library' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reportInteraction).toHaveBeenCalledWith('dashboards_toolbar_add_clicked', { item: 'import_from_library' });
|
||||||
|
expect(locationService.partial).not.toHaveBeenCalled();
|
||||||
|
expect(onAddLibraryPanel).toHaveBeenCalled();
|
||||||
|
});
|
||||||
@@ -16,11 +16,11 @@ import { useDispatch, useSelector } from 'app/types';
|
|||||||
|
|
||||||
import { setInitialDatasource } from '../../state/reducers';
|
import { setInitialDatasource } from '../../state/reducers';
|
||||||
|
|
||||||
interface Props {
|
export interface Props {
|
||||||
dashboard: DashboardModel;
|
dashboard: DashboardModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AddPanelMenu = ({ dashboard }: Props) => {
|
const AddPanelMenu = ({ dashboard }: Props) => {
|
||||||
const copiedPanelPlugin = useMemo(() => getCopiedPanelPlugin(), []);
|
const copiedPanelPlugin = useMemo(() => getCopiedPanelPlugin(), []);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const initialDatasource = useSelector((state) => state.dashboard.initialDatasource);
|
const initialDatasource = useSelector((state) => state.dashboard.initialDatasource);
|
||||||
@@ -29,8 +29,8 @@ export const AddPanelMenu = ({ dashboard }: Props) => {
|
|||||||
<Menu>
|
<Menu>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="add-visualisation"
|
key="add-visualisation"
|
||||||
|
testId={selectors.pages.AddDashboard.itemButton('Add new visualization menu item')}
|
||||||
label={t('dashboard.add-menu.visualization', 'Visualization')}
|
label={t('dashboard.add-menu.visualization', 'Visualization')}
|
||||||
testId={selectors.components.PageToolbar.itemButton('Add new visualization menu item')}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const id = onCreateNewPanel(dashboard, initialDatasource);
|
const id = onCreateNewPanel(dashboard, initialDatasource);
|
||||||
reportInteraction('dashboards_toolbar_add_clicked', { item: 'add_visualization' });
|
reportInteraction('dashboards_toolbar_add_clicked', { item: 'add_visualization' });
|
||||||
@@ -40,8 +40,8 @@ export const AddPanelMenu = ({ dashboard }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="add-row"
|
key="add-row"
|
||||||
|
testId={selectors.pages.AddDashboard.itemButton('Add new row menu item')}
|
||||||
label={t('dashboard.add-menu.row', 'Row')}
|
label={t('dashboard.add-menu.row', 'Row')}
|
||||||
testId={selectors.components.PageToolbar.itemButton('Add new row menu item')}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
reportInteraction('dashboards_toolbar_add_clicked', { item: 'add_row' });
|
reportInteraction('dashboards_toolbar_add_clicked', { item: 'add_row' });
|
||||||
onCreateNewRow(dashboard);
|
onCreateNewRow(dashboard);
|
||||||
@@ -49,8 +49,8 @@ export const AddPanelMenu = ({ dashboard }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="add-panel-lib"
|
key="add-panel-lib"
|
||||||
|
testId={selectors.pages.AddDashboard.itemButton('Add new panel from panel library menu item')}
|
||||||
label={t('dashboard.add-menu.import', 'Import from library')}
|
label={t('dashboard.add-menu.import', 'Import from library')}
|
||||||
testId={selectors.components.PageToolbar.itemButton('Add new panel from panel library menu item')}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
reportInteraction('dashboards_toolbar_add_clicked', { item: 'import_from_library' });
|
reportInteraction('dashboards_toolbar_add_clicked', { item: 'import_from_library' });
|
||||||
onAddLibraryPanel(dashboard);
|
onAddLibraryPanel(dashboard);
|
||||||
@@ -58,8 +58,8 @@ export const AddPanelMenu = ({ dashboard }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="add-panel-clipboard"
|
key="add-panel-clipboard"
|
||||||
|
testId={selectors.pages.AddDashboard.itemButton('Add new panel from clipboard menu item')}
|
||||||
label={t('dashboard.add-menu.paste-panel', 'Paste panel')}
|
label={t('dashboard.add-menu.paste-panel', 'Paste panel')}
|
||||||
testId={selectors.components.PageToolbar.itemButton('Add new panel from clipboard menu item')}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
reportInteraction('dashboards_toolbar_add_clicked', { item: 'paste_panel' });
|
reportInteraction('dashboards_toolbar_add_clicked', { item: 'paste_panel' });
|
||||||
onPasteCopiedPanel(dashboard, copiedPanelPlugin);
|
onPasteCopiedPanel(dashboard, copiedPanelPlugin);
|
||||||
@@ -69,3 +69,5 @@ export const AddPanelMenu = ({ dashboard }: Props) => {
|
|||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default AddPanelMenu;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { appEvents } from 'app/core/core';
|
|||||||
import { useBusEvent } from 'app/core/hooks/useBusEvent';
|
import { useBusEvent } from 'app/core/hooks/useBusEvent';
|
||||||
import { t, Trans } from 'app/core/internationalization';
|
import { t, Trans } from 'app/core/internationalization';
|
||||||
import { setStarred } from 'app/core/reducers/navBarTree';
|
import { setStarred } from 'app/core/reducers/navBarTree';
|
||||||
import { AddPanelButton } from 'app/features/dashboard/components/AddPanelButton/AddPanelButton';
|
import AddPanelButton from 'app/features/dashboard/components/AddPanelButton/AddPanelButton';
|
||||||
import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer';
|
import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer';
|
||||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
import { DashboardModel } from 'app/features/dashboard/state';
|
import { DashboardModel } from 'app/features/dashboard/state';
|
||||||
|
|||||||
103
public/app/features/dashboard/dashgrid/DashboardEmpty.test.tsx
Normal file
103
public/app/features/dashboard/dashgrid/DashboardEmpty.test.tsx
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { locationService, reportInteraction } from '@grafana/runtime';
|
||||||
|
import { defaultDashboard } from '@grafana/schema';
|
||||||
|
|
||||||
|
import { createDashboardModelFixture } from '../state/__fixtures__/dashboardFixtures';
|
||||||
|
import { onCreateNewPanel, onCreateNewRow, onAddLibraryPanel } from '../utils/dashboard';
|
||||||
|
|
||||||
|
import DashboardEmpty, { Props } from './DashboardEmpty';
|
||||||
|
|
||||||
|
jest.mock('app/types', () => ({
|
||||||
|
...jest.requireActual('app/types'),
|
||||||
|
useDispatch: () => jest.fn(),
|
||||||
|
useSelector: () => jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('@grafana/runtime', () => ({
|
||||||
|
...jest.requireActual('@grafana/runtime'),
|
||||||
|
locationService: {
|
||||||
|
partial: jest.fn(),
|
||||||
|
},
|
||||||
|
reportInteraction: jest.fn(),
|
||||||
|
config: {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('app/features/dashboard/utils/dashboard', () => ({
|
||||||
|
onCreateNewPanel: jest.fn(),
|
||||||
|
onCreateNewRow: jest.fn(),
|
||||||
|
onAddLibraryPanel: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
function setup(options?: Partial<Props>) {
|
||||||
|
const props = {
|
||||||
|
dashboard: createDashboardModelFixture(defaultDashboard),
|
||||||
|
canCreate: options?.canCreate ?? true,
|
||||||
|
};
|
||||||
|
const { rerender } = render(<DashboardEmpty dashboard={props.dashboard} canCreate={props.canCreate} />);
|
||||||
|
|
||||||
|
return rerender;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders page with correct title for an empty dashboard', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.getByText('your new dashboard', { exact: false })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders with all buttons enabled when canCreate is true', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
expect(screen.getByRole('button', { name: 'Add visualization' })).not.toBeDisabled();
|
||||||
|
expect(screen.getByRole('button', { name: 'Add row' })).not.toBeDisabled();
|
||||||
|
expect(screen.getByRole('button', { name: 'Import library panel' })).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders with all buttons disabled when canCreate is false', () => {
|
||||||
|
setup({ canCreate: false });
|
||||||
|
|
||||||
|
expect(screen.getByRole('button', { name: 'Add visualization' })).toBeDisabled();
|
||||||
|
expect(screen.getByRole('button', { name: 'Add row' })).toBeDisabled();
|
||||||
|
expect(screen.getByRole('button', { name: 'Import library panel' })).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates new visualization when clicked Add visualization', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Add visualization' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reportInteraction).toHaveBeenCalledWith('dashboards_emptydashboard_clicked', { item: 'add_visualization' });
|
||||||
|
expect(locationService.partial).toHaveBeenCalled();
|
||||||
|
expect(onCreateNewPanel).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates new row when clicked Add row', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Add row' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reportInteraction).toHaveBeenCalledWith('dashboards_emptydashboard_clicked', { item: 'add_row' });
|
||||||
|
expect(locationService.partial).not.toHaveBeenCalled();
|
||||||
|
expect(onCreateNewRow).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a library panel when clicked Import library panel', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Import library panel' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reportInteraction).toHaveBeenCalledWith('dashboards_emptydashboard_clicked', { item: 'import_from_library' });
|
||||||
|
expect(locationService.partial).not.toHaveBeenCalled();
|
||||||
|
expect(onAddLibraryPanel).toHaveBeenCalled();
|
||||||
|
});
|
||||||
@@ -2,6 +2,7 @@ import { css, cx } from '@emotion/css';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { locationService, reportInteraction } from '@grafana/runtime';
|
import { locationService, reportInteraction } from '@grafana/runtime';
|
||||||
import { Button, useStyles2 } from '@grafana/ui';
|
import { Button, useStyles2 } from '@grafana/ui';
|
||||||
import { H1, H3, P } from '@grafana/ui/src/unstable';
|
import { H1, H3, P } from '@grafana/ui/src/unstable';
|
||||||
@@ -17,7 +18,7 @@ export interface Props {
|
|||||||
canCreate: boolean;
|
canCreate: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const initialDatasource = useSelector((state) => state.dashboard.initialDatasource);
|
const initialDatasource = useSelector((state) => state.dashboard.initialDatasource);
|
||||||
@@ -44,7 +45,7 @@ export const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
size="lg"
|
size="lg"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
aria-label="Add new panel"
|
data-testid={selectors.pages.AddDashboard.itemButton('Create new panel button')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const id = onCreateNewPanel(dashboard, initialDatasource);
|
const id = onCreateNewPanel(dashboard, initialDatasource);
|
||||||
reportInteraction('dashboards_emptydashboard_clicked', { item: 'add_visualization' });
|
reportInteraction('dashboards_emptydashboard_clicked', { item: 'add_visualization' });
|
||||||
@@ -73,7 +74,7 @@ export const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
icon="plus"
|
icon="plus"
|
||||||
fill="outline"
|
fill="outline"
|
||||||
aria-label="Add new row"
|
data-testid={selectors.pages.AddDashboard.itemButton('Create new row button')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
reportInteraction('dashboards_emptydashboard_clicked', { item: 'add_row' });
|
reportInteraction('dashboards_emptydashboard_clicked', { item: 'add_row' });
|
||||||
onCreateNewRow(dashboard);
|
onCreateNewRow(dashboard);
|
||||||
@@ -99,7 +100,7 @@ export const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
icon="plus"
|
icon="plus"
|
||||||
fill="outline"
|
fill="outline"
|
||||||
aria-label="Add new panel from panel library"
|
data-testid={selectors.pages.AddDashboard.itemButton('Add a panel from the panel library button')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
reportInteraction('dashboards_emptydashboard_clicked', { item: 'import_from_library' });
|
reportInteraction('dashboards_emptydashboard_clicked', { item: 'import_from_library' });
|
||||||
onAddLibraryPanel(dashboard);
|
onAddLibraryPanel(dashboard);
|
||||||
@@ -115,6 +116,8 @@ export const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default DashboardEmpty;
|
||||||
|
|
||||||
function getStyles(theme: GrafanaTheme2) {
|
function getStyles(theme: GrafanaTheme2) {
|
||||||
return {
|
return {
|
||||||
wrapper: css({
|
wrapper: css({
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { DashboardRow } from '../components/DashboardRow';
|
|||||||
import { DashboardModel, PanelModel } from '../state';
|
import { DashboardModel, PanelModel } from '../state';
|
||||||
import { GridPos } from '../state/PanelModel';
|
import { GridPos } from '../state/PanelModel';
|
||||||
|
|
||||||
import { DashboardEmpty } from './DashboardEmpty';
|
import DashboardEmpty from './DashboardEmpty';
|
||||||
import { DashboardPanel } from './DashboardPanel';
|
import { DashboardPanel } from './DashboardPanel';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|||||||
Reference in New Issue
Block a user