From 161f64399efc266c776e5e5ee3a0a1c41e5eef0c Mon Sep 17 00:00:00 2001 From: Samantha Ming Date: Mon, 27 Sep 2021 19:57:23 -0700 Subject: [PATCH 1/5] Add new directory modal in Vue Changelog: changed --- .../repository/components/breadcrumbs.vue | 24 ++- .../components/new_directory_modal.vue | 177 ++++++++++++++++++ .../javascripts/repository/constants.js | 3 + app/assets/javascripts/repository/index.js | 1 + app/views/projects/_files.html.haml | 2 - locale/gitlab.pot | 3 + .../files/user_creates_directory_spec.rb | 2 + .../components/new_directory_modal_spec.js | 177 ++++++++++++++++++ 8 files changed, 385 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/repository/components/new_directory_modal.vue create mode 100644 spec/frontend/repository/components/new_directory_modal_spec.js diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue index db84e2b59121ed..6e4fd8dfe2c886 100644 --- a/app/assets/javascripts/repository/components/breadcrumbs.vue +++ b/app/assets/javascripts/repository/components/breadcrumbs.vue @@ -14,6 +14,7 @@ import getRefMixin from '../mixins/get_ref'; import projectPathQuery from '../queries/project_path.query.graphql'; import projectShortPathQuery from '../queries/project_short_path.query.graphql'; import UploadBlobModal from './upload_blob_modal.vue'; +import NewDirectoryModal from './new_directory_modal.vue'; const ROW_TYPES = { header: 'header', @@ -21,6 +22,7 @@ const ROW_TYPES = { }; const UPLOAD_BLOB_MODAL_ID = 'modal-upload-blob'; +const NEW_DIRECTORY_MODAL_ID = 'modal-new-directory'; export default { components: { @@ -30,6 +32,7 @@ export default { GlDropdownItem, GlIcon, UploadBlobModal, + NewDirectoryModal, }, apollo: { projectShortPath: { @@ -121,8 +124,14 @@ export default { required: false, default: '', }, + newDirPath: { + type: String, + required: false, + default: '', + }, }, uploadBlobModalId: UPLOAD_BLOB_MODAL_ID, + newDirectoryModalId: NEW_DIRECTORY_MODAL_ID, data() { return { projectShortPath: '', @@ -160,6 +169,9 @@ export default { showUploadModal() { return this.canEditTree && !this.$apollo.queries.userPermissions.loading; }, + showNewDirectoryModal() { + return this.canEditTree && !this.$apollo.queries.userPermissions.loading; + }, dropdownItems() { const items = []; @@ -188,10 +200,9 @@ export default { { attrs: { href: '#modal-create-new-dir', - 'data-target': '#modal-create-new-dir', - 'data-toggle': 'modal', }, text: __('New directory'), + modalId: NEW_DIRECTORY_MODAL_ID, }, ); } else if (this.canCreateMrFromFork) { @@ -306,5 +317,14 @@ export default { :can-push-code="canPushCode" :path="uploadPath" /> + diff --git a/app/assets/javascripts/repository/components/new_directory_modal.vue b/app/assets/javascripts/repository/components/new_directory_modal.vue new file mode 100644 index 00000000000000..9171678545e8d1 --- /dev/null +++ b/app/assets/javascripts/repository/components/new_directory_modal.vue @@ -0,0 +1,177 @@ + + + diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js index 70952c8413b34c..152fabbd7cc647 100644 --- a/app/assets/javascripts/repository/constants.js +++ b/app/assets/javascripts/repository/constants.js @@ -10,6 +10,9 @@ export const SECONDARY_OPTIONS_TEXT = __('Cancel'); export const COMMIT_LABEL = __('Commit message'); export const TARGET_BRANCH_LABEL = __('Target branch'); export const TOGGLE_CREATE_MR_LABEL = __('Start a new merge request with these changes'); +export const NEW_BRANCH_IN_FORK = __( + 'A new branch will be created in your fork and a new merge request will be started.', +); export const COMMIT_MESSAGE_SUBJECT_MAX_LENGTH = 52; export const COMMIT_MESSAGE_BODY_MAX_LENGTH = 72; diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index 60a1a0443f7f7b..45e026ad69560d 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -120,6 +120,7 @@ export default function setupVueRepositoryList() { forkNewDirectoryPath, forkUploadBlobPath, uploadPath, + newDirPath, }, }); }, diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml index 597a22bf34a075..b76c20aca20c6a 100644 --- a/app/views/projects/_files.html.haml +++ b/app/views/projects/_files.html.haml @@ -20,5 +20,3 @@ = render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout), project_buttons: true #js-tree-list{ data: vue_file_list_data(project, ref) } - - if can_edit_tree? - = render 'projects/blob/new_dir' diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 7e38030b870ca9..6ed55aed211389 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -13272,6 +13272,9 @@ msgstr "" msgid "Error creating label." msgstr "" +msgid "Error creating new directory. Please try again." +msgstr "" + msgid "Error creating new iteration" msgstr "" diff --git a/spec/features/projects/files/user_creates_directory_spec.rb b/spec/features/projects/files/user_creates_directory_spec.rb index 46b93d738e11c8..5ad7641a5be0f3 100644 --- a/spec/features/projects/files/user_creates_directory_spec.rb +++ b/spec/features/projects/files/user_creates_directory_spec.rb @@ -98,12 +98,14 @@ expect(page).to have_content(fork_message) find('.add-to-tree').click + wait_for_requests click_link('New directory') fill_in(:dir_name, with: 'new_directory') fill_in(:commit_message, with: 'New commit message', visible: true) click_button('Create directory') fork = user.fork_of(project2.reload) + wait_for_requests expect(current_path).to eq(project_new_merge_request_path(fork)) end diff --git a/spec/frontend/repository/components/new_directory_modal_spec.js b/spec/frontend/repository/components/new_directory_modal_spec.js new file mode 100644 index 00000000000000..54642978b1dd92 --- /dev/null +++ b/spec/frontend/repository/components/new_directory_modal_spec.js @@ -0,0 +1,177 @@ +import { GlModal, GlFormTextarea, GlToggle } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +import waitForPromises from 'helpers/wait_for_promises'; +import createFlash from '~/flash'; +import httpStatusCodes from '~/lib/utils/http_status'; +import { visitUrl } from '~/lib/utils/url_utility'; +import NewDirectoryModal from '~/repository/components/new_directory_modal.vue'; + +jest.mock('~/flash'); +jest.mock('~/lib/utils/url_utility', () => ({ + visitUrl: jest.fn(), +})); + +const initialProps = { + modalTitle: 'Create New Directory', + modalId: 'modal-new-directory', + commitMessage: 'Add new directory', + targetBranch: 'some-target-branch', + originalBranch: 'master', + canPushCode: true, + path: 'create_dir', +}; + +describe('NewDirectoryModal', () => { + let wrapper; + let mock; + + const createComponent = (props = {}) => { + wrapper = shallowMount(NewDirectoryModal, { + propsData: { + ...initialProps, + ...props, + }, + attrs: { + static: true, + visible: true, + }, + }); + }; + + const findModal = () => wrapper.findComponent(GlModal); + const findDirName = () => wrapper.find('[name="dir_name"]'); + const findBranchName = () => wrapper.find('[name="branch_name"]'); + const findCommitMessage = () => wrapper.findComponent(GlFormTextarea); + const findMrToggle = () => wrapper.findComponent(GlToggle); + + const fillForm = async (inputValue = {}) => { + const { dirName, branchName, commitMessage } = inputValue; + + await findDirName().vm.$emit('input', dirName); + await findBranchName().vm.$emit('input', branchName); + await findCommitMessage().vm.$emit('input', commitMessage); + await nextTick; + }; + + const submitForm = async () => { + const mockEvent = { preventDefault: jest.fn() }; + findModal().vm.$emit('primary', mockEvent); + await waitForPromises(); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders modal component', () => { + createComponent(); + + const { modalTitle: title } = initialProps; + + expect(findModal().props()).toMatchObject({ + title, + size: 'md', + actionPrimary: { + text: 'Create directory', + }, + actionCancel: { + text: 'Cancel', + }, + }); + }); + + describe('form', () => { + it.each` + component | defaultValue | canPushCode | targetBranch | originalBranch | exist + ${findDirName} | ${undefined} | ${true} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${true} + ${findBranchName} | ${initialProps.targetBranch} | ${true} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${true} + ${findBranchName} | ${undefined} | ${false} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${false} + ${findCommitMessage} | ${initialProps.commitMessage} | ${true} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${true} + ${findMrToggle} | ${'true'} | ${true} | ${'new-target-branch'} | ${'master'} | ${true} + ${findMrToggle} | ${undefined} | ${true} | ${'master'} | ${'master'} | ${false} + `( + 'has the correct form fields ', + ({ component, defaultValue, canPushCode, targetBranch, originalBranch, exist }) => { + createComponent({ + canPushCode, + targetBranch, + originalBranch, + }); + const formField = component(); + + if (!exist) { + expect(formField.exists()).toBe(false); + return; + } + + expect(formField.exists()).toBe(true); + expect(formField.attributes('value')).toBe(defaultValue); + }, + ); + }); + + describe('form submission', () => { + beforeEach(async () => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('valid form', () => { + beforeEach(() => { + createComponent(); + }); + + it('passes the formData', async () => { + mock.onPost(initialProps.path).reply(httpStatusCodes.OK, {}); + const dirName = 'foo'; + const branchName = 'master'; + const commitMessage = 'add new dir'; + + await fillForm({ dirName, branchName, commitMessage }); + await submitForm(); + + expect(mock.history.post[0].data.get('dir_name')).toEqual(dirName); + expect(mock.history.post[0].data.get('branch_name')).toEqual(branchName); + expect(mock.history.post[0].data.get('commit_message')).toEqual(commitMessage); + }); + + it('redirects to the new directory', async () => { + const response = { filePath: 'new-dir-path' }; + mock.onPost(initialProps.path).reply(httpStatusCodes.OK, response); + + await fillForm({ dirName: 'foo', branchName: 'master', commitMessage: 'foo' }); + await submitForm(); + + expect(visitUrl).toHaveBeenCalledWith(response.filePath); + }); + }); + + describe('invalid form', () => { + beforeEach(() => { + createComponent(); + }); + + it('disables submit button', async () => { + await fillForm({ dirName: '', branchName: '', commitMessage: '' }); + expect(findModal().props('actionPrimary').attributes[0].disabled).toBe(true); + }); + + it('creates a flash error', async () => { + mock.onPost(initialProps.path).timeout(); + + await fillForm({ dirName: 'foo', branchName: 'master', commitMessage: 'foo' }); + await submitForm(); + + expect(createFlash).toHaveBeenCalledWith({ + message: 'Error creating new directory. Please try again.', + }); + }); + }); + }); +}); -- GitLab From 9d4c133e737cf7b7f5c4b89a1cc36823caf80b19 Mon Sep 17 00:00:00 2001 From: Samantha Ming Date: Thu, 7 Oct 2021 09:14:36 -0700 Subject: [PATCH 2/5] Put feature behind feature flag Update tests to use i18n Add feature flag --- .../repository/components/breadcrumbs.vue | 24 ++++++++++--- .../components/new_directory_modal.vue | 4 ++- app/controllers/projects/tree_controller.rb | 1 + app/controllers/projects_controller.rb | 1 + app/views/projects/_files.html.haml | 3 ++ .../development/new_dir_modal.yml | 8 +++++ .../repository/components/breadcrumbs_spec.js | 35 +++++++++++++++++++ .../components/new_directory_modal_spec.js | 6 ++-- 8 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 config/feature_flags/development/new_dir_modal.yml diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue index 6e4fd8dfe2c886..d3c41ef183125d 100644 --- a/app/assets/javascripts/repository/components/breadcrumbs.vue +++ b/app/assets/javascripts/repository/components/breadcrumbs.vue @@ -170,7 +170,11 @@ export default { return this.canEditTree && !this.$apollo.queries.userPermissions.loading; }, showNewDirectoryModal() { - return this.canEditTree && !this.$apollo.queries.userPermissions.loading; + return ( + gon.features?.newDirModal && + this.canEditTree && + !this.$apollo.queries.userPermissions.loading + ); }, dropdownItems() { const items = []; @@ -197,14 +201,26 @@ export default { text: __('Upload file'), modalId: UPLOAD_BLOB_MODAL_ID, }, - { + ); + + if (gon.features?.newDirModal) { + items.push({ attrs: { href: '#modal-create-new-dir', }, text: __('New directory'), modalId: NEW_DIRECTORY_MODAL_ID, - }, - ); + }); + } else { + items.push({ + attrs: { + href: '#modal-create-new-dir', + 'data-target': '#modal-create-new-dir', + 'data-toggle': 'modal', + }, + text: __('New directory'), + }); + } } else if (this.canCreateMrFromFork) { items.push( { diff --git a/app/assets/javascripts/repository/components/new_directory_modal.vue b/app/assets/javascripts/repository/components/new_directory_modal.vue index 9171678545e8d1..1fd88075c23da5 100644 --- a/app/assets/javascripts/repository/components/new_directory_modal.vue +++ b/app/assets/javascripts/repository/components/new_directory_modal.vue @@ -41,6 +41,8 @@ export default { TARGET_BRANCH_LABEL, TOGGLE_CREATE_MR_LABEL, NEW_BRANCH_IN_FORK, + PRIMARY_OPTIONS_TEXT, + ERROR_MESSAGE, }, props: { modalTitle: { @@ -111,7 +113,7 @@ export default { }; }, showCreateNewMrToggle() { - return this.canPushCode && this.target !== this.originalBranch; + return this.canPushCode; }, formCompleted() { return this.dir && this.commit && this.target; diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index cb0e1900e484b1..a76d45411dd768 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -18,6 +18,7 @@ class Projects::TreeController < Projects::ApplicationController before_action do push_frontend_feature_flag(:lazy_load_commits, @project, default_enabled: :yaml) push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml) + push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml) end feature_category :source_code_management diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 7c7e6457020871..26da0436dd83a3 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -38,6 +38,7 @@ class ProjectsController < Projects::ApplicationController push_frontend_feature_flag(:refactor_text_viewer, @project, default_enabled: :yaml) push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml) push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml) + push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml) end layout :determine_layout diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml index b76c20aca20c6a..cdcc98552f90b9 100644 --- a/app/views/projects/_files.html.haml +++ b/app/views/projects/_files.html.haml @@ -20,3 +20,6 @@ = render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout), project_buttons: true #js-tree-list{ data: vue_file_list_data(project, ref) } + - if !Feature.enabled?(:new_dir_modal, default_enabled: :yaml) && can_edit_tree? + = render 'projects/blob/new_dir' + diff --git a/config/feature_flags/development/new_dir_modal.yml b/config/feature_flags/development/new_dir_modal.yml new file mode 100644 index 00000000000000..12d007209b70b2 --- /dev/null +++ b/config/feature_flags/development/new_dir_modal.yml @@ -0,0 +1,8 @@ +--- +name: new_dir_modal +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71154 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341675 +milestone: '14.4' +type: development +group: group::source code +default_enabled: true diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js index 0733cffe4f41a8..b1bbff41530c1d 100644 --- a/spec/frontend/repository/components/breadcrumbs_spec.js +++ b/spec/frontend/repository/components/breadcrumbs_spec.js @@ -2,6 +2,7 @@ import { GlDropdown } from '@gitlab/ui'; import { shallowMount, RouterLinkStub } from '@vue/test-utils'; import Breadcrumbs from '~/repository/components/breadcrumbs.vue'; import UploadBlobModal from '~/repository/components/upload_blob_modal.vue'; +import NewDirectoryModal from '~/repository/components/new_directory_modal.vue'; const defaultMockRoute = { name: 'blobPath', @@ -38,6 +39,7 @@ describe('Repository breadcrumbs component', () => { }; const findUploadBlobModal = () => wrapper.find(UploadBlobModal); + const findNewDirectoryModal = () => wrapper.find(NewDirectoryModal); afterEach(() => { wrapper.destroy(); @@ -121,4 +123,37 @@ describe('Repository breadcrumbs component', () => { expect(findUploadBlobModal().exists()).toBe(true); }); }); + + describe('renders the new directory modal', () => { + describe('with the feature flag enabled', () => { + beforeEach(() => { + window.gon.features = { + newDirModal: true, + }; + factory('/', { canEditTree: true }); + }); + + it('does not render the modal while loading', () => { + expect(findNewDirectoryModal().exists()).toBe(false); + }); + + it('renders the modal once loaded', async () => { + wrapper.setData({ $apollo: { queries: { userPermissions: { loading: false } } } }); + + await wrapper.vm.$nextTick(); + + expect(findNewDirectoryModal().exists()).toBe(true); + }); + }); + + describe('with the feature flag disabled', () => { + it('does not render the modal', () => { + window.gon.features = { + newDirModal: false, + }; + factory('/', { canEditTree: true }, undefined, { newDirModal: false }); + expect(findNewDirectoryModal().exists()).toBe(false); + }); + }); + }); }); diff --git a/spec/frontend/repository/components/new_directory_modal_spec.js b/spec/frontend/repository/components/new_directory_modal_spec.js index 54642978b1dd92..4ffc3c8b34d473 100644 --- a/spec/frontend/repository/components/new_directory_modal_spec.js +++ b/spec/frontend/repository/components/new_directory_modal_spec.js @@ -75,7 +75,7 @@ describe('NewDirectoryModal', () => { title, size: 'md', actionPrimary: { - text: 'Create directory', + text: NewDirectoryModal.i18n.PRIMARY_OPTIONS_TEXT, }, actionCancel: { text: 'Cancel', @@ -91,7 +91,7 @@ describe('NewDirectoryModal', () => { ${findBranchName} | ${undefined} | ${false} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${false} ${findCommitMessage} | ${initialProps.commitMessage} | ${true} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${true} ${findMrToggle} | ${'true'} | ${true} | ${'new-target-branch'} | ${'master'} | ${true} - ${findMrToggle} | ${undefined} | ${true} | ${'master'} | ${'master'} | ${false} + ${findMrToggle} | ${'true'} | ${true} | ${'master'} | ${'master'} | ${true} `( 'has the correct form fields ', ({ component, defaultValue, canPushCode, targetBranch, originalBranch, exist }) => { @@ -169,7 +169,7 @@ describe('NewDirectoryModal', () => { await submitForm(); expect(createFlash).toHaveBeenCalledWith({ - message: 'Error creating new directory. Please try again.', + message: NewDirectoryModal.i18n.ERROR_MESSAGE, }); }); }); -- GitLab From b6d947cc774c51a0df1562cfe9d1b8161854cdfc Mon Sep 17 00:00:00 2001 From: Jacques Date: Fri, 8 Oct 2021 13:12:07 +0200 Subject: [PATCH 3/5] Make use of glFeatureFlagsMixin Used glFeatureFlagsMixin instead of global scope --- .../javascripts/repository/components/breadcrumbs.vue | 7 ++++--- spec/frontend/repository/components/breadcrumbs_spec.js | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue index d3c41ef183125d..d3717f10ec7ba0 100644 --- a/app/assets/javascripts/repository/components/breadcrumbs.vue +++ b/app/assets/javascripts/repository/components/breadcrumbs.vue @@ -9,6 +9,7 @@ import { } from '@gitlab/ui'; import permissionsQuery from 'shared_queries/repository/permissions.query.graphql'; import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { __ } from '../../locale'; import getRefMixin from '../mixins/get_ref'; import projectPathQuery from '../queries/project_path.query.graphql'; @@ -57,7 +58,7 @@ export default { directives: { GlModal: GlModalDirective, }, - mixins: [getRefMixin], + mixins: [getRefMixin, glFeatureFlagsMixin()], props: { currentPath: { type: String, @@ -171,7 +172,7 @@ export default { }, showNewDirectoryModal() { return ( - gon.features?.newDirModal && + this.glFeatures.newDirModal && this.canEditTree && !this.$apollo.queries.userPermissions.loading ); @@ -203,7 +204,7 @@ export default { }, ); - if (gon.features?.newDirModal) { + if (this.glFeatures.newDirModal) { items.push({ attrs: { href: '#modal-create-new-dir', diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js index b1bbff41530c1d..eb957c635ac4ff 100644 --- a/spec/frontend/repository/components/breadcrumbs_spec.js +++ b/spec/frontend/repository/components/breadcrumbs_spec.js @@ -11,7 +11,7 @@ const defaultMockRoute = { describe('Repository breadcrumbs component', () => { let wrapper; - const factory = (currentPath, extraProps = {}, mockRoute = {}) => { + const factory = (currentPath, extraProps = {}, mockRoute = {}, newDirModal = true) => { const $apollo = { queries: { userPermissions: { @@ -35,6 +35,7 @@ describe('Repository breadcrumbs component', () => { }, $apollo, }, + provide: { glFeatures: { newDirModal } }, }); }; @@ -151,7 +152,7 @@ describe('Repository breadcrumbs component', () => { window.gon.features = { newDirModal: false, }; - factory('/', { canEditTree: true }, undefined, { newDirModal: false }); + factory('/', { canEditTree: true }, {}, {}, false); expect(findNewDirectoryModal().exists()).toBe(false); }); }); -- GitLab From c42df38d8f9ecc22205a3754366de53c582dcf2b Mon Sep 17 00:00:00 2001 From: Samantha Ming Date: Fri, 8 Oct 2021 22:24:08 -0700 Subject: [PATCH 4/5] Add formData and add spec Add original_branch formData and make create_merge_request a conditional. Add spec to cover these updates. --- .../components/new_directory_modal.vue | 6 ++- .../components/new_directory_modal_spec.js | 38 ++++++++++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/repository/components/new_directory_modal.vue b/app/assets/javascripts/repository/components/new_directory_modal.vue index 1fd88075c23da5..6c5797bf5b20df 100644 --- a/app/assets/javascripts/repository/components/new_directory_modal.vue +++ b/app/assets/javascripts/repository/components/new_directory_modal.vue @@ -127,7 +127,11 @@ export default { formData.append('dir_name', this.dir); formData.append('commit_message', this.commit); formData.append('branch_name', this.target); - formData.append('create_merge_request', this.createNewMr); + formData.append('original_branch', this.originalBranch); + + if (this.createNewMr) { + formData.append('create_merge_request', this.createNewMr); + } return axios .post(this.path, formData) diff --git a/spec/frontend/repository/components/new_directory_modal_spec.js b/spec/frontend/repository/components/new_directory_modal_spec.js index 4ffc3c8b34d473..fe7f024e3eaaa0 100644 --- a/spec/frontend/repository/components/new_directory_modal_spec.js +++ b/spec/frontend/repository/components/new_directory_modal_spec.js @@ -24,6 +24,14 @@ const initialProps = { path: 'create_dir', }; +const defaultFormValue = { + dirName: 'foo', + originalBranch: initialProps.originalBranch, + branchName: initialProps.targetBranch, + commitMessage: initialProps.commitMessage, + createNewMr: true, +}; + describe('NewDirectoryModal', () => { let wrapper; let mock; @@ -48,11 +56,17 @@ describe('NewDirectoryModal', () => { const findMrToggle = () => wrapper.findComponent(GlToggle); const fillForm = async (inputValue = {}) => { - const { dirName, branchName, commitMessage } = inputValue; + const { + dirName = defaultFormValue.dirName, + branchName = defaultFormValue.branchName, + commitMessage = defaultFormValue.commitMessage, + createNewMr = true, + } = inputValue; await findDirName().vm.$emit('input', dirName); await findBranchName().vm.$emit('input', branchName); await findCommitMessage().vm.$emit('input', commitMessage); + await findMrToggle().vm.$emit('change', createNewMr); await nextTick; }; @@ -128,17 +142,29 @@ describe('NewDirectoryModal', () => { }); it('passes the formData', async () => { + const { + dirName, + branchName, + commitMessage, + originalBranch, + createNewMr, + } = defaultFormValue; mock.onPost(initialProps.path).reply(httpStatusCodes.OK, {}); - const dirName = 'foo'; - const branchName = 'master'; - const commitMessage = 'add new dir'; - - await fillForm({ dirName, branchName, commitMessage }); + await fillForm(); await submitForm(); expect(mock.history.post[0].data.get('dir_name')).toEqual(dirName); expect(mock.history.post[0].data.get('branch_name')).toEqual(branchName); expect(mock.history.post[0].data.get('commit_message')).toEqual(commitMessage); + expect(mock.history.post[0].data.get('original_branch')).toEqual(originalBranch); + expect(mock.history.post[0].data.get('create_merge_request')).toEqual(String(createNewMr)); + }); + + it('does not submit "create_merge_request" formData if createNewMr is not checked', async () => { + mock.onPost(initialProps.path).reply(httpStatusCodes.OK, {}); + await fillForm({ createNewMr: false }); + await submitForm(); + expect(mock.history.post[0].data.get('create_merge_request')).toBeNull(); }); it('redirects to the new directory', async () => { -- GitLab From 15f14e0a623df25afe9369ff8435460442034fa5 Mon Sep 17 00:00:00 2001 From: Samantha Ming Date: Fri, 8 Oct 2021 22:31:17 -0700 Subject: [PATCH 5/5] Add missing closing tag in startup_js --- app/views/layouts/_startup_js.html.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/layouts/_startup_js.html.haml b/app/views/layouts/_startup_js.html.haml index b7dd3a9556cc29..0d5f6bbe25be84 100644 --- a/app/views/layouts/_startup_js.html.haml +++ b/app/views/layouts/_startup_js.html.haml @@ -25,6 +25,7 @@ headers: { "Content-Type": "application/json", ...headers, + } }; gl.startup_graphql_calls = gl.startup_graphql_calls.map(call => ({ -- GitLab