@@ -340,8 +340,121 @@ test('a confirmed invalid provisional PAT opens account recovery', async () => {
340340 ) ;
341341
342342 assert . equal ( await controller . getAccount ( ) , null ) ;
343- assert . equal ( values . get ( 'github-token' ) , 'legacy-token' ) ;
343+ assert . equal ( values . has ( 'github-token' ) , false ) ;
344344 assert . equal ( accounts . at ( - 1 ) , null ) ;
345+
346+ const restarted = new GitHubAccountController ( {
347+ authManager,
348+ createGitHub : ( ) => ( { } ) ,
349+ legacyStore : createStore ( values ) ,
350+ } ) ;
351+ assert . equal ( await restarted . initialize ( ) , null ) ;
352+ } ,
353+ ) ;
354+ } ) ;
355+
356+ test ( 'an invalid background migration removes the legacy PAT permanently' , async ( ) => {
357+ const values = new Map ( [ [ 'github-token' , 'legacy-token' ] ] ) ;
358+ const authManager = createAuthManager ( [ ] ) ;
359+ authManager . usePersonalAccessToken = async ( ) => {
360+ throw Object . assign ( new Error ( 'invalid token' ) , { kind : 'invalid-token' } ) ;
361+ } ;
362+
363+ await withSourceModule (
364+ 'githubAccount.js' ,
365+ { localStorage : createStore ( values ) } ,
366+ async ( { GitHubAccountController } ) => {
367+ const controller = new GitHubAccountController ( {
368+ authManager,
369+ createGitHub : ( ) => ( { } ) ,
370+ legacyStore : createStore ( values ) ,
371+ } ) ;
372+ await controller . initialize ( ) ;
373+
374+ assert . equal ( await controller . run ( ( ) => 'loaded' ) , 'loaded' ) ;
375+ await settle ( ) ;
376+
377+ assert . equal ( await controller . getAccount ( ) , null ) ;
378+ assert . equal ( values . has ( 'github-token' ) , false ) ;
379+
380+ const restarted = new GitHubAccountController ( {
381+ authManager,
382+ createGitHub : ( ) => ( { } ) ,
383+ legacyStore : createStore ( values ) ,
384+ } ) ;
385+ assert . equal ( await restarted . initialize ( ) , null ) ;
386+ } ,
387+ ) ;
388+ } ) ;
389+
390+ test ( 'legacy PAT invalidation stays signed out when cleanup fails' , async ( ) => {
391+ const values = new Map ( [ [ 'github-token' , 'legacy-token' ] ] ) ;
392+ const authManager = createAuthManager ( [ ] ) ;
393+ const legacyStore = {
394+ ...createStore ( values ) ,
395+ removeItem ( ) {
396+ throw new Error ( 'storage unavailable' ) ;
397+ } ,
398+ } ;
399+
400+ await withSourceModule (
401+ 'githubAccount.js' ,
402+ { localStorage : legacyStore } ,
403+ async ( { GitHubAccountController } ) => {
404+ const controller = new GitHubAccountController ( {
405+ authManager,
406+ createGitHub : ( ) => ( { } ) ,
407+ legacyStore,
408+ } ) ;
409+ await controller . initialize ( ) ;
410+
411+ await assert . rejects (
412+ controller . run ( ( ) => {
413+ throw Object . assign ( new Error ( 'unauthorized' ) , { status : 401 } ) ;
414+ } ) ,
415+ hasKind ( 'storage' ) ,
416+ ) ;
417+
418+ assert . equal ( await controller . getAccount ( ) , null ) ;
419+ assert . equal ( values . get ( 'github-token' ) , 'legacy-token' ) ;
420+ } ,
421+ ) ;
422+ } ) ;
423+
424+ test ( 'a stale legacy rejection cannot clear replacement credentials' , async ( ) => {
425+ const values = new Map ( [ [ 'github-token' , 'legacy-token' ] ] ) ;
426+ const operationStarted = deferred ( ) ;
427+ const releaseOperation = deferred ( ) ;
428+ const authManager = createAuthManager ( [ ] ) ;
429+
430+ await withSourceModule (
431+ 'githubAccount.js' ,
432+ { localStorage : createStore ( values ) } ,
433+ async ( { GitHubAccountController } ) => {
434+ const controller = new GitHubAccountController ( {
435+ authManager,
436+ createGitHub : ( ) => ( { } ) ,
437+ legacyStore : createStore ( values ) ,
438+ } ) ;
439+ const accounts = [ ] ;
440+ controller . subscribe ( ( account ) => accounts . push ( account ) ) ;
441+ await controller . initialize ( ) ;
442+
443+ const stale = controller . run ( async ( ) => {
444+ operationStarted . resolve ( ) ;
445+ await releaseOperation . promise ;
446+ throw Object . assign ( new Error ( 'unauthorized' ) , { status : 401 } ) ;
447+ } ) ;
448+ const staleRejection = assert . rejects ( stale , hasKind ( 'cancelled' ) ) ;
449+ await operationStarted . promise ;
450+
451+ await controller . usePersonalAccessToken ( 'replacement-token' ) ;
452+ releaseOperation . resolve ( ) ;
453+ await staleRejection ;
454+
455+ assert . equal ( ( await controller . getAccount ( ) ) . login , 'octocat' ) ;
456+ assert . equal ( values . has ( 'github-token' ) , false ) ;
457+ assert . equal ( accounts . at ( - 1 ) . login , 'octocat' ) ;
345458 } ,
346459 ) ;
347460} ) ;
0 commit comments