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(); 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(); 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(); 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(); 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); } }