33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import { strictEqual , deepStrictEqual } from 'assert' ;
6+ import { strictEqual , deepStrictEqual , rejects } from 'assert' ;
7+ import { Octokit } from '@octokit/rest' ;
8+ import { createSandbox , SinonSandbox } from 'sinon' ;
79import * as vscode from 'vscode' ;
810import { AuthProvider } from '../../common/authentication' ;
9- import { findExistingSession } from '../../github/credentials' ;
11+ import { CredentialStore , findExistingSession , GitHub } from '../../github/credentials' ;
12+ import { LoggingApolloClient , LoggingOctokit , RateLogger } from '../../github/loggingOctokit' ;
13+ import { MockExtensionContext } from '../mocks/mockExtensionContext' ;
14+ import { MockTelemetry } from '../mocks/mockTelemetry' ;
1015
1116const oldestScopes = [ 'read:user' , 'user:email' , 'repo' ] ;
1217const defaultScopes = [ ...oldestScopes , 'workflow' ] ;
@@ -29,6 +34,16 @@ function createSession(id: string, accountId: string, scopes: string[]): vscode.
2934}
3035
3136describe ( 'CredentialStore' , function ( ) {
37+ let sinon : SinonSandbox ;
38+
39+ beforeEach ( function ( ) {
40+ sinon = createSandbox ( ) ;
41+ } ) ;
42+
43+ afterEach ( function ( ) {
44+ sinon . restore ( ) ;
45+ } ) ;
46+
3247 describe ( 'findExistingSession' , function ( ) {
3348 it ( 'keeps broader scope lookup on the preferred account' , async function ( ) {
3449 const firstAccountAdditional = createSession ( 'first-additional' , 'first' , additionalScopes ) ;
@@ -99,4 +114,43 @@ describe('CredentialStore', function () {
99114 deepStrictEqual ( additionalResult ?. scopes , additionalScopes ) ;
100115 } ) ;
101116 } ) ;
117+
118+ it ( 'retries the current user request after a failure' , async function ( ) {
119+ const telemetry = new MockTelemetry ( ) ;
120+ const credentialStore = new CredentialStore ( telemetry , new MockExtensionContext ( ) ) ;
121+ const github : GitHub = {
122+ octokit : new LoggingOctokit ( new Octokit ( ) , new RateLogger ( telemetry , false ) ) ,
123+ graphql : { } as LoggingApolloClient ,
124+ } ;
125+ sinon . stub ( credentialStore , 'getHub' ) . returns ( github ) ;
126+ const getAuthenticatedUser = sinon . stub ( github . octokit , 'call' ) ;
127+ const error = new Error ( 'Connect Timeout Error' ) ;
128+ getAuthenticatedUser . onFirstCall ( ) . rejects ( error ) ;
129+ getAuthenticatedUser . onSecondCall ( ) . resolves ( {
130+ data : {
131+ login : 'octocat' ,
132+ node_id : 'MDQ6VXNlcjE=' ,
133+ html_url : 'https://github.com/octocat' ,
134+ avatar_url : 'https://github.com/images/error/octocat_happy.gif' ,
135+ type : 'User' ,
136+ plan : { name : 'emu_user' } ,
137+ }
138+ } ) ;
139+
140+ await rejects ( credentialStore . getCurrentUser ( AuthProvider . github ) , candidate => candidate === error ) ;
141+ const [ currentUser , isEmu ] = await Promise . all ( [
142+ credentialStore . getCurrentUser ( AuthProvider . github ) ,
143+ credentialStore . getIsEmu ( AuthProvider . github ) ,
144+ ] ) ;
145+
146+ deepStrictEqual ( {
147+ requests : getAuthenticatedUser . callCount ,
148+ login : currentUser . login ,
149+ isEmu,
150+ } , {
151+ requests : 2 ,
152+ login : 'octocat' ,
153+ isEmu : true ,
154+ } ) ;
155+ } ) ;
102156} ) ;
0 commit comments