test: close the empty-array hole in the e2e unstubbed-request guard (closes #187)
All checks were successful
check / check (push) Successful in 42s
All checks were successful
check / check (push) Successful in 42s
batch.every() is vacuously true on an empty array, so a POST with body []
was fulfilled with 200 [] instead of being reported as an unstubbed
request. The one mechanism whose job is to fail the suite on unrecognised
outbound traffic let it through. Reject an empty batch explicitly; no real
JSON-RPC batch is empty, so nothing legitimate is caught by it.
Demonstrated by execution with a throwaway probe firing four POSTs the
harness does not stub. Before: [] fulfilled and its probe passed, while
the bodyless, scalar-JSON and [null] probes were reported and failed.
After: all four reported and failed, with tests 1-27 still green.
Also corrects the comment above the guard. postData() is
buffer.toString("utf-8") || null in playwright-core, so a binary body is
decoded lossily into invalid JSON and reported by the catch, not returned
as null; only an absent or empty body yields null and reaches the type
guard. Both paths report, but the stated reason was wrong.
This commit is contained in:
@@ -297,17 +297,26 @@ async function handleRpc(route, postData, opts, report) {
|
||||
// ethers batches by default, so the body may be an array.
|
||||
const batch = Array.isArray(payload) ? payload : [payload];
|
||||
|
||||
// Anything that is not a JSON-RPC object, or a batch of them, is not
|
||||
// RPC at all and must be reported like any other unrecognised
|
||||
// outbound traffic rather than dereferenced. request.postData()
|
||||
// returns null both for a bodyless POST and for a body Playwright
|
||||
// cannot decode as UTF-8 (sendBeacon with a Blob, or any binary
|
||||
// payload), so this is not an empty-string special case: it rejects
|
||||
// every non-object payload, exactly as the catch above rejects every
|
||||
// unparseable one.
|
||||
// Anything that is not a JSON-RPC object, or a NON-EMPTY batch of
|
||||
// them, is not RPC at all and must be reported like any other
|
||||
// unrecognised outbound traffic rather than dereferenced.
|
||||
//
|
||||
// The length check is not decoration: every() is vacuously true on an
|
||||
// empty array, so without it a POST with body [] was answered 200 []
|
||||
// and escaped the guard entirely (issue #187). No real batch is empty,
|
||||
// so nothing legitimate is caught by it.
|
||||
//
|
||||
// Two distinct paths land a non-RPC body here, and neither is an
|
||||
// empty-string special case. playwright-core's postData() is
|
||||
// `buffer.toString("utf-8") || null`, so an absent or empty body
|
||||
// decodes to null, JSON.parse("null") yields null, and the type guard
|
||||
// below reports it. A binary body is instead decoded LOSSILY into
|
||||
// mojibake — not null — which is not valid JSON, so the catch above
|
||||
// reports that one. Both end up reported; only the route differs.
|
||||
if (
|
||||
payload === null ||
|
||||
typeof payload !== "object" ||
|
||||
batch.length === 0 ||
|
||||
!batch.every((req) => req !== null && typeof req === "object")
|
||||
) {
|
||||
report("unstubbed request: POST " + route.request().url());
|
||||
|
||||
Reference in New Issue
Block a user