Testing with mock clocks can often turn into a real struggle when
dealing with situations where some work in the test is truly async and
other work is captured by the mock clock. This can happen for many
reasons, but as one example:
An asynchonrous change from a task in the mocked clock may change DOM where
a resize observer then gets triggered. This browser API is truly asynchronous
and would require the user to wait real time for it to fire. If there is
follow-up work after the resize observer fires, it may be captured by the mock
clock again. This would require the tester to write something like the
following:
```
// flush the timer
jasmine.clock().tick();
// wait for resize observer
await new Promise(resolve => setTimeout(resolve));
// flush follow-up work from the resize observer callback
jasmine.clock().tick();
```
When using mock clocks, testers are always forced to write tests with intimate
knowledge of when the mock clock needs to be ticked. Oftentimes, the
purpose of using a mock clock is to speed up the execution time of the
test when there are timeouts involved. It is not often a goal to test
the exact timeout values. This can cause tests to be riddled with
`tick`. It ideal for test code to be written in a way
that is independent of whether a mock clock is installed. For example:
```
document.getElementById('submit');
// https://testing-library.com/docs/dom-testing-library/api-async/#waitfor
await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1))
```
When mock clocks are involved, the above may not be possible if there is
some delay involved between the click and the request to the API.
Instead, developers would need to manually tick the clock beyond the
delay to trigger the API call.
This commit attempts to resolve these issues by adding a feature to the
clock which allows it to advance on its own with the passage of time,
just as clocks do without mocks installed. It also allows for some
breathing time so any unmocked micro and macrotasks are given space to
execute as well.
This feature would also address both #1725 and #1932. `asyncTick` can be
accomplished by enabling the auto tick feature and then waiting for a
promise with a timout to be resolved
(`await new Promise(resolve => setTimeout(resolve, 20))`) where
`setTimeout` is captured by the mock clock and flushed while the code is
waiting for the promise to resolve.
resolves #1725
resolves #1932
All credit goes to @stephenfarrar for this.
A JavaScript Testing Framework
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, Node.js projects, or anywhere that JavaScript can run.
Upgrading from Jasmine 4.x? Check out the upgrade guide.
Contributing
Please read the contributors' guide.
Installation
There are several different ways to install Jasmine, depending on your environment and how you'd like to use it. See the Getting Started page for details.
Usage
See the documentation site, particularly the Your First Suite tutorial for information on writing specs, and the FAQ.
Supported environments
Jasmine tests itself across popular browsers (Safari, Chrome, Firefox, and Microsoft Edge) as well as Node.
| Environment | Supported versions |
|---|---|
| Node | 18, 20, 22 |
| Safari | 15-17 |
| Chrome | Evergreen |
| Firefox | Evergreen, 102, 115 |
| Edge | Evergreen |
For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work. However, Jasmine isn't tested against them and they aren't actively supported.
To find out what environments work with a particular Jasmine release, see the release notes.
Maintainers
Maintainers Emeritus
- Davis W. Frank
- Rajan Agaskar
- Greg Cobb
- Chris Amavisca
- Christian Williams
- Sheel Choksi
Copyright (c) 2008-2019 Pivotal Labs
Copyright (c) 2008-2023 The Jasmine developers
This software is licensed under the MIT License.