Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

lolex

sinonjs7.7mBSD-3-Clausedeprecated6.0.0TypeScript support: definitely-typed

lolex has been renamed to @sinonjs/fake-timers. No API changes made. Please use the new package instead

Fake JavaScript timers

readme

Lolex CircleCI codecov

JavaScript implementation of the timer APIs; setTimeout, clearTimeout, setImmediate, clearImmediate, setInterval, clearInterval, requestAnimationFrame, cancelAnimationFrame, requestIdleCallback, and cancelIdleCallback, along with a clock instance that controls the flow of time. Lolex also provides a Date implementation that gets its time from the clock.

In addition in browser environment lolex provides a performance implementation that gets its time from the clock. In Node environments lolex provides a nextTick implementation that is synchronized with the clock - and a process.hrtime shim that works with the clock.

Lolex can be used to simulate passing time in automated tests and other situations where you want the scheduling semantics, but don't want to actually wait (however, from version 2.0 lolex supports those of you who would like to wait too).

Lolex is extracted from Sinon.JS and targets the same runtimes.

Installation

Lolex can be used in both Node and browser environments. Installation is as easy as

npm install lolex

If you want to use Lolex in a browser you can use the pre-built version available in the repo and the npm package. Using npm you only need to reference ./node_modules/lolex/lolex.js in your <script> tags.

You are always free to build it yourself, of course.

Usage

To use lolex, create a new clock, schedule events on it using the timer functions and pass time using the tick method.

// In the browser distribution, a global `lolex` is already available
var lolex = require("lolex");
var clock = lolex.createClock();

clock.setTimeout(function () {
    console.log("The poblano is a mild chili pepper originating in the state of Puebla, Mexico.");
}, 15);

// ...

clock.tick(15);

Upon executing the last line, an interesting fact about the Poblano will be printed synchronously to the screen. If you want to simulate asynchronous behavior, you have to use your imagination when calling the various functions.

The next, runAll, runToFrame, and runToLast methods are available to advance the clock. See the API Reference for more details.

Faking the native timers

When using lolex to test timers, you will most likely want to replace the native timers such that calling setTimeout actually schedules a callback with your clock instance, not the browser's internals.

Calling install with no arguments achieves this. You can call uninstall later to restore things as they were again.

// In the browser distribution, a global `lolex` is already available
var lolex = require("lolex");

var clock = lolex.install();
// Equivalent to
// var clock = lolex.install(typeof global !== "undefined" ? global : window);

setTimeout(fn, 15); // Schedules with clock.setTimeout

clock.uninstall();
// setTimeout is restored to the native implementation

To hijack timers in another context pass it to the install method.

var lolex = require("lolex");
var context = {
    setTimeout: setTimeout // By default context.setTimeout uses the global setTimeout
}
var clock = lolex.install({target: context});

context.setTimeout(fn, 15); // Schedules with clock.setTimeout

clock.uninstall();
// context.setTimeout is restored to the original implementation

Usually you want to install the timers onto the global object, so call install without arguments.

Automatically incrementing mocked time

Since version 2.0 Lolex supports the possibility to attach the faked timers to any change in the real system time. This basically means you no longer need to tick() the clock in a situation where you won't know when to call tick().

Please note that this is achieved using the original setImmediate() API at a certain configurable interval config.advanceTimeDelta (default: 20ms). Meaning time would be incremented every 20ms, not in real time.

An example would be:

var lolex = require("lolex");
var clock = lolex.install({shouldAdvanceTime: true, advanceTimeDelta: 40});

setTimeout(() => {
    console.log('this just timed out'); //executed after 40ms
}, 30);

setImmediate(() => {
    console.log('not so immediate'); //executed after 40ms
});

setTimeout(() => {
    console.log('this timed out after'); //executed after 80ms
    clock.uninstall();
}, 50);

API Reference

var clock = lolex.createClock([now[, loopLimit]])

Creates a clock. The default epoch is 0.

The now argument may be a number (in milliseconds) or a Date object.

The loopLimit argument sets the maximum number of timers that will be run when calling runAll() before assuming that we have an infinite loop and throwing an error. The default is 1000.

var clock = lolex.install([config])

Installs lolex using the specified config (otherwise with epoch 0 on the global scope). The following configuration options are available

Parameter Type Default Description
config.target Object global installs lolex onto the specified target context
config.now Number/Date 0 installs lolex with the specified unix epoch
config.toFake String[] ["setTimeout", "clearTimeout", "setImmediate", "clearImmediate","setInterval", "clearInterval", "Date", "requestAnimationFrame", "cancelAnimationFrame", "requestIdleCallback", "cancelIdleCallback", "hrtime"] an array with explicit function names to hijack. When not set, lolex will automatically fake all methods except nextTick e.g., lolex.install({ toFake: ["setTimeout","nextTick"]}) will fake only setTimeout and nextTick
config.loopLimit Number 1000 the maximum number of timers that will be run when calling runAll()
config.shouldAdvanceTime Boolean false tells lolex to increment mocked time automatically based on the real system time shift (e.g. the mocked time will be incremented by 20ms for every 20ms change in the real system time)
config.advanceTimeDelta Number 20 relevant only when using with shouldAdvanceTime: true. increment mocked time by advanceTimeDelta ms every advanceTimeDelta ms change in the real system time.

var id = clock.setTimeout(callback, timeout)

Schedules the callback to be fired once timeout milliseconds have ticked by.

In Node.js setTimeout returns a timer object. Lolex will do the same, however its ref() and unref() methods have no effect.

In browsers a timer ID is returned.

clock.clearTimeout(id)

Clears the timer given the ID or timer object, as long as it was created using setTimeout.

var id = clock.setInterval(callback, timeout)

Schedules the callback to be fired every time timeout milliseconds have ticked by.

In Node.js setInterval returns a timer object. Lolex will do the same, however its ref() and unref() methods have no effect.

In browsers a timer ID is returned.

clock.clearInterval(id)

Clears the timer given the ID or timer object, as long as it was created using setInterval.

var id = clock.setImmediate(callback)

Schedules the callback to be fired once 0 milliseconds have ticked by. Note that you'll still have to call clock.tick() for the callback to fire. If called during a tick the callback won't fire until 1 millisecond has ticked by.

In Node.js setImmediate returns a timer object. Lolex will do the same, however its ref() and unref() methods have no effect.

In browsers a timer ID is returned.

clock.clearImmediate(id)

Clears the timer given the ID or timer object, as long as it was created using setImmediate.

clock.requestAnimationFrame(callback)

Schedules the callback to be fired on the next animation frame, which runs every 16 ticks. Returns an id which can be used to cancel the callback. This is available in both browser & node environments.

clock.cancelAnimationFrame(id)

Cancels the callback scheduled by the provided id.

clock.requestIdleCallback(callback[, timeout])

Queued the callback to be fired during idle periods to perform background and low priority work on the main event loop. Callbacks which have a timeout option will be fired no later than time in milliseconds. Returns an id which can be used to cancel the callback.

clock.cancelIdleCallback(id)

Cancels the callback scheduled by the provided id.

clock.countTimers()

Returns the number of waiting timers. This can be used to assert that a test finishes without leaking any timers.

clock.hrtime(prevTime?)

Only available in Node.js, mimicks process.hrtime().

clock.nextTick(callback)

Only available in Node.js, mimics process.nextTick to enable completely synchronous testing flows.

clock.performance.now()

Only available in browser environments, mimicks performance.now().

clock.tick(time) / await clock.tickAsync(time)

Advance the clock, firing callbacks if necessary. time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.

The tickAsync() will also break the event loop, allowing any scheduled promise callbacks to execute before running the timers.

clock.next() / await clock.nextAsync()

Advances the clock to the the moment of the first scheduled timer, firing it.

The nextAsync() will also break the event loop, allowing any scheduled promise callbacks to execute before running the timers.

clock.reset()

Removes all timers and ticks without firing them, and sets now to config.now that was provided to lolex.install or to 0 if config.now was not provided. Useful to reset the state of the clock without having to uninstall and install it.

clock.runAll() / await clock.runAllAsync()

This runs all pending timers until there are none remaining. If new timers are added while it is executing they will be run as well.

This makes it easier to run asynchronous tests to completion without worrying about the number of timers they use, or the delays in those timers.

It runs a maximum of loopLimit times after which it assumes there is an infinite loop of timers and throws an error.

The runAllAsync() will also break the event loop, allowing any scheduled promise callbacks to execute before running the timers.

clock.runMicrotasks()

This runs all pending microtasks scheduled with nextTick but none of the timers and is mostly useful for libraries using lolex underneath and for running nextTick items without any timers.

clock.runToFrame()

Advances the clock to the next frame, firing all scheduled animation frame callbacks, if any, for that frame as well as any other timers scheduled along the way.

clock.runToLast() / await clock.runToLastAsync()

This takes note of the last scheduled timer when it is run, and advances the clock to that time firing callbacks as necessary.

If new timers are added while it is executing they will be run only if they would occur before this time.

This is useful when you want to run a test to completion, but the test recursively sets timers that would cause runAll to trigger an infinite loop warning.

The runToLastAsync() will also break the event loop, allowing any scheduled promise callbacks to execute before running the timers.

clock.setSystemTime([now])

This simulates a user changing the system clock while your program is running. It affects the current time but it does not in itself cause e.g. timers to fire; they will fire exactly as they would have done without the call to setSystemTime().

clock.uninstall()

Restores the original methods on the target that was passed to lolex.install, or the native timers if no target was given.

Date

Implements the Date object but using the clock to provide the correct time.

Performance

Implements the now method of the Performance object but using the clock to provide the correct time. Only available in environments that support the Performance object (browsers mostly).

lolex.withGlobal

In order to support creating clocks based on separate or sandboxed environments (such as JSDOM), Lolex exports a factory method which takes single argument global, which it inspects to figure out what to mock and what features to support. When invoking this function with a global, you will get back an object with timers, createClock and install - same as the regular Lolex exports only based on the passed in global instead of the global environment.

Running tests

Lolex has a comprehensive test suite. If you're thinking of contributing bug fixes or suggesting new features, you need to make sure you have not broken any tests. You are also expected to add tests for any new behavior.

On node:

npm test

Or, if you prefer more verbose output:

$(npm bin)/mocha ./test/lolex-test.js

In the browser

Mochify is used to run the tests in PhantomJS. Make sure you have phantomjs installed. Then:

npm test-headless

License

BSD 3-clause "New" or "Revised" License (see LICENSE file)

changelog

6.0.0 / 2020-02-04

  • Final version under the lolex name

5.1.2 / 2019-12-19

  • Use global from @sinonjs/commons
  • Fix setSystemTime affects hrtime if its called multiple times.
  • Test coverage: use nyc

5.1.1 / 2019-10-21

  • Fix global ReferenceError (#273)

5.1.0 / 2019-10-14

  • Upgrade lolex with async versions of most calls

5.0.1 / 2019-10-10

  • Upgrade eslint, add prettier
  • Use --no-detect-globals to bundle and test lolex (#270)

5.0.0 / 2019-10-07

  • Avoid installing setImmediate in unsupported environments
  • fix #246: non-constructor Date() should return a string

4.2.0 / 2019-08-04

  • Fix support for replacing the JSDOM performance field

4.1.0 / 2019-06-04

  • Fix crash on Bash version 3 (macOS)
  • Support hrtime.bigint()
  • fix: count microtasks in countTimers
  • Return empty arrays for performance.getEntries, other relevant methods

4.0.1 / 2019-04-17

  • Remove sinon: added by mistake

4.0.0 / 2019-04-17

  • Drop support for IE9 and IE10: link to supported browsers in README
  • No more ExperimentalWarnings in Node environment for queueMicrotask() if it's not used in user's code

3.1.0 / 2019-02-11

  • default timeout set to 50ms
  • first implementation of requestIdleCallback and cancelIdleCallback
  • fixed accidentally performance.now() -> x.now() replacement
  • added queueMicrotask

3.0.0 / 2018-10-08

  • Add countTimers method
  • Disallow negative ticks (breaking API change!)
  • Avoid exposing hrNow
  • Fix #207 - round-off errors in hrtime
  • Truncate sub-nanosecond values for hrtime
  • Truncate sub-millisceond values for Date.now()

v2.7.5 / 2018-09-19

  • fix: handle floating point in hrtime (#210)
  • fix: reset high resolution timer on clock.reset (#209)
  • Add an error when creating a clock with no Date object (#205)

v2.7.4 / 2018-09-05

  • performance.mark related fixes for failing Safari, IE 10 and IE 11 tests

v2.7.3 / 2018-09-05

  • Fix for #200: TypeError on performance.mark

v2.7.2 / 2018-09-04

  • fix(setInterval): parse timeout arg to integer (#202)
  • Upgrade insecure dependencies with npm audit fix

v2.7.1 / 2018-07-06

  • Fix performance replacement on iOS 9.3

v2.7.0 / 2018-05-25

  • reset clock to start
  • check Performance exists before touching it

v2.6.0 / 2018-05-16

  • Fix reset and document it publicly Clear microtick jobs and set now to 0 in reset (#179)
  • Access Date on _global (#178)

v2.5.0 / 2018-05-13

  • feat: respect loopLimit in runMicrotasks (#172)
  • assign performance as a property, not as a function

v2.4.2 / 2018-05-11

  • Upgrade Mochify to v5.6 (#162) fixed #170
  • Access Performance via _global (#168)

v2.4.1 / 2018-05-08

  • fix: handle negative infinity timeout (#165)

v2.4.0 / 2018-05-08

  • Add withGlobal export
  • expose runMicrotasks
  • Fix that performance.mark is undefined after timer install

v2.3.2 / 2018-01-29

  • Add files section to package.json to avoid unnecessary package bloat #154
  • Add missing functions in default toFake #150

v2.3.1 / 2017-11-22

  • bugfix for a setTimeout() or setSystemTime() within a nextTick() call. (#145)

v2.3.0 / 2017-11-08

  • Stops leak of (request|cancel)AnimationFrame into global scope. (#143)
  • return timers on uninstall

v2.2.0 / 2017-11-07

  • Add support for requestAnimationFrame
  • fix negative timeout bug

v2.1.3 / 2017-10-03

  • add module entry point (#133)

v2.1.2 / 2017-07-25

    • does not fake process.nextTick by default - added .idea folder to .gitignore - fixed documentation - added clock teardowns in tests
  • overflowing the timer correctly (issue #67)

v2.1.1 / 2017-07-19

  • support passing parameters in nextTick (fixes #122)

v2.1.0 / 2017-07-18

  • Throw error on incorrect install use (#112)
  • Add support for process.nextTick
  • lolex can now attach itself to the system timers and automatically ad… (#102)
  • update hrtime when an interval ticks

v2.0.0 / 2017-07-13

  • New install() signature
  • Add support for performance.now (#106)
  • Fix issue with tick(): setSystemClock then throw
  • Update old dependencies
  • Added support to automatically increment time (#85)
  • Changed internal uninstall method signature

v1.6.0 / 2017-02-25

  • Use common Sinon.JS eslint config
  • Allow install to be called with date object
  • Remove wrapper function
  • Fixed typo in clock.runAll error

v1.5.2 / 2016-11-10

  • Upgrade mocha to latest
  • Only overwrite globals when running in IE

1.5.1 / 2016-07-26

  • Fix setInterval() behavior with string times
  • Incorporate test from PR #65
  • Fix issue #59: context object required 'process'
  • fixed a case where runAll was called and there are no timers (#70)
  • Correct the clear{Interval|Timeout|Immediate} error message when calling set* for a different type of timer.
  • Lots of minor changes to tooling and the build process

v1.5.0 / 2016-05-18

  • 1.5.0
  • Check for existence of process before using it
  • Run to last existing timer
  • Add runAll method to run timers until empty
  • Turn off Sauce Labs tests for pull requests
  • Add tests demonstrating that a fake Date could be created with one argument as a String since this string is in a format recognized by the Date.parse() method.
  • Run test-cloud on Travis
  • Add process.hrtime()
  • Add bithound badge to Readme.md
  • Make Travis also run tests in node 4.2
  • Update jslint, referee, sinon, browserify, mocha, mochify
  • Rename src/lolex.js to src/lolex-src.js to avoid bithound ignoring it
  • Add .bithoundrc

v1.4.0 / 2015-12-11

  • 1.4.0
  • Remove BASH syntax in lint script
  • correct test descriptions to match the tests
  • correct parseTime() error message so it matches behavior
  • don't run test-cloud as part of npm test
  • doc: full API reference
  • doc: update 'Running tests' section
  • doc: update 'Faking the native timers' section
  • doc: remove requestAnimationFrame
  • Implement clock.next()
  • Run lint in CI
  • Fix jslint errors

v1.3.2 / 2015-09-22

  • 1.3.2
  • Fix for breaking shimmed setImmediate

v1.3.1 / 2015-08-20

  • Remove error whos reason is no longer accurate

v1.3.0 / 2015-08-19

  • 1.3.0
  • Throw exception on wrong use of clearXYZ()
  • Fix for Sinon.JS issue #808 :add setSystemTime() function
  • Fix for Sinon.JS issue #766: clearTimeout() no longer clears Immediate/Interval and vice versa
  • Update Readme.md to point to LICENSE file
  • Fix error in readme about running tests
  • Fix for warning about SPDX license format on npm install

v1.2.2 / 2015-07-22

  • 1.2.2
  • Fixing lint mistake
  • Update travis to use node@0.12
  • Fix complaint about missing fake setImmediate
  • Use license in package.json

v1.2.1 / 2015-01-06

  • New build
  • Dodge JSLint...
  • Up version
  • Proper fix for writable globals in IE
  • Make timers writable in old IEs

v1.2.0 / 2014-12-12

  • 1.2.0
  • Fix Sinon.JS issue 624
  • Lint the test files also
  • Add .jslintrc
  • Delay setImmediate if it is during tick call
  • Add test case
  • Test behaviour of hasOwnProperty beforehand
  • Compare now() with delta
  • Use undefined for defined predicate
  • Put setImmediate in toFake list
  • Capture clock instance for uninstall
  • Restore commented out tests
  • Add JSLint verification to test
  • Configure Travis to run tests in node 0.10.x
  • Add .editorconfig
  • Fail when faking Date but not setTimeout/setInterval

v1.1.10 / 2014-11-14

  • 1.1.0 Fixes setImmediate problems
  • Rely on timer initialization to null
  • Timer assembly occurs at addTimer callsites
  • Sort immediate timers before non-immediate
  • Add createdAt to timers
  • Sort timers by multiple criteria, not just callAt
  • Refactor firstTimerInRange
  • Rename timeouts property to timers
  • addTimer is options-driven

v1.0.0 / 2014-11-12

  • Add built file for browsers
  • Fix URL
  • Don't run tests that require global.proto on IE 9 and IE 10
  • Add "bundle" script to create standalone UMD bundle with browserify
  • Float with new test framework versions
  • Remove redundant module prefix
  • Let Browserify set "global" for us
  • Change test framework from Buster to Mocha and Mochify
  • Make timer functions independent on this
  • Change APIs according to Readme
  • Change clock-creating interface
  • Change Github paths
  • Basically working extraction from Sinon.JS