Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js')
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js221
1 files changed, 221 insertions, 0 deletions
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
new file mode 100644
index 00000000000..cacbe358a62
--- /dev/null
+++ b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
@@ -0,0 +1,221 @@
+import MockAdapter from 'axios-mock-adapter';
+import { InMemoryCache } from 'apollo-cache-inmemory';
+import { createMockClient } from 'mock-apollo-client';
+import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
+import {
+ clientTypenames,
+ createResolvers,
+} from '~/import_entities/import_groups/graphql/client_factory';
+import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
+import { STATUSES } from '~/import_entities/constants';
+
+import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
+import availableNamespacesQuery from '~/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql';
+import setTargetNamespaceMutation from '~/import_entities/import_groups/graphql/mutations/set_target_namespace.mutation.graphql';
+import setNewNameMutation from '~/import_entities/import_groups/graphql/mutations/set_new_name.mutation.graphql';
+import importGroupMutation from '~/import_entities/import_groups/graphql/mutations/import_group.mutation.graphql';
+import httpStatus from '~/lib/utils/http_status';
+import { statusEndpointFixture, availableNamespacesFixture } from './fixtures';
+
+jest.mock('~/import_entities/import_groups/graphql/services/status_poller', () => ({
+ StatusPoller: jest.fn().mockImplementation(function mock() {
+ this.startPolling = jest.fn();
+ }),
+}));
+
+const FAKE_ENDPOINTS = {
+ status: '/fake_status_url',
+ availableNamespaces: '/fake_available_namespaces',
+ createBulkImport: '/fake_create_bulk_import',
+};
+
+describe('Bulk import resolvers', () => {
+ let axiosMockAdapter;
+ let client;
+
+ beforeEach(() => {
+ axiosMockAdapter = new MockAdapter(axios);
+ client = createMockClient({
+ cache: new InMemoryCache({
+ fragmentMatcher: { match: () => true },
+ addTypename: false,
+ }),
+ resolvers: createResolvers({ endpoints: FAKE_ENDPOINTS }),
+ });
+ });
+
+ afterEach(() => {
+ axiosMockAdapter.restore();
+ });
+
+ describe('queries', () => {
+ describe('availableNamespaces', () => {
+ let results;
+
+ beforeEach(async () => {
+ axiosMockAdapter
+ .onGet(FAKE_ENDPOINTS.availableNamespaces)
+ .reply(httpStatus.OK, availableNamespacesFixture);
+
+ const response = await client.query({ query: availableNamespacesQuery });
+ results = response.data.availableNamespaces;
+ });
+
+ it('mirrors REST endpoint response fields', () => {
+ const extractRelevantFields = obj => ({ id: obj.id, full_path: obj.full_path });
+
+ expect(results.map(extractRelevantFields)).toStrictEqual(
+ availableNamespacesFixture.map(extractRelevantFields),
+ );
+ });
+ });
+
+ describe('bulkImportSourceGroups', () => {
+ let results;
+
+ beforeEach(async () => {
+ axiosMockAdapter.onGet(FAKE_ENDPOINTS.status).reply(httpStatus.OK, statusEndpointFixture);
+ axiosMockAdapter
+ .onGet(FAKE_ENDPOINTS.availableNamespaces)
+ .reply(httpStatus.OK, availableNamespacesFixture);
+
+ const response = await client.query({ query: bulkImportSourceGroupsQuery });
+ results = response.data.bulkImportSourceGroups;
+ });
+
+ it('mirrors REST endpoint response fields', () => {
+ const MIRRORED_FIELDS = ['id', 'full_name', 'full_path', 'web_url'];
+ expect(
+ results.every((r, idx) =>
+ MIRRORED_FIELDS.every(
+ field => r[field] === statusEndpointFixture.importable_data[idx][field],
+ ),
+ ),
+ ).toBe(true);
+ });
+
+ it('populates each result instance with status field default to none', () => {
+ expect(results.every(r => r.status === STATUSES.NONE)).toBe(true);
+ });
+
+ it('populates each result instance with import_target defaulted to first available namespace', () => {
+ expect(
+ results.every(
+ r => r.import_target.target_namespace === availableNamespacesFixture[0].full_path,
+ ),
+ ).toBe(true);
+ });
+ });
+ });
+
+ describe('mutations', () => {
+ let results;
+ const GROUP_ID = 1;
+
+ beforeEach(() => {
+ client.writeQuery({
+ query: bulkImportSourceGroupsQuery,
+ data: {
+ bulkImportSourceGroups: [
+ {
+ __typename: clientTypenames.BulkImportSourceGroup,
+ id: GROUP_ID,
+ status: STATUSES.NONE,
+ web_url: 'https://fake.host/1',
+ full_path: 'fake_group_1',
+ full_name: 'fake_name_1',
+ import_target: {
+ target_namespace: 'root',
+ new_name: 'group1',
+ },
+ },
+ ],
+ },
+ });
+
+ client
+ .watchQuery({
+ query: bulkImportSourceGroupsQuery,
+ fetchPolicy: 'cache-only',
+ })
+ .subscribe(({ data }) => {
+ results = data.bulkImportSourceGroups;
+ });
+ });
+
+ it('setTargetNamespaces updates group target namespace', async () => {
+ const NEW_TARGET_NAMESPACE = 'target';
+ await client.mutate({
+ mutation: setTargetNamespaceMutation,
+ variables: { sourceGroupId: GROUP_ID, targetNamespace: NEW_TARGET_NAMESPACE },
+ });
+
+ expect(results[0].import_target.target_namespace).toBe(NEW_TARGET_NAMESPACE);
+ });
+
+ it('setNewName updates group target name', async () => {
+ const NEW_NAME = 'new';
+ await client.mutate({
+ mutation: setNewNameMutation,
+ variables: { sourceGroupId: GROUP_ID, newName: NEW_NAME },
+ });
+
+ expect(results[0].import_target.new_name).toBe(NEW_NAME);
+ });
+
+ describe('importGroup', () => {
+ it('sets status to SCHEDULING when request initiates', async () => {
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(() => new Promise(() => {}));
+
+ client.mutate({
+ mutation: importGroupMutation,
+ variables: { sourceGroupId: GROUP_ID },
+ });
+ await waitForPromises();
+
+ const { bulkImportSourceGroups: intermediateResults } = client.readQuery({
+ query: bulkImportSourceGroupsQuery,
+ });
+
+ expect(intermediateResults[0].status).toBe(STATUSES.SCHEDULING);
+ });
+
+ it('sets group status to STARTED when request completes', async () => {
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK);
+ await client.mutate({
+ mutation: importGroupMutation,
+ variables: { sourceGroupId: GROUP_ID },
+ });
+
+ expect(results[0].status).toBe(STATUSES.STARTED);
+ });
+
+ it('starts polling when request completes', async () => {
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK);
+ await client.mutate({
+ mutation: importGroupMutation,
+ variables: { sourceGroupId: GROUP_ID },
+ });
+ const [statusPoller] = StatusPoller.mock.instances;
+ expect(statusPoller.startPolling).toHaveBeenCalled();
+ });
+
+ it('resets status to NONE if request fails', async () => {
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.INTERNAL_SERVER_ERROR);
+
+ client
+ .mutate({
+ mutation: importGroupMutation,
+ variables: { sourceGroupId: GROUP_ID },
+ })
+ .catch(() => {});
+ await waitForPromises();
+
+ expect(results[0].status).toBe(STATUSES.NONE);
+ });
+ });
+ });
+});