@@ -64,7 +64,6 @@ public void GitHubHostProvider_IsSupported(string protocol, string host, bool ex
6464 Assert . Equal ( expected , provider . IsSupported ( input ) ) ;
6565 }
6666
67-
6867 [ Theory ]
6968 [ InlineData ( "https" , "github.com" , "https://github.com" ) ]
7069 [ InlineData ( "https" , "GitHub.Com" , "https://github.com" ) ]
@@ -151,6 +150,176 @@ public async Task GitHubHostProvider_GetSupportedAuthenticationModes_WithMetadat
151150 Assert . Equal ( expectedModes , actualModes ) ;
152151 }
153152
153+ [ Fact ]
154+ public async Task GitHubHostProvider_GetCredentialAsync_NoCredentials_NoUserNoHeaders_PromptsUser ( )
155+ {
156+ var input = new InputArguments (
157+ new Dictionary < string , string >
158+ {
159+ [ "protocol" ] = "https" ,
160+ [ "host" ] = "github.com" ,
161+ }
162+ ) ;
163+
164+ var newCredential = new GitCredential ( "alice" , "password" ) ;
165+
166+ var context = new TestCommandContext ( ) ;
167+ var ghApiMock = new Mock < IGitHubRestApi > ( MockBehavior . Strict ) ;
168+ var ghAuthMock = new Mock < IGitHubAuthentication > ( MockBehavior . Strict ) ;
169+ ghAuthMock . Setup ( x => x . GetAuthenticationAsync (
170+ It . IsAny < Uri > ( ) , It . IsAny < string > ( ) , It . IsAny < AuthenticationModes > ( ) ) )
171+ . ReturnsAsync ( new AuthenticationPromptResult ( AuthenticationModes . Pat , newCredential ) ) ;
172+
173+ var provider = new GitHubHostProvider ( context , ghApiMock . Object , ghAuthMock . Object ) ;
174+
175+ ICredential result = await provider . GetCredentialAsync ( input ) ;
176+
177+ Assert . Equal ( result . Account , newCredential . Account ) ;
178+ Assert . Equal ( result . Password , newCredential . Password ) ;
179+ ghAuthMock . Verify ( x => x . GetAuthenticationAsync (
180+ new Uri ( "https://github.com" ) , null , It . IsAny < AuthenticationModes > ( ) ) ,
181+ Times . Once ) ;
182+ }
183+
184+ [ Fact ]
185+ public async Task GitHubHostProvider_GetCredentialAsync_InputUser_ReturnsCredentialForUser ( )
186+ {
187+ var input = new InputArguments (
188+ new Dictionary < string , string >
189+ {
190+ [ "protocol" ] = "https" ,
191+ [ "host" ] = "github.com" ,
192+ [ "username" ] = "alice"
193+ }
194+ ) ;
195+
196+ var context = new TestCommandContext ( ) ;
197+ context . CredentialStore . Add ( "https://github.com" , "alice" , "letmein123" ) ;
198+ context . CredentialStore . Add ( "https://github.com" , "bob" , "secret123" ) ;
199+
200+ var ghApiMock = new Mock < IGitHubRestApi > ( MockBehavior . Strict ) ;
201+ var ghAuthMock = new Mock < IGitHubAuthentication > ( MockBehavior . Strict ) ;
202+
203+ var provider = new GitHubHostProvider ( context , ghApiMock . Object , ghAuthMock . Object ) ;
204+
205+ ICredential result = await provider . GetCredentialAsync ( input ) ;
206+
207+ Assert . NotNull ( result ) ;
208+ Assert . Equal ( "alice" , result . Account ) ;
209+ Assert . Equal ( "letmein123" , result . Password ) ;
210+ }
211+
212+ [ Fact ]
213+ public async Task GitHubHostProvider_GetCredentialAsync_OneDomainAccount_ReturnsCredentialForRealmAccount ( )
214+ {
215+ var input = new InputArguments (
216+ new Dictionary < string , string >
217+ {
218+ [ "protocol" ] = "https" ,
219+ [ "host" ] = "github.com" ,
220+ [ "wwwauth" ] = "Basic realm=\" GitHub\" domain_hint=\" contoso\" " ,
221+ }
222+ ) ;
223+
224+ var context = new TestCommandContext ( ) ;
225+ context . CredentialStore . Add ( "https://github.com" , "alice" , "letmein123" ) ;
226+ context . CredentialStore . Add ( "https://github.com" , "bob_contoso" , "secret123" ) ;
227+ context . CredentialStore . Add ( "https://github.com" , "test_fabrikam" , "hidden_value" ) ;
228+
229+ var ghApiMock = new Mock < IGitHubRestApi > ( MockBehavior . Strict ) ;
230+ var ghAuthMock = new Mock < IGitHubAuthentication > ( MockBehavior . Strict ) ;
231+
232+ var provider = new GitHubHostProvider ( context , ghApiMock . Object , ghAuthMock . Object ) ;
233+
234+ ICredential result = await provider . GetCredentialAsync ( input ) ;
235+
236+ Assert . NotNull ( result ) ;
237+ Assert . Equal ( "bob_contoso" , result . Account ) ;
238+ Assert . Equal ( "secret123" , result . Password ) ;
239+ }
240+
241+ [ Fact ]
242+ public async Task GitHubHostProvider_GetCredentialAsync_MultipleDomainAccounts_PromptForAccountAndReturnCredentialForAccount ( )
243+ {
244+ var input = new InputArguments (
245+ new Dictionary < string , string >
246+ {
247+ [ "protocol" ] = "https" ,
248+ [ "host" ] = "github.com" ,
249+ [ "wwwauth" ] = "Basic realm=\" GitHub\" domain_hint=\" contoso\" " ,
250+ }
251+ ) ;
252+
253+ var context = new TestCommandContext ( ) ;
254+ context . CredentialStore . Add ( "https://github.com" , "alice" , "letmein123" ) ;
255+ context . CredentialStore . Add ( "https://github.com" , "bob_contoso" , "secret123" ) ;
256+ context . CredentialStore . Add ( "https://github.com" , "john_contoso" , "who_knows" ) ;
257+
258+ var ghApiMock = new Mock < IGitHubRestApi > ( MockBehavior . Strict ) ;
259+ var ghAuthMock = new Mock < IGitHubAuthentication > ( MockBehavior . Strict ) ;
260+
261+ ghAuthMock . Setup ( x => x . SelectAccountAsync ( It . IsAny < Uri > ( ) , It . IsAny < IEnumerable < string > > ( ) ) )
262+ . ReturnsAsync ( "john_contoso" ) ;
263+
264+ var provider = new GitHubHostProvider ( context , ghApiMock . Object , ghAuthMock . Object ) ;
265+
266+ ICredential result = await provider . GetCredentialAsync ( input ) ;
267+
268+ Assert . NotNull ( result ) ;
269+ Assert . Equal ( "john_contoso" , result . Account ) ;
270+ Assert . Equal ( "who_knows" , result . Password ) ;
271+
272+ ghAuthMock . Verify ( x => x . SelectAccountAsync (
273+ new Uri ( "https://github.com" ) , new [ ] { "bob_contoso" , "john_contoso" } ) ,
274+ Times . Once
275+ ) ;
276+ }
277+
278+ [ Fact ]
279+ public async Task GitHubHostProvider_GetCredentialAsync_MultipleDomainAccounts_PromptForAccountNewAccount ( )
280+ {
281+ var input = new InputArguments (
282+ new Dictionary < string , string >
283+ {
284+ [ "protocol" ] = "https" ,
285+ [ "host" ] = "github.com" ,
286+ [ "wwwauth" ] = "Basic realm=\" GitHub\" domain_hint=\" contoso\" " ,
287+ }
288+ ) ;
289+
290+ var newCredential = new GitCredential ( "alice" , "password" ) ;
291+
292+ var context = new TestCommandContext ( ) ;
293+ context . CredentialStore . Add ( "https://github.com" , "alice" , "letmein123" ) ;
294+ context . CredentialStore . Add ( "https://github.com" , "bob_contoso" , "secret123" ) ;
295+ context . CredentialStore . Add ( "https://github.com" , "john_contoso" , "who_knows" ) ;
296+
297+ var ghApiMock = new Mock < IGitHubRestApi > ( MockBehavior . Strict ) ;
298+ var ghAuthMock = new Mock < IGitHubAuthentication > ( MockBehavior . Strict ) ;
299+
300+ ghAuthMock . Setup ( x => x . SelectAccountAsync ( It . IsAny < Uri > ( ) , It . IsAny < IEnumerable < string > > ( ) ) )
301+ . ReturnsAsync ( ( string ) null ) ;
302+
303+ ghAuthMock . Setup ( x => x . GetAuthenticationAsync (
304+ It . IsAny < Uri > ( ) , It . IsAny < string > ( ) , It . IsAny < AuthenticationModes > ( ) ) )
305+ . ReturnsAsync ( new AuthenticationPromptResult ( AuthenticationModes . Pat , newCredential ) ) ;
306+
307+ var provider = new GitHubHostProvider ( context , ghApiMock . Object , ghAuthMock . Object ) ;
308+
309+ ICredential result = await provider . GetCredentialAsync ( input ) ;
310+
311+ Assert . Equal ( newCredential . Account , result . Account ) ;
312+ Assert . Equal ( newCredential . Password , result . Password ) ;
313+
314+ ghAuthMock . Verify ( x => x . GetAuthenticationAsync (
315+ new Uri ( "https://github.com" ) , null , It . IsAny < AuthenticationModes > ( ) ) ,
316+ Times . Once ) ;
317+ ghAuthMock . Verify ( x => x . SelectAccountAsync (
318+ new Uri ( "https://github.com" ) , new [ ] { "bob_contoso" , "john_contoso" } ) ,
319+ Times . Once
320+ ) ;
321+ }
322+
154323 [ Fact ]
155324 public async Task GitHubHostProvider_GenerateCredentialAsync_UnencryptedHttp_ThrowsException ( )
156325 {
0 commit comments