Skip to content

@roamhq/wrtc (node-webrtc) emits/keeps late events after pc.close() causing Node test file to fail at 1:1 even though all subtests pass #37

@collapsinghierarchy

Description

@collapsinghierarchy

I’m a bit stuck. I’ve tried just about everything, and while all my non-WebRTC tests pass, any test that wires in WebRTC fails due to something that seems to happen outside the actual test. This might be my unfamiliarity with Node’s test runner, but I haven’t been able to pin it down yet.

Environment

  • OS: Windows 11 + WSL2 Ubuntu (fill in exact distro/kernel)
  • Node.js: v20.19.4
  • @roamhq/[email protected]
  • Repro is pure datachannel (no media), local host ICE only

Using a tiny in-process WebSocket broker and two wrtc peers (A initiator, B responder) (see the attached and self-contained test file):

  • Both non-trickle and trickle open a DataChannel successfully
  • Messages ping/echo both ways
  • We then close the peers and the broker and wait a tick
  • All subtests pass, but Node’s test runner still reports the file failed at line 1:1 (“anonymous test”), i.e., something fires after tests complete.

We’ve already:

  • Made teardown idempotent (clear timers, remove every listener, null pc.on..., close DC if not closed)
  • Silenced ws socket/server 'error' events
  • Made the broker’s close() idempotent and terminate any clients
  • Added a global process.on('uncaughtException'/'unhandledRejection') trap so late throws are captured (final test confirms no late errors)
  • Ensured exactly-one EoC (candidate:null) in trickle mode (send on DC open if not seen)
    Still, the file fails at 1:1 even though the last two tests pass.

Expected

After we close both peer connections and the broker, the process should go idle and the test file should finish without a top-level failure.

Actual

`=== CASE trickle=false ===
[A] setLocal(offer)
gather change -> complete
[A] sent offer (non-trickle, completed=true, waitMs=53)
...
✔ wrtc e2e (non-trickle...) (…ms)

=== CASE trickle=true ===
… (similar, with EoC on open)
✔ wrtc e2e (trickle...) (…ms)
✔ no late errors after wrtc e2e (…ms)
ℹ tests 4
ℹ suites 0
ℹ pass 3
ℹ fail 1
✖ /path/to/wrtc_e2e.test.mjs (2719.757474ms)
'test failed'`

"Minimal" Repro

Dependencies: npm i @roamhq/wrtc ws

wrtc_e2e.test.js

Notes

  • The failure seems not to be an unhandled exception. it looks either
    • Some internal handle stays open post-teardown (libwebrtc thread/socket) and the test runner flags the file, or
    • A late event on a closed PC/DC fires outside the tests and triggers Node’s runner behavior.
  • If there’s a recommended canonical teardown order for wrtc to fully quiesce (beyond pc.close() + removing listeners), please advise. If any thread needs a tick to join, we can await a promise/hook.

Thanks a ton!

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions