diff options
Diffstat (limited to 'spec/frontend/monitoring/components/dashboard_panel_builder_spec.js')
-rw-r--r-- | spec/frontend/monitoring/components/dashboard_panel_builder_spec.js | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js new file mode 100644 index 00000000000..587ddd23d3f --- /dev/null +++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js @@ -0,0 +1,234 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlCard, GlForm, GlFormTextarea, GlAlert } from '@gitlab/ui'; +import { createStore } from '~/monitoring/stores'; +import DashboardPanel from '~/monitoring/components/dashboard_panel.vue'; +import * as types from '~/monitoring/stores/mutation_types'; +import { metricsDashboardResponse } from '../fixture_data'; +import { mockTimeRange } from '../mock_data'; + +import DashboardPanelBuilder from '~/monitoring/components/dashboard_panel_builder.vue'; +import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; + +const mockPanel = metricsDashboardResponse.dashboard.panel_groups[0].panels[0]; + +describe('dashboard invalid url parameters', () => { + let store; + let wrapper; + let mockShowToast; + + const createComponent = (props = {}, options = {}) => { + wrapper = shallowMount(DashboardPanelBuilder, { + propsData: { ...props }, + store, + stubs: { + GlCard, + }, + mocks: { + $toast: { + show: mockShowToast, + }, + }, + options, + }); + }; + + const findForm = () => wrapper.find(GlForm); + const findTxtArea = () => findForm().find(GlFormTextarea); + const findSubmitBtn = () => findForm().find('[type="submit"]'); + const findClipboardCopyBtn = () => wrapper.find({ ref: 'clipboardCopyBtn' }); + const findViewDocumentationBtn = () => wrapper.find({ ref: 'viewDocumentationBtn' }); + const findOpenRepositoryBtn = () => wrapper.find({ ref: 'openRepositoryBtn' }); + const findPanel = () => wrapper.find(DashboardPanel); + const findTimeRangePicker = () => wrapper.find(DateTimePicker); + const findRefreshButton = () => wrapper.find('[data-testid="previewRefreshButton"]'); + + beforeEach(() => { + mockShowToast = jest.fn(); + store = createStore(); + createComponent(); + jest.spyOn(store, 'dispatch').mockResolvedValue(); + }); + + afterEach(() => {}); + + it('is mounted', () => { + expect(wrapper.exists()).toBe(true); + }); + + it('displays an empty dashboard panel', () => { + expect(findPanel().exists()).toBe(true); + expect(findPanel().props('graphData')).toBe(null); + }); + + it('does not fetch initial data by default', () => { + expect(store.dispatch).not.toHaveBeenCalled(); + }); + + describe('yml form', () => { + it('form exists and can be submitted', () => { + expect(findForm().exists()).toBe(true); + expect(findSubmitBtn().exists()).toBe(true); + expect(findSubmitBtn().is('[disabled]')).toBe(false); + }); + + it('form has a text area with a default value', () => { + expect(findTxtArea().exists()).toBe(true); + + const value = findTxtArea().attributes('value'); + + // Panel definition should contain a title and a type + expect(value).toContain('title:'); + expect(value).toContain('type:'); + }); + + it('"copy to clipboard" button works', () => { + findClipboardCopyBtn().vm.$emit('click'); + const clipboardText = findClipboardCopyBtn().attributes('data-clipboard-text'); + + expect(clipboardText).toContain('title:'); + expect(clipboardText).toContain('type:'); + + expect(mockShowToast).toHaveBeenCalledTimes(1); + }); + + it('on submit fetches a panel preview', () => { + findForm().vm.$emit('submit', new Event('submit')); + + return wrapper.vm.$nextTick().then(() => { + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/fetchPanelPreview', + expect.stringContaining('title:'), + ); + }); + }); + + describe('when form is submitted', () => { + beforeEach(() => { + store.commit(`monitoringDashboard/${types.REQUEST_PANEL_PREVIEW}`, 'mock yml content'); + return wrapper.vm.$nextTick(); + }); + + it('submit button is disabled', () => { + expect(findSubmitBtn().is('[disabled]')).toBe(true); + }); + }); + }); + + describe('time range picker', () => { + it('is visible by default', () => { + expect(findTimeRangePicker().exists()).toBe(true); + }); + + it('when changed does not trigger data fetch unless preview panel button is clicked', () => { + // mimic initial state where SET_PANEL_PREVIEW_IS_SHOWN is set to false + store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, false); + + return wrapper.vm.$nextTick(() => { + expect(store.dispatch).not.toHaveBeenCalled(); + }); + }); + + it('when changed triggers data fetch if preview panel button is clicked', () => { + findForm().vm.$emit('submit', new Event('submit')); + + store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_TIME_RANGE}`, mockTimeRange); + + return wrapper.vm.$nextTick(() => { + expect(store.dispatch).toHaveBeenCalled(); + }); + }); + }); + + describe('refresh', () => { + it('is visible by default', () => { + expect(findRefreshButton().exists()).toBe(true); + }); + + it('when clicked does not trigger data fetch unless preview panel button is clicked', () => { + // mimic initial state where SET_PANEL_PREVIEW_IS_SHOWN is set to false + store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, false); + + return wrapper.vm.$nextTick(() => { + expect(store.dispatch).not.toHaveBeenCalled(); + }); + }); + + it('when clicked triggers data fetch if preview panel button is clicked', () => { + // mimic state where preview is visible. SET_PANEL_PREVIEW_IS_SHOWN is set to true + store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, true); + + findRefreshButton().vm.$emit('click'); + + return wrapper.vm.$nextTick(() => { + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/fetchPanelPreviewMetrics', + undefined, + ); + }); + }); + }); + + describe('instructions card', () => { + const mockDocsPath = '/docs-path'; + const mockProjectPath = '/project-path'; + + beforeEach(() => { + store.state.monitoringDashboard.addDashboardDocumentationPath = mockDocsPath; + store.state.monitoringDashboard.projectPath = mockProjectPath; + + createComponent(); + }); + + it('displays next actions for the user', () => { + expect(findViewDocumentationBtn().exists()).toBe(true); + expect(findViewDocumentationBtn().attributes('href')).toBe(mockDocsPath); + + expect(findOpenRepositoryBtn().exists()).toBe(true); + expect(findOpenRepositoryBtn().attributes('href')).toBe(mockProjectPath); + }); + }); + + describe('when there is an error', () => { + const mockError = 'an error ocurred!'; + + beforeEach(() => { + store.commit(`monitoringDashboard/${types.RECEIVE_PANEL_PREVIEW_FAILURE}`, mockError); + return wrapper.vm.$nextTick(); + }); + + it('displays an alert', () => { + expect(wrapper.find(GlAlert).exists()).toBe(true); + expect(wrapper.find(GlAlert).text()).toBe(mockError); + }); + + it('displays an empty dashboard panel', () => { + expect(findPanel().props('graphData')).toBe(null); + }); + + it('changing time range should not refetch data', () => { + store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_TIME_RANGE}`, mockTimeRange); + + return wrapper.vm.$nextTick(() => { + expect(store.dispatch).not.toHaveBeenCalled(); + }); + }); + }); + + describe('when panel data is available', () => { + beforeEach(() => { + store.commit(`monitoringDashboard/${types.RECEIVE_PANEL_PREVIEW_SUCCESS}`, mockPanel); + return wrapper.vm.$nextTick(); + }); + + it('displays no alert', () => { + expect(wrapper.find(GlAlert).exists()).toBe(false); + }); + + it('displays panel with data', () => { + const { title, type } = wrapper.find(DashboardPanel).props('graphData'); + + expect(title).toBe(mockPanel.title); + expect(type).toBe(mockPanel.type); + }); + }); +}); |