Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add tests for Dashboard Header and HeaderActionsDropdown components #13973

Merged
merged 14 commits into from
Apr 14, 2021
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import fetchMock from 'fetch-mock';
import HeaderActionsDropdown from '.';

const mockedProps = {
addSuccessToast: jest.fn(),
addDangerToast: jest.fn(),
customCss: '#save-dash-split-button{margin-left: 100px;}',
dashboardId: 1,
dashboardInfo: {},
dashboardTitle: 'Title',
editMode: true,
expandedSlices: {},
filters: {},
forceRefreshAllCharts: jest.fn(),
hasUnsavedChanges: false,
isLoading: false,
layout: {},
onChange: jest.fn(),
onSave: jest.fn(),
refreshFrequency: 200,
setRefreshFrequency: jest.fn(),
shouldPersistRefreshFrequency: true,
showPropertiesModal: jest.fn(),
startPeriodicRender: jest.fn(),
updateCss: jest.fn(),
userCanEdit: true,
userCanSave: true,
lastModifiedTime: 0,
};

const editModeOffProps = {
...mockedProps,
editMode: false,
};

fetchMock.get('glob:*/csstemplateasyncmodelview/api/read', {});

async function openDropdown() {
const btn = screen.getByRole('button');
userEvent.click(btn);
expect(await screen.findByRole('menu')).toBeInTheDocument();
}

test('should render', () => {
const { container } = render(<HeaderActionsDropdown {...mockedProps} />);
expect(container).toBeInTheDocument();
});

test('should render the dropdown button', () => {
render(<HeaderActionsDropdown {...mockedProps} />);
expect(screen.getByRole('button')).toBeInTheDocument();
});

test('should render the dropdown icon', () => {
render(<HeaderActionsDropdown {...mockedProps} />);
expect(screen.getByRole('img', { name: 'more-horiz' })).toBeInTheDocument();
});

test('should open the dropdown', async () => {
render(<HeaderActionsDropdown {...mockedProps} />);
await openDropdown();
expect(await screen.findByRole('menu')).toBeInTheDocument();
});

test('should render the menu items in edit mode', async () => {
render(<HeaderActionsDropdown {...mockedProps} />);
await openDropdown();
expect(screen.getAllByRole('menuitem')).toHaveLength(8);
expect(screen.getByText('Save as')).toBeInTheDocument();
expect(screen.getByText('Copy dashboard URL')).toBeInTheDocument();
expect(screen.getByText('Share dashboard by email')).toBeInTheDocument();
expect(screen.getByText('Refresh dashboard')).toBeInTheDocument();
expect(screen.getByText('Set auto-refresh interval')).toBeInTheDocument();
expect(screen.getByText('Set filter mapping')).toBeInTheDocument();
expect(screen.getByText('Edit dashboard properties')).toBeInTheDocument();
expect(screen.getByText('Edit CSS')).toBeInTheDocument();
});

test('should render the menu items when not in edit mode', async () => {
render(<HeaderActionsDropdown {...editModeOffProps} />);
await openDropdown();
expect(screen.getAllByRole('menuitem')).toHaveLength(7);
expect(screen.getByText('Save as')).toBeInTheDocument();
expect(screen.getByText('Copy dashboard URL')).toBeInTheDocument();
expect(screen.getByText('Share dashboard by email')).toBeInTheDocument();
expect(screen.getByText('Refresh dashboard')).toBeInTheDocument();
expect(screen.getByText('Set auto-refresh interval')).toBeInTheDocument();
expect(screen.getByText('Download as image')).toBeInTheDocument();
expect(screen.getByText('Toggle fullscreen')).toBeInTheDocument();
});

test('should render the "Save Modal" when user can save', async () => {
render(<HeaderActionsDropdown {...mockedProps} />);
await openDropdown();
expect(screen.getByText('Save as')).toBeInTheDocument();
});

test('should NOT render the "Save Modal" menu item when user cannot save', async () => {
const cannotSaveProps = {
...mockedProps,
userCanSave: false,
};
render(<HeaderActionsDropdown {...cannotSaveProps} />);
await openDropdown();
expect(screen.queryByText('Save as')).not.toBeInTheDocument();
});

test('should render the "Refresh dashboard" menu item as disabled when loading', async () => {
const loadingProps = {
...mockedProps,
isLoading: true,
};
render(<HeaderActionsDropdown {...loadingProps} />);
await openDropdown();
expect(screen.getByText('Refresh dashboard')).toHaveClass(
'ant-dropdown-menu-item-disabled',
);
});

test('should render with custom css', () => {
const loadingProps = {
...mockedProps,
isLoading: true,
};
render(<HeaderActionsDropdown {...loadingProps} />);
expect(screen.getByRole('button')).toHaveStyle('margin-left: 100px');
});

test('should refresh the charts', async () => {
render(<HeaderActionsDropdown {...mockedProps} />);
await openDropdown();
userEvent.click(screen.getByText('Refresh dashboard'));
expect(mockedProps.forceRefreshAllCharts).toHaveBeenCalledTimes(1);
});

test('should show the properties modal', async () => {
render(<HeaderActionsDropdown {...mockedProps} />);
await openDropdown();
userEvent.click(screen.getByText('Edit dashboard properties'));
expect(mockedProps.showPropertiesModal).toHaveBeenCalledTimes(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import React from 'react';
import { shallow } from 'enzyme';
import { Menu, NoAnimationDropdown } from 'src/common/components';
import RefreshIntervalModal from 'src/dashboard/components/RefreshIntervalModal';
import HeaderActionsDropdown from 'src/dashboard/components/HeaderActionsDropdown';
import SaveModal from 'src/dashboard/components/SaveModal';
import CssEditor from 'src/dashboard/components/CssEditor';
import fetchMock from 'fetch-mock';
import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems';
import HeaderActionsDropdown from '.';

fetchMock.get('glob:*/csstemplateasyncmodelview/api/read', {});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ import { Menu, NoAnimationDropdown } from 'src/common/components';
import Icon from 'src/components/Icon';
import { URL_PARAMS } from 'src/constants';
import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems';
import CssEditor from './CssEditor';
import RefreshIntervalModal from './RefreshIntervalModal';
import SaveModal from './SaveModal';
import injectCustomCss from '../util/injectCustomCss';
import { SAVE_TYPE_NEWDASHBOARD } from '../util/constants';
import FilterScopeModal from './filterscope/FilterScopeModal';
import downloadAsImage from '../../utils/downloadAsImage';
import getDashboardUrl from '../util/getDashboardUrl';
import { getActiveFilters } from '../util/activeDashboardFilters';
import { getUrlParam } from '../../utils/urlUtils';
import CssEditor from 'src/dashboard/components/CssEditor';
import RefreshIntervalModal from 'src/dashboard/components/RefreshIntervalModal';
import SaveModal from 'src/dashboard/components/SaveModal';
import injectCustomCss from 'src/dashboard/util/injectCustomCss';
import { SAVE_TYPE_NEWDASHBOARD } from 'src/dashboard/util/constants';
import FilterScopeModal from 'src/dashboard/components/filterscope/FilterScopeModal';
import downloadAsImage from 'src/utils/downloadAsImage';
import getDashboardUrl from 'src/dashboard/util/getDashboardUrl';
import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters';
import { getUrlParam } from 'src/utils/urlUtils';

const propTypes = {
addSuccessToast: PropTypes.func.isRequired,
Expand Down Expand Up @@ -312,9 +312,10 @@ class HeaderActionsDropdown extends React.PureComponent {
<NoAnimationDropdown
overlay={menu}
trigger={['click']}
/* TODO
getPopupContainer={triggerNode =>
triggerNode.closest(SCREENSHOT_NODE_SELECTOR)
}
}*/
>
<DropdownButton id="save-dash-split-button" role="button">
<Icon name="more-horiz" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
*/
import React from 'react';
import { shallow } from 'enzyme';
import Header from 'src/dashboard/components/Header';
import EditableTitle from 'src/components/EditableTitle';
import FaveStar from 'src/components/FaveStar';
import PublishedStatus from 'src/dashboard/components/PublishedStatus';
import HeaderActionsDropdown from 'src/dashboard/components/HeaderActionsDropdown';
import Button from 'src/components/Button';
import UndoRedoKeylisteners from 'src/dashboard/components/UndoRedoKeylisteners';
import HeaderActionsDropdown from './HeaderActionsDropdown';
import Header from '.';

describe('Header', () => {
const props = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,19 @@ import EditableTitle from 'src/components/EditableTitle';
import FaveStar from 'src/components/FaveStar';
import { safeStringify } from 'src/utils/safeStringify';

import HeaderActionsDropdown from './HeaderActionsDropdown';
import PublishedStatus from './PublishedStatus';
import UndoRedoKeylisteners from './UndoRedoKeylisteners';
import PropertiesModal from './PropertiesModal';
import HeaderActionsDropdown from 'src/dashboard/components/Header/HeaderActionsDropdown';
import PublishedStatus from 'src/dashboard/components/PublishedStatus';
import UndoRedoKeylisteners from 'src/dashboard/components/UndoRedoKeylisteners';
import PropertiesModal from 'src/dashboard/components/PropertiesModal';

import { chartPropShape } from '../util/propShapes';
import { chartPropShape } from 'src/dashboard/util/propShapes';
import {
UNDO_LIMIT,
SAVE_TYPE_OVERWRITE,
DASHBOARD_POSITION_DATA_LIMIT,
} from '../util/constants';
import setPeriodicRunner from '../util/setPeriodicRunner';
import { options as PeriodicRefreshOptions } from './RefreshIntervalModal';
} from 'src/dashboard/util/constants';
import setPeriodicRunner from 'src/dashboard/util/setPeriodicRunner';
import { options as PeriodicRefreshOptions } from 'src/dashboard/components/RefreshIntervalModal';

const propTypes = {
addSuccessToast: PropTypes.func.isRequired,
Expand Down