Commit 87d384a6 authored by Miguel Rincon's avatar Miguel Rincon

Replaces the loading state with an icon

This change replaces the loading state with an icon and changes loading
order so the dashboard loads data as soon as possible.
parent 4a513828
......@@ -161,7 +161,6 @@ export default {
...mapState('monitoringDashboard', [
'dashboard',
'emptyState',
'showEmptyState',
'expandedPanel',
'variables',
'links',
......@@ -169,6 +168,9 @@ export default {
'hasDashboardValidationWarnings',
]),
...mapGetters('monitoringDashboard', ['selectedDashboard', 'getMetricStates']),
shouldShowEmptyState() {
return Boolean(this.emptyState);
},
shouldShowVariablesSection() {
return Boolean(this.variables.length);
},
......@@ -277,6 +279,14 @@ export default {
}
return null;
},
/**
* Return true if the entire group is loading.
* @param {String} groupKey - Identifier for group
* @returns {boolean}
*/
isGroupLoading(groupKey) {
return this.groupSingleEmptyState(groupKey) === metricStates.LOADING;
},
/**
* A group should be not collapsed if any metric is loaded (OK)
*
......@@ -412,9 +422,9 @@ export default {
@dateTimePickerInvalid="onDateTimePickerInvalid"
@setRearrangingPanels="onSetRearrangingPanels"
/>
<variables-section v-if="shouldShowVariablesSection && !showEmptyState" />
<links-section v-if="shouldShowLinksSection && !showEmptyState" />
<div v-if="!showEmptyState">
<template v-if="!shouldShowEmptyState">
<variables-section v-if="shouldShowVariablesSection" />
<links-section v-if="shouldShowLinksSection" />
<dashboard-panel
v-show="expandedPanel.panel"
ref="expandedPanel"
......@@ -449,6 +459,7 @@ export default {
:key="`${groupData.group}.${groupData.priority}`"
:name="groupData.group"
:show-panels="showPanels"
:is-loading="isGroupLoading(groupData.key)"
:collapse-group="collapseGroup(groupData.key)"
>
<vue-draggable
......@@ -506,7 +517,7 @@ export default {
</div>
</graph-group>
</div>
</div>
</template>
<empty-state
v-else
:selected-state="emptyState"
......
......@@ -119,10 +119,10 @@ export default {
},
computed: {
...mapState('monitoringDashboard', [
'emptyState',
'environmentsLoading',
'currentEnvironmentName',
'isUpdatingStarredValue',
'showEmptyState',
'dashboardTimezone',
'projectPath',
'canAccessOperationsSettings',
......@@ -132,13 +132,16 @@ export default {
isOutOfTheBoxDashboard() {
return this.selectedDashboard?.out_of_the_box_dashboard;
},
shouldShowEmptyState() {
return Boolean(this.emptyState);
},
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
addingMetricsAvailable() {
return (
this.customMetricsAvailable &&
!this.showEmptyState &&
!this.shouldShowEmptyState &&
// Custom metrics only avaialble on system dashboards because
// they are stored in the database. This can be improved. See:
// https://gitlab.com/gitlab-org/gitlab/-/issues/28241
......@@ -146,7 +149,7 @@ export default {
);
},
showRearrangePanelsBtn() {
return !this.showEmptyState && this.rearrangePanelsAvailable;
return !this.shouldShowEmptyState && this.rearrangePanelsAvailable;
},
displayUtc() {
return this.dashboardTimezone === timezones.UTC;
......
<script>
import { GlEmptyState } from '@gitlab/ui';
import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
import { __ } from '~/locale';
import { dashboardEmptyStates } from '../constants';
export default {
components: {
GlLoadingIcon,
GlEmptyState,
},
props: {
selectedState: {
type: String,
required: true,
validator: state => Object.values(dashboardEmptyStates).includes(state),
},
documentationPath: {
type: String,
required: true,
......@@ -22,10 +28,6 @@ export default {
required: false,
default: '',
},
selectedState: {
type: String,
required: true,
},
emptyGettingStartedSvgPath: {
type: String,
required: true,
......@@ -54,52 +56,49 @@ export default {
},
data() {
return {
/**
* Possible empty states.
* Keys in each state must match GlEmptyState props
*/
states: {
[dashboardEmptyStates.GETTING_STARTED]: {
svgUrl: this.emptyGettingStartedSvgPath,
svgPath: this.emptyGettingStartedSvgPath,
title: __('Get started with performance monitoring'),
description: __(`Stay updated about the performance and health
of your environment by configuring Prometheus to monitor your deployments.`),
buttonText: __('Install on clusters'),
buttonPath: this.clustersPath,
primaryButtonText: __('Install on clusters'),
primaryButtonLink: this.clustersPath,
secondaryButtonText: __('Configure existing installation'),
secondaryButtonPath: this.settingsPath,
},
[dashboardEmptyStates.LOADING]: {
svgUrl: this.emptyLoadingSvgPath,
title: __('Waiting for performance data'),
description: __(`Creating graphs uses the data from the Prometheus server.
If this takes a long time, ensure that data is available.`),
buttonText: __('View documentation'),
buttonPath: this.documentationPath,
secondaryButtonText: '',
secondaryButtonPath: '',
secondaryButtonLink: this.settingsPath,
},
[dashboardEmptyStates.NO_DATA]: {
svgUrl: this.emptyNoDataSvgPath,
svgPath: this.emptyNoDataSvgPath,
title: __('No data found'),
description: __(`You are connected to the Prometheus server, but there is currently
no data to display.`),
buttonText: __('Configure Prometheus'),
buttonPath: this.settingsPath,
primaryButtonText: __('Configure Prometheus'),
primaryButtonLink: this.settingsPath,
secondaryButtonText: '',
secondaryButtonPath: '',
secondaryButtonLink: '',
},
[dashboardEmptyStates.UNABLE_TO_CONNECT]: {
svgUrl: this.emptyUnableToConnectSvgPath,
svgPath: this.emptyUnableToConnectSvgPath,
title: __('Unable to connect to Prometheus server'),
description: __(
'Ensure connectivity is available from the GitLab server to the Prometheus server',
),
buttonText: __('View documentation'),
buttonPath: this.documentationPath,
primaryButtonText: __('View documentation'),
primaryButtonLink: this.documentationPath,
secondaryButtonText: __('Configure Prometheus'),
secondaryButtonPath: this.settingsPath,
secondaryButtonLink: this.settingsPath,
},
},
};
},
computed: {
isLoading() {
return this.selectedState === dashboardEmptyStates.LOADING;
},
currentState() {
return this.states[this.selectedState];
},
......@@ -108,14 +107,8 @@ export default {
</script>
<template>
<gl-empty-state
:title="currentState.title"
:description="currentState.description"
:primary-button-text="currentState.buttonText"
:primary-button-link="currentState.buttonPath"
:secondary-button-text="currentState.secondaryButtonText"
:secondary-button-link="currentState.secondaryButtonPath"
:svg-path="currentState.svgUrl"
:compact="compact"
/>
<div>
<gl-loading-icon v-if="isLoading" size="xl" class="gl-my-9" />
<gl-empty-state v-if="currentState" v-bind="currentState" :compact="compact" />
</div>
</template>
<script>
import Icon from '~/vue_shared/components/icon.vue';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
export default {
components: {
Icon,
GlLoadingIcon,
GlIcon,
},
props: {
name: {
......@@ -15,6 +16,11 @@ export default {
required: false,
default: true,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
/**
* Initial value of collapse on mount.
*/
......@@ -55,15 +61,18 @@ export default {
<div v-if="showPanels" ref="graph-group" class="card prometheus-panel">
<div class="card-header d-flex align-items-center">
<h4 class="flex-grow-1">{{ name }}</h4>
<gl-loading-icon v-if="isLoading" name="loading" />
<a
data-testid="group-toggle-button"
:aria-label="__('Toggle collapse')"
:icon="caretIcon"
role="button"
class="js-graph-group-toggle gl-text-gray-900"
class="js-graph-group-toggle gl-display-flex gl-ml-2 gl-text-gray-900"
tabindex="0"
@click="collapse"
@keyup.enter="collapse"
>
<icon :size="16" :aria-label="__('Toggle collapse')" :name="caretIcon" />
<gl-icon :name="caretIcon" />
</a>
</div>
<div
......
......@@ -40,7 +40,6 @@ export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER';
export const SET_PANEL_GROUP_METRICS = 'SET_PANEL_GROUP_METRICS';
export const SET_ENVIRONMENTS_FILTER = 'SET_ENVIRONMENTS_FILTER';
......
......@@ -59,7 +59,6 @@ export default {
*/
[types.REQUEST_METRICS_DASHBOARD](state) {
state.emptyState = dashboardEmptyStates.LOADING;
state.showEmptyState = true;
},
[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboardYML) {
const { dashboard, panelGroups, variables, links } = mapToDashboardViewModel(dashboardYML);
......@@ -72,13 +71,14 @@ export default {
if (!state.dashboard.panelGroups.length) {
state.emptyState = dashboardEmptyStates.NO_DATA;
} else {
state.emptyState = null;
}
},
[types.RECEIVE_METRICS_DASHBOARD_FAILURE](state, error) {
state.emptyState = error
? dashboardEmptyStates.UNABLE_TO_CONNECT
: dashboardEmptyStates.NO_DATA;
state.showEmptyState = true;
},
[types.REQUEST_DASHBOARD_STARRING](state) {
......@@ -152,9 +152,6 @@ export default {
const metric = findMetricInDashboard(metricId, state.dashboard);
metric.loading = false;
state.showEmptyState = false;
state.emptyState = null;
if (!data.result || data.result.length === 0) {
metric.state = metricStates.NO_DATA;
metric.result = null;
......@@ -184,13 +181,8 @@ export default {
state.timeRange = timeRange;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.showEmptyState = true;
state.emptyState = dashboardEmptyStates.GETTING_STARTED;
},
[types.SET_NO_DATA_EMPTY_STATE](state) {
state.showEmptyState = true;
state.emptyState = dashboardEmptyStates.NO_DATA;
},
[types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards || [];
},
......
......@@ -21,8 +21,13 @@ export default () => ({
// Dashboard data
hasDashboardValidationWarnings: false,
/**
* {?String} If set, dashboard should display a global
* empty state, there is no way to interact (yet)
* with the dashboard.
*/
emptyState: dashboardEmptyStates.GETTING_STARTED,
showEmptyState: true,
showErrorBanner: true,
isUpdatingStarredValue: false,
dashboard: {
......
......@@ -76,9 +76,11 @@ module Clusters
'clusters-path': clusterable.index_path,
'dashboard-endpoint': clusterable.metrics_dashboard_path(cluster),
'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster-ultimate'),
'add-dashboard-documentation-path': help_page_path('user/project/integrations/prometheus.md', anchor: 'adding-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': image_path('illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': image_path('illustrations/monitoring/loading.svg'),
'empty-no-data-svg-path': image_path('illustrations/monitoring/no_data.svg'),
'empty-no-data-small-svg-path': image_path('illustrations/chart-empty-state-small.svg'),
'empty-unable-to-connect-svg-path': image_path('illustrations/monitoring/unable_to_connect.svg'),
'settings-path': '',
'project-path': '',
......
---
title: Replace initial dashboard loading state with a loading spinner, show dashboard
skeleton earlier with smaller loading indicators
merge_request: 36399
author:
type: changed
......@@ -141,10 +141,6 @@ exports[`Dashboard template matches the default snapshot 1`] = `
/>
</div>
<!---->
<!---->
<empty-state-stub
clusterspath="/monitoring/monitor-project/-/clusters"
documentationpath="/help/administration/monitoring/prometheus/index.md"
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`EmptyState shows gettingStarted state 1`] = `
<gl-empty-state-stub
description="Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
primarybuttonlink="/clustersPath"
primarybuttontext="Install on clusters"
secondarybuttonlink="/settingsPath"
secondarybuttontext="Configure existing installation"
svgpath="/path/to/getting-started.svg"
title="Get started with performance monitoring"
/>
`;
exports[`EmptyState shows loading state 1`] = `
<gl-empty-state-stub
description="Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
primarybuttonlink="/documentationPath"
primarybuttontext="View documentation"
secondarybuttonlink=""
secondarybuttontext=""
svgpath="/path/to/loading.svg"
title="Waiting for performance data"
/>
<div>
<!---->
<gl-empty-state-stub
description="Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
primarybuttonlink="/clustersPath"
primarybuttontext="Install on clusters"
secondarybuttonlink="/settingsPath"
secondarybuttontext="Configure existing installation"
svgpath="/path/to/getting-started.svg"
title="Get started with performance monitoring"
/>
</div>
`;
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"
/>
<div>
<!---->
<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"
/>
</div>
`;
exports[`EmptyState shows unableToConnect state 1`] = `
<gl-empty-state-stub
description="Ensure connectivity is available from the GitLab server to the Prometheus server"
primarybuttonlink="/documentationPath"
primarybuttontext="View documentation"
secondarybuttonlink="/settingsPath"
secondarybuttontext="Configure Prometheus"
svgpath="/path/to/unable-to-connect.svg"
title="Unable to connect to Prometheus server"
/>
<div>
<!---->
<gl-empty-state-stub
description="Ensure connectivity is available from the GitLab server to the Prometheus server"
primarybuttonlink="/documentationPath"
primarybuttontext="View documentation"
secondarybuttonlink="/settingsPath"
secondarybuttontext="Configure Prometheus"
svgpath="/path/to/unable-to-connect.svg"
title="Unable to connect to Prometheus server"
/>
</div>
`;
......@@ -143,7 +143,7 @@ describe('Dashboard', () => {
setupStoreWithData(store);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.showEmptyState).toEqual(false);
expect(wrapper.vm.emptyState).toBeNull();
expect(wrapper.findAll('.prometheus-panel')).toHaveLength(0);
});
});
......@@ -455,6 +455,33 @@ describe('Dashboard', () => {
});
});
describe('when all panels in the first group are loading', () => {
const findGroupAt = i => wrapper.findAll(GraphGroup).at(i);
beforeEach(() => {
setupStoreWithDashboard(store);
const { panels } = store.state.monitoringDashboard.dashboard.panelGroups[0];
panels.forEach(({ metrics }) => {
store.commit(`monitoringDashboard/${types.REQUEST_METRIC_RESULT}`, {
metricId: metrics[0].metricId,
});
});
createShallowWrapper();
return wrapper.vm.$nextTick();
});
it('a loading icon appears in the first group', () => {
expect(findGroupAt(0).props('isLoading')).toBe(true);
});
it('a loading icon does not appear in the second group', () => {
expect(findGroupAt(1).props('isLoading')).toBe(false);
});
});
describe('when all requests have been commited by the store', () => {
beforeEach(() => {
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
......@@ -478,6 +505,16 @@ describe('Dashboard', () => {
});
});
it('it does not show loading icons in any group', () => {
setupStoreWithData(store);
wrapper.vm.$nextTick(() => {
wrapper.findAll(GraphGroup).wrappers.forEach(groupWrapper => {
expect(groupWrapper.props('isLoading')).toBe(false);
});
});
});
// Note: This test is not working, .active does not show the active environment
// eslint-disable-next-line jest/no-disabled-tests
it.skip('renders the environments dropdown with a single active element', () => {
......
import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
import { dashboardEmptyStates } from '~/monitoring/constants';
import EmptyState from '~/monitoring/components/empty_state.vue';
function createComponent(props) {
return shallowMount(EmptyState, {
propsData: {
...props,
settingsPath: '/settingsPath',
clustersPath: '/clustersPath',
documentationPath: '/documentationPath',
......@@ -14,22 +14,24 @@ function createComponent(props) {
emptyNoDataSvgPath: '/path/to/no-data.svg',
emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
...props,
},
});
}
describe('EmptyState', () => {
it('shows gettingStarted state', () => {
it('shows loading state with a loading icon', () => {
const wrapper = createComponent({
selectedState: dashboardEmptyStates.GETTING_STARTED,
selectedState: dashboardEmptyStates.LOADING,
});
expect(wrapper.element).toMatchSnapshot();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
expect(wrapper.find(GlEmptyState).exists()).toBe(false);
});
it('shows loading state', () => {
it('shows gettingStarted state', () => {
const wrapper = createComponent({
selectedState: dashboardEmptyStates.LOADING,
selectedState: dashboardEmptyStates.GETTING_STARTED,
});
expect(wrapper.element).toMatchSnapshot();
......
import { shallowMount } from '@vue/test-utils';
import GraphGroup from '~/monitoring/components/graph_group.vue';
import Icon from '~/vue_shared/components/icon.vue';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
describe('Graph group component', () => {
let wrapper;
const findGroup = () => wrapper.find({ ref: 'graph-group' });
const findContent = () => wrapper.find({ ref: 'graph-group-content' });
const findCaretIcon = () => wrapper.find(Icon);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findCaretIcon = () => wrapper.find(GlIcon);
const findToggleButton = () => wrapper.find('[data-testid="group-toggle-button"]');
const createComponent = propsData => {
......@@ -28,15 +29,19 @@ describe('Graph group component', () => {
});
});
it('should not show a loading icon', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
it('should show the angle-down caret icon', () => {
expect(findContent().isVisible()).toBe(true);
expect(findCaretIcon().props('name')).toBe('angle-down');
});
it('should show the angle-right caret icon when the user collapses the group', () => {
wrapper.vm.collapse();
findToggleButton().trigger('click');
return wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick().then(() => {
expect(findContent().isVisible()).toBe(false);
expect(findCaretIcon().props('name')).toBe('angle-right');
});
......@@ -53,77 +58,94 @@ describe('Graph group component', () => {
collapseGroup: true,
});
return wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick().then(() => {
expect(findContent().isVisible()).toBe(true);
expect(findCaretIcon().props('name')).toBe('angle-down');
});
});
});
describe('When group is collapsed', () => {
beforeEach(() => {
createComponent({
name: 'panel',
collapseGroup: true,
});
describe('When group is collapsed', () => {
beforeEach(() => {
createComponent({
name: 'panel',
collapseGroup: true,
});
});
it('should show the angle-down caret icon when collapseGroup is true', () => {
expect(wrapper.vm.caretIcon).toBe('angle-right');
});
it('should show the angle-down caret icon when collapseGroup is true', () => {
expect(findCaretIcon().props('name')).toBe('angle-right');
});
it('should show the angle-right caret icon when collapseGroup is false', () => {
wrapper.vm.collapse();
it('should show the angle-right caret icon when collapseGroup is false', () => {
findToggleButton().trigger('click');
expect(wrapper.vm.caretIcon).toBe('angle-down');
return wrapper.vm.$nextTick().then(() => {
expect(findCaretIcon().props('name')).toBe('angle-down');
});
});
it('should call collapse the graph group content when enter is pressed on the caret icon', () => {
const graphGroupContent = findContent();
const button = findToggleButton();
it('should call collapse the graph group content when enter is pressed on the caret icon', () => {
const graphGroupContent = findContent();
const button = findToggleButton();
button.trigger('keyup.enter');
button.trigger('keyup.enter');
expect(graphGroupContent.isVisible()).toBe(false);
expect(graphGroupContent.isVisible()).toBe(false);
});
});
describe('When groups can not be collapsed', () => {
beforeEach(() => {
createComponent({
name: 'panel',
showPanels: false,
collapseGroup: false,
});
});
describe('When groups can not be collapsed', () => {
beforeEach(() => {
createComponent({
name: 'panel',
showPanels: false,
collapseGroup: false,
});
it('should not have a container when showPanels is false', () => {
expect(findGroup().exists()).toBe(false);
expect(findContent().exists()).toBe(true);
});
});
describe('When group is loading', () => {
beforeEach(() => {
createComponent({
name: 'panel',
isLoading: true,
});
});
it('should not have a container when showPanels is false', () => {
expect(findGroup().exists()).toBe(false);
expect(findContent().exists()).toBe(true);
it('should show a loading icon', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
describe('When group does not show a panel heading', () => {
beforeEach(() => {
createComponent({
name: 'panel',
showPanels: false,
collapseGroup: false,
});
});
describe('When group does not show a panel heading', () => {
beforeEach(() => {
createComponent({
name: 'panel',
showPanels: false,
collapseGroup: false,
});
it('should collapse the panel content', () => {
expect(findContent().isVisible()).toBe(true);
expect(findCaretIcon().exists()).toBe(false);
});
it('should show the panel content when collapse is set to false', () => {
wrapper.setProps({
collapseGroup: false,
});
it('should collapse the panel content', () => {
return wrapper.vm.$nextTick().then(() => {
expect(findContent().isVisible()).toBe(true);
expect(findCaretIcon().exists()).toBe(false);
});
it('should show the panel content when clicked', () => {
wrapper.vm.collapse();
return wrapper.vm.$nextTick(() => {
expect(findContent().isVisible()).toBe(true);
expect(findCaretIcon().exists()).toBe(false);
});
});
});
});
});
......@@ -15,7 +15,7 @@ describe('Links Section component', () => {
const setState = links => {
store.state.monitoringDashboard = {
...store.state.monitoringDashboard,
showEmptyState: false,
emptyState: null,
links,
};
};
......
......@@ -29,7 +29,7 @@ describe('Metrics dashboard/variables section component', () => {
beforeEach(() => {
store = createStore();
store.state.monitoringDashboard.showEmptyState = false;
store.state.monitoringDashboard.emptyState = null;
});
it('does not show the variables section', () => {
......@@ -70,7 +70,7 @@ describe('Metrics dashboard/variables section component', () => {
monitoringDashboard: {
namespaced: true,
state: {
showEmptyState: false,
emptyState: null,
variables: storeVariables,
},
actions: {
......
......@@ -20,7 +20,6 @@ describe('Monitoring mutations', () => {
mutations[types.REQUEST_METRICS_DASHBOARD](stateCopy);
expect(stateCopy.emptyState).toBe(dashboardEmptyStates.LOADING);
expect(stateCopy.showEmptyState).toBe(true);
});
});
......@@ -98,14 +97,12 @@ describe('Monitoring mutations', () => {
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);
});
});
......@@ -292,13 +289,10 @@ describe('Monitoring mutations', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](stateCopy, dashboard);
});
it('stores a loading state on a metric', () => {
expect(stateCopy.showEmptyState).toBe(true);
mutations[types.REQUEST_METRIC_RESULT](stateCopy, {
metricId,
});
expect(stateCopy.showEmptyState).toBe(true);
expect(getMetric()).toEqual(
expect.objectContaining({
loading: true,
......@@ -311,17 +305,6 @@ describe('Monitoring mutations', () => {
beforeEach(() => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](stateCopy, dashboard);
});
it('clears empty state', () => {
expect(stateCopy.showEmptyState).toBe(true);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](stateCopy, {
metricId,
data,
});
expect(stateCopy.showEmptyState).toBe(false);
expect(stateCopy.emptyState).toBe(null);
});
it('adds results to the store', () => {
expect(getMetric().result).toBe(null);
......@@ -345,16 +328,6 @@ describe('Monitoring mutations', () => {
beforeEach(() => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](stateCopy, dashboard);
});
it('maintains the loading state when a metric fails', () => {
expect(stateCopy.showEmptyState).toBe(true);
mutations[types.RECEIVE_METRIC_RESULT_FAILURE](stateCopy, {
metricId,
error: 'an error',
});
expect(stateCopy.showEmptyState).toBe(true);
});
it('stores a timeout error in a metric', () => {
mutations[types.RECEIVE_METRIC_RESULT_FAILURE](stateCopy, {
......
......@@ -265,9 +265,11 @@ RSpec.describe Clusters::ClusterPresenter do
is_expected.to include('clusters-path': clusterable_presenter.index_path,
'dashboard-endpoint': clusterable_presenter.metrics_dashboard_path(cluster),
'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster-ultimate'),
'add-dashboard-documentation-path': help_page_path('user/project/integrations/prometheus.md', anchor: 'adding-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': match_asset_path('/assets/illustrations/monitoring/loading.svg'),
'empty-no-data-svg-path': match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
'empty-no-data-small-svg-path': match_asset_path('illustrations/chart-empty-state-small.svg'),
'empty-unable-to-connect-svg-path': match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
'settings-path': '',
'project-path': '',
......
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