Open mohanraj-r opened 3 years ago
Thanks for the issue. Could you provide an example of a test using axe and fake timers? Axe doesn't use too many timeouts
so I'm not sure if timers would help make axe mock a run.
Here is a minimal example @straker
describe('demo axe timeout with mock timer', () => {
it('should not timeout when using mock timer', async () => {
jest.useFakeTimers(); // Commenting this line out will make the test pass
await axe.run();
});
});
Running the above test with Jest results in timeout error.
demo axe timeout with mock timer
✕ should not timeout when using mock timer (5022 ms)
● demo axe timeout with mock timer › should not timeout when using mock timer
: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error:
39 |
40 | describe('demo axe timeout with mock timer', () => {
> 41 | it('should not timeout when using mock timer', async () => {
| ^
42 | jest.useFakeTimers();
43 | await axe.run();
44 | });
at new Spec (../../node_modules/jest-jasmine2/build/jasmine/Spec.js:116:22)
at Suite.<anonymous> (__tests__/jest.test.js:41:5)
at Object.<anonymous> (__tests__/jest.test.js:40:1)
Test Suites: 1 failed, 1 total
Out of curiosity, does jest.runAllTimers();
help at all?
Tried jest.runAllTimers();
- it doesn't help, still times out.
@mohanraj-r any guess as to what is causing the issue? If you're up for it, we'd appreciate a pull request. Axe-core needs setTimeout
for a few things. I'm not sure if there is a way around it, but if you have an idea, we'd be open to it.
I wonder if people are still encountering this issue. Been more than a year now. 👀
I am still seeing it with fake timers.
Looks like we need a way to let axe-core
use/remember the original setTimeout
before fake timer is installed.
I think axe-core
should add an option to axe.configure()
and allow passing the real setTimeout
in case the clock is faked/polluted.
AFAIK, axe-core
use setTimeout
for checking things across frames (including the main frame). When a fake timer (jest
, sinonjs
, or lolex
) is installed globally, axe-core
will use the globally polluted setTimeout
and it would fail all checks.
The alternative is to ask the app developer not to pollute the global setTimeout
. I have done this in one of my repos. This is very tricky and very limited because:
setTimeout
, setInterval
, and the whole Date
class
Date
class, think about the code calling Date.now()
and new Date().getTime()
, both should return 0
Date
class could be used everywhere in the appsetTimeout()
, setInterval()
, Date.now()
, and Date.prototype.getXXX()
0
, while the 3P is on a date of "now")So, it is much easier for axe-core
to use a setTimeout
passed from the axe.configure()
.
Was this ever solved? I'm seeing the same issue even if I advance my timer before using axe()
Product: axe-core
Expectation: axe-core does not timeout when timer is mocked in JS unit tests
Actual: When mock timers are used with axe (e.g. jest.useFakeTimers()), tests fail with error "Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Timeout"
Motivation: Mocking timers are common in JS unit tests. Getting axe-core to work as expected even when mock timers are being used would be great. The timeout issue occurs even with other third-party mock timer libs such as @sinonjs/fake-timers - so it is not a problem just with Jest.
Something about mocking timers results in axe timeout - not sure why ?