public async Task Cancellation_token_is_passed_down_to_low_level_operations() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore; dataStore.RequestExecutor .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()) .Returns(async callInfo => { // Will pause for 1 second, unless CancellationToken has been passed through to us await Task.Delay(1000, callInfo.Arg <CancellationToken>()); return(new DefaultHttpResponse(204, "No Content", new HttpHeaders(), null, null, transportError: false) as IHttpResponse); }); var fakeAccount = dataStore.InstantiateWithHref <IAccount>("http://api.foo.bar/accounts/1"); var alreadyCanceledSource = new CancellationTokenSource(); alreadyCanceledSource.Cancel(); var stopwatch = Stopwatch.StartNew(); var deleted = false; try { await dataStore.DeleteAsync(fakeAccount, alreadyCanceledSource.Token); } catch (TaskCanceledException) { deleted = true; } stopwatch.Stop(); stopwatch.ElapsedMilliseconds.ShouldBeLessThan(1000); deleted.ShouldBeTrue(); }
public async Task Handle_error(string id_, string jwtResponse, Type expectedExceptionType, int expectedCode, int expectedStatus, string expectedMessage, string expectedDeveloperMessage) { var testApiKey = ClientApiKeys.Builder() .SetId("2EV70AHRTYF0JOA7OEFO3SM29") .SetSecret("goPUHQMkS4dlKwl5wtbNd91I+UrRehCsEDJrIrMruK8") .Build(); var fakeRequestExecutor = Substitute.For <IRequestExecutor>(); fakeRequestExecutor.ApiKey.Returns(testApiKey); this.dataStore = TestDataStore.Create(fakeRequestExecutor, Caches.NewInMemoryCacheProvider().Build()); var request = new DefaultHttpRequest(HttpMethod.Get, new CanonicalUri($"https://foo.bar?{IdSiteClaims.JwtResponse}={jwtResponse}")); IIdSiteAsyncCallbackHandler callbackHandler = new DefaultIdSiteAsyncCallbackHandler(this.dataStore, request); try { var accountResult = await callbackHandler.GetAccountResultAsync(CancellationToken.None); throw new Exception("Should not reach here. Proper exception was not thrown."); } catch (IdSiteRuntimeException e) when(expectedExceptionType.IsAssignableFrom(e.GetType())) { e.Code.ShouldBe(expectedCode); e.HttpStatus.ShouldBe(expectedStatus); e.Message.ShouldBe(expectedMessage); e.DeveloperMessage.ShouldBe(expectedDeveloperMessage); } catch (Exception e) when(expectedExceptionType.IsAssignableFrom(e.GetType())) { e.Message.ShouldStartWith(expectedMessage); } }
public async Task Single_item_data_is_deserialized_properly() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); // Verify against data from FakeJson.Account account.CreatedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z")); account.Email.ShouldBe("*****@*****.**"); account.FullName.ShouldBe("Han Solo"); account.GivenName.ShouldBe("Han"); account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount"); account.MiddleName.ShouldBeNull(); account.ModifiedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z")); account.Status.ShouldBe(AccountStatus.Enabled); account.Surname.ShouldBe("Solo"); account.Username.ShouldBe("*****@*****.**"); (account as DefaultAccount).AccessTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/accessTokens"); (account as DefaultAccount).ApiKeys.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/apiKeys"); (account as DefaultAccount).Applications.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/applications"); (account as DefaultAccount).CustomData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/customData"); (account as DefaultAccount).Directory.Href.ShouldBe("https://api.stormpath.com/v1/directories/foobarDirectory"); (account as DefaultAccount).EmailVerificationToken.Href.ShouldBeNull(); (account as DefaultAccount).GroupMemberships.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/groupMemberships"); (account as DefaultAccount).Groups.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/groups"); (account as DefaultAccount).ProviderData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/providerData"); (account as DefaultAccount).RefreshTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/refreshTokens"); (account as DefaultAccount).Tenant.Href.ShouldBe("https://api.stormpath.com/v1/tenants/foobarTenant"); }
public async Task Saving_resource_posts_changed_values_only() { string savedHref = null; string savedJson = null; var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); dataStore.RequestExecutor .When(x => x.ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>())) .Do(call => { savedHref = call.Arg <IHttpRequest>().CanonicalUri.ToString(); savedJson = call.Arg <IHttpRequest>().Body; }); var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount"); account.SetMiddleName("Test"); account.SetUsername("newusername"); await account.SaveAsync(); savedHref.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount"); var savedMap = Newtonsoft.Json.JsonConvert.DeserializeObject <Dictionary <string, string> >(savedJson); savedMap.Count.ShouldBe(2); savedMap["middleName"].ShouldBe("Test"); savedMap["username"].ShouldBe("newusername"); }
public async Task Deleting_custom_data_with_proxy_updates_cache() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); // GET returns expanded request requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false) as IHttpResponse)); // Save is not an expanded request requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse)); var account = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount?expand=customData"); account.CustomData.Remove("isAdmin"); await account.SaveAsync(); var customData = await account.GetCustomDataAsync(); customData["isAdmin"].ShouldBe(null); await this.dataStore.RequestExecutor.Received(1).ExecuteAsync( Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get), Arg.Any <CancellationToken>()); }
public async Task Embedded_custom_data_is_cleared_for_all_instances_after_save() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); var account2 = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); account.CustomData.Put("foo", 123); await account.SaveAsync(); var expectedBody = @"{""customData"":{""foo"":123}}"; var body = dataStore.RequestExecutor .ReceivedCalls() .Last() .GetArguments() .OfType <IHttpRequest>() .First() .Body; body.ShouldBe(expectedBody); dataStore.RequestExecutor.ClearReceivedCalls(); await account2.SaveAsync(); // Empty save, should not POST anything await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()); }
public async Task Does_not_cache_email_verification_tokens() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); var emailVerificationTokenResponse = @" { ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount"" } "; // POST returns email verification token response requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse)); var href = $"/accounts/emailVerificationTokens/fooToken"; await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None); await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None); // Not cached await this.dataStore.RequestExecutor.Received(2).ExecuteAsync( Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()); }
public void Does_not_cache_password_reset_tokens() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); var passwordResetTokenResponse = @" { ""href"": ""https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar"", ""email"": ""*****@*****.**"", ""account"": { ""href"": ""https://api.stormpath.com/v1/accounts/cJoiwcorTTmkDDBsf02bAb"" } } "; // POST returns token response requestExecutor .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post)) .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false)); // GET also returns token response requestExecutor .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get)) .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false)); this.dataStore.GetResource <IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar"); this.dataStore.GetResource <IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar"); // Not cached this.dataStore.RequestExecutor.Received(2).Execute( Arg.Any <IHttpRequest>()); }
public DefaultResourceFactory_tests() { var dataStore = TestDataStore.Create(); var identityMap = new MemoryCacheIdentityMap <ResourceData>(TimeSpan.FromSeconds(10), Substitute.For <ILogger>()); // arbitrary expiration time this.factory = new DefaultResourceFactory(dataStore, identityMap); }
public async Task When_saving_returns_empty_response_without_status_202_throws_error() { // Expected behavior: Saving should always return the updated data unless we get back HTTP 202 (Accepted for Processing). var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore; dataStore.RequestExecutor .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()) .Returns(Task.FromResult <IHttpResponse>(new DefaultHttpResponse(200, "OK", null, null, null, transportError: false))); var account = dataStore.Instantiate <IAccount>(); account.SetMiddleName("Test"); account.SetUsername("newusername"); bool erroredAsExpected = false; try { await dataStore.CreateAsync("http://api.foo.bar/accounts", account, CancellationToken.None); } catch (ResourceException rex) { rex.DeveloperMessage.ShouldBe("Unable to obtain resource data from the API server."); erroredAsExpected = true; } erroredAsExpected.ShouldBeTrue(); }
public async Task Does_not_cache_login_attempts() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); var authResponse = @" { ""account"": { ""href"" : ""https://api.stormpath.com/v1/accounts/5BedLIvyfLjdKKEEXAMPLE"" } }"; // POST returns auth response requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), authResponse, "application/json", transportError: false) as IHttpResponse)); var request = new UsernamePasswordRequest("foo", "bar", null, null) as IAuthenticationRequest; var authenticator = new BasicAuthenticator(this.dataStore); var result1 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None); var result2 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None); // Not cached await this.dataStore.RequestExecutor.Received(2).ExecuteAsync( Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()); }
public async Task Updating_resource_updates_cache() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); // GET returns original requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse)); // Save returns update data requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account.Replace("*****@*****.**", "*****@*****.**"), "application/json", transportError: false) as IHttpResponse)); var account1 = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount"); account1.Email.ShouldBe("*****@*****.**"); account1.SetEmail("*****@*****.**"); await account1.SaveAsync(); account1.Email.ShouldBe("*****@*****.**"); var account2 = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount"); account2.Email.ShouldBe("*****@*****.**"); // Only one GET; second is intercepted by the cache (but the updated data is returned!) #magic await this.dataStore.RequestExecutor.Received(1).ExecuteAsync( Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get), Arg.Any <CancellationToken>()); }
public void Updating_custom_data_with_proxy_updates_cache() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); // GET returns expanded request requestExecutor .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get)) .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false)); // Save is not an expanded request requestExecutor .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post)) .Returns(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false)); var account = this.dataStore.GetResource <IAccount>("/accounts/foobarAccount?expand=customData"); account.CustomData.Put("isAdmin", true); account.CustomData.Put("writeAccess", "yes"); account.Save(); var customData = account.GetCustomData(); customData["isAdmin"].ShouldBe(true); customData["writeAccess"].ShouldBe("yes"); this.dataStore.RequestExecutor.Received(1).Execute( Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get)); }
public void Instantiated_resources_contain_reference_to_client() { var fakeClient = Substitute.For <IClient>(); var dataStore = TestDataStore.Create(client: fakeClient); var account = dataStore.Instantiate <IAccount>(); account.Client.ShouldBe(fakeClient); }
public void GetValue_returns_token_value() { var dataStore = TestDataStore.Create(); var href = "https://api.foobar.com/v1/applications/WpM9nyZ2TbaEzfbRvLk9KA/passwordResetTokens/my-token-value-here"; var passwordResetToken = dataStore.InstantiateWithHref <IPasswordResetToken>(href); passwordResetToken.GetValue().ShouldBe("my-token-value-here"); }
public async Task Default_headers_are_applied_to_all_requests() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); // Verify the default headers await dataStore.RequestExecutor.Received().ExecuteAsync( Arg.Is <IHttpRequest>(request => request.Headers.Accept == "application/json"), Arg.Any <CancellationToken>()); }
private static IInternalDataStore GetFakeDataStore() { var fakeApiKey = ClientApiKeys.Builder() .SetId("fake_api_key") .SetSecret("fake_secret") .Build(); var stubClient = Clients.Builder() .SetApiKey(fakeApiKey) .Build(); var fakeDataStore = TestDataStore.Create( requestExecutor: new StubRequestExecutor(FakeJson.Application, fakeApiKey).Object, client: stubClient); return(fakeDataStore); }
public async Task Trace_log_is_sent_to_logger() { var fakeLog = new List <LogEntry>(); var stubLogger = Substitute.For <ILogger>(); stubLogger.When(x => x.Log(Arg.Any <LogEntry>())).Do(call => { fakeLog.Add(call.Arg <LogEntry>()); }); var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object, logger: stubLogger); var account = await dataStore.GetResourceAsync <IAccount>("account", CancellationToken.None); await account.DeleteAsync(); fakeLog.Count.ShouldBeGreaterThanOrEqualTo(2); }
public async Task When_getting_account() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); var accountResult = dataStore.InstantiateWithData <IAccountResult>( new Dictionary <string, object>() { ["account"] = new LinkProperty("https://foo.bar/account1") }); var account = await accountResult.GetAccountAsync(); account.FullName.ShouldBe("Han Solo"); await dataStore.RequestExecutor.Received().ExecuteAsync( Arg.Is <IHttpRequest>(x => x.CanonicalUri.ToString() == "https://foo.bar/account1"), Arg.Any <CancellationToken>()); }
public async Task When_getting_existing_provider_based_account() { // 200 OK indicates the account is not new var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore; dataStore.RequestExecutor .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()) .Returns(Task.FromResult <IHttpResponse>(new DefaultHttpResponse(200, "OK", null, FakeJson.Account, "application/json", transportError: false))); var providerAccountResult = await dataStore.GetResourceAsync <IProviderAccountResult>("/providerAccount", CancellationToken.None); providerAccountResult.IsNewAccount.ShouldBeFalse(); var account = providerAccountResult.Account; // Verify against data from FakeJson.Account account.Email.ShouldBe("*****@*****.**"); account.FullName.ShouldBe("Han Solo"); }
public async Task Embedded_custom_data_is_cleared_after_reload() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); account.CustomData.Put("foo", 123); await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); // reload await account.SaveAsync(); // Empty save, should not POST anything await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()); }
public async Task Email_verification_result_removes_associated_account_from_cache() { var cacheProvider = Caches.NewInMemoryCacheProvider().Build(); var requestExecutor = Substitute.For <IRequestExecutor>(); this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider); var emailVerificationTokenResponse = @" { ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount"" } "; // POST returns email verification token response requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()) .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse)); // GET returns account as unverified first, // then second GET returns account as verified requestExecutor .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account.Replace(@"""status"": ""ENABLED""", @"""status"": ""UNVERIFIED"""), "application/json", transportError: false) as IHttpResponse), Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse)); var account = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount"); account.Status.ShouldBe(AccountStatus.Unverified); var href = $"/accounts/emailVerificationTokens/fooToken"; var tokenResponse = await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None); await this.dataStore.GetResourceAsync <IAccount>(tokenResponse.Href); account.Status.ShouldBe(AccountStatus.Enabled); // Second GET should *not* hit cache await this.dataStore.RequestExecutor.Received(2).ExecuteAsync( Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get), Arg.Any <CancellationToken>()); }
public async Task When_getting_account_and_no_account_present_throws() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object); var accountResult = dataStore.InstantiateWithData <IAccountResult>( new Dictionary <string, object>() { ["state"] = "foobar" }); // TODO mono bug - should be ApplicationException await Should.ThrowAsync <Exception>(async() => { var account = await accountResult.GetAccountAsync(); }); await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync( Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()); }
public async Task Only_diff_is_sent_for_updates() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.CustomData).Object); var customData = await dataStore.GetResourceAsync <ICustomData>("/customData", CancellationToken.None); customData.Count().ShouldBe(5); customData.Put("newprop", "foo"); await customData.SaveAsync(); var expectedBody = @"{""newprop"":""foo""}"; // Sent the update as a diff await dataStore.RequestExecutor.Received().ExecuteAsync( Arg.Is <IHttpRequest>(request => request.Method == HttpMethod.Post && request.Body == expectedBody), Arg.Any <CancellationToken>()); }
public void Encodes_password_grant_attempt() { var dataStore = TestDataStore.Create(); var createGrantAttempt = dataStore.Instantiate <IPasswordGrantAuthenticationAttempt>(); createGrantAttempt.SetLogin("*****@*****.**"); createGrantAttempt.SetPassword("Secret1"); createGrantAttempt.SetAccountStore("https://api.stormpath.com/v1/directories/1bcd23ec1d0a8wa6"); var properties = (createGrantAttempt as AbstractResource).GetResourceData().GetUpdatedProperties().ToDictionary(); var result = new FormUrlEncoder(properties) .ToString() .Split('&'); result.ShouldContain("grant_type=password"); result.ShouldContain("username=tom%40stormpath.com"); result.ShouldContain("password=Secret1"); result.ShouldContain("accountStore=https%3A%2F%2Fapi.stormpath.com%2Fv1%2Fdirectories%2F1bcd23ec1d0a8wa6"); }
public async Task When_saving_returns_empty_response_with_status_202() { // Expected behavior: Saving should always return the updated data unless we get back HTTP 202 (Accepted for Processing). var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore; dataStore.RequestExecutor .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()) .Returns(Task.FromResult <IHttpResponse>(new DefaultHttpResponse(202, "Accepted", null, null, null, transportError: false))); var account = dataStore.Instantiate <IAccount>(); account.SetMiddleName("Test"); account.SetUsername("newusername"); var result = await dataStore.CreateAsync("http://api.foo.bar/accounts", account, CancellationToken.None); bool isEmpty = (result as AbstractResource).GetPropertyNames().Single() == "href"; isEmpty.ShouldBeTrue(); result.Href.ShouldBeNullOrEmpty(); }
public async Task Collection_resource_data_is_deserialized_properly() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.AccountList).Object); IAsyncQueryable <IAccount> accounts = new CollectionResourceQueryable <IAccount>("/accounts", dataStore); await accounts.MoveNextAsync(); // Verify against data from FakeJson.AccountList (accounts as CollectionResourceQueryable <IAccount>).Size.ShouldBe(6); (accounts as CollectionResourceQueryable <IAccount>).Offset.ShouldBe(0); (accounts as CollectionResourceQueryable <IAccount>).Limit.ShouldBe(25); accounts.CurrentPage.Count().ShouldBe(6); var account = accounts.CurrentPage.First(); account.CreatedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z")); account.Email.ShouldBe("*****@*****.**"); account.FullName.ShouldBe("Han Solo"); account.GivenName.ShouldBe("Han"); account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1"); account.MiddleName.ShouldBeNull(); account.ModifiedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z")); account.Status.ShouldBe(AccountStatus.Enabled); account.Surname.ShouldBe("Solo"); account.Username.ShouldBe("*****@*****.**"); (account as DefaultAccount).AccessTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/accessTokens"); (account as DefaultAccount).ApiKeys.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/apiKeys"); (account as DefaultAccount).Applications.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/applications"); (account as DefaultAccount).CustomData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/customData"); (account as DefaultAccount).Directory.Href.ShouldBe("https://api.stormpath.com/v1/directories/directory1"); (account as DefaultAccount).EmailVerificationToken.Href.ShouldBeNull(); (account as DefaultAccount).GroupMemberships.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/groupMemberships"); (account as DefaultAccount).Groups.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/groups"); (account as DefaultAccount).ProviderData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/providerData"); (account as DefaultAccount).RefreshTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/refreshTokens"); (account as DefaultAccount).Tenant.Href.ShouldBe("https://api.stormpath.com/v1/tenants/foobarTenant"); }
public async Task Deletes_are_performed_with_updates() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.CustomData).Object); var customData = await dataStore.GetResourceAsync <ICustomData>("/customData", CancellationToken.None); customData.Put("testingIsUseful", true); customData.Remove("membershipType"); await customData.SaveAsync(); // Delete await dataStore.RequestExecutor.Received().ExecuteAsync( Arg.Is <IHttpRequest>(request => request.Method == HttpMethod.Delete && request.CanonicalUri.ToString() == "https://api.stormpath.com/v1/accounts/foobarAccount/customData/membershipType"), Arg.Any <CancellationToken>()); // Post await dataStore.RequestExecutor.Received().ExecuteAsync( Arg.Is <IHttpRequest>(request => request.Method == HttpMethod.Post && request.Body == @"{""testingIsUseful"":true}"), Arg.Any <CancellationToken>()); }
public async Task Simultaneous_delete_and_update_only_performs_update() { var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.CustomData).Object); var customData = await dataStore.GetResourceAsync <ICustomData>("/customData", CancellationToken.None); customData.Remove("membershipType"); customData.Put("membershipType", "unknown"); await customData.SaveAsync(); // Delete await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync( Arg.Is <IHttpRequest>(request => request.Method == HttpMethod.Delete && request.CanonicalUri.ToString() == "https://api.stormpath.com/v1/accounts/foobarAccount/customData/membershipType"), Arg.Any <CancellationToken>()); // Update await dataStore.RequestExecutor.Received().ExecuteAsync( Arg.Is <IHttpRequest>(request => request.Method == HttpMethod.Post && request.Body == @"{""membershipType"":""unknown""}"), Arg.Any <CancellationToken>()); }
private void BuildDataStore(string resourceResponse, ICacheProvider cacheProviderUnderTest) { var fakeRequestExecutor = new StubRequestExecutor(resourceResponse); this.dataStore = TestDataStore.Create(fakeRequestExecutor.Object, cacheProviderUnderTest); }