summaryrefslogtreecommitdiff
path: root/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pipeline_editor/pipeline_editor_app_spec.js')
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js118
1 files changed, 89 insertions, 29 deletions
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index 46d0452f437..887d296222f 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -7,6 +7,8 @@ import httpStatusCodes from '~/lib/utils/http_status';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
+import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
+import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
import { COMMIT_SUCCESS, COMMIT_FAILURE, LOAD_FAILURE_UNKNOWN } from '~/pipeline_editor/constants';
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
@@ -29,6 +31,9 @@ const MockEditorLite = {
const mockProvide = {
ciConfigPath: mockCiConfigPath,
defaultBranch: mockDefaultBranch,
+ glFeatures: {
+ pipelineEditorEmptyStateAction: false,
+ },
projectFullPath: mockProjectFullPath,
};
@@ -39,14 +44,17 @@ describe('Pipeline editor app component', () => {
let mockBlobContentData;
let mockCiConfigData;
- const createComponent = ({ blobLoading = false, options = {} } = {}) => {
+ const createComponent = ({ blobLoading = false, options = {}, provide = {} } = {}) => {
wrapper = shallowMount(PipelineEditorApp, {
- provide: mockProvide,
+ provide: { ...mockProvide, ...provide },
stubs: {
GlTabs,
GlButton,
CommitForm,
+ PipelineEditorHome,
+ PipelineEditorTabs,
EditorLite: MockEditorLite,
+ PipelineEditorEmptyState,
},
mocks: {
$apollo: {
@@ -64,7 +72,7 @@ describe('Pipeline editor app component', () => {
});
};
- const createComponentWithApollo = ({ props = {} } = {}) => {
+ const createComponentWithApollo = ({ props = {}, provide = {} } = {}) => {
const handlers = [[getCiConfigData, mockCiConfigData]];
const resolvers = {
Query: {
@@ -85,13 +93,16 @@ describe('Pipeline editor app component', () => {
apolloProvider: mockApollo,
};
- createComponent({ props, options });
+ createComponent({ props, provide, options });
};
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAlert = () => wrapper.findComponent(GlAlert);
const findEditorHome = () => wrapper.findComponent(PipelineEditorHome);
const findTextEditor = () => wrapper.findComponent(TextEditor);
+ const findEmptyState = () => wrapper.findComponent(PipelineEditorEmptyState);
+ const findEmptyStateButton = () =>
+ wrapper.findComponent(PipelineEditorEmptyState).findComponent(GlButton);
beforeEach(() => {
mockBlobContentData = jest.fn();
@@ -103,7 +114,6 @@ describe('Pipeline editor app component', () => {
mockCiConfigData.mockReset();
wrapper.destroy();
- wrapper = null;
});
it('displays a loading icon if the blob query is loading', () => {
@@ -146,45 +156,79 @@ describe('Pipeline editor app component', () => {
});
});
- describe('when no file exists', () => {
- const noFileAlertMsg =
- 'There is no .gitlab-ci.yml file in this repository, please add one and visit the Pipeline Editor again.';
+ describe('when no CI config file exists', () => {
+ describe('in a project without a repository', () => {
+ it('shows an empty state and does not show editor home component', async () => {
+ mockBlobContentData.mockRejectedValueOnce({
+ response: {
+ status: httpStatusCodes.BAD_REQUEST,
+ },
+ });
+ createComponentWithApollo();
- it('shows a 404 error message and does not show editor home component', async () => {
- mockBlobContentData.mockRejectedValueOnce({
- response: {
- status: httpStatusCodes.NOT_FOUND,
- },
+ await waitForPromises();
+
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findAlert().exists()).toBe(false);
+ expect(findEditorHome().exists()).toBe(false);
});
- createComponentWithApollo();
+ });
- await waitForPromises();
+ describe('in a project with a repository', () => {
+ it('shows an empty state and does not show editor home component', async () => {
+ mockBlobContentData.mockRejectedValueOnce({
+ response: {
+ status: httpStatusCodes.NOT_FOUND,
+ },
+ });
+ createComponentWithApollo();
- expect(findAlert().text()).toBe(noFileAlertMsg);
- expect(findEditorHome().exists()).toBe(false);
+ await waitForPromises();
+
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findAlert().exists()).toBe(false);
+ expect(findEditorHome().exists()).toBe(false);
+ });
+ });
+
+ describe('because of a fetching error', () => {
+ it('shows a unkown error message', async () => {
+ mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
+ createComponentWithApollo();
+ await waitForPromises();
+
+ expect(findEmptyState().exists()).toBe(false);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[LOAD_FAILURE_UNKNOWN]);
+ expect(findEditorHome().exists()).toBe(true);
+ });
});
+ });
- it('shows a 400 error message and does not show editor home component', async () => {
+ describe('when landing on the empty state with feature flag on', () => {
+ it('user can click on CTA button and see an empty editor', async () => {
mockBlobContentData.mockRejectedValueOnce({
response: {
- status: httpStatusCodes.BAD_REQUEST,
+ status: httpStatusCodes.NOT_FOUND,
+ },
+ });
+
+ createComponentWithApollo({
+ provide: {
+ glFeatures: {
+ pipelineEditorEmptyStateAction: true,
+ },
},
});
- createComponentWithApollo();
await waitForPromises();
- expect(findAlert().text()).toBe(noFileAlertMsg);
- expect(findEditorHome().exists()).toBe(false);
- });
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findTextEditor().exists()).toBe(false);
- it('shows a unkown error message', async () => {
- mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
- createComponentWithApollo();
- await waitForPromises();
+ await findEmptyStateButton().vm.$emit('click');
- expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[LOAD_FAILURE_UNKNOWN]);
- expect(findEditorHome().exists()).toBe(true);
+ expect(findEmptyState().exists()).toBe(false);
+ expect(findTextEditor().exists()).toBe(true);
});
});
@@ -193,6 +237,7 @@ describe('Pipeline editor app component', () => {
describe('and the commit mutation succeeds', () => {
beforeEach(() => {
+ window.scrollTo = jest.fn();
createComponent();
findEditorHome().vm.$emit('commit', { type: COMMIT_SUCCESS });
@@ -201,11 +246,16 @@ describe('Pipeline editor app component', () => {
it('shows a confirmation message', () => {
expect(findAlert().text()).toBe(wrapper.vm.$options.successTexts[COMMIT_SUCCESS]);
});
+
+ it('scrolls to the top of the page to bring attention to the confirmation message', () => {
+ expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
+ });
});
describe('and the commit mutation fails', () => {
const commitFailedReasons = ['Commit failed'];
beforeEach(() => {
+ window.scrollTo = jest.fn();
createComponent();
findEditorHome().vm.$emit('showError', {
@@ -219,11 +269,17 @@ describe('Pipeline editor app component', () => {
`${updateFailureMessage} ${commitFailedReasons[0]}`,
);
});
+
+ it('scrolls to the top of the page to bring attention to the error message', () => {
+ expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
+ });
});
+
describe('when an unknown error occurs', () => {
const unknownReasons = ['Commit failed'];
beforeEach(() => {
+ window.scrollTo = jest.fn();
createComponent();
findEditorHome().vm.$emit('showError', {
@@ -237,6 +293,10 @@ describe('Pipeline editor app component', () => {
`${updateFailureMessage} ${unknownReasons[0]}`,
);
});
+
+ it('scrolls to the top of the page to bring attention to the error message', () => {
+ expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
+ });
});
});
});