You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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>
Copy file name to clipboardExpand all lines: packages/client/src/oauth-applications-register-request-members.test.ts
+23-9Lines changed: 23 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -53,7 +53,8 @@
53
53
* `scopes` → `scope` is not a rename: `scope` is one space-delimited string,
54
54
* and the array form is driven-refused with
55
55
* `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.
57
58
*
58
59
* `metadata` has no reachable door at all: only the SERVER_ONLY
59
60
* `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
210
211
expect(init.body).toBe(JSON.stringify(req));
211
212
});
212
213
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.
220
233
constfetchMock=vi.fn(
221
234
async()=>
222
235
newResponse(
@@ -232,7 +245,8 @@ describe('#15447 oauth.applications.register — the honoured members still reac
232
245
c.oauth.applications.register({
233
246
client_name: 'CTRL-CLIENT-NAME-15447',
234
247
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
0 commit comments