Commit 66ad04e4 authored by Winnie Hellmann's avatar Winnie Hellmann Committed by Mike Greiling

Mock timeouts and Promise in SmartInterval tests

parent 5bd8bfb6
export default () => new Promise(resolve => requestAnimationFrame(resolve));
...@@ -5,6 +5,7 @@ import { numberToHumanSize } from '~/lib/utils/number_utils'; ...@@ -5,6 +5,7 @@ import { numberToHumanSize } from '~/lib/utils/number_utils';
import '~/lib/utils/datetime_utility'; import '~/lib/utils/datetime_utility';
import Job from '~/job'; import Job from '~/job';
import '~/breakpoints'; import '~/breakpoints';
import waitForPromises from 'spec/helpers/wait_for_promises';
describe('Job', () => { describe('Job', () => {
const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`; const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`;
...@@ -12,10 +13,6 @@ describe('Job', () => { ...@@ -12,10 +13,6 @@ describe('Job', () => {
let response; let response;
let job; let job;
function waitForPromise() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
preloadFixtures('builds/build-with-artifacts.html.raw'); preloadFixtures('builds/build-with-artifacts.html.raw');
beforeEach(() => { beforeEach(() => {
...@@ -49,7 +46,7 @@ describe('Job', () => { ...@@ -49,7 +46,7 @@ describe('Job', () => {
beforeEach(function (done) { beforeEach(function (done) {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
...@@ -93,7 +90,7 @@ describe('Job', () => { ...@@ -93,7 +90,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
expect(job.state).toBe('newstate'); expect(job.state).toBe('newstate');
...@@ -107,7 +104,7 @@ describe('Job', () => { ...@@ -107,7 +104,7 @@ describe('Job', () => {
}; };
}) })
.then(() => jasmine.clock().tick(4001)) .then(() => jasmine.clock().tick(4001))
.then(waitForPromise) .then(waitForPromises)
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/);
expect(job.state).toBe('finalstate'); expect(job.state).toBe('finalstate');
...@@ -126,7 +123,7 @@ describe('Job', () => { ...@@ -126,7 +123,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
...@@ -137,7 +134,7 @@ describe('Job', () => { ...@@ -137,7 +134,7 @@ describe('Job', () => {
}; };
}) })
.then(() => jasmine.clock().tick(4001)) .then(() => jasmine.clock().tick(4001))
.then(waitForPromise) .then(waitForPromises)
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/);
expect($('#build-trace .js-build-output').text()).toMatch(/Different/); expect($('#build-trace .js-build-output').text()).toMatch(/Different/);
...@@ -160,7 +157,7 @@ describe('Job', () => { ...@@ -160,7 +157,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden'); expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden');
}) })
...@@ -181,7 +178,7 @@ describe('Job', () => { ...@@ -181,7 +178,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect( expect(
document.querySelector('.js-truncated-info-size').textContent.trim(), document.querySelector('.js-truncated-info-size').textContent.trim(),
...@@ -203,7 +200,7 @@ describe('Job', () => { ...@@ -203,7 +200,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect( expect(
document.querySelector('.js-truncated-info-size').textContent.trim(), document.querySelector('.js-truncated-info-size').textContent.trim(),
...@@ -219,7 +216,7 @@ describe('Job', () => { ...@@ -219,7 +216,7 @@ describe('Job', () => {
}; };
}) })
.then(() => jasmine.clock().tick(4001)) .then(() => jasmine.clock().tick(4001))
.then(waitForPromise) .then(waitForPromises)
.then(() => { .then(() => {
expect( expect(
document.querySelector('.js-truncated-info-size').textContent.trim(), document.querySelector('.js-truncated-info-size').textContent.trim(),
...@@ -258,7 +255,7 @@ describe('Job', () => { ...@@ -258,7 +255,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect(document.querySelector('.js-truncated-info').classList).toContain('hidden'); expect(document.querySelector('.js-truncated-info').classList).toContain('hidden');
}) })
...@@ -280,7 +277,7 @@ describe('Job', () => { ...@@ -280,7 +277,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
......
import $ from 'jquery'; import $ from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
import SmartInterval from '~/smart_interval'; import SmartInterval from '~/smart_interval';
import waitForPromises from 'spec/helpers/wait_for_promises';
describe('SmartInterval', function () { describe('SmartInterval', function () {
const DEFAULT_MAX_INTERVAL = 100; const DEFAULT_MAX_INTERVAL = 100;
const DEFAULT_STARTING_INTERVAL = 5; const DEFAULT_STARTING_INTERVAL = 5;
const DEFAULT_SHORT_TIMEOUT = 75; const DEFAULT_SHORT_TIMEOUT = 75;
const DEFAULT_LONG_TIMEOUT = 1000;
const DEFAULT_INCREMENT_FACTOR = 2; const DEFAULT_INCREMENT_FACTOR = 2;
function createDefaultSmartInterval(config) { function createDefaultSmartInterval(config) {
...@@ -27,52 +27,65 @@ describe('SmartInterval', function () { ...@@ -27,52 +27,65 @@ describe('SmartInterval', function () {
return new SmartInterval(defaultParams); return new SmartInterval(defaultParams);
} }
beforeEach(() => {
jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().uninstall();
});
describe('Increment Interval', function () { describe('Increment Interval', function () {
beforeEach(function () { it('should increment the interval delay', (done) => {
this.smartInterval = createDefaultSmartInterval(); const smartInterval = createDefaultSmartInterval();
});
it('should increment the interval delay', function (done) { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
const interval = this.smartInterval;
setTimeout(() => { waitForPromises()
const intervalConfig = this.smartInterval.cfg; .then(() => {
const iterationCount = 4; const intervalConfig = smartInterval.cfg;
const maxIntervalAfterIterations = intervalConfig.startingInterval * const iterationCount = 4;
(intervalConfig.incrementByFactorOf ** (iterationCount - 1)); // 40 const maxIntervalAfterIterations = intervalConfig.startingInterval *
const currentInterval = interval.getCurrentInterval(); (intervalConfig.incrementByFactorOf ** iterationCount);
const currentInterval = smartInterval.getCurrentInterval();
// Provide some flexibility for performance of testing environment
expect(currentInterval).toBeGreaterThan(intervalConfig.startingInterval); // Provide some flexibility for performance of testing environment
expect(currentInterval <= maxIntervalAfterIterations).toBeTruthy(); expect(currentInterval).toBeGreaterThan(intervalConfig.startingInterval);
expect(currentInterval).toBeLessThanOrEqual(maxIntervalAfterIterations);
done(); })
}, DEFAULT_SHORT_TIMEOUT); // 4 iterations, increment by 2x = (5 + 10 + 20 + 40) .then(done)
.catch(done.fail);
}); });
it('should not increment past maxInterval', function (done) { it('should not increment past maxInterval', (done) => {
const interval = this.smartInterval; const smartInterval = createDefaultSmartInterval({ maxInterval: DEFAULT_STARTING_INTERVAL });
setTimeout(() => { jasmine.clock().tick(DEFAULT_STARTING_INTERVAL);
const currentInterval = interval.getCurrentInterval(); jasmine.clock().tick(DEFAULT_STARTING_INTERVAL * DEFAULT_INCREMENT_FACTOR);
expect(currentInterval).toBe(interval.cfg.maxInterval);
done(); waitForPromises()
}, DEFAULT_LONG_TIMEOUT); .then(() => {
const currentInterval = smartInterval.getCurrentInterval();
expect(currentInterval).toBe(smartInterval.cfg.maxInterval);
})
.then(done)
.catch(done.fail);
}); });
it('does not increment while waiting for callback', function () { it('does not increment while waiting for callback', done => {
jasmine.clock().install();
const smartInterval = createDefaultSmartInterval({ const smartInterval = createDefaultSmartInterval({
callback: () => new Promise($.noop), callback: () => new Promise($.noop),
}); });
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT); jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
const oneInterval = smartInterval.cfg.startingInterval * DEFAULT_INCREMENT_FACTOR; waitForPromises()
expect(smartInterval.getCurrentInterval()).toEqual(oneInterval); .then(() => {
const oneInterval = smartInterval.cfg.startingInterval * DEFAULT_INCREMENT_FACTOR;
jasmine.clock().uninstall(); expect(smartInterval.getCurrentInterval()).toEqual(oneInterval);
})
.then(done)
.catch(done.fail);
}); });
}); });
...@@ -84,34 +97,39 @@ describe('SmartInterval', function () { ...@@ -84,34 +97,39 @@ describe('SmartInterval', function () {
it('should cancel an interval', function (done) { it('should cancel an interval', function (done) {
const interval = this.smartInterval; const interval = this.smartInterval;
setTimeout(() => { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
interval.cancel();
const { intervalId } = interval.state; interval.cancel();
const currentInterval = interval.getCurrentInterval();
const intervalLowerLimit = interval.cfg.startingInterval;
expect(intervalId).toBeUndefined(); waitForPromises()
expect(currentInterval).toBe(intervalLowerLimit); .then(() => {
const { intervalId } = interval.state;
const currentInterval = interval.getCurrentInterval();
const intervalLowerLimit = interval.cfg.startingInterval;
done(); expect(intervalId).toBeUndefined();
}, DEFAULT_SHORT_TIMEOUT); expect(currentInterval).toBe(intervalLowerLimit);
})
.then(done)
.catch(done.fail);
}); });
it('should resume an interval', function (done) { it('should resume an interval', function (done) {
const interval = this.smartInterval; const interval = this.smartInterval;
setTimeout(() => { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
interval.cancel();
interval.resume();
const { intervalId } = interval.state; interval.cancel();
expect(intervalId).toBeTruthy(); interval.resume();
done(); waitForPromises()
}, DEFAULT_SHORT_TIMEOUT); .then(() => {
const { intervalId } = interval.state;
expect(intervalId).toBeTruthy();
})
.then(done)
.catch(done.fail);
}); });
}); });
...@@ -126,64 +144,79 @@ describe('SmartInterval', function () { ...@@ -126,64 +144,79 @@ describe('SmartInterval', function () {
it('should pause when page is not visible', function (done) { it('should pause when page is not visible', function (done) {
const interval = this.smartInterval; const interval = this.smartInterval;
setTimeout(() => { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
expect(interval.state.intervalId).toBeTruthy();
waitForPromises()
.then(() => {
expect(interval.state.intervalId).toBeTruthy();
// simulates triggering of visibilitychange event // simulates triggering of visibilitychange event
interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } }); interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
expect(interval.state.intervalId).toBeUndefined(); expect(interval.state.intervalId).toBeUndefined();
done(); })
}, DEFAULT_SHORT_TIMEOUT); .then(done)
.catch(done.fail);
}); });
it('should change to the hidden interval when page is not visible', function (done) { it('should change to the hidden interval when page is not visible', done => {
const HIDDEN_INTERVAL = 1500; const HIDDEN_INTERVAL = 1500;
const interval = createDefaultSmartInterval({ hiddenInterval: HIDDEN_INTERVAL }); const interval = createDefaultSmartInterval({ hiddenInterval: HIDDEN_INTERVAL });
setTimeout(() => { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
expect(interval.state.intervalId).toBeTruthy();
expect(interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL && waitForPromises()
interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL).toBeTruthy(); .then(() => {
expect(interval.state.intervalId).toBeTruthy();
expect(interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL &&
interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL).toBeTruthy();
// simulates triggering of visibilitychange event // simulates triggering of visibilitychange event
interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } }); interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
expect(interval.state.intervalId).toBeTruthy(); expect(interval.state.intervalId).toBeTruthy();
expect(interval.getCurrentInterval()).toBe(HIDDEN_INTERVAL); expect(interval.getCurrentInterval()).toBe(HIDDEN_INTERVAL);
done(); })
}, DEFAULT_SHORT_TIMEOUT); .then(done)
.catch(done.fail);
}); });
it('should resume when page is becomes visible at the previous interval', function (done) { it('should resume when page is becomes visible at the previous interval', function (done) {
const interval = this.smartInterval; const interval = this.smartInterval;
setTimeout(() => { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
expect(interval.state.intervalId).toBeTruthy();
// simulates triggering of visibilitychange event waitForPromises()
interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } }); .then(() => {
expect(interval.state.intervalId).toBeTruthy();
expect(interval.state.intervalId).toBeUndefined(); // simulates triggering of visibilitychange event
interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
// simulates triggering of visibilitychange event expect(interval.state.intervalId).toBeUndefined();
interval.handleVisibilityChange({ target: { visibilityState: 'visible' } });
expect(interval.state.intervalId).toBeTruthy(); // simulates triggering of visibilitychange event
interval.handleVisibilityChange({ target: { visibilityState: 'visible' } });
done(); expect(interval.state.intervalId).toBeTruthy();
}, DEFAULT_SHORT_TIMEOUT); })
.then(done)
.catch(done.fail);
}); });
it('should cancel on page unload', function (done) { it('should cancel on page unload', function (done) {
const interval = this.smartInterval; const interval = this.smartInterval;
setTimeout(() => { jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
$(document).triggerHandler('beforeunload');
expect(interval.state.intervalId).toBeUndefined(); waitForPromises()
expect(interval.getCurrentInterval()).toBe(interval.cfg.startingInterval); .then(() => {
done(); $(document).triggerHandler('beforeunload');
}, DEFAULT_SHORT_TIMEOUT); expect(interval.state.intervalId).toBeUndefined();
expect(interval.getCurrentInterval()).toBe(interval.cfg.startingInterval);
})
.then(done)
.catch(done.fail);
}); });
it('should execute callback before first interval', function () { it('should execute callback before first interval', function () {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment