Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pipeline_editor')
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_form_spec.js8
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js4
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js37
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js150
-rw-r--r--spec/frontend/pipeline_editor/components/header/validation_segment_spec.js21
-rw-r--r--spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js79
-rw-r--r--spec/frontend/pipeline_editor/graphql/resolvers_spec.js18
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js16
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js118
9 files changed, 410 insertions, 41 deletions
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
index 5dae77a4626..8040c9d701c 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
@@ -12,7 +12,7 @@ describe('Pipeline Editor | Commit Form', () => {
wrapper = mountFn(CommitForm, {
propsData: {
defaultMessage: mockCommitMessage,
- defaultBranch: mockDefaultBranch,
+ currentBranch: mockDefaultBranch,
...props,
},
@@ -41,7 +41,7 @@ describe('Pipeline Editor | Commit Form', () => {
expect(findCommitTextarea().attributes('value')).toBe(mockCommitMessage);
});
- it('shows a default branch', () => {
+ it('shows current branch', () => {
expect(findBranchInput().attributes('value')).toBe(mockDefaultBranch);
});
@@ -66,7 +66,7 @@ describe('Pipeline Editor | Commit Form', () => {
expect(wrapper.emitted('submit')[0]).toEqual([
{
message: mockCommitMessage,
- branch: mockDefaultBranch,
+ targetBranch: mockDefaultBranch,
openMergeRequest: false,
},
]);
@@ -101,7 +101,7 @@ describe('Pipeline Editor | Commit Form', () => {
expect(wrapper.emitted('submit')[0]).toEqual([
{
message: anotherMessage,
- branch: anotherBranch,
+ targetBranch: anotherBranch,
openMergeRequest: true,
},
]);
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
index b87ff6ec0de..aa62144736c 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -35,7 +35,6 @@ const mockVariables = {
const mockProvide = {
ciConfigPath: mockCiConfigPath,
- defaultBranch: mockDefaultBranch,
projectFullPath: mockProjectFullPath,
newMergeRequestPath: mockNewMergeRequestPath,
};
@@ -64,6 +63,7 @@ describe('Pipeline Editor | Commit section', () => {
data() {
return {
commitSha: mockCommitSha,
+ currentBranch: mockDefaultBranch,
};
},
mocks: {
@@ -116,7 +116,7 @@ describe('Pipeline Editor | Commit section', () => {
await submitCommit();
});
- it('calls the mutation with the default branch', () => {
+ it('calls the mutation with the current branch', () => {
expect(mockMutate).toHaveBeenCalledTimes(1);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
index df15a6c8e7f..ef8ca574e59 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
@@ -1,21 +1,33 @@
import { shallowMount } from '@vue/test-utils';
import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_editor_header.vue';
+import PipelineStatus from '~/pipeline_editor/components/header/pipeline_status.vue';
import ValidationSegment from '~/pipeline_editor/components/header/validation_segment.vue';
-import { mockLintResponse } from '../../mock_data';
+import { mockCiYml, mockLintResponse } from '../../mock_data';
describe('Pipeline editor header', () => {
let wrapper;
+ const mockProvide = {
+ glFeatures: {
+ pipelineStatusForPipelineEditor: true,
+ },
+ };
- const createComponent = () => {
+ const createComponent = ({ provide = {} } = {}) => {
wrapper = shallowMount(PipelineEditorHeader, {
- props: {
+ provide: {
+ ...mockProvide,
+ ...provide,
+ },
+ propsData: {
ciConfigData: mockLintResponse,
+ ciFileContent: mockCiYml,
isCiConfigDataLoading: false,
},
});
};
+ const findPipelineStatus = () => wrapper.findComponent(PipelineStatus);
const findValidationSegment = () => wrapper.findComponent(ValidationSegment);
afterEach(() => {
@@ -27,8 +39,27 @@ describe('Pipeline editor header', () => {
beforeEach(() => {
createComponent();
});
+
+ it('renders the pipeline status', () => {
+ expect(findPipelineStatus().exists()).toBe(true);
+ });
+
it('renders the validation segment', () => {
expect(findValidationSegment().exists()).toBe(true);
});
});
+
+ describe('with pipeline status feature flag off', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures: { pipelineStatusForPipelineEditor: false },
+ },
+ });
+ });
+
+ it('does not render the pipeline status', () => {
+ expect(findPipelineStatus().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
new file mode 100644
index 00000000000..de6e112866b
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
@@ -0,0 +1,150 @@
+import { GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import PipelineStatus, { i18n } from '~/pipeline_editor/components/header/pipeline_status.vue';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+const mockProvide = {
+ projectFullPath: mockProjectFullPath,
+};
+
+describe('Pipeline Status', () => {
+ let wrapper;
+ let mockApollo;
+ let mockPipelineQuery;
+
+ const createComponent = ({ hasPipeline = true, isQueryLoading = false }) => {
+ const pipeline = hasPipeline
+ ? { loading: isQueryLoading, ...mockProjectPipeline.pipeline }
+ : { loading: isQueryLoading };
+
+ wrapper = shallowMount(PipelineStatus, {
+ provide: mockProvide,
+ stubs: { GlLink, GlSprintf },
+ data: () => (hasPipeline ? { pipeline } : {}),
+ mocks: {
+ $apollo: {
+ queries: {
+ pipeline,
+ },
+ },
+ },
+ });
+ };
+
+ const createComponentWithApollo = () => {
+ const resolvers = {
+ Query: {
+ project: mockPipelineQuery,
+ },
+ };
+ mockApollo = createMockApollo([], resolvers);
+
+ wrapper = shallowMount(PipelineStatus, {
+ localVue,
+ apolloProvider: mockApollo,
+ provide: mockProvide,
+ stubs: { GlLink, GlSprintf },
+ data() {
+ return {
+ commitSha: mockCommitSha,
+ };
+ },
+ });
+ };
+
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findCiIcon = () => wrapper.findComponent(CiIcon);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findPipelineId = () => wrapper.find('[data-testid="pipeline-id"]');
+ const findPipelineCommit = () => wrapper.find('[data-testid="pipeline-commit"]');
+ const findPipelineErrorMsg = () => wrapper.find('[data-testid="pipeline-error-msg"]');
+ const findPipelineLoadingMsg = () => wrapper.find('[data-testid="pipeline-loading-msg"]');
+
+ beforeEach(() => {
+ mockPipelineQuery = jest.fn();
+ });
+
+ afterEach(() => {
+ mockPipelineQuery.mockReset();
+
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('while querying', () => {
+ it('renders loading icon', () => {
+ createComponent({ isQueryLoading: true, hasPipeline: false });
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findPipelineLoadingMsg().text()).toBe(i18n.fetchLoading);
+ });
+
+ it('does not render loading icon if pipeline data is already set', () => {
+ createComponent({ isQueryLoading: true });
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('when querying data', () => {
+ describe('when data is set', () => {
+ beforeEach(async () => {
+ mockPipelineQuery.mockResolvedValue(mockProjectPipeline);
+
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('query is called with correct variables', async () => {
+ expect(mockPipelineQuery).toHaveBeenCalledTimes(1);
+ expect(mockPipelineQuery).toHaveBeenCalledWith(
+ expect.anything(),
+ {
+ fullPath: mockProjectFullPath,
+ },
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('does not render error', () => {
+ expect(findIcon().exists()).toBe(false);
+ });
+
+ it('renders pipeline data', () => {
+ const { id } = mockProjectPipeline.pipeline;
+
+ expect(findCiIcon().exists()).toBe(true);
+ expect(findPipelineId().text()).toBe(`#${id.match(/\d+/g)[0]}`);
+ expect(findPipelineCommit().text()).toBe(mockCommitSha);
+ });
+ });
+
+ describe('when data cannot be fetched', () => {
+ beforeEach(async () => {
+ mockPipelineQuery.mockRejectedValue(new Error());
+
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('renders error', () => {
+ expect(findIcon().attributes('name')).toBe('warning-solid');
+ expect(findPipelineErrorMsg().text()).toBe(i18n.fetchError);
+ });
+
+ it('does not render pipeline data', () => {
+ expect(findCiIcon().exists()).toBe(false);
+ expect(findPipelineId().exists()).toBe(false);
+ expect(findPipelineCommit().exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
index cf1d89e1d7c..274c2d1b8da 100644
--- a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
@@ -7,9 +7,9 @@ import ValidationSegment, {
i18n,
} from '~/pipeline_editor/components/header/validation_segment.vue';
import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { mockYmlHelpPagePath, mergeUnwrappedCiConfig } from '../../mock_data';
+import { mockYmlHelpPagePath, mergeUnwrappedCiConfig, mockCiYml } from '../../mock_data';
-describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
+describe('Validation segment component', () => {
let wrapper;
const createComponent = (props = {}) => {
@@ -20,6 +20,7 @@ describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
},
propsData: {
ciConfig: mergeUnwrappedCiConfig(),
+ ciFileContent: mockCiYml,
loading: false,
...props,
},
@@ -42,6 +43,20 @@ describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
expect(wrapper.text()).toBe(i18n.loading);
});
+ describe('when config is empty', () => {
+ beforeEach(() => {
+ createComponent({ ciFileContent: '' });
+ });
+
+ it('has check icon', () => {
+ expect(findIcon().props('name')).toBe('check');
+ });
+
+ it('shows a message for empty state', () => {
+ expect(findValidationMsg().text()).toBe(i18n.empty);
+ });
+ });
+
describe('when config is valid', () => {
beforeEach(() => {
createComponent({});
@@ -61,7 +76,7 @@ describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
});
});
- describe('when config is not valid', () => {
+ describe('when config is invalid', () => {
beforeEach(() => {
createComponent({
ciConfig: mergeUnwrappedCiConfig({
diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
new file mode 100644
index 00000000000..b444d9dcfea
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
@@ -0,0 +1,79 @@
+import { GlButton, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
+
+describe('Pipeline editor empty state', () => {
+ let wrapper;
+ const defaultProvide = {
+ glFeatures: {
+ pipelineEditorEmptyStateAction: false,
+ },
+ emptyStateIllustrationPath: 'my/svg/path',
+ };
+
+ const createComponent = ({ provide } = {}) => {
+ wrapper = shallowMount(PipelineEditorEmptyState, {
+ provide: { ...defaultProvide, ...provide },
+ });
+ };
+
+ const findSvgImage = () => wrapper.find('img');
+ const findTitle = () => wrapper.find('h1');
+ const findConfirmButton = () => wrapper.findComponent(GlButton);
+ const findDescription = () => wrapper.findComponent(GlSprintf);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders an svg image', () => {
+ expect(findSvgImage().exists()).toBe(true);
+ });
+
+ it('renders a title', () => {
+ expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toBe(wrapper.vm.$options.i18n.title);
+ });
+
+ it('renders a description', () => {
+ expect(findDescription().exists()).toBe(true);
+ expect(findDescription().html()).toContain(wrapper.vm.$options.i18n.body);
+ });
+
+ describe('with feature flag off', () => {
+ it('does not renders a CTA button', () => {
+ expect(findConfirmButton().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('with feature flag on', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures: {
+ pipelineEditorEmptyStateAction: true,
+ },
+ },
+ });
+ });
+
+ it('renders a CTA button', () => {
+ expect(findConfirmButton().exists()).toBe(true);
+ expect(findConfirmButton().text()).toBe(wrapper.vm.$options.i18n.btnText);
+ });
+
+ it('emits an event when clicking on the CTA', async () => {
+ const expectedEvent = 'createEmptyConfigFile';
+ expect(wrapper.emitted(expectedEvent)).toBeUndefined();
+
+ await findConfirmButton().vm.$emit('click');
+ expect(wrapper.emitted(expectedEvent)).toHaveLength(1);
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
index d39c0d80296..196a4133eea 100644
--- a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
+++ b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
@@ -46,6 +46,24 @@ describe('~/pipeline_editor/graphql/resolvers', () => {
await expect(result.rawData).resolves.toBe(mockCiYml);
});
});
+
+ describe('pipeline', () => {
+ it('resolves pipeline data with type names', async () => {
+ const result = await resolvers.Query.project(null);
+
+ // eslint-disable-next-line no-underscore-dangle
+ expect(result.__typename).toBe('Project');
+ });
+
+ it('resolves pipeline data with necessary data', async () => {
+ const result = await resolvers.Query.project(null);
+ const pipelineKeys = Object.keys(result.pipeline);
+ const statusKeys = Object.keys(result.pipeline.detailedStatus);
+
+ expect(pipelineKeys).toContain('id', 'commitPath', 'detailedStatus', 'shortSha');
+ expect(statusKeys).toContain('detailsPath', 'text');
+ });
+ });
});
describe('Mutation', () => {
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index 8e248c11b87..16d5ba0e714 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -138,6 +138,22 @@ export const mergeUnwrappedCiConfig = (mergedConfig) => {
};
};
+export const mockProjectPipeline = {
+ pipeline: {
+ commitPath: '/-/commit/aabbccdd',
+ id: 'gid://gitlab/Ci::Pipeline/118',
+ iid: '28',
+ shortSha: mockCommitSha,
+ status: 'SUCCESS',
+ detailedStatus: {
+ detailsPath: '/root/sample-ci-project/-/pipelines/118"',
+ group: 'success',
+ icon: 'status_success',
+ text: 'passed',
+ },
+ },
+};
+
export const mockLintResponse = {
valid: true,
mergedYaml: mockCiYml,
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' });
+ });
});
});
});