2017-09-10 17:25:29 +05:30
|
|
|
import Vue from 'vue';
|
2019-10-12 21:52:04 +05:30
|
|
|
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|
|
|
import { GlToast } from '@gitlab/ui';
|
2019-12-21 20:55:43 +05:30
|
|
|
import VueDraggable from 'vuedraggable';
|
2018-03-17 18:26:18 +05:30
|
|
|
import MockAdapter from 'axios-mock-adapter';
|
|
|
|
import Dashboard from '~/monitoring/components/dashboard.vue';
|
2020-01-01 13:55:28 +05:30
|
|
|
import { metricStates } from '~/monitoring/constants';
|
|
|
|
import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
|
2019-09-04 21:01:54 +05:30
|
|
|
import * as types from '~/monitoring/stores/mutation_types';
|
|
|
|
import { createStore } from '~/monitoring/stores';
|
2018-03-17 18:26:18 +05:30
|
|
|
import axios from '~/lib/utils/axios_utils';
|
2019-12-26 22:10:19 +05:30
|
|
|
import {
|
2019-09-04 21:01:54 +05:30
|
|
|
metricsGroupsAPIResponse,
|
2020-01-01 13:55:28 +05:30
|
|
|
mockedEmptyResult,
|
2019-12-26 22:10:19 +05:30
|
|
|
mockedQueryResultPayload,
|
|
|
|
mockedQueryResultPayloadCoresTotal,
|
2019-09-04 21:01:54 +05:30
|
|
|
mockApiEndpoint,
|
|
|
|
environmentData,
|
2019-09-30 21:07:59 +05:30
|
|
|
dashboardGitResponse,
|
2019-12-04 20:38:33 +05:30
|
|
|
} from '../mock_data';
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2019-10-12 21:52:04 +05:30
|
|
|
const localVue = createLocalVue();
|
2018-12-05 23:21:45 +05:30
|
|
|
const propsData = {
|
|
|
|
hasMetrics: false,
|
|
|
|
documentationPath: '/path/to/docs',
|
|
|
|
settingsPath: '/path/to/settings',
|
|
|
|
clustersPath: '/path/to/clusters',
|
|
|
|
tagsPath: '/path/to/tags',
|
|
|
|
projectPath: '/path/to/project',
|
|
|
|
metricsEndpoint: mockApiEndpoint,
|
2019-09-04 21:01:54 +05:30
|
|
|
deploymentsEndpoint: null,
|
2018-12-05 23:21:45 +05:30
|
|
|
emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
|
|
|
|
emptyLoadingSvgPath: '/path/to/loading.svg',
|
|
|
|
emptyNoDataSvgPath: '/path/to/no-data.svg',
|
2020-01-01 13:55:28 +05:30
|
|
|
emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg',
|
2018-12-05 23:21:45 +05:30
|
|
|
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
|
|
|
|
environmentsEndpoint: '/root/hello-prometheus/environments/35',
|
|
|
|
currentEnvironmentName: 'production',
|
2019-07-31 22:56:46 +05:30
|
|
|
customMetricsAvailable: false,
|
|
|
|
customMetricsPath: '',
|
|
|
|
validateQueryPath: '',
|
2018-12-05 23:21:45 +05:30
|
|
|
};
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
const resetSpy = spy => {
|
|
|
|
if (spy) {
|
|
|
|
spy.calls.reset();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
let expectedPanelCount;
|
2018-12-05 23:21:45 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
function setupComponentStore(component) {
|
2020-01-01 13:55:28 +05:30
|
|
|
// Load 2 panel groups
|
2019-12-26 22:10:19 +05:30
|
|
|
component.$store.commit(
|
|
|
|
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
|
|
|
|
metricsGroupsAPIResponse,
|
|
|
|
);
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
// Load 3 panels to the dashboard, one with an empty result
|
2019-12-26 22:10:19 +05:30
|
|
|
component.$store.commit(
|
2020-01-01 13:55:28 +05:30
|
|
|
`monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
|
|
|
|
mockedEmptyResult,
|
|
|
|
);
|
|
|
|
component.$store.commit(
|
|
|
|
`monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
|
2019-12-26 22:10:19 +05:30
|
|
|
mockedQueryResultPayload,
|
|
|
|
);
|
|
|
|
component.$store.commit(
|
2020-01-01 13:55:28 +05:30
|
|
|
`monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
|
2019-12-26 22:10:19 +05:30
|
|
|
mockedQueryResultPayloadCoresTotal,
|
|
|
|
);
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
expectedPanelCount = 2;
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
component.$store.commit(
|
|
|
|
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
|
|
|
|
environmentData,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
describe('Dashboard', () => {
|
|
|
|
let DashboardComponent;
|
2019-03-02 22:35:43 +05:30
|
|
|
let mock;
|
2019-09-04 21:01:54 +05:30
|
|
|
let store;
|
|
|
|
let component;
|
2020-01-01 13:55:28 +05:30
|
|
|
let wrapper;
|
|
|
|
|
|
|
|
const createComponentWrapper = (props = {}, options = {}) => {
|
|
|
|
wrapper = shallowMount(localVue.extend(DashboardComponent), {
|
|
|
|
localVue,
|
|
|
|
sync: false,
|
|
|
|
propsData: { ...propsData, ...props },
|
|
|
|
store,
|
|
|
|
...options,
|
|
|
|
});
|
|
|
|
};
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
beforeEach(() => {
|
2018-12-05 23:21:45 +05:30
|
|
|
setFixtures(`
|
|
|
|
<div class="prometheus-graphs"></div>
|
2019-03-02 22:35:43 +05:30
|
|
|
<div class="layout-page"></div>
|
2018-12-05 23:21:45 +05:30
|
|
|
`);
|
2019-03-02 22:35:43 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
store = createStore();
|
2019-03-02 22:35:43 +05:30
|
|
|
mock = new MockAdapter(axios);
|
2020-01-01 13:55:28 +05:30
|
|
|
DashboardComponent = localVue.extend(Dashboard);
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
|
|
|
|
2019-03-02 22:35:43 +05:30
|
|
|
afterEach(() => {
|
2019-10-12 21:52:04 +05:30
|
|
|
if (component) {
|
|
|
|
component.$destroy();
|
|
|
|
}
|
2020-01-01 13:55:28 +05:30
|
|
|
if (wrapper) {
|
|
|
|
wrapper.destroy();
|
|
|
|
}
|
2019-03-02 22:35:43 +05:30
|
|
|
mock.restore();
|
|
|
|
});
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
describe('no metrics are available yet', () => {
|
2019-09-30 21:07:59 +05:30
|
|
|
beforeEach(() => {
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2018-03-27 19:54:05 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-09-04 21:01:54 +05:30
|
|
|
propsData: { ...propsData },
|
|
|
|
store,
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
2019-09-30 21:07:59 +05:30
|
|
|
});
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2019-09-30 21:07:59 +05:30
|
|
|
it('shows a getting started empty state when no metrics are present', () => {
|
2018-03-27 19:54:05 +05:30
|
|
|
expect(component.$el.querySelector('.prometheus-graphs')).toBe(null);
|
2019-09-04 21:01:54 +05:30
|
|
|
expect(component.emptyState).toEqual('gettingStarted');
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
2019-09-30 21:07:59 +05:30
|
|
|
|
|
|
|
it('shows the environment selector', () => {
|
|
|
|
expect(component.$el.querySelector('.js-environments-dropdown')).toBeTruthy();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('no data found', () => {
|
|
|
|
it('shows the environment selector dropdown', () => {
|
2020-01-01 13:55:28 +05:30
|
|
|
createComponentWrapper();
|
2019-09-30 21:07:59 +05:30
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
expect(wrapper.find('.js-environments-dropdown').exists()).toBeTruthy();
|
2019-09-30 21:07:59 +05:30
|
|
|
});
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
describe('cluster health', () => {
|
|
|
|
beforeEach(done => {
|
2020-01-01 13:55:28 +05:30
|
|
|
createComponentWrapper({ hasMetrics: true });
|
2019-12-26 22:10:19 +05:30
|
|
|
|
|
|
|
// all_dashboards is not defined in health dashboards
|
|
|
|
wrapper.vm.$store.commit(`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, undefined);
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('renders correctly', () => {
|
|
|
|
expect(wrapper.isVueInstance()).toBe(true);
|
|
|
|
expect(wrapper.exists()).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
describe('requests information to the server', () => {
|
2019-12-21 20:55:43 +05:30
|
|
|
let spy;
|
2017-09-10 17:25:29 +05:30
|
|
|
beforeEach(() => {
|
2018-03-27 19:54:05 +05:30
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
afterEach(() => {
|
|
|
|
resetSpy(spy);
|
|
|
|
});
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
it('shows up a loading state', done => {
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2018-03-27 19:54:05 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-09-04 21:01:54 +05:30
|
|
|
propsData: { ...propsData, hasMetrics: true },
|
|
|
|
store,
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
Vue.nextTick(() => {
|
2019-09-04 21:01:54 +05:30
|
|
|
expect(component.emptyState).toEqual('loading');
|
2017-09-10 17:25:29 +05:30
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
it('hides the group panels when showPanels is false', done => {
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2018-03-27 19:54:05 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-07-07 11:18:12 +05:30
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
showPanels: false,
|
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
store,
|
2018-03-27 19:54:05 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
setupComponentStore(component);
|
|
|
|
|
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
|
|
|
expect(component.showEmptyState).toEqual(false);
|
|
|
|
expect(component.$el.querySelector('.prometheus-panel')).toEqual(null);
|
|
|
|
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
|
|
|
|
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
2018-03-27 19:54:05 +05:30
|
|
|
});
|
2018-11-08 19:23:39 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
describe('when all the requests have been commited by the store', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
component = new DashboardComponent({
|
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
},
|
|
|
|
store,
|
|
|
|
});
|
|
|
|
|
|
|
|
setupComponentStore(component);
|
2018-11-08 19:23:39 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
it('renders the environments dropdown with a number of environments', done => {
|
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
|
|
|
const dropdownMenuEnvironments = component.$el.querySelectorAll(
|
|
|
|
'.js-environments-dropdown .dropdown-item',
|
|
|
|
);
|
2018-11-08 19:23:39 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
expect(component.environments.length).toEqual(environmentData.length);
|
|
|
|
expect(dropdownMenuEnvironments.length).toEqual(component.environments.length);
|
2018-12-13 13:39:08 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
Array.from(dropdownMenuEnvironments).forEach((value, index) => {
|
|
|
|
if (environmentData[index].metrics_path) {
|
|
|
|
expect(value).toHaveAttr('href', environmentData[index].metrics_path);
|
|
|
|
}
|
|
|
|
});
|
2019-09-30 21:07:59 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
|
|
|
});
|
2019-09-30 21:07:59 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
it('renders the environments dropdown with a single active element', done => {
|
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
|
|
|
const dropdownItems = component.$el.querySelectorAll(
|
|
|
|
'.js-environments-dropdown .dropdown-item.active',
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(dropdownItems.length).toEqual(1);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
|
|
|
});
|
2018-11-08 19:23:39 +05:30
|
|
|
});
|
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
it('hides the environments dropdown list when there is no environments', done => {
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2018-12-13 13:39:08 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-07-07 11:18:12 +05:30
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
store,
|
2018-12-13 13:39:08 +05:30
|
|
|
});
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component.$store.commit(
|
|
|
|
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
|
2019-12-26 22:10:19 +05:30
|
|
|
metricsGroupsAPIResponse,
|
|
|
|
);
|
|
|
|
component.$store.commit(
|
2020-01-01 13:55:28 +05:30
|
|
|
`monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
|
2019-12-26 22:10:19 +05:30
|
|
|
mockedQueryResultPayload,
|
2019-09-04 21:01:54 +05:30
|
|
|
);
|
2018-12-13 13:39:08 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
|
|
|
const dropdownMenuEnvironments = component.$el.querySelectorAll(
|
|
|
|
'.js-environments-dropdown .dropdown-item',
|
|
|
|
);
|
2018-12-13 13:39:08 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
expect(dropdownMenuEnvironments.length).toEqual(0);
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
2018-12-13 13:39:08 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
it('renders the datetimepicker dropdown', done => {
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2018-11-08 19:23:39 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-07-07 11:18:12 +05:30
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
showPanels: false,
|
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
store,
|
2018-11-08 19:23:39 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
setupComponentStore(component);
|
2018-11-08 19:23:39 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
2019-12-26 22:10:19 +05:30
|
|
|
expect(component.$el.querySelector('.js-time-window-dropdown')).not.toBeNull();
|
2019-09-04 21:01:54 +05:30
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
2019-07-07 11:18:12 +05:30
|
|
|
});
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
it('fetches the metrics data with proper time window', done => {
|
|
|
|
component = new DashboardComponent({
|
2019-07-07 11:18:12 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
showPanels: false,
|
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
store,
|
2019-07-07 11:18:12 +05:30
|
|
|
});
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
spyOn(component.$store, 'dispatch').and.stub();
|
2019-10-12 21:52:04 +05:30
|
|
|
const getTimeDiffSpy = spyOnDependency(Dashboard, 'getTimeDiff').and.callThrough();
|
2019-07-07 11:18:12 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component.$store.commit(
|
|
|
|
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
|
|
|
|
environmentData,
|
|
|
|
);
|
2019-07-07 11:18:12 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component.$mount();
|
|
|
|
|
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
|
|
|
expect(component.$store.dispatch).toHaveBeenCalled();
|
2019-10-12 21:52:04 +05:30
|
|
|
expect(getTimeDiffSpy).toHaveBeenCalled();
|
2019-09-04 21:01:54 +05:30
|
|
|
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
2018-11-08 19:23:39 +05:30
|
|
|
});
|
2019-07-31 22:56:46 +05:30
|
|
|
|
|
|
|
it('shows a specific time window selected from the url params', done => {
|
2019-12-21 20:55:43 +05:30
|
|
|
const start = '2019-10-01T18:27:47.000Z';
|
|
|
|
const end = '2019-10-01T18:57:47.000Z';
|
2019-10-12 21:52:04 +05:30
|
|
|
spyOnDependency(Dashboard, 'getTimeDiff').and.returnValue({
|
|
|
|
start,
|
|
|
|
end,
|
|
|
|
});
|
|
|
|
spyOnDependency(Dashboard, 'getParameterValues').and.callFake(param => {
|
|
|
|
if (param === 'start') return [start];
|
|
|
|
if (param === 'end') return [end];
|
|
|
|
return [];
|
|
|
|
});
|
2019-07-31 22:56:46 +05:30
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2019-07-31 22:56:46 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-09-04 21:01:54 +05:30
|
|
|
propsData: { ...propsData, hasMetrics: true },
|
|
|
|
store,
|
2019-12-26 22:10:19 +05:30
|
|
|
sync: false,
|
2019-07-31 22:56:46 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
setupComponentStore(component);
|
2019-07-31 22:56:46 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
Vue.nextTick()
|
|
|
|
.then(() => {
|
|
|
|
const selectedTimeWindow = component.$el.querySelector(
|
|
|
|
'.js-time-window-dropdown .active',
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes');
|
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
2019-07-31 22:56:46 +05:30
|
|
|
});
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
it('shows an error message if invalid url parameters are passed', done => {
|
2019-07-31 22:56:46 +05:30
|
|
|
spyOnDependency(Dashboard, 'getParameterValues').and.returnValue([
|
|
|
|
'<script>alert("XSS")</script>',
|
|
|
|
]);
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2019-07-31 22:56:46 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-09-04 21:01:54 +05:30
|
|
|
propsData: { ...propsData, hasMetrics: true },
|
|
|
|
store,
|
2019-07-31 22:56:46 +05:30
|
|
|
});
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
spy = spyOn(component, 'showInvalidDateError');
|
|
|
|
component.$mount();
|
2019-07-31 22:56:46 +05:30
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
component.$nextTick(() => {
|
|
|
|
expect(component.showInvalidDateError).toHaveBeenCalled();
|
2019-07-31 22:56:46 +05:30
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|
2018-12-05 23:21:45 +05:30
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
describe('when one of the metrics is missing', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(done => {
|
|
|
|
createComponentWrapper({ hasMetrics: true });
|
|
|
|
setupComponentStore(wrapper.vm);
|
|
|
|
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
2019-12-26 22:10:19 +05:30
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
it('shows a group empty area', () => {
|
|
|
|
const emptyGroup = wrapper.findAll({ ref: 'empty-group' });
|
|
|
|
|
|
|
|
expect(emptyGroup).toHaveLength(1);
|
|
|
|
expect(emptyGroup.is(GroupEmptyState)).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('group empty area displays a NO_DATA state', () => {
|
|
|
|
expect(
|
|
|
|
wrapper
|
|
|
|
.findAll({ ref: 'empty-group' })
|
|
|
|
.at(0)
|
|
|
|
.props('selectedState'),
|
|
|
|
).toEqual(metricStates.NO_DATA);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('drag and drop function', () => {
|
2019-12-21 20:55:43 +05:30
|
|
|
const findDraggables = () => wrapper.findAll(VueDraggable);
|
|
|
|
const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled'));
|
|
|
|
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
|
|
|
|
const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
beforeEach(() => {
|
2019-12-21 20:55:43 +05:30
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
2019-12-26 22:10:19 +05:30
|
|
|
});
|
2019-12-21 20:55:43 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
beforeEach(done => {
|
2020-01-01 13:55:28 +05:30
|
|
|
createComponentWrapper({ hasMetrics: true }, { attachToDocument: true });
|
2019-12-21 20:55:43 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
setupComponentStore(wrapper.vm);
|
|
|
|
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
2019-12-21 20:55:43 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('wraps vuedraggable', () => {
|
|
|
|
expect(findDraggablePanels().exists()).toBe(true);
|
|
|
|
expect(findDraggablePanels().length).toEqual(expectedPanelCount);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('is disabled by default', () => {
|
|
|
|
expect(findRearrangeButton().exists()).toBe(false);
|
|
|
|
expect(findEnabledDraggables().length).toBe(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when rearrange is enabled', () => {
|
|
|
|
beforeEach(done => {
|
|
|
|
wrapper.setProps({ rearrangePanelsAvailable: true });
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays rearrange button', () => {
|
|
|
|
expect(findRearrangeButton().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when rearrange button is clicked', () => {
|
|
|
|
const findFirstDraggableRemoveButton = () =>
|
|
|
|
findDraggablePanels()
|
|
|
|
.at(0)
|
|
|
|
.find('.js-draggable-remove');
|
|
|
|
|
|
|
|
beforeEach(done => {
|
|
|
|
findRearrangeButton().vm.$emit('click');
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('it enables draggables', () => {
|
|
|
|
expect(findRearrangeButton().attributes('pressed')).toBeTruthy();
|
|
|
|
expect(findEnabledDraggables()).toEqual(findDraggables());
|
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
it('metrics can be swapped', done => {
|
|
|
|
const firstDraggable = findDraggables().at(0);
|
2020-01-01 13:55:28 +05:30
|
|
|
const mockMetrics = [...metricsGroupsAPIResponse[1].panels];
|
2019-12-26 22:10:19 +05:30
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
const firstTitle = mockMetrics[0].title;
|
|
|
|
const secondTitle = mockMetrics[1].title;
|
2019-12-26 22:10:19 +05:30
|
|
|
|
|
|
|
// swap two elements and `input` them
|
|
|
|
[mockMetrics[0], mockMetrics[1]] = [mockMetrics[1], mockMetrics[0]];
|
|
|
|
firstDraggable.vm.$emit('input', mockMetrics);
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
wrapper.vm.$nextTick(() => {
|
|
|
|
const { panels } = wrapper.vm.dashboard.panel_groups[1];
|
|
|
|
|
|
|
|
expect(panels[1].title).toEqual(firstTitle);
|
|
|
|
expect(panels[0].title).toEqual(secondTitle);
|
2019-12-26 22:10:19 +05:30
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
it('shows a remove button, which removes a panel', done => {
|
|
|
|
expect(findFirstDraggableRemoveButton().isEmpty()).toBe(false);
|
|
|
|
|
|
|
|
expect(findDraggablePanels().length).toEqual(expectedPanelCount);
|
|
|
|
findFirstDraggableRemoveButton().trigger('click');
|
|
|
|
|
|
|
|
wrapper.vm.$nextTick(() => {
|
|
|
|
expect(findDraggablePanels().length).toEqual(expectedPanelCount - 1);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('it disables draggables when clicked again', done => {
|
|
|
|
findRearrangeButton().vm.$emit('click');
|
|
|
|
wrapper.vm.$nextTick(() => {
|
|
|
|
expect(findRearrangeButton().attributes('pressed')).toBeFalsy();
|
|
|
|
expect(findEnabledDraggables().length).toBe(0);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// https://gitlab.com/gitlab-org/gitlab-ce/issues/66922
|
2019-12-04 20:38:33 +05:30
|
|
|
// eslint-disable-next-line jasmine/no-disabled-tests
|
|
|
|
xdescribe('link to chart', () => {
|
2019-10-12 21:52:04 +05:30
|
|
|
const currentDashboard = 'TEST_DASHBOARD';
|
|
|
|
localVue.use(GlToast);
|
|
|
|
const link = () => wrapper.find('.js-chart-link');
|
|
|
|
const clipboardText = () => link().element.dataset.clipboardText;
|
|
|
|
|
|
|
|
beforeEach(done => {
|
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
createComponentWrapper({ hasMetrics: true, currentDashboard }, { attachToDocument: true });
|
2019-10-12 21:52:04 +05:30
|
|
|
|
|
|
|
setTimeout(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('adds a copy button to the dropdown', () => {
|
|
|
|
expect(link().text()).toContain('Generate link to chart');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('contains a link to the dashboard', () => {
|
|
|
|
expect(clipboardText()).toContain(`dashboard=${currentDashboard}`);
|
|
|
|
expect(clipboardText()).toContain(`group=`);
|
|
|
|
expect(clipboardText()).toContain(`title=`);
|
|
|
|
expect(clipboardText()).toContain(`y_label=`);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('undefined parameter is stripped', done => {
|
|
|
|
wrapper.setProps({ currentDashboard: undefined });
|
|
|
|
|
|
|
|
wrapper.vm.$nextTick(() => {
|
|
|
|
expect(clipboardText()).not.toContain(`dashboard=`);
|
|
|
|
expect(clipboardText()).toContain(`y_label=`);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('null parameter is stripped', done => {
|
|
|
|
wrapper.setProps({ currentDashboard: null });
|
|
|
|
|
|
|
|
wrapper.vm.$nextTick(() => {
|
|
|
|
expect(clipboardText()).not.toContain(`dashboard=`);
|
|
|
|
expect(clipboardText()).toContain(`y_label=`);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('creates a toast when clicked', () => {
|
|
|
|
spyOn(wrapper.vm.$toast, 'show').and.stub();
|
|
|
|
|
|
|
|
link().vm.$emit('click');
|
|
|
|
|
|
|
|
expect(wrapper.vm.$toast.show).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
describe('responds to window resizes', () => {
|
|
|
|
let promPanel;
|
|
|
|
let promGroup;
|
|
|
|
let panelToggle;
|
|
|
|
let chart;
|
2018-12-05 23:21:45 +05:30
|
|
|
beforeEach(() => {
|
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
2018-12-05 23:21:45 +05:30
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
2019-07-07 11:18:12 +05:30
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
2019-12-26 22:10:19 +05:30
|
|
|
showPanels: true,
|
2019-07-07 11:18:12 +05:30
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
store,
|
2018-12-05 23:21:45 +05:30
|
|
|
});
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
setupComponentStore(component);
|
2018-12-05 23:21:45 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
return Vue.nextTick().then(() => {
|
2020-01-01 13:55:28 +05:30
|
|
|
[, promPanel] = component.$el.querySelectorAll('.prometheus-panel');
|
2019-12-26 22:10:19 +05:30
|
|
|
promGroup = promPanel.querySelector('.prometheus-graph-group');
|
|
|
|
panelToggle = promPanel.querySelector('.js-graph-group-toggle');
|
|
|
|
chart = promGroup.querySelector('.position-relative svg');
|
|
|
|
});
|
|
|
|
});
|
2018-12-05 23:21:45 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
it('setting chart size to zero when panel group is hidden', () => {
|
|
|
|
expect(promGroup.style.display).toBe('');
|
|
|
|
expect(chart.clientWidth).toBeGreaterThan(0);
|
|
|
|
|
|
|
|
panelToggle.click();
|
|
|
|
return Vue.nextTick().then(() => {
|
|
|
|
expect(promGroup.style.display).toBe('none');
|
|
|
|
expect(chart.clientWidth).toBe(0);
|
|
|
|
promPanel.style.width = '500px';
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('expanding chart panel group after resize displays chart', () => {
|
|
|
|
panelToggle.click();
|
|
|
|
|
|
|
|
expect(chart.clientWidth).toBeGreaterThan(0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('dashboard edit link', () => {
|
|
|
|
const findEditLink = () => wrapper.find('.js-edit-link');
|
|
|
|
|
|
|
|
beforeEach(done => {
|
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
createComponentWrapper({ hasMetrics: true }, { attachToDocument: true });
|
2019-12-26 22:10:19 +05:30
|
|
|
|
|
|
|
wrapper.vm.$store.commit(
|
|
|
|
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
|
|
|
|
dashboardGitResponse,
|
|
|
|
);
|
|
|
|
wrapper.vm.$nextTick(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('is not present for the default dashboard', () => {
|
|
|
|
expect(findEditLink().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('is present for a custom dashboard, and links to its edit_path', done => {
|
|
|
|
const dashboard = dashboardGitResponse[1]; // non-default dashboard
|
|
|
|
const currentDashboard = dashboard.path;
|
|
|
|
|
|
|
|
wrapper.setProps({ currentDashboard });
|
|
|
|
wrapper.vm.$nextTick(() => {
|
|
|
|
expect(findEditLink().exists()).toBe(true);
|
|
|
|
expect(findEditLink().attributes('href')).toBe(dashboard.project_blob_path);
|
|
|
|
done();
|
|
|
|
});
|
2018-12-05 23:21:45 +05:30
|
|
|
});
|
|
|
|
});
|
2019-07-31 22:56:46 +05:30
|
|
|
|
|
|
|
describe('external dashboard link', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
component = new DashboardComponent({
|
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
showPanels: false,
|
|
|
|
showTimeWindowDropdown: false,
|
|
|
|
externalDashboardUrl: '/mockUrl',
|
|
|
|
},
|
|
|
|
store,
|
2019-07-31 22:56:46 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
it('shows the link', done => {
|
|
|
|
setTimeout(() => {
|
|
|
|
expect(component.$el.querySelector('.js-external-dashboard-link').innerText).toContain(
|
|
|
|
'View full dashboard',
|
|
|
|
);
|
|
|
|
done();
|
2019-07-31 22:56:46 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2019-09-30 21:07:59 +05:30
|
|
|
|
|
|
|
describe('Dashboard dropdown', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
|
|
|
|
|
|
|
|
component = new DashboardComponent({
|
|
|
|
el: document.querySelector('.prometheus-graphs'),
|
|
|
|
propsData: {
|
|
|
|
...propsData,
|
|
|
|
hasMetrics: true,
|
|
|
|
showPanels: false,
|
|
|
|
},
|
|
|
|
store,
|
|
|
|
});
|
|
|
|
|
|
|
|
component.$store.commit(
|
|
|
|
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
|
|
|
|
dashboardGitResponse,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('shows the dashboard dropdown', done => {
|
|
|
|
setTimeout(() => {
|
|
|
|
const dashboardDropdown = component.$el.querySelector('.js-dashboards-dropdown');
|
|
|
|
|
|
|
|
expect(dashboardDropdown).not.toEqual(null);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-09-10 17:25:29 +05:30
|
|
|
});
|