web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
14 KiB

  1. # `@sinonjs/fake-timers`
  2. [![CircleCI](https://circleci.com/gh/sinonjs/fake-timers.svg?style=svg)](https://circleci.com/gh/sinonjs/fake-timers)
  3. [![codecov](https://codecov.io/gh/sinonjs/fake-timers/branch/master/graph/badge.svg)](https://codecov.io/gh/sinonjs/fake-timers)
  4. <a href="CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Contributor Covenant" /></a>
  5. 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. FakeTimers also provides a `Date` implementation that gets its time from the clock.
  6. In addition in browser environment `@sinonjs/fake-timers` provides a `performance` implementation that gets its time from the clock. In Node environments FakeTimers provides a `nextTick` implementation that is synchronized with the clock - and a `process.hrtime` shim that works with the clock.
  7. `@sinonjs/fake-timers` can be used to simulate passing time in automated tests and other
  8. situations where you want the scheduling semantics, but don't want to actually
  9. wait.
  10. `@sinonjs/fake-timers` is extracted from [Sinon.JS](https://github.com/sinonjs/sinon.js) and targets the [same runtimes](https://sinonjs.org/releases/latest/#supported-runtimes).
  11. ## Installation
  12. `@sinonjs/fake-timers` can be used in both Node and browser environments. Installation is as easy as
  13. ```sh
  14. npm install @sinonjs/fake-timers
  15. ```
  16. If you want to use `@sinonjs/fake-timers` in a browser you can use [the pre-built
  17. version](https://github.com/sinonjs/fake-timers/blob/master/fake-timers.js) available in the repo
  18. and the npm package. Using npm you only need to reference `./node_modules/@sinonjs/fake-timers/fake-timers.js` in your `<script>` tags.
  19. You are always free to [build it yourself](https://github.com/sinonjs/fake-timers/blob/53ea4d9b9e5bcff53cc7c9755dc9aa340368cf1c/package.json#L22), of course.
  20. ## Usage
  21. To use `@sinonjs/fake-timers`, create a new clock, schedule events on it using the timer
  22. functions and pass time using the `tick` method.
  23. ```js
  24. // In the browser distribution, a global `FakeTimers` is already available
  25. var FakeTimers = require("@sinonjs/fake-timers");
  26. var clock = FakeTimers.createClock();
  27. clock.setTimeout(function () {
  28. console.log("The poblano is a mild chili pepper originating in the state of Puebla, Mexico.");
  29. }, 15);
  30. // ...
  31. clock.tick(15);
  32. ```
  33. Upon executing the last line, an interesting fact about the
  34. [Poblano](http://en.wikipedia.org/wiki/Poblano) will be printed synchronously to
  35. the screen. If you want to simulate asynchronous behavior, you have to use your
  36. imagination when calling the various functions.
  37. The `next`, `runAll`, `runToFrame`, and `runToLast` methods are available to advance the clock. See the
  38. API Reference for more details.
  39. ### Faking the native timers
  40. When using `@sinonjs/fake-timers` to test timers, you will most likely want to replace the native
  41. timers such that calling `setTimeout` actually schedules a callback with your
  42. clock instance, not the browser's internals.
  43. Calling `install` with no arguments achieves this. You can call `uninstall`
  44. later to restore things as they were again.
  45. ```js
  46. // In the browser distribution, a global `FakeTimers` is already available
  47. var FakeTimers = require("@sinonjs/fake-timers");
  48. var clock = FakeTimers.install();
  49. // Equivalent to
  50. // var clock = FakeTimers.install(typeof global !== "undefined" ? global : window);
  51. setTimeout(fn, 15); // Schedules with clock.setTimeout
  52. clock.uninstall();
  53. // setTimeout is restored to the native implementation
  54. ```
  55. To hijack timers in another context pass it to the `install` method.
  56. ```js
  57. var FakeTimers = require("@sinonjs/fake-timers");
  58. var context = {
  59. setTimeout: setTimeout // By default context.setTimeout uses the global setTimeout
  60. }
  61. var clock = FakeTimers.install({target: context});
  62. context.setTimeout(fn, 15); // Schedules with clock.setTimeout
  63. clock.uninstall();
  64. // context.setTimeout is restored to the original implementation
  65. ```
  66. Usually you want to install the timers onto the global object, so call `install`
  67. without arguments.
  68. #### Automatically incrementing mocked time
  69. Since version 2.0 FakeTimers supports the possibility to attach the faked timers
  70. to any change in the real system time. This basically means you no longer need
  71. to `tick()` the clock in a situation where you won't know **when** to call `tick()`.
  72. Please note that this is achieved using the original setImmediate() API at a certain
  73. configurable interval `config.advanceTimeDelta` (default: 20ms). Meaning time would
  74. be incremented every 20ms, not in real time.
  75. An example would be:
  76. ```js
  77. var FakeTimers = require("@sinonjs/fake-timers");
  78. var clock = FakeTimers.install({shouldAdvanceTime: true, advanceTimeDelta: 40});
  79. setTimeout(() => {
  80. console.log('this just timed out'); //executed after 40ms
  81. }, 30);
  82. setImmediate(() => {
  83. console.log('not so immediate'); //executed after 40ms
  84. });
  85. setTimeout(() => {
  86. console.log('this timed out after'); //executed after 80ms
  87. clock.uninstall();
  88. }, 50);
  89. ```
  90. ## API Reference
  91. ### `var clock = FakeTimers.createClock([now[, loopLimit]])`
  92. Creates a clock. The default
  93. [epoch](https://en.wikipedia.org/wiki/Epoch_%28reference_date%29) is `0`.
  94. The `now` argument may be a number (in milliseconds) or a Date object.
  95. 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`.
  96. ### `var clock = FakeTimers.install([config])`
  97. Installs FakeTimers using the specified config (otherwise with epoch `0` on the global scope). The following configuration options are available
  98. Parameter | Type | Default | Description
  99. --------- | ---- | ------- | ------------
  100. `config.target`| Object | global | installs FakeTimers onto the specified target context
  101. `config.now` | Number/Date | 0 | installs FakeTimers with the specified unix epoch
  102. `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, FakeTimers will automatically fake all methods **except** `nextTick`* e.g., `FakeTimers.install({ toFake: ["setTimeout","nextTick"]})` will fake only `setTimeout` and `nextTick`
  103. `config.loopLimit` | Number | 1000 | the maximum number of timers that will be run when calling runAll()
  104. `config.shouldAdvanceTime` | Boolean | false | tells FakeTimers 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)
  105. `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.
  106. ### `var id = clock.setTimeout(callback, timeout)`
  107. Schedules the callback to be fired once `timeout` milliseconds have ticked by.
  108. In Node.js `setTimeout` returns a timer object. FakeTimers will do the same, however
  109. its `ref()` and `unref()` methods have no effect.
  110. In browsers a timer ID is returned.
  111. ### `clock.clearTimeout(id)`
  112. Clears the timer given the ID or timer object, as long as it was created using
  113. `setTimeout`.
  114. ### `var id = clock.setInterval(callback, timeout)`
  115. Schedules the callback to be fired every time `timeout` milliseconds have ticked
  116. by.
  117. In Node.js `setInterval` returns a timer object. FakeTimers will do the same, however
  118. its `ref()` and `unref()` methods have no effect.
  119. In browsers a timer ID is returned.
  120. ### `clock.clearInterval(id)`
  121. Clears the timer given the ID or timer object, as long as it was created using
  122. `setInterval`.
  123. ### `var id = clock.setImmediate(callback)`
  124. Schedules the callback to be fired once `0` milliseconds have ticked by. Note
  125. that you'll still have to call `clock.tick()` for the callback to fire. If
  126. called during a tick the callback won't fire until `1` millisecond has ticked
  127. by.
  128. In Node.js `setImmediate` returns a timer object. FakeTimers will do the same,
  129. however its `ref()` and `unref()` methods have no effect.
  130. In browsers a timer ID is returned.
  131. ### `clock.clearImmediate(id)`
  132. Clears the timer given the ID or timer object, as long as it was created using
  133. `setImmediate`.
  134. ### `clock.requestAnimationFrame(callback)`
  135. Schedules the callback to be fired on the next animation frame, which runs every
  136. 16 ticks. Returns an `id` which can be used to cancel the callback. This is
  137. available in both browser & node environments.
  138. ### `clock.cancelAnimationFrame(id)`
  139. Cancels the callback scheduled by the provided id.
  140. ### `clock.requestIdleCallback(callback[, timeout])`
  141. 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.
  142. ### `clock.cancelIdleCallback(id)`
  143. Cancels the callback scheduled by the provided id.
  144. ### `clock.countTimers()`
  145. Returns the number of waiting timers. This can be used to assert that a test
  146. finishes without leaking any timers.
  147. ### `clock.hrtime(prevTime?)`
  148. Only available in Node.js, mimicks process.hrtime().
  149. ### `clock.nextTick(callback)`
  150. Only available in Node.js, mimics `process.nextTick` to enable completely synchronous testing flows.
  151. ### `clock.performance.now()`
  152. Only available in browser environments, mimicks performance.now().
  153. ### `clock.tick(time)` / `await clock.tickAsync(time)`
  154. Advance the clock, firing callbacks if necessary. `time` may be the number of
  155. milliseconds to advance the clock by or a human-readable string. Valid string
  156. formats are `"08"` for eight seconds, `"01:00"` for one minute and `"02:34:10"`
  157. for two hours, 34 minutes and ten seconds.
  158. The `tickAsync()` will also break the event loop, allowing any scheduled promise
  159. callbacks to execute _before_ running the timers.
  160. ### `clock.next()` / `await clock.nextAsync()`
  161. Advances the clock to the the moment of the first scheduled timer, firing it.
  162. The `nextAsync()` will also break the event loop, allowing any scheduled promise
  163. callbacks to execute _before_ running the timers.
  164. ### `clock.reset()`
  165. Removes all timers and ticks without firing them, and sets `now` to `config.now`
  166. that was provided to `FakeTimers.install` or to `0` if `config.now` was not provided.
  167. Useful to reset the state of the clock without having to `uninstall` and `install` it.
  168. ### `clock.runAll()` / `await clock.runAllAsync()`
  169. 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.
  170. 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.
  171. It runs a maximum of `loopLimit` times after which it assumes there is an infinite loop of timers and throws an error.
  172. The `runAllAsync()` will also break the event loop, allowing any scheduled promise
  173. callbacks to execute _before_ running the timers.
  174. ### `clock.runMicrotasks()`
  175. This runs all pending microtasks scheduled with `nextTick` but none of the timers and is mostly useful for libraries using FakeTimers underneath and for running `nextTick` items without any timers.
  176. ### `clock.runToFrame()`
  177. Advances the clock to the next frame, firing all scheduled animation frame callbacks,
  178. if any, for that frame as well as any other timers scheduled along the way.
  179. ### `clock.runToLast()` / `await clock.runToLastAsync()`
  180. This takes note of the last scheduled timer when it is run, and advances the
  181. clock to that time firing callbacks as necessary.
  182. If new timers are added while it is executing they will be run only if they
  183. would occur before this time.
  184. This is useful when you want to run a test to completion, but the test recursively
  185. sets timers that would cause `runAll` to trigger an infinite loop warning.
  186. The `runToLastAsync()` will also break the event loop, allowing any scheduled promise
  187. callbacks to execute _before_ running the timers.
  188. ### `clock.setSystemTime([now])`
  189. This simulates a user changing the system clock while your program is running.
  190. It affects the current time but it does not in itself cause e.g. timers to fire;
  191. they will fire exactly as they would have done without the call to
  192. setSystemTime().
  193. ### `clock.uninstall()`
  194. Restores the original methods on the `target` that was passed to
  195. `FakeTimers.install`, or the native timers if no `target` was given.
  196. ### `Date`
  197. Implements the `Date` object but using the clock to provide the correct time.
  198. ### `Performance`
  199. Implements the `now` method of the [`Performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) object but using the clock to provide the correct time. Only available in environments that support the Performance object (browsers mostly).
  200. ### `FakeTimers.withGlobal`
  201. In order to support creating clocks based on separate or sandboxed environments (such as JSDOM), FakeTimers 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 FakeTimers exports only based on the passed in global instead of the global environment.
  202. ## Running tests
  203. FakeTimers has a comprehensive test suite. If you're thinking of contributing bug
  204. fixes or suggesting new features, you need to make sure you have not broken any
  205. tests. You are also expected to add tests for any new behavior.
  206. ### On node:
  207. ```sh
  208. npm test
  209. ```
  210. Or, if you prefer more verbose output:
  211. ```
  212. $(npm bin)/mocha ./test/fake-timers-test.js
  213. ```
  214. ### In the browser
  215. [Mochify](https://github.com/mantoni/mochify.js) is used to run the tests in
  216. PhantomJS. Make sure you have `phantomjs` installed. Then:
  217. ```sh
  218. npm test-headless
  219. ```
  220. ## License
  221. BSD 3-clause "New" or "Revised" License (see LICENSE file)