refacto + test fixes
Some checks failed
Dotnet build and test / build (pull_request) Failing after 5m11s
Some checks failed
Dotnet build and test / build (pull_request) Failing after 5m11s
This commit is contained in:
parent
e56bdd4329
commit
1c2e1760b0
8 changed files with 60 additions and 32 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -42,5 +42,6 @@
|
|||
"copilotcli/gpt-5.3-codex"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dotnet.defaultSolution": "yavsc.sln"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,8 @@ public sealed class BlogAclApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
BlogPostId = _fixture.PostId
|
||||
};
|
||||
|
||||
var response = await http.PostAsJsonAsync(BlogAclUrl(), payload,
|
||||
var response = await http.PostAsJsonAsync(
|
||||
BlogAclUrl(), payload,
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,16 @@ using Yavsc.Tests.Shared;
|
|||
namespace Yavsc.Blogs.Tests;
|
||||
|
||||
[Collection("JwtClaimMapping")]
|
||||
public sealed class BlogApiMappedClaimsTests : IClassFixture<MappedClaimsBlogsWebServerFixture>
|
||||
public sealed class BlogApiMappedClaimsTests :
|
||||
IClassFixture<MappedClaimsBlogsWebServerFixture>,
|
||||
IBackendFixture
|
||||
{
|
||||
private readonly MappedClaimsBlogsWebServerFixture _fixture;
|
||||
|
||||
public IReadOnlyList<string> Addresses => throw new NotImplementedException();
|
||||
|
||||
public IServiceProvider Services => throw new NotImplementedException();
|
||||
|
||||
public BlogApiMappedClaimsTests(MappedClaimsBlogsWebServerFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
|
|
@ -79,7 +85,7 @@ public sealed class BlogApiMappedClaimsTests : IClassFixture<MappedClaimsBlogsWe
|
|||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var response = await http.PostAsJsonAsync("/api/v1/blog", draft, TestContext.Current.CancellationToken);
|
||||
var response = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft, TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
|
||||
|
||||
var created = await response.Content.ReadFromJsonAsync<BlogPost>(TestContext.Current.CancellationToken);
|
||||
|
|
@ -93,7 +99,7 @@ public sealed class BlogApiMappedClaimsTests : IClassFixture<MappedClaimsBlogsWe
|
|||
ResetDatabase();
|
||||
using var http = NewClient(subject: "mapped-owner");
|
||||
|
||||
var createdResponse = await http.PostAsJsonAsync("/api/v1/blog", new BlogPost
|
||||
var createdResponse = await http.PostAsJsonAsync(_fixture.BlogUrl(), new BlogPost
|
||||
{
|
||||
Id = 0,
|
||||
Title = "Billet à modifier",
|
||||
|
|
@ -126,7 +132,7 @@ public sealed class BlogApiMappedClaimsTests : IClassFixture<MappedClaimsBlogsWe
|
|||
ResetDatabase();
|
||||
using var ownerHttp = NewClient(subject: "mapped-owner");
|
||||
|
||||
var createdResponse = await ownerHttp.PostAsJsonAsync("/api/v1/blog", new BlogPost
|
||||
var createdResponse = await ownerHttp.PostAsJsonAsync(_fixture.BlogUrl(), new BlogPost
|
||||
{
|
||||
Id = 0,
|
||||
Title = "Billet protégé",
|
||||
|
|
|
|||
|
|
@ -46,15 +46,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
_fixture.SeedUser("tester");
|
||||
}
|
||||
|
||||
/// <summary>The fixture's <c>WebApplication</c> is bound to
|
||||
/// <c>https://localhost:<random></c> via
|
||||
/// <see cref="WebHostFixture.Addresses"/>. We pick the first
|
||||
/// https URL and append the controller route
|
||||
/// (<c>/api/v1/blog</c>, matching the production
|
||||
/// <c>[Route(APIPrefix + "/blog")]</c>).</summary>
|
||||
private string BlogsUrl =>
|
||||
_fixture.Addresses.First(a => a.StartsWith("https://")) + "/api/v1/blog";
|
||||
|
||||
|
||||
/// <summary>Build an authenticated client: a real
|
||||
/// <c>Authorization: Bearer <jwt></c> header where the JWT
|
||||
/// is signed by <see cref="TestTokenIssuer"/> and carries
|
||||
|
|
@ -101,7 +93,8 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
_fixture.ResetDatabase();
|
||||
using var http = NewClient();
|
||||
|
||||
var response = await http.GetAsync("/api/v1/blog",
|
||||
var response = await http.GetAsync(
|
||||
_fixture.BlogUrl(),
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
|
@ -134,7 +127,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var postResponse = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var postResponse = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.Created, postResponse.StatusCode);
|
||||
|
||||
|
|
@ -147,7 +140,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
Assert.Equal(draft.Title, created.Title);
|
||||
|
||||
// The list should now contain exactly one entry.
|
||||
var listResponse = await http.GetAsync("/api/v1/blog",
|
||||
var listResponse = await http.GetAsync(_fixture.BlogUrl(),
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
|
||||
|
||||
|
|
@ -175,7 +168,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var postResponse = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var postResponse = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.Created, postResponse.StatusCode);
|
||||
|
||||
|
|
@ -185,7 +178,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
Assert.NotNull(created);
|
||||
Assert.Equal("tester", created!.AuthorId);
|
||||
|
||||
var listResponse = await http.GetAsync("/api/v1/blog",
|
||||
var listResponse = await http.GetAsync(_fixture.BlogUrl(),
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
|
||||
|
||||
|
|
@ -213,7 +206,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var postResponse = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var postResponse = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.Created, postResponse.StatusCode);
|
||||
|
||||
|
|
@ -262,7 +255,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
// the framework returns 401. This is the proof that the
|
||||
// production policy is wired in the test host and not
|
||||
// short-circuited by a test-only auth bypass.
|
||||
var response = await http.GetAsync("/api/v1/blog",
|
||||
var response = await http.GetAsync(_fixture.BlogUrl(),
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
|
||||
}
|
||||
|
|
@ -290,7 +283,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateCreated = DateTime.UtcNow,
|
||||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
var postResponse = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var postResponse = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.Created, postResponse.StatusCode);
|
||||
|
||||
|
|
@ -309,13 +302,13 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateCreated = created.DateCreated,
|
||||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
var putResponse = await http.PutAsJsonAsync($"/api/v1/blog/{created.Id}",
|
||||
var putResponse = await http.PutAsJsonAsync(_fixture.BlogUrl()+$"/{created.Id}",
|
||||
update,
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.NoContent, putResponse.StatusCode);
|
||||
|
||||
// The list should now reflect the new title.
|
||||
var listResponse = await http.GetAsync("/api/v1/blog",
|
||||
var listResponse = await http.GetAsync(_fixture.BlogUrl(),
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
|
||||
using var doc = JsonDocument.Parse(
|
||||
|
|
@ -343,19 +336,19 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateCreated = DateTime.UtcNow,
|
||||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
var postResponse = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var postResponse = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
var created = (await postResponse.Content.ReadFromJsonAsync<BlogPost>(
|
||||
TestContext.Current.CancellationToken
|
||||
))!;
|
||||
|
||||
var deleteResponse = await http.DeleteAsync($"/api/v1/blog/{created.Id}",
|
||||
var deleteResponse = await http.DeleteAsync(_fixture.BlogUrl()+$"/{created.Id}",
|
||||
TestContext.Current.CancellationToken
|
||||
);
|
||||
Assert.Equal(HttpStatusCode.OK, deleteResponse.StatusCode);
|
||||
|
||||
// The list should now be empty.
|
||||
var listResponse = await http.GetAsync("/api/v1/blog",
|
||||
var listResponse = await http.GetAsync(_fixture.BlogUrl(),
|
||||
TestContext.Current.CancellationToken);
|
||||
String response = await listResponse.Content.ReadAsStringAsync(
|
||||
TestContext.Current.CancellationToken
|
||||
|
|
@ -398,7 +391,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var response = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var response = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
// Dump the body on failure so the test name + the response
|
||||
|
|
@ -443,7 +436,7 @@ public sealed class BlogApiTests : IClassFixture<BlogsWebServerFixture>
|
|||
DateModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var response = await http.PostAsJsonAsync("/api/v1/blog", draft,
|
||||
var response = await http.PostAsJsonAsync(_fixture.BlogUrl(), draft,
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.BadRequest)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using Yavsc.Models.Blog;
|
|||
using Yavsc.Models.Relationship;
|
||||
using Yavsc.Services;
|
||||
using Yavsc.Tests.Shared;
|
||||
|
||||
using static Yavsc.Constants;
|
||||
namespace Yavsc.Blogs.Tests;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -415,4 +415,5 @@ public sealed class BlogsWebServerFixture : WebHostFixture
|
|||
db.SaveChanges();
|
||||
return post.Id;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
11
src/Yavsc.Blogs.Tests/Fixtures/BlogHelpers.cs
Normal file
11
src/Yavsc.Blogs.Tests/Fixtures/BlogHelpers.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
namespace Yavsc.Blogs.Tests.Fixtures;
|
||||
|
||||
|
||||
public static class BlogHelpers
|
||||
{
|
||||
public static string BlogUrl(this IBackendFixture fixture)
|
||||
=> $"{fixture.Addresses.First(a => a.StartsWith("https://"))}/{Constants.APIPrefix}/{Constants.BlogSpotPath}";
|
||||
|
||||
public static string BlogAclUrl(this IBackendFixture fixture)
|
||||
=> $"{fixture.Addresses.First(a => a.StartsWith("https://"))}/{Constants.APIPrefix}/{Constants.BlogAclPath}";
|
||||
}
|
||||
15
src/Yavsc.Blogs.Tests/Fixtures/IBackendFixture.cs
Normal file
15
src/Yavsc.Blogs.Tests/Fixtures/IBackendFixture.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
using Yavsc.Blogs.Tests;
|
||||
|
||||
public interface IBackendFixture
|
||||
{
|
||||
/// <summary>
|
||||
/// The addresses the fixture bound to.
|
||||
/// </summary>
|
||||
IReadOnlyList<string> Addresses { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The service provider for the fixture host.
|
||||
/// </summary>
|
||||
IServiceProvider Services { get; }
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
namespace Yavsc.Blogs;
|
||||
|
||||
public static class Constants
|
||||
public static class BlogConstants
|
||||
{
|
||||
public const string AdminRole = "Admin";
|
||||
public const string ModeratorRole = "Moderator";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue