diff options
Diffstat (limited to 'spec/frontend/monitoring/components/dashboard_actions_menu_spec.js')
-rw-r--r-- | spec/frontend/monitoring/components/dashboard_actions_menu_spec.js | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js new file mode 100644 index 00000000000..024b2cbd7f1 --- /dev/null +++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js @@ -0,0 +1,440 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlNewDropdownItem } from '@gitlab/ui'; +import { createStore } from '~/monitoring/stores'; +import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants'; +import { setupAllDashboards, setupStoreWithData } from '../store_utils'; +import { redirectTo } from '~/lib/utils/url_utility'; +import Tracking from '~/tracking'; +import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue'; +import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue'; +import { dashboardActionsMenuProps, dashboardGitResponse } from '../mock_data'; +import * as types from '~/monitoring/stores/mutation_types'; + +jest.mock('~/lib/utils/url_utility', () => ({ + redirectTo: jest.fn(), + queryToObject: jest.fn(), +})); + +describe('Actions menu', () => { + const ootbDashboards = [dashboardGitResponse[0], dashboardGitResponse[2]]; + const customDashboard = dashboardGitResponse[1]; + + let store; + let wrapper; + + const findAddMetricItem = () => wrapper.find('[data-testid="add-metric-item"]'); + const findAddPanelItemEnabled = () => wrapper.find('[data-testid="add-panel-item-enabled"]'); + const findAddPanelItemDisabled = () => wrapper.find('[data-testid="add-panel-item-disabled"]'); + const findAddMetricModal = () => wrapper.find('[data-testid="add-metric-modal"]'); + const findAddMetricModalSubmitButton = () => + wrapper.find('[data-testid="add-metric-modal-submit-button"]'); + const findStarDashboardItem = () => wrapper.find('[data-testid="star-dashboard-item"]'); + const findEditDashboardItemEnabled = () => + wrapper.find('[data-testid="edit-dashboard-item-enabled"]'); + const findEditDashboardItemDisabled = () => + wrapper.find('[data-testid="edit-dashboard-item-disabled"]'); + const findDuplicateDashboardItem = () => wrapper.find('[data-testid="duplicate-dashboard-item"]'); + const findDuplicateDashboardModal = () => + wrapper.find('[data-testid="duplicate-dashboard-modal"]'); + const findCreateDashboardItem = () => wrapper.find('[data-testid="create-dashboard-item"]'); + const findCreateDashboardModal = () => wrapper.find('[data-testid="create-dashboard-modal"]'); + + const createShallowWrapper = (props = {}, options = {}) => { + wrapper = shallowMount(ActionsMenu, { + propsData: { ...dashboardActionsMenuProps, ...props }, + store, + ...options, + }); + }; + + beforeEach(() => { + store = createStore(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('add metric item', () => { + it('is rendered when custom metrics are available', () => { + createShallowWrapper(); + + return wrapper.vm.$nextTick(() => { + expect(findAddMetricItem().exists()).toBe(true); + }); + }); + + it('is not rendered when custom metrics are not available', () => { + createShallowWrapper({ + addingMetricsAvailable: false, + }); + + return wrapper.vm.$nextTick(() => { + expect(findAddMetricItem().exists()).toBe(false); + }); + }); + + describe('when available', () => { + beforeEach(() => { + createShallowWrapper(); + }); + + it('modal for custom metrics form is rendered', () => { + expect(findAddMetricModal().exists()).toBe(true); + expect(findAddMetricModal().attributes().modalid).toBe('addMetric'); + }); + + it('add metric modal submit button exists', () => { + expect(findAddMetricModalSubmitButton().exists()).toBe(true); + }); + + it('renders custom metrics form fields', () => { + expect(wrapper.find(CustomMetricsFormFields).exists()).toBe(true); + }); + }); + + describe('when not available', () => { + beforeEach(() => { + createShallowWrapper({ addingMetricsAvailable: false }); + }); + + it('modal for custom metrics form is not rendered', () => { + expect(findAddMetricModal().exists()).toBe(false); + }); + }); + + describe('adding new metric from modal', () => { + let origPage; + + beforeEach(done => { + jest.spyOn(Tracking, 'event').mockReturnValue(); + createShallowWrapper(); + + setupStoreWithData(store); + + origPage = document.body.dataset.page; + document.body.dataset.page = 'projects:environments:metrics'; + + wrapper.vm.$nextTick(done); + }); + + afterEach(() => { + document.body.dataset.page = origPage; + }); + + it('is tracked', done => { + const submitButton = findAddMetricModalSubmitButton().vm; + + wrapper.vm.$nextTick(() => { + submitButton.$el.click(); + wrapper.vm.$nextTick(() => { + expect(Tracking.event).toHaveBeenCalledWith( + document.body.dataset.page, + 'click_button', + { + label: 'add_new_metric', + property: 'modal', + value: undefined, + }, + ); + done(); + }); + }); + }); + }); + }); + + describe('add panel item', () => { + const GlNewDropdownItemStub = { + extends: GlNewDropdownItem, + props: { + to: [String, Object], + }, + }; + + let $route; + + beforeEach(() => { + $route = { name: DASHBOARD_PAGE, params: { dashboard: 'my_dashboard.yml' } }; + + createShallowWrapper( + { + isOotbDashboard: false, + }, + { + mocks: { $route }, + stubs: { GlNewDropdownItem: GlNewDropdownItemStub }, + }, + ); + }); + + it('is disabled for ootb dashboards', () => { + createShallowWrapper({ + isOotbDashboard: true, + }); + + return wrapper.vm.$nextTick(() => { + expect(findAddPanelItemDisabled().exists()).toBe(true); + }); + }); + + it('is visible for custom dashboards', () => { + expect(findAddPanelItemEnabled().exists()).toBe(true); + }); + + it('renders a link to the new panel page for custom dashboards', () => { + expect(findAddPanelItemEnabled().props('to')).toEqual({ + name: PANEL_NEW_PAGE, + params: { + dashboard: 'my_dashboard.yml', + }, + }); + }); + }); + + describe('edit dashboard yml item', () => { + beforeEach(() => { + createShallowWrapper(); + }); + + describe('when current dashboard is custom', () => { + beforeEach(() => { + setupAllDashboards(store, customDashboard.path); + }); + + it('enabled item is rendered and has falsy disabled attribute', () => { + expect(findEditDashboardItemEnabled().exists()).toBe(true); + expect(findEditDashboardItemEnabled().attributes('disabled')).toBe(undefined); + }); + + it('enabled item links to their edit path', () => { + expect(findEditDashboardItemEnabled().attributes('href')).toBe( + customDashboard.project_blob_path, + ); + }); + + it('disabled item is not rendered', () => { + expect(findEditDashboardItemDisabled().exists()).toBe(false); + }); + }); + + describe.each(ootbDashboards)('when current dashboard is OOTB', dashboard => { + beforeEach(() => { + setupAllDashboards(store, dashboard.path); + }); + + it('disabled item is rendered and has disabled attribute set on it', () => { + expect(findEditDashboardItemDisabled().exists()).toBe(true); + expect(findEditDashboardItemDisabled().attributes('disabled')).toBe(''); + }); + + it('enabled item is not rendered', () => { + expect(findEditDashboardItemEnabled().exists()).toBe(false); + }); + }); + }); + + describe('duplicate dashboard item', () => { + beforeEach(() => { + createShallowWrapper(); + }); + + describe.each(ootbDashboards)('when current dashboard is OOTB', dashboard => { + beforeEach(() => { + setupAllDashboards(store, dashboard.path); + }); + + it('is rendered', () => { + expect(findDuplicateDashboardItem().exists()).toBe(true); + }); + + it('duplicate dashboard modal is rendered', () => { + expect(findDuplicateDashboardModal().exists()).toBe(true); + }); + + it('clicking on item opens up the duplicate dashboard modal', () => { + const modalId = 'duplicateDashboard'; + const modalTrigger = findDuplicateDashboardItem(); + const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); + + modalTrigger.trigger('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(rootEmit.mock.calls[0]).toContainEqual(modalId); + }); + }); + }); + + describe('when current dashboard is custom', () => { + beforeEach(() => { + setupAllDashboards(store, customDashboard.path); + }); + + it('is not rendered', () => { + expect(findDuplicateDashboardItem().exists()).toBe(false); + }); + + it('duplicate dashboard modal is not rendered', () => { + expect(findDuplicateDashboardModal().exists()).toBe(false); + }); + }); + + describe('when no dashboard is set', () => { + it('is not rendered', () => { + expect(findDuplicateDashboardItem().exists()).toBe(false); + }); + + it('duplicate dashboard modal is not rendered', () => { + expect(findDuplicateDashboardModal().exists()).toBe(false); + }); + }); + + describe('when a dashboard has been duplicated in the duplicate dashboard modal', () => { + beforeEach(() => { + store.state.monitoringDashboard.projectPath = 'root/sandbox'; + + setupAllDashboards(store, dashboardGitResponse[0].path); + }); + + it('redirects to the newly created dashboard', () => { + delete window.location; + window.location = new URL('https://localhost'); + + const newDashboard = dashboardGitResponse[1]; + + 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('star dashboard item', () => { + beforeEach(() => { + createShallowWrapper(); + setupAllDashboards(store); + + jest.spyOn(store, 'dispatch').mockResolvedValue(); + }); + + it('is shown', () => { + expect(findStarDashboardItem().exists()).toBe(true); + }); + + it('is not disabled', () => { + expect(findStarDashboardItem().attributes('disabled')).toBeFalsy(); + }); + + it('is disabled when starring is taking place', () => { + store.commit(`monitoringDashboard/${types.REQUEST_DASHBOARD_STARRING}`); + + return wrapper.vm.$nextTick(() => { + expect(findStarDashboardItem().exists()).toBe(true); + expect(findStarDashboardItem().attributes('disabled')).toBe('true'); + }); + }); + + it('on click it dispatches a toggle star action', () => { + findStarDashboardItem().vm.$emit('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/toggleStarredValue', + undefined, + ); + }); + }); + + describe('when dashboard is not starred', () => { + beforeEach(() => { + store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { + currentDashboard: dashboardGitResponse[0].path, + }); + return wrapper.vm.$nextTick(); + }); + + it('item text shows "Star dashboard"', () => { + expect(findStarDashboardItem().html()).toMatch(/Star dashboard/); + }); + }); + + describe('when dashboard is starred', () => { + beforeEach(() => { + store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { + currentDashboard: dashboardGitResponse[1].path, + }); + return wrapper.vm.$nextTick(); + }); + + it('item text shows "Unstar dashboard"', () => { + expect(findStarDashboardItem().html()).toMatch(/Unstar dashboard/); + }); + }); + }); + + describe('create dashboard item', () => { + beforeEach(() => { + createShallowWrapper(); + }); + + it('is rendered by default but it is disabled', () => { + expect(findCreateDashboardItem().attributes('disabled')).toBe('true'); + }); + + describe('when project path is set', () => { + const mockProjectPath = 'root/sandbox'; + const mockAddDashboardDocPath = '/doc/add-dashboard'; + + beforeEach(() => { + store.state.monitoringDashboard.projectPath = mockProjectPath; + store.state.monitoringDashboard.addDashboardDocumentationPath = mockAddDashboardDocPath; + }); + + it('is not disabled', () => { + expect(findCreateDashboardItem().attributes('disabled')).toBe(undefined); + }); + + it('renders a modal for creating a dashboard', () => { + expect(findCreateDashboardModal().exists()).toBe(true); + }); + + it('clicking opens up the modal', () => { + const modalId = 'createDashboard'; + const modalTrigger = findCreateDashboardItem(); + const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); + + modalTrigger.trigger('click'); + + return wrapper.vm.$nextTick().then(() => { + expect(rootEmit.mock.calls[0]).toContainEqual(modalId); + }); + }); + + it('modal gets passed correct props', () => { + expect(findCreateDashboardModal().props('projectPath')).toBe(mockProjectPath); + expect(findCreateDashboardModal().props('addDashboardDocumentationPath')).toBe( + mockAddDashboardDocPath, + ); + }); + }); + + describe('when project path is not set', () => { + beforeEach(() => { + store.state.monitoringDashboard.projectPath = null; + }); + + it('is disabled', () => { + expect(findCreateDashboardItem().attributes('disabled')).toBe('true'); + }); + + it('does not render a modal for creating a dashboard', () => { + expect(findCreateDashboardModal().exists()).toBe(false); + }); + }); + }); +}); |