From f233a8c8d6ac9dd30babaf79e975c08d45768b17 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Thu, 28 May 2026 11:27:37 -0400 Subject: [PATCH] fix(viewer): fresh signups start at tutorial_state=0, not 100 Previously RegisterAnonymousViewer auto-completed the tutorial, which prevented the client from ever entering the tutorial flow. SeedViewerAsync gains a tutorialState parameter (default 100) so existing tests keep their pre-completed-tutorial assumption. --- .../Repositories/Viewer/ViewerRepository.cs | 2 +- .../Infrastructure/SVSimTestFactory.cs | 16 ++++++++++++- .../ViewerRepositoryTutorialDefaultTests.cs | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs diff --git a/SVSim.Database/Repositories/Viewer/ViewerRepository.cs b/SVSim.Database/Repositories/Viewer/ViewerRepository.cs index bc96d5c..6132c4d 100644 --- a/SVSim.Database/Repositories/Viewer/ViewerRepository.cs +++ b/SVSim.Database/Repositories/Viewer/ViewerRepository.cs @@ -180,7 +180,7 @@ public class ViewerRepository : IViewerRepository viewer.Currency.Crystals = grants.Crystals; viewer.Currency.Rupees = grants.Rupees; viewer.Currency.RedEther = grants.Ether; - viewer.MissionData.TutorialState = 100; // finishes tutorial for now + viewer.MissionData.TutorialState = 0; // PRE_TUTORIAL_STEP โ€” fresh signups go through the tutorial flow // Load classes WITH their LeaderSkins โ€” DefaultLeaderSkin iterates the nav collection // and would otherwise be null (audit ยง6 #3 latent NRE โ€” this is the one). diff --git a/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs b/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs index ba6b73e..fae522c 100644 --- a/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs +++ b/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs @@ -150,7 +150,8 @@ internal sealed class SVSimTestFactory : WebApplicationFactory /// public async Task SeedViewerAsync( ulong steamId = 76_561_198_000_000_001UL, - string displayName = "Test Viewer") + string displayName = "Test Viewer", + int tutorialState = 100) { long viewerId; long shortUdid; @@ -173,6 +174,19 @@ internal sealed class SVSimTestFactory : WebApplicationFactory await db.SaveChangesAsync(); } + // Third scope: override TutorialState to the requested value when non-zero. + // BuildDefaultViewer now starts viewers at 0 (PRE_TUTORIAL_STEP). Tests that want + // a pre-completed-tutorial viewer (the common case for existing tests) pass the + // default tutorialState=100 here. + if (tutorialState != 0) + { + using var scope = Services.CreateScope(); + var db = scope.ServiceProvider.GetRequiredService(); + var viewer = await db.Viewers.Include(v => v.MissionData).FirstAsync(v => v.Id == viewerId); + viewer.MissionData.TutorialState = tutorialState; + await db.SaveChangesAsync(); + } + return viewerId; } diff --git a/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs b/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs new file mode 100644 index 0000000..9175903 --- /dev/null +++ b/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using SVSim.Database; +using SVSim.Database.Repositories.Viewer; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Repositories; + +public class ViewerRepositoryTutorialDefaultTests +{ + [Test] + public async Task RegisterAnonymousViewer_starts_at_tutorial_step_0() + { + using var factory = new SVSimTestFactory(); + using var scope = factory.Services.CreateScope(); + var repo = scope.ServiceProvider.GetRequiredService(); + + var viewer = await repo.RegisterAnonymousViewer(Guid.NewGuid()); + + Assert.That(viewer.MissionData.TutorialState, Is.EqualTo(0), + "Fresh signups must start at PRE_TUTORIAL_STEP=0 so the client triggers the tutorial flow. " + + "Tests that want a pre-completed tutorial should use SeedViewerAsync (which defaults to 100)."); + } +}