@@ -254,7 +254,7 @@ describe("accessLog middleware", () => {
254254
255255 // ── Structured log on finish ───────────────────────────────────────────
256256
257- it ( "emits a users_access_log entry on response finish with required fields" , async ( ) => {
257+ it ( "emits a users_access_log entry on response finish with all required fields" , async ( ) => {
258258 const req = makeReq ( {
259259 headers : { "x-correlation-id" : "log-test-id" } ,
260260 method : "GET" ,
@@ -269,12 +269,17 @@ describe("accessLog middleware", () => {
269269
270270 expect ( loggerInfoSpy ) . toHaveBeenCalledWith (
271271 expect . objectContaining ( {
272+ "req-id" : "log-test-id" ,
272273 correlationId : "log-test-id" ,
273274 method : "GET" ,
274275 path : "/api/users/me" ,
275276 statusCode : 200 ,
277+ status : 200 ,
276278 ip : "10.0.0.1" ,
277279 durationMs : expect . any ( Number ) ,
280+ latency : expect . any ( Number ) ,
281+ size : 0 ,
282+ actor : "anonymous" ,
278283 } ) ,
279284 "users_access_log" ,
280285 ) ;
@@ -493,4 +498,84 @@ describe("accessLog middleware", () => {
493498 "users_access_log" ,
494499 ) ;
495500 } ) ;
501+
502+ // ── Content-Length / size ──────────────────────────────────────────────
503+
504+ it ( "logs the Content-Length when set on the response" , async ( ) => {
505+ const req = makeReq ( { headers : { "x-correlation-id" : "size-test-id" } } ) ;
506+ const res = makeRes ( ) ;
507+ res . setHeader ( "Content-Length" , "512" ) ;
508+ const next : NextFunction = jest . fn ( ) ;
509+
510+ accessLog ( req , res , next ) ;
511+ await fireFinish ( res ) ;
512+
513+ expect ( loggerInfoSpy ) . toHaveBeenCalledWith (
514+ expect . objectContaining ( { size : 512 } ) ,
515+ "users_access_log" ,
516+ ) ;
517+ } ) ;
518+
519+ it ( "logs size=0 when Content-Length is absent" , async ( ) => {
520+ const req = makeReq ( { headers : { "x-correlation-id" : "no-size-id" } } ) ;
521+ const res = makeRes ( ) ;
522+ const next : NextFunction = jest . fn ( ) ;
523+
524+ accessLog ( req , res , next ) ;
525+ await fireFinish ( res ) ;
526+
527+ expect ( loggerInfoSpy ) . toHaveBeenCalledWith (
528+ expect . objectContaining ( { size : 0 } ) ,
529+ "users_access_log" ,
530+ ) ;
531+ } ) ;
532+
533+ // ── Actor extraction ───────────────────────────────────────────────────
534+
535+ it ( "logs the authenticated actor when req.user is set" , async ( ) => {
536+ const req = makeReq ( {
537+ headers : { "x-correlation-id" : "actor-test-id" } ,
538+ method : "POST" ,
539+ path : "/api/users/me" ,
540+ } ) ;
541+ ( req as any ) . user = { id : "authenticated-user-id" } ;
542+ const res = makeRes ( ) ;
543+ const next : NextFunction = jest . fn ( ) ;
544+
545+ accessLog ( req , res , next ) ;
546+ await fireFinish ( res ) ;
547+
548+ expect ( loggerInfoSpy ) . toHaveBeenCalledWith (
549+ expect . objectContaining ( { actor : "authenticated-user-id" } ) ,
550+ "users_access_log" ,
551+ ) ;
552+ } ) ;
553+
554+ // ── referrals_access_log ──────────────────────────────────────────────
555+
556+ it ( "emits a referrals_access_log entry when originalUrl starts with /api/referrals" , async ( ) => {
557+ const req = makeReq ( {
558+ headers : { "x-correlation-id" : "ref-log-test-id" } ,
559+ method : "POST" ,
560+ path : "/api/referrals" ,
561+ ip : "10.0.0.5" ,
562+ } ) ;
563+ const res = makeRes ( ) ;
564+ const next : NextFunction = jest . fn ( ) ;
565+
566+ accessLog ( req , res , next ) ;
567+ await fireFinish ( res ) ;
568+
569+ expect ( loggerInfoSpy ) . toHaveBeenCalledWith (
570+ expect . objectContaining ( {
571+ correlationId : "ref-log-test-id" ,
572+ method : "POST" ,
573+ path : "/api/referrals" ,
574+ statusCode : 200 ,
575+ ip : "10.0.0.5" ,
576+ durationMs : expect . any ( Number ) ,
577+ } ) ,
578+ "referrals_access_log" ,
579+ ) ;
580+ } ) ;
496581} ) ;
0 commit comments