using System; using System.Collections.Generic; using System.Reactive.Linq; using System.Threading.Tasks; using NSubstitute; using Octokit.Reactive; using Xunit; namespace Octokit.Tests.Reactive { public class AuthorizationExtensionsTests { public class TheGetOrCreateApplicationAuthenticationMethod { [Fact] public async Task UsesCallbackToRetrieveTwoFactorCode() { var firstResponse = new TwoFactorRequiredException(TwoFactorType.AuthenticatorApp); var twoFactorChallengeResult = new TwoFactorChallengeResult("two-factor-code"); var secondResponse = new ApplicationAuthorization(0, null, null, null, null, null, null, null, DateTimeOffset.Now, DateTimeOffset.Now, null, "OAUTHSECRET"); var client = Substitute.For(); client.GetOrCreateApplicationAuthentication(Args.String, Args.String, Args.NewAuthorization) .Returns(Observable.Throw(firstResponse)); client.GetOrCreateApplicationAuthentication( Args.String, Args.String, Args.NewAuthorization, "two-factor-code") .Returns(Observable.Return(secondResponse)); var result = await client.GetOrCreateApplicationAuthentication( "clientId", "secret", new NewAuthorization { Note = "Was it this one?" }, _ => Observable.Return(twoFactorChallengeResult)); Assert.Equal("OAUTHSECRET", result.Token); client.Received().GetOrCreateApplicationAuthentication( "clientId", "secret", Arg.Is(a => a.Note == "Was it this one?")); client.Received().GetOrCreateApplicationAuthentication( "clientId", "secret", Arg.Is(a => a.Note == "Was it this one?"), "two-factor-code"); } [Fact] public async Task RetriesWhenResendRequested() { var firstResponse = new TwoFactorRequiredException(TwoFactorType.AuthenticatorApp); var challengeResults = new Queue(new[] { TwoFactorChallengeResult.RequestResendCode, new TwoFactorChallengeResult("two-factor-code") }); var secondResponse = new ApplicationAuthorization(0, null, null, null, null, null, null, null, DateTimeOffset.Now, DateTimeOffset.Now, null, "OAUTHSECRET"); var client = Substitute.For(); client.GetOrCreateApplicationAuthentication(Args.String, Args.String, Args.NewAuthorization) .Returns(Observable.Throw(firstResponse)); client.GetOrCreateApplicationAuthentication( Args.String, Args.String, Args.NewAuthorization, "two-factor-code") .Returns(Observable.Return(secondResponse)); var result = await client.GetOrCreateApplicationAuthentication( "clientId", "secret", new NewAuthorization { Note = "Was it this one?" }, _ => Observable.Return(challengeResults.Dequeue())); client.Received(2).GetOrCreateApplicationAuthentication("clientId", "secret", Arg.Any()); client.Received().GetOrCreateApplicationAuthentication("clientId", "secret", Arg.Any(), "two-factor-code"); Assert.Equal("OAUTHSECRET", result.Token); } [Fact] public void ThrowsTwoFactorChallengeFailedExceptionWhenProvidedCodeIsIncorrect() { var challengeResults = new Queue(new[] { TwoFactorChallengeResult.RequestResendCode, new TwoFactorChallengeResult("wrong-code") }); var twoFactorFailedException = new TwoFactorChallengeFailedException(); var data = new NewAuthorization(); var client = Substitute.For(); client.GetOrCreateApplicationAuthentication("clientId", "secret", Arg.Any()) .Returns(Observable.Throw(new TwoFactorRequiredException())); client.GetOrCreateApplicationAuthentication("clientId", "secret", Arg.Any(), "wrong-code") .Returns(Observable.Throw(twoFactorFailedException)); var observer = Substitute.For>(); client.GetOrCreateApplicationAuthentication( "clientId", "secret", data, _ => Observable.Return(challengeResults.Dequeue())) .Subscribe(observer); observer.Received().OnError(twoFactorFailedException); client.Received().GetOrCreateApplicationAuthentication("clientId", "secret", Arg.Any()); client.Received().GetOrCreateApplicationAuthentication("clientId", "secret", Arg.Any(), "wrong-code"); } } } }