import domEventSourceBlocking, { validateCursor, createErrorBackoff, } from 'consul-ui/utils/dom/event-source/blocking'; import { module, test } from 'qunit'; import sinon from 'sinon'; module('Unit | Utility | dom/event-source/blocking', function() { const createEventSource = function() { const EventSource = function(cb) { this.readyState = 1; this.source = cb; }; const o = EventSource.prototype; ['addEventListener', 'removeEventListener', 'dispatchEvent', 'close'].forEach(function(item) { o[item] = function() {}; }); return EventSource; }; const createPromise = function(resolve = function() {}) { class PromiseMock { constructor(cb = function() {}) { cb(resolve); } then(cb) { setTimeout(() => cb.bind(this)(), 0); return this; } catch(cb) { cb({ message: 'error' }); return this; } } PromiseMock.resolve = function() { return new PromiseMock(); }; return PromiseMock; }; test('it creates an BlockingEventSource class implementing EventSource', function(assert) { const EventSource = createEventSource(); const BlockingEventSource = domEventSourceBlocking(EventSource, function() {}); assert.ok(BlockingEventSource instanceof Function); const source = new BlockingEventSource(function() { return createPromise().resolve(); }); assert.ok(source instanceof EventSource); }); test("the 5xx backoff continues to throw when it's not a 5xx", function(assert) { const backoff = createErrorBackoff(); [ undefined, null, new Error(), { statusCode: 404 }, { errors: [] }, { errors: [{ status: '401' }] }, { errors: [{ status: '500' }] }, { errors: [{ status: '5' }] }, { errors: [{ status: '50' }] }, { errors: [{ status: '5000' }] }, { errors: [{ status: '5050' }] }, ].forEach(function(item) { assert.throws(function() { backoff(item); }); }); }); test('the 5xx backoff returns a resolve promise on a 5xx (apart from 500)', function(assert) { [ { statusCode: 501 }, { errors: [{ status: 501 }] }, { errors: [{ status: '501' }] }, { errors: [{ status: '503' }] }, { errors: [{ status: '504' }] }, { errors: [{ status: '524' }] }, ].forEach(item => { const timeout = sinon.stub().callsArg(0); const resolve = sinon.stub().withArgs(item); const Promise = createPromise(resolve); const backoff = createErrorBackoff(undefined, Promise, timeout); const promise = backoff(item); assert.ok(promise instanceof Promise, 'a promise was returned'); assert.ok(resolve.calledOnce, 'the promise was resolved with the correct arguments'); assert.ok(timeout.calledOnce, 'timeout was called once'); }); }); test("the cursor validation always returns undefined if the cursor can't be parsed to an integer", function(assert) { ['null', null, '', undefined].forEach(item => { const actual = validateCursor(item); assert.equal(actual, undefined); }); }); test('the cursor validation always returns a cursor greater than zero', function(assert) { [ { cursor: 0, expected: 1, }, { cursor: -10, expected: 1, }, { cursor: -1, expected: 1, }, { cursor: -1000, expected: 1, }, { cursor: 10, expected: 10, }, ].forEach(item => { const actual = validateCursor(item.cursor); assert.equal(actual, item.expected, 'cursor is greater than zero'); }); }); test('the cursor validation resets to 1 if its less than the previous cursor', function(assert) { [ { previous: 100, cursor: 99, expected: 1, }, { previous: 100, cursor: -10, expected: 1, }, { previous: 100, cursor: 0, expected: 1, }, { previous: 100, cursor: 101, expected: 101, }, ].forEach(item => { const actual = validateCursor(item.cursor, item.previous); assert.equal(actual, item.expected); }); }); });