Browse Source

Some tests

pull/65/head
Sebastian Stehle 9 years ago
parent
commit
bc3bd42d32
  1. 8
      src/Squidex/Controllers/UI/Extensions.cs
  2. 66
      src/Squidex/Controllers/UI/Profile/ProfileController.cs
  3. 4
      src/Squidex/Controllers/UI/Profile/ProfileVM.cs
  4. 113
      src/Squidex/Views/Profile/Profile.cshtml
  5. 18
      tests/Squidex.Read.Tests/Apps/CachingAppProviderTests.cs
  6. 18
      tests/Squidex.Read.Tests/Schemas/CachingSchemaProviderTests.cs
  7. 60
      tests/Squidex.Read.Tests/Users/AssetUserPictureStoreTests.cs

8
src/Squidex/Controllers/UI/Extensions.cs

@ -15,6 +15,14 @@ namespace Squidex.Controllers.UI
{ {
public static class Extensions public static class Extensions
{ {
public static Task<IdentityResult> UpdateAsync(this UserManager<IUser> userManager, IUser user, string email, string displayName)
{
user.UpdateEmail(email);
user.UpdateDisplayName(displayName);
return userManager.UpdateAsync(user);
}
public static async Task<ExternalLoginInfo> GetExternalLoginInfoWithDisplayNameAsync(this SignInManager<IUser> signInManager, string expectedXsrf = null) public static async Task<ExternalLoginInfo> GetExternalLoginInfoWithDisplayNameAsync(this SignInManager<IUser> signInManager, string expectedXsrf = null)
{ {
var externalLogin = await signInManager.GetExternalLoginInfoAsync(expectedXsrf); var externalLogin = await signInManager.GetExternalLoginInfoAsync(expectedXsrf);

66
src/Squidex/Controllers/UI/Profile/ProfileController.cs

@ -57,26 +57,11 @@ namespace Squidex.Controllers.UI.Profile
{ {
var user = await userManager.GetUserAsync(User); var user = await userManager.GetUserAsync(User);
ViewBag.SuccessMessage = successMessage; return View(await GetProfileVM(user, successMessage: successMessage));
return View(await GetProfileVM(user));
} }
[HttpPost] [HttpPost]
[Route("/account/profile")] [Route("/account/profile/login-add/")]
public Task<IActionResult> Profile(ChangeProfileModel model)
{
return MakeChangeAsync(async user =>
{
user.UpdateEmail(model.Email);
user.UpdateDisplayName(model.DisplayName);
return await userManager.UpdateAsync(user);
}, "Account updated successfully. Please logout and login again to see the changes.");
}
[HttpPost]
[Route("account/add-login/")]
public async Task<IActionResult> AddLogin(string provider) public async Task<IActionResult> AddLogin(string provider)
{ {
await HttpContext.Authentication.SignOutAsync(identityCookieOptions.Value.ExternalCookieAuthenticationScheme); await HttpContext.Authentication.SignOutAsync(identityCookieOptions.Value.ExternalCookieAuthenticationScheme);
@ -89,7 +74,7 @@ namespace Squidex.Controllers.UI.Profile
} }
[HttpGet] [HttpGet]
[Route("account/add-login-callback/")] [Route("/account/profile/login-add-callback/")]
public Task<IActionResult> AddLoginCallback(string remoteError = null) public Task<IActionResult> AddLoginCallback(string remoteError = null)
{ {
return MakeChangeAsync(async user => return MakeChangeAsync(async user =>
@ -101,7 +86,23 @@ namespace Squidex.Controllers.UI.Profile
} }
[HttpPost] [HttpPost]
[Route("/account/set-password")] [Route("/account/profile/update")]
public Task<IActionResult> Profile(ChangeProfileModel model)
{
return MakeChangeAsync(user => userManager.UpdateAsync(user, model.Email, model.DisplayName),
"Account updated successfully.");
}
[HttpPost]
[Route("/account/profile/login-remove")]
public Task<IActionResult> RemoveLogin(RemoveLoginModel model)
{
return MakeChangeAsync(user => userManager.RemoveLoginAsync(user, model.LoginProvider, model.ProviderKey),
"Login provider removed successfully.");
}
[HttpPost]
[Route("/account/profile/password-set")]
public Task<IActionResult> SetPassword(SetPasswordModel model) public Task<IActionResult> SetPassword(SetPasswordModel model)
{ {
return MakeChangeAsync(user => userManager.AddPasswordAsync(user, model.Password), return MakeChangeAsync(user => userManager.AddPasswordAsync(user, model.Password),
@ -109,7 +110,7 @@ namespace Squidex.Controllers.UI.Profile
} }
[HttpPost] [HttpPost]
[Route("/account/change-password")] [Route("/account/profile/password-change")]
public Task<IActionResult> ChangePassword(ChangePasswordModel model) public Task<IActionResult> ChangePassword(ChangePasswordModel model)
{ {
return MakeChangeAsync(user => userManager.ChangePasswordAsync(user, model.OldPassword, model.Password), return MakeChangeAsync(user => userManager.ChangePasswordAsync(user, model.OldPassword, model.Password),
@ -117,15 +118,7 @@ namespace Squidex.Controllers.UI.Profile
} }
[HttpPost] [HttpPost]
[Route("/account/remove-login")] [Route("/account/profile/upload-picture")]
public Task<IActionResult> RemoveLogin(RemoveLoginModel model)
{
return MakeChangeAsync(user => userManager.RemoveLoginAsync(user, model.LoginProvider, model.ProviderKey),
"Login provider removed successfully.");
}
[HttpPost]
[Route("/account/upload-picture")]
public Task<IActionResult> UploadPicture(List<IFormFile> file) public Task<IActionResult> UploadPicture(List<IFormFile> file)
{ {
return MakeChangeAsync(async user => return MakeChangeAsync(async user =>
@ -152,7 +145,7 @@ namespace Squidex.Controllers.UI.Profile
user.SetPictureUrlToStore(); user.SetPictureUrlToStore();
return await userManager.UpdateAsync(user); return await userManager.UpdateAsync(user);
}, "Password set successfully."); }, "Picture uploaded successfully.");
} }
private async Task<IActionResult> MakeChangeAsync(Func<IUser, Task<IdentityResult>> action, string successMessage, ChangeProfileModel model = null) private async Task<IActionResult> MakeChangeAsync(Func<IUser, Task<IdentityResult>> action, string successMessage, ChangeProfileModel model = null)
@ -164,6 +157,7 @@ namespace Squidex.Controllers.UI.Profile
return View("Profile", await GetProfileVM(user, model)); return View("Profile", await GetProfileVM(user, model));
} }
string errorMessage;
try try
{ {
var result = await action(user); var result = await action(user);
@ -175,17 +169,17 @@ namespace Squidex.Controllers.UI.Profile
return RedirectToAction(nameof(Profile), new { successMessage }); return RedirectToAction(nameof(Profile), new { successMessage });
} }
ViewBag.ErrorMessage = string.Join(". ", result.Errors.Select(x => x.Description)); errorMessage = string.Join(". ", result.Errors.Select(x => x.Description));
} }
catch catch
{ {
ViewBag.ErrorMessage = "An unexpected exception occurred."; errorMessage = "An unexpected exception occurred.";
} }
return View("Profile", await GetProfileVM(user, model)); return View("Profile", await GetProfileVM(user, model, errorMessage));
} }
private async Task<ProfileVM> GetProfileVM(IUser user, ChangeProfileModel model = null) private async Task<ProfileVM> GetProfileVM(IUser user, ChangeProfileModel model = null, string errorMessage = null, string successMessage = null)
{ {
var providers = var providers =
signInManager.GetExternalAuthenticationSchemes() signInManager.GetExternalAuthenticationSchemes()
@ -195,11 +189,13 @@ namespace Squidex.Controllers.UI.Profile
{ {
Id = user.Id, Id = user.Id,
Email = user.Email, Email = user.Email,
ErrorMessage = errorMessage,
ExternalLogins = user.Logins, ExternalLogins = user.Logins,
ExternalProviders = providers, ExternalProviders = providers,
DisplayName = user.DisplayName(), DisplayName = user.DisplayName(),
HasPassword = await userManager.HasPasswordAsync(user), HasPassword = await userManager.HasPasswordAsync(user),
HasPasswordAuth = identityOptions.Value.AllowPasswordAuth HasPasswordAuth = identityOptions.Value.AllowPasswordAuth,
SuccessMessage = successMessage
}; };
if (model != null) if (model != null)

4
src/Squidex/Controllers/UI/Profile/ProfileVM.cs

@ -19,6 +19,10 @@ namespace Squidex.Controllers.UI.Profile
public string DisplayName { get; set; } public string DisplayName { get; set; }
public string ErrorMessage { get; set; }
public string SuccessMessage { get; set; }
public bool HasPassword { get; set; } public bool HasPassword { get; set; }
public bool HasPasswordAuth { get; set; } public bool HasPasswordAuth { get; set; }

113
src/Squidex/Views/Profile/Profile.cshtml

@ -15,17 +15,17 @@
<h2>Personal Information</h2> <h2>Personal Information</h2>
@if (!string.IsNullOrWhiteSpace(ViewBag.SuccessMessage)) @if (!string.IsNullOrWhiteSpace(Model.SuccessMessage))
{ {
<div class="form-alert form-alert-success" id="success"> <div class="form-alert form-alert-success" id="success">
@ViewBag.SuccessMessage @Model.SuccessMessage
</div> </div>
} }
@if (!string.IsNullOrWhiteSpace(ViewBag.ErrorMessage)) @if (!string.IsNullOrWhiteSpace(Model.ErrorMessage))
{ {
<div class="form-alert form-alert-error"> <div class="form-alert form-alert-error">
@ViewBag.ErrorMessage @Model.ErrorMessage
</div> </div>
} }
@ -74,56 +74,59 @@
<button type="submit" class="btn btn-primary">Save</button> <button type="submit" class="btn btn-primary">Save</button>
</form> </form>
<div class="profile-section"> @if (Model.ExternalProviders.Any())
<h2>Logins</h2> {
<div class="profile-section">
<table class="table table-fixed table-lesspadding"> <h2>Logins</h2>
<colgroup>
<col style="width: 100px;" /> <table class="table table-fixed table-lesspadding">
<col style="width: 100%;" /> <colgroup>
<col style="width: 100px;" /> <col style="width: 100px;"/>
</colgroup> <col style="width: 100%;"/>
@foreach (var login in Model.ExternalLogins) <col style="width: 100px;"/>
{ </colgroup>
<tr> @foreach (var login in Model.ExternalLogins)
<td> {
<span>@login.LoginProvider</span> <tr>
</td> <td>
<td> <span>@login.LoginProvider</span>
<span class="truncate">@login.ProviderDisplayName</span> </td>
</td> <td>
<td class="text-right"> <span class="truncate">@login.ProviderDisplayName</span>
@if (Model.ExternalLogins.Count > 1 || Model.HasPassword) </td>
{ <td class="text-right">
<form asp-controller="Profile" asp-action="RemoveLogin" method="post"> @if (Model.ExternalLogins.Count > 1 || Model.HasPassword)
<input type="hidden" value="@login.LoginProvider" name="LoginProvider" /> {
<input type="hidden" value="@login.ProviderKey" name="ProviderKey" /> <form asp-controller="Profile" asp-action="RemoveLogin" method="post">
<input type="hidden" value="@login.LoginProvider" name="LoginProvider"/>
<button type="submit" class="btn btn-link btn-danger btn-sm"> <input type="hidden" value="@login.ProviderKey" name="ProviderKey"/>
Remove
</button> <button type="submit" class="btn btn-link btn-danger btn-sm">
</form> Remove
} </button>
</td> </form>
</tr> }
} </td>
</table> </tr>
}
<form asp-controller="Profile" asp-action="AddLogin" method="post"> </table>
@foreach (var provider in Model.ExternalProviders)
{ <form asp-controller="Profile" asp-action="AddLogin" method="post">
var schema = provider.AuthenticationScheme.ToLowerInvariant(); @foreach (var provider in Model.ExternalProviders.Where(x => !Model.ExternalLogins.Any(y => x.AuthenticationScheme == y.LoginProvider)))
{
<button class="btn external-button-small btn btn-@schema" type="submit" name="provider" value="@provider.AuthenticationScheme"> var schema = provider.AuthenticationScheme.ToLowerInvariant();
<i class="icon-@schema external-icon"></i>
</button> <button class="btn external-button-small btn btn-@schema" type="submit" name="provider" value="@provider.AuthenticationScheme">
} <i class="icon-@schema external-icon"></i>
</form> </button>
</div> }
</form>
</div>
}
<div class="profile-section"> @if (Model.HasPasswordAuth)
@if (Model.HasPasswordAuth) {
{ <div class="profile-section">
<h2>Password</h2> <h2>Password</h2>
@if (Model.HasPassword) @if (Model.HasPassword)
@ -207,8 +210,8 @@
</div> </div>
</form> </form>
} }
} </div>
</div> }
</div> </div>
<script> <script>

18
tests/Squidex.Read.Tests/Apps/CachingAppProviderTests.cs

@ -49,6 +49,24 @@ namespace Squidex.Read.Apps
sut = new CachingAppProvider(cache, repository.Object); sut = new CachingAppProvider(cache, repository.Object);
} }
[Fact]
public void Should_return_empty_for_events_filter()
{
Assert.Equal(string.Empty, sut.EventsFilter);
}
[Fact]
public void Should_return_empty_for_name()
{
Assert.Equal(typeof(CachingAppProvider).Name, sut.Name);
}
[Fact]
public void Should_do_nothing_when_clearing()
{
Assert.NotNull(sut.ClearAsync());
}
[Fact] [Fact]
public async Task Should_also_retrieve_app_by_name_if_retrieved_by_id_before() public async Task Should_also_retrieve_app_by_name_if_retrieved_by_id_before()
{ {

18
tests/Squidex.Read.Tests/Schemas/CachingSchemaProviderTests.cs

@ -52,6 +52,24 @@ namespace Squidex.Read.Schemas
sut = new CachingSchemaProvider(cache, repository.Object); sut = new CachingSchemaProvider(cache, repository.Object);
} }
[Fact]
public void Should_return_empty_for_events_filter()
{
Assert.Equal(string.Empty, sut.EventsFilter);
}
[Fact]
public void Should_return_empty_for_name()
{
Assert.Equal(typeof(CachingSchemaProvider).Name, sut.Name);
}
[Fact]
public void Should_do_nothing_when_clearing()
{
Assert.NotNull(sut.ClearAsync());
}
[Fact] [Fact]
public async Task Should_also_retrieve_schema_by_name_if_retrieved_by_id_before() public async Task Should_also_retrieve_schema_by_name_if_retrieved_by_id_before()
{ {

60
tests/Squidex.Read.Tests/Users/AssetUserPictureStoreTests.cs

@ -0,0 +1,60 @@
// ==========================================================================
// AssetUserPictureStoreTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.IO;
using System.Threading.Tasks;
using Moq;
using Squidex.Infrastructure.Assets;
using Squidex.Infrastructure.Tasks;
using Xunit;
namespace Squidex.Read.Users
{
public class AssetUserPictureStoreTests
{
private readonly Mock<IAssetStore> assetStore = new Mock<IAssetStore>();
private readonly AssetUserPictureStore sut;
private readonly string userId = Guid.NewGuid().ToString();
public AssetUserPictureStoreTests()
{
sut = new AssetUserPictureStore(assetStore.Object);
}
[Fact]
public async Task Should_invoke_asset_store_to_upload_picture()
{
var stream = new MemoryStream();
assetStore.Setup(x => x.UploadAsync(userId, 0, "picture", stream))
.Returns(TaskHelper.Done)
.Verifiable();
await sut.UploadAsync(userId, stream);
assetStore.VerifyAll();
}
[Fact]
public async Task Should_invoke_asset_store_to_download_picture()
{
assetStore.Setup(x => x.DownloadAsync(userId, 0, "picture", It.IsAny<Stream>()))
.Callback<string, long, string, Stream>((id, version, suffix, stream) => stream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4 ))
.Returns(TaskHelper.Done)
.Verifiable();
var result = await sut.DownloadAsync(userId);
Assert.Equal(0, result.Position);
Assert.Equal(4, result.Length);
assetStore.VerifyAll();
}
}
}
Loading…
Cancel
Save