diff options
Diffstat (limited to 'spec/frontend/issuable')
5 files changed, 101 insertions, 63 deletions
diff --git a/spec/frontend/issuable/components/issue_milestone_spec.js b/spec/frontend/issuable/components/issue_milestone_spec.js index 44416676180..9d67f602136 100644 --- a/spec/frontend/issuable/components/issue_milestone_spec.js +++ b/spec/frontend/issuable/components/issue_milestone_spec.js @@ -1,6 +1,6 @@ import { GlIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { mockMilestone } from 'jest/boards/mock_data'; import IssueMilestone from '~/issuable/components/issue_milestone.vue'; @@ -19,12 +19,12 @@ describe('IssueMilestoneComponent', () => { let wrapper; let vm; - beforeEach((done) => { + beforeEach(async () => { wrapper = createComponent(); ({ vm } = wrapper); - Vue.nextTick(done); + await nextTick(); }); afterEach(() => { @@ -37,7 +37,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, start_date: '' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.isMilestoneStarted).toBe(false); }); @@ -46,7 +46,7 @@ describe('IssueMilestoneComponent', () => { await wrapper.setProps({ milestone: { ...mockMilestone, start_date: '1990-07-22' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.isMilestoneStarted).toBe(true); }); @@ -57,7 +57,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, due_date: '' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.isMilestonePastDue).toBe(false); }); @@ -80,7 +80,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, due_date: '' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.milestoneDatesAbsolute).toBe('(January 1, 2018)'); }); @@ -89,7 +89,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, start_date: '', due_date: '' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.milestoneDatesAbsolute).toBe(''); }); @@ -100,7 +100,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, due_date: `${new Date().getFullYear() + 10}-01-01` }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.milestoneDatesHuman).toContain('years remaining'); }); @@ -109,7 +109,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, start_date: '1990-07-22', due_date: '' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.milestoneDatesHuman).toContain('Started'); }); @@ -122,7 +122,7 @@ describe('IssueMilestoneComponent', () => { due_date: '', }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.milestoneDatesHuman).toContain('Starts'); }); @@ -131,7 +131,7 @@ describe('IssueMilestoneComponent', () => { wrapper.setProps({ milestone: { ...mockMilestone, start_date: '', due_date: '' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.milestoneDatesHuman).toBe(''); }); diff --git a/spec/frontend/issuable/components/related_issuable_item_spec.js b/spec/frontend/issuable/components/related_issuable_item_spec.js index 6a896ccd21a..6b48f83041a 100644 --- a/spec/frontend/issuable/components/related_issuable_item_spec.js +++ b/spec/frontend/issuable/components/related_issuable_item_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import IssueDueDate from '~/boards/components/issue_due_date.vue'; import { formatDate } from '~/lib/utils/datetime_utility'; @@ -105,7 +106,7 @@ describe('RelatedIssuableItem', () => { state: 'closed', closedAt: '2018-12-01T00:00:00.00Z', }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true); }); @@ -140,7 +141,7 @@ describe('RelatedIssuableItem', () => { closedAt: '2018-12-01T00:00:00.00Z', }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(IssueDueDate).props('closed')).toBe(true); }); @@ -172,14 +173,14 @@ describe('RelatedIssuableItem', () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ removeDisabled: true }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findRemoveButton().attributes('disabled')).toEqual('disabled'); }); it('triggers onRemoveRequest when clicked', async () => { findRemoveButton().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); const { relatedIssueRemoveRequest } = wrapper.emitted(); expect(relatedIssueRemoveRequest.length).toBe(1); diff --git a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js index ff6922989cb..ce98a16dbb7 100644 --- a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js +++ b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js @@ -1,4 +1,6 @@ +import { GlFormGroup } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue'; import IssueToken from '~/related_issues/components/issue_token.vue'; import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants'; @@ -152,6 +154,30 @@ describe('AddIssuableForm', () => { }); }); + describe('categorized issuables', () => { + it.each` + issuableType | pathIdSeparator | contextHeader | contextFooter + ${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issue(s)'} + ${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epic(s)'} + `( + 'show header text as "$contextHeader" and footer text as "$contextFooter" issuableType is set to $issuableType', + ({ issuableType, contextHeader, contextFooter }) => { + wrapper = shallowMount(AddIssuableForm, { + propsData: { + issuableType, + inputValue: '', + showCategorizedIssues: true, + pathIdSeparator, + pendingReferences: [], + }, + }); + + expect(wrapper.findComponent(GlFormGroup).attributes('label')).toBe(contextHeader); + expect(wrapper.find('p.bold').text()).toContain(contextFooter); + }, + ); + }); + describe('when it is a Linked Issues form', () => { beforeEach(() => { wrapper = mount(AddIssuableForm, { @@ -194,63 +220,55 @@ describe('AddIssuableForm', () => { }); describe('when the form is submitted', () => { - it('emits an event with a "relates_to" link type when the "relates to" radio input selected', (done) => { + it('emits an event with a "relates_to" link type when the "relates to" radio input selected', async () => { jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); wrapper.vm.linkedIssueType = linkedIssueTypesMap.RELATES_TO; wrapper.vm.onFormSubmit(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { - pendingReferences: '', - linkedIssueType: linkedIssueTypesMap.RELATES_TO, - }); - done(); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { + pendingReferences: '', + linkedIssueType: linkedIssueTypesMap.RELATES_TO, }); }); - it('emits an event with a "blocks" link type when the "blocks" radio input selected', (done) => { + it('emits an event with a "blocks" link type when the "blocks" radio input selected', async () => { jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); wrapper.vm.linkedIssueType = linkedIssueTypesMap.BLOCKS; wrapper.vm.onFormSubmit(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { - pendingReferences: '', - linkedIssueType: linkedIssueTypesMap.BLOCKS, - }); - done(); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { + pendingReferences: '', + linkedIssueType: linkedIssueTypesMap.BLOCKS, }); }); - it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', (done) => { + it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', async () => { jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); wrapper.vm.linkedIssueType = linkedIssueTypesMap.IS_BLOCKED_BY; wrapper.vm.onFormSubmit(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { - pendingReferences: '', - linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY, - }); - done(); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { + pendingReferences: '', + linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY, }); }); - it('shows error message when error is present', (done) => { + it('shows error message when error is present', async () => { const itemAddFailureMessage = 'Something went wrong while submitting.'; wrapper.setProps({ hasError: true, itemAddFailureMessage, }); - wrapper.vm.$nextTick(() => { - expect(wrapper.find('.gl-field-error').exists()).toBe(true); - expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage); - done(); - }); + await nextTick(); + expect(wrapper.find('.gl-field-error').exists()).toBe(true); + expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage); }); }); }); diff --git a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js index 608fec45bbd..c7925034eb0 100644 --- a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js +++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js @@ -7,6 +7,7 @@ import { } from 'jest/issuable/components/related_issuable_mock_data'; import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue'; import { + issuableTypesMap, linkedIssueTypesMap, linkedIssueTypesTextMap, PathIdSeparator, @@ -29,14 +30,34 @@ describe('RelatedIssuesBlock', () => { wrapper = mount(RelatedIssuesBlock, { propsData: { pathIdSeparator: PathIdSeparator.Issue, - issuableType: 'issue', + issuableType: issuableTypesMap.ISSUE, }, }); }); - it('displays "Linked issues" in the header', () => { - expect(wrapper.find('.card-title').text()).toContain('Linked issues'); - }); + it.each` + issuableType | pathIdSeparator | titleText | helpLinkText | addButtonText + ${'issue'} | ${PathIdSeparator.Issue} | ${'Linked issues'} | ${'Read more about related issues'} | ${'Add a related issue'} + ${'epic'} | ${PathIdSeparator.Epic} | ${'Linked epics'} | ${'Read more about related epics'} | ${'Add a related epic'} + `( + 'displays "$titleText" in the header, "$helpLinkText" aria-label for help link, and "$addButtonText" aria-label for add button when issuableType is set to "$issuableType"', + ({ issuableType, pathIdSeparator, titleText, helpLinkText, addButtonText }) => { + wrapper = mount(RelatedIssuesBlock, { + propsData: { + pathIdSeparator, + issuableType, + canAdmin: true, + helpPath: '/help/user/project/issues/related_issues', + }, + }); + + expect(wrapper.find('.card-title').text()).toContain(titleText); + expect(wrapper.find('[data-testid="help-link"]').attributes('aria-label')).toBe( + helpLinkText, + ); + expect(findIssueCountBadgeAddButton().attributes('aria-label')).toBe(addButtonText); + }, + ); it('unable to add new related issues', () => { expect(findIssueCountBadgeAddButton().exists()).toBe(false); diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js index 01de4da7900..b59717a1f60 100644 --- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js +++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js @@ -1,5 +1,6 @@ import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import { defaultProps, @@ -210,40 +211,37 @@ describe('RelatedIssuesRoot', () => { }), ); - it('when canceling and hiding add issuable form', () => { + it('when canceling and hiding add issuable form', async () => { wrapper.vm.onPendingFormCancel(); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.isFormVisible).toEqual(false); - expect(wrapper.vm.inputValue).toEqual(''); - expect(wrapper.vm.state.pendingReferences).toHaveLength(0); - }); + await nextTick(); + expect(wrapper.vm.isFormVisible).toEqual(false); + expect(wrapper.vm.inputValue).toEqual(''); + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); }); }); describe('fetchRelatedIssues', () => { beforeEach(() => createComponent()); - it('sets isFetching while fetching', () => { + it('sets isFetching while fetching', async () => { wrapper.vm.fetchRelatedIssues(); expect(wrapper.vm.isFetching).toEqual(true); - return waitForPromises().then(() => { - expect(wrapper.vm.isFetching).toEqual(false); - }); + await waitForPromises(); + expect(wrapper.vm.isFetching).toEqual(false); }); - it('should fetch related issues', () => { + it('should fetch related issues', async () => { mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]); wrapper.vm.fetchRelatedIssues(); - return waitForPromises().then(() => { - expect(wrapper.vm.state.relatedIssues).toHaveLength(2); - expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); - expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id); - }); + await waitForPromises(); + expect(wrapper.vm.state.relatedIssues).toHaveLength(2); + expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); + expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id); }); }); |