2020-08-17 21:09:56 +00:00
|
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
2017-03-21 18:07:02 +00:00
|
|
|
import Poll from '~/lib/utils/poll';
|
2018-07-30 14:25:34 +00:00
|
|
|
import { successCodes } from '~/lib/utils/http_status';
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2017-05-11 12:09:13 +00:00
|
|
|
describe('Poll', () => {
|
2020-05-19 09:08:12 +00:00
|
|
|
let callbacks;
|
|
|
|
let service;
|
2017-07-18 01:35:43 +00:00
|
|
|
|
|
|
|
function setup() {
|
|
|
|
return new Poll({
|
|
|
|
resource: service,
|
|
|
|
method: 'fetch',
|
|
|
|
successCallback: callbacks.success,
|
|
|
|
errorCallback: callbacks.error,
|
|
|
|
notificationCallback: callbacks.notification,
|
|
|
|
}).makeRequest();
|
|
|
|
}
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
const mockServiceCall = (response, shouldFail = false) => {
|
|
|
|
const value = {
|
|
|
|
...response,
|
|
|
|
header: response.header || {},
|
|
|
|
};
|
|
|
|
|
|
|
|
if (shouldFail) {
|
|
|
|
service.fetch.mockRejectedValue(value);
|
|
|
|
} else {
|
|
|
|
service.fetch.mockResolvedValue(value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const waitForAllCallsToFinish = (waitForCount, successCallback) => {
|
|
|
|
if (!waitForCount) {
|
|
|
|
return Promise.resolve().then(successCallback());
|
|
|
|
}
|
|
|
|
|
|
|
|
jest.runOnlyPendingTimers();
|
|
|
|
|
|
|
|
return waitForPromises().then(() => waitForAllCallsToFinish(waitForCount - 1, successCallback));
|
|
|
|
};
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
service = {
|
|
|
|
fetch: jest.fn(),
|
|
|
|
};
|
|
|
|
callbacks = {
|
|
|
|
success: jest.fn(),
|
|
|
|
error: jest.fn(),
|
|
|
|
notification: jest.fn(),
|
|
|
|
};
|
2017-03-21 18:07:02 +00:00
|
|
|
});
|
|
|
|
|
2018-10-17 07:13:26 +00:00
|
|
|
it('calls the success callback when no header for interval is provided', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 200 });
|
2017-07-18 01:35:43 +00:00
|
|
|
setup();
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(1, () => {
|
2017-03-21 18:07:02 +00:00
|
|
|
expect(callbacks.success).toHaveBeenCalled();
|
|
|
|
expect(callbacks.error).not.toHaveBeenCalled();
|
2017-04-12 12:42:01 +00:00
|
|
|
|
2017-03-21 18:07:02 +00:00
|
|
|
done();
|
2017-05-11 12:09:13 +00:00
|
|
|
});
|
2017-03-21 18:07:02 +00:00
|
|
|
});
|
|
|
|
|
2018-10-17 07:13:26 +00:00
|
|
|
it('calls the error callback when the http request returns an error', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 500 }, true);
|
2017-07-18 01:35:43 +00:00
|
|
|
setup();
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(1, () => {
|
2017-03-21 18:07:02 +00:00
|
|
|
expect(callbacks.success).not.toHaveBeenCalled();
|
|
|
|
expect(callbacks.error).toHaveBeenCalled();
|
|
|
|
|
2017-04-12 12:42:01 +00:00
|
|
|
done();
|
|
|
|
});
|
2017-03-21 18:07:02 +00:00
|
|
|
});
|
|
|
|
|
2018-10-17 07:13:26 +00:00
|
|
|
it('skips the error callback when request is aborted', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 0 }, true);
|
2017-07-18 01:35:43 +00:00
|
|
|
setup();
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(1, () => {
|
2017-07-18 01:35:43 +00:00
|
|
|
expect(callbacks.success).not.toHaveBeenCalled();
|
|
|
|
expect(callbacks.error).not.toHaveBeenCalled();
|
|
|
|
expect(callbacks.notification).toHaveBeenCalled();
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-10-17 07:13:26 +00:00
|
|
|
it('should call the success callback when the interval header is -1', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 200, headers: { 'poll-interval': -1 } });
|
2018-10-17 07:13:26 +00:00
|
|
|
setup()
|
|
|
|
.then(() => {
|
|
|
|
expect(callbacks.success).toHaveBeenCalled();
|
|
|
|
expect(callbacks.error).not.toHaveBeenCalled();
|
2017-04-12 12:42:01 +00:00
|
|
|
|
2018-10-17 07:13:26 +00:00
|
|
|
done();
|
|
|
|
})
|
|
|
|
.catch(done.fail);
|
2017-03-21 18:07:02 +00:00
|
|
|
});
|
|
|
|
|
2018-07-30 14:25:34 +00:00
|
|
|
describe('for 2xx status code', () => {
|
|
|
|
successCodes.forEach(httpCode => {
|
2018-10-17 07:13:26 +00:00
|
|
|
it(`starts polling when http status is ${httpCode} and interval header is provided`, done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: httpCode, headers: { 'poll-interval': 1 } });
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2018-07-30 14:25:34 +00:00
|
|
|
const Polling = new Poll({
|
|
|
|
resource: service,
|
|
|
|
method: 'fetch',
|
|
|
|
data: { page: 1 },
|
|
|
|
successCallback: callbacks.success,
|
|
|
|
errorCallback: callbacks.error,
|
|
|
|
});
|
2017-04-12 12:42:01 +00:00
|
|
|
|
2018-07-30 14:25:34 +00:00
|
|
|
Polling.makeRequest();
|
2017-04-12 12:42:01 +00:00
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(2, () => {
|
2018-07-30 14:25:34 +00:00
|
|
|
Polling.stop();
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
expect(service.fetch.mock.calls).toHaveLength(2);
|
2018-07-30 14:25:34 +00:00
|
|
|
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
|
|
|
|
expect(callbacks.success).toHaveBeenCalled();
|
|
|
|
expect(callbacks.error).not.toHaveBeenCalled();
|
2017-03-21 18:07:02 +00:00
|
|
|
|
2018-07-30 14:25:34 +00:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2017-04-12 12:42:01 +00:00
|
|
|
});
|
2017-03-21 18:07:02 +00:00
|
|
|
});
|
2017-03-23 15:57:03 +00:00
|
|
|
|
|
|
|
describe('stop', () => {
|
2018-10-17 07:13:26 +00:00
|
|
|
it('stops polling when method is called', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
|
2017-03-23 15:57:03 +00:00
|
|
|
|
|
|
|
const Polling = new Poll({
|
|
|
|
resource: service,
|
|
|
|
method: 'fetch',
|
|
|
|
data: { page: 1 },
|
|
|
|
successCallback: () => {
|
|
|
|
Polling.stop();
|
|
|
|
},
|
|
|
|
errorCallback: callbacks.error,
|
|
|
|
});
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
jest.spyOn(Polling, 'stop');
|
2017-03-23 15:57:03 +00:00
|
|
|
|
|
|
|
Polling.makeRequest();
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(1, () => {
|
|
|
|
expect(service.fetch.mock.calls).toHaveLength(1);
|
2017-03-23 15:57:03 +00:00
|
|
|
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
|
|
|
|
expect(Polling.stop).toHaveBeenCalled();
|
|
|
|
|
2017-04-12 12:42:01 +00:00
|
|
|
done();
|
|
|
|
});
|
2017-03-23 15:57:03 +00:00
|
|
|
});
|
|
|
|
});
|
2017-03-24 16:59:14 +00:00
|
|
|
|
2019-02-23 19:00:38 +00:00
|
|
|
describe('enable', () => {
|
|
|
|
it('should enable polling upon a response', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 200 });
|
2019-02-23 19:00:38 +00:00
|
|
|
const Polling = new Poll({
|
|
|
|
resource: service,
|
|
|
|
method: 'fetch',
|
|
|
|
data: { page: 1 },
|
|
|
|
successCallback: () => {},
|
|
|
|
});
|
|
|
|
|
|
|
|
Polling.enable({
|
|
|
|
data: { page: 4 },
|
|
|
|
response: { status: 200, headers: { 'poll-interval': 1 } },
|
|
|
|
});
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(1, () => {
|
2019-02-23 19:00:38 +00:00
|
|
|
Polling.stop();
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
expect(service.fetch.mock.calls).toHaveLength(1);
|
2019-02-23 19:00:38 +00:00
|
|
|
expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
|
|
|
|
expect(Polling.options.data).toEqual({ page: 4 });
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-03-24 16:59:14 +00:00
|
|
|
describe('restart', () => {
|
2018-10-17 07:13:26 +00:00
|
|
|
it('should restart polling when its called', done => {
|
2020-05-19 09:08:12 +00:00
|
|
|
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
|
2017-03-24 16:59:14 +00:00
|
|
|
|
|
|
|
const Polling = new Poll({
|
|
|
|
resource: service,
|
|
|
|
method: 'fetch',
|
|
|
|
data: { page: 1 },
|
|
|
|
successCallback: () => {
|
|
|
|
Polling.stop();
|
2020-05-19 09:08:12 +00:00
|
|
|
|
|
|
|
// Let's pretend that we asynchronously restart this.
|
|
|
|
// setTimeout is mocked but this will actually get triggered
|
|
|
|
// in waitForAllCalssToFinish.
|
2017-03-24 16:59:14 +00:00
|
|
|
setTimeout(() => {
|
2017-11-14 15:35:29 +00:00
|
|
|
Polling.restart({ data: { page: 4 } });
|
2020-05-19 09:08:12 +00:00
|
|
|
}, 1);
|
2017-03-24 16:59:14 +00:00
|
|
|
},
|
|
|
|
errorCallback: callbacks.error,
|
|
|
|
});
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
jest.spyOn(Polling, 'stop');
|
|
|
|
jest.spyOn(Polling, 'enable');
|
|
|
|
jest.spyOn(Polling, 'restart');
|
2017-03-24 16:59:14 +00:00
|
|
|
|
|
|
|
Polling.makeRequest();
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
waitForAllCallsToFinish(2, () => {
|
2017-04-12 12:42:01 +00:00
|
|
|
Polling.stop();
|
|
|
|
|
2020-05-19 09:08:12 +00:00
|
|
|
expect(service.fetch.mock.calls).toHaveLength(2);
|
2017-11-14 15:35:29 +00:00
|
|
|
expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
|
2017-03-24 16:59:14 +00:00
|
|
|
expect(Polling.stop).toHaveBeenCalled();
|
2019-02-23 19:00:38 +00:00
|
|
|
expect(Polling.enable).toHaveBeenCalled();
|
2017-04-12 12:42:01 +00:00
|
|
|
expect(Polling.restart).toHaveBeenCalled();
|
2017-11-14 15:35:29 +00:00
|
|
|
expect(Polling.options.data).toEqual({ page: 4 });
|
2017-04-12 12:42:01 +00:00
|
|
|
done();
|
|
|
|
});
|
2017-03-24 16:59:14 +00:00
|
|
|
});
|
|
|
|
});
|
2017-03-21 18:07:02 +00:00
|
|
|
});
|