diff options
Diffstat (limited to 'spec/frontend/issuable')
5 files changed, 276 insertions, 13 deletions
diff --git a/spec/frontend/issuable/components/csv_export_modal_spec.js b/spec/frontend/issuable/components/csv_export_modal_spec.js index ad4abda6912..f798f87b6b2 100644 --- a/spec/frontend/issuable/components/csv_export_modal_spec.js +++ b/spec/frontend/issuable/components/csv_export_modal_spec.js @@ -1,7 +1,8 @@ -import { GlModal, GlIcon, GlButton } from '@gitlab/ui'; +import { GlModal, GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { stubComponent } from 'helpers/stub_component'; import CsvExportModal from '~/issuable/components/csv_export_modal.vue'; +import { __ } from '~/locale'; describe('CsvExportModal', () => { let wrapper; @@ -34,7 +35,6 @@ describe('CsvExportModal', () => { const findModal = () => wrapper.findComponent(GlModal); const findIcon = () => wrapper.findComponent(GlIcon); - const findButton = () => wrapper.findComponent(GlButton); describe('template', () => { describe.each` @@ -47,11 +47,25 @@ describe('CsvExportModal', () => { }); it('displays the modal title "$modalTitle"', () => { - expect(findModal().text()).toContain(modalTitle); + expect(findModal().props('title')).toBe(modalTitle); }); - it('displays the button with title "$modalTitle"', () => { - expect(findButton().text()).toBe(modalTitle); + it('displays the primary button with title "$modalTitle" and href', () => { + expect(findModal().props('actionPrimary')).toMatchObject({ + text: modalTitle, + attributes: { + href: 'export/csv/path', + variant: 'confirm', + 'data-method': 'post', + 'data-qa-selector': `export_${issuableType}_button`, + 'data-track-action': 'click_button', + 'data-track-label': `export_${issuableType}_csv`, + }, + }); + }); + + it('displays the cancel button', () => { + expect(findModal().props('actionCancel')).toEqual({ text: __('Cancel') }); }); }); @@ -72,13 +86,5 @@ describe('CsvExportModal', () => { ); }); }); - - describe('primary button', () => { - it('passes the exportCsvPath to the button', () => { - const exportCsvPath = '/gitlab-org/gitlab-test/-/issues/export_csv'; - wrapper = createComponent({ props: { exportCsvPath } }); - expect(findButton().attributes('href')).toBe(exportCsvPath); - }); - }); }); }); diff --git a/spec/frontend/issuable/components/csv_import_modal_spec.js b/spec/frontend/issuable/components/csv_import_modal_spec.js index f4636fd7e6a..6e954c91f46 100644 --- a/spec/frontend/issuable/components/csv_import_modal_spec.js +++ b/spec/frontend/issuable/components/csv_import_modal_spec.js @@ -76,6 +76,10 @@ describe('CsvImportModal', () => { expect(formSubmitSpy).toHaveBeenCalled(); }); + + it('displays the cancel button', () => { + expect(findModal().props('actionCancel')).toEqual({ text: __('Cancel') }); + }); }); }); }); diff --git a/spec/frontend/issuable/popover/components/issue_popover_spec.js b/spec/frontend/issuable/popover/components/issue_popover_spec.js new file mode 100644 index 00000000000..3e77e750f3a --- /dev/null +++ b/spec/frontend/issuable/popover/components/issue_popover_spec.js @@ -0,0 +1,81 @@ +import { GlSkeletonLoader } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import StatusBox from '~/issuable/components/status_box.vue'; +import IssuePopover from '~/issuable/popover/components/issue_popover.vue'; +import issueQuery from '~/issuable/popover/queries/issue.query.graphql'; + +describe('Issue Popover', () => { + let wrapper; + + Vue.use(VueApollo); + + const issueQueryResponse = { + data: { + project: { + __typename: 'Project', + id: '1', + issue: { + __typename: 'Issue', + id: 'gid://gitlab/Issue/1', + createdAt: '2020-07-01T04:08:01Z', + state: 'opened', + title: 'Issue title', + }, + }, + }, + }; + + const mountComponent = ({ + queryResponse = jest.fn().mockResolvedValue(issueQueryResponse), + } = {}) => { + wrapper = shallowMount(IssuePopover, { + apolloProvider: createMockApollo([[issueQuery, queryResponse]]), + propsData: { + target: document.createElement('a'), + projectPath: 'foo/bar', + iid: '1', + cachedTitle: 'Cached title', + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + it('shows skeleton-loader while apollo is loading', () => { + mountComponent(); + + expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true); + }); + + describe('when loaded', () => { + beforeEach(() => { + mountComponent(); + return waitForPromises(); + }); + + it('shows status badge', () => { + expect(wrapper.findComponent(StatusBox).props()).toEqual({ + issuableType: 'issue', + initialState: issueQueryResponse.data.project.issue.state, + }); + }); + + it('shows opened time', () => { + expect(wrapper.text()).toContain('Opened 4 days ago'); + }); + + it('shows title', () => { + expect(wrapper.find('h5').text()).toBe(issueQueryResponse.data.project.issue.title); + }); + + it('shows reference', () => { + expect(wrapper.text()).toContain('foo/bar#1'); + }); + }); +}); diff --git a/spec/frontend/issuable/popover/components/mr_popover_spec.js b/spec/frontend/issuable/popover/components/mr_popover_spec.js new file mode 100644 index 00000000000..5fdd1e6e8fc --- /dev/null +++ b/spec/frontend/issuable/popover/components/mr_popover_spec.js @@ -0,0 +1,119 @@ +import { GlSkeletonLoader } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import MRPopover from '~/issuable/popover/components/mr_popover.vue'; +import mergeRequestQuery from '~/issuable/popover/queries/merge_request.query.graphql'; +import CiIcon from '~/vue_shared/components/ci_icon.vue'; + +describe('MR Popover', () => { + let wrapper; + + Vue.use(VueApollo); + + const mrQueryResponse = { + data: { + project: { + __typename: 'Project', + id: '1', + mergeRequest: { + __typename: 'Merge Request', + id: 'gid://gitlab/Merge_Request/1', + createdAt: '2020-07-01T04:08:01Z', + state: 'opened', + title: 'MR title', + headPipeline: { + id: '1', + detailedStatus: { + id: '1', + icon: 'status_success', + group: 'success', + }, + }, + }, + }, + }, + }; + + const mrQueryResponseWithoutDetailedStatus = { + data: { + project: { + __typename: 'Project', + id: '1', + mergeRequest: { + __typename: 'Merge Request', + id: 'gid://gitlab/Merge_Request/1', + createdAt: '2020-07-01T04:08:01Z', + state: 'opened', + title: 'MR title', + headPipeline: { + id: '1', + detailedStatus: null, + }, + }, + }, + }, + }; + + const mountComponent = ({ + queryResponse = jest.fn().mockResolvedValue(mrQueryResponse), + } = {}) => { + wrapper = shallowMount(MRPopover, { + apolloProvider: createMockApollo([[mergeRequestQuery, queryResponse]]), + propsData: { + target: document.createElement('a'), + projectPath: 'foo/bar', + iid: '1', + cachedTitle: 'Cached Title', + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + it('shows skeleton-loader while apollo is loading', () => { + mountComponent(); + + expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true); + }); + + describe('when loaded', () => { + beforeEach(() => { + mountComponent(); + return waitForPromises(); + }); + + it('shows opened time', () => { + expect(wrapper.text()).toContain('Opened 4 days ago'); + }); + + it('shows title', () => { + expect(wrapper.find('h5').text()).toBe(mrQueryResponse.data.project.mergeRequest.title); + }); + + it('shows reference', () => { + expect(wrapper.text()).toContain('foo/bar!1'); + }); + + it('shows CI Icon if there is pipeline data', async () => { + expect(wrapper.findComponent(CiIcon).exists()).toBe(true); + }); + }); + + describe('without detailed status', () => { + beforeEach(() => { + mountComponent({ + queryResponse: jest.fn().mockResolvedValue(mrQueryResponseWithoutDetailedStatus), + }); + return waitForPromises(); + }); + + it('does not show CI icon if there is no pipeline data', async () => { + expect(wrapper.findComponent(CiIcon).exists()).toBe(false); + }); + }); +}); diff --git a/spec/frontend/issuable/popover/index_spec.js b/spec/frontend/issuable/popover/index_spec.js new file mode 100644 index 00000000000..b1aa7f0f0b0 --- /dev/null +++ b/spec/frontend/issuable/popover/index_spec.js @@ -0,0 +1,53 @@ +import { setHTMLFixture } from 'helpers/fixtures'; +import * as createDefaultClient from '~/lib/graphql'; +import initIssuablePopovers from '~/issuable/popover/index'; + +createDefaultClient.default = jest.fn(); + +describe('initIssuablePopovers', () => { + let mr1; + let mr2; + let mr3; + let issue1; + + beforeEach(() => { + setHTMLFixture(` + <div id="one" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project" data-reference-type="merge_request"> + MR1 + </div> + <div id="two" class="gfm-merge_request" title="title" data-iid="1" data-project-path="group/project" data-reference-type="merge_request"> + MR2 + </div> + <div id="three" class="gfm-merge_request"> + MR3 + </div> + <div id="four" class="gfm-issue" title="title" data-iid="1" data-project-path="group/project" data-reference-type="issue"> + MR3 + </div> + `); + + mr1 = document.querySelector('#one'); + mr2 = document.querySelector('#two'); + mr3 = document.querySelector('#three'); + issue1 = document.querySelector('#four'); + + mr1.addEventListener = jest.fn(); + mr2.addEventListener = jest.fn(); + mr3.addEventListener = jest.fn(); + issue1.addEventListener = jest.fn(); + }); + + it('does not add the same event listener twice', () => { + initIssuablePopovers([mr1, mr1, mr2, issue1]); + + expect(mr1.addEventListener).toHaveBeenCalledTimes(1); + expect(mr2.addEventListener).toHaveBeenCalledTimes(1); + expect(issue1.addEventListener).toHaveBeenCalledTimes(1); + }); + + it('does not add listener if it does not have the necessary data attributes', () => { + initIssuablePopovers([mr1, mr2, mr3]); + + expect(mr3.addEventListener).not.toHaveBeenCalled(); + }); +}); |