Commit f5cc2c92 authored by Miguel Rincon's avatar Miguel Rincon

Merge branch 'ps-fix-ide-pipelines-empty-state' into 'master'

Fix empty state of IDE pipelines tab

See merge request gitlab-org/gitlab!74916
parents 297e5de4 a42e3020
<script>
import { GlEmptyState } from '@gitlab/ui';
import { mapState } from 'vuex';
import { s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
export default {
components: {
GlEmptyState,
},
computed: {
...mapState(['pipelinesEmptyStateSvgPath']),
ciHelpPagePath() {
return helpPagePath('ci/quick_start/index.md');
},
},
i18n: {
title: s__('Pipelines|Build with confidence'),
description: s__(`Pipelines|GitLab CI/CD can automatically build,
test, and deploy your code. Let GitLab take care of time
consuming tasks, so you can spend more time creating.`),
primaryButtonText: s__('Pipelines|Get started with GitLab CI/CD'),
},
};
</script>
<template>
<gl-empty-state
:title="$options.i18n.title"
:svg-path="pipelinesEmptyStateSvgPath"
:description="$options.i18n.description"
:primary-button-text="$options.i18n.primaryButtonText"
:primary-button-link="ciHelpPagePath"
/>
</template>
...@@ -11,10 +11,17 @@ import { ...@@ -11,10 +11,17 @@ import {
import { escape } from 'lodash'; import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import IDEServices from '~/ide/services'; import IDEServices from '~/ide/services';
import { sprintf, __ } from '../../../locale'; import { sprintf, __ } from '~/locale';
import EmptyState from '../../../pipelines/components/pipelines_list/empty_state.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import JobsList from '../jobs/list.vue'; import JobsList from '../jobs/list.vue';
import EmptyState from './empty_state.vue';
const CLASSES_FLEX_VERTICAL_CENTER = [
'gl-h-full',
'gl-display-flex',
'gl-flex-direction-column',
'gl-justify-content-center',
];
export default { export default {
components: { components: {
...@@ -32,7 +39,6 @@ export default { ...@@ -32,7 +39,6 @@ export default {
SafeHtml, SafeHtml,
}, },
computed: { computed: {
...mapState(['pipelinesEmptyStateSvgPath']),
...mapGetters(['currentProject']), ...mapGetters(['currentProject']),
...mapGetters('pipelines', ['jobsCount', 'failedJobsCount', 'failedStages', 'pipelineFailed']), ...mapGetters('pipelines', ['jobsCount', 'failedJobsCount', 'failedStages', 'pipelineFailed']),
...mapState('pipelines', [ ...mapState('pipelines', [
...@@ -63,12 +69,15 @@ export default { ...@@ -63,12 +69,15 @@ export default {
methods: { methods: {
...mapActions('pipelines', ['fetchLatestPipeline']), ...mapActions('pipelines', ['fetchLatestPipeline']),
}, },
CLASSES_FLEX_VERTICAL_CENTER,
}; };
</script> </script>
<template> <template>
<div class="ide-pipeline"> <div class="ide-pipeline">
<gl-loading-icon v-if="showLoadingIcon" size="lg" class="gl-mt-3" /> <div v-if="showLoadingIcon" :class="$options.CLASSES_FLEX_VERTICAL_CENTER">
<gl-loading-icon size="lg" />
</div>
<template v-else-if="hasLoadedPipeline"> <template v-else-if="hasLoadedPipeline">
<header v-if="latestPipeline" class="ide-tree-header ide-pipeline-header"> <header v-if="latestPipeline" class="ide-tree-header ide-pipeline-header">
<ci-icon :status="latestPipeline.details.status" :size="24" class="d-flex" /> <ci-icon :status="latestPipeline.details.status" :size="24" class="d-flex" />
...@@ -83,12 +92,9 @@ export default { ...@@ -83,12 +92,9 @@ export default {
</a> </a>
</span> </span>
</header> </header>
<empty-state <div v-if="!latestPipeline" :class="$options.CLASSES_FLEX_VERTICAL_CENTER">
v-if="!latestPipeline" <empty-state />
:empty-state-svg-path="pipelinesEmptyStateSvgPath" </div>
:can-set-ci="true"
class="gl-p-5"
/>
<gl-alert <gl-alert
v-else-if="latestPipeline.yamlError" v-else-if="latestPipeline.yamlError"
variant="danger" variant="danger"
......
...@@ -6,10 +6,10 @@ exports[`IDE pipelines list when loaded renders empty state when no latestPipeli ...@@ -6,10 +6,10 @@ exports[`IDE pipelines list when loaded renders empty state when no latestPipeli
> >
<!----> <!---->
<empty-state-stub <div
cansetci="true" class="gl-h-full gl-display-flex gl-flex-direction-column gl-justify-content-center"
class="gl-p-5" >
emptystatesvgpath="http://test.host" <empty-state-stub />
/> </div>
</div> </div>
`; `;
import { GlEmptyState } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import EmptyState from '~/ide/components/pipelines/empty_state.vue';
import { createStore } from '~/ide/stores';
const TEST_PIPELINES_EMPTY_STATE_SVG_PATH = 'illustrations/test/pipelines.svg';
describe('~/ide/components/pipelines/empty_state.vue', () => {
let store;
let wrapper;
const createComponent = () => {
wrapper = shallowMount(EmptyState, {
store,
});
};
beforeEach(() => {
store = createStore();
store.dispatch('setEmptyStateSvgs', {
pipelinesEmptyStateSvgPath: TEST_PIPELINES_EMPTY_STATE_SVG_PATH,
});
});
afterEach(() => {
wrapper.destroy();
});
describe('default', () => {
beforeEach(() => {
createComponent();
});
it('renders empty state', () => {
expect(wrapper.find(GlEmptyState).props()).toMatchObject({
title: EmptyState.i18n.title,
description: EmptyState.i18n.description,
primaryButtonText: EmptyState.i18n.primaryButtonText,
primaryButtonLink: '/help/ci/quick_start/index.md',
svgPath: TEST_PIPELINES_EMPTY_STATE_SVG_PATH,
});
});
});
});
...@@ -2,10 +2,10 @@ import { GlLoadingIcon, GlTab } from '@gitlab/ui'; ...@@ -2,10 +2,10 @@ import { GlLoadingIcon, GlTab } 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 { TEST_HOST } from 'helpers/test_constants';
import { pipelines } from 'jest/ide/mock_data'; import { pipelines } from 'jest/ide/mock_data';
import JobsList from '~/ide/components/jobs/list.vue'; import JobsList from '~/ide/components/jobs/list.vue';
import List from '~/ide/components/pipelines/list.vue'; import List from '~/ide/components/pipelines/list.vue';
import EmptyState from '~/ide/components/pipelines/empty_state.vue';
import IDEServices from '~/ide/services'; import IDEServices from '~/ide/services';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
...@@ -18,9 +18,6 @@ jest.mock('~/ide/services', () => ({ ...@@ -18,9 +18,6 @@ jest.mock('~/ide/services', () => ({
describe('IDE pipelines list', () => { describe('IDE pipelines list', () => {
let wrapper; let wrapper;
const defaultState = {
pipelinesEmptyStateSvgPath: TEST_HOST,
};
const defaultPipelinesState = { const defaultPipelinesState = {
stages: [], stages: [],
failedStages: [], failedStages: [],
...@@ -38,7 +35,6 @@ describe('IDE pipelines list', () => { ...@@ -38,7 +35,6 @@ describe('IDE pipelines list', () => {
currentProject: () => ({ web_url: 'some/url ', path_with_namespace: fakeProjectPath }), currentProject: () => ({ web_url: 'some/url ', path_with_namespace: fakeProjectPath }),
}, },
state: { state: {
...defaultState,
...rootState, ...rootState,
}, },
modules: { modules: {
...@@ -131,6 +127,8 @@ describe('IDE pipelines list', () => { ...@@ -131,6 +127,8 @@ describe('IDE pipelines list', () => {
it('renders empty state when no latestPipeline', () => { it('renders empty state when no latestPipeline', () => {
createComponent({}, { ...defaultPipelinesLoadedState, latestPipeline: null }); createComponent({}, { ...defaultPipelinesLoadedState, latestPipeline: null });
expect(wrapper.find(EmptyState).exists()).toBe(true);
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
......
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