diff --git a/SVSim.Database/Repositories/Viewer/ViewerRepository.cs b/SVSim.Database/Repositories/Viewer/ViewerRepository.cs index 56c9ed9..bbedc17 100644 --- a/SVSim.Database/Repositories/Viewer/ViewerRepository.cs +++ b/SVSim.Database/Repositories/Viewer/ViewerRepository.cs @@ -100,12 +100,14 @@ public class ViewerRepository : IViewerRepository if (udid == Guid.Empty) throw new InvalidOperationException("Cannot register viewer for empty UDID."); - // " - " (space-dash-space) matches the prod placeholder for a fresh-signup viewer - // before the user enters their name. Non-empty + non-placeholder values trip - // UserNameInput.Start's IsNullOrEmpty short-circuit, which silently skips the name - // dialog AND the /tutorial/update_action #1 + /account/update_name calls that - // accompany it — that whole sub-step of the tutorial then never runs. - var viewer = await BuildDefaultViewer(" - "); + // Empty DisplayName is load-bearing: the client's Wizard.Title/UserNameInput.Start + // does `IsFinished = !string.IsNullOrEmpty(PlayerStaticData.UserName);` — IsFinished + // true skips the dialog AND the /tutorial/update_action #1 + /account/update_name + // calls that accompany it. Any non-empty value (including the " - " placeholder this + // method used to pass) trips that check and silently bypasses the name-entry sub-step. + // Empty string flows through /load/index → user_info.name → PlayerStaticData.UserName, + // and the title screen surfaces the input dialog. + var viewer = await BuildDefaultViewer(""); viewer.Udid = udid; _dbContext.Set().Add(viewer); try diff --git a/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs b/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs index d88fbc8..d670983 100644 --- a/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs +++ b/SVSim.UnitTests/Repositories/ViewerRepositoryTutorialDefaultTests.cs @@ -25,4 +25,23 @@ public class ViewerRepositoryTutorialDefaultTests "client. Tests that want a pre-completed tutorial should use SeedViewerAsync " + "(which defaults to 100)."); } + + [Test] + public async Task RegisterAnonymousViewer_starts_with_empty_display_name() + { + // The client's Wizard.Title/UserNameInput.Start does: + // IsFinished = !string.IsNullOrEmpty(PlayerStaticData.UserName); + // Any non-empty seeded value (including the prior " - " placeholder) makes the + // name-input dialog skip itself, and the /tutorial/update_action #1 + + // /account/update_name calls never fire. Empty is what triggers the dialog. + using var factory = new SVSimTestFactory(); + using var scope = factory.Services.CreateScope(); + var repo = scope.ServiceProvider.GetRequiredService(); + + var viewer = await repo.RegisterAnonymousViewer(System.Guid.NewGuid()); + + Assert.That(viewer.DisplayName, Is.Empty, + "Anonymous signups MUST start with empty DisplayName so the client's " + + "UserNameInput.Start IsNullOrEmpty short-circuit fails and the dialog runs."); + } }