Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions LongevityWorldCup.Tests/LongevityWorldCup.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.9" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
<PackageReference Include="Microsoft.Playwright" Version="1.60.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
<PackageReference Include="Microsoft.Playwright" Version="1.61.0" />
<PackageReference Include="coverlet.msbuild" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
14 changes: 7 additions & 7 deletions LongevityWorldCup.Tests/SelectedAthleteBootstrapPageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ public async Task SelectedAthleteRecovery_UsesSafeStorageCleanup(string path, st
if (path == "/dashboard")
{
var flow = await client.GetStringAsync("/js/play-athlete-flow.js");
var recoveryStart = flow.IndexOf("function readRequiredSelectedAthlete()", StringComparison.Ordinal);
var redirectIndex = flow.IndexOf("window.location.replace(\"/select-athlete\");", recoveryStart, StringComparison.Ordinal);
var recoveryStart = flow.IndexOf("function getStoredSelectedAthlete()", StringComparison.Ordinal);
var recoveryEnd = flow.IndexOf("function isValidSelectedAthlete(value)", recoveryStart, StringComparison.Ordinal);

Assert.Contains("flow.readRequiredSelectedAthlete();", html);
Assert.Contains("flow.getStoredSelectedAthlete();", html);
Assert.True(recoveryStart >= 0);
Assert.True(redirectIndex > recoveryStart);
Assert.True(recoveryEnd > recoveryStart);

var recoveryBody = flow[recoveryStart..redirectIndex];
var recoveryBody = flow[recoveryStart..recoveryEnd];

Assert.Contains("function removeSessionItem(key)", flow);
Assert.Contains("removeSessionItem(\"selectedAthlete\");", recoveryBody);
Expand Down Expand Up @@ -87,7 +87,7 @@ public async Task SelectedAthleteValidation_RejectsArrays(string path)

if (path == "/dashboard")
{
Assert.Contains("flow.readRequiredSelectedAthlete();", html);
Assert.Contains("flow.getStoredSelectedAthlete();", html);
}
else if (isBioagePage)
{
Expand Down Expand Up @@ -119,7 +119,7 @@ public async Task SelectedAthleteValidation_RejectsBlankNames(string path)

if (path == "/dashboard")
{
Assert.Contains("flow.readRequiredSelectedAthlete();", html);
Assert.Contains("flow.getStoredSelectedAthlete();", html);
}
else if (isBioagePage)
{
Expand Down
4 changes: 2 additions & 2 deletions LongevityWorldCup.Website/LongevityWorldCup.Website.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
<PackageReference Include="Google.Apis.Auth" Version="1.75.0" />
<PackageReference Include="MailKit" Version="4.17.0" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="10.0.9" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.18.1" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.18.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
</ItemGroup>

<Target Name="GenerateDocumentationPages" BeforeTargets="BeforeBuild">
Expand Down
11 changes: 7 additions & 4 deletions LongevityWorldCup.Website/wwwroot/js/play-athlete-flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,15 @@ function getStoredSelectedAthlete() {

try {
const athlete = JSON.parse(json);
return athlete && typeof athlete === "object" && typeof athlete.Name === "string"
? athlete
: null;
if (isValidSelectedAthlete(athlete)) {
return athlete;
}
} catch (_) {
return null;
}

removeSessionItem("selectedAthlete");
removeSessionItem("tempAthlete");
return null;
}

function isValidSelectedAthlete(value) {
Expand Down
20 changes: 18 additions & 2 deletions LongevityWorldCup.Website/wwwroot/play/menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -939,14 +939,25 @@ <h1 id="athleteDashboardTitle" class="play-dashboard-title">Athlete dashboard</h
let target = panelByPath[path];
if (!target) return;

function redirectToSelectionPanel() {
try {
window.sessionStorage.removeItem('selectedAthlete');
window.sessionStorage.removeItem('tempAthlete');
} catch (_) {
}
window.location.replace('/select-athlete');
}

if (path === '/dashboard') {
try {
const athlete = JSON.parse(window.sessionStorage.getItem('selectedAthlete') || 'null');
if (!athlete || typeof athlete.Name !== 'string' || !athlete.Name.trim()) {
target = panelByPath['/select-athlete'];
redirectToSelectionPanel();
return;
}
} catch (_) {
target = panelByPath['/select-athlete'];
redirectToSelectionPanel();
return;
}
}

Expand Down Expand Up @@ -1058,6 +1069,10 @@ <h1 id="athleteDashboardTitle" class="play-dashboard-title">Athlete dashboard</h
const dashboardAthlete = athleteSelection.getCurrentAthlete()
|| flow.getStoredSelectedAthlete();
if (!dashboardAthlete || !dashboardAthlete.Name) {
if (window.location.pathname.toLowerCase() === getPlayRoute('dashboard')) {
window.location.replace(getPlayRoute('selection'));
return { panelName: 'selection', dashboardAthlete: null, isRedirecting: true };
}
return { panelName: 'selection', dashboardAthlete: null };
}

Expand All @@ -1068,6 +1083,7 @@ <h1 id="athleteDashboardTitle" class="play-dashboard-title">Athlete dashboard</h
function showPlayPanel(requestedPanelName, options = {}) {
const requested = playRouteStates[requestedPanelName] ? requestedPanelName : 'start';
const resolved = resolveRequestedPlayPanel(requested);
if (resolved.isRedirecting) return;
const panelName = resolved.panelName;
const historyMode = requested === panelName ? options.historyMode : (options.historyMode || 'replace');

Expand Down
Loading