using System.Net; using System.Net.Http.Headers; using System.Text; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Xunit; using System.Net.Http.Json; namespace CDN.Tests; public class FileUploadTests : IClassFixture> { private readonly WebApplicationFactory _factory; public FileUploadTests(WebApplicationFactory factory) { _factory = factory; } private string GenerateToken() { var key = Encoding.UTF8.GetBytes("this_is_a_very_secret_key_for_development_purposes"); var securityKey = new SymmetricSecurityKey(key); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, "testuser"), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var token = new JwtSecurityToken( issuer: "MassTechCDN", audience: "MassTechClients", claims: claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); } [Fact] public async Task Upload_Image_ReturnsSuccessAndUrl() { // Arrange var client = _factory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GenerateToken()); var content = new MultipartFormDataContent(); var fileContent = new ByteArrayContent(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, // Magic 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, // IHDR 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, // Width 1, Height 1 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, // Bit depth, Color type 0x89, 0x00, 0x00, 0x00, 0x0A, 0x49, 0x44, 0x41, // IDAT chunk length 0x54, 0x78, 0x9C, 0x63, 0x00, 0x01, 0x00, 0x00, // IDAT data 0x05, 0x00, 0x01, 0x0D, 0x0A, 0x2D, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, // IEND 0x42, 0x60, 0x82 }); fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png"); content.Add(fileContent, "file", "test.png"); // Act var response = await client.PostAsync("/api/files/upload?w=100&h=100", content); // Assert response.EnsureSuccessStatusCode(); var responseString = await response.Content.ReadAsStringAsync(); Assert.Contains("File uploaded successfully", responseString); } [Fact] public async Task Upload_NoFile_ReturnsBadRequest() { // Arrange var client = _factory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GenerateToken()); var content = new MultipartFormDataContent(); // Empty // Act var response = await client.PostAsync("/api/files/upload", content); // Assert Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } [Fact] public async Task Delete_File_ReturnsSuccess() { // Arrange var client = _factory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GenerateToken()); // First upload a file to get a known filename var content = new MultipartFormDataContent(); var fileContent = new ByteArrayContent(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, // Magic 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, // IHDR 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, // Width 1, Height 1 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, // Bit depth, Color type 0x89, 0x00, 0x00, 0x00, 0x0A, 0x49, 0x44, 0x41, // IDAT chunk length 0x54, 0x78, 0x9C, 0x63, 0x00, 0x01, 0x00, 0x00, // IDAT data 0x05, 0x00, 0x01, 0x0D, 0x0A, 0x2D, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, // IEND 0x42, 0x60, 0x82 }); fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png"); content.Add(fileContent, "file", "todelete.png"); var uploadRes = await client.PostAsync("/api/files/upload", content); uploadRes.EnsureSuccessStatusCode(); var json = await uploadRes.Content.ReadFromJsonAsync(); var fileName = json.FileName; // This will likely be [guid].webp // Act var deleteRes = await client.DeleteAsync($"/api/files/{fileName}"); // Assert deleteRes.EnsureSuccessStatusCode(); } private class UploadResponse { public string FileName { get; set; } } }