diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
commit | 48aff82709769b098321c738f3444b9bdaa694c6 (patch) | |
tree | e00c7c43e2d9b603a5a6af576b1685e400410dee /spec/frontend/static_site_editor | |
parent | 879f5329ee916a948223f8f43d77fba4da6cd028 (diff) | |
download | gitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz |
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'spec/frontend/static_site_editor')
10 files changed, 452 insertions, 93 deletions
diff --git a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js new file mode 100644 index 00000000000..191f91be076 --- /dev/null +++ b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js @@ -0,0 +1,99 @@ +import { shallowMount } from '@vue/test-utils'; + +import { useLocalStorageSpy } from 'helpers/local_storage_helper'; +import { GlFormInput, GlFormTextarea } from '@gitlab/ui'; + +import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue'; + +import { mergeRequestMeta } from '../mock_data'; + +describe('~/static_site_editor/components/edit_meta_controls.vue', () => { + useLocalStorageSpy(); + + let wrapper; + let mockSelect; + let mockGlFormInputTitleInstance; + const { title, description } = mergeRequestMeta; + const newTitle = 'New title'; + const newDescription = 'New description'; + + const buildWrapper = (propsData = {}) => { + wrapper = shallowMount(EditMetaControls, { + propsData: { + title, + description, + ...propsData, + }, + }); + }; + + const buildMocks = () => { + mockSelect = jest.fn(); + mockGlFormInputTitleInstance = { $el: { select: mockSelect } }; + wrapper.vm.$refs.title = mockGlFormInputTitleInstance; + }; + + const findGlFormInputTitle = () => wrapper.find(GlFormInput); + const findGlFormTextAreaDescription = () => wrapper.find(GlFormTextarea); + + beforeEach(() => { + buildWrapper(); + buildMocks(); + + return wrapper.vm.$nextTick(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('renders the title input', () => { + expect(findGlFormInputTitle().exists()).toBe(true); + }); + + it('renders the description input', () => { + expect(findGlFormTextAreaDescription().exists()).toBe(true); + }); + + it('forwards the title prop to the title input', () => { + expect(findGlFormInputTitle().attributes().value).toBe(title); + }); + + it('forwards the description prop to the description input', () => { + expect(findGlFormTextAreaDescription().attributes().value).toBe(description); + }); + + it('calls select on the title input when mounted', () => { + expect(mockGlFormInputTitleInstance.$el.select).toHaveBeenCalled(); + }); + + describe('when inputs change', () => { + const storageKey = 'sse-merge-request-meta-local-storage-editable'; + + afterEach(() => { + localStorage.removeItem(storageKey); + }); + + it.each` + findFn | key | value + ${findGlFormInputTitle} | ${'title'} | ${newTitle} + ${findGlFormTextAreaDescription} | ${'description'} | ${newDescription} + `('emits updated settings when $findFn input updates', ({ key, value, findFn }) => { + findFn().vm.$emit('input', value); + + const newSettings = { ...mergeRequestMeta, [key]: value }; + + expect(wrapper.emitted('updateSettings')[0][0]).toMatchObject(newSettings); + }); + + it('should remember the input changes', () => { + findGlFormInputTitle().vm.$emit('input', newTitle); + findGlFormTextAreaDescription().vm.$emit('input', newDescription); + + const newSettings = { title: newTitle, description: newDescription }; + + expect(localStorage.setItem).toHaveBeenCalledWith(storageKey, JSON.stringify(newSettings)); + }); + }); +}); diff --git a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js new file mode 100644 index 00000000000..7a5685033f3 --- /dev/null +++ b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js @@ -0,0 +1,80 @@ +import { shallowMount } from '@vue/test-utils'; + +import { GlModal } from '@gitlab/ui'; + +import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue'; +import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue'; + +import { sourcePath, mergeRequestMeta } from '../mock_data'; + +describe('~/static_site_editor/components/edit_meta_modal.vue', () => { + let wrapper; + let resetCachedEditable; + let mockEditMetaControlsInstance; + const { title, description } = mergeRequestMeta; + + const buildWrapper = (propsData = {}) => { + wrapper = shallowMount(EditMetaModal, { + propsData: { + sourcePath, + ...propsData, + }, + }); + }; + + const buildMocks = () => { + resetCachedEditable = jest.fn(); + mockEditMetaControlsInstance = { resetCachedEditable }; + wrapper.vm.$refs.editMetaControls = mockEditMetaControlsInstance; + }; + + const findGlModal = () => wrapper.find(GlModal); + const findEditMetaControls = () => wrapper.find(EditMetaControls); + + beforeEach(() => { + buildWrapper(); + buildMocks(); + + return wrapper.vm.$nextTick(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('renders the modal', () => { + expect(findGlModal().exists()).toBe(true); + }); + + it('renders the edit meta controls', () => { + expect(findEditMetaControls().exists()).toBe(true); + }); + + it('contains the sourcePath in the title', () => { + expect(findEditMetaControls().props('title')).toContain(sourcePath); + }); + + it('forwards the title prop', () => { + expect(findEditMetaControls().props('title')).toBe(title); + }); + + it('forwards the description prop', () => { + expect(findEditMetaControls().props('description')).toBe(description); + }); + + it('emits the primary event with mergeRequestMeta', () => { + findGlModal().vm.$emit('primary', mergeRequestMeta); + expect(wrapper.emitted('primary')).toEqual([[mergeRequestMeta]]); + }); + + it('calls resetCachedEditable on EditMetaControls when primary emits', () => { + findGlModal().vm.$emit('primary', mergeRequestMeta); + expect(mockEditMetaControlsInstance.resetCachedEditable).toHaveBeenCalled(); + }); + + it('emits the hide event', () => { + findGlModal().vm.$emit('hide'); + expect(wrapper.emitted('hide')).toEqual([[]]); + }); +}); diff --git a/spec/frontend/static_site_editor/components/front_matter_controls_spec.js b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js index 82e8fad643e..8001f2fbd29 100644 --- a/spec/frontend/static_site_editor/components/front_matter_controls_spec.js +++ b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js @@ -5,18 +5,11 @@ import { humanize } from '~/lib/utils/text_utility'; import FrontMatterControls from '~/static_site_editor/components/front_matter_controls.vue'; +import { sourceContentHeaderObjYAML as settings } from '../mock_data'; + describe('~/static_site_editor/components/front_matter_controls.vue', () => { let wrapper; - // TODO Refactor and update `sourceContentHeaderObjYAML` in mock_data when !41230 lands - const settings = { - layout: 'handbook-page-toc', - title: 'Handbook', - twitter_image: '/images/tweets/handbook-gitlab.png', - suppress_header: true, - extra_css: ['sales-and-free-trial-common.css', 'form-to-resource.css'], - }; - const buildWrapper = (propsData = {}) => { wrapper = shallowMount(FrontMatterControls, { propsData: { diff --git a/spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js new file mode 100644 index 00000000000..0670b240a3f --- /dev/null +++ b/spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js @@ -0,0 +1,27 @@ +import appDataQuery from '~/static_site_editor/graphql/queries/app_data.query.graphql'; +import hasSubmittedChanges from '~/static_site_editor/graphql/resolvers/has_submitted_changes'; + +describe('static_site_editor/graphql/resolvers/has_submitted_changes', () => { + it('updates the cache with the data passed in input', () => { + const cachedData = { appData: { original: 'foo' } }; + const newValue = { input: { hasSubmittedChanges: true } }; + + const cache = { + readQuery: jest.fn().mockReturnValue(cachedData), + writeQuery: jest.fn(), + }; + hasSubmittedChanges(null, newValue, { cache }); + + expect(cache.readQuery).toHaveBeenCalledWith({ query: appDataQuery }); + expect(cache.writeQuery).toHaveBeenCalledWith({ + query: appDataQuery, + data: { + appData: { + __typename: 'AppData', + original: 'foo', + hasSubmittedChanges: true, + }, + }, + }); + }); +}); diff --git a/spec/frontend/static_site_editor/mock_data.js b/spec/frontend/static_site_editor/mock_data.js index d861f6c9cd7..0b08e290227 100644 --- a/spec/frontend/static_site_editor/mock_data.js +++ b/spec/frontend/static_site_editor/mock_data.js @@ -2,11 +2,17 @@ export const sourceContentHeaderYAML = `--- layout: handbook-page-toc title: Handbook twitter_image: /images/tweets/handbook-gitlab.png +suppress_header: true +extra_css: + - sales-and-free-trial-common.css + - form-to-resource.css ---`; export const sourceContentHeaderObjYAML = { layout: 'handbook-page-toc', title: 'Handbook', twitter_image: '/images/tweets/handbook-gitlab.png', + suppress_header: true, + extra_css: ['sales-and-free-trial-common.css', 'form-to-resource.css'], }; export const sourceContentSpacing = `\n`; export const sourceContentBody = `## On this page @@ -23,7 +29,10 @@ export const username = 'gitlabuser'; export const projectId = '123456'; export const returnUrl = 'https://www.gitlab.com'; export const sourcePath = 'foobar.md.html'; - +export const mergeRequestMeta = { + title: `Update ${sourcePath} file`, + description: 'Copy update', +}; export const savedContentMeta = { branch: { label: 'foobar', diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js index 41f8a1075c0..2c69e884005 100644 --- a/spec/frontend/static_site_editor/pages/home_spec.js +++ b/spec/frontend/static_site_editor/pages/home_spec.js @@ -1,12 +1,13 @@ -import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import Home from '~/static_site_editor/pages/home.vue'; import SkeletonLoader from '~/static_site_editor/components/skeleton_loader.vue'; import EditArea from '~/static_site_editor/components/edit_area.vue'; +import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue'; import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue'; import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue'; import submitContentChangesMutation from '~/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql'; +import hasSubmittedChangesMutation from '~/static_site_editor/graphql/mutations/has_submitted_changes.mutation.graphql'; import { SUCCESS_ROUTE } from '~/static_site_editor/router/constants'; import { TRACKING_ACTION_INITIALIZE_EDITOR } from '~/static_site_editor/constants'; @@ -17,15 +18,15 @@ import { sourceContentTitle as title, sourcePath, username, + mergeRequestMeta, savedContentMeta, submitChangesError, trackingCategory, + images, } from '../mock_data'; const localVue = createLocalVue(); -localVue.use(Vuex); - describe('static_site_editor/pages/home', () => { let wrapper; let store; @@ -33,6 +34,19 @@ describe('static_site_editor/pages/home', () => { let $router; let mutateMock; let trackingSpy; + const defaultAppData = { + isSupportedContent: true, + hasSubmittedChanges: false, + returnUrl, + project, + username, + sourcePath, + }; + const hasSubmittedChangesMutationPayload = { + data: { + appData: { ...defaultAppData, hasSubmittedChanges: true }, + }, + }; const buildApollo = (queries = {}) => { mutateMock = jest.fn(); @@ -64,7 +78,7 @@ describe('static_site_editor/pages/home', () => { }, data() { return { - appData: { isSupportedContent: true, returnUrl, project, username, sourcePath }, + appData: { ...defaultAppData }, sourceContent: { title, content }, ...data, }; @@ -73,6 +87,7 @@ describe('static_site_editor/pages/home', () => { }; const findEditArea = () => wrapper.find(EditArea); + const findEditMetaModal = () => wrapper.find(EditMetaModal); const findInvalidContentMessage = () => wrapper.find(InvalidContentMessage); const findSkeletonLoader = () => wrapper.find(SkeletonLoader); const findSubmitChangesError = () => wrapper.find(SubmitChangesError); @@ -140,24 +155,51 @@ describe('static_site_editor/pages/home', () => { }); it('displays invalid content message when content is not supported', () => { - buildWrapper({ appData: { isSupportedContent: false } }); + buildWrapper({ appData: { ...defaultAppData, isSupportedContent: false } }); expect(findInvalidContentMessage().exists()).toBe(true); }); it('does not display invalid content message when content is supported', () => { - buildWrapper({ appData: { isSupportedContent: true } }); + buildWrapper(); expect(findInvalidContentMessage().exists()).toBe(false); }); - describe('when submitting changes fails', () => { - beforeEach(() => { - mutateMock.mockRejectedValue(new Error(submitChangesError)); + it('renders an EditMetaModal component', () => { + buildWrapper(); + + expect(findEditMetaModal().exists()).toBe(true); + }); + describe('when preparing submission', () => { + it('calls the show method when the edit-area submit event is emitted', () => { buildWrapper(); + + const mockInstance = { show: jest.fn() }; + wrapper.vm.$refs.editMetaModal = mockInstance; + findEditArea().vm.$emit('submit', { content }); + return wrapper.vm.$nextTick().then(() => { + expect(mockInstance.show).toHaveBeenCalled(); + }); + }); + }); + + describe('when submitting changes fails', () => { + const setupMutateMock = () => { + mutateMock + .mockResolvedValueOnce(hasSubmittedChangesMutationPayload) + .mockRejectedValueOnce(new Error(submitChangesError)); + }; + + beforeEach(() => { + setupMutateMock(); + + buildWrapper({ content }); + findEditMetaModal().vm.$emit('primary', mergeRequestMeta); + return wrapper.vm.$nextTick(); }); @@ -166,6 +208,8 @@ describe('static_site_editor/pages/home', () => { }); it('retries submitting changes when retry button is clicked', () => { + setupMutateMock(); + findSubmitChangesError().vm.$emit('retry'); expect(mutateMock).toHaveBeenCalled(); @@ -180,26 +224,35 @@ describe('static_site_editor/pages/home', () => { }); }); - it('does not display submit changes error when an error does not exist', () => { - buildWrapper(); - - expect(findSubmitChangesError().exists()).toBe(false); - }); - describe('when submitting changes succeeds', () => { const newContent = `new ${content}`; beforeEach(() => { - mutateMock.mockResolvedValueOnce({ data: { submitContentChanges: savedContentMeta } }); + mutateMock.mockResolvedValueOnce(hasSubmittedChangesMutationPayload).mockResolvedValueOnce({ + data: { + submitContentChanges: savedContentMeta, + }, + }); - buildWrapper(); - findEditArea().vm.$emit('submit', { content: newContent }); + buildWrapper({ content: newContent, images }); + findEditMetaModal().vm.$emit('primary', mergeRequestMeta); return wrapper.vm.$nextTick(); }); + it('dispatches hasSubmittedChanges mutation', () => { + expect(mutateMock).toHaveBeenNthCalledWith(1, { + mutation: hasSubmittedChangesMutation, + variables: { + input: { + hasSubmittedChanges: true, + }, + }, + }); + }); + it('dispatches submitContentChanges mutation', () => { - expect(mutateMock).toHaveBeenCalledWith({ + expect(mutateMock).toHaveBeenNthCalledWith(2, { mutation: submitContentChangesMutation, variables: { input: { @@ -207,6 +260,8 @@ describe('static_site_editor/pages/home', () => { project, sourcePath, username, + images, + mergeRequestMeta, }, }, }); @@ -217,6 +272,12 @@ describe('static_site_editor/pages/home', () => { }); }); + it('does not display submit changes error when an error does not exist', () => { + buildWrapper(); + + expect(findSubmitChangesError().exists()).toBe(false); + }); + it('tracks when editor is initialized on the mounted lifecycle hook', () => { buildWrapper(); expect(trackingSpy).toHaveBeenCalledWith( diff --git a/spec/frontend/static_site_editor/pages/success_spec.js b/spec/frontend/static_site_editor/pages/success_spec.js index 3e19e2413e7..3fc69dc4586 100644 --- a/spec/frontend/static_site_editor/pages/success_spec.js +++ b/spec/frontend/static_site_editor/pages/success_spec.js @@ -1,10 +1,10 @@ import { shallowMount } from '@vue/test-utils'; -import { GlEmptyState, GlButton } from '@gitlab/ui'; +import { GlButton, GlEmptyState, GlLoadingIcon } from '@gitlab/ui'; import Success from '~/static_site_editor/pages/success.vue'; import { savedContentMeta, returnUrl, sourcePath } from '../mock_data'; import { HOME_ROUTE } from '~/static_site_editor/router/constants'; -describe('static_site_editor/pages/success', () => { +describe('~/static_site_editor/pages/success.vue', () => { const mergeRequestsIllustrationPath = 'illustrations/merge_requests.svg'; let wrapper; let router; @@ -15,14 +15,15 @@ describe('static_site_editor/pages/success', () => { }; }; - const buildWrapper = (data = {}) => { + const buildWrapper = (data = {}, appData = {}) => { wrapper = shallowMount(Success, { mocks: { $router: router, }, stubs: { - GlEmptyState, GlButton, + GlEmptyState, + GlLoadingIcon, }, propsData: { mergeRequestsIllustrationPath, @@ -33,6 +34,8 @@ describe('static_site_editor/pages/success', () => { appData: { returnUrl, sourcePath, + hasSubmittedChanges: true, + ...appData, }, ...data, }; @@ -40,8 +43,9 @@ describe('static_site_editor/pages/success', () => { }); }; - const findEmptyState = () => wrapper.find(GlEmptyState); const findReturnUrlButton = () => wrapper.find(GlButton); + const findEmptyState = () => wrapper.find(GlEmptyState); + const findLoadingIcon = () => wrapper.find(GlLoadingIcon); beforeEach(() => { buildRouter(); @@ -52,50 +56,76 @@ describe('static_site_editor/pages/success', () => { wrapper = null; }); - it('renders empty state with a link to the created merge request', () => { - buildWrapper(); + describe('when savedContentMeta is valid', () => { + it('renders empty state with a link to the created merge request', () => { + buildWrapper(); + + expect(findEmptyState().exists()).toBe(true); + expect(findEmptyState().props()).toMatchObject({ + primaryButtonText: 'View merge request', + primaryButtonLink: savedContentMeta.mergeRequest.url, + title: 'Your merge request has been created', + svgPath: mergeRequestsIllustrationPath, + svgHeight: 146, + }); + }); - expect(findEmptyState().exists()).toBe(true); - expect(findEmptyState().props()).toMatchObject({ - primaryButtonText: 'View merge request', - primaryButtonLink: savedContentMeta.mergeRequest.url, - title: 'Your merge request has been created', - svgPath: mergeRequestsIllustrationPath, + it('displays merge request instructions in the empty state', () => { + buildWrapper(); + + expect(findEmptyState().text()).toContain( + 'To see your changes live you will need to do the following things:', + ); + expect(findEmptyState().text()).toContain('1. Add a clear title to describe the change.'); + expect(findEmptyState().text()).toContain( + '2. Add a description to explain why the change is being made.', + ); + expect(findEmptyState().text()).toContain( + '3. Assign a person to review and accept the merge request.', + ); }); - }); - it('displays merge request instructions in the empty state', () => { - buildWrapper(); - - expect(findEmptyState().text()).toContain( - 'To see your changes live you will need to do the following things:', - ); - expect(findEmptyState().text()).toContain('1. Add a clear title to describe the change.'); - expect(findEmptyState().text()).toContain( - '2. Add a description to explain why the change is being made.', - ); - expect(findEmptyState().text()).toContain( - '3. Assign a person to review and accept the merge request.', - ); - }); + it('displays return to site button', () => { + buildWrapper(); + + expect(findReturnUrlButton().text()).toBe('Return to site'); + expect(findReturnUrlButton().attributes().href).toBe(returnUrl); + }); - it('displays return to site button', () => { - buildWrapper(); + it('displays source path', () => { + buildWrapper(); - expect(findReturnUrlButton().text()).toBe('Return to site'); - expect(findReturnUrlButton().attributes().href).toBe(returnUrl); + expect(wrapper.text()).toContain(`Update ${sourcePath} file`); + }); }); - it('displays source path', () => { - buildWrapper(); + describe('when savedContentMeta is invalid', () => { + it('renders empty state with a loader', () => { + buildWrapper({ savedContentMeta: null }); - expect(wrapper.text()).toContain(`Update ${sourcePath} file`); - }); + expect(findEmptyState().exists()).toBe(true); + expect(findEmptyState().props()).toMatchObject({ + title: 'Creating your merge request', + svgPath: mergeRequestsIllustrationPath, + }); + expect(findLoadingIcon().exists()).toBe(true); + }); - it('redirects to the HOME route when content has not been submitted', () => { - buildWrapper({ savedContentMeta: null }); + it('displays helper info in the empty state', () => { + buildWrapper({ savedContentMeta: null }); - expect(router.push).toHaveBeenCalledWith(HOME_ROUTE); - expect(wrapper.html()).toBe(''); + expect(findEmptyState().text()).toContain( + 'You can set an assignee to get your changes reviewed and deployed once your merge request is created', + ); + expect(findEmptyState().text()).toContain( + 'A link to view the merge request will appear once ready', + ); + }); + + it('redirects to the HOME route when content has not been submitted', () => { + buildWrapper({ savedContentMeta: null }, { hasSubmittedChanges: false }); + + expect(router.push).toHaveBeenCalledWith(HOME_ROUTE); + }); }); }); diff --git a/spec/frontend/static_site_editor/services/front_matterify_spec.js b/spec/frontend/static_site_editor/services/front_matterify_spec.js new file mode 100644 index 00000000000..dbaedc30849 --- /dev/null +++ b/spec/frontend/static_site_editor/services/front_matterify_spec.js @@ -0,0 +1,47 @@ +import { + sourceContentYAML as content, + sourceContentHeaderObjYAML as yamlFrontMatterObj, + sourceContentSpacing as spacing, + sourceContentBody as body, +} from '../mock_data'; + +import { frontMatterify, stringify } from '~/static_site_editor/services/front_matterify'; + +describe('static_site_editor/services/front_matterify', () => { + const frontMatterifiedContent = { + source: content, + matter: yamlFrontMatterObj, + spacing, + content: body, + delimiter: '---', + type: 'yaml', + }; + const frontMatterifiedBody = { + source: body, + matter: null, + spacing: null, + content: body, + delimiter: null, + type: null, + }; + + describe('frontMatterify', () => { + it.each` + frontMatterified | target + ${frontMatterify(content)} | ${frontMatterifiedContent} + ${frontMatterify(body)} | ${frontMatterifiedBody} + `('returns $target from $frontMatterified', ({ frontMatterified, target }) => { + expect(frontMatterified).toEqual(target); + }); + }); + + describe('stringify', () => { + it.each` + stringified | target + ${stringify(frontMatterifiedContent)} | ${content} + ${stringify(frontMatterifiedBody)} | ${body} + `('returns $target from $stringified', ({ stringified, target }) => { + expect(stringified).toBe(target); + }); + }); +}); diff --git a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js index d464e6b1895..5018da7300b 100644 --- a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js +++ b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js @@ -19,6 +19,7 @@ import { commitBranchResponse, commitMultipleResponse, createMergeRequestResponse, + mergeRequestMeta, sourcePath, sourceContentYAML as content, trackingCategory, @@ -28,11 +29,20 @@ import { jest.mock('~/static_site_editor/services/generate_branch_name'); describe('submitContentChanges', () => { - const mergeRequestTitle = `Update ${sourcePath} file`; const branch = 'branch-name'; let trackingSpy; let origPage; + const buildPayload = (overrides = {}) => ({ + username, + projectId, + sourcePath, + content, + images, + mergeRequestMeta, + ...overrides, + }); + beforeEach(() => { jest.spyOn(Api, 'createBranch').mockResolvedValue({ data: commitBranchResponse }); jest.spyOn(Api, 'commitMultiple').mockResolvedValue({ data: commitMultipleResponse }); @@ -53,7 +63,7 @@ describe('submitContentChanges', () => { }); it('creates a branch named after the username and target branch', () => { - return submitContentChanges({ username, projectId }).then(() => { + return submitContentChanges(buildPayload()).then(() => { expect(Api.createBranch).toHaveBeenCalledWith(projectId, { ref: DEFAULT_TARGET_BRANCH, branch, @@ -64,16 +74,16 @@ describe('submitContentChanges', () => { it('notifies error when branch could not be created', () => { Api.createBranch.mockRejectedValueOnce(); - return expect(submitContentChanges({ username, projectId })).rejects.toThrow( + return expect(submitContentChanges(buildPayload())).rejects.toThrow( SUBMIT_CHANGES_BRANCH_ERROR, ); }); it('commits the content changes to the branch when creating branch succeeds', () => { - return submitContentChanges({ username, projectId, sourcePath, content, images }).then(() => { + return submitContentChanges(buildPayload()).then(() => { expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, { branch, - commit_message: mergeRequestTitle, + commit_message: mergeRequestMeta.title, actions: [ { action: 'update', @@ -93,16 +103,11 @@ describe('submitContentChanges', () => { it('does not commit an image if it has been removed from the content', () => { const contentWithoutImages = '## Content without images'; - return submitContentChanges({ - username, - projectId, - sourcePath, - content: contentWithoutImages, - images, - }).then(() => { + const payload = buildPayload({ content: contentWithoutImages }); + return submitContentChanges(payload).then(() => { expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, { branch, - commit_message: mergeRequestTitle, + commit_message: mergeRequestMeta.title, actions: [ { action: 'update', @@ -117,17 +122,19 @@ describe('submitContentChanges', () => { it('notifies error when content could not be committed', () => { Api.commitMultiple.mockRejectedValueOnce(); - return expect(submitContentChanges({ username, projectId, images })).rejects.toThrow( + return expect(submitContentChanges(buildPayload())).rejects.toThrow( SUBMIT_CHANGES_COMMIT_ERROR, ); }); - it('creates a merge request when commiting changes succeeds', () => { - return submitContentChanges({ username, projectId, sourcePath, content, images }).then(() => { + it('creates a merge request when committing changes succeeds', () => { + return submitContentChanges(buildPayload()).then(() => { + const { title, description } = mergeRequestMeta; expect(Api.createProjectMergeRequest).toHaveBeenCalledWith( projectId, convertObjectPropsToSnakeCase({ - title: mergeRequestTitle, + title, + description, targetBranch: DEFAULT_TARGET_BRANCH, sourceBranch: branch, }), @@ -138,7 +145,7 @@ describe('submitContentChanges', () => { it('notifies error when merge request could not be created', () => { Api.createProjectMergeRequest.mockRejectedValueOnce(); - return expect(submitContentChanges({ username, projectId, images })).rejects.toThrow( + return expect(submitContentChanges(buildPayload())).rejects.toThrow( SUBMIT_CHANGES_MERGE_REQUEST_ERROR, ); }); @@ -147,11 +154,9 @@ describe('submitContentChanges', () => { let result; beforeEach(() => { - return submitContentChanges({ username, projectId, sourcePath, content, images }).then( - _result => { - result = _result; - }, - ); + return submitContentChanges(buildPayload()).then(_result => { + result = _result; + }); }); it('returns the branch name', () => { @@ -179,7 +184,7 @@ describe('submitContentChanges', () => { describe('sends the correct tracking event', () => { beforeEach(() => { - return submitContentChanges({ username, projectId, sourcePath, content, images }); + return submitContentChanges(buildPayload()); }); it('for committing changes', () => { diff --git a/spec/frontend/static_site_editor/services/templater_spec.js b/spec/frontend/static_site_editor/services/templater_spec.js index 1e7ae872b7e..cb3a0a0c106 100644 --- a/spec/frontend/static_site_editor/services/templater_spec.js +++ b/spec/frontend/static_site_editor/services/templater_spec.js @@ -39,6 +39,10 @@ Below this line is a codeblock of the same HTML that should be ignored and prese <p>Some paragraph...</p> </div> \`\`\` + +Below this line is a iframe that should be ignored and preserved + +<iframe></iframe> `; const sourceTemplated = `Below this line is a simple ERB (single-line erb block) example. @@ -87,6 +91,10 @@ Below this line is a codeblock of the same HTML that should be ignored and prese <p>Some paragraph...</p> </div> \`\`\` + +Below this line is a iframe that should be ignored and preserved + +<iframe></iframe> `; it.each` |