diff options
Diffstat (limited to 'spec/frontend/snippets/components/edit_spec.js')
-rw-r--r-- | spec/frontend/snippets/components/edit_spec.js | 179 |
1 files changed, 93 insertions, 86 deletions
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js index 83f46dd347f..d2265dfd506 100644 --- a/spec/frontend/snippets/components/edit_spec.js +++ b/spec/frontend/snippets/components/edit_spec.js @@ -1,9 +1,8 @@ import { shallowMount } from '@vue/test-utils'; -import axios from '~/lib/utils/axios_utils'; import Flash from '~/flash'; import { GlLoadingIcon } from '@gitlab/ui'; -import { joinPaths, redirectTo } from '~/lib/utils/url_utility'; +import { redirectTo } from '~/lib/utils/url_utility'; import SnippetEditApp from '~/snippets/components/edit.vue'; import SnippetDescriptionEdit from '~/snippets/components/snippet_description_edit.vue'; @@ -16,25 +15,17 @@ import { SNIPPET_CREATE_MUTATION_ERROR, SNIPPET_UPDATE_MUTATION_ERROR } from '~/ import UpdateSnippetMutation from '~/snippets/mutations/updateSnippet.mutation.graphql'; import CreateSnippetMutation from '~/snippets/mutations/createSnippet.mutation.graphql'; -import AxiosMockAdapter from 'axios-mock-adapter'; import waitForPromises from 'helpers/wait_for_promises'; import { ApolloMutation } from 'vue-apollo'; jest.mock('~/lib/utils/url_utility', () => ({ - getBaseURL: jest.fn().mockReturnValue('foo/'), redirectTo: jest.fn().mockName('redirectTo'), - joinPaths: jest - .fn() - .mockName('joinPaths') - .mockReturnValue('contentApiURL'), })); jest.mock('~/flash'); let flashSpy; -const contentMock = 'Foo Bar'; -const rawPathMock = '/foo/bar'; const rawProjectPathMock = '/project/path'; const newlyEditedSnippetUrl = 'http://foo.bar'; const apiError = { message: 'Ufff' }; @@ -43,15 +34,27 @@ const mutationError = 'Bummer'; const attachedFilePath1 = 'foo/bar'; const attachedFilePath2 = 'alpha/beta'; +const actionWithContent = { + content: 'Foo Bar', +}; +const actionWithoutContent = { + content: '', +}; + const defaultProps = { snippetGid: 'gid://gitlab/PersonalSnippet/42', markdownPreviewPath: 'http://preview.foo.bar', markdownDocsPath: 'http://docs.foo.bar', }; +const defaultData = { + blobsActions: { + ...actionWithContent, + action: '', + }, +}; describe('Snippet Edit app', () => { let wrapper; - let axiosMock; const resolveMutate = jest.fn().mockResolvedValue({ data: { @@ -156,18 +159,21 @@ describe('Snippet Edit app', () => { }); it.each` - title | content | expectation - ${''} | ${''} | ${true} - ${'foo'} | ${''} | ${true} - ${''} | ${'foo'} | ${true} - ${'foo'} | ${'bar'} | ${false} + title | blobsActions | expectation + ${''} | ${{}} | ${true} + ${''} | ${{ actionWithContent }} | ${true} + ${''} | ${{ actionWithoutContent }} | ${true} + ${'foo'} | ${{}} | ${true} + ${'foo'} | ${{ actionWithoutContent }} | ${true} + ${'foo'} | ${{ actionWithoutContent, actionWithContent }} | ${true} + ${'foo'} | ${{ actionWithContent }} | ${false} `( - 'disables submit button unless both title and content are present', - ({ title, content, expectation }) => { + 'disables submit button unless both title and content for all blobs are present', + ({ title, blobsActions, expectation }) => { createComponent({ data: { snippet: { title }, - content, + blobsActions, }, }); const isBtnDisabled = Boolean(findSubmitButton().attributes('disabled')); @@ -192,83 +198,31 @@ describe('Snippet Edit app', () => { }); describe('functionality', () => { - describe('handling of the data from GraphQL response', () => { - const snippet = { - blob: { - rawPath: rawPathMock, - }, - }; - const getResSchema = newSnippet => { - return { - data: { - snippets: { - edges: newSnippet ? [] : [snippet], - }, - }, + describe('form submission handling', () => { + it('does not submit unchanged blobs', () => { + const foo = { + action: '', + }; + const bar = { + action: 'update', }; - }; - - const bootstrapForExistingSnippet = resp => { createComponent({ data: { - snippet, + blobsActions: { + foo, + bar, + }, }, }); - - if (resp === 500) { - axiosMock.onGet('contentApiURL').reply(500); - } else { - axiosMock.onGet('contentApiURL').reply(200, contentMock); - } - wrapper.vm.onSnippetFetch(getResSchema()); - }; - - const bootstrapForNewSnippet = () => { - createComponent(); - wrapper.vm.onSnippetFetch(getResSchema(true)); - }; - - beforeEach(() => { - axiosMock = new AxiosMockAdapter(axios); - }); - - afterEach(() => { - axiosMock.restore(); - }); - - it('fetches blob content with the additional query', () => { - bootstrapForExistingSnippet(); - - return waitForPromises().then(() => { - expect(joinPaths).toHaveBeenCalledWith('foo/', rawPathMock); - expect(wrapper.vm.newSnippet).toBe(false); - expect(wrapper.vm.content).toBe(contentMock); - }); - }); - - it('flashes the error message if fetching content fails', () => { - bootstrapForExistingSnippet(500); - - return waitForPromises().then(() => { - expect(flashSpy).toHaveBeenCalled(); - expect(wrapper.vm.content).toBe(''); - }); - }); - - it('does not fetch content for new snippet', () => { - bootstrapForNewSnippet(); + clickSubmitBtn(); return waitForPromises().then(() => { - // we keep using waitForPromises to make sure we do not run failed test - expect(wrapper.vm.newSnippet).toBe(true); - expect(wrapper.vm.content).toBe(''); - expect(joinPaths).not.toHaveBeenCalled(); - expect(wrapper.vm.snippet).toEqual(wrapper.vm.$options.newSnippetSchema); + expect(resolveMutate).toHaveBeenCalledWith( + expect.objectContaining({ variables: { input: { files: [bar] } } }), + ); }); }); - }); - describe('form submission handling', () => { it.each` newSnippet | projectPath | mutation | mutationName ${true} | ${rawProjectPathMock} | ${CreateSnippetMutation} | ${'CreateSnippetMutation with projectPath'} @@ -279,6 +233,7 @@ describe('Snippet Edit app', () => { createComponent({ data: { newSnippet, + ...defaultData, }, props: { ...defaultProps, @@ -419,5 +374,57 @@ describe('Snippet Edit app', () => { expect(resolveMutate).toHaveBeenCalledWith(updateMutationPayload()); }); }); + + describe('on before unload', () => { + let event; + let returnValueSetter; + + const bootstrap = data => { + createComponent({ + data, + }); + + event = new Event('beforeunload'); + returnValueSetter = jest.spyOn(event, 'returnValue', 'set'); + }; + + it('does not prevent page navigation if there are no blobs', () => { + bootstrap(); + window.dispatchEvent(event); + + expect(returnValueSetter).not.toHaveBeenCalled(); + }); + + it('does not prevent page navigation if there are no changes to the blobs content', () => { + bootstrap({ + blobsActions: { + foo: { + ...actionWithContent, + action: '', + }, + }, + }); + window.dispatchEvent(event); + + expect(returnValueSetter).not.toHaveBeenCalled(); + }); + + it('prevents page navigation if there are some changes in the snippet content', () => { + bootstrap({ + blobsActions: { + foo: { + ...actionWithContent, + action: 'update', + }, + }, + }); + + window.dispatchEvent(event); + + expect(returnValueSetter).toHaveBeenCalledWith( + 'Are you sure you want to lose unsaved changes?', + ); + }); + }); }); }); |