Files
PnvPanel/backend/tests/PnvPanel.IntegrationTests/Auth/AuthFlowTests.cs
T
Leonid Pershin df137ca5a7
CI / Backend (build + test) (push) Successful in 1m18s
CI / Frontend (lint + typecheck + build) (push) Successful in 31s
Refactor project files for improved readability and structure
- Cleaned up whitespace in Directory.Build.props and Directory.Packages.props for consistency.
- Reformatted project file references in PnvPanel.Api.csproj for better clarity.
- Enhanced code readability in various endpoint files by adjusting line breaks and indentation.
- Standardized method signatures and improved formatting in ResultExtensions and multiple endpoint classes for better maintainability.
2026-07-14 07:24:13 +03:00

113 lines
4.0 KiB
C#

using System.Net;
using System.Net.Http.Json;
using PnvPanel.IntegrationTests.TestSupport;
using Xunit;
namespace PnvPanel.IntegrationTests.Auth;
[Collection(IntegrationTestCollection.Name)]
public class AuthFlowTests(PnvPanelWebApplicationFactory factory)
{
private sealed record RegisterResponse(Guid Id, string UserName);
private sealed record CurrentUserResponse(
Guid Id,
string UserName,
string Role,
bool IsActivated,
bool TelegramLinked
);
private sealed record LoginResponse(
string AccessToken,
DateTimeOffset ExpiresAt,
CurrentUserResponse User
);
[Fact]
public async Task RegisterLoginMeRefreshLogout_FullFlow_Succeeds()
{
using var client = factory.CreateClient();
var userName = $"alice_{Guid.NewGuid():N}"[..20];
const string password = "P@ssw0rd123";
var registerResponse = await client.PostJsonAsync(
"/api/auth/register",
new { userName, password }
);
Assert.Equal(HttpStatusCode.OK, registerResponse.StatusCode);
var registered = await registerResponse.ReadAsAsync<RegisterResponse>();
Assert.NotNull(registered);
Assert.Equal(userName, registered!.UserName);
var loginResponse = await client.PostJsonAsync(
"/api/auth/login",
new { userName, password }
);
Assert.Equal(HttpStatusCode.OK, loginResponse.StatusCode);
var login = await loginResponse.ReadAsAsync<LoginResponse>();
Assert.NotNull(login);
Assert.False(login!.User.IsActivated);
Assert.False(login.User.TelegramLinked);
Assert.Equal("user", login.User.Role);
client.UseBearerToken(login.AccessToken);
var meResponse = await client.GetAsync("/api/auth/me");
Assert.Equal(HttpStatusCode.OK, meResponse.StatusCode);
var me = await meResponse.ReadAsAsync<CurrentUserResponse>();
Assert.Equal(userName, me!.UserName);
var refreshResponse = await client.PostAsync("/api/auth/refresh", content: null);
Assert.Equal(HttpStatusCode.OK, refreshResponse.StatusCode);
var refreshed = await refreshResponse.ReadAsAsync<LoginResponse>();
Assert.NotNull(refreshed);
Assert.NotEqual(login.AccessToken, refreshed!.AccessToken);
var logoutResponse = await client.PostAsync("/api/auth/logout", content: null);
Assert.Equal(HttpStatusCode.NoContent, logoutResponse.StatusCode);
// Использованный refresh-токен отозван при logout — повторный refresh должен провалиться.
var refreshAfterLogout = await client.PostAsync("/api/auth/refresh", content: null);
Assert.Equal(HttpStatusCode.Unauthorized, refreshAfterLogout.StatusCode);
}
[Fact]
public async Task Login_WithWrongPassword_ReturnsUnauthorized()
{
using var client = factory.CreateClient();
var userName = $"bob_{Guid.NewGuid():N}"[..20];
await client.PostJsonAsync(
"/api/auth/register",
new { userName, password = "CorrectPassword123" }
);
var loginResponse = await client.PostJsonAsync(
"/api/auth/login",
new { userName, password = "WrongPassword123" }
);
Assert.Equal(HttpStatusCode.Unauthorized, loginResponse.StatusCode);
}
[Fact]
public async Task Register_WithDuplicateUserName_ReturnsConflict()
{
using var client = factory.CreateClient();
var userName = $"carol_{Guid.NewGuid():N}"[..20];
var first = await client.PostJsonAsync(
"/api/auth/register",
new { userName, password = "P@ssw0rd123" }
);
Assert.Equal(HttpStatusCode.OK, first.StatusCode);
var second = await client.PostJsonAsync(
"/api/auth/register",
new { userName, password = "AnotherPass123!" }
);
Assert.Equal(HttpStatusCode.Conflict, second.StatusCode);
}
}