250 lines
8.3 KiB
JavaScript
250 lines
8.3 KiB
JavaScript
import { InMemoryCache } from 'apollo-cache-inmemory';
|
|
import MockAdapter from 'axios-mock-adapter';
|
|
import { createMockClient } from 'mock-apollo-client';
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
import { STATUSES } from '~/import_entities/constants';
|
|
import {
|
|
clientTypenames,
|
|
createResolvers,
|
|
} from '~/import_entities/import_groups/graphql/client_factory';
|
|
import importGroupMutation from '~/import_entities/import_groups/graphql/mutations/import_group.mutation.graphql';
|
|
import setNewNameMutation from '~/import_entities/import_groups/graphql/mutations/set_new_name.mutation.graphql';
|
|
import setTargetNamespaceMutation from '~/import_entities/import_groups/graphql/mutations/set_target_namespace.mutation.graphql';
|
|
import availableNamespacesQuery from '~/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql';
|
|
import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
|
|
import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
|
|
|
|
import axios from '~/lib/utils/axios_utils';
|
|
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',
|
|
jobs: '/fake_jobs',
|
|
};
|
|
|
|
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);
|
|
});
|
|
|
|
describe('when called', () => {
|
|
beforeEach(async () => {
|
|
const response = await client.query({ query: bulkImportSourceGroupsQuery });
|
|
results = response.data.bulkImportSourceGroups.nodes;
|
|
});
|
|
|
|
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);
|
|
});
|
|
|
|
it('starts polling when request completes', async () => {
|
|
const [statusPoller] = StatusPoller.mock.instances;
|
|
expect(statusPoller.startPolling).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it.each`
|
|
variable | queryParam | value
|
|
${'filter'} | ${'filter'} | ${'demo'}
|
|
${'perPage'} | ${'per_page'} | ${30}
|
|
${'page'} | ${'page'} | ${3}
|
|
`(
|
|
'properly passes GraphQL variable $variable as REST $queryParam query parameter',
|
|
async ({ variable, queryParam, value }) => {
|
|
await client.query({
|
|
query: bulkImportSourceGroupsQuery,
|
|
variables: { [variable]: value },
|
|
});
|
|
const restCall = axiosMockAdapter.history.get.find(
|
|
(q) => q.url === FAKE_ENDPOINTS.status,
|
|
);
|
|
expect(restCall.params[queryParam]).toBe(value);
|
|
},
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('mutations', () => {
|
|
let results;
|
|
const GROUP_ID = 1;
|
|
|
|
beforeEach(() => {
|
|
client.writeQuery({
|
|
query: bulkImportSourceGroupsQuery,
|
|
data: {
|
|
bulkImportSourceGroups: {
|
|
nodes: [
|
|
{
|
|
__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',
|
|
},
|
|
},
|
|
],
|
|
pageInfo: {
|
|
page: 1,
|
|
perPage: 20,
|
|
total: 37,
|
|
totalPages: 2,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
client
|
|
.watchQuery({
|
|
query: bulkImportSourceGroupsQuery,
|
|
fetchPolicy: 'cache-only',
|
|
})
|
|
.subscribe(({ data }) => {
|
|
results = data.bulkImportSourceGroups.nodes;
|
|
});
|
|
});
|
|
|
|
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: { nodes: 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, { id: 1 });
|
|
await client.mutate({
|
|
mutation: importGroupMutation,
|
|
variables: { sourceGroupId: GROUP_ID },
|
|
});
|
|
|
|
expect(results[0].status).toBe(STATUSES.STARTED);
|
|
});
|
|
|
|
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);
|
|
});
|
|
});
|
|
});
|
|
});
|