using System.Net;
using System.Net.Http.Headers;
using PnvPanel.IntegrationTests.TestSupport;
using Xunit;
using static PnvPanel.IntegrationTests.TestSupport.AuthTestHelper;
namespace PnvPanel.IntegrationTests.Media;
[Collection(IntegrationTestCollection.Name)]
public class MediaImageFlowTests(PnvPanelWebApplicationFactory factory)
{
private sealed record MediaImageResponse(
Guid Id,
string FileName,
string ContentType,
long SizeBytes
);
/// Минимальный валидный PNG (1×1) — не важно содержимое, важен путь загрузка → отдача.
private static readonly byte[] PngBytes = Convert.FromBase64String(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
);
private static MultipartFormDataContent ImageContent(
byte[] bytes,
string contentType,
string fileName
)
{
var file = new ByteArrayContent(bytes);
file.Headers.ContentType = new MediaTypeHeaderValue(contentType);
return new MultipartFormDataContent { { file, "file", fileName } };
}
[Fact]
public async Task AdminUploadsImage_ThenAnyoneCanFetchItWithoutAuth()
{
using var adminClient = factory.CreateClient();
adminClient.UseBearerToken(await LoginAsAdminAsync(adminClient));
var uploadResponse = await adminClient.PostAsync(
"/api/admin/media/images",
ImageContent(PngBytes, "image/png", "shot.png")
);
Assert.Equal(HttpStatusCode.OK, uploadResponse.StatusCode);
var image = await uploadResponse.ReadAsAsync();
Assert.NotNull(image);
Assert.Equal("shot.png", image!.FileName);
// Анонимный клиент: markdown-картинку грузит обычный
без Authorization.
using var anonymousClient = factory.CreateClient();
var getResponse = await anonymousClient.GetAsync($"/api/media/images/{image.Id}");
Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode);
Assert.Equal("image/png", getResponse.Content.Headers.ContentType?.MediaType);
Assert.Equal(PngBytes, await getResponse.Content.ReadAsByteArrayAsync());
}
[Fact]
public async Task Upload_WhenNotAdmin_ReturnsForbidden()
{
using var userClient = factory.CreateClient();
var userName = $"mia_{Guid.NewGuid():N}"[..20];
var (_, token) = await RegisterAndLoginAsync(userClient, userName, "P@ssw0rd123");
userClient.UseBearerToken(token);
var response = await userClient.PostAsync(
"/api/admin/media/images",
ImageContent(PngBytes, "image/png", "shot.png")
);
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
}
[Fact]
public async Task Upload_WithUnsupportedType_ReturnsBadRequest()
{
using var adminClient = factory.CreateClient();
adminClient.UseBearerToken(await LoginAsAdminAsync(adminClient));
var response = await adminClient.PostAsync(
"/api/admin/media/images",
ImageContent(""u8.ToArray(), "image/svg+xml", "x.svg")
);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Fact]
public async Task GetImage_WhenUnknownId_ReturnsNotFound()
{
using var anonymousClient = factory.CreateClient();
var response = await anonymousClient.GetAsync($"/api/media/images/{Guid.NewGuid()}");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
}