Skip to content

Commit 5e38385

Browse files
committed
test(client): the array-form scope case sends the body that produced the recorded 400
The third case in the #15447 pin paired a VALID request (the joined string the route accepts with 201) with the error the INVALID request produces, against a double that answers 400 unconditionally — so its title asserted two things the case could not see. It now sends the array form through a suppression, which is the body that actually drew the recorded refusal, and the title and comment say what it pins: the SDK's handling of that refusal, never the route's verdict. The suppression is load-bearing: after this card's narrowing the array form is no longer expressible through the declared type, and widening `scope` to accept one leaves the directive unused and this case red. Claude-Session: https://claude.ai/code/session_015QE8qk46e5CHJxyQEUjbf8 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3277d03 commit 5e38385

1 file changed

Lines changed: 23 additions & 9 deletions

File tree

packages/client/src/oauth-applications-register-request-members.test.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
* `scopes` → `scope` is not a rename: `scope` is one space-delimited string,
5454
* and the array form is driven-refused with
5555
* `400 [body.scope] Invalid input: expected string, received array`. The
56-
* space-joined case below is that prescription, pinned.
56+
* FIRST case below sends that prescription, byte for byte; the third pins what
57+
* the SDK does with the refusal the array form draws.
5758
*
5859
* `metadata` has no reachable door at all: only the SERVER_ONLY
5960
* `PATCH /admin/oauth2/update-client` honours it, and `better-call`'s router
@@ -210,13 +211,25 @@ describe('#15447 oauth.applications.register — the honoured members still reac
210211
expect(init.body).toBe(JSON.stringify(req));
211212
});
212213

213-
it('the space-joined `scope` is what the route accepts — the array form is refused on the wire', async () => {
214-
// Driven, not invented: posting `scope: ['openid','profile']` answered
215-
// `400 [body.scope] Invalid input: expected string, received array`, while
216-
// `['openid','profile'].join(' ')` answered 201 with
217-
// `"scope":"openid profile"`. This case pins that the SDK surfaces the
218-
// refusal rather than papering over it — the reason a caller's array must
219-
// be joined at the CALL SITE and not by a translation layer here.
214+
it("surfaces the route's refusal of an array-form `scope` rather than swallowing it", async () => {
215+
// ⚠️ The 400 below is a RECORDED response, replayed — never one this test
216+
// produces. It is the verbatim answer the driven run got (issue #15447,
217+
// comment 5559384773) from posting `scope: ['openid','profile']` at the
218+
// real route; the same run got 201 and `"scope":"openid profile"` back from
219+
// `['openid','profile'].join(' ')`. ⛔ Nothing here re-drives that, so what
220+
// this case pins is the SDK's HANDLING of the refusal — that it surfaces
221+
// it rather than papering over it — and never the route's own verdict,
222+
// which a transport double answering 400 unconditionally cannot witness.
223+
//
224+
// The request carries the ARRAY form, spelled through a suppression,
225+
// because that is the body which actually produced the recorded 400 —
226+
// pairing it with the joined body the route ACCEPTS would be a fixture
227+
// asserting one request's answer against another request. The suppression
228+
// is load-bearing twice: after this card's narrowing the array form is no
229+
// longer expressible through the declared type at all (the removed
230+
// `scopes` was the member that invited it), which is the fact that makes
231+
// the pairing honest rather than merely relabelled; and if `scope` is ever
232+
// widened to accept an array, the directive goes unused and this goes red.
220233
const fetchMock = vi.fn(
221234
async () =>
222235
new Response(
@@ -232,7 +245,8 @@ describe('#15447 oauth.applications.register — the honoured members still reac
232245
c.oauth.applications.register({
233246
client_name: 'CTRL-CLIENT-NAME-15447',
234247
redirect_uris: ['https://app.example.com/cb'],
235-
scope: 'openid profile email',
248+
// @ts-expect-error [#15447] `scope` is ONE space-delimited string; the array is what the recorded 400 refuses, and the narrowed type no longer lets a caller spell it
249+
scope: ['openid', 'profile', 'email'],
236250
}),
237251
).rejects.toThrow(/expected string, received array/);
238252
});

0 commit comments

Comments
 (0)