The feed doesn't say "Empty" before its persona is known
On opening, the feed showed "Empty" until the session had been read and a persona chosen, then loaded: a flash of a wrong answer on every start (and the end-to-end sign-in took it for a loaded feed). CascadingState says once the session has been read (IsSessionLoaded), and until then a feed with no persona yet is loading; a login without any persona still gets its empty feed. The persona-switch test waits for the sibling's home read with another token than the first persona's, instead of any home read after the switch was asked for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
18331531b8
commit
47ff60f57b
3 files changed
+24
-7
No files matched your search
@@ -27,6 +27,8 @@
|
|||||||
public PublicCacheData PublicCacheData { get; private set; } = new();
|
public PublicCacheData PublicCacheData { get; private set; } = new();
|
||||||
/// <summary>Whether a root is signed in (its JWT is still valid).</summary>
|
/// <summary>Whether a root is signed in (its JWT is still valid).</summary>
|
||||||
public bool IsSignedIn { get; private set; }
|
public bool IsSignedIn { get; private set; }
|
||||||
|
/// <summary>The session has been read once: from then on a null PersonaId means the login has no persona, not "not yet".</summary>
|
||||||
|
public bool IsSessionLoaded { get; private set; }
|
||||||
/// <summary>The root's login name, shown to its owner only.</summary>
|
/// <summary>The root's login name, shown to its owner only.</summary>
|
||||||
public string RootUserName { get; private set; }
|
public string RootUserName { get; private set; }
|
||||||
/// <summary>The root's personas.</summary>
|
/// <summary>The root's personas.</summary>
|
||||||
@@ -93,6 +95,7 @@
|
|||||||
if (!IsSignedIn)
|
if (!IsSignedIn)
|
||||||
{
|
{
|
||||||
ClearSession();
|
ClearSession();
|
||||||
|
IsSessionLoaded = true;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -105,10 +108,12 @@
|
|||||||
{
|
{
|
||||||
PersonaId = null;
|
PersonaId = null;
|
||||||
Persona = null;
|
Persona = null;
|
||||||
|
IsSessionLoaded = true;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IsSessionLoaded = true;
|
||||||
await SwitchPersona(personaId, cancellationToken);
|
await SwitchPersona(personaId, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-3
@@ -155,6 +155,7 @@
|
|||||||
(double Latitude, double Longitude)? position;
|
(double Latitude, double Longitude)? position;
|
||||||
string positionError;
|
string positionError;
|
||||||
string loadedPersonaId;
|
string loadedPersonaId;
|
||||||
|
bool waitingForPersona;
|
||||||
FeedQuery lastQuery;
|
FeedQuery lastQuery;
|
||||||
DateTime? lastPollAt;
|
DateTime? lastPollAt;
|
||||||
TimeSpan? lastLoadTook;
|
TimeSpan? lastLoadTook;
|
||||||
@@ -183,9 +184,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (while the session is still being read the persona isn't known yet: the feed is loading, not empty)
|
||||||
if (CascadingState.PersonaId is null)
|
if (CascadingState.PersonaId is null)
|
||||||
{
|
{
|
||||||
IsLoading = false;
|
waitingForPersona = !CascadingState.IsSessionLoaded;
|
||||||
|
IsLoading = waitingForPersona;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,11 +222,19 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The persona changed (NavMenu's switcher): everything on the page belongs to the old one.
|
// The persona is known (the session was read after the page opened) or changed (NavMenu's switcher): everything on the
|
||||||
|
// page belongs to it.
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
if (CascadingState.PersonaId is null || CascadingState.PersonaId == loadedPersonaId || IsLoading && loadedPersonaId is null)
|
if (waitingForPersona && CascadingState.IsSessionLoaded && CascadingState.PersonaId is null)
|
||||||
|
{
|
||||||
|
waitingForPersona = false;
|
||||||
|
IsLoading = false;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
if (CascadingState.PersonaId is null || CascadingState.PersonaId == loadedPersonaId || IsLoading && loadedPersonaId is null && !waitingForPersona)
|
||||||
|
return;
|
||||||
|
waitingForPersona = false;
|
||||||
await Reload();
|
await Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,12 @@ namespace decePubClient.E2E.Login
|
|||||||
await session.Page.Locator("nav [title='Switch persona']").First.ClickAsync();
|
await session.Page.Locator("nav [title='Switch persona']").First.ClickAsync();
|
||||||
await session.Page.Locator("nav").GetByRole(AriaRole.Button).Filter(new() { HasText = sibling.Name ?? sibling.UserName }).First.ClickAsync();
|
await session.Page.Locator("nav").GetByRole(AriaRole.Button).Filter(new() { HasText = sibling.Name ?? sibling.UserName }).First.ClickAsync();
|
||||||
|
|
||||||
|
// the sibling's home, read with another token than the first persona's (whose own home may still be loading when the
|
||||||
|
// switch is asked for)
|
||||||
|
string FirstToken() => session.ApiCalls.FirstOrDefault(c => new Uri(c.Url).AbsolutePath.StartsWith("/api/") && c.Authorization is not null).Authorization;
|
||||||
Assert.True(await Pasture.Eventually(() => Task.FromResult(session.ApiCalls.Skip(before)
|
Assert.True(await Pasture.Eventually(() => Task.FromResult(session.ApiCalls.Skip(before)
|
||||||
.Any(c => new Uri(c.Url).AbsolutePath == "/api/v1/timelines/home")), 20), "the sibling's home was never read");
|
.Any(c => new Uri(c.Url).AbsolutePath == "/api/v1/timelines/home" && c.Authorization is not null && c.Authorization != FirstToken())), 20),
|
||||||
var tokens = session.ApiCalls.Where(c => new Uri(c.Url).AbsolutePath.StartsWith("/api/") && c.Authorization is not null)
|
"the sibling's home was never read with its own token");
|
||||||
.Select(c => c.Authorization).Distinct().ToList();
|
|
||||||
Assert.True(tokens.Count >= 2, "both personas' requests went out with one token");
|
|
||||||
await session.AssertGuards();
|
await session.AssertGuards();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user