Simplifying capabilities check and mocking
DELETE
addon/capabilities.js
-const CAPABILITIES = {
- requestAnimationFrame: requestAnimationFrame,
- requestIdleCallback: requestIdleCallback,
-};
-
-export const DISABLED = true;
-
-/**
- * @type {Capabilities}
- */
-let _instance = null;
-
-class Capabilities {
- constructor() {
- if (_instance) {
- throw new Error('Capabilities can only be constructed once');
- }
-
- this.reset();
- }
-
- static get instance() {
- if (!_instance) {
- _instance = new Capabilities();
- }
-
- return _instance;
- }
-
- overrideCapability(capability, override = false) {
- this[capability + 'Enabled'] = override
- ? false
- : typeof CAPABILITIES[capability] === 'function';
- }
-
- reset() {
- this.overrideCapability('requestAnimationFrame');
- this.overrideCapability('requestIdleCallback');
- }
-}
-
-export default Capabilities;

MODIFY
addon/scheduler.js
addon/scheduler.js
@@ -2,9 +2,7 @@ import RSVP from 'rsvp';
import { run } from '@ember/runloop';
import { DEBUG } from '@glimmer/env';
import { registerWaiter } from '@ember/test';
-import Capabilities from './capabilities';
-const CAPABILITIES = Capabilities.instance;
const APP_SCHEDULER_HAS_SETUP = '__APP_SCHEDULER_HAS_SETUP__';
let _didTransition;
@@ -13,6 +11,11 @@ let _whenRoutePaintedScheduleFn;
let _whenRouteIdle;
let _whenRouteIdleScheduleFn;
let _activeScheduledTasks = 0;
+const CAPABILITIES = {
+ requestAnimationFrameEnabled: typeof requestAnimationFrame === 'function',
+ requestIdleCallbackEnabled: typeof requestIdleCallback === 'function',
+};
+let _capabilities = CAPABILITIES;
export const USE_REQUEST_IDLE_CALLBACK = true;
export const SIMPLE_CALLBACK = callback => callback();
@@ -92,15 +95,19 @@ export function routeSettled() {
}
export function _getScheduleFn(useRequestIdleCallback = false) {
- if (useRequestIdleCallback && CAPABILITIES.requestIdleCallbackEnabled) {
+ if (useRequestIdleCallback && _capabilities.requestIdleCallbackEnabled) {
return requestIdleCallback;
- } else if (CAPABILITIES.requestAnimationFrameEnabled) {
+ } else if (_capabilities.requestAnimationFrameEnabled) {
return requestAnimationFrame;
} else {
return SIMPLE_CALLBACK;
}
}
+export function _setCapabilities(newCapabilities = CAPABILITIES) {
+ _capabilities = newCapabilities;
+}
+
_whenRoutePaintedScheduleFn = _getScheduleFn();
_whenRouteIdleScheduleFn = _getScheduleFn(USE_REQUEST_IDLE_CALLBACK);

DELETE
tests/unit/capabilities-test.js
-import { module, test } from 'qunit';
-import Capabilities, { DISABLED } from 'ember-app-scheduler/capabilities';
-
-const CAPABILITIES = Capabilities.instance;
-
-module('Unit | Capabilities', function(hooks) {
- hooks.beforeEach(function() {
- CAPABILITIES.reset();
- });
-
- test('capabilities is initialized correctly', function(assert) {
- assert.expect(2);
-
- assert.ok(CAPABILITIES.requestAnimationFrameEnabled);
- assert.ok(CAPABILITIES.requestIdleCallbackEnabled);
- });
-
- test('capabilities can be overridden correctly', function(assert) {
- assert.expect(2);
-
- CAPABILITIES.overrideCapability('requestAnimationFrame', DISABLED);
- CAPABILITIES.overrideCapability('requestIdleCallback', DISABLED);
-
- assert.equal(CAPABILITIES.requestAnimationFrameEnabled, false);
- assert.equal(CAPABILITIES.requestIdleCallbackEnabled, false);
- });
-});

MODIFY
tests/unit/scheduler-test.js
tests/unit/scheduler-test.js
@@ -7,19 +7,18 @@ import {
endTransition,
} from 'ember-app-scheduler';
import {
+ _setCapabilities,
_getScheduleFn,
USE_REQUEST_IDLE_CALLBACK,
SIMPLE_CALLBACK,
} from 'ember-app-scheduler/scheduler';
-import Capabilities, { DISABLED } from 'ember-app-scheduler/capabilities';
-const CAPABILITIES = Capabilities.instance;
const REQUEST_ANIMATION_FRAME = requestAnimationFrame;
module('Unit | Scheduler', function(hooks) {
hooks.afterEach(function() {
reset();
- CAPABILITIES.reset();
+ _setCapabilities();
window.requestAnimationFrame = REQUEST_ANIMATION_FRAME;
});
@@ -42,7 +41,10 @@ module('Unit | Scheduler', function(hooks) {
test('whenRouteIdle resolves when transition ended when requestAnimationFrame not available', async function(assert) {
assert.expect(1);
- CAPABILITIES.overrideCapability('requestAnimationFrame', DISABLED);
+ _setCapabilities({
+ requestAnimationFrameEnabled: false,
+ requestIdleCallbackEnabled: false,
+ });
window.requestAnimationFrame = () =>
assert.ok(false, 'requestAnimationFrame was used');
beginTransition();
@@ -58,10 +60,13 @@ module('Unit | Scheduler', function(hooks) {
await routeSettled();
});
- test('whenRouteIdle resolves using requestAnimationFrame when transition ended when requestIdleCallback not available', async function(assert) {
+ test('whenRouteIdle resolves using requestAnimationFrame when transition ended when requestIdleCallbackEnabled: not available', async function(assert) {
assert.expect(1);
- CAPABILITIES.overrideCapability('requestIdleCallback', DISABLED);
+ _setCapabilities({
+ requestAnimationFrameEnabled: true,
+ requestIdleCallbackEnabled: false,
+ });
window.requestAnimationFrame = () =>
assert.ok(true, 'requestAnimationFrame was used');
beginTransition();
@@ -99,16 +104,22 @@ module('Unit | Scheduler', function(hooks) {
assert.verifySteps(['first whenRouteIdle', 'second whenRouteIdle']);
});
- test('_getScheduleFn returns correct scheduleFn for requestIdleCallback', function(assert) {
+ test('_getScheduleFn returns correct scheduleFn for requestIdleCallbackEnabled:', function(assert) {
+ assert.expect(1);
+
assert.equal(
_getScheduleFn(USE_REQUEST_IDLE_CALLBACK),
requestIdleCallback
);
});
- test('_getScheduleFn falls back to requestAnimationFrame if requestIdleCallback not available', function(assert) {
- CAPABILITIES.overrideCapability('requestIdleCallback', DISABLED);
+ test('_getScheduleFn falls back to requestAnimationFrame if requestIdleCallbackEnabled: not available', function(assert) {
+ assert.expect(1);
+ _setCapabilities({
+ requestAnimationFrameEnabled: true,
+ requestIdleCallbackEnabled: false,
+ });
assert.equal(
_getScheduleFn(USE_REQUEST_IDLE_CALLBACK),
requestAnimationFrame
@@ -116,8 +127,12 @@ module('Unit | Scheduler', function(hooks) {
});
test('_getScheduleFn returns simple callback if requestAnimationFrame not available', function(assert) {
- CAPABILITIES.overrideCapability('requestAnimationFrame', DISABLED);
- CAPABILITIES.overrideCapability('requestIdleCallback', DISABLED);
+ assert.expect(1);
+
+ _setCapabilities({
+ requestAnimationFrameEnabled: false,
+ requestIdleCallbackEnabled: false,
+ });
assert.equal(_getScheduleFn(), SIMPLE_CALLBACK);
});

Simplifying capabilities check and mocking