fix(viewer): fresh signups start with empty DisplayName
Verified against Wizard.Title/UserNameInput.cs:30 in the 2026-05-23
decompile:
IsFinished = !string.IsNullOrEmpty(PlayerStaticData.UserName);
Any non-empty seeded value — including the prior " - " placeholder
this method was passing — sets IsFinished=true on the first frame and
silently skips both the input dialog and the /tutorial/update_action #1
+ /account/update_name calls that travel with it. The in-source comment
described the opposite behavior; empty string is what actually triggers
the dialog.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -100,12 +100,14 @@ public class ViewerRepository : IViewerRepository
|
|||||||
if (udid == Guid.Empty)
|
if (udid == Guid.Empty)
|
||||||
throw new InvalidOperationException("Cannot register viewer for empty UDID.");
|
throw new InvalidOperationException("Cannot register viewer for empty UDID.");
|
||||||
|
|
||||||
// " - " (space-dash-space) matches the prod placeholder for a fresh-signup viewer
|
// Empty DisplayName is load-bearing: the client's Wizard.Title/UserNameInput.Start
|
||||||
// before the user enters their name. Non-empty + non-placeholder values trip
|
// does `IsFinished = !string.IsNullOrEmpty(PlayerStaticData.UserName);` — IsFinished
|
||||||
// UserNameInput.Start's IsNullOrEmpty short-circuit, which silently skips the name
|
// true skips the dialog AND the /tutorial/update_action #1 + /account/update_name
|
||||||
// dialog AND the /tutorial/update_action #1 + /account/update_name calls that
|
// calls that accompany it. Any non-empty value (including the " - " placeholder this
|
||||||
// accompany it — that whole sub-step of the tutorial then never runs.
|
// method used to pass) trips that check and silently bypasses the name-entry sub-step.
|
||||||
var viewer = await BuildDefaultViewer(" - ");
|
// 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;
|
viewer.Udid = udid;
|
||||||
_dbContext.Set<Models.Viewer>().Add(viewer);
|
_dbContext.Set<Models.Viewer>().Add(viewer);
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -25,4 +25,23 @@ public class ViewerRepositoryTutorialDefaultTests
|
|||||||
"client. Tests that want a pre-completed tutorial should use SeedViewerAsync " +
|
"client. Tests that want a pre-completed tutorial should use SeedViewerAsync " +
|
||||||
"(which defaults to 100).");
|
"(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<IViewerRepository>();
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user