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