@@ -225,6 +225,107 @@ test.describe('Kitty Graphics Protocol', () => {
225225 ( window as any ) . smallLimitAddon . dispose ( ) ;
226226 } ) ;
227227 } ) ;
228+
229+ test ( 'chunked a=T works when subsequent chunks omit i= (spec pattern)' , async ( ) => {
230+ const half = Math . floor ( KITTY_BLACK_1X1_BASE64 . length / 2 ) ;
231+ const part1 = KITTY_BLACK_1X1_BASE64 . substring ( 0 , half ) ;
232+ const part2 = KITTY_BLACK_1X1_BASE64 . substring ( half ) ;
233+
234+ await ctx . proxy . write ( `\x1b_Ga=T,f=100,i=400,m=1;${ part1 } \x1b\\` ) ;
235+ await timeout ( 50 ) ;
236+ strictEqual ( await getImageStorageLength ( ) , 0 ) ;
237+
238+ await ctx . proxy . write ( `\x1b_Gm=0;${ part2 } \x1b\\` ) ;
239+ await timeout ( 100 ) ;
240+ strictEqual ( await getImageStorageLength ( ) , 1 ) ;
241+ } ) ;
242+
243+ test ( 'chunked a=t works when subsequent chunks omit i= (spec pattern)' , async ( ) => {
244+ const half = Math . floor ( KITTY_BLACK_1X1_BASE64 . length / 2 ) ;
245+ const part1 = KITTY_BLACK_1X1_BASE64 . substring ( 0 , half ) ;
246+ const part2 = KITTY_BLACK_1X1_BASE64 . substring ( half ) ;
247+
248+ await ctx . proxy . write ( `\x1b_Ga=t,f=100,i=401,m=1;${ part1 } \x1b\\` ) ;
249+ await ctx . proxy . write ( `\x1b_Gm=0;${ part2 } \x1b\\` ) ;
250+ await timeout ( 100 ) ;
251+
252+ strictEqual ( await ctx . page . evaluate ( `window.imageAddon._handlers.get('kitty').images.has(401)` ) , true ) ;
253+ } ) ;
254+
255+ test ( 'chunked data without i= on subsequent chunks is assembled correctly' , async ( ) => {
256+ const half = Math . floor ( KITTY_BLACK_1X1_BASE64 . length / 2 ) ;
257+ const part1 = KITTY_BLACK_1X1_BASE64 . substring ( 0 , half ) ;
258+ const part2 = KITTY_BLACK_1X1_BASE64 . substring ( half ) ;
259+
260+ await ctx . proxy . write ( `\x1b_Ga=t,f=100,i=402,m=1;${ part1 } \x1b\\` ) ;
261+ await ctx . proxy . write ( `\x1b_Gm=0;${ part2 } \x1b\\` ) ;
262+ await timeout ( 100 ) ;
263+
264+ const storedData = await ctx . page . evaluate ( async ( ) => {
265+ const blob = ( window as any ) . imageAddon . _handlers . get ( 'kitty' ) . images . get ( 402 ) . data ;
266+ const buffer = await blob . arrayBuffer ( ) ;
267+ return Array . from ( new Uint8Array ( buffer ) ) ;
268+ } ) ;
269+ deepStrictEqual ( storedData , KITTY_BLACK_1X1_BYTES ) ;
270+ } ) ;
271+
272+ test ( 'three-chunk transfer with only m= on middle and last chunks' , async ( ) => {
273+ const third = Math . floor ( KITTY_BLACK_1X1_BASE64 . length / 3 ) ;
274+ const part1 = KITTY_BLACK_1X1_BASE64 . substring ( 0 , third ) ;
275+ const part2End = third + Math . floor ( ( KITTY_BLACK_1X1_BASE64 . length - third ) / 2 ) ;
276+ const alignedPart2End = part2End - ( part2End - third ) % 4 + third ;
277+ const part2 = KITTY_BLACK_1X1_BASE64 . substring ( third , alignedPart2End ) ;
278+ const part3 = KITTY_BLACK_1X1_BASE64 . substring ( alignedPart2End ) ;
279+
280+ await ctx . proxy . write ( `\x1b_Ga=t,f=100,i=403,m=1;${ part1 } \x1b\\` ) ;
281+ await ctx . proxy . write ( `\x1b_Gm=1;${ part2 } \x1b\\` ) ;
282+ await ctx . proxy . write ( `\x1b_Gm=0;${ part3 } \x1b\\` ) ;
283+ await timeout ( 100 ) ;
284+
285+ const storedData = await ctx . page . evaluate ( async ( ) => {
286+ const blob = ( window as any ) . imageAddon . _handlers . get ( 'kitty' ) . images . get ( 403 ) . data ;
287+ const buffer = await blob . arrayBuffer ( ) ;
288+ return Array . from ( new Uint8Array ( buffer ) ) ;
289+ } ) ;
290+ deepStrictEqual ( storedData , KITTY_BLACK_1X1_BYTES ) ;
291+ } ) ;
292+
293+ test ( 'chunked a=T without i= on any chunk works (no response)' , async ( ) => {
294+ const half = Math . floor ( KITTY_BLACK_1X1_BASE64 . length / 2 ) ;
295+ const part1 = KITTY_BLACK_1X1_BASE64 . substring ( 0 , half ) ;
296+ const part2 = KITTY_BLACK_1X1_BASE64 . substring ( half ) ;
297+
298+ await ctx . proxy . write ( `\x1b_Ga=T,f=100,m=1;${ part1 } \x1b\\` ) ;
299+ await timeout ( 50 ) ;
300+ strictEqual ( await getImageStorageLength ( ) , 0 ) ;
301+
302+ await ctx . proxy . write ( `\x1b_Gm=0;${ part2 } \x1b\\` ) ;
303+ await timeout ( 100 ) ;
304+ strictEqual ( await getImageStorageLength ( ) , 1 ) ;
305+ } ) ;
306+
307+ test ( 'chunked transfer responds OK on final chunk when i= on first only' , async ( ) => {
308+ await ctx . page . evaluate ( ( ) => {
309+ ( window as any ) . kittyResponse = '' ;
310+ ( window as any ) . term . onData ( ( data : string ) => { ( window as any ) . kittyResponse = data ; } ) ;
311+ } ) ;
312+
313+ const half = Math . floor ( KITTY_BLACK_1X1_BASE64 . length / 2 ) ;
314+ const part1 = KITTY_BLACK_1X1_BASE64 . substring ( 0 , half ) ;
315+ const part2 = KITTY_BLACK_1X1_BASE64 . substring ( half ) ;
316+
317+ await ctx . proxy . write ( `\x1b_Ga=T,f=100,i=405,m=1;${ part1 } \x1b\\` ) ;
318+ await timeout ( 50 ) ;
319+
320+ let response : string = await ctx . page . evaluate ( 'window.kittyResponse' ) ;
321+ strictEqual ( response , '' ) ;
322+
323+ await ctx . proxy . write ( `\x1b_Gm=0;${ part2 } \x1b\\` ) ;
324+ await timeout ( 100 ) ;
325+
326+ response = await ctx . page . evaluate ( 'window.kittyResponse' ) ;
327+ strictEqual ( response , '\x1b_Gi=405;OK\x1b\\' ) ;
328+ } ) ;
228329 } ) ;
229330
230331 test . describe ( 'Delete commands' , ( ) => {
@@ -749,8 +850,6 @@ test.describe('Kitty Graphics Protocol', () => {
749850 strictEqual ( response , '\x1b_Gi=204;OK\x1b\\' ) ;
750851 } ) ;
751852
752- // TODO: When file-based transmission mediums (t=f, t=t, t=s) are supported,
753- // update these tests to verify successful transmission instead of EINVAL.
754853 test ( 'transmit rejects t=f with id (EINVAL response)' , async ( ) => {
755854 await ctx . page . evaluate ( ( ) => {
756855 ( window as any ) . kittyResponse = '' ;
@@ -803,8 +902,6 @@ test.describe('Kitty Graphics Protocol', () => {
803902 strictEqual ( response , '' ) ;
804903 } ) ;
805904
806- // TODO: When file-based transmission mediums (t=f, t=t, t=s) are supported,
807- // update these tests to verify successful transmit+display instead of EINVAL.
808905 test ( 'transmit+display rejects t=f with id (EINVAL response)' , async ( ) => {
809906 await ctx . page . evaluate ( ( ) => {
810907 ( window as any ) . kittyResponse = '' ;
0 commit comments