summaryrefslogtreecommitdiff
path: root/spec/frontend/monitoring
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-31 09:08:16 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-31 09:08:16 +0000
commit6044caed20964a70c1ac6c5a3365d567ed96dfde (patch)
tree3fe8f14b4acbd542265544843efeb6f59b5d3efe /spec/frontend/monitoring
parent92077e0f8d70c70a908395808b16f98ecd3a5fcd (diff)
downloadgitlab-ce-6044caed20964a70c1ac6c5a3365d567ed96dfde.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/monitoring')
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js163
-rw-r--r--spec/frontend/monitoring/components/embeds/metric_embed_spec.js (renamed from spec/frontend/monitoring/embed/embed_spec.js)6
-rw-r--r--spec/frontend/monitoring/components/embeds/mock_data.js (renamed from spec/frontend/monitoring/embed/mock_data.js)33
-rw-r--r--spec/frontend/monitoring/components/panel_type_spec.js72
-rw-r--r--spec/frontend/monitoring/mock_data.js17
-rw-r--r--spec/frontend/monitoring/store/embed_group/actions_spec.js16
-rw-r--r--spec/frontend/monitoring/store/embed_group/getters_spec.js19
-rw-r--r--spec/frontend/monitoring/store/embed_group/mutations_spec.js16
8 files changed, 329 insertions, 13 deletions
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
new file mode 100644
index 00000000000..54d21def603
--- /dev/null
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -0,0 +1,163 @@
+import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { GlButton, GlCard } from '@gitlab/ui';
+import { TEST_HOST } from 'helpers/test_constants';
+import EmbedGroup from '~/monitoring/components/embeds/embed_group.vue';
+import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
+import {
+ addModuleAction,
+ initialEmbedGroupState,
+ singleEmbedProps,
+ dashboardEmbedProps,
+ multipleEmbedProps,
+} from './mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Embed Group', () => {
+ let wrapper;
+ let store;
+ const metricsWithDataGetter = jest.fn();
+
+ function mountComponent({ urls = [TEST_HOST], shallow = true, stubs } = {}) {
+ const mountMethod = shallow ? shallowMount : mount;
+ wrapper = mountMethod(EmbedGroup, {
+ localVue,
+ store,
+ propsData: {
+ urls,
+ },
+ stubs,
+ });
+ }
+
+ beforeEach(() => {
+ store = new Vuex.Store({
+ modules: {
+ embedGroup: {
+ namespaced: true,
+ actions: { addModule: jest.fn() },
+ getters: { metricsWithData: metricsWithDataGetter },
+ state: initialEmbedGroupState,
+ },
+ },
+ });
+ store.registerModule = jest.fn();
+ jest.spyOn(store, 'dispatch');
+ });
+
+ afterEach(() => {
+ metricsWithDataGetter.mockReset();
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('interactivity', () => {
+ it('hides the component when no chart data is loaded', () => {
+ metricsWithDataGetter.mockReturnValue([]);
+ mountComponent();
+
+ expect(wrapper.find(GlCard).isVisible()).toBe(false);
+ });
+
+ it('shows the component when chart data is loaded', () => {
+ metricsWithDataGetter.mockReturnValue([1]);
+ mountComponent();
+
+ expect(wrapper.find(GlCard).isVisible()).toBe(true);
+ });
+
+ it('is expanded by default', () => {
+ metricsWithDataGetter.mockReturnValue([1]);
+ mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+
+ expect(wrapper.find('.card-body').classes()).not.toContain('d-none');
+ });
+
+ it('collapses when clicked', done => {
+ metricsWithDataGetter.mockReturnValue([1]);
+ mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+
+ wrapper.find(GlButton).trigger('click');
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.find('.card-body').classes()).toContain('d-none');
+ done();
+ });
+ });
+ });
+
+ describe('single metrics', () => {
+ beforeEach(() => {
+ metricsWithDataGetter.mockReturnValue([1]);
+ mountComponent();
+ });
+
+ it('renders an Embed component', () => {
+ expect(wrapper.find(MetricEmbed).exists()).toBe(true);
+ });
+
+ it('passes the correct props to the Embed component', () => {
+ expect(wrapper.find(MetricEmbed).props()).toEqual(singleEmbedProps());
+ });
+
+ it('adds the monitoring dashboard module', () => {
+ expect(store.dispatch).toHaveBeenCalledWith(addModuleAction, 'monitoringDashboard/0');
+ });
+ });
+
+ describe('dashboard metrics', () => {
+ beforeEach(() => {
+ metricsWithDataGetter.mockReturnValue([2]);
+ mountComponent();
+ });
+
+ it('passes the correct props to the dashboard Embed component', () => {
+ expect(wrapper.find(MetricEmbed).props()).toEqual(dashboardEmbedProps());
+ });
+
+ it('adds the monitoring dashboard module', () => {
+ expect(store.dispatch).toHaveBeenCalledWith(addModuleAction, 'monitoringDashboard/0');
+ });
+ });
+
+ describe('multiple metrics', () => {
+ beforeEach(() => {
+ metricsWithDataGetter.mockReturnValue([1, 1]);
+ mountComponent({ urls: [TEST_HOST, TEST_HOST] });
+ });
+
+ it('creates Embed components', () => {
+ expect(wrapper.findAll(MetricEmbed)).toHaveLength(2);
+ });
+
+ it('passes the correct props to the Embed components', () => {
+ expect(wrapper.findAll(MetricEmbed).wrappers.map(item => item.props())).toEqual(
+ multipleEmbedProps(),
+ );
+ });
+
+ it('adds multiple monitoring dashboard modules', () => {
+ expect(store.dispatch).toHaveBeenCalledWith(addModuleAction, 'monitoringDashboard/0');
+ expect(store.dispatch).toHaveBeenCalledWith(addModuleAction, 'monitoringDashboard/1');
+ });
+ });
+
+ describe('button text', () => {
+ it('has a singular label when there is one embed', () => {
+ metricsWithDataGetter.mockReturnValue([1]);
+ mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+
+ expect(wrapper.find(GlButton).text()).toBe('Hide chart');
+ });
+
+ it('has a plural label when there are multiple embeds', () => {
+ metricsWithDataGetter.mockReturnValue([2]);
+ mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+
+ expect(wrapper.find(GlButton).text()).toBe('Hide charts');
+ });
+ });
+});
diff --git a/spec/frontend/monitoring/embed/embed_spec.js b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
index 850092c4a72..d0fe22cefec 100644
--- a/spec/frontend/monitoring/embed/embed_spec.js
+++ b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
@@ -2,20 +2,20 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue';
import { TEST_HOST } from 'helpers/test_constants';
-import Embed from '~/monitoring/components/embed.vue';
+import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
import { groups, initialState, metricsData, metricsWithData } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
-describe('Embed', () => {
+describe('MetricEmbed', () => {
let wrapper;
let store;
let actions;
let metricsWithDataGetter;
function mountComponent() {
- wrapper = shallowMount(Embed, {
+ wrapper = shallowMount(MetricEmbed, {
localVue,
store,
propsData: {
diff --git a/spec/frontend/monitoring/embed/mock_data.js b/spec/frontend/monitoring/components/embeds/mock_data.js
index da8eb8c0fc4..9cf66e52d22 100644
--- a/spec/frontend/monitoring/embed/mock_data.js
+++ b/spec/frontend/monitoring/components/embeds/mock_data.js
@@ -1,3 +1,5 @@
+import { TEST_HOST } from 'helpers/test_constants';
+
export const metricsWithData = ['15_metric_a', '16_metric_b'];
export const groups = [
@@ -52,3 +54,34 @@ export const initialState = () => ({
},
useDashboardEndpoint: true,
});
+
+export const initialEmbedGroupState = () => ({
+ modules: [],
+});
+
+export const singleEmbedProps = () => ({
+ dashboardUrl: TEST_HOST,
+ containerClass: 'col-lg-12',
+ namespace: 'monitoringDashboard/0',
+});
+
+export const dashboardEmbedProps = () => ({
+ dashboardUrl: TEST_HOST,
+ containerClass: 'col-lg-6',
+ namespace: 'monitoringDashboard/0',
+});
+
+export const multipleEmbedProps = () => [
+ {
+ dashboardUrl: TEST_HOST,
+ containerClass: 'col-lg-6',
+ namespace: 'monitoringDashboard/0',
+ },
+ {
+ dashboardUrl: TEST_HOST,
+ containerClass: 'col-lg-6',
+ namespace: 'monitoringDashboard/1',
+ },
+];
+
+export const addModuleAction = 'embedGroup/addModule';
diff --git a/spec/frontend/monitoring/components/panel_type_spec.js b/spec/frontend/monitoring/components/panel_type_spec.js
index 927d93ab697..782a276a91b 100644
--- a/spec/frontend/monitoring/components/panel_type_spec.js
+++ b/spec/frontend/monitoring/components/panel_type_spec.js
@@ -8,8 +8,17 @@ import PanelType from '~/monitoring/components/panel_type.vue';
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
import TimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
import AnomalyChart from '~/monitoring/components/charts/anomaly.vue';
-import { anomalyMockGraphData, graphDataPrometheusQueryRange } from 'jest/monitoring/mock_data';
-import { createStore } from '~/monitoring/stores';
+import {
+ anomalyMockGraphData,
+ graphDataPrometheusQueryRange,
+ mockLogsHref,
+ mockLogsPath,
+ mockNamespace,
+ mockNamespacedData,
+ mockTimeRange,
+} from 'jest/monitoring/mock_data';
+import { createStore, monitoringDashboard } from '~/monitoring/stores';
+import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group';
global.IS_EE = true;
global.URL.createObjectURL = jest.fn();
@@ -29,6 +38,7 @@ describe('Panel Type component', () => {
const exampleText = 'example_text';
const findCopyLink = () => wrapper.find({ ref: 'copyChartLink' });
+ const findTimeChart = () => wrapper.find({ ref: 'timeChart' });
const createWrapper = props => {
wrapper = shallowMount(PanelType, {
@@ -99,8 +109,6 @@ describe('Panel Type component', () => {
});
describe('when graph data is available', () => {
- const findTimeChart = () => wrapper.find({ ref: 'timeChart' });
-
beforeEach(() => {
createWrapper({
graphData: graphDataPrometheusQueryRange,
@@ -242,10 +250,6 @@ describe('Panel Type component', () => {
});
describe('View Logs dropdown item', () => {
- const mockLogsPath = '/path/to/logs';
- const mockTimeRange = { duration: { seconds: 120 } };
-
- const findTimeChart = () => wrapper.find({ ref: 'timeChart' });
const findViewLogsLink = () => wrapper.find({ ref: 'viewLogsLink' });
beforeEach(() => {
@@ -292,8 +296,7 @@ describe('Panel Type component', () => {
state.timeRange = mockTimeRange;
return wrapper.vm.$nextTick(() => {
- const href = `${mockLogsPath}?duration_seconds=${mockTimeRange.duration.seconds}`;
- expect(findViewLogsLink().attributes('href')).toMatch(href);
+ expect(findViewLogsLink().attributes('href')).toMatch(mockLogsHref);
});
});
@@ -388,4 +391,53 @@ describe('Panel Type component', () => {
});
});
});
+
+ describe('when using dynamic modules', () => {
+ const { mockDeploymentData, mockProjectPath } = mockNamespacedData;
+
+ beforeEach(() => {
+ store = createEmbedGroupStore();
+ store.registerModule(mockNamespace, monitoringDashboard);
+ store.state.embedGroup.modules.push(mockNamespace);
+
+ wrapper = shallowMount(PanelType, {
+ propsData: {
+ graphData: graphDataPrometheusQueryRange,
+ namespace: mockNamespace,
+ },
+ store,
+ mocks,
+ });
+ });
+
+ it('handles namespaced time range and logs path state', () => {
+ store.state[mockNamespace].timeRange = mockTimeRange;
+ store.state[mockNamespace].logsPath = mockLogsPath;
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.find({ ref: 'viewLogsLink' }).attributes().href).toBe(mockLogsHref);
+ });
+ });
+
+ it('handles namespaced deployment data state', () => {
+ store.state[mockNamespace].deploymentData = mockDeploymentData;
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findTimeChart().props().deploymentData).toEqual(mockDeploymentData);
+ });
+ });
+
+ it('handles namespaced project path state', () => {
+ store.state[mockNamespace].projectPath = mockProjectPath;
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findTimeChart().props().projectPath).toBe(mockProjectPath);
+ });
+ });
+
+ it('it renders a time series chart with no errors', () => {
+ expect(wrapper.find(TimeSeriesChart).isVueInstance()).toBe(true);
+ expect(wrapper.find(TimeSeriesChart).exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index 284b7a0997f..58693723624 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -750,3 +750,20 @@ export const barMockData = {
},
],
};
+
+export const baseNamespace = 'monitoringDashboard';
+
+export const mockNamespace = `${baseNamespace}/1`;
+
+export const mockNamespaces = [`${baseNamespace}/1`, `${baseNamespace}/2`];
+
+export const mockTimeRange = { duration: { seconds: 120 } };
+
+export const mockNamespacedData = {
+ mockDeploymentData: ['mockDeploymentData'],
+ mockProjectPath: '/mockProjectPath',
+};
+
+export const mockLogsPath = '/mockLogsPath';
+
+export const mockLogsHref = `${mockLogsPath}?duration_seconds=${mockTimeRange.duration.seconds}`;
diff --git a/spec/frontend/monitoring/store/embed_group/actions_spec.js b/spec/frontend/monitoring/store/embed_group/actions_spec.js
new file mode 100644
index 00000000000..5bdfc506cff
--- /dev/null
+++ b/spec/frontend/monitoring/store/embed_group/actions_spec.js
@@ -0,0 +1,16 @@
+// import store from '~/monitoring/stores/embed_group';
+import * as actions from '~/monitoring/stores/embed_group/actions';
+import * as types from '~/monitoring/stores/embed_group/mutation_types';
+import { mockNamespace } from '../../mock_data';
+
+describe('Embed group actions', () => {
+ describe('addModule', () => {
+ it('adds a module to the store', () => {
+ const commit = jest.fn();
+
+ actions.addModule({ commit }, mockNamespace);
+
+ expect(commit).toHaveBeenCalledWith(types.ADD_MODULE, mockNamespace);
+ });
+ });
+});
diff --git a/spec/frontend/monitoring/store/embed_group/getters_spec.js b/spec/frontend/monitoring/store/embed_group/getters_spec.js
new file mode 100644
index 00000000000..e3241e41f5e
--- /dev/null
+++ b/spec/frontend/monitoring/store/embed_group/getters_spec.js
@@ -0,0 +1,19 @@
+import { metricsWithData } from '~/monitoring/stores/embed_group/getters';
+import { mockNamespaces } from '../../mock_data';
+
+describe('Embed group getters', () => {
+ describe('metricsWithData', () => {
+ it('correctly sums the number of metrics with data', () => {
+ const mockMetric = {};
+ const state = {
+ modules: mockNamespaces,
+ };
+ const rootGetters = {
+ [`${mockNamespaces[0]}/metricsWithData`]: () => [mockMetric],
+ [`${mockNamespaces[1]}/metricsWithData`]: () => [mockMetric, mockMetric],
+ };
+
+ expect(metricsWithData(state, null, null, rootGetters)).toEqual([1, 2]);
+ });
+ });
+});
diff --git a/spec/frontend/monitoring/store/embed_group/mutations_spec.js b/spec/frontend/monitoring/store/embed_group/mutations_spec.js
new file mode 100644
index 00000000000..a1d04e23e41
--- /dev/null
+++ b/spec/frontend/monitoring/store/embed_group/mutations_spec.js
@@ -0,0 +1,16 @@
+import state from '~/monitoring/stores/embed_group/state';
+import mutations from '~/monitoring/stores/embed_group/mutations';
+import * as types from '~/monitoring/stores/embed_group/mutation_types';
+import { mockNamespace } from '../../mock_data';
+
+describe('Embed group mutations', () => {
+ describe('ADD_MODULE', () => {
+ it('should add a module', () => {
+ const stateCopy = state();
+
+ mutations[types.ADD_MODULE](stateCopy, mockNamespace);
+
+ expect(stateCopy.modules).toEqual([mockNamespace]);
+ });
+ });
+});