Repository navigation
Test runner: spurious "Promise resolution is still pending but the event loop has already resolved" when a callback tests fails #51381
Copy link
Copy link
Closed
Labels
confirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.test_runnerIssues and PRs related to the test runner subsystem.Issues and PRs related to the test runner subsystem.
Description
Version
v21.4.0
Platform
Microsoft Windows NT 10.0.22621.0 x64
Subsystem
test
What steps will reproduce the bug?
Run the following code with node --test test.js:
"use strict";
const { describe, test } = require("node:test");
const assert = require("node:assert");
describe("describe wrapper", () => {
test("callback test", (t, done) => {
setTimeout(() => {
assert.ok(false, "oh no an assert failed");
done();
});
});
test("promise test", async () => {
assert.ok(true, "this assert will pass");
});
});
describe("another describe block", () => {
test("sync test", () => {
assert.ok(true, "this assert will pass 2");
});
});How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
It should tell me that "callback test" alone is failing
What do you see instead?
It shows four failure messages: one for callback test (correct), one for describe wrapper, one for sync test, and one for another describe block. The latter three have a (green??) 'Promise resolution is still pending but the event loop has already resolved' failure reason.
$ node --test test.js
▶ describe wrapper
✖ callback test (2.4042ms)
AssertionError [ERR_ASSERTION]: oh no an assert failed
at Timeout._onTimeout (C:\Users\d\OneDrive - domenic.me\Code\GitHub\jsdom\jsdom\test.js:8:14)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}
✔ promise test (0.2519ms)
▶ describe wrapper (5.4167ms)
'Promise resolution is still pending but the event loop has already resolved'
▶ another describe block
✖ sync test
'Promise resolution is still pending but the event loop has already resolved'
▶ another describe block
'Promise resolution is still pending but the event loop has already resolved'
ℹ tests 3
ℹ suites 2
ℹ pass 1
ℹ fail 1
ℹ cancelled 1
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 47.7459
✖ failing tests:
test at test.js:6:3
✖ callback test (2.4042ms)
AssertionError [ERR_ASSERTION]: oh no an assert failed
at Timeout._onTimeout (C:\Users\d\OneDrive - domenic.me\Code\GitHub\jsdom\jsdom\test.js:8:14)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}
test at test.js:5:1
✖ describe wrapper (5.4167ms)
'Promise resolution is still pending but the event loop has already resolved'
test at test.js:19:3
✖ sync test
'Promise resolution is still pending but the event loop has already resolved'
test at test.js:18:1
✖ another describe block
'Promise resolution is still pending but the event loop has already resolved'
Additional information
There isn't a lot of documentation about callback-style tests...
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
confirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.test_runnerIssues and PRs related to the test runner subsystem.Issues and PRs related to the test runner subsystem.
Activity
marco-ippolito commentedon Jan 5, 2024
You can just remove
doneand it will work as expected.AFAIK
doneis useful when you have function thats take a callback and you want to check that it is called or when for some reason can't use assertions:PRs to improve the documentation are always welcomed
domenic commentedon Jan 5, 2024
That doesn't quite work as expected. In that case, the error gets thrown disconnected from any test, so it looks like all tests are passing, but then there's a mysterious
'test failed'(again, in green?) and a discussion about generating async activity.Modified script
Output:
My expectation is that callback tests wait on the callback to be called, or an error to be thrown, in order to tie any thrown errors to the in-progress test. That's how they work in other test frameworks.
benjamingr commentedon Jan 5, 2024
@nodejs/test_runner @MoLow I think in any case the callback test failing shouldn't interfere with any of the other tests.
Re: the second example - The "fail the test file for an uncaught error" behavior actually seems reasonable to me.
MoLow commentedon Jan 6, 2024
I agree with both these statments
marco-ippolito commentedon Feb 4, 2024
If the test goes in 'uncaughtException' it's not possible to recover, so it will interfere with other test.
I agree with the second statement
domenic commentedon Feb 4, 2024
In other test frameworks, the framework is responsible for catching the exception, so it never reaches uncaughtException.
cjihrig commentedon Feb 9, 2024
This seems to fix the issue. The problem is that this never finishes.
It might also be worth considering
ref()'ingthis timer or implementing another waiting technique, because currently, the following code does not honor its timeout.It might also be worth considering setting a reasonable default test timeout instead of Infinity for the same reason.
Speaking of test timeouts, the new
--test-timeoutCLI flag behaves surprisingly. Consider the following code run with--test-timeout=2000. It correctly times out when used with--test, but passes without--test. I believe that's because it is not incorporated intoparseCommandLine()and the logic that uses it.test_runner: abort unfinished tests on async error
test_runner: abort unfinished tests on async error
test_runner: abort unfinished tests on async error
TechQuery commentedon Aug 24, 2024
I find a similar bug that Node.js test runner works well in Codespaces and throw errors just like this issue in GitHub actions, they are all running in latest Linux + Node.js 20:
avivkeller commentedon Aug 24, 2024
Hey, this issue has been resolved for several months. If you're experiencing an issue, please open a new issue or visit nodejs/help.
fix(reference-implementation): fix the pending-promise-at-exit cluste…
fix(reference-implementation): unblock the Move-B CI seam (typecheck …
test: estabiliza los 2 flakes por carga (AbortSignal.timeout es unref…
test: stabilize abort-timeout mocks and Redis command scans (#8392)