@@ -34,28 +34,27 @@ function buildSnapshot(count = 1): ChatSnapshotV1 {
3434
3535/**
3636 * Stub `apiClientManager.clientOrThrow()` so the helpers see a fake API
37- * client whose `getPayloadUrl ` / `createUploadPayloadUrl ` resolve with the
38- * presigned URLs the test wants. Returns spies for assertion.
37+ * client whose `getChatSnapshotUrl ` / `createChatSnapshotUploadUrl ` resolve
38+ * with the presigned URLs the test wants. Returns spies for assertion.
3939 */
4040function stubApiClient ( opts : {
41- getPayloadUrl ?: ( filename : string ) => Promise < { presignedUrl : string } > ;
42- createUploadPayloadUrl ?: ( filename : string ) => Promise < { presignedUrl : string } > ;
41+ getChatSnapshotUrl ?: ( sessionId : string ) => Promise < { presignedUrl : string } > ;
42+ createChatSnapshotUploadUrl ?: ( sessionId : string ) => Promise < { presignedUrl : string } > ;
4343} ) {
44- const getPayloadUrl = vi . fn (
45- opts . getPayloadUrl ?? ( async ( _filename : string ) => ( { presignedUrl : "https://example.invalid/get" } ) )
44+ const getChatSnapshotUrl = vi . fn (
45+ opts . getChatSnapshotUrl ??
46+ ( async ( _sessionId : string ) => ( { presignedUrl : "https://example.invalid/get" } ) )
4647 ) ;
47- const createUploadPayloadUrl = vi . fn (
48- opts . createUploadPayloadUrl ??
49- ( async ( _filename : string ) => ( { presignedUrl : "https://example.invalid/put" } ) )
48+ const createChatSnapshotUploadUrl = vi . fn (
49+ opts . createChatSnapshotUploadUrl ??
50+ ( async ( _sessionId : string ) => ( { presignedUrl : "https://example.invalid/put" } ) )
5051 ) ;
5152 const fakeClient = {
52- getPayloadUrl ,
53- createUploadPayloadUrl ,
53+ getChatSnapshotUrl ,
54+ createChatSnapshotUploadUrl ,
5455 } ;
55- vi . spyOn ( apiClientManager , "clientOrThrow" ) . mockReturnValue (
56- fakeClient as never
57- ) ;
58- return { getPayloadUrl, createUploadPayloadUrl } ;
56+ vi . spyOn ( apiClientManager , "clientOrThrow" ) . mockReturnValue ( fakeClient as never ) ;
57+ return { getChatSnapshotUrl, createChatSnapshotUploadUrl } ;
5958}
6059
6160/**
@@ -87,7 +86,7 @@ describe("chat snapshot helpers", () => {
8786
8887 describe ( "readChatSnapshot" , ( ) => {
8988 it ( "returns the snapshot on a successful GET" , async ( ) => {
90- const { getPayloadUrl } = stubApiClient ( { } ) ;
89+ const { getChatSnapshotUrl } = stubApiClient ( { } ) ;
9190 const snapshot = buildSnapshot ( 2 ) ;
9291 stubFetch ( async ( ) =>
9392 new Response ( JSON . stringify ( snapshot ) , {
@@ -97,7 +96,7 @@ describe("chat snapshot helpers", () => {
9796 ) ;
9897
9998 const result = await readChatSnapshot ( "session-1" ) ;
100- expect ( getPayloadUrl ) . toHaveBeenCalledWith ( "sessions/ session-1/snapshot.json " ) ;
99+ expect ( getChatSnapshotUrl ) . toHaveBeenCalledWith ( "session-1" ) ;
101100 expect ( result ) . toMatchObject ( {
102101 version : 1 ,
103102 messages : snapshot . messages ,
@@ -177,7 +176,7 @@ describe("chat snapshot helpers", () => {
177176
178177 it ( "returns undefined when presign call fails" , async ( ) => {
179178 stubApiClient ( {
180- getPayloadUrl : async ( ) => {
179+ getChatSnapshotUrl : async ( ) => {
181180 throw new Error ( "presign denied" ) ;
182181 } ,
183182 } ) ;
@@ -202,13 +201,13 @@ describe("chat snapshot helpers", () => {
202201
203202 describe ( "writeChatSnapshot" , ( ) => {
204203 it ( "PUTs the snapshot JSON to the presigned URL" , async ( ) => {
205- const { createUploadPayloadUrl } = stubApiClient ( { } ) ;
204+ const { createChatSnapshotUploadUrl } = stubApiClient ( { } ) ;
206205 const fetchSpy = stubFetch ( async ( ) => new Response ( null , { status : 200 } ) ) ;
207206
208207 const snapshot = buildSnapshot ( 3 ) ;
209208 await writeChatSnapshot ( "session-2" , snapshot ) ;
210209
211- expect ( createUploadPayloadUrl ) . toHaveBeenCalledWith ( "sessions/ session-2/snapshot.json " ) ;
210+ expect ( createChatSnapshotUploadUrl ) . toHaveBeenCalledWith ( "session-2" ) ;
212211 expect ( fetchSpy ) . toHaveBeenCalledOnce ( ) ;
213212 const [ url , init ] = fetchSpy . mock . calls [ 0 ] ! ;
214213 expect ( url ) . toBe ( "https://example.invalid/put" ) ;
@@ -239,7 +238,7 @@ describe("chat snapshot helpers", () => {
239238
240239 it ( "returns without throwing when presign fails (warns)" , async ( ) => {
241240 stubApiClient ( {
242- createUploadPayloadUrl : async ( ) => {
241+ createChatSnapshotUploadUrl : async ( ) => {
243242 throw new Error ( "presign denied" ) ;
244243 } ,
245244 } ) ;
@@ -250,29 +249,28 @@ describe("chat snapshot helpers", () => {
250249 expect ( fetchSpy ) . not . toHaveBeenCalled ( ) ;
251250 } ) ;
252251
253- it ( "uses the same `snapshotFilename(sessionId)` convention as the read path" , async ( ) => {
254- // Round-trip check: read and write target the same key for a given
255- // sessionId. The runtime relies on this to make read-after-write
256- // coherent on subsequent boots.
257- const { getPayloadUrl } = stubApiClient ( {
258- getPayloadUrl : async ( ) => ( { presignedUrl : "https://example.invalid/get" } ) ,
252+ it ( "addresses reads and writes by the same sessionId" , async ( ) => {
253+ // Round-trip check: both presign methods receive the same sessionId.
254+ // The canonical key (`sessions/{id}/snapshot.json`) lives server-side
255+ // now, so the SDK has no key string to compare — sessionId equality
256+ // is the SDK-visible invariant.
257+ const { getChatSnapshotUrl } = stubApiClient ( {
258+ getChatSnapshotUrl : async ( ) => ( { presignedUrl : "https://example.invalid/get" } ) ,
259259 } ) ;
260260 stubFetch ( async ( ) => new Response ( null , { status : 404 } ) ) ;
261261
262- // Trigger a read.
263262 await readChatSnapshot ( "round-trip-session" ) ;
264- const [ readKey ] = getPayloadUrl . mock . calls [ 0 ] ! ;
263+ const [ readArg ] = getChatSnapshotUrl . mock . calls [ 0 ] ! ;
265264
266- // Trigger a write to the same session.
267- const { createUploadPayloadUrl } = stubApiClient ( {
268- createUploadPayloadUrl : async ( ) => ( { presignedUrl : "https://example.invalid/put" } ) ,
265+ const { createChatSnapshotUploadUrl } = stubApiClient ( {
266+ createChatSnapshotUploadUrl : async ( ) => ( { presignedUrl : "https://example.invalid/put" } ) ,
269267 } ) ;
270268 stubFetch ( async ( ) => new Response ( null , { status : 200 } ) ) ;
271269 await writeChatSnapshot ( "round-trip-session" , buildSnapshot ( ) ) ;
272- const [ writeKey ] = createUploadPayloadUrl . mock . calls [ 0 ] ! ;
270+ const [ writeArg ] = createChatSnapshotUploadUrl . mock . calls [ 0 ] ! ;
273271
274- expect ( readKey ) . toBe ( writeKey ) ;
275- expect ( readKey ) . toBe ( "sessions/ round-trip-session/snapshot.json " ) ;
272+ expect ( readArg ) . toBe ( writeArg ) ;
273+ expect ( readArg ) . toBe ( "round-trip-session" ) ;
276274 } ) ;
277275 } ) ;
278276} ) ;
0 commit comments