test(postit): pin blogs scope on bearer, fix post-refactor tests
Two intertwined jobs here:
1. Diagnostic test for the production 401 we see when PostIt
talks to Yavsc.Blogs. The hypothesis this test isolates:
the access token sent on the wire is missing the 'blogs'
scope that Yavsc.Blogs' BlogScope policy requires (see
Yavsc.Blogs/Program.cs: RequireClaim(JwtClaimTypes.Scope,
"blogs")). The test fakes a single HttpMessageHandler,
captures the outbound bearer, decodes the JWT, and asserts
the 'scope' claim contains 'blogs'. It does not stand up a
server, an OIDC stub, or any network listener. Result: the
scope is present in the access_token we construct, so the
401 is not on the client side — most likely the IdP at
Yavsc.Org is not issuing 'blogs' as a recognised scope.
2. Mechanical fix of the three test files that broke during
the Settings model refactor (PostIt.Settings ->
PostIt.ViewModels.Settings; ApiUrl -> BusinessApiUrl;
Scopes/RedirectUri moved under Authentication;
DefaultDesktopRedirectUri is on AuthenticationSettings in
the global namespace). Also restored the BaseAddress
setup that BlogApiClient does in production in
LoginAndPersistAsync / the reloaded-client path of
YavscApiClientTests, so the two integration tests that
call CallAsync("posts") directly don't trip on
'request URI must be absolute or BaseAddress must be set'.
Test status: 45 / 45 passing in PostIt.Tests.
This commit is contained in:
parent
4a6609e2f1
commit
e9df13a477
6 changed files with 323 additions and 279 deletions
|
|
@ -27,7 +27,7 @@ public class SettingsLoadTests
|
|||
return; // nothing to assert: user file wins.
|
||||
}
|
||||
|
||||
var settings = new PostIt.Settings();
|
||||
var settings = new PostIt.ViewModels.Settings();
|
||||
settings.Load();
|
||||
|
||||
// The bundled postit-settings.json points at yavsc.pschneider.fr.
|
||||
|
|
@ -48,7 +48,7 @@ public class SettingsLoadTests
|
|||
[Fact]
|
||||
public async Task Concurrent_load_and_mutate_does_not_throw_or_corrupt_state()
|
||||
{
|
||||
var settings = new PostIt.Settings();
|
||||
var settings = new PostIt.ViewModels.Settings();
|
||||
|
||||
// First load pre-populates Authentication.Authority so the
|
||||
// early-return path in Load() runs (we don't want file I/O
|
||||
|
|
@ -58,9 +58,9 @@ public class SettingsLoadTests
|
|||
settings.Authentication = new AuthenticationSettings
|
||||
{
|
||||
Authority = "https://example.test/",
|
||||
ClientId = "postit-tests"
|
||||
ClientId = "postit-tests",
|
||||
Scopes = new[] { "openid" },
|
||||
};
|
||||
settings.Scopes = new[] { "openid" };
|
||||
// Load() takes the early-return path because Authority is
|
||||
// already populated; flips Loaded=true under the gate.
|
||||
settings.Load();
|
||||
|
|
@ -90,10 +90,10 @@ public class SettingsLoadTests
|
|||
{
|
||||
bool flip = ((workerId + i) & 1) == 0;
|
||||
settings.DarkMode = flip;
|
||||
settings.RedirectUri = flip
|
||||
? PostIt.Settings.DefaultDesktopRedirectUri
|
||||
: PostIt.Settings.DefaultLoopbackRedirectUri;
|
||||
settings.ApiUrl = flip
|
||||
settings.Authentication.RedirectUri = flip
|
||||
? global::AuthenticationSettings.DefaultDesktopRedirectUri
|
||||
: PostIt.ViewModels.Settings.DefaultLoopbackRedirectUri;
|
||||
settings.BusinessApiUrl = flip
|
||||
? "https://a.example.test/api/v1/"
|
||||
: "https://b.example.test/api/v1/";
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ public class SettingsLoadTests
|
|||
// invariants that the gate protects.
|
||||
Assert.True(settings.Loaded);
|
||||
Assert.NotNull(settings.Authentication);
|
||||
Assert.NotNull(settings.Scopes);
|
||||
Assert.NotNull(settings.Authentication.Scopes);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -131,7 +131,7 @@ public class SettingsLoadTests
|
|||
[Fact]
|
||||
public void Load_is_idempotent_under_concurrent_calls()
|
||||
{
|
||||
var settings = new PostIt.Settings
|
||||
var settings = new PostIt.ViewModels.Settings
|
||||
{
|
||||
Authentication = new AuthenticationSettings
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue