summaryrefslogtreecommitdiff
path: root/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js')
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js213
1 files changed, 213 insertions, 0 deletions
diff --git a/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
new file mode 100644
index 00000000000..8eb1ffb3cd0
--- /dev/null
+++ b/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
@@ -0,0 +1,213 @@
+import { createMockClient } from 'mock-apollo-client';
+import { InMemoryCache } from 'apollo-cache-inmemory';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import createFlash from '~/flash';
+import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
+import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
+import { STATUSES } from '~/import_entities/constants';
+import { SourceGroupsManager } from '~/import_entities/import_groups/graphql/services/source_groups_manager';
+import { generateFakeEntry } from '../fixtures';
+
+jest.mock('~/flash');
+jest.mock('~/import_entities/import_groups/graphql/services/source_groups_manager', () => ({
+ SourceGroupsManager: jest.fn().mockImplementation(function mock() {
+ this.setImportStatus = jest.fn();
+ }),
+}));
+
+const TEST_POLL_INTERVAL = 1000;
+
+describe('Bulk import status poller', () => {
+ let poller;
+ let clientMock;
+
+ const listQueryCacheCalls = () =>
+ clientMock.readQuery.mock.calls.filter(call => call[0].query === bulkImportSourceGroupsQuery);
+
+ beforeEach(() => {
+ clientMock = createMockClient({
+ cache: new InMemoryCache({
+ fragmentMatcher: { match: () => true },
+ }),
+ });
+
+ jest.spyOn(clientMock, 'readQuery');
+
+ poller = new StatusPoller({
+ client: clientMock,
+ interval: TEST_POLL_INTERVAL,
+ });
+ });
+
+ describe('general behavior', () => {
+ beforeEach(() => {
+ clientMock.cache.writeQuery({
+ query: bulkImportSourceGroupsQuery,
+ data: { bulkImportSourceGroups: [] },
+ });
+ });
+
+ it('does not perform polling when constructed', () => {
+ jest.runOnlyPendingTimers();
+ expect(listQueryCacheCalls()).toHaveLength(0);
+ });
+
+ it('immediately start polling when requested', async () => {
+ await poller.startPolling();
+ expect(listQueryCacheCalls()).toHaveLength(1);
+ });
+
+ it('constantly polls when started', async () => {
+ poller.startPolling();
+ expect(listQueryCacheCalls()).toHaveLength(1);
+
+ jest.advanceTimersByTime(TEST_POLL_INTERVAL);
+ expect(listQueryCacheCalls()).toHaveLength(2);
+
+ jest.advanceTimersByTime(TEST_POLL_INTERVAL);
+ expect(listQueryCacheCalls()).toHaveLength(3);
+ });
+
+ it('does not start polling when requested multiple times', async () => {
+ poller.startPolling();
+ expect(listQueryCacheCalls()).toHaveLength(1);
+
+ poller.startPolling();
+ expect(listQueryCacheCalls()).toHaveLength(1);
+ });
+
+ it('stops polling when requested', async () => {
+ poller.startPolling();
+ expect(listQueryCacheCalls()).toHaveLength(1);
+
+ poller.stopPolling();
+ jest.runOnlyPendingTimers();
+ expect(listQueryCacheCalls()).toHaveLength(1);
+ });
+
+ it('does not query server when list is empty', async () => {
+ jest.spyOn(clientMock, 'query');
+ poller.startPolling();
+ expect(clientMock.query).not.toHaveBeenCalled();
+ });
+ });
+
+ it('does not query server when no groups have STARTED status', async () => {
+ clientMock.cache.writeQuery({
+ query: bulkImportSourceGroupsQuery,
+ data: {
+ bulkImportSourceGroups: [STATUSES.NONE, STATUSES.FINISHED].map((status, idx) =>
+ generateFakeEntry({ status, id: idx }),
+ ),
+ },
+ });
+
+ jest.spyOn(clientMock, 'query');
+ poller.startPolling();
+ expect(clientMock.query).not.toHaveBeenCalled();
+ });
+
+ describe('when there are groups which have STARTED status', () => {
+ const TARGET_NAMESPACE = 'root';
+
+ const STARTED_GROUP_1 = {
+ status: STATUSES.STARTED,
+ id: 'started1',
+ import_target: {
+ target_namespace: TARGET_NAMESPACE,
+ new_name: 'group1',
+ },
+ };
+
+ const STARTED_GROUP_2 = {
+ status: STATUSES.STARTED,
+ id: 'started2',
+ import_target: {
+ target_namespace: TARGET_NAMESPACE,
+ new_name: 'group2',
+ },
+ };
+
+ const NOT_STARTED_GROUP = {
+ status: STATUSES.NONE,
+ id: 'not_started',
+ import_target: {
+ target_namespace: TARGET_NAMESPACE,
+ new_name: 'group3',
+ },
+ };
+
+ it('query server only for groups with STATUSES.STARTED', async () => {
+ clientMock.cache.writeQuery({
+ query: bulkImportSourceGroupsQuery,
+ data: {
+ bulkImportSourceGroups: [STARTED_GROUP_1, NOT_STARTED_GROUP, STARTED_GROUP_2].map(group =>
+ generateFakeEntry(group),
+ ),
+ },
+ });
+
+ clientMock.query = jest.fn().mockResolvedValue({ data: {} });
+ poller.startPolling();
+
+ expect(clientMock.query).toHaveBeenCalledTimes(1);
+ await waitForPromises();
+ const [[doc]] = clientMock.query.mock.calls;
+ const { selections } = doc.query.definitions[0].selectionSet;
+ expect(selections.every(field => field.name.value === 'group')).toBeTruthy();
+ expect(selections).toHaveLength(2);
+ expect(selections.map(sel => sel.arguments[0].value.value)).toStrictEqual([
+ `${TARGET_NAMESPACE}/${STARTED_GROUP_1.import_target.new_name}`,
+ `${TARGET_NAMESPACE}/${STARTED_GROUP_2.import_target.new_name}`,
+ ]);
+ });
+
+ it('updates statuses only for groups in response', async () => {
+ clientMock.cache.writeQuery({
+ query: bulkImportSourceGroupsQuery,
+ data: {
+ bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map(group =>
+ generateFakeEntry(group),
+ ),
+ },
+ });
+
+ clientMock.query = jest.fn().mockResolvedValue({ data: { group0: {} } });
+ poller.startPolling();
+ await waitForPromises();
+ const [managerInstance] = SourceGroupsManager.mock.instances;
+ expect(managerInstance.setImportStatus).toHaveBeenCalledTimes(1);
+ expect(managerInstance.setImportStatus).toHaveBeenCalledWith(
+ expect.objectContaining({ id: STARTED_GROUP_1.id }),
+ STATUSES.FINISHED,
+ );
+ });
+
+ describe('when error occurs', () => {
+ beforeEach(() => {
+ clientMock.cache.writeQuery({
+ query: bulkImportSourceGroupsQuery,
+ data: {
+ bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map(group =>
+ generateFakeEntry(group),
+ ),
+ },
+ });
+
+ clientMock.query = jest.fn().mockRejectedValue(new Error('dummy error'));
+ poller.startPolling();
+ return waitForPromises();
+ });
+
+ it('reports an error', () => {
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('continues polling', async () => {
+ jest.advanceTimersByTime(TEST_POLL_INTERVAL);
+ expect(listQueryCacheCalls()).toHaveLength(2);
+ });
+ });
+ });
+});