@@ -1752,6 +1752,93 @@ describe("storage", () => {
17521752 }
17531753 } ) ;
17541754
1755+ it . each ( [ "EBUSY" , "EPERM" , "EAGAIN" ] as const ) (
1756+ "rethrows %s when the current storage reappears locked during export fallback" ,
1757+ async ( code ) => {
1758+ const currentStoragePath = join (
1759+ testWorkDir ,
1760+ `accounts-reappeared-locked-${ code } .json` ,
1761+ ) ;
1762+ const legacyStoragePath = join (
1763+ testWorkDir ,
1764+ `accounts-reappeared-legacy-${ code } .json` ,
1765+ ) ;
1766+ await fs . writeFile (
1767+ legacyStoragePath ,
1768+ JSON . stringify ( {
1769+ version : 3 ,
1770+ activeIndex : 0 ,
1771+ activeIndexByFamily : { } ,
1772+ accounts : [
1773+ {
1774+ accountId : "legacy" ,
1775+ refreshToken : "legacy-token" ,
1776+ addedAt : 1 ,
1777+ lastUsed : 1 ,
1778+ } ,
1779+ ] ,
1780+ } ) ,
1781+ ) ;
1782+
1783+ const actualStorageParser = await vi . importActual <
1784+ typeof import ( "../lib/storage/storage-parser.js" )
1785+ > ( "../lib/storage/storage-parser.js" ) ;
1786+ let currentReadCount = 0 ;
1787+ vi . resetModules ( ) ;
1788+ vi . doMock ( "../lib/storage/storage-parser.js" , ( ) => ( {
1789+ ...actualStorageParser ,
1790+ loadAccountsFromPath : vi . fn ( async ( path , deps ) => {
1791+ if ( path === currentStoragePath ) {
1792+ currentReadCount += 1 ;
1793+ if ( currentReadCount === 1 ) {
1794+ await fs . writeFile (
1795+ currentStoragePath ,
1796+ JSON . stringify ( {
1797+ version : 3 ,
1798+ activeIndex : 0 ,
1799+ activeIndexByFamily : { } ,
1800+ accounts : [ ] ,
1801+ } ) ,
1802+ ) ;
1803+ throw Object . assign (
1804+ new Error ( "missing current storage" ) ,
1805+ { code : "ENOENT" } ,
1806+ ) ;
1807+ }
1808+ throw Object . assign ( new Error ( `locked ${ code } ` ) , { code } ) ;
1809+ }
1810+ return actualStorageParser . loadAccountsFromPath ( path , deps ) ;
1811+ } ) ,
1812+ } ) ) ;
1813+
1814+ try {
1815+ const isolatedStorageModule = await import ( "../lib/storage.js" ) ;
1816+ const isolatedPathState = await import ( "../lib/storage/path-state.js" ) ;
1817+ isolatedPathState . setStoragePathState ( {
1818+ currentStoragePath,
1819+ currentLegacyProjectStoragePath : legacyStoragePath ,
1820+ currentLegacyWorktreeStoragePath : null ,
1821+ currentProjectRoot : null ,
1822+ } ) ;
1823+
1824+ await expect (
1825+ isolatedStorageModule . exportAccounts ( exportPath ) ,
1826+ ) . rejects . toMatchObject ( { code } ) ;
1827+
1828+ const currentStorage = JSON . parse (
1829+ await fs . readFile ( currentStoragePath , "utf-8" ) ,
1830+ ) ;
1831+ expect ( currentStorage . accounts ) . toEqual ( [ ] ) ;
1832+ expect ( existsSync ( legacyStoragePath ) ) . toBe ( true ) ;
1833+ expect ( existsSync ( exportPath ) ) . toBe ( false ) ;
1834+ } finally {
1835+ vi . doUnmock ( "../lib/storage/storage-parser.js" ) ;
1836+ vi . resetModules ( ) ;
1837+ setStoragePathDirect ( testStoragePath ) ;
1838+ }
1839+ } ,
1840+ ) ;
1841+
17551842 it ( "does not revive legacy accounts when the current storage has an intentional reset marker" , async ( ) => {
17561843 const currentStoragePath = join ( testWorkDir , "accounts-reset-current.json" ) ;
17571844 const legacyStoragePath = join ( testWorkDir , "accounts-reset-legacy.json" ) ;
0 commit comments