gitlab-org--gitlab-foss/spec/frontend/clusters_list/store/actions_spec.js

202 lines
6.2 KiB
JavaScript

import * as Sentry from '@sentry/browser';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { MAX_REQUESTS } from '~/clusters_list/constants';
import * as actions from '~/clusters_list/store/actions';
import * as types from '~/clusters_list/store/mutation_types';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
import { apiData } from '../mock_data';
jest.mock('~/flash.js');
describe('Clusters store actions', () => {
let captureException;
describe('reportSentryError', () => {
beforeEach(() => {
captureException = jest.spyOn(Sentry, 'captureException');
});
afterEach(() => {
captureException.mockRestore();
});
it('should report sentry error', async () => {
const sentryError = new Error('New Sentry Error');
const tag = 'sentryErrorTag';
await testAction(actions.reportSentryError, { error: sentryError, tag }, {}, [], []);
expect(captureException).toHaveBeenCalledWith(sentryError);
});
});
describe('fetchClusters', () => {
let mock;
const headers = {
'x-next-page': 1,
'x-total': apiData.clusters.length,
'x-total-pages': 1,
'x-per-page': 20,
'x-page': 1,
'x-prev-page': 1,
};
const paginationInformation = {
nextPage: 1,
page: 1,
perPage: 20,
previousPage: 1,
total: apiData.clusters.length,
totalPages: 1,
};
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => mock.restore());
it('should commit SET_CLUSTERS_DATA with received response', () => {
mock.onGet().reply(200, apiData, headers);
return testAction(
actions.fetchClusters,
{ endpoint: apiData.endpoint },
{},
[
{ type: types.SET_LOADING_NODES, payload: true },
{ type: types.SET_CLUSTERS_DATA, payload: { data: apiData, paginationInformation } },
{ type: types.SET_LOADING_CLUSTERS, payload: false },
],
[],
);
});
it('should show flash on API error', async () => {
mock.onGet().reply(400, 'Not Found');
await testAction(
actions.fetchClusters,
{ endpoint: apiData.endpoint },
{},
[
{ type: types.SET_LOADING_NODES, payload: true },
{ type: types.SET_LOADING_CLUSTERS, payload: false },
{ type: types.SET_LOADING_NODES, payload: false },
],
[
{
type: 'reportSentryError',
payload: {
error: new Error('Request failed with status code 400'),
tag: 'fetchClustersErrorCallback',
},
},
],
);
expect(createFlash).toHaveBeenCalledWith({
message: expect.stringMatching('error'),
});
});
describe('multiple api requests', () => {
let pollRequest;
let pollStop;
const pollInterval = 10;
const pollHeaders = { 'poll-interval': pollInterval, ...headers };
beforeEach(() => {
pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
pollStop = jest.spyOn(Poll.prototype, 'stop');
mock.onGet().reply(200, apiData, pollHeaders);
});
afterEach(() => {
pollRequest.mockRestore();
pollStop.mockRestore();
});
it('should stop polling after MAX Requests', async () => {
await testAction(
actions.fetchClusters,
{ endpoint: apiData.endpoint },
{},
[
{ type: types.SET_LOADING_NODES, payload: true },
{ type: types.SET_CLUSTERS_DATA, payload: { data: apiData, paginationInformation } },
{ type: types.SET_LOADING_CLUSTERS, payload: false },
],
[],
);
expect(pollRequest).toHaveBeenCalledTimes(1);
expect(pollStop).toHaveBeenCalledTimes(0);
jest.advanceTimersByTime(pollInterval);
return waitForPromises()
.then(() => {
expect(pollRequest).toHaveBeenCalledTimes(2);
expect(pollStop).toHaveBeenCalledTimes(0);
jest.advanceTimersByTime(pollInterval);
})
.then(() => waitForPromises())
.then(() => {
expect(pollRequest).toHaveBeenCalledTimes(MAX_REQUESTS);
expect(pollStop).toHaveBeenCalledTimes(0);
jest.advanceTimersByTime(pollInterval);
})
.then(() => waitForPromises())
.then(() => {
expect(pollRequest).toHaveBeenCalledTimes(MAX_REQUESTS + 1);
// Stops poll once it exceeds the MAX_REQUESTS limit
expect(pollStop).toHaveBeenCalledTimes(1);
jest.advanceTimersByTime(pollInterval);
})
.then(() => waitForPromises())
.then(() => {
// Additional poll requests are not made once pollStop is called
expect(pollRequest).toHaveBeenCalledTimes(MAX_REQUESTS + 1);
expect(pollStop).toHaveBeenCalledTimes(1);
});
});
it('should stop polling and report to Sentry when data is invalid', async () => {
const badApiResponse = { clusters: {} };
mock.onGet().reply(200, badApiResponse, pollHeaders);
await testAction(
actions.fetchClusters,
{ endpoint: apiData.endpoint },
{},
[
{ type: types.SET_LOADING_NODES, payload: true },
{
type: types.SET_CLUSTERS_DATA,
payload: { data: badApiResponse, paginationInformation },
},
{ type: types.SET_LOADING_CLUSTERS, payload: false },
{ type: types.SET_LOADING_CLUSTERS, payload: false },
{ type: types.SET_LOADING_NODES, payload: false },
],
[
{
type: 'reportSentryError',
payload: {
error: new Error('clusters.every is not a function'),
tag: 'fetchClustersSuccessCallback',
},
},
],
);
expect(pollRequest).toHaveBeenCalledTimes(1);
expect(pollStop).toHaveBeenCalledTimes(1);
});
});
});
});