Post Files

This commit is contained in:
Paul Schneider 2026-09-07 15:41:33 +01:00
commit 41d8fad8c3
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
21 changed files with 659 additions and 34 deletions

View file

@ -1,7 +1,9 @@
using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Security.Claims;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Yavsc.Models;
using Yavsc.Models.Blog;
using Yavsc.Server.Helpers;
@ -88,6 +90,13 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
};
}
private int CountAttachmentsForPost(long postId)
{
using var scope = _fixture.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
return db.BlogAttachedFiles.Count(a => a.PostId == postId);
}
[Fact]
public async Task GetBlogs_returns_200_with_empty_list_when_no_posts()
{
@ -321,6 +330,126 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
Assert.Equal("Après", doc.RootElement[0].GetProperty("title").GetString());
}
[Fact]
public async Task PutBlog_multipart_with_blog_and_file_returns_204_and_persists_attachment()
{
ResetAndSeedDefaultUser();
using var http = NewClient(subject: "tester");
var previousRoot = AbstractFileSystemHelpers.UserFilesDirName;
var tempRoot = Path.Combine(Path.GetTempPath(), "yavsc-blogs-tests-files-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(tempRoot);
AbstractFileSystemHelpers.UserFilesDirName = tempRoot;
try
{
var draft = new BlogPost
{
Id = 0,
Title = "Initial",
AuthorId = "tester",
Article = "Contenu initial.",
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow
};
var postResponse = await http.PostAsJsonAsync(
_fixture.BlogSpotUrl(),
draft,
TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.Created, postResponse.StatusCode);
var created = (await postResponse.Content.ReadFromJsonAsync<BlogPost>(
TestContext.Current.CancellationToken))!;
var update = new BlogPost
{
Id = created.Id,
Title = "Mis a jour via multipart",
AuthorId = created.AuthorId,
Article = "Contenu mis a jour.",
DateCreated = created.DateCreated,
DateModified = DateTime.UtcNow
};
var form = new MultipartFormDataContent();
form.Add(new StringContent(JsonSerializer.Serialize(update)), "blog");
var fileBytes = System.Text.Encoding.UTF8.GetBytes("payload test");
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
form.Add(fileContent, "file", "note.txt");
using var request = new HttpRequestMessage(
HttpMethod.Put,
_fixture.BlogSpotUrl() + $"/{created.Id}")
{
Content = form
};
var putResponse = await http.SendAsync(request, TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.NoContent, putResponse.StatusCode);
var detailsResponse = await http.GetAsync(
_fixture.BlogSpotUrl() + $"/{created.Id}",
TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, detailsResponse.StatusCode);
using var detailsDoc = JsonDocument.Parse(
await detailsResponse.Content.ReadAsStringAsync(TestContext.Current.CancellationToken));
Assert.Equal("Mis a jour via multipart", detailsDoc.RootElement.GetProperty("title").GetString());
Assert.True(CountAttachmentsForPost(created.Id) >= 1);
}
finally
{
AbstractFileSystemHelpers.UserFilesDirName = previousRoot;
try { Directory.Delete(tempRoot, recursive: true); } catch { }
}
}
[Fact]
public async Task PutBlog_multipart_without_blog_field_returns_400()
{
ResetAndSeedDefaultUser();
using var http = NewClient(subject: "tester");
var draft = new BlogPost
{
Id = 0,
Title = "Initial",
AuthorId = "tester",
Article = "Contenu initial.",
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow
};
var postResponse = await http.PostAsJsonAsync(
_fixture.BlogSpotUrl(),
draft,
TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.Created, postResponse.StatusCode);
var created = (await postResponse.Content.ReadFromJsonAsync<BlogPost>(
TestContext.Current.CancellationToken))!;
var form = new MultipartFormDataContent();
var fileBytes = System.Text.Encoding.UTF8.GetBytes("payload test");
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
form.Add(fileContent, "file", "note.txt");
using var request = new HttpRequestMessage(
HttpMethod.Put,
_fixture.BlogSpotUrl() + $"/{created.Id}")
{
Content = form
};
var putResponse = await http.SendAsync(request, TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.BadRequest, putResponse.StatusCode);
}
[Fact]
public async Task DeleteBlog_removes_a_post_and_Get_returns_an_empty_list()
{