11import { describe , expect , test } from "bun:test" ;
2+ import { setTimeout as delay } from "node:timers/promises" ;
23
34import type { CallbackPageCopy } from "../callback-page.js" ;
4- import { XAI_CALLBACK_PORT } from "./constants.js" ;
5+ import { XAI_CALLBACK_PATH , XAI_CALLBACK_PORT } from "./constants.js" ;
56import { startXaiCallbackServer } from "./callback-server.js" ;
67
78const copy : CallbackPageCopy = {
@@ -12,12 +13,13 @@ const copy: CallbackPageCopy = {
1213 githubLabel : "github.com/fixture" ,
1314} ;
1415
15- const base = `http://127.0.0.1:${ String ( XAI_CALLBACK_PORT ) } /callback ` ;
16+ const base = `http://127.0.0.1:${ String ( XAI_CALLBACK_PORT ) } ${ XAI_CALLBACK_PATH } ` ;
1617
1718describe ( "xAI callback server" , ( ) => {
1819 test ( "accepts a matching state and returns the code" , async ( ) => {
1920 const server = await startXaiCallbackServer ( "expected" , copy ) ;
2021 try {
22+ expect ( server . port ) . toBe ( XAI_CALLBACK_PORT ) ;
2123 const wait = server . waitForCode ( new AbortController ( ) . signal ) ;
2224 const res = await fetch ( `${ base } ?code=abc&state=expected` ) ;
2325 expect ( res . status ) . toBe ( 200 ) ;
@@ -27,20 +29,21 @@ describe("xAI callback server", () => {
2729 }
2830 } ) ;
2931
30- test ( "rejects state mismatches before accepting a code " , async ( ) => {
32+ test ( "keeps waiting after a state mismatch until a matching redirect " , async ( ) => {
3133 const server = await startXaiCallbackServer ( "expected" , copy ) ;
3234 try {
33- const wait = server . waitForCode ( new AbortController ( ) . signal ) . then (
34- ( ) => ( { ok : true as const } ) ,
35- ( err : unknown ) => ( { ok : false as const , err } ) ,
36- ) ;
37- const res = await fetch ( `${ base } ?code=abc&state=wrong` ) ;
38- expect ( res . status ) . toBe ( 400 ) ;
39- const result = await wait ;
40- expect ( result . ok ) . toBe ( false ) ;
41- if ( ! result . ok ) expect ( result . err ) . toBeInstanceOf ( Error ) ;
42- if ( ! result . ok && result . err instanceof Error )
43- expect ( result . err . message ) . toMatch ( / s t a t e d i d n o t m a t c h / ) ;
35+ const wait = server . waitForCode ( new AbortController ( ) . signal ) ;
36+ const mismatch = await fetch ( `${ base } ?code=abc&state=wrong` ) ;
37+ expect ( mismatch . status ) . toBe ( 400 ) ;
38+ expect (
39+ await Promise . race ( [
40+ wait . then ( ( ) => "settled" ) ,
41+ delay ( 50 ) . then ( ( ) => "pending" ) ,
42+ ] ) ,
43+ ) . toBe ( "pending" ) ;
44+ const match = await fetch ( `${ base } ?code=abc&state=expected` ) ;
45+ expect ( match . status ) . toBe ( 200 ) ;
46+ await expect ( wait ) . resolves . toBe ( "abc" ) ;
4447 } finally {
4548 server . close ( ) ;
4649 }
0 commit comments