using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Novelly.Api.Data; using Novelly.Api.Users; namespace Novelly.Api.Tests; [TestFixture] public class UserAccountTests { private TestDatabase _db = null!; private ServiceProvider _provider = null!; private IServiceScope _scope = null!; private UserAccountService _accounts = null!; [SetUp] public void SetUp() { _db = new TestDatabase(); var services = new ServiceCollection(); services.AddLogging(); services.AddHttpContextAccessor(); services.AddDataProtection(); services.AddAuthentication(IdentityConstants.ApplicationScheme).AddIdentityCookies(); services.AddScoped(_ => _db.CreateContext()); services.AddScoped(sp => sp.GetRequiredService()); services.AddIdentityCore(options => options.User.RequireUniqueEmail = true) .AddEntityFrameworkStores() .AddSignInManager(); _provider = services.BuildServiceProvider(); _provider.GetRequiredService().HttpContext = new DefaultHttpContext { RequestServices = _provider }; _scope = _provider.CreateScope(); _accounts = new UserAccountService( _scope.ServiceProvider.GetRequiredService>(), _scope.ServiceProvider.GetRequiredService>(), _scope.ServiceProvider.GetRequiredService(), new CapturingLogger(), new RegisterRequestValidator(), new LoginRequestValidator()); } [TearDown] public void TearDown() { _scope.Dispose(); _provider.Dispose(); _db.Dispose(); } [Test] public async Task The_first_account_created_becomes_an_admin() { var user = await _accounts.RegisterAsync(new RegisterRequest("first@novelly.test", "Password123!", "First Writer")); Assert.That(user.GlobalRole, Is.EqualTo(GlobalRole.Admin)); } [Test] public async Task The_first_account_created_alongside_a_seeded_service_user_still_becomes_an_admin() { await ServiceUser.EnsureSeededAsync(_db.Context, "a-service-key", NullLogger.Instance); var user = await _accounts.RegisterAsync(new RegisterRequest("first@novelly.test", "Password123!", "First Writer")); Assert.That(user.GlobalRole, Is.EqualTo(GlobalRole.Admin)); } [Test] public async Task Accounts_created_after_the_first_are_reviewers() { await _accounts.RegisterAsync(new RegisterRequest("first@novelly.test", "Password123!", "First Writer")); var second = await _accounts.RegisterAsync(new RegisterRequest("second@novelly.test", "Password123!", "Second Writer")); Assert.That(second.GlobalRole, Is.EqualTo(GlobalRole.Reviewer)); } [Test] public async Task Registering_with_an_email_already_in_use_is_rejected() { await _accounts.RegisterAsync(new RegisterRequest("taken@novelly.test", "Password123!", "First Writer")); Assert.That( () => _accounts.RegisterAsync(new RegisterRequest("taken@novelly.test", "Password123!", "Someone Else")), Throws.TypeOf()); } [Test] public async Task Signing_in_with_the_wrong_password_is_rejected() { await _accounts.RegisterAsync(new RegisterRequest("first@novelly.test", "Password123!", "First Writer")); var result = await _accounts.LoginAsync(new LoginRequest("first@novelly.test", "WrongPassword!")); Assert.That(result, Is.Null); } [Test] public async Task Signing_in_with_the_right_password_succeeds() { await _accounts.RegisterAsync(new RegisterRequest("first@novelly.test", "Password123!", "First Writer")); var result = await _accounts.LoginAsync(new LoginRequest("first@novelly.test", "Password123!")); Assert.That(result?.Email, Is.EqualTo("first@novelly.test")); } }