summaryrefslogtreecommitdiff
path: root/spec/frontend/import_entities
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 13:37:47 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 13:37:47 +0000
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380 /spec/frontend/import_entities
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
downloadgitlab-ce-aee0a117a889461ce8ced6fcf73207fe017f1d99.tar.gz
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'spec/frontend/import_entities')
-rw-r--r--spec/frontend/import_entities/components/pagination_bar_spec.js92
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js107
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js11
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js59
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/fixtures.js9
5 files changed, 170 insertions, 108 deletions
diff --git a/spec/frontend/import_entities/components/pagination_bar_spec.js b/spec/frontend/import_entities/components/pagination_bar_spec.js
deleted file mode 100644
index 163ce11a8db..00000000000
--- a/spec/frontend/import_entities/components/pagination_bar_spec.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { GlPagination, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import PaginationBar from '~/import_entities/components/pagination_bar.vue';
-import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
-
-describe('Pagination bar', () => {
- const DEFAULT_PROPS = {
- pageInfo: {
- total: 50,
- page: 1,
- perPage: 20,
- },
- itemsCount: 17,
- };
- let wrapper;
-
- const createComponent = (propsData) => {
- wrapper = mount(PaginationBar, {
- propsData: {
- ...DEFAULT_PROPS,
- ...propsData,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('events', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('emits set-page event when page is selected', () => {
- const NEXT_PAGE = 3;
- // PaginationLinks uses prop instead of event for handling page change
- // So we go one level deep to test this
- wrapper
- .findComponent(PaginationLinks)
- .findComponent(GlPagination)
- .vm.$emit('input', NEXT_PAGE);
- expect(wrapper.emitted('set-page')).toEqual([[NEXT_PAGE]]);
- });
-
- it('emits set-page-size event when page size is selected', () => {
- const firstItemInPageSizeDropdown = wrapper.findComponent(GlDropdownItem);
- firstItemInPageSizeDropdown.vm.$emit('click');
-
- const [emittedPageSizeChange] = wrapper.emitted('set-page-size')[0];
- expect(firstItemInPageSizeDropdown.text()).toMatchInterpolatedText(
- `${emittedPageSizeChange} items per page`,
- );
- });
- });
-
- it('renders current page size', () => {
- const CURRENT_PAGE_SIZE = 40;
-
- createComponent({
- pageInfo: {
- ...DEFAULT_PROPS.pageInfo,
- perPage: CURRENT_PAGE_SIZE,
- },
- });
-
- expect(wrapper.find(GlDropdown).find('button').text()).toMatchInterpolatedText(
- `${CURRENT_PAGE_SIZE} items per page`,
- );
- });
-
- it('renders current page information', () => {
- createComponent();
-
- expect(wrapper.find('[data-testid="information"]').text()).toMatchInterpolatedText(
- 'Showing 1 - 17 of 50',
- );
- });
-
- it('renders current page information when total count is over 1000', () => {
- createComponent({
- pageInfo: {
- ...DEFAULT_PROPS.pageInfo,
- total: 1200,
- },
- });
-
- expect(wrapper.find('[data-testid="information"]').text()).toMatchInterpolatedText(
- 'Showing 1 - 17 of 1000+',
- );
- });
-});
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 6e3df21e30a..b17ff2e0f52 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
@@ -1,4 +1,4 @@
-import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -33,13 +33,23 @@ describe('import table', () => {
generateFakeEntry({ id: 2, status: STATUSES.FINISHED }),
];
const FAKE_PAGE_INFO = { page: 1, perPage: 20, total: 40, totalPages: 2 };
+ const FAKE_VERSION_VALIDATION = {
+ features: {
+ projectMigration: { available: false, minVersion: '14.8.0' },
+ sourceInstanceVersion: '14.6.0',
+ },
+ };
const findImportSelectedButton = () =>
wrapper.findAll('button').wrappers.find((w) => w.text() === 'Import selected');
const findImportButtons = () =>
wrapper.findAll('button').wrappers.filter((w) => w.text() === 'Import');
- const findPaginationDropdown = () => wrapper.find('[aria-label="Page size"]');
+ const findPaginationDropdown = () => wrapper.find('[data-testid="page-size"]');
const findPaginationDropdownText = () => findPaginationDropdown().find('button').text();
+ const findSelectionCount = () => wrapper.find('[data-test-id="selection-count"]');
+
+ const triggerSelectAllCheckbox = () =>
+ wrapper.find('thead input[type=checkbox]').trigger('click');
const selectRow = (idx) =>
wrapper.findAll('tbody td input[type=checkbox]').at(idx).trigger('click');
@@ -104,6 +114,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: [],
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -117,6 +128,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: FAKE_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -129,6 +141,7 @@ describe('import table', () => {
bulkImportSourceGroups: jest.fn().mockResolvedValue({
nodes: [],
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -138,7 +151,11 @@ describe('import table', () => {
it('invokes importGroups mutation when row button is clicked', async () => {
createComponent({
- bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
+ bulkImportSourceGroups: () => ({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
});
jest.spyOn(apolloProvider.defaultClient, 'mutate');
@@ -162,7 +179,11 @@ describe('import table', () => {
it('displays error if importing group fails', async () => {
createComponent({
- bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
+ bulkImportSourceGroups: () => ({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
importGroups: () => {
throw new Error();
},
@@ -182,9 +203,11 @@ describe('import table', () => {
});
describe('pagination', () => {
- const bulkImportSourceGroupsQueryMock = jest
- .fn()
- .mockResolvedValue({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO });
+ const bulkImportSourceGroupsQueryMock = jest.fn().mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ });
beforeEach(() => {
createComponent({
@@ -205,7 +228,13 @@ describe('import table', () => {
const otherOption = findPaginationDropdown().findAll('li p').at(1);
expect(otherOption.text()).toMatchInterpolatedText('50 items per page');
+ bulkImportSourceGroupsQueryMock.mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: { ...FAKE_PAGE_INFO, perPage: 50 },
+ versionValidation: FAKE_VERSION_VALIDATION,
+ });
await otherOption.trigger('click');
+
await waitForPromises();
expect(findPaginationDropdownText()).toMatchInterpolatedText('50 items per page');
@@ -234,6 +263,7 @@ describe('import table', () => {
perPage: 20,
totalPages: 2,
},
+ versionValidation: FAKE_VERSION_VALIDATION,
});
wrapper.find(PaginationLinks).props().change(REQUESTED_PAGE);
await waitForPromises();
@@ -243,9 +273,11 @@ describe('import table', () => {
});
describe('filters', () => {
- const bulkImportSourceGroupsQueryMock = jest
- .fn()
- .mockResolvedValue({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO });
+ const bulkImportSourceGroupsQueryMock = jest.fn().mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ });
beforeEach(() => {
createComponent({
@@ -313,11 +345,28 @@ describe('import table', () => {
});
describe('bulk operations', () => {
+ it('import all button correctly selects/deselects all groups', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
+ });
+ await waitForPromises();
+ expect(findSelectionCount().text()).toMatchInterpolatedText('0 selected');
+ await triggerSelectAllCheckbox();
+ expect(findSelectionCount().text()).toMatchInterpolatedText('2 selected');
+ await triggerSelectAllCheckbox();
+ expect(findSelectionCount().text()).toMatchInterpolatedText('0 selected');
+ });
+
it('import selected button is disabled when no groups selected', async () => {
createComponent({
bulkImportSourceGroups: () => ({
nodes: FAKE_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -330,6 +379,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: FAKE_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -346,6 +396,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: NEW_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -368,6 +419,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: NEW_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -391,6 +443,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: NEW_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
jest.spyOn(apolloProvider.defaultClient, 'mutate');
@@ -421,4 +474,38 @@ describe('import table', () => {
});
});
});
+
+ describe('unavailable features warning', () => {
+ it('renders alert when there are unavailable features', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
+ });
+ await waitForPromises();
+
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+ expect(wrapper.find(GlAlert).text()).toContain('projects (require v14.8.0)');
+ });
+
+ it('does not renders alert when there are no unavailable features', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: {
+ features: {
+ projectMigration: { available: true, minVersion: '14.8.0' },
+ sourceInstanceVersion: '14.6.0',
+ },
+ },
+ }),
+ });
+ await waitForPromises();
+
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
+ });
+ });
});
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 3c2367e22f5..d3f86672f33 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
@@ -123,13 +123,22 @@ describe('import target cell', () => {
});
describe('when entity is available for import', () => {
+ const FAKE_PROGRESS_MESSAGE = 'progress message';
beforeEach(() => {
- group = generateFakeTableEntry({ id: 1, flags: { isAvailableForImport: true } });
+ group = generateFakeTableEntry({
+ id: 1,
+ flags: { isAvailableForImport: true },
+ progress: { message: FAKE_PROGRESS_MESSAGE },
+ });
createComponent({ group });
});
it('renders namespace dropdown as enabled', () => {
expect(findNamespaceDropdown().attributes('disabled')).toBe(undefined);
});
+
+ it('renders progress message as error if it exists', () => {
+ expect(wrapper.find('[role=alert]').text()).toBe(FAKE_PROGRESS_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 f3447494578..c6ddce17fe4 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
@@ -163,12 +163,34 @@ describe('Bulk import resolvers', () => {
});
describe('mutations', () => {
- beforeEach(() => {
- axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
- });
+ beforeEach(() => {});
describe('importGroup', () => {
- it('sets import status to CREATED when request completes', async () => {
+ it('sets import status to CREATED for successful groups when request completes', async () => {
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.OK, [{ success: true, id: 1 }]);
+
+ await client.mutate({
+ mutation: importGroupsMutation,
+ variables: {
+ importRequests: [
+ {
+ sourceGroupId: statusEndpointFixture.importable_data[0].id,
+ newName: 'test',
+ targetNamespace: 'root',
+ },
+ ],
+ },
+ });
+
+ await axios.waitForAll();
+ expect(results[0].progress.status).toBe(STATUSES.CREATED);
+ });
+
+ it('sets import status to CREATED for successful groups when request completes with legacy response', async () => {
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
+
await client.mutate({
mutation: importGroupsMutation,
variables: {
@@ -185,9 +207,37 @@ describe('Bulk import resolvers', () => {
await axios.waitForAll();
expect(results[0].progress.status).toBe(STATUSES.CREATED);
});
+
+ it('sets import status to FAILED and sets progress message for failed groups when request completes', async () => {
+ const FAKE_ERROR_MESSAGE = 'foo';
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.OK, [{ success: false, id: 1, message: FAKE_ERROR_MESSAGE }]);
+
+ await client.mutate({
+ mutation: importGroupsMutation,
+ variables: {
+ importRequests: [
+ {
+ sourceGroupId: statusEndpointFixture.importable_data[0].id,
+ newName: 'test',
+ targetNamespace: 'root',
+ },
+ ],
+ },
+ });
+
+ await axios.waitForAll();
+ expect(results[0].progress.status).toBe(STATUSES.FAILED);
+ expect(results[0].progress.message).toBe(FAKE_ERROR_MESSAGE);
+ });
});
it('updateImportStatus updates status', async () => {
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.OK, [{ success: true, id: 1 }]);
+
const NEW_STATUS = 'dummy';
await client.mutate({
mutation: importGroupsMutation,
@@ -216,6 +266,7 @@ describe('Bulk import resolvers', () => {
expect(statusInResponse).toStrictEqual({
__typename: clientTypenames.BulkImportProgress,
id,
+ message: null,
status: NEW_STATUS,
});
});
diff --git a/spec/frontend/import_entities/import_groups/graphql/fixtures.js b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
index 5f6f9987a8f..ed4e343f331 100644
--- a/spec/frontend/import_entities/import_groups/graphql/fixtures.js
+++ b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
@@ -1,7 +1,7 @@
import { STATUSES } from '~/import_entities/constants';
import { clientTypenames } from '~/import_entities/import_groups/graphql/client_factory';
-export const generateFakeEntry = ({ id, status, ...rest }) => ({
+export const generateFakeEntry = ({ id, status, message, ...rest }) => ({
__typename: clientTypenames.BulkImportSourceGroup,
webUrl: `https://fake.host/${id}`,
fullPath: `fake_group_${id}`,
@@ -18,6 +18,7 @@ export const generateFakeEntry = ({ id, status, ...rest }) => ({
: {
id,
status,
+ message: message || '',
},
...rest,
});
@@ -49,6 +50,12 @@ export const statusEndpointFixture = {
web_url: 'https://gitlab.com/groups/gitlab-examples',
},
],
+ version_validation: {
+ features: {
+ project_migration: { available: false, min_version: '14.8.0' },
+ source_instance_version: '14.6.0',
+ },
+ },
};
export const availableNamespacesFixture = Object.freeze([