Skip to content

Commit

Permalink
Update lolex to the latest version 🚀 (material-components#3507)
Browse files Browse the repository at this point in the history
This updates lolex to 3.0.0, which now covers rAF as well, so createMockRaf has been removed.

`clock.runToFrame()` replaces `mockRaf.flush()`, and
`clock.countTimers()` replaces `mockRaf.pendingFrames.length`.

This also creates a centralized `test/unit/helpers/clock` module to avoid
any missed cleanup of mocked timeout/rAF functions.
Instead of using lolex directly in unit tests, import the clock module's
`install` function and call that. It creates a lolex instance and stores it
within the module, and there is a "global" afterEach set up to uninstall it
if it exists, after every test in every suite.

(cherry picked from commit 7c60849)
  • Loading branch information
greenkeeper[bot] authored and abhiomkar committed Nov 14, 2018
1 parent 65d34d4 commit fedd1c1
Show file tree
Hide file tree
Showing 42 changed files with 984 additions and 1,466 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"karma-tap": "^4.0.0",
"karma-webpack": "^3.0.0",
"lerna": "^2.11.0",
"lolex": "2.1.3",
"lolex": "3.0.0",
"mkdirp": "^0.5.1",
"mocha": "^5.0.0",
"mz": "^2.7.0",
Expand Down
21 changes: 21 additions & 0 deletions test/unit/helpers/clock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import lolex from 'lolex';

let instance;

function install() {
if (instance) {
console.log('A clock instance already exists! Uninstalling it first...');
instance.uninstall();
}
instance = lolex.install();
return instance;
}

function uninstall() {
if (instance) {
instance.uninstall();
instance = undefined;
}
}

export {install, uninstall};
79 changes: 0 additions & 79 deletions test/unit/helpers/raf.js

This file was deleted.

8 changes: 8 additions & 0 deletions test/unit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@

/** @fileoverview Bootstraps the test bundle for karma-webpack. */

import {uninstall as uninstallClock} from './helpers/clock';

// Hooks are valuable for ensuring we restore native functions after each test
// eslint-disable-next-line mocha/no-hooks
afterEach(() => {
uninstallClock();
});

// https://github.com/webpack/docs/wiki/context#requirecontext
const testsContext = require.context(/* directory */ '.', /* useSubdirectories */ true, /\.test\.js$/);
testsContext.keys().forEach(testsContext);
16 changes: 3 additions & 13 deletions test/unit/mdc-checkbox/foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@

import {assert} from 'chai';
import bel from 'bel';
import lolex from 'lolex';
import td from 'testdouble';

import {install as installClock} from '../helpers/clock';
import {setupFoundationTest} from '../helpers/setup';
import {verifyDefaultAdapter} from '../helpers/foundation';
import MDCCheckboxFoundation from '../../../packages/mdc-checkbox/foundation';
Expand Down Expand Up @@ -259,7 +259,7 @@ testChangeHandler('no transition classes applied when no state change', [
], cssClasses.ANIM_UNCHECKED_CHECKED, {times: 1});

test('animation end handler removes animation class after short delay', () => {
const clock = lolex.install();
const clock = installClock();
const {ANIM_UNCHECKED_CHECKED} = cssClasses;
const {mockAdapter, foundation} = setupTest();

Expand All @@ -272,12 +272,10 @@ test('animation end handler removes animation class after short delay', () => {
clock.tick(numbers.ANIM_END_LATCH_MS);
td.verify(mockAdapter.removeClass(ANIM_UNCHECKED_CHECKED), {times: 1});
assert.isFalse(foundation.enableAnimationEndHandler_);

clock.uninstall();
});

test('animation end is debounced if event is called twice', () => {
const clock = lolex.install();
const clock = installClock();
const {ANIM_UNCHECKED_CHECKED} = cssClasses;
const {mockAdapter, foundation} = setupChangeHandlerTest();
foundation.enableAnimationEndHandler_ = true;
Expand All @@ -291,8 +289,6 @@ test('animation end is debounced if event is called twice', () => {

clock.tick(numbers.ANIM_END_LATCH_MS);
td.verify(mockAdapter.removeClass(ANIM_UNCHECKED_CHECKED), {times: 1});

clock.uninstall();
});

test('change handler triggers layout for changes within the same frame to correctly restart anims', () => {
Expand Down Expand Up @@ -339,7 +335,6 @@ test('change handler gracefully exits when getNativeControl() returns nothing',

test('"checked" property change hook works correctly', () => {
const {foundation, mockAdapter, nativeControl} = setupTest();
const clock = lolex.install();
td.when(mockAdapter.isAttachedToDOM()).thenReturn(true);
td.when(mockAdapter.hasNativeControl()).thenReturn(true);

Expand All @@ -355,13 +350,10 @@ test('"checked" property change hook works correctly', () => {
nativeControl.checked = !nativeControl.checked;
td.verify(mockAdapter.addClass(cssClasses.ANIM_UNCHECKED_CHECKED));
});

clock.uninstall();
});

test('"indeterminate" property change hook works correctly', () => {
const {foundation, mockAdapter, nativeControl} = setupTest();
const clock = lolex.install();
td.when(mockAdapter.isAttachedToDOM()).thenReturn(true);
td.when(mockAdapter.hasNativeControl()).thenReturn(true);

Expand All @@ -378,6 +370,4 @@ test('"indeterminate" property change hook works correctly', () => {
nativeControl.indeterminate = !nativeControl.indeterminate;
td.verify(mockAdapter.addClass(cssClasses.ANIM_UNCHECKED_INDETERMINATE));
});

clock.uninstall();
});
21 changes: 9 additions & 12 deletions test/unit/mdc-checkbox/mdc-checkbox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import bel from 'bel';
import domEvents from 'dom-events';
import td from 'testdouble';

import {install as installClock} from '../helpers/clock';
import {supportsCssVariables} from '../../../packages/mdc-ripple/util';
import {createMockRaf} from '../helpers/raf';
import {MDCCheckbox} from '../../../packages/mdc-checkbox/index';
import {MDCRipple} from '../../../packages/mdc-ripple/index';
import {strings} from '../../../packages/mdc-checkbox/constants';
Expand Down Expand Up @@ -65,39 +65,36 @@ suite('MDCCheckbox');

if (supportsCssVariables(window)) {
test('#constructor initializes the root element with a ripple', () => {
const raf = createMockRaf();
const clock = installClock();
const {root} = setupTest();
raf.flush();
clock.runToFrame();
assert.isOk(root.classList.contains('mdc-ripple-upgraded'));
raf.restore();
});

test('#destroy removes the ripple', () => {
const raf = createMockRaf();
const clock = installClock();
const {root, component} = setupTest();
raf.flush();
clock.runToFrame();
component.destroy();
raf.flush();
clock.runToFrame();
assert.isNotOk(root.classList.contains('mdc-ripple-upgraded'));
raf.restore();
});

test('(regression) activates ripple on keydown when the input element surface is active', () => {
const raf = createMockRaf();
const clock = installClock();
const {root} = setupTest();
const input = root.querySelector('input');
raf.flush();
clock.runToFrame();

const fakeMatches = td.func('.matches');
td.when(fakeMatches(':active')).thenReturn(true);
input[getMatchesProperty(HTMLElement.prototype)] = fakeMatches;

assert.isTrue(root.classList.contains('mdc-ripple-upgraded'));
domEvents.emit(input, 'keydown');
raf.flush();
clock.runToFrame();

assert.isTrue(root.classList.contains('mdc-ripple-upgraded--foreground-activation'));
raf.restore();
});
}

Expand Down
8 changes: 4 additions & 4 deletions test/unit/mdc-chips/mdc-chip.foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
import {assert} from 'chai';
import td from 'testdouble';

import {install as installClock} from '../helpers/clock';
import {verifyDefaultAdapter} from '../helpers/foundation';
import {createMockRaf} from '../helpers/raf';
import {setupFoundationTest} from '../helpers/setup';
import {MDCChipFoundation} from '../../../packages/mdc-chips/chip/foundation';

Expand Down Expand Up @@ -121,7 +121,7 @@ test('#handleTransitionEnd notifies removal of chip on width transition end', ()

test('#handleTransitionEnd animates width if chip is exiting on chip opacity transition end', () => {
const {foundation, mockAdapter} = setupTest();
const raf = createMockRaf();
const clock = installClock();
const mockEvt = {
type: 'transitionend',
target: {},
Expand All @@ -132,12 +132,12 @@ test('#handleTransitionEnd animates width if chip is exiting on chip opacity tra

foundation.handleTransitionEnd(mockEvt);

raf.flush();
clock.runToFrame();
td.verify(mockAdapter.setStyleProperty('width', '100px'));
td.verify(mockAdapter.setStyleProperty('padding', '0'));
td.verify(mockAdapter.setStyleProperty('margin', '0'));

raf.flush();
clock.runToFrame();
td.verify(mockAdapter.setStyleProperty('width', '0'));
});

Expand Down
Loading

0 comments on commit fedd1c1

Please sign in to comment.