Commit 6e317521 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch 'branch-switcher-empty-state' into 'master'

Add branch switcher to pipeline editor empty state

See merge request gitlab-org/gitlab!60465
parents 8ece15a6 dbff1e77
<script> <script>
import { GlButton, GlSprintf } from '@gitlab/ui'; import { GlButton, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
components: { components: {
GlButton, GlButton,
GlSprintf, GlSprintf,
PipelineEditorFileNav,
}, },
i18n: { i18n: {
title: __('Optimize your workflow with CI/CD Pipelines'), title: __('Optimize your workflow with CI/CD Pipelines'),
...@@ -22,6 +24,9 @@ export default { ...@@ -22,6 +24,9 @@ export default {
}, },
}, },
computed: { computed: {
showFileNav() {
return this.glFeatures.pipelineEditorBranchSwitcher;
},
showCTAButton() { showCTAButton() {
return this.glFeatures.pipelineEditorEmptyStateAction; return this.glFeatures.pipelineEditorEmptyStateAction;
}, },
...@@ -34,23 +39,28 @@ export default { ...@@ -34,23 +39,28 @@ export default {
}; };
</script> </script>
<template> <template>
<div class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-mt-11"> <div>
<img :src="emptyStateIllustrationPath" /> <div class="gl-mb-5">
<h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1> <pipeline-editor-file-nav v-if="showFileNav" v-on="$listeners" />
<p class="gl-mt-3"> </div>
<gl-sprintf :message="$options.i18n.body"> <div class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-mt-11">
<template #code="{ content }"> <img :src="emptyStateIllustrationPath" />
<code>{{ content }}</code> <h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1>
</template> <p class="gl-mt-3">
</gl-sprintf> <gl-sprintf :message="$options.i18n.body">
</p> <template #code="{ content }">
<gl-button <code>{{ content }}</code>
v-if="showCTAButton" </template>
variant="confirm" </gl-sprintf>
class="gl-mt-3" </p>
@click="createEmptyConfigFile" <gl-button
> v-if="showCTAButton"
{{ $options.i18n.btnText }} variant="confirm"
</gl-button> class="gl-mt-3"
@click="createEmptyConfigFile"
>
{{ $options.i18n.btnText }}
</gl-button>
</div>
</div> </div>
</template> </template>
...@@ -80,6 +80,12 @@ export default { ...@@ -80,6 +80,12 @@ export default {
this.lastCommittedContent = fileContent; this.lastCommittedContent = fileContent;
this.currentCiFileContent = fileContent; this.currentCiFileContent = fileContent;
// make sure to reset the start screen flag during a refetch
// e.g. when switching branches
if (fileContent.length) {
this.showStartScreen = false;
}
}, },
error(error) { error(error) {
this.handleBlobContentError(error); this.handleBlobContentError(error);
...@@ -236,6 +242,7 @@ export default { ...@@ -236,6 +242,7 @@ export default {
<pipeline-editor-empty-state <pipeline-editor-empty-state
v-else-if="showStartScreen" v-else-if="showStartScreen"
@createEmptyConfigFile="setNewEmptyCiConfigFile" @createEmptyConfigFile="setNewEmptyCiConfigFile"
@refetchContent="refetchContent"
/> />
<div v-else> <div v-else>
<pipeline-editor-messages <pipeline-editor-messages
......
import { GlButton, GlSprintf } from '@gitlab/ui'; import { GlButton, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue';
import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue'; import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
describe('Pipeline editor empty state', () => { describe('Pipeline editor empty state', () => {
let wrapper; let wrapper;
const defaultProvide = { const defaultProvide = {
glFeatures: { glFeatures: {
pipelineEditorBranchSwitcher: true,
pipelineEditorEmptyStateAction: false, pipelineEditorEmptyStateAction: false,
}, },
emptyStateIllustrationPath: 'my/svg/path', emptyStateIllustrationPath: 'my/svg/path',
...@@ -17,6 +19,7 @@ describe('Pipeline editor empty state', () => { ...@@ -17,6 +19,7 @@ describe('Pipeline editor empty state', () => {
}); });
}; };
const findFileNav = () => wrapper.findComponent(PipelineEditorFileNav);
const findSvgImage = () => wrapper.find('img'); const findSvgImage = () => wrapper.find('img');
const findTitle = () => wrapper.find('h1'); const findTitle = () => wrapper.find('h1');
const findConfirmButton = () => wrapper.findComponent(GlButton); const findConfirmButton = () => wrapper.findComponent(GlButton);
...@@ -45,6 +48,10 @@ describe('Pipeline editor empty state', () => { ...@@ -45,6 +48,10 @@ describe('Pipeline editor empty state', () => {
expect(findDescription().html()).toContain(wrapper.vm.$options.i18n.body); expect(findDescription().html()).toContain(wrapper.vm.$options.i18n.body);
}); });
it('renders the file nav', () => {
expect(findFileNav().exists()).toBe(true);
});
describe('with feature flag off', () => { describe('with feature flag off', () => {
it('does not renders a CTA button', () => { it('does not renders a CTA button', () => {
expect(findConfirmButton().exists()).toBe(false); expect(findConfirmButton().exists()).toBe(false);
...@@ -75,5 +82,17 @@ describe('Pipeline editor empty state', () => { ...@@ -75,5 +82,17 @@ describe('Pipeline editor empty state', () => {
await findConfirmButton().vm.$emit('click'); await findConfirmButton().vm.$emit('click');
expect(wrapper.emitted(expectedEvent)).toHaveLength(1); expect(wrapper.emitted(expectedEvent)).toHaveLength(1);
}); });
describe('with branch switcher feature flag OFF', () => {
it('does not render the file nav', () => {
createComponent({
provide: {
glFeatures: { pipelineEditorBranchSwitcher: false },
},
});
expect(findFileNav().exists()).toBe(false);
});
});
}); });
}); });
...@@ -301,20 +301,35 @@ describe('Pipeline editor app component', () => { ...@@ -301,20 +301,35 @@ describe('Pipeline editor app component', () => {
}); });
describe('when refetching content', () => { describe('when refetching content', () => {
beforeEach(async () => { it('refetches blob content', async () => {
await createComponentWithApollo(); await createComponentWithApollo();
jest jest
.spyOn(wrapper.vm.$apollo.queries.initialCiFileContent, 'refetch') .spyOn(wrapper.vm.$apollo.queries.initialCiFileContent, 'refetch')
.mockImplementation(jest.fn()); .mockImplementation(jest.fn());
});
it('refetches blob content', async () => {
expect(wrapper.vm.$apollo.queries.initialCiFileContent.refetch).toHaveBeenCalledTimes(0); expect(wrapper.vm.$apollo.queries.initialCiFileContent.refetch).toHaveBeenCalledTimes(0);
await wrapper.vm.refetchContent(); await wrapper.vm.refetchContent();
expect(wrapper.vm.$apollo.queries.initialCiFileContent.refetch).toHaveBeenCalledTimes(1); expect(wrapper.vm.$apollo.queries.initialCiFileContent.refetch).toHaveBeenCalledTimes(1);
}); });
it('hides start screen when refetch fetches CI file', async () => {
mockBlobContentData.mockRejectedValue({
response: {
status: httpStatusCodes.NOT_FOUND,
},
});
await createComponentWithApollo();
expect(findEmptyState().exists()).toBe(true);
expect(findEditorHome().exists()).toBe(false);
mockBlobContentData.mockResolvedValue(mockCiYml);
await wrapper.vm.$apollo.queries.initialCiFileContent.refetch();
expect(findEmptyState().exists()).toBe(false);
expect(findEditorHome().exists()).toBe(true);
});
}); });
}); });
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