summaryrefslogtreecommitdiff
path: root/spec/frontend/issuable/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/issuable/components')
-rw-r--r--spec/frontend/issuable/components/csv_export_modal_spec.js91
-rw-r--r--spec/frontend/issuable/components/csv_import_export_buttons_spec.js187
-rw-r--r--spec/frontend/issuable/components/csv_import_modal_spec.js86
3 files changed, 364 insertions, 0 deletions
diff --git a/spec/frontend/issuable/components/csv_export_modal_spec.js b/spec/frontend/issuable/components/csv_export_modal_spec.js
new file mode 100644
index 00000000000..f46b6f72f05
--- /dev/null
+++ b/spec/frontend/issuable/components/csv_export_modal_spec.js
@@ -0,0 +1,91 @@
+import { GlModal, GlIcon, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CsvExportModal from '~/issuable/components/csv_export_modal.vue';
+
+describe('CsvExportModal', () => {
+ let wrapper;
+
+ function createComponent(options = {}) {
+ const { injectedProperties = {}, props = {} } = options;
+ return extendedWrapper(
+ mount(CsvExportModal, {
+ propsData: {
+ modalId: 'csv-export-modal',
+ ...props,
+ },
+ provide: {
+ issuableType: 'issues',
+ ...injectedProperties,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ }),
+ );
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ describe('template', () => {
+ describe.each`
+ issuableType | modalTitle
+ ${'issues'} | ${'Export issues'}
+ ${'merge-requests'} | ${'Export merge requests'}
+ `('with the issuableType "$issuableType"', ({ issuableType, modalTitle }) => {
+ beforeEach(() => {
+ wrapper = createComponent({ injectedProperties: { issuableType } });
+ });
+
+ it('displays the modal title "$modalTitle"', () => {
+ expect(findModal().text()).toContain(modalTitle);
+ });
+
+ it('displays the button with title "$modalTitle"', () => {
+ expect(findButton().text()).toBe(modalTitle);
+ });
+ });
+
+ describe('issuable count info text', () => {
+ it('displays the info text when issuableCount is > -1', () => {
+ wrapper = createComponent({ injectedProperties: { issuableCount: 10 } });
+ expect(wrapper.findByTestId('issuable-count-note').exists()).toBe(true);
+ expect(wrapper.findByTestId('issuable-count-note').text()).toContain('10 issues selected');
+ expect(findIcon().exists()).toBe(true);
+ });
+
+ it("doesn't display the info text when issuableCount is -1", () => {
+ wrapper = createComponent({ injectedProperties: { issuableCount: -1 } });
+ expect(wrapper.findByTestId('issuable-count-note').exists()).toBe(false);
+ });
+ });
+
+ describe('email info text', () => {
+ it('displays the proper email', () => {
+ const email = 'admin@example.com';
+ wrapper = createComponent({ injectedProperties: { email } });
+ expect(findModal().text()).toContain(
+ `The CSV export will be created in the background. Once finished, it will be sent to ${email} in an attachment.`,
+ );
+ });
+ });
+
+ describe('primary button', () => {
+ it('passes the exportCsvPath to the button', () => {
+ const exportCsvPath = '/gitlab-org/gitlab-test/-/issues/export_csv';
+ wrapper = createComponent({ injectedProperties: { exportCsvPath } });
+ expect(findButton().attributes('href')).toBe(exportCsvPath);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
new file mode 100644
index 00000000000..e32bf35b13a
--- /dev/null
+++ b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
@@ -0,0 +1,187 @@
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CsvExportModal from '~/issuable/components/csv_export_modal.vue';
+import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
+import CsvImportModal from '~/issuable/components/csv_import_modal.vue';
+
+describe('CsvImportExportButtons', () => {
+ let wrapper;
+ let glModalDirective;
+
+ function createComponent(injectedProperties = {}) {
+ glModalDirective = jest.fn();
+ return extendedWrapper(
+ shallowMount(CsvImportExportButtons, {
+ directives: {
+ GlTooltip: createMockDirective(),
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
+ },
+ },
+ },
+ provide: {
+ ...injectedProperties,
+ },
+ }),
+ );
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findExportCsvButton = () => wrapper.findByTestId('export-csv-button');
+ const findImportDropdown = () => wrapper.findByTestId('import-csv-dropdown');
+ const findImportCsvButton = () => wrapper.findByTestId('import-csv-dropdown');
+ const findImportFromJiraLink = () => wrapper.findByTestId('import-from-jira-link');
+ const findExportCsvModal = () => wrapper.findComponent(CsvExportModal);
+ const findImportCsvModal = () => wrapper.findComponent(CsvImportModal);
+
+ describe('template', () => {
+ describe('when the showExportButton=true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showExportButton: true });
+ });
+
+ it('displays the export button', () => {
+ expect(findExportCsvButton().exists()).toBe(true);
+ });
+
+ it('export button has a tooltip', () => {
+ const tooltip = getBinding(findExportCsvButton().element, 'gl-tooltip');
+
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value).toBe('Export as CSV');
+ });
+
+ it('renders the export modal', () => {
+ expect(findExportCsvModal().exists()).toBe(true);
+ });
+
+ it('opens the export modal', () => {
+ findExportCsvButton().trigger('click');
+
+ expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.exportModalId);
+ });
+ });
+
+ describe('when the showExportButton=false', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showExportButton: false });
+ });
+
+ it('does not display the export button', () => {
+ expect(findExportCsvButton().exists()).toBe(false);
+ });
+
+ it('does not render the export modal', () => {
+ expect(findExportCsvModal().exists()).toBe(false);
+ });
+ });
+
+ describe('when the showImportButton=true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showImportButton: true });
+ });
+
+ it('displays the import dropdown', () => {
+ expect(findImportDropdown().exists()).toBe(true);
+ });
+
+ it('renders the import button', () => {
+ expect(findImportCsvButton().exists()).toBe(true);
+ });
+
+ describe('when showLabel=false', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showImportButton: true, showLabel: false });
+ });
+
+ it('does not have a button text', () => {
+ expect(findImportCsvButton().props('text')).toBe(null);
+ });
+
+ it('import button has a tooltip', () => {
+ const tooltip = getBinding(findImportDropdown().element, 'gl-tooltip');
+
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value).toBe('Import issues');
+ });
+ });
+
+ describe('when showLabel=true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showImportButton: true, showLabel: true });
+ });
+
+ it('displays a button text', () => {
+ expect(findImportCsvButton().props('text')).toBe('Import issues');
+ });
+
+ it('import button has no tooltip', () => {
+ const tooltip = getBinding(findImportDropdown().element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(null);
+ });
+ });
+
+ it('renders the import modal', () => {
+ expect(findImportCsvModal().exists()).toBe(true);
+ });
+
+ it('opens the import modal', () => {
+ findImportCsvButton().trigger('click');
+
+ expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.importModalId);
+ });
+
+ describe('import from jira link', () => {
+ const projectImportJiraPath = 'gitlab-org/gitlab-test/-/import/jira';
+
+ beforeEach(() => {
+ wrapper = createComponent({
+ showImportButton: true,
+ canEdit: true,
+ projectImportJiraPath,
+ });
+ });
+
+ describe('when canEdit=true', () => {
+ it('renders the import dropdown item', () => {
+ expect(findImportFromJiraLink().exists()).toBe(true);
+ });
+
+ it('passes the proper path to the link', () => {
+ expect(findImportFromJiraLink().attributes('href')).toBe(projectImportJiraPath);
+ });
+ });
+
+ describe('when canEdit=false', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showImportButton: true, canEdit: false });
+ });
+
+ it('does not render the import dropdown item', () => {
+ expect(findImportFromJiraLink().exists()).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('when the showImportButton=false', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ showImportButton: false });
+ });
+
+ it('does not display the import dropdown', () => {
+ expect(findImportDropdown().exists()).toBe(false);
+ });
+
+ it('does not render the import modal', () => {
+ expect(findImportCsvModal().exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuable/components/csv_import_modal_spec.js b/spec/frontend/issuable/components/csv_import_modal_spec.js
new file mode 100644
index 00000000000..ce9d738f77b
--- /dev/null
+++ b/spec/frontend/issuable/components/csv_import_modal_spec.js
@@ -0,0 +1,86 @@
+import { GlModal } from '@gitlab/ui';
+import { getByRole, getByLabelText } from '@testing-library/dom';
+import { mount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CsvImportModal from '~/issuable/components/csv_import_modal.vue';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+
+describe('CsvImportModal', () => {
+ let wrapper;
+ let formSubmitSpy;
+
+ function createComponent(options = {}) {
+ const { injectedProperties = {}, props = {} } = options;
+ return extendedWrapper(
+ mount(CsvImportModal, {
+ propsData: {
+ modalId: 'csv-import-modal',
+ ...props,
+ },
+ provide: {
+ issuableType: 'issues',
+ ...injectedProperties,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template: '<div><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ }),
+ );
+ }
+
+ beforeEach(() => {
+ formSubmitSpy = jest.spyOn(HTMLFormElement.prototype, 'submit').mockImplementation();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findPrimaryButton = () => getByRole(wrapper.element, 'button', { name: 'Import issues' });
+ const findForm = () => wrapper.findByTestId('import-csv-form');
+ const findFileInput = () => getByLabelText(wrapper.element, 'Upload CSV file');
+ const findAuthenticityToken = () => new FormData(findForm().element).get('authenticity_token');
+
+ describe('template', () => {
+ it('displays modal title', () => {
+ wrapper = createComponent();
+ expect(findModal().text()).toContain('Import issues');
+ });
+
+ it('displays a note about the maximum allowed file size', () => {
+ const maxAttachmentSize = 500;
+ wrapper = createComponent({ injectedProperties: { maxAttachmentSize } });
+ expect(findModal().text()).toContain(`The maximum file size allowed is ${maxAttachmentSize}`);
+ });
+
+ describe('form', () => {
+ const importCsvIssuesPath = 'gitlab-org/gitlab-test/-/issues/import_csv';
+
+ beforeEach(() => {
+ wrapper = createComponent({ injectedProperties: { importCsvIssuesPath } });
+ });
+
+ it('displays the form with the correct action and inputs', () => {
+ expect(findForm().exists()).toBe(true);
+ expect(findForm().attributes('action')).toBe(importCsvIssuesPath);
+ expect(findAuthenticityToken()).toBe('mock-csrf-token');
+ expect(findFileInput()).toExist();
+ });
+
+ it('displays the correct primary button action text', () => {
+ expect(findPrimaryButton()).toExist();
+ });
+
+ it('submits the form when the primary action is clicked', async () => {
+ findPrimaryButton().click();
+
+ expect(formSubmitSpy).toHaveBeenCalled();
+ });
+ });
+ });
+});