201 lines
6.2 KiB
JavaScript
201 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);
|
|
});
|
|
});
|
|
});
|
|
});
|