diff options
Diffstat (limited to 'spec/frontend/monitoring/components/dashboard_header_spec.js')
-rw-r--r-- | spec/frontend/monitoring/components/dashboard_header_spec.js | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js new file mode 100644 index 00000000000..5a1a615c703 --- /dev/null +++ b/spec/frontend/monitoring/components/dashboard_header_spec.js @@ -0,0 +1,232 @@ +import { shallowMount } from '@vue/test-utils'; +import { createStore } from '~/monitoring/stores'; +import DashboardHeader from '~/monitoring/components/dashboard_header.vue'; +import DuplicateDashboardModal from '~/monitoring/components/duplicate_dashboard_modal.vue'; +import CreateDashboardModal from '~/monitoring/components/create_dashboard_modal.vue'; +import { setupAllDashboards } from '../store_utils'; +import { + dashboardGitResponse, + selfMonitoringDashboardGitResponse, + dashboardHeaderProps, +} from '../mock_data'; +import { redirectTo } from '~/lib/utils/url_utility'; + +jest.mock('~/lib/utils/url_utility', () => ({ + redirectTo: jest.fn(), + queryToObject: jest.fn(), + mergeUrlParams: jest.requireActual('~/lib/utils/url_utility').mergeUrlParams, +})); + +describe('Dashboard header', () => { + let store; + let wrapper; + + const findActionsMenu = () => wrapper.find('[data-testid="actions-menu"]'); + const findCreateDashboardMenuItem = () => + findActionsMenu().find('[data-testid="action-create-dashboard"]'); + const findCreateDashboardDuplicateItem = () => + findActionsMenu().find('[data-testid="action-duplicate-dashboard"]'); + const findDuplicateDashboardModal = () => wrapper.find(DuplicateDashboardModal); + const findCreateDashboardModal = () => wrapper.find('[data-testid="create-dashboard-modal"]'); + + const createShallowWrapper = (props = {}, options = {}) => { + wrapper = shallowMount(DashboardHeader, { + propsData: { ...dashboardHeaderProps, ...props }, + store, + ...options, + }); + }; + + beforeEach(() => { + store = createStore(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when a dashboard has been duplicated in the duplicate dashboard modal', () => { + beforeEach(() => { + store.state.monitoringDashboard.projectPath = 'root/sandbox'; + }); + /** + * The duplicate dashboard modal gets called both by a menu item from the + * dashboards dropdown and by an item from the actions menu. + * + * This spec is context agnostic, so it addresses all cases where the + * duplicate dashboard modal gets called. + */ + it('redirects to the newly created dashboard', () => { + delete window.location; + window.location = new URL('https://localhost'); + + const newDashboard = dashboardGitResponse[1]; + + createShallowWrapper(); + + const newDashboardUrl = 'root/sandbox/-/metrics/dashboard.yml'; + findDuplicateDashboardModal().vm.$emit('dashboardDuplicated', newDashboard); + + return wrapper.vm.$nextTick().then(() => { + expect(redirectTo).toHaveBeenCalled(); + expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl); + }); + }); + }); + + describe('actions menu', () => { + beforeEach(() => { + store.state.monitoringDashboard.projectPath = ''; + createShallowWrapper(); + }); + + it('is rendered if projectPath is set in store', () => { + store.state.monitoringDashboard.projectPath = 'https://path/to/project'; + + return wrapper.vm.$nextTick().then(() => { + expect(findActionsMenu().exists()).toBe(true); + }); + }); + + it('is not rendered if projectPath is not set in store', () => { + expect(findActionsMenu().exists()).toBe(false); + }); + + it('contains a modal', () => { + store.state.monitoringDashboard.projectPath = 'https://path/to/project'; + + return wrapper.vm.$nextTick().then(() => { + expect(findActionsMenu().contains(CreateDashboardModal)).toBe(true); + }); + }); + + const duplicableCases = [ + null, // When no path is specified, it uses the default dashboard path. + dashboardGitResponse[0].path, + dashboardGitResponse[2].path, + selfMonitoringDashboardGitResponse[0].path, + ]; + + describe.each(duplicableCases)( + 'when the selected dashboard can be duplicated', + dashboardPath => { + it('contains a "Create New" menu item and a "Duplicate Dashboard" menu item', () => { + store.state.monitoringDashboard.projectPath = 'https://path/to/project'; + setupAllDashboards(store, dashboardPath); + + return wrapper.vm.$nextTick().then(() => { + expect(findCreateDashboardMenuItem().exists()).toBe(true); + expect(findCreateDashboardDuplicateItem().exists()).toBe(true); + }); + }); + }, + ); + + const nonDuplicableCases = [ + dashboardGitResponse[1].path, + selfMonitoringDashboardGitResponse[1].path, + ]; + + describe.each(nonDuplicableCases)( + 'when the selected dashboard cannot be duplicated', + dashboardPath => { + it('contains a "Create New" menu item and no "Duplicate Dashboard" menu item', () => { + store.state.monitoringDashboard.projectPath = 'https://path/to/project'; + setupAllDashboards(store, dashboardPath); + + return wrapper.vm.$nextTick().then(() => { + expect(findCreateDashboardMenuItem().exists()).toBe(true); + expect(findCreateDashboardDuplicateItem().exists()).toBe(false); + }); + }); + }, + ); + }); + + describe('actions menu modals', () => { + const url = 'https://path/to/project'; + + beforeEach(() => { + store.state.monitoringDashboard.projectPath = url; + setupAllDashboards(store); + + createShallowWrapper(); + }); + + it('Clicking on "Create New" opens up a modal', () => { + const modalId = 'createDashboard'; + const modalTrigger = findCreateDashboardMenuItem(); + const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); + + modalTrigger.trigger('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(rootEmit.mock.calls[0]).toContainEqual(modalId); + }); + }); + + it('"Create new dashboard" modal contains correct buttons', () => { + expect(findCreateDashboardModal().props('projectPath')).toBe(url); + }); + + it('"Duplicate Dashboard" opens up a modal', () => { + const modalId = 'duplicateDashboard'; + const modalTrigger = findCreateDashboardDuplicateItem(); + const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); + + modalTrigger.trigger('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(rootEmit.mock.calls[0]).toContainEqual(modalId); + }); + }); + }); + + describe('metrics settings button', () => { + const findSettingsButton = () => wrapper.find('[data-testid="metrics-settings-button"]'); + const url = 'https://path/to/project/settings'; + + beforeEach(() => { + createShallowWrapper(); + + store.state.monitoringDashboard.canAccessOperationsSettings = false; + store.state.monitoringDashboard.operationsSettingsPath = ''; + }); + + it('is rendered when the user can access the project settings and path to settings is available', () => { + store.state.monitoringDashboard.canAccessOperationsSettings = true; + store.state.monitoringDashboard.operationsSettingsPath = url; + + return wrapper.vm.$nextTick(() => { + expect(findSettingsButton().exists()).toBe(true); + }); + }); + + it('is not rendered when the user can not access the project settings', () => { + store.state.monitoringDashboard.canAccessOperationsSettings = false; + store.state.monitoringDashboard.operationsSettingsPath = url; + + return wrapper.vm.$nextTick(() => { + expect(findSettingsButton().exists()).toBe(false); + }); + }); + + it('is not rendered when the path to settings is unavailable', () => { + store.state.monitoringDashboard.canAccessOperationsSettings = false; + store.state.monitoringDashboard.operationsSettingsPath = ''; + + return wrapper.vm.$nextTick(() => { + expect(findSettingsButton().exists()).toBe(false); + }); + }); + + it('leads to the project settings page', () => { + store.state.monitoringDashboard.canAccessOperationsSettings = true; + store.state.monitoringDashboard.operationsSettingsPath = url; + + return wrapper.vm.$nextTick(() => { + expect(findSettingsButton().attributes('href')).toBe(url); + }); + }); + }); +}); |