1616
1717import  {  contextTest ,  expect  }  from  '../config/browserTest' ; 
1818
19- import  type  {  Page ,  BrowserContext  }  from  'playwright' ; 
19+ import  type  {  Page ,  BrowserContext ,   Cookie  }  from  'playwright' ; 
2020import  type  {  TestServer  }  from  '../config/testserver' ; 
2121
2222type  TestUrls  =  { 
@@ -63,6 +63,12 @@ test.use({
6363 *     frame-partitioned=value 
6464 *     frame-non-partitioned=value 
6565 * 
66+  * origin1: 
67+  *   origin2: 
68+  *     origin1: 
69+  *       frame-partitioned=value 
70+  *       frame-non-partitioned=value 
71+  * 
6672 * origin1 = httpsServer.PREFIX 
6773 * origin2 = httpsServer.CROSS_PROCESS_PREFIX 
6874 */ 
@@ -93,6 +99,17 @@ function addCommonCookieHandlers(httpsServer: TestServer, urls: TestUrls) {
9399  } ) ; 
94100} 
95101
102+ function  findCookie ( cookies : Cookie [ ] ,  name : string )  { 
103+   const  result  =  cookies . find ( cookie  =>  cookie . name  ===  name ) ; 
104+   expect ( result ,  `Cookie ${ name } ${ JSON . stringify ( cookies ,  null ,  2 ) }  ) . toBeTruthy ( ) ; 
105+   return  result ; 
106+ } 
107+ 
108+ function  expectTopLevelSite ( cookies : Cookie [ ] ,  name : string ,  topLevelSite : string )  { 
109+   const  cookie  =  findCookie ( cookies ,  name ) ; 
110+   expect ( cookie . topLevelSite ,  `Cookie ${ name }  ) . toBe ( topLevelSite ) ; 
111+ } 
112+ 
96113async  function  runNonPartitionedTest ( page : Page ,  httpsServer : TestServer ,  browserName : string ,  isMac : boolean ,  urls : TestUrls )  { 
97114  addCommonCookieHandlers ( httpsServer ,  urls ) ; 
98115  httpsServer . setRoute ( '/set-cookie.html' ,  ( req ,  res )  =>  { 
@@ -264,6 +281,23 @@ test(`save/load third party 'Partitioned;' cookies`, async ({ page, browserName,
264281
265282  await  checkCookies ( page ) ; 
266283
284+   function  checkStorageCookies ( cookies : Cookie [ ] )  { 
285+     const  expectedTopLevelPartitioned  =  browserName  ===  'webkit'  &&  isMac  ?
286+       undefined  :
287+       'https://localhost' ; 
288+     expectTopLevelSite ( cookies ,  'top-level-partitioned' ,  expectedTopLevelPartitioned ) ; 
289+     expectTopLevelSite ( cookies ,  'top-level-non-partitioned' ,  undefined ) ; 
290+     if  ( browserName  ===  'webkit'  &&  isMac )  { 
291+       expect ( cookies . find ( cookie  =>  cookie . name  ===  'frame-partitioned' ) ) . toBeUndefined ( ) ; 
292+       expect ( cookies . find ( cookie  =>  cookie . name  ===  'frame-non-partitioned' ) ) . toBeUndefined ( ) ; 
293+     }  else  { 
294+       expectTopLevelSite ( cookies ,  'frame-partitioned' ,  'https://127.0.0.1' ) ; 
295+       expectTopLevelSite ( cookies ,  'frame-non-partitioned' ,  undefined ) ; 
296+     } 
297+   } 
298+   checkStorageCookies ( await  page . context ( ) . cookies ( ) ) ; 
299+   checkStorageCookies ( ( await  page . context ( ) . storageState ( ) ) . cookies ) ; 
300+ 
267301  await  test . step ( 'export via cookies/addCookies' ,  async  ( )  =>  { 
268302    const  cookies  =  await  page . context ( ) . cookies ( ) ; 
269303    const  context2  =  await  browser . newContext ( ) ; 
@@ -280,20 +314,90 @@ test(`save/load third party 'Partitioned;' cookies`, async ({ page, browserName,
280314  } ) ; 
281315} ) ; 
282316
283- /** 
284-  * origin1: 
285-  *     top-level-partitioned=value 
286-  *     top-level-non-partitioned=value 
287-  * 
288-  * origin1: 
289-  *   origin2: 
290-  *     origin1: 
291-  *       frame-partitioned=value 
292-  *       frame-non-partitioned=value 
293-  * 
294-  * origin1 = httpsServer.PREFIX 
295-  * origin2 = httpsServer.CROSS_PROCESS_PREFIX 
296-  */ 
317+ test ( `add 'Partitioned;' cookie via API` ,  async  ( {  page,  context,  browserName,  httpsServer,  isMac,  urls } )  =>  { 
318+   // test.fixme(browserName === 'firefox', 'Firefox cookie partitioning is disabled in Firefox.'); 
319+   // test.fixme(browserName === 'webkit' && !isMac, 'Linux and Windows WebKit builds do not partition third-party cookies at all.'); 
320+   addCommonCookieHandlers ( httpsServer ,  urls ) ; 
321+ 
322+   await  context . addCookies ( [ 
323+     { 
324+       name : 'top-level-partitioned' , 
325+       value : 'value' , 
326+       domain : 'localhost' , 
327+       path : '/' , 
328+       expires : - 1 , 
329+       httpOnly : false , 
330+       secure : true , 
331+       sameSite : 'None' , 
332+       topLevelSite : 'https://localhost' , 
333+       _chromiumHasCrossSiteAncestor : false 
334+     }  as  any , 
335+     { 
336+       name : 'top-level-non-partitioned' , 
337+       value : 'value' , 
338+       domain : 'localhost' , 
339+       path : '/' , 
340+       expires : - 1 , 
341+       httpOnly : false , 
342+       secure : true , 
343+       sameSite : 'None' 
344+     } , 
345+     { 
346+       name : 'frame-partitioned' , 
347+       value : 'value' , 
348+       domain : 'localhost' , 
349+       path : '/' , 
350+       expires : - 1 , 
351+       httpOnly : false , 
352+       secure : true , 
353+       sameSite : 'None' , 
354+       topLevelSite : 'https://127.0.0.1' , 
355+       _chromiumHasCrossSiteAncestor : true 
356+     }  as  any , 
357+     { 
358+       name : 'frame-non-partitioned' , 
359+       value : 'value' , 
360+       domain : 'localhost' , 
361+       path : '/' , 
362+       expires : - 1 , 
363+       httpOnly : false , 
364+       secure : true , 
365+       sameSite : 'None' 
366+     } 
367+   ] ) ; 
368+ 
369+   async  function  checkCookies ( page : Page )  { 
370+     { 
371+       // Check top-level cookie first. 
372+       await  page . goto ( urls . read_origin1 ) ; 
373+       const  expectedTopLevel  =  browserName  ===  'webkit'  ||  browserName  ===  'firefox'  ?
374+         'Received cookie: frame-non-partitioned=value; frame-partitioned=value; top-level-non-partitioned=value; top-level-partitioned=value'  :
375+         'Received cookie: frame-non-partitioned=value; top-level-non-partitioned=value; top-level-partitioned=value' ; 
376+       expect . soft ( await  page . locator ( 'body' ) . textContent ( ) ) . toBe ( expectedTopLevel ) ; 
377+     } 
378+     { 
379+       // Check third-party cookie. 
380+       await  page . goto ( urls . read_origin2_origin1 ) ; 
381+       const  frameBody  =  page . locator ( 'iframe' ) . contentFrame ( ) . locator ( 'body' ) ; 
382+       const  expectedThirdParty  =  browserName  ===  'webkit'  ?
383+         'Received cookie: undefined'  : browserName  ===  'firefox'  ?
384+           'Received cookie: frame-non-partitioned=value; frame-partitioned=value; top-level-non-partitioned=value; top-level-partitioned=value'  :
385+           'Received cookie: frame-non-partitioned=value; frame-partitioned=value; top-level-non-partitioned=value' ; 
386+       await  expect . soft ( frameBody ) . toHaveText ( expectedThirdParty ,  {  timeout : 1000  } ) ; 
387+     } 
388+     { 
389+       await  page . goto ( urls . read_origin1_origin2_origin1 ) ;  // read-origin1-origin2-origin1.html 
390+       const  frameBody  =  page . locator ( 'iframe' ) . contentFrame ( ) . locator ( 'iframe' ) . contentFrame ( ) . locator ( 'body' ) ; 
391+       const  expectedThirdParty  =  browserName  ===  'webkit'  ||  browserName  ===  'firefox'  ?
392+         'Received cookie: frame-non-partitioned=value; frame-partitioned=value; top-level-non-partitioned=value; top-level-partitioned=value'  :
393+         'Received cookie: frame-non-partitioned=value; top-level-non-partitioned=value' ; 
394+       await  expect . soft ( frameBody ) . toHaveText ( expectedThirdParty ,  {  timeout : 1000  } ) ; 
395+     } 
396+   } 
397+ 
398+   await  checkCookies ( page ) ; 
399+ } ) ; 
400+ 
297401
298402test ( `same origin third party 'Partitioned;' cookie with different origin intermediate iframe` ,  async  ( {  page,  httpsServer,  browser,  urls } )  =>  { 
299403  addCommonCookieHandlers ( httpsServer ,  urls ) ; 
0 commit comments