diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-20 21:42:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-20 21:42:06 +0300 |
commit | 6e4e1050d9dba2b7b2523fdd1768823ab85feef4 (patch) | |
tree | 78be5963ec075d80116a932011d695dd33910b4e /spec/frontend/releases/components | |
parent | 1ce776de4ae122aba3f349c02c17cebeaa8ecf07 (diff) |
Add latest changes from gitlab-org/gitlab@13-3-stable-ee
Diffstat (limited to 'spec/frontend/releases/components')
-rw-r--r-- | spec/frontend/releases/components/app_edit_new_spec.js (renamed from spec/frontend/releases/components/app_edit_spec.js) | 103 | ||||
-rw-r--r-- | spec/frontend/releases/components/app_index_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/releases/components/app_new_spec.js | 26 | ||||
-rw-r--r-- | spec/frontend/releases/components/app_show_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/releases/components/asset_links_form_spec.js | 143 | ||||
-rw-r--r-- | spec/frontend/releases/components/release_block_assets_spec.js | 4 | ||||
-rw-r--r-- | spec/frontend/releases/components/release_block_footer_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/releases/components/release_block_metadata_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/releases/components/tag_field_exsting_spec.js | 78 | ||||
-rw-r--r-- | spec/frontend/releases/components/tag_field_new_spec.js | 144 | ||||
-rw-r--r-- | spec/frontend/releases/components/tag_field_spec.js | 59 |
11 files changed, 465 insertions, 100 deletions
diff --git a/spec/frontend/releases/components/app_edit_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js index 4450b047acd..e9727801c1a 100644 --- a/spec/frontend/releases/components/app_edit_spec.js +++ b/spec/frontend/releases/components/app_edit_new_spec.js @@ -1,15 +1,15 @@ import Vuex from 'vuex'; import { mount } from '@vue/test-utils'; -import ReleaseEditApp from '~/releases/components/app_edit.vue'; +import { merge } from 'lodash'; +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +import ReleaseEditNewApp from '~/releases/components/app_edit_new.vue'; import { release as originalRelease, milestones as originalMilestones } from '../mock_data'; import * as commonUtils from '~/lib/utils/common_utils'; import { BACK_URL_PARAM } from '~/releases/constants'; import AssetLinksForm from '~/releases/components/asset_links_form.vue'; -import { merge } from 'lodash'; -import axios from 'axios'; -import MockAdapter from 'axios-mock-adapter'; -describe('Release edit component', () => { +describe('Release edit/new component', () => { let wrapper; let release; let actions; @@ -27,13 +27,14 @@ describe('Release edit component', () => { }; actions = { - fetchRelease: jest.fn(), - updateRelease: jest.fn(), + initializeRelease: jest.fn(), + saveRelease: jest.fn(), addEmptyAssetLink: jest.fn(), }; getters = { isValid: () => true, + isExistingRelease: () => true, validationErrors: () => ({ assets: { links: [], @@ -57,12 +58,14 @@ describe('Release edit component', () => { ), ); - wrapper = mount(ReleaseEditApp, { + wrapper = mount(ReleaseEditNewApp, { store, provide: { glFeatures: featureFlags, }, }); + + wrapper.element.querySelectorAll('input').forEach(input => jest.spyOn(input, 'focus')); }; beforeEach(() => { @@ -80,14 +83,23 @@ describe('Release edit component', () => { }); const findSubmitButton = () => wrapper.find('button[type=submit]'); + const findForm = () => wrapper.find('form'); describe(`basic functionality tests: all tests unrelated to the "${BACK_URL_PARAM}" parameter`, () => { - beforeEach(() => { - factory(); + beforeEach(factory); + + it('calls initializeRelease when the component is created', () => { + expect(actions.initializeRelease).toHaveBeenCalledTimes(1); }); - it('calls fetchRelease when the component is created', () => { - expect(actions.fetchRelease).toHaveBeenCalledTimes(1); + it('focuses the first non-disabled input element once the page is shown', () => { + const firstEnabledInput = wrapper.element.querySelector('input:enabled'); + const allInputs = wrapper.element.querySelectorAll('input'); + + allInputs.forEach(input => { + const expectedFocusCalls = input === firstEnabledInput ? 1 : 0; + expect(input.focus).toHaveBeenCalledTimes(expectedFocusCalls); + }); }); it('renders the description text at the top of the page', () => { @@ -96,28 +108,6 @@ describe('Release edit component', () => { ); }); - it('renders the correct tag name in the "Tag name" field', () => { - expect(wrapper.find('#git-ref').element.value).toBe(release.tagName); - }); - - it('renders the correct help text under the "Tag name" field', () => { - const helperText = wrapper.find('#tag-name-help'); - const helperTextLink = helperText.find('a'); - const helperTextLinkAttrs = helperTextLink.attributes(); - - expect(helperText.text()).toBe( - 'Changing a Release tag is only supported via Releases API. More information', - ); - expect(helperTextLink.text()).toBe('More information'); - expect(helperTextLinkAttrs).toEqual( - expect.objectContaining({ - href: state.updateReleaseApiDocsPath, - rel: 'noopener noreferrer', - target: '_blank', - }), - ); - }); - it('renders the correct release title in the "Release title" field', () => { expect(wrapper.find('#release-title').element.value).toBe(release.name); }); @@ -130,16 +120,15 @@ describe('Release edit component', () => { expect(findSubmitButton().attributes('type')).toBe('submit'); }); - it('calls updateRelease when the form is submitted', () => { - wrapper.find('form').trigger('submit'); - expect(actions.updateRelease).toHaveBeenCalledTimes(1); + it('calls saveRelease when the form is submitted', () => { + findForm().trigger('submit'); + + expect(actions.saveRelease).toHaveBeenCalledTimes(1); }); }); describe(`when the URL does not contain a "${BACK_URL_PARAM}" parameter`, () => { - beforeEach(() => { - factory(); - }); + beforeEach(factory); it(`renders a "Cancel" button with an href pointing to "${BACK_URL_PARAM}"`, () => { const cancelButton = wrapper.find('.js-cancel-button'); @@ -164,6 +153,34 @@ describe('Release edit component', () => { }); }); + describe('when creating a new release', () => { + beforeEach(() => { + factory({ + store: { + modules: { + detail: { + getters: { + isExistingRelease: () => false, + }, + }, + }, + }, + }); + }); + + it('renders the submit button with the text "Create release"', () => { + expect(findSubmitButton().text()).toBe('Create release'); + }); + }); + + describe('when editing an existing release', () => { + beforeEach(factory); + + it('renders the submit button with the text "Save changes"', () => { + expect(findSubmitButton().text()).toBe('Save changes'); + }); + }); + describe('asset links form', () => { const findAssetLinksForm = () => wrapper.find(AssetLinksForm); @@ -227,6 +244,12 @@ describe('Release edit component', () => { it('renders the submit button as disabled', () => { expect(findSubmitButton().attributes('disabled')).toBe('disabled'); }); + + it('does not allow the form to be submitted', () => { + findForm().trigger('submit'); + + expect(actions.saveRelease).not.toHaveBeenCalled(); + }); }); }); }); diff --git a/spec/frontend/releases/components/app_index_spec.js b/spec/frontend/releases/components/app_index_spec.js index 91beb5b1418..8eafe07cb2f 100644 --- a/spec/frontend/releases/components/app_index_spec.js +++ b/spec/frontend/releases/components/app_index_spec.js @@ -1,6 +1,7 @@ import { range as rge } from 'lodash'; import Vue from 'vue'; import { mountComponentWithStore } from 'helpers/vue_mount_component_helper'; +import waitForPromises from 'helpers/wait_for_promises'; import app from '~/releases/components/app_index.vue'; import createStore from '~/releases/stores'; import listModule from '~/releases/stores/modules/list'; @@ -13,7 +14,6 @@ import { releases, } from '../mock_data'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -import waitForPromises from 'helpers/wait_for_promises'; describe('Releases App ', () => { const Component = Vue.extend(app); diff --git a/spec/frontend/releases/components/app_new_spec.js b/spec/frontend/releases/components/app_new_spec.js deleted file mode 100644 index 0d5664766e5..00000000000 --- a/spec/frontend/releases/components/app_new_spec.js +++ /dev/null @@ -1,26 +0,0 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; -import { mount } from '@vue/test-utils'; -import ReleaseNewApp from '~/releases/components/app_new.vue'; - -Vue.use(Vuex); - -describe('Release new component', () => { - let wrapper; - - const factory = () => { - const store = new Vuex.Store(); - wrapper = mount(ReleaseNewApp, { store }); - }; - - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - - it('renders the app', () => { - factory(); - - expect(wrapper.exists()).toBe(true); - }); -}); diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js index 3dc9964c25c..e757fe98661 100644 --- a/spec/frontend/releases/components/app_show_spec.js +++ b/spec/frontend/releases/components/app_show_spec.js @@ -1,8 +1,8 @@ import Vuex from 'vuex'; import { shallowMount } from '@vue/test-utils'; +import { GlSkeletonLoading } from '@gitlab/ui'; import ReleaseShowApp from '~/releases/components/app_show.vue'; import { release as originalRelease } from '../mock_data'; -import { GlSkeletonLoading } from '@gitlab/ui'; import ReleaseBlock from '~/releases/components/release_block.vue'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js index e1f8592270e..727d593d851 100644 --- a/spec/frontend/releases/components/asset_links_form_spec.js +++ b/spec/frontend/releases/components/asset_links_form_spec.js @@ -3,6 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils'; import AssetLinksForm from '~/releases/components/asset_links_form.vue'; import { release as originalRelease } from '../mock_data'; import * as commonUtils from '~/lib/utils/common_utils'; +import { ENTER_KEY } from '~/lib/utils/keys'; import { ASSET_LINK_TYPE, DEFAULT_ASSET_LINK_TYPE } from '~/releases/constants'; const localVue = createLocalVue(); @@ -91,42 +92,128 @@ describe('Release edit component', () => { expect(actions.removeAssetLink).toHaveBeenCalledTimes(1); }); - it('calls the "updateAssetLinkUrl" store method when text is entered into the "URL" input field', () => { - const linkIdToUpdate = release.assets.links[0].id; - const newUrl = 'updated url'; + describe('URL input field', () => { + let input; + let linkIdToUpdate; + let newUrl; - expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled(); + beforeEach(() => { + input = wrapper.find({ ref: 'urlInput' }).element; + linkIdToUpdate = release.assets.links[0].id; + newUrl = 'updated url'; + }); - wrapper.find({ ref: 'urlInput' }).vm.$emit('change', newUrl); + const expectStoreMethodNotToBeCalled = () => { + expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled(); + }; - expect(actions.updateAssetLinkUrl).toHaveBeenCalledTimes(1); - expect(actions.updateAssetLinkUrl).toHaveBeenCalledWith( - expect.anything(), - { - linkIdToUpdate, - newUrl, - }, - undefined, - ); + const dispatchKeydowEvent = eventParams => { + const event = new KeyboardEvent('keydown', eventParams); + + input.dispatchEvent(event); + }; + + const expectStoreMethodToBeCalled = () => { + expect(actions.updateAssetLinkUrl).toHaveBeenCalledTimes(1); + expect(actions.updateAssetLinkUrl).toHaveBeenCalledWith( + expect.anything(), + { + linkIdToUpdate, + newUrl, + }, + undefined, + ); + }; + + it('calls the "updateAssetLinkUrl" store method when text is entered into the "URL" input field', () => { + expectStoreMethodNotToBeCalled(); + + wrapper.find({ ref: 'urlInput' }).vm.$emit('change', newUrl); + + expectStoreMethodToBeCalled(); + }); + + it('calls the "updateAssetLinkUrl" store method when Ctrl+Enter is pressed inside the "URL" input field', () => { + expectStoreMethodNotToBeCalled(); + + input.value = newUrl; + + dispatchKeydowEvent({ key: ENTER_KEY, ctrlKey: true }); + + expectStoreMethodToBeCalled(); + }); + + it('calls the "updateAssetLinkUrl" store method when Cmd+Enter is pressed inside the "URL" input field', () => { + expectStoreMethodNotToBeCalled(); + + input.value = newUrl; + + dispatchKeydowEvent({ key: ENTER_KEY, metaKey: true }); + + expectStoreMethodToBeCalled(); + }); }); - it('calls the "updateAssetLinkName" store method when text is entered into the "Link title" input field', () => { - const linkIdToUpdate = release.assets.links[0].id; - const newName = 'updated name'; + describe('Link title field', () => { + let input; + let linkIdToUpdate; + let newName; - expect(actions.updateAssetLinkName).not.toHaveBeenCalled(); + beforeEach(() => { + input = wrapper.find({ ref: 'nameInput' }).element; + linkIdToUpdate = release.assets.links[0].id; + newName = 'updated name'; + }); - wrapper.find({ ref: 'nameInput' }).vm.$emit('change', newName); + const expectStoreMethodNotToBeCalled = () => { + expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled(); + }; - expect(actions.updateAssetLinkName).toHaveBeenCalledTimes(1); - expect(actions.updateAssetLinkName).toHaveBeenCalledWith( - expect.anything(), - { - linkIdToUpdate, - newName, - }, - undefined, - ); + const dispatchKeydowEvent = eventParams => { + const event = new KeyboardEvent('keydown', eventParams); + + input.dispatchEvent(event); + }; + + const expectStoreMethodToBeCalled = () => { + expect(actions.updateAssetLinkName).toHaveBeenCalledTimes(1); + expect(actions.updateAssetLinkName).toHaveBeenCalledWith( + expect.anything(), + { + linkIdToUpdate, + newName, + }, + undefined, + ); + }; + + it('calls the "updateAssetLinkName" store method when text is entered into the "Link title" input field', () => { + expectStoreMethodNotToBeCalled(); + + wrapper.find({ ref: 'nameInput' }).vm.$emit('change', newName); + + expectStoreMethodToBeCalled(); + }); + + it('calls the "updateAssetLinkName" store method when Ctrl+Enter is pressed inside the "Link title" input field', () => { + expectStoreMethodNotToBeCalled(); + + input.value = newName; + + dispatchKeydowEvent({ key: ENTER_KEY, ctrlKey: true }); + + expectStoreMethodToBeCalled(); + }); + + it('calls the "updateAssetLinkName" store method when Cmd+Enter is pressed inside the "Link title" input field', () => { + expectStoreMethodNotToBeCalled(); + + input.value = newName; + + dispatchKeydowEvent({ key: ENTER_KEY, metaKey: true }); + + expectStoreMethodToBeCalled(); + }); }); it('calls the "updateAssetLinkType" store method when an option is selected from the "Type" dropdown', () => { diff --git a/spec/frontend/releases/components/release_block_assets_spec.js b/spec/frontend/releases/components/release_block_assets_spec.js index a85532a8118..5e84290716c 100644 --- a/spec/frontend/releases/components/release_block_assets_spec.js +++ b/spec/frontend/releases/components/release_block_assets_spec.js @@ -1,10 +1,10 @@ import { mount } from '@vue/test-utils'; import { GlCollapse } from '@gitlab/ui'; +import { trimText } from 'helpers/text_helper'; +import { cloneDeep } from 'lodash'; import ReleaseBlockAssets from '~/releases/components/release_block_assets.vue'; import { ASSET_LINK_TYPE } from '~/releases/constants'; -import { trimText } from 'helpers/text_helper'; import { assets } from '../mock_data'; -import { cloneDeep } from 'lodash'; describe('Release block assets', () => { let wrapper; diff --git a/spec/frontend/releases/components/release_block_footer_spec.js b/spec/frontend/releases/components/release_block_footer_spec.js index b91cfb82b65..c066bfbf020 100644 --- a/spec/frontend/releases/components/release_block_footer_spec.js +++ b/spec/frontend/releases/components/release_block_footer_spec.js @@ -1,11 +1,11 @@ import { mount } from '@vue/test-utils'; import { GlLink } from '@gitlab/ui'; import { trimText } from 'helpers/text_helper'; +import { cloneDeep } from 'lodash'; import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue'; import Icon from '~/vue_shared/components/icon.vue'; import { release as originalRelease } from '../mock_data'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -import { cloneDeep } from 'lodash'; const mockFutureDate = new Date(9999, 0, 0).toISOString(); let mockIsFutureRelease = false; diff --git a/spec/frontend/releases/components/release_block_metadata_spec.js b/spec/frontend/releases/components/release_block_metadata_spec.js index cbe478bfa1f..6f184e45600 100644 --- a/spec/frontend/releases/components/release_block_metadata_spec.js +++ b/spec/frontend/releases/components/release_block_metadata_spec.js @@ -1,9 +1,9 @@ import { mount } from '@vue/test-utils'; import { trimText } from 'helpers/text_helper'; +import { cloneDeep } from 'lodash'; import ReleaseBlockMetadata from '~/releases/components/release_block_metadata.vue'; import { release as originalRelease } from '../mock_data'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -import { cloneDeep } from 'lodash'; const mockFutureDate = new Date(9999, 0, 0).toISOString(); let mockIsFutureRelease = false; diff --git a/spec/frontend/releases/components/tag_field_exsting_spec.js b/spec/frontend/releases/components/tag_field_exsting_spec.js new file mode 100644 index 00000000000..0a04f68bd67 --- /dev/null +++ b/spec/frontend/releases/components/tag_field_exsting_spec.js @@ -0,0 +1,78 @@ +import { GlFormInput } from '@gitlab/ui'; +import { shallowMount, mount } from '@vue/test-utils'; +import TagFieldExisting from '~/releases/components/tag_field_existing.vue'; +import createStore from '~/releases/stores'; +import createDetailModule from '~/releases/stores/modules/detail'; + +const TEST_TAG_NAME = 'test-tag-name'; +const TEST_DOCS_PATH = '/help/test/docs/path'; + +describe('releases/components/tag_field_existing', () => { + let store; + let wrapper; + + const createComponent = (mountFn = shallowMount) => { + wrapper = mountFn(TagFieldExisting, { + store, + }); + }; + + const findInput = () => wrapper.find(GlFormInput); + const findHelp = () => wrapper.find('[data-testid="tag-name-help"]'); + const findHelpLink = () => { + const link = findHelp().find('a'); + + return { + text: link.text(), + href: link.attributes('href'), + target: link.attributes('target'), + }; + }; + + beforeEach(() => { + store = createStore({ + modules: { + detail: createDetailModule({ + updateReleaseApiDocsPath: TEST_DOCS_PATH, + tagName: TEST_TAG_NAME, + }), + }, + }); + + store.state.detail.release = { + tagName: TEST_TAG_NAME, + }; + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('default', () => { + it('shows the tag name', () => { + createComponent(); + + expect(findInput().attributes()).toMatchObject({ + disabled: '', + value: TEST_TAG_NAME, + }); + }); + + it('shows help', () => { + createComponent(mount); + + expect(findHelp().text()).toMatchInterpolatedText( + 'Changing a Release tag is only supported via Releases API. More information', + ); + + const helpLink = findHelpLink(); + + expect(helpLink).toEqual({ + text: 'More information', + href: TEST_DOCS_PATH, + target: '_blank', + }); + }); + }); +}); diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js new file mode 100644 index 00000000000..b6ebc496f33 --- /dev/null +++ b/spec/frontend/releases/components/tag_field_new_spec.js @@ -0,0 +1,144 @@ +import { mount, shallowMount } from '@vue/test-utils'; +import { GlFormInput } from '@gitlab/ui'; +import TagFieldNew from '~/releases/components/tag_field_new.vue'; +import createStore from '~/releases/stores'; +import createDetailModule from '~/releases/stores/modules/detail'; +import RefSelector from '~/ref/components/ref_selector.vue'; + +const TEST_TAG_NAME = 'test-tag-name'; +const TEST_PROJECT_ID = '1234'; +const TEST_CREATE_FROM = 'test-create-from'; + +describe('releases/components/tag_field_new', () => { + let store; + let wrapper; + + const createComponent = (mountFn = shallowMount) => { + wrapper = mountFn(TagFieldNew, { + store, + stubs: { + RefSelector: true, + }, + }); + }; + + beforeEach(() => { + store = createStore({ + modules: { + detail: createDetailModule({ + projectId: TEST_PROJECT_ID, + }), + }, + }); + + store.state.detail.createFrom = TEST_CREATE_FROM; + + store.state.detail.release = { + tagName: TEST_TAG_NAME, + assets: { + links: [], + }, + }; + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const findTagNameFormGroup = () => wrapper.find('[data-testid="tag-name-field"]'); + const findTagNameGlInput = () => findTagNameFormGroup().find(GlFormInput); + const findTagNameInput = () => findTagNameFormGroup().find('input'); + + const findCreateFromFormGroup = () => wrapper.find('[data-testid="create-from-field"]'); + const findCreateFromDropdown = () => findCreateFromFormGroup().find(RefSelector); + + describe('"Tag name" field', () => { + describe('rendering and behavior', () => { + beforeEach(() => createComponent()); + + it('renders a label', () => { + expect(findTagNameFormGroup().attributes().label).toBe('Tag name'); + }); + + describe('when the user updates the field', () => { + it("updates the store's release.tagName property", () => { + const updatedTagName = 'updated-tag-name'; + findTagNameGlInput().vm.$emit('input', updatedTagName); + + return wrapper.vm.$nextTick().then(() => { + expect(store.state.detail.release.tagName).toBe(updatedTagName); + }); + }); + }); + }); + + describe('validation', () => { + beforeEach(() => { + createComponent(mount); + }); + + /** + * Utility function to test the visibility of the validation message + * @param {'shown' | 'hidden'} state The expected state of the validation message. + * Should be passed either 'shown' or 'hidden' + */ + const expectValidationMessageToBe = state => { + return wrapper.vm.$nextTick().then(() => { + expect(findTagNameFormGroup().element).toHaveClass( + state === 'shown' ? 'is-invalid' : 'is-valid', + ); + expect(findTagNameFormGroup().element).not.toHaveClass( + state === 'shown' ? 'is-valid' : 'is-invalid', + ); + }); + }; + + describe('when the user has not yet interacted with the component', () => { + it('does not display a validation error', () => { + findTagNameInput().setValue(''); + + return expectValidationMessageToBe('hidden'); + }); + }); + + describe('when the user has interacted with the component and the value is not empty', () => { + it('does not display validation error', () => { + findTagNameInput().trigger('blur'); + + return expectValidationMessageToBe('hidden'); + }); + }); + + describe('when the user has interacted with the component and the value is empty', () => { + it('displays a validation error', () => { + const tagNameInput = findTagNameInput(); + + tagNameInput.setValue(''); + tagNameInput.trigger('blur'); + + return expectValidationMessageToBe('shown'); + }); + }); + }); + }); + + describe('"Create from" field', () => { + beforeEach(() => createComponent()); + + it('renders a label', () => { + expect(findCreateFromFormGroup().attributes().label).toBe('Create from'); + }); + + describe('when the user selects a git ref', () => { + it("updates the store's createFrom property", () => { + const updatedCreateFrom = 'update-create-from'; + findCreateFromDropdown().vm.$emit('input', updatedCreateFrom); + + return wrapper.vm.$nextTick().then(() => { + expect(store.state.detail.createFrom).toBe(updatedCreateFrom); + }); + }); + }); + }); +}); diff --git a/spec/frontend/releases/components/tag_field_spec.js b/spec/frontend/releases/components/tag_field_spec.js new file mode 100644 index 00000000000..c7909a2369b --- /dev/null +++ b/spec/frontend/releases/components/tag_field_spec.js @@ -0,0 +1,59 @@ +import { shallowMount } from '@vue/test-utils'; +import TagField from '~/releases/components/tag_field.vue'; +import TagFieldNew from '~/releases/components/tag_field_new.vue'; +import TagFieldExisting from '~/releases/components/tag_field_existing.vue'; +import createStore from '~/releases/stores'; +import createDetailModule from '~/releases/stores/modules/detail'; + +describe('releases/components/tag_field', () => { + let store; + let wrapper; + + const createComponent = ({ tagName }) => { + store = createStore({ + modules: { + detail: createDetailModule({}), + }, + }); + + store.state.detail.tagName = tagName; + + wrapper = shallowMount(TagField, { store }); + }; + + const findTagFieldNew = () => wrapper.find(TagFieldNew); + const findTagFieldExisting = () => wrapper.find(TagFieldExisting); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('when an existing release is being edited', () => { + beforeEach(() => { + createComponent({ tagName: 'v1.0' }); + }); + + it('renders the TagFieldExisting component', () => { + expect(findTagFieldExisting().exists()).toBe(true); + }); + + it('does not render the TagFieldNew component', () => { + expect(findTagFieldNew().exists()).toBe(false); + }); + }); + + describe('when a new release is being created', () => { + beforeEach(() => { + createComponent({ tagName: null }); + }); + + it('renders the TagFieldNew component', () => { + expect(findTagFieldNew().exists()).toBe(true); + }); + + it('does not render the TagFieldExisting component', () => { + expect(findTagFieldExisting().exists()).toBe(false); + }); + }); +}); |