diff options
Diffstat (limited to 'spec/frontend/import_entities/import_groups')
7 files changed, 191 insertions, 39 deletions
diff --git a/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js new file mode 100644 index 00000000000..60f0780fdb3 --- /dev/null +++ b/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js @@ -0,0 +1,90 @@ +import { GlButton, GlIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import { STATUSES } from '~/import_entities/constants'; +import ImportActionsCell from '~/import_entities/import_groups/components/import_actions_cell.vue'; +import { generateFakeEntry } from '../graphql/fixtures'; + +describe('import actions cell', () => { + let wrapper; + + const createComponent = (props) => { + wrapper = shallowMount(ImportActionsCell, { + propsData: { + groupPathRegex: /^[a-zA-Z]+$/, + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when import status is NONE', () => { + beforeEach(() => { + const group = generateFakeEntry({ id: 1, status: STATUSES.NONE }); + createComponent({ group }); + }); + + it('renders import button', () => { + const button = wrapper.findComponent(GlButton); + expect(button.exists()).toBe(true); + expect(button.text()).toBe('Import'); + }); + + it('does not render icon with a hint', () => { + expect(wrapper.findComponent(GlIcon).exists()).toBe(false); + }); + }); + + describe('when import status is FINISHED', () => { + beforeEach(() => { + const group = generateFakeEntry({ id: 1, status: STATUSES.FINISHED }); + createComponent({ group }); + }); + + it('renders re-import button', () => { + const button = wrapper.findComponent(GlButton); + expect(button.exists()).toBe(true); + expect(button.text()).toBe('Re-import'); + }); + + it('renders icon with a hint', () => { + const icon = wrapper.findComponent(GlIcon); + expect(icon.exists()).toBe(true); + expect(icon.attributes().title).toBe( + 'Re-import creates a new group. It does not sync with the existing group.', + ); + }); + }); + + it('does not render import button when group import is in progress', () => { + const group = generateFakeEntry({ id: 1, status: STATUSES.STARTED }); + createComponent({ group }); + + const button = wrapper.findComponent(GlButton); + expect(button.exists()).toBe(false); + }); + + it('renders import button as disabled when there are validation errors', () => { + const group = generateFakeEntry({ + id: 1, + status: STATUSES.NONE, + validation_errors: [{ field: 'new_name', message: 'something ' }], + }); + createComponent({ group }); + + const button = wrapper.findComponent(GlButton); + expect(button.props().disabled).toBe(true); + }); + + it('emits import-group event when import button is clicked', () => { + const group = generateFakeEntry({ id: 1, status: STATUSES.NONE }); + createComponent({ group }); + + const button = wrapper.findComponent(GlButton); + button.vm.$emit('click'); + + expect(wrapper.emitted('import-group')).toHaveLength(1); + }); +}); diff --git a/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js new file mode 100644 index 00000000000..2a56efd1cbb --- /dev/null +++ b/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js @@ -0,0 +1,59 @@ +import { GlLink, GlSprintf } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import { STATUSES } from '~/import_entities/constants'; +import ImportSourceCell from '~/import_entities/import_groups/components/import_source_cell.vue'; +import { generateFakeEntry } from '../graphql/fixtures'; + +describe('import source cell', () => { + let wrapper; + let group; + + const createComponent = (props) => { + wrapper = shallowMount(ImportSourceCell, { + propsData: { + ...props, + }, + stubs: { GlSprintf }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when group status is NONE', () => { + beforeEach(() => { + group = generateFakeEntry({ id: 1, status: STATUSES.NONE }); + createComponent({ group }); + }); + + it('renders link to a group', () => { + const link = wrapper.findComponent(GlLink); + expect(link.attributes().href).toBe(group.web_url); + expect(link.text()).toContain(group.full_path); + }); + + it('does not render last imported line', () => { + expect(wrapper.text()).not.toContain('Last imported to'); + }); + }); + + describe('when group status is FINISHED', () => { + beforeEach(() => { + group = generateFakeEntry({ id: 1, status: STATUSES.FINISHED }); + createComponent({ group }); + }); + + it('renders link to a group', () => { + const link = wrapper.findComponent(GlLink); + expect(link.attributes().href).toBe(group.web_url); + expect(link.text()).toContain(group.full_path); + }); + + it('renders last imported line', () => { + expect(wrapper.text()).toMatchInterpolatedText( + 'fake_group_1 Last imported to root/last-group1', + ); + }); + }); +}); diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js index bbd8463e685..f43e545e049 100644 --- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js +++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js @@ -15,6 +15,7 @@ import stubChildren from 'helpers/stub_children'; import { stubComponent } from 'helpers/stub_component'; import waitForPromises from 'helpers/wait_for_promises'; import { STATUSES } from '~/import_entities/constants'; +import ImportActionsCell from '~/import_entities/import_groups/components/import_actions_cell.vue'; import ImportTable from '~/import_entities/import_groups/components/import_table.vue'; import ImportTargetCell from '~/import_entities/import_groups/components/import_target_cell.vue'; import importGroupsMutation from '~/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql'; @@ -163,11 +164,8 @@ describe('import table', () => { it('invokes importGroups mutation when row button is clicked', async () => { jest.spyOn(apolloProvider.defaultClient, 'mutate'); - const triggerImportButton = wrapper - .findAllComponents(GlButton) - .wrappers.find((w) => w.text() === 'Import'); - triggerImportButton.vm.$emit('click'); + wrapper.findComponent(ImportActionsCell).vm.$emit('import-group'); await waitForPromises(); expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({ mutation: importGroupsMutation, @@ -329,7 +327,7 @@ describe('import table', () => { }); it('does not allow selecting already started groups', async () => { - const NEW_GROUPS = [generateFakeEntry({ id: 1, status: STATUSES.FINISHED })]; + const NEW_GROUPS = [generateFakeEntry({ id: 1, status: STATUSES.STARTED })]; createComponent({ bulkImportSourceGroups: () => ({ diff --git a/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js index 8231297e594..be83a61841f 100644 --- a/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js +++ b/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js @@ -1,14 +1,10 @@ -import { GlButton, GlDropdownItem, GlLink, GlFormInput } from '@gitlab/ui'; +import { GlDropdownItem, GlFormInput } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; -import VueApollo from 'vue-apollo'; import ImportGroupDropdown from '~/import_entities/components/group_dropdown.vue'; import { STATUSES } from '~/import_entities/constants'; import ImportTargetCell from '~/import_entities/import_groups/components/import_target_cell.vue'; import { availableNamespacesFixture } from '../graphql/fixtures'; -Vue.use(VueApollo); - const getFakeGroup = (status) => ({ web_url: 'https://fake.host/', full_path: 'fake_group_1', @@ -26,9 +22,6 @@ describe('import target cell', () => { let wrapper; let group; - const findByText = (cmp, text) => { - return wrapper.findAll(cmp).wrappers.find((node) => node.text().indexOf(text) === 0); - }; const findNameInput = () => wrapper.find(GlFormInput); const findNamespaceDropdown = () => wrapper.find(ImportGroupDropdown); @@ -117,10 +110,6 @@ describe('import target cell', () => { createComponent({ group }); }); - it('does not render Import button', () => { - expect(findByText(GlButton, 'Import')).toBe(undefined); - }); - it('renders namespace dropdown as disabled', () => { expect(findNamespaceDropdown().attributes('disabled')).toBe('true'); }); @@ -132,17 +121,8 @@ describe('import target cell', () => { createComponent({ group }); }); - it('does not render Import button', () => { - expect(findByText(GlButton, 'Import')).toBe(undefined); - }); - - it('does not render namespace dropdown', () => { - expect(findNamespaceDropdown().exists()).toBe(false); - }); - - it('renders target as link', () => { - const TARGET_LINK = `${group.import_target.target_namespace}/${group.import_target.new_name}`; - expect(findByText(GlLink, TARGET_LINK).exists()).toBe(true); + it('renders namespace dropdown as enabled', () => { + expect(findNamespaceDropdown().attributes('disabled')).toBe(undefined); }); }); @@ -179,9 +159,6 @@ describe('import target cell', () => { }, }); - jest.runOnlyPendingTimers(); - await nextTick(); - expect(wrapper.text()).toContain(FAKE_ERROR_MESSAGE); }); }); diff --git a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js index ec50dfd037f..e1d65095888 100644 --- a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js +++ b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js @@ -259,6 +259,10 @@ describe('Bulk import resolvers', () => { target_namespace: 'root', new_name: 'group1', }, + last_import_target: { + target_namespace: 'root', + new_name: 'group1', + }, validation_errors: [], }, ], @@ -414,19 +418,32 @@ describe('Bulk import resolvers', () => { }); }); - it('setImportProgress updates group progress', async () => { + it('setImportProgress updates group progress and sets import target', async () => { const NEW_STATUS = 'dummy'; const FAKE_JOB_ID = 5; + const IMPORT_TARGET = { + __typename: 'ClientBulkImportTarget', + new_name: 'fake_name', + target_namespace: 'fake_target', + }; const { data: { - setImportProgress: { progress }, + setImportProgress: { progress, last_import_target: lastImportTarget }, }, } = await client.mutate({ mutation: setImportProgressMutation, - variables: { sourceGroupId: GROUP_ID, status: NEW_STATUS, jobId: FAKE_JOB_ID }, + variables: { + sourceGroupId: GROUP_ID, + status: NEW_STATUS, + jobId: FAKE_JOB_ID, + importTarget: IMPORT_TARGET, + }, }); - expect(progress).toMatchObject({ + expect(lastImportTarget).toStrictEqual(IMPORT_TARGET); + + expect(progress).toStrictEqual({ + __typename: clientTypenames.BulkImportProgress, id: FAKE_JOB_ID, status: NEW_STATUS, }); @@ -442,7 +459,8 @@ describe('Bulk import resolvers', () => { variables: { id: FAKE_JOB_ID, status: NEW_STATUS }, }); - expect(statusInResponse).toMatchObject({ + expect(statusInResponse).toStrictEqual({ + __typename: clientTypenames.BulkImportProgress, id: FAKE_JOB_ID, status: NEW_STATUS, }); @@ -460,7 +478,13 @@ describe('Bulk import resolvers', () => { variables: { sourceGroupId: GROUP_ID, field: FAKE_FIELD, message: FAKE_MESSAGE }, }); - expect(validationErrors).toMatchObject([{ field: FAKE_FIELD, message: FAKE_MESSAGE }]); + expect(validationErrors).toStrictEqual([ + { + __typename: clientTypenames.BulkImportValidationError, + field: FAKE_FIELD, + message: FAKE_MESSAGE, + }, + ]); }); it('removeValidationError removes error from group', async () => { @@ -481,7 +505,7 @@ describe('Bulk import resolvers', () => { variables: { sourceGroupId: GROUP_ID, field: FAKE_FIELD }, }); - expect(validationErrors).toMatchObject([]); + expect(validationErrors).toStrictEqual([]); }); }); }); diff --git a/spec/frontend/import_entities/import_groups/graphql/fixtures.js b/spec/frontend/import_entities/import_groups/graphql/fixtures.js index 6f66066b312..d1bd52693b6 100644 --- a/spec/frontend/import_entities/import_groups/graphql/fixtures.js +++ b/spec/frontend/import_entities/import_groups/graphql/fixtures.js @@ -9,6 +9,10 @@ export const generateFakeEntry = ({ id, status, ...rest }) => ({ target_namespace: 'root', new_name: `group${id}`, }, + last_import_target: { + target_namespace: 'root', + new_name: `last-group${id}`, + }, id, progress: { id: `test-${id}`, diff --git a/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js index bae715edac0..f06babcb149 100644 --- a/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js +++ b/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js @@ -20,7 +20,7 @@ describe('SourceGroupsManager', () => { describe('storage management', () => { const IMPORT_ID = 1; - const IMPORT_TARGET = { destination_name: 'demo', destination_namespace: 'foo' }; + const IMPORT_TARGET = { new_name: 'demo', target_namespace: 'foo' }; const STATUS = 'FAKE_STATUS'; const FAKE_GROUP = { id: 1, import_target: IMPORT_TARGET, status: STATUS }; |