Files
fiscalos/tests/FiscalOS.API.Tests/Integration/Auth/LoginTests.cs
T

182 lines
5.2 KiB
C#

namespace FiscalOS.API.Tests.Integration.Auth;
public class LoginTests(TestApi testApi) : IntegrationTest(testApi)
{
private static readonly Uri LoginUri = new("/auth/login", UriKind.Relative);
[Theory]
[ClassData<LoginValidationTestCases>]
public async Task Login_WhenUserSubmitsInvalidRequest_ItShouldReturn400WithProblemDetails(LoginValidationTestCase tc)
{
using var request = HttpRequestBuilder.New()
.Post(LoginUri)
.WithBody(new
{
username = tc.Username,
password = tc.Password,
})
.Build();
var res = await Client.SendAsync(request, TestContext.Current.CancellationToken);
await res.Should().BeValidationProblemDetails(tc.ExpectedErrors);
}
[Fact]
public async Task Login_WhenUserDoesNotExist_ItShouldReturn401WithProblemDetails()
{
using var request = HttpRequestBuilder.New()
.Post(LoginUri)
.WithBody(new
{
username = "Test",
password = "@Password2",
})
.Build();
var res = await Client.SendAsync(request, TestContext.Current.CancellationToken);
await res.Should().BeProblemDetails(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task Login_WhenUserExistsButPasswordIsIncorrect_ItShouldReturn401WithProblemDetails()
{
await Api.ExecuteAsync(static async (context, ct, sp) =>
{
var passwordHasher = sp.GetRequiredService<IPasswordHasher>();
var encryptor = sp.GetRequiredService<IEncryptor>();
var userEncryptionKey = await encryptor.GenerateEncryptedKeyAsync(ct);
context.Add(User.From("Stevan", passwordHasher.Hash("@Password1"), userEncryptionKey));
await context.SaveChangesAsync(ct);
}, TestContext.Current.CancellationToken);
using var request = HttpRequestBuilder.New()
.Post(LoginUri)
.WithBody(new
{
username = "Stevan",
password = "@Password2",
})
.Build();
var res = await Client.SendAsync(request, TestContext.Current.CancellationToken);
await res.Should().BeProblemDetails(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task Login_WhenUserExistsAndPasswordIsCorrect_ItShouldReturn200WithJwtTokenAndSetRefreshCookie()
{
await Api.ExecuteAsync(static async (context, ct, sp) =>
{
var passwordHasher = sp.GetRequiredService<IPasswordHasher>();
var encryptor = sp.GetRequiredService<IEncryptor>();
var userEncryptionKey = await encryptor.GenerateEncryptedKeyAsync(ct);
context.Add(User.From("Stevan", passwordHasher.Hash("@Password1"), userEncryptionKey));
await context.SaveChangesAsync(ct);
}, TestContext.Current.CancellationToken);
using var request = HttpRequestBuilder.New()
.Post(LoginUri)
.WithBody(new
{
username = "Stevan",
password = "@Password1",
})
.Build();
var res = await Client.SendAsync(request, TestContext.Current.CancellationToken);
res.Should().HaveSetCookieHeader("fiscalos_refresh_cookie");
await res.Should().BeJsonContentOfType<API.Auth.Login.Response>(HttpStatusCode.OK);
}
}
public class LoginValidationTestCases : TheoryData<LoginValidationTestCase>
{
public LoginValidationTestCases()
{
Add(new LoginValidationTestCase(
"No username or password",
string.Empty,
string.Empty,
new SerializableDictionary<string, string[]>()
{
["Username"] = ["The Username field is required."],
["Password"] = ["The Password field is required."]
}
));
Add(new LoginValidationTestCase(
"No username",
string.Empty,
"@Password1",
new SerializableDictionary<string, string[]>()
{
["Username"] = ["The Username field is required."],
}
));
Add(new LoginValidationTestCase(
"No password",
"Stevan",
string.Empty,
new SerializableDictionary<string, string[]>()
{
["Password"] = ["The Password field is required."]
}
));
}
}
public record LoginValidationTestCase : IXunitSerializable
{
public string Name { get; private set; } = string.Empty;
public string Username { get; private set; } = string.Empty;
public string Password { get; private set; } = string.Empty;
public SerializableDictionary<string, string[]> ExpectedErrors { get; private set; } = [];
public override string ToString()
{
return Name;
}
public LoginValidationTestCase()
{
}
public LoginValidationTestCase(
string name,
string username,
string password,
SerializableDictionary<string, string[]> expectedErrors
)
{
Name = name;
Username = username;
Password = password;
ExpectedErrors = expectedErrors;
}
public void Deserialize(IXunitSerializationInfo info)
{
Name = info.GetValue<string>(nameof(Name)) ?? string.Empty;
Username = info.GetValue<string>(nameof(Username)) ?? string.Empty;
Password = info.GetValue<string>(nameof(Password)) ?? string.Empty;
ExpectedErrors = info.GetValue<SerializableDictionary<string, string[]>>(nameof(ExpectedErrors)) ?? [];
}
public void Serialize(IXunitSerializationInfo info)
{
info.AddValue(nameof(Name), Name);
info.AddValue(nameof(Username), Username);
info.AddValue(nameof(Password), Password);
info.AddValue(nameof(ExpectedErrors), ExpectedErrors);
}
}