summaryrefslogtreecommitdiff
path: root/spec/frontend/pipeline_wizard/components/commit_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pipeline_wizard/components/commit_spec.js')
-rw-r--r--spec/frontend/pipeline_wizard/components/commit_spec.js282
1 files changed, 282 insertions, 0 deletions
diff --git a/spec/frontend/pipeline_wizard/components/commit_spec.js b/spec/frontend/pipeline_wizard/components/commit_spec.js
new file mode 100644
index 00000000000..6496850b028
--- /dev/null
+++ b/spec/frontend/pipeline_wizard/components/commit_spec.js
@@ -0,0 +1,282 @@
+import { GlButton, GlFormGroup } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { __, s__, sprintf } from '~/locale';
+import { mountExtended } from 'jest/__helpers__/vue_test_utils_helper';
+import CommitStep, { i18n } from '~/pipeline_wizard/components/commit.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import createCommitMutation from '~/pipeline_wizard/queries/create_commit.graphql';
+import getFileMetadataQuery from '~/pipeline_wizard/queries/get_file_meta.graphql';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import flushPromises from 'helpers/flush_promises';
+import {
+ createCommitMutationErrorResult,
+ createCommitMutationResult,
+ fileQueryErrorResult,
+ fileQueryResult,
+ fileQueryEmptyResult,
+} from '../mock/query_responses';
+
+Vue.use(VueApollo);
+
+const COMMIT_MESSAGE_ADD_FILE = s__('PipelineWizardDefaultCommitMessage|Add %{filename}');
+const COMMIT_MESSAGE_UPDATE_FILE = s__('PipelineWizardDefaultCommitMessage|Update %{filename}');
+
+describe('Pipeline Wizard - Commit Page', () => {
+ const createCommitMutationHandler = jest.fn();
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ let wrapper;
+
+ const getMockApollo = (scenario = {}) => {
+ return createMockApollo([
+ [
+ createCommitMutation,
+ createCommitMutationHandler.mockResolvedValue(
+ scenario.commitHasError ? createCommitMutationErrorResult : createCommitMutationResult,
+ ),
+ ],
+ [
+ getFileMetadataQuery,
+ (vars) => {
+ if (scenario.fileResultByRef) return scenario.fileResultByRef[vars.ref];
+ if (scenario.hasError) return fileQueryErrorResult;
+ return scenario.fileExists ? fileQueryResult : fileQueryEmptyResult;
+ },
+ ],
+ ]);
+ };
+ const createComponent = (props = {}, mockApollo = getMockApollo()) => {
+ wrapper = mountExtended(CommitStep, {
+ apolloProvider: mockApollo,
+ propsData: {
+ projectPath: 'some/path',
+ defaultBranch: 'main',
+ filename: 'newFile.yml',
+ ...props,
+ },
+ mocks: { $toast },
+ stubs: {
+ RefSelector: true,
+ GlFormGroup,
+ },
+ });
+ };
+
+ function getButtonWithLabel(label) {
+ return wrapper.findAllComponents(GlButton).filter((n) => n.text().match(label));
+ }
+
+ describe('ui setup', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('shows a commit message input with the correct label', () => {
+ expect(wrapper.findByTestId('commit_message').exists()).toBe(true);
+ expect(wrapper.find('label[for="commit_message"]').text()).toBe(i18n.commitMessageLabel);
+ });
+
+ it('shows a branch selector with the correct label', () => {
+ expect(wrapper.findByTestId('branch').exists()).toBe(true);
+ expect(wrapper.find('label[for="branch"]').text()).toBe(i18n.branchSelectorLabel);
+ });
+
+ it('shows a commit button', () => {
+ expect(getButtonWithLabel(i18n.commitButtonLabel).exists()).toBe(true);
+ });
+
+ it('shows a back button', () => {
+ expect(getButtonWithLabel(__('Back')).exists()).toBe(true);
+ });
+
+ it('does not show a next button', () => {
+ expect(getButtonWithLabel(__('Next')).exists()).toBe(false);
+ });
+ });
+
+ describe('loading the remote file', () => {
+ const projectPath = 'foo/bar';
+ const filename = 'foo.yml';
+
+ it('does not show a load error if call is successful', async () => {
+ createComponent({ projectPath, filename });
+ await flushPromises();
+ expect(wrapper.findByTestId('load-error').exists()).not.toBe(true);
+ });
+
+ it('shows a load error if call returns an unexpected error', async () => {
+ const branch = 'foo';
+ createComponent(
+ { defaultBranch: branch, projectPath, filename },
+ createMockApollo([[getFileMetadataQuery, () => fileQueryErrorResult]]),
+ );
+ await flushPromises();
+ expect(wrapper.findByTestId('load-error').exists()).toBe(true);
+ expect(wrapper.findByTestId('load-error').text()).toBe(i18n.errors.loadError);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+ });
+
+ describe('commit result handling', () => {
+ describe('successful commit', () => {
+ beforeEach(async () => {
+ createComponent();
+ await flushPromises();
+ await getButtonWithLabel(__('Commit')).trigger('click');
+ await flushPromises();
+ });
+
+ it('will not show an error', async () => {
+ expect(wrapper.findByTestId('commit-error').exists()).not.toBe(true);
+ });
+
+ it('will show a toast message', () => {
+ expect($toast.show).toHaveBeenCalledWith(
+ s__('PipelineWizard|The file has been committed.'),
+ );
+ });
+
+ it('emits a done event', () => {
+ expect(wrapper.emitted().done.length).toBe(1);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ jest.clearAllMocks();
+ });
+ });
+
+ describe('failed commit', () => {
+ beforeEach(async () => {
+ createComponent({}, getMockApollo({ commitHasError: true }));
+ await flushPromises();
+ await getButtonWithLabel(__('Commit')).trigger('click');
+ await flushPromises();
+ });
+
+ it('will show an error', async () => {
+ expect(wrapper.findByTestId('commit-error').exists()).toBe(true);
+ expect(wrapper.findByTestId('commit-error').text()).toBe(i18n.errors.commitError);
+ });
+
+ it('will not show a toast message', () => {
+ expect($toast.show).not.toHaveBeenCalledWith(i18n.commitSuccessMessage);
+ });
+
+ it('will not emit a done event', () => {
+ expect(wrapper.emitted().done?.length).toBeFalsy();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ jest.clearAllMocks();
+ });
+ });
+ });
+
+ describe('modelling different input combinations', () => {
+ const projectPath = 'some/path';
+ const defaultBranch = 'foo';
+ const fileContent = 'foo: bar';
+
+ describe.each`
+ filename | fileExistsOnDefaultBranch | fileExistsOnInputtedBranch | fileLoadError | commitMessageInputValue | branchInputValue | expectedCommitBranch | expectedCommitMessage | expectedAction
+ ${'foo.yml'} | ${false} | ${undefined} | ${false} | ${'foo'} | ${undefined} | ${defaultBranch} | ${'foo'} | ${'CREATE'}
+ ${'foo.yml'} | ${true} | ${undefined} | ${false} | ${'foo'} | ${undefined} | ${defaultBranch} | ${'foo'} | ${'UPDATE'}
+ ${'foo.yml'} | ${false} | ${true} | ${false} | ${'foo'} | ${'dev'} | ${'dev'} | ${'foo'} | ${'UPDATE'}
+ ${'foo.yml'} | ${false} | ${undefined} | ${false} | ${null} | ${undefined} | ${defaultBranch} | ${COMMIT_MESSAGE_ADD_FILE} | ${'CREATE'}
+ ${'foo.yml'} | ${true} | ${undefined} | ${false} | ${null} | ${undefined} | ${defaultBranch} | ${COMMIT_MESSAGE_UPDATE_FILE} | ${'UPDATE'}
+ ${'foo.yml'} | ${false} | ${true} | ${false} | ${null} | ${'dev'} | ${'dev'} | ${COMMIT_MESSAGE_UPDATE_FILE} | ${'UPDATE'}
+ `(
+ 'Test with fileExistsOnDefaultBranch=$fileExistsOnDefaultBranch, fileExistsOnInputtedBranch=$fileExistsOnInputtedBranch, commitMessageInputValue=$commitMessageInputValue, branchInputValue=$branchInputValue, commitReturnsError=$commitReturnsError',
+ ({
+ filename,
+ fileExistsOnDefaultBranch,
+ fileExistsOnInputtedBranch,
+ commitMessageInputValue,
+ branchInputValue,
+ expectedCommitBranch,
+ expectedCommitMessage,
+ expectedAction,
+ }) => {
+ let consoleSpy;
+
+ beforeAll(async () => {
+ createComponent(
+ {
+ filename,
+ defaultBranch,
+ projectPath,
+ fileContent,
+ },
+ getMockApollo({
+ fileResultByRef: {
+ [defaultBranch]: fileExistsOnDefaultBranch ? fileQueryResult : fileQueryEmptyResult,
+ [branchInputValue]: fileExistsOnInputtedBranch
+ ? fileQueryResult
+ : fileQueryEmptyResult,
+ },
+ }),
+ );
+
+ await flushPromises();
+
+ consoleSpy = jest.spyOn(console, 'error');
+
+ await wrapper
+ .findByTestId('commit_message')
+ .get('textarea')
+ .setValue(commitMessageInputValue);
+
+ if (branchInputValue) {
+ await wrapper.getComponent(RefSelector).vm.$emit('input', branchInputValue);
+ }
+ await Vue.nextTick();
+
+ await flushPromises();
+ });
+
+ afterAll(() => {
+ wrapper.destroy();
+ });
+
+ it('sets up without error', async () => {
+ expect(consoleSpy).not.toHaveBeenCalled();
+ });
+
+ it('does not show a load error', async () => {
+ expect(wrapper.findByTestId('load-error').exists()).not.toBe(true);
+ });
+
+ it('sends the expected commit mutation', async () => {
+ await getButtonWithLabel(__('Commit')).trigger('click');
+
+ expect(createCommitMutationHandler).toHaveBeenCalledWith({
+ input: {
+ actions: [
+ {
+ action: expectedAction,
+ content: fileContent,
+ filePath: `/${filename}`,
+ },
+ ],
+ branch: expectedCommitBranch,
+ message: sprintf(expectedCommitMessage, { filename }),
+ projectPath,
+ },
+ });
+ });
+ },
+ );
+ });
+});