@@ -903,6 +903,81 @@ test('Open PR drawer keeps a single active PR context in localStorage', async ({
903903 expect ( activeContext . parsed ?. componentFilePath ) . toBe ( 'examples/css/App.tsx' )
904904} )
905905
906+ test ( 'Open PR drawer does not prune saved PR context on repo switch before save' , async ( {
907+ page,
908+ } ) => {
909+ await page . route ( 'https://api.github.com/user/repos**' , async route => {
910+ await route . fulfill ( {
911+ status : 200 ,
912+ contentType : 'application/json' ,
913+ body : JSON . stringify ( [
914+ {
915+ id : 2 ,
916+ owner : { login : 'knightedcodemonkey' } ,
917+ name : 'develop' ,
918+ full_name : 'knightedcodemonkey/develop' ,
919+ default_branch : 'main' ,
920+ permissions : { push : true } ,
921+ } ,
922+ {
923+ id : 1 ,
924+ owner : { login : 'knightedcodemonkey' } ,
925+ name : 'css' ,
926+ full_name : 'knightedcodemonkey/css' ,
927+ default_branch : 'stable' ,
928+ permissions : { push : true } ,
929+ } ,
930+ ] ) ,
931+ } )
932+ } )
933+
934+ await mockRepositoryBranches ( page , {
935+ 'knightedcodemonkey/develop' : [ 'main' , 'develop-next' ] ,
936+ 'knightedcodemonkey/css' : [ 'stable' , 'release/1.x' ] ,
937+ } )
938+
939+ await waitForAppReady ( page , `${ appEntryPath } ?feature-ai=true` )
940+
941+ await page . locator ( '#github-token-input' ) . fill ( 'github_pat_fake_1234567890' )
942+ await page . locator ( '#github-token-add' ) . click ( )
943+ await ensureOpenPrDrawerOpen ( page )
944+
945+ const repoSelect = page . locator ( '#github-pr-repo-select' )
946+ const componentPath = page . locator ( '#github-pr-component-path' )
947+
948+ await repoSelect . selectOption ( 'knightedcodemonkey/develop' )
949+ await componentPath . fill ( 'examples/develop/App.tsx' )
950+ await componentPath . blur ( )
951+
952+ await repoSelect . selectOption ( 'knightedcodemonkey/css' )
953+
954+ const contexts = await page . evaluate ( ( ) => {
955+ const storagePrefix = 'knighted:develop:github-pr-config:'
956+ const keys = Object . keys ( localStorage )
957+ . filter ( key => key . startsWith ( storagePrefix ) )
958+ . sort ( ( left , right ) => left . localeCompare ( right ) )
959+
960+ return keys . map ( key => {
961+ const raw = localStorage . getItem ( key )
962+ let parsed = null
963+
964+ try {
965+ parsed = raw ? JSON . parse ( raw ) : null
966+ } catch {
967+ parsed = null
968+ }
969+
970+ return { key, parsed }
971+ } )
972+ } )
973+
974+ expect ( contexts ) . toHaveLength ( 1 )
975+ expect ( contexts [ 0 ] ?. key ) . toBe (
976+ 'knighted:develop:github-pr-config:knightedcodemonkey/develop' ,
977+ )
978+ expect ( contexts [ 0 ] ?. parsed ?. componentFilePath ) . toBe ( 'examples/develop/App.tsx' )
979+ } )
980+
906981test ( 'Open PR drawer validates unsafe filepaths' , async ( { page } ) => {
907982 await waitForAppReady ( page , `${ appEntryPath } ?feature-ai=true` )
908983 await connectByotWithSingleRepo ( page )
0 commit comments