Commit 7a02b40c authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Added additional test to the base_spec

Checks the various rendering states for the base
vue component for project VSA
parent 555068a0
...@@ -64,18 +64,13 @@ export default { ...@@ -64,18 +64,13 @@ export default {
return selectedStageEvents.length && !isLoadingStage && !isEmptyStage; return selectedStageEvents.length && !isLoadingStage && !isEmptyStage;
}, },
displayNotEnoughData() { displayNotEnoughData() {
const { selectedStage, isEmptyStage, isLoadingStage } = this; return this.selectedStageReady && this.isEmptyStage;
return selectedStage && isEmptyStage && !isLoadingStage;
}, },
displayNoAccess() { displayNoAccess() {
const { selectedStage } = this; return this.selectedStageReady && !this.selectedStage.isUserAllowed;
return selectedStage && !selectedStage.isUserAllowed;
}, },
selectedStageReady() { selectedStageReady() {
return !this.hasNoAccessError && this.selectedStage; return !this.isLoadingStage && this.selectedStage;
},
shouldDisplayPathNavigation() {
return this.selectedStage;
}, },
}, },
methods: { methods: {
...@@ -116,7 +111,7 @@ export default { ...@@ -116,7 +111,7 @@ export default {
<template> <template>
<div class="cycle-analytics"> <div class="cycle-analytics">
<path-navigation <path-navigation
v-if="shouldDisplayPathNavigation" v-if="selectedStageReady"
class="js-path-navigation gl-w-full gl-pb-2" class="js-path-navigation gl-w-full gl-pb-2"
:loading="isLoading" :loading="isLoading"
:stages="pathNavigationData" :stages="pathNavigationData"
...@@ -198,29 +193,29 @@ export default { ...@@ -198,29 +193,29 @@ export default {
</div> </div>
<div class="stage-panel-body"> <div class="stage-panel-body">
<section class="stage-events gl-overflow-auto gl-w-full"> <section class="stage-events gl-overflow-auto gl-w-full">
<gl-loading-icon v-show="isLoadingStage" size="lg" /> <gl-loading-icon v-if="isLoadingStage" size="lg" />
<template v-if="displayNoAccess"> <template v-else>
<gl-empty-state <gl-empty-state
v-if="displayNoAccess"
class="js-empty-state" class="js-empty-state"
:title="__('You need permission.')" :title="__('You need permission.')"
:svg-path="noAccessSvgPath" :svg-path="noAccessSvgPath"
:description="__('Want to see the data? Please ask an administrator for access.')" :description="__('Want to see the data? Please ask an administrator for access.')"
/> />
</template>
<template v-else> <template v-else>
<template v-if="displayNotEnoughData">
<gl-empty-state <gl-empty-state
v-if="displayNotEnoughData"
class="js-empty-state" class="js-empty-state"
:description="selectedStage.emptyStageText" :description="selectedStage.emptyStageText"
:svg-path="noDataSvgPath" :svg-path="noDataSvgPath"
:title="__('We don\'t have enough data to show this stage.')" :title="__('We don\'t have enough data to show this stage.')"
/> />
</template>
<template v-if="displayStageEvents">
<component <component
:is="selectedStage.component" :is="selectedStage.component"
v-if="displayStageEvents"
:stage="selectedStage" :stage="selectedStage"
:items="selectedStageEvents" :items="selectedStageEvents"
data-testid="stage-table-events"
/> />
</template> </template>
</template> </template>
......
...@@ -10,13 +10,13 @@ import Metrics from 'ee/analytics/cycle_analytics/components/metrics.vue'; ...@@ -10,13 +10,13 @@ import Metrics from 'ee/analytics/cycle_analytics/components/metrics.vue';
import StageTable from 'ee/analytics/cycle_analytics/components/stage_table.vue'; import StageTable from 'ee/analytics/cycle_analytics/components/stage_table.vue';
import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue'; import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue';
import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue'; import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue';
import { OVERVIEW_STAGE_ID } from 'ee/analytics/cycle_analytics/constants';
import createStore from 'ee/analytics/cycle_analytics/store'; import createStore from 'ee/analytics/cycle_analytics/store';
import Daterange from 'ee/analytics/shared/components/daterange.vue'; import Daterange from 'ee/analytics/shared/components/daterange.vue';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue'; import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
import { toYmd } from 'ee/analytics/shared/utils'; import { toYmd } from 'ee/analytics/shared/utils';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue'; import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import { OVERVIEW_STAGE_ID } from '~/cycle_analytics/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import * as commonUtils from '~/lib/utils/common_utils'; import * as commonUtils from '~/lib/utils/common_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
......
import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Component from '~/cycle_analytics/components/base.vue'; import BaseComponent from '~/cycle_analytics/components/base.vue';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue'; import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import createStore from '~/cycle_analytics/store'; import initState from '~/cycle_analytics/store/state';
import { selectedStage, convertedEvents as selectedStageEvents } from './mock_data';
const noDataSvgPath = 'path/to/no/data'; const noDataSvgPath = 'path/to/no/data';
const noAccessSvgPath = 'path/to/no/access'; const noAccessSvgPath = 'path/to/no/access';
...@@ -13,11 +15,22 @@ Vue.use(Vuex); ...@@ -13,11 +15,22 @@ Vue.use(Vuex);
let wrapper; let wrapper;
function createComponent() { function createStore({ initialState = {} }) {
const store = createStore(); return new Vuex.Store({
state: {
...initState(),
...initialState,
},
getters: {
pathNavigationData: () => [],
},
});
}
function createComponent({ initialState } = {}) {
return extendedWrapper( return extendedWrapper(
shallowMount(Component, { shallowMount(BaseComponent, {
store, store: createStore({ initialState }),
propsData: { propsData: {
noDataSvgPath, noDataSvgPath,
noAccessSvgPath, noAccessSvgPath,
...@@ -26,13 +39,24 @@ function createComponent() { ...@@ -26,13 +39,24 @@ function createComponent() {
); );
} }
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findPathNavigation = () => wrapper.findComponent(PathNavigation); const findPathNavigation = () => wrapper.findComponent(PathNavigation);
const findOverviewMetrics = () => wrapper.findByTestId('vsa-stage-overview-metrics'); const findOverviewMetrics = () => wrapper.findByTestId('vsa-stage-overview-metrics');
const findStageTable = () => wrapper.findByTestId('vsa-stage-table'); const findStageTable = () => wrapper.findByTestId('vsa-stage-table');
const findEmptyStage = () => wrapper.findComponent(GlEmptyState);
const findStageEvents = () => wrapper.findByTestId('stage-table-events');
describe('Value stream analytics component', () => { describe('Value stream analytics component', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); wrapper = createComponent({
initialState: {
isLoading: false,
isLoadingStage: false,
isEmptyStage: false,
selectedStageEvents,
selectedStage,
},
});
}); });
afterEach(() => { afterEach(() => {
...@@ -51,4 +75,104 @@ describe('Value stream analytics component', () => { ...@@ -51,4 +75,104 @@ describe('Value stream analytics component', () => {
it('renders the stage table', () => { it('renders the stage table', () => {
expect(findStageTable().exists()).toBe(true); expect(findStageTable().exists()).toBe(true);
}); });
it('renders the stage table events', () => {
expect(findEmptyStage().exists()).toBe(false);
expect(findStageEvents().exists()).toBe(true);
});
it('does not render the loading icon', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
describe('isLoading = true', () => {
beforeEach(() => {
wrapper = createComponent({
initialState: { isLoading: true },
});
});
it('renders the path navigation component with prop `loading` set to true', () => {
expect(findPathNavigation().exists()).toBe(true);
expect(findPathNavigation().props('loading')).toBe(true);
});
it('does not render the overview metrics', () => {
expect(findOverviewMetrics().exists()).toBe(false);
});
it('does not render the stage table', () => {
expect(findStageTable().exists()).toBe(false);
});
it('renders the loading icon', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
describe('isLoadingStage = true', () => {
beforeEach(() => {
wrapper = createComponent({
initialState: { isLoadingStage: true },
});
});
it('renders the stage table with a loading icon', () => {
const tableWrapper = findStageTable();
expect(tableWrapper.exists()).toBe(true);
expect(tableWrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
describe('isEmptyStage = true', () => {
beforeEach(() => {
wrapper = createComponent({
initialState: { selectedStage, isEmptyStage: true },
});
});
it('renders the empty stage with not enough data', () => {
const es = findEmptyStage();
expect(es.exists()).toBe(true);
expect(es.props('title')).toBe("We don't have enough data to show this stage.");
});
});
describe('without enough permissions', () => {
beforeEach(() => {
wrapper = createComponent({
initialState: { selectedStage: { ...selectedStage, isUserAllowed: false } },
});
});
it('renders the empty stage', () => {
const es = findEmptyStage();
expect(es.exists()).toBe(true);
expect(es.props('title')).toBe('You need permission.');
});
});
describe('without a selected stage', () => {
beforeEach(() => {
wrapper = createComponent({
initialState: { selectedStage: null, isEmptyStage: true },
});
});
it('renders the stage table', () => {
expect(findStageTable().exists()).toBe(true);
});
it('does not render the path navigation component', () => {
expect(findPathNavigation().exists()).toBe(false);
});
it('does not render the stage table events', () => {
expect(findStageEvents().exists()).toBe(false);
});
it('does not render the loading icon', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
});
}); });
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