diff options
Diffstat (limited to 'spec/javascripts/monitoring/dashboard_spec.js')
-rw-r--r-- | spec/javascripts/monitoring/dashboard_spec.js | 316 |
1 files changed, 282 insertions, 34 deletions
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js index b1778029a77..1a371c3adaf 100644 --- a/spec/javascripts/monitoring/dashboard_spec.js +++ b/spec/javascripts/monitoring/dashboard_spec.js @@ -1,8 +1,16 @@ import Vue from 'vue'; import MockAdapter from 'axios-mock-adapter'; import Dashboard from '~/monitoring/components/dashboard.vue'; +import { timeWindows, timeWindowsKeyNames } from '~/monitoring/constants'; +import * as types from '~/monitoring/stores/mutation_types'; +import { createStore } from '~/monitoring/stores'; import axios from '~/lib/utils/axios_utils'; -import { metricsGroupsAPIResponse, mockApiEndpoint, environmentData } from './mock_data'; +import { + metricsGroupsAPIResponse, + mockApiEndpoint, + environmentData, + singleGroupResponse, +} from './mock_data'; const propsData = { hasMetrics: false, @@ -19,6 +27,9 @@ const propsData = { emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg', environmentsEndpoint: '/root/hello-prometheus/environments/35', currentEnvironmentName: 'production', + customMetricsAvailable: false, + customMetricsPath: '', + validateQueryPath: '', }; export default propsData; @@ -26,6 +37,8 @@ export default propsData; describe('Dashboard', () => { let DashboardComponent; let mock; + let store; + let component; beforeEach(() => { setFixtures(` @@ -33,23 +46,34 @@ describe('Dashboard', () => { <div class="layout-page"></div> `); + window.gon = { + ...window.gon, + ee: false, + features: { + grafanaDashboardLink: true, + }, + }; + + store = createStore(); mock = new MockAdapter(axios); DashboardComponent = Vue.extend(Dashboard); }); afterEach(() => { + component.$destroy(); mock.restore(); }); describe('no metrics are available yet', () => { it('shows a getting started empty state when no metrics are present', () => { - const component = new DashboardComponent({ + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData, + propsData: { ...propsData }, + store, }); expect(component.$el.querySelector('.prometheus-graphs')).toBe(null); - expect(component.state).toEqual('gettingStarted'); + expect(component.emptyState).toEqual('gettingStarted'); }); }); @@ -59,21 +83,27 @@ describe('Dashboard', () => { }); it('shows up a loading state', done => { - const component = new DashboardComponent({ + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), propsData: { ...propsData, hasMetrics: true }, + store, }); Vue.nextTick(() => { - expect(component.state).toEqual('loading'); + expect(component.emptyState).toEqual('loading'); done(); }); }); it('hides the legend when showLegend is false', done => { - const component = new DashboardComponent({ + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData: { ...propsData, hasMetrics: true, showLegend: false }, + propsData: { + ...propsData, + hasMetrics: true, + showLegend: false, + }, + store, }); setTimeout(() => { @@ -85,9 +115,14 @@ describe('Dashboard', () => { }); it('hides the group panels when showPanels is false', done => { - const component = new DashboardComponent({ + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData: { ...propsData, hasMetrics: true, showPanels: false }, + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, }); setTimeout(() => { @@ -98,55 +133,210 @@ describe('Dashboard', () => { }); }); - it('renders the dropdown with a number of environments', done => { - const component = new DashboardComponent({ + it('renders the environments dropdown with a number of environments', done => { + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData: { ...propsData, hasMetrics: true, showPanels: false }, + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, }); - component.store.storeEnvironmentsData(environmentData); + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, + environmentData, + ); + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + singleGroupResponse, + ); setTimeout(() => { - const dropdownMenuEnvironments = component.$el.querySelectorAll('.dropdown-menu ul li a'); + const dropdownMenuEnvironments = component.$el.querySelectorAll( + '.js-environments-dropdown .dropdown-item', + ); - expect(dropdownMenuEnvironments.length).toEqual(component.store.environmentsData.length); + expect(dropdownMenuEnvironments.length).toEqual(component.environments.length); done(); }); }); - it('hides the dropdown list when there is no environments', done => { - const component = new DashboardComponent({ + it('hides the environments dropdown list when there is no environments', done => { + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, + }); + + component.$store.commit(`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, []); + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + singleGroupResponse, + ); + + Vue.nextTick() + .then(() => { + const dropdownMenuEnvironments = component.$el.querySelectorAll( + '.js-environments-dropdown .dropdown-item', + ); + + expect(dropdownMenuEnvironments.length).toEqual(0); + done(); + }) + .catch(done.fail); + }); + + it('renders the environments dropdown with a single active element', done => { + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, + }); + + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, + environmentData, + ); + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + singleGroupResponse, + ); + + Vue.nextTick() + .then(() => { + const dropdownItems = component.$el.querySelectorAll( + '.js-environments-dropdown .dropdown-item[active="true"]', + ); + + expect(dropdownItems.length).toEqual(1); + done(); + }) + .catch(done.fail); + }); + + it('hides the dropdown', done => { + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData: { ...propsData, hasMetrics: true, showPanels: false }, + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + environmentsEndpoint: '', + }, + store, + }); + + Vue.nextTick(() => { + const dropdownIsActiveElement = component.$el.querySelectorAll('.environments'); + + expect(dropdownIsActiveElement.length).toEqual(0); + done(); }); + }); - component.store.storeEnvironmentsData([]); + it('renders the time window dropdown with a set of options', done => { + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, + }); + const numberOfTimeWindows = Object.keys(timeWindows).length; setTimeout(() => { - const dropdownMenuEnvironments = component.$el.querySelectorAll('.dropdown-menu ul'); + const timeWindowDropdown = component.$el.querySelector('.js-time-window-dropdown'); + const timeWindowDropdownEls = component.$el.querySelectorAll( + '.js-time-window-dropdown .dropdown-item', + ); + + expect(timeWindowDropdown).not.toBeNull(); + expect(timeWindowDropdownEls.length).toEqual(numberOfTimeWindows); - expect(dropdownMenuEnvironments.length).toEqual(0); done(); }); }); - it('renders the dropdown with a single is-active element', done => { - const component = new DashboardComponent({ + it('fetches the metrics data with proper time window', done => { + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData: { ...propsData, hasMetrics: true, showPanels: false }, + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, }); - component.store.storeEnvironmentsData(environmentData); + spyOn(component.$store, 'dispatch').and.stub(); + const getTimeDiffSpy = spyOnDependency(Dashboard, 'getTimeDiff'); + + component.$store.commit( + `monitoringDashboard/${types.SET_ENVIRONMENTS_ENDPOINT}`, + '/environments', + ); + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, + environmentData, + ); + + component.$mount(); + + Vue.nextTick() + .then(() => { + expect(component.$store.dispatch).toHaveBeenCalled(); + expect(getTimeDiffSpy).toHaveBeenCalledWith(component.selectedTimeWindow); + + done(); + }) + .catch(done.fail); + }); + + it('shows a specific time window selected from the url params', done => { + spyOnDependency(Dashboard, 'getParameterValues').and.returnValue(['thirtyMinutes']); + + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { ...propsData, hasMetrics: true }, + store, + }); setTimeout(() => { - const dropdownIsActiveElement = component.$el.querySelectorAll( - '.dropdown-menu ul li a.is-active', + const selectedTimeWindow = component.$el.querySelector( + '.js-time-window-dropdown [active="true"]', ); - expect(dropdownIsActiveElement.length).toEqual(1); - expect(dropdownIsActiveElement[0].textContent.trim()).toEqual( - component.currentEnvironmentName, - ); + expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes'); + done(); + }); + }); + + it('defaults to the eight hours time window for non valid url parameters', done => { + spyOnDependency(Dashboard, 'getParameterValues').and.returnValue([ + '<script>alert("XSS")</script>', + ]); + + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { ...propsData, hasMetrics: true }, + store, + }); + + Vue.nextTick(() => { + expect(component.selectedTimeWindowKey).toEqual(timeWindowsKeyNames.eightHours); + done(); }); }); @@ -163,9 +353,14 @@ describe('Dashboard', () => { }); it('sets elWidth to page width when the sidebar is resized', done => { - const component = new DashboardComponent({ + component = new DashboardComponent({ el: document.querySelector('.prometheus-graphs'), - propsData: { ...propsData, hasMetrics: true, showPanels: false }, + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, }); expect(component.elWidth).toEqual(0); @@ -185,4 +380,57 @@ describe('Dashboard', () => { .catch(done.fail); }); }); + + describe('external dashboard link', () => { + beforeEach(() => { + mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse); + }); + + describe('with feature flag enabled', () => { + beforeEach(() => { + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + externalDashboardUrl: '/mockUrl', + }, + store, + }); + }); + + it('shows the link', done => { + setTimeout(() => { + expect(component.$el.querySelector('.js-external-dashboard-link').innerText).toContain( + 'View full dashboard', + ); + done(); + }); + }); + }); + + describe('without feature flage enabled', () => { + beforeEach(() => { + window.gon.features.grafanaDashboardLink = false; + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + externalDashboardUrl: '', + }, + store, + }); + }); + + it('does not show the link', done => { + setTimeout(() => { + expect(component.$el.querySelector('.js-external-dashboard-link')).toBe(null); + done(); + }); + }); + }); + }); }); |