@@ -6,6 +6,11 @@ import {
66 postJson ,
77} from "./test-utils" ;
88
9+ // ---- In-memory sessions fixture (simulates FK target) ----
10+ // Pre-seeded IDs that are valid FK targets for session_id.
11+ // Tests that use sessionId: 42 must find it here; others must not.
12+ const VALID_SESSION_IDS = new Set < number > ( [ 42 ] ) ;
13+
914// ---- In-memory store simulating agent_sessions table ----
1015
1116let nextId = 1 ;
@@ -16,6 +21,7 @@ let store: Array<{
1621 session_type : string ;
1722 issue_number : number | null ;
1823 checklist_md : string ;
24+ session_id : number | null ;
1925 status : string ;
2026 started_at : Date ;
2127 completed_at : Date | null ;
@@ -48,6 +54,7 @@ const dispatch: SqlDispatcher = (query, params) => {
4854 session_type : params [ 2 ] as string ,
4955 issue_number : params [ 3 ] as number | null ,
5056 checklist_md : params [ 4 ] as string ,
57+ session_id : null ,
5158 status : "active" ,
5259 started_at : new Date ( ) ,
5360 completed_at : null ,
@@ -88,6 +95,17 @@ const dispatch: SqlDispatcher = (query, params) => {
8895 case "checklist_md" :
8996 store [ idx ] . checklist_md = params [ pIdx ] as string ;
9097 break ;
98+ case "session_id" : {
99+ const sid = params [ pIdx ] as number | null ;
100+ if ( sid !== null && ! VALID_SESSION_IDS . has ( sid ) ) {
101+ // Simulate FK constraint violation — the route translates this to 400.
102+ throw new Error (
103+ `insert or update on table "agent_sessions" violates foreign key constraint`
104+ ) ;
105+ }
106+ store [ idx ] . session_id = sid ;
107+ break ;
108+ }
91109 case "status" :
92110 store [ idx ] . status = params [ pIdx ] as string ;
93111 break ;
@@ -486,6 +504,61 @@ describe("Agent Sessions API", () => {
486504 } ) ;
487505 expect ( res . status ) . toBe ( 400 ) ;
488506 } ) ;
507+
508+ it ( "sets sessionId FK link to session log" , async ( ) => {
509+ await postJson ( app , "/api/agent-sessions" , sampleSession ) ;
510+
511+ const res = await patchJson ( app , "/api/agent-sessions/1" , {
512+ sessionId : 42 ,
513+ } ) ;
514+ expect ( res . status ) . toBe ( 200 ) ;
515+ const body = await res . json ( ) ;
516+ expect ( body . sessionId ) . toBe ( 42 ) ;
517+ } ) ;
518+
519+ it ( "clears sessionId with null" , async ( ) => {
520+ await postJson ( app , "/api/agent-sessions" , sampleSession ) ;
521+
522+ // Set it first
523+ await patchJson ( app , "/api/agent-sessions/1" , { sessionId : 42 } ) ;
524+
525+ // Now clear it
526+ const res = await patchJson ( app , "/api/agent-sessions/1" , {
527+ sessionId : null ,
528+ } ) ;
529+ expect ( res . status ) . toBe ( 200 ) ;
530+ const body = await res . json ( ) ;
531+ expect ( body . sessionId ) . toBeNull ( ) ;
532+ } ) ;
533+
534+ it ( "rejects non-integer sessionId" , async ( ) => {
535+ await postJson ( app , "/api/agent-sessions" , sampleSession ) ;
536+
537+ const res = await patchJson ( app , "/api/agent-sessions/1" , {
538+ sessionId : 1.5 ,
539+ } ) ;
540+ expect ( res . status ) . toBe ( 400 ) ;
541+ } ) ;
542+
543+ it ( "rejects zero sessionId" , async ( ) => {
544+ await postJson ( app , "/api/agent-sessions" , sampleSession ) ;
545+
546+ const res = await patchJson ( app , "/api/agent-sessions/1" , {
547+ sessionId : 0 ,
548+ } ) ;
549+ expect ( res . status ) . toBe ( 400 ) ;
550+ } ) ;
551+
552+ it ( "returns 400 invalid_reference for non-existent sessionId" , async ( ) => {
553+ await postJson ( app , "/api/agent-sessions" , sampleSession ) ;
554+
555+ const res = await patchJson ( app , "/api/agent-sessions/1" , {
556+ sessionId : 9999 , // not in VALID_SESSION_IDS — FK violation
557+ } ) ;
558+ expect ( res . status ) . toBe ( 400 ) ;
559+ const body = await res . json ( ) ;
560+ expect ( body . error ) . toBe ( "invalid_reference" ) ;
561+ } ) ;
489562 } ) ;
490563
491564 // ================================================================
0 commit comments