Commit 61e9fcf3 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '300689-use-mock-apollo-to-test-commit-section-mutation' into 'master'

Use mock apollo to test commit section mutation

See merge request gitlab-org/gitlab!75267
parents 41fc3257 3621d16d
......@@ -87,7 +87,7 @@ export default {
try {
const {
data: {
commitCreate: { errors },
commitCreate: { errors, commitPipelinePath: pipelineEtag },
},
} = await this.$apollo.mutate({
mutation: commitCIFile,
......@@ -101,14 +101,12 @@ export default {
content: this.ciFileContent,
lastCommitId: this.commitSha,
},
update(_, { data }) {
const pipelineEtag = data?.commitCreate?.commit?.commitPipelinePath;
if (pipelineEtag) {
this.$apollo.mutate({ mutation: updatePipelineEtag, variables: pipelineEtag });
}
},
});
if (pipelineEtag) {
this.updatePipelineEtag(pipelineEtag);
}
if (errors?.length) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: errors });
} else if (openMergeRequest) {
......@@ -139,6 +137,9 @@ export default {
variables: { lastCommitBranch },
});
},
updatePipelineEtag(pipelineEtag) {
this.$apollo.mutate({ mutation: updatePipelineEtag, variables: { pipelineEtag } });
},
},
};
</script>
......
......@@ -19,7 +19,9 @@ mutation commitCIFile(
]
}
) {
__typename
commit {
__typename
sha
}
commitPipelinePath
......
import { nextTick } from 'vue';
import { GlFormInput, GlFormTextarea } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
......@@ -32,7 +33,6 @@ describe('Pipeline Editor | Commit Form', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when the form is displayed', () => {
......@@ -121,7 +121,7 @@ describe('Pipeline Editor | Commit Form', () => {
beforeEach(async () => {
createComponent();
wrapper.setProps({ scrollToCommitForm: true });
await wrapper.vm.$nextTick();
await nextTick();
});
it('scrolls into view', () => {
......
import VueApollo from 'vue-apollo';
import { GlFormTextarea, GlFormInput, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { createLocalVue, mount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { objectToQuery, redirectTo } from '~/lib/utils/url_utility';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
......@@ -10,18 +12,22 @@ import {
COMMIT_SUCCESS,
} from '~/pipeline_editor/constants';
import commitCreate from '~/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql';
import updatePipelineEtag from '~/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql';
import {
mockCiConfigPath,
mockCiYml,
mockCommitCreateResponse,
mockCommitCreateResponseNewEtag,
mockCommitSha,
mockCommitNextSha,
mockCommitMessage,
mockDefaultBranch,
mockProjectFullPath,
mockNewMergeRequestPath,
} from '../../mock_data';
const localVue = createLocalVue();
jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
refreshCurrentPage: jest.fn(),
......@@ -47,7 +53,8 @@ const mockProvide = {
describe('Pipeline Editor | Commit section', () => {
let wrapper;
let mockMutate;
let mockApollo;
const mockMutateCommitData = jest.fn();
const defaultProps = {
ciFileContent: mockCiYml,
......@@ -55,18 +62,7 @@ describe('Pipeline Editor | Commit section', () => {
isNewCiConfigFile: false,
};
const createComponent = ({ props = {}, options = {}, provide = {} } = {}) => {
mockMutate = jest.fn().mockResolvedValue({
data: {
commitCreate: {
errors: [],
commit: {
sha: mockCommitNextSha,
},
},
},
});
const createComponent = ({ apolloConfig = {}, props = {}, options = {}, provide = {} } = {}) => {
wrapper = mount(CommitSection, {
propsData: { ...defaultProps, ...props },
provide: { ...mockProvide, ...provide },
......@@ -75,16 +71,25 @@ describe('Pipeline Editor | Commit section', () => {
currentBranch: mockDefaultBranch,
};
},
mocks: {
$apollo: {
mutate: mockMutate,
},
},
attachTo: document.body,
...apolloConfig,
...options,
});
};
const createComponentWithApollo = (options) => {
const handlers = [[commitCreate, mockMutateCommitData]];
localVue.use(VueApollo);
mockApollo = createMockApollo(handlers);
const apolloConfig = {
localVue,
apolloProvider: mockApollo,
};
createComponent({ ...options, apolloConfig });
};
const findCommitForm = () => wrapper.findComponent(CommitForm);
const findCommitBtnLoadingIcon = () =>
wrapper.find('[type="submit"]').findComponent(GlLoadingIcon);
......@@ -104,66 +109,53 @@ describe('Pipeline Editor | Commit section', () => {
};
afterEach(() => {
mockMutate.mockReset();
wrapper.destroy();
});
describe('when the user commits a new file', () => {
beforeEach(async () => {
createComponent({ props: { isNewCiConfigFile: true } });
mockMutateCommitData.mockResolvedValue(mockCommitCreateResponse);
createComponentWithApollo({ props: { isNewCiConfigFile: true } });
await submitCommit();
});
it('calls the mutation with the CREATE action', () => {
// the extra calls are for updating client queries (currentBranch and lastCommitBranch)
expect(mockMutate).toHaveBeenCalledTimes(3);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
variables: {
...mockVariables,
action: COMMIT_ACTION_CREATE,
branch: mockDefaultBranch,
},
expect(mockMutateCommitData).toHaveBeenCalledTimes(1);
expect(mockMutateCommitData).toHaveBeenCalledWith({
...mockVariables,
action: COMMIT_ACTION_CREATE,
branch: mockDefaultBranch,
});
});
});
describe('when the user commits an update to an existing file', () => {
beforeEach(async () => {
createComponent();
createComponentWithApollo();
await submitCommit();
});
it('calls the mutation with the UPDATE action', () => {
expect(mockMutate).toHaveBeenCalledTimes(3);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
variables: {
...mockVariables,
action: COMMIT_ACTION_UPDATE,
branch: mockDefaultBranch,
},
expect(mockMutateCommitData).toHaveBeenCalledTimes(1);
expect(mockMutateCommitData).toHaveBeenCalledWith({
...mockVariables,
action: COMMIT_ACTION_UPDATE,
branch: mockDefaultBranch,
});
});
});
describe('when the user commits changes to the current branch', () => {
beforeEach(async () => {
createComponent();
createComponentWithApollo();
await submitCommit();
});
it('calls the mutation with the current branch', () => {
expect(mockMutate).toHaveBeenCalledTimes(3);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
variables: {
...mockVariables,
branch: mockDefaultBranch,
},
expect(mockMutateCommitData).toHaveBeenCalledTimes(1);
expect(mockMutateCommitData).toHaveBeenCalledWith({
...mockVariables,
branch: mockDefaultBranch,
});
});
......@@ -183,14 +175,10 @@ describe('Pipeline Editor | Commit section', () => {
it('a second commit submits the latest sha, keeping the form updated', async () => {
await submitCommit();
expect(mockMutate).toHaveBeenCalledTimes(6);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
variables: {
...mockVariables,
branch: mockDefaultBranch,
},
expect(mockMutateCommitData).toHaveBeenCalledTimes(2);
expect(mockMutateCommitData).toHaveBeenCalledWith({
...mockVariables,
branch: mockDefaultBranch,
});
});
});
......@@ -199,20 +187,16 @@ describe('Pipeline Editor | Commit section', () => {
const newBranch = 'new-branch';
beforeEach(async () => {
createComponent();
createComponentWithApollo();
await submitCommit({
branch: newBranch,
});
});
it('calls the mutation with the new branch', () => {
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
variables: {
...mockVariables,
branch: newBranch,
},
expect(mockMutateCommitData).toHaveBeenCalledWith({
...mockVariables,
branch: newBranch,
});
});
......@@ -225,7 +209,7 @@ describe('Pipeline Editor | Commit section', () => {
const newBranch = 'new-branch';
beforeEach(async () => {
createComponent();
createComponentWithApollo();
await submitCommit({
branch: newBranch,
openMergeRequest: true,
......@@ -244,11 +228,11 @@ describe('Pipeline Editor | Commit section', () => {
describe('when the commit is ocurring', () => {
beforeEach(() => {
createComponent();
createComponentWithApollo();
});
it('shows a saving state', async () => {
mockMutate.mockImplementationOnce(() => {
mockMutateCommitData.mockImplementationOnce(() => {
expect(findCommitBtnLoadingIcon().exists()).toBe(true);
return Promise.resolve();
});
......@@ -261,6 +245,26 @@ describe('Pipeline Editor | Commit section', () => {
});
});
describe('when the commit returns a different etag path', () => {
beforeEach(async () => {
createComponentWithApollo();
jest.spyOn(wrapper.vm.$apollo, 'mutate');
mockMutateCommitData.mockResolvedValue(mockCommitCreateResponseNewEtag);
await submitCommit();
});
it('calls the client mutation to update the etag', () => {
// 1:Commit submission, 2:etag update, 3:currentBranch update, 4:lastCommit update
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(4);
expect(wrapper.vm.$apollo.mutate).toHaveBeenNthCalledWith(2, {
mutation: updatePipelineEtag,
variables: {
pipelineEtag: mockCommitCreateResponseNewEtag.data.commitCreate.commitPipelinePath,
},
});
});
});
it('sets listeners on commit form', () => {
const handler = jest.fn();
createComponent({ options: { listeners: { event: handler } } });
......
......@@ -453,3 +453,31 @@ export const mockErrors = [
export const mockWarnings = [
'"jobs:multi_project_job may allow multiple pipelines to run for a single action due to `rules:when` clause with no `workflow:rules` - read more: https://docs.gitlab.com/ee/ci/troubleshooting.html#pipeline-warnings"',
];
export const mockCommitCreateResponse = {
data: {
commitCreate: {
__typename: 'CommitCreatePayload',
errors: [],
commit: {
__typename: 'Commit',
sha: mockCommitNextSha,
},
commitPipelinePath: '',
},
},
};
export const mockCommitCreateResponseNewEtag = {
data: {
commitCreate: {
__typename: 'CommitCreatePayload',
errors: [],
commit: {
__typename: 'Commit',
sha: mockCommitNextSha,
},
commitPipelinePath: '/api/graphql:pipelines/sha/550ceace1acd373c84d02bd539cb9d4614f786db',
},
},
};
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