Commit 37805a8d authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '217758-add-empty-state-tests' into 'master'

Add constants for empty dashboard states

Closes #217758

See merge request gitlab-org/gitlab!36405
parents edc2761f 2125551c
<script> <script>
import { GlEmptyState } from '@gitlab/ui'; import { GlEmptyState } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { dashboardEmptyStates } from '../constants';
export default { export default {
components: { components: {
...@@ -54,7 +55,7 @@ export default { ...@@ -54,7 +55,7 @@ export default {
data() { data() {
return { return {
states: { states: {
gettingStarted: { [dashboardEmptyStates.GETTING_STARTED]: {
svgUrl: this.emptyGettingStartedSvgPath, svgUrl: this.emptyGettingStartedSvgPath,
title: __('Get started with performance monitoring'), title: __('Get started with performance monitoring'),
description: __(`Stay updated about the performance and health description: __(`Stay updated about the performance and health
...@@ -64,7 +65,7 @@ export default { ...@@ -64,7 +65,7 @@ export default {
secondaryButtonText: __('Configure existing installation'), secondaryButtonText: __('Configure existing installation'),
secondaryButtonPath: this.settingsPath, secondaryButtonPath: this.settingsPath,
}, },
loading: { [dashboardEmptyStates.LOADING]: {
svgUrl: this.emptyLoadingSvgPath, svgUrl: this.emptyLoadingSvgPath,
title: __('Waiting for performance data'), title: __('Waiting for performance data'),
description: __(`Creating graphs uses the data from the Prometheus server. description: __(`Creating graphs uses the data from the Prometheus server.
...@@ -74,7 +75,7 @@ export default { ...@@ -74,7 +75,7 @@ export default {
secondaryButtonText: '', secondaryButtonText: '',
secondaryButtonPath: '', secondaryButtonPath: '',
}, },
noData: { [dashboardEmptyStates.NO_DATA]: {
svgUrl: this.emptyNoDataSvgPath, svgUrl: this.emptyNoDataSvgPath,
title: __('No data found'), title: __('No data found'),
description: __(`You are connected to the Prometheus server, but there is currently description: __(`You are connected to the Prometheus server, but there is currently
...@@ -84,7 +85,7 @@ export default { ...@@ -84,7 +85,7 @@ export default {
secondaryButtonText: '', secondaryButtonText: '',
secondaryButtonPath: '', secondaryButtonPath: '',
}, },
unableToConnect: { [dashboardEmptyStates.UNABLE_TO_CONNECT]: {
svgUrl: this.emptyUnableToConnectSvgPath, svgUrl: this.emptyUnableToConnectSvgPath,
title: __('Unable to connect to Prometheus server'), title: __('Unable to connect to Prometheus server'),
description: __( description: __(
......
export const PROMETHEUS_TIMEOUT = 120000; // TWO_MINUTES export const PROMETHEUS_TIMEOUT = 120000; // TWO_MINUTES
export const dashboardEmptyStates = {
GETTING_STARTED: 'gettingStarted',
LOADING: 'loading',
NO_DATA: 'noData',
UNABLE_TO_CONNECT: 'unableToConnect',
};
/** /**
* States and error states in Prometheus Queries (PromQL) for metrics * States and error states in Prometheus Queries (PromQL) for metrics
*/ */
......
...@@ -4,7 +4,7 @@ import * as types from './mutation_types'; ...@@ -4,7 +4,7 @@ import * as types from './mutation_types';
import { mapToDashboardViewModel, normalizeQueryResponseData } from './utils'; import { mapToDashboardViewModel, normalizeQueryResponseData } from './utils';
import httpStatusCodes from '~/lib/utils/http_status'; import httpStatusCodes from '~/lib/utils/http_status';
import { BACKOFF_TIMEOUT } from '../../lib/utils/common_utils'; import { BACKOFF_TIMEOUT } from '../../lib/utils/common_utils';
import { endpointKeys, initialStateKeys, metricStates } from '../constants'; import { dashboardEmptyStates, endpointKeys, initialStateKeys, metricStates } from '../constants';
import { optionsFromSeriesData } from './variable_mapping'; import { optionsFromSeriesData } from './variable_mapping';
/** /**
...@@ -58,7 +58,7 @@ export default { ...@@ -58,7 +58,7 @@ export default {
* Dashboard panels structure and global state * Dashboard panels structure and global state
*/ */
[types.REQUEST_METRICS_DASHBOARD](state) { [types.REQUEST_METRICS_DASHBOARD](state) {
state.emptyState = 'loading'; state.emptyState = dashboardEmptyStates.LOADING;
state.showEmptyState = true; state.showEmptyState = true;
}, },
[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboardYML) { [types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboardYML) {
...@@ -71,11 +71,13 @@ export default { ...@@ -71,11 +71,13 @@ export default {
state.links = links; state.links = links;
if (!state.dashboard.panelGroups.length) { if (!state.dashboard.panelGroups.length) {
state.emptyState = 'noData'; state.emptyState = dashboardEmptyStates.NO_DATA;
} }
}, },
[types.RECEIVE_METRICS_DASHBOARD_FAILURE](state, error) { [types.RECEIVE_METRICS_DASHBOARD_FAILURE](state, error) {
state.emptyState = error ? 'unableToConnect' : 'noData'; state.emptyState = error
? dashboardEmptyStates.UNABLE_TO_CONNECT
: dashboardEmptyStates.NO_DATA;
state.showEmptyState = true; state.showEmptyState = true;
}, },
...@@ -151,6 +153,8 @@ export default { ...@@ -151,6 +153,8 @@ export default {
metric.loading = false; metric.loading = false;
state.showEmptyState = false; state.showEmptyState = false;
state.emptyState = null;
if (!data.result || data.result.length === 0) { if (!data.result || data.result.length === 0) {
metric.state = metricStates.NO_DATA; metric.state = metricStates.NO_DATA;
metric.result = null; metric.result = null;
...@@ -180,11 +184,12 @@ export default { ...@@ -180,11 +184,12 @@ export default {
state.timeRange = timeRange; state.timeRange = timeRange;
}, },
[types.SET_GETTING_STARTED_EMPTY_STATE](state) { [types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.emptyState = 'gettingStarted'; state.showEmptyState = true;
state.emptyState = dashboardEmptyStates.GETTING_STARTED;
}, },
[types.SET_NO_DATA_EMPTY_STATE](state) { [types.SET_NO_DATA_EMPTY_STATE](state) {
state.showEmptyState = true; state.showEmptyState = true;
state.emptyState = 'noData'; state.emptyState = dashboardEmptyStates.NO_DATA;
}, },
[types.SET_ALL_DASHBOARDS](state, dashboards) { [types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards || []; state.allDashboards = dashboards || [];
......
import invalidUrl from '~/lib/utils/invalid_url'; import invalidUrl from '~/lib/utils/invalid_url';
import { timezones } from '../format_date'; import { timezones } from '../format_date';
import { dashboardEmptyStates } from '../constants';
export default () => ({ export default () => ({
// API endpoints // API endpoints
...@@ -20,7 +21,7 @@ export default () => ({ ...@@ -20,7 +21,7 @@ export default () => ({
// Dashboard data // Dashboard data
hasDashboardValidationWarnings: false, hasDashboardValidationWarnings: false,
emptyState: 'gettingStarted', emptyState: dashboardEmptyStates.GETTING_STARTED,
showEmptyState: true, showEmptyState: true,
showErrorBanner: true, showErrorBanner: true,
isUpdatingStarredValue: false, isUpdatingStarredValue: false,
......
...@@ -24,6 +24,18 @@ exports[`EmptyState shows loading state 1`] = ` ...@@ -24,6 +24,18 @@ exports[`EmptyState shows loading state 1`] = `
/> />
`; `;
exports[`EmptyState shows noData state 1`] = `
<gl-empty-state-stub
description="You are connected to the Prometheus server, but there is currently no data to display."
primarybuttonlink="/settingsPath"
primarybuttontext="Configure Prometheus"
secondarybuttonlink=""
secondarybuttontext=""
svgpath="/path/to/no-data.svg"
title="No data found"
/>
`;
exports[`EmptyState shows unableToConnect state 1`] = ` exports[`EmptyState shows unableToConnect state 1`] = `
<gl-empty-state-stub <gl-empty-state-stub
description="Ensure connectivity is available from the GitLab server to the Prometheus server" description="Ensure connectivity is available from the GitLab server to the Prometheus server"
......
...@@ -6,7 +6,7 @@ import { objectToQuery } from '~/lib/utils/url_utility'; ...@@ -6,7 +6,7 @@ import { objectToQuery } from '~/lib/utils/url_utility';
import VueDraggable from 'vuedraggable'; import VueDraggable from 'vuedraggable';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { metricStates } from '~/monitoring/constants'; import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
import Dashboard from '~/monitoring/components/dashboard.vue'; import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue'; import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
...@@ -126,13 +126,13 @@ describe('Dashboard', () => { ...@@ -126,13 +126,13 @@ describe('Dashboard', () => {
}); });
it('shows up a loading state', () => { it('shows up a loading state', () => {
store.state.monitoringDashboard.emptyState = 'loading'; store.state.monitoringDashboard.emptyState = dashboardEmptyStates.LOADING;
createShallowWrapper({ hasMetrics: true }); createShallowWrapper({ hasMetrics: true });
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(EmptyState).exists()).toBe(true); expect(wrapper.find(EmptyState).exists()).toBe(true);
expect(wrapper.find(EmptyState).props('selectedState')).toBe('loading'); expect(wrapper.find(EmptyState).props('selectedState')).toBe(dashboardEmptyStates.LOADING);
}); });
}); });
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { dashboardEmptyStates } from '~/monitoring/constants';
import EmptyState from '~/monitoring/components/empty_state.vue'; import EmptyState from '~/monitoring/components/empty_state.vue';
function createComponent(props) { function createComponent(props) {
...@@ -20,7 +21,7 @@ function createComponent(props) { ...@@ -20,7 +21,7 @@ function createComponent(props) {
describe('EmptyState', () => { describe('EmptyState', () => {
it('shows gettingStarted state', () => { it('shows gettingStarted state', () => {
const wrapper = createComponent({ const wrapper = createComponent({
selectedState: 'gettingStarted', selectedState: dashboardEmptyStates.GETTING_STARTED,
}); });
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
...@@ -28,7 +29,7 @@ describe('EmptyState', () => { ...@@ -28,7 +29,7 @@ describe('EmptyState', () => {
it('shows loading state', () => { it('shows loading state', () => {
const wrapper = createComponent({ const wrapper = createComponent({
selectedState: 'loading', selectedState: dashboardEmptyStates.LOADING,
}); });
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
...@@ -36,7 +37,15 @@ describe('EmptyState', () => { ...@@ -36,7 +37,15 @@ describe('EmptyState', () => {
it('shows unableToConnect state', () => { it('shows unableToConnect state', () => {
const wrapper = createComponent({ const wrapper = createComponent({
selectedState: 'unableToConnect', selectedState: dashboardEmptyStates.UNABLE_TO_CONNECT,
});
expect(wrapper.element).toMatchSnapshot();
});
it('shows noData state', () => {
const wrapper = createComponent({
selectedState: dashboardEmptyStates.NO_DATA,
}); });
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
......
...@@ -3,7 +3,7 @@ import httpStatusCodes from '~/lib/utils/http_status'; ...@@ -3,7 +3,7 @@ import httpStatusCodes from '~/lib/utils/http_status';
import mutations from '~/monitoring/stores/mutations'; import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types'; import * as types from '~/monitoring/stores/mutation_types';
import state from '~/monitoring/stores/state'; import state from '~/monitoring/stores/state';
import { metricStates } from '~/monitoring/constants'; import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
import { deploymentData, dashboardGitResponse, storeTextVariables } from '../mock_data'; import { deploymentData, dashboardGitResponse, storeTextVariables } from '../mock_data';
import { metricsDashboardPayload } from '../fixture_data'; import { metricsDashboardPayload } from '../fixture_data';
...@@ -15,6 +15,15 @@ describe('Monitoring mutations', () => { ...@@ -15,6 +15,15 @@ describe('Monitoring mutations', () => {
stateCopy = state(); stateCopy = state();
}); });
describe('REQUEST_METRICS_DASHBOARD', () => {
it('sets an empty loading state', () => {
mutations[types.REQUEST_METRICS_DASHBOARD](stateCopy);
expect(stateCopy.emptyState).toBe(dashboardEmptyStates.LOADING);
expect(stateCopy.showEmptyState).toBe(true);
});
});
describe('RECEIVE_METRICS_DASHBOARD_SUCCESS', () => { describe('RECEIVE_METRICS_DASHBOARD_SUCCESS', () => {
let payload; let payload;
const getGroups = () => stateCopy.dashboard.panelGroups; const getGroups = () => stateCopy.dashboard.panelGroups;
...@@ -23,6 +32,18 @@ describe('Monitoring mutations', () => { ...@@ -23,6 +32,18 @@ describe('Monitoring mutations', () => {
stateCopy.dashboard.panelGroups = []; stateCopy.dashboard.panelGroups = [];
payload = metricsDashboardPayload; payload = metricsDashboardPayload;
}); });
it('sets an empty noData state when the dashboard is empty', () => {
const emptyDashboardPayload = {
...payload,
panel_groups: [],
};
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](stateCopy, emptyDashboardPayload);
const groups = getGroups();
expect(groups).toEqual([]);
expect(stateCopy.emptyState).toBe(dashboardEmptyStates.NO_DATA);
});
it('adds a key to the group', () => { it('adds a key to the group', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](stateCopy, payload); mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](stateCopy, payload);
const groups = getGroups(); const groups = getGroups();
...@@ -72,6 +93,22 @@ describe('Monitoring mutations', () => { ...@@ -72,6 +93,22 @@ describe('Monitoring mutations', () => {
}); });
}); });
describe('RECEIVE_METRICS_DASHBOARD_FAILURE', () => {
it('sets an empty noData state when an empty error occurs', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_FAILURE](stateCopy);
expect(stateCopy.emptyState).toBe(dashboardEmptyStates.NO_DATA);
expect(stateCopy.showEmptyState).toBe(true);
});
it('sets an empty unableToConnect state when an error occurs', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_FAILURE](stateCopy, 'myerror');
expect(stateCopy.emptyState).toBe(dashboardEmptyStates.UNABLE_TO_CONNECT);
expect(stateCopy.showEmptyState).toBe(true);
});
});
describe('Dashboard starring mutations', () => { describe('Dashboard starring mutations', () => {
it('REQUEST_DASHBOARD_STARRING', () => { it('REQUEST_DASHBOARD_STARRING', () => {
stateCopy = { isUpdatingStarredValue: false }; stateCopy = { isUpdatingStarredValue: false };
...@@ -283,6 +320,7 @@ describe('Monitoring mutations', () => { ...@@ -283,6 +320,7 @@ describe('Monitoring mutations', () => {
}); });
expect(stateCopy.showEmptyState).toBe(false); expect(stateCopy.showEmptyState).toBe(false);
expect(stateCopy.emptyState).toBe(null);
}); });
it('adds results to the store', () => { it('adds results to the store', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment