fix(launcher): close LA4 review findings
This commit is contained in:
parent
d0a9c65d85
commit
10a712d66b
19 changed files with 1631 additions and 134 deletions
|
|
@ -160,6 +160,28 @@ public sealed class LauncherWindowViewModelTests
|
|||
Assert.Equal("Headless session started for +Acdream.", viewModel.OperationStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AccountGuiSelectWorksWithoutAnyCachedCharacter()
|
||||
{
|
||||
using var orchestrator = new FakeLauncherOrchestrator
|
||||
{
|
||||
IncludeCharacter = false,
|
||||
};
|
||||
using var viewModel = CreateInitialized(orchestrator);
|
||||
SelectAccount(viewModel);
|
||||
|
||||
Assert.Empty(viewModel.SelectedNode!.Children);
|
||||
Assert.True(viewModel.CanLaunchAccountGuiSelect);
|
||||
await viewModel.LaunchAccountGuiSelectCommand.ExecuteAsync();
|
||||
|
||||
Assert.Equal(
|
||||
("Local ACE", "testaccount", (string?)null, LaunchMode.GuiSelect),
|
||||
orchestrator.LaunchRequest);
|
||||
Assert.Equal(
|
||||
"Character-select session started for testaccount.",
|
||||
viewModel.OperationStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProbeUsesTheSelectedAccountAndRunningAccountDisablesIt()
|
||||
{
|
||||
|
|
@ -201,6 +223,25 @@ public sealed class LauncherWindowViewModelTests
|
|||
Assert.Contains("parked at L1", viewModel.GuiLaunchDisabledReason, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MissingCoDeployedHostReasonIsVisibleForCharacterActions()
|
||||
{
|
||||
using var orchestrator = new FakeLauncherOrchestrator
|
||||
{
|
||||
AccountLaunchCapability = LauncherCapability.Unavailable(
|
||||
"The co-deployed host is missing; reinstall or update the client."),
|
||||
};
|
||||
using var viewModel = CreateInitialized(orchestrator);
|
||||
SelectCharacter(viewModel);
|
||||
|
||||
Assert.False(viewModel.CanLaunchGui);
|
||||
Assert.False(viewModel.CanLaunchHeadless);
|
||||
Assert.True(viewModel.ShowGuiLaunchDisabledReason);
|
||||
Assert.True(viewModel.ShowHeadlessLaunchDisabledReason);
|
||||
Assert.Contains("missing", viewModel.GuiLaunchDisabledReason, StringComparison.Ordinal);
|
||||
Assert.Contains("missing", viewModel.HeadlessLaunchDisabledReason, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LaunchErrorAndCancellationBecomeSafeVisibleState()
|
||||
{
|
||||
|
|
@ -254,6 +295,36 @@ public sealed class LauncherWindowViewModelTests
|
|||
Assert.False(dialog.IsOpen);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModalShellsBlockBackgroundCommandsAndAreMutuallyExclusive()
|
||||
{
|
||||
using var orchestrator = new FakeLauncherOrchestrator();
|
||||
using var viewModel = CreateInitialized(orchestrator);
|
||||
|
||||
Assert.True(viewModel.AddServerCommand.CanExecute(null));
|
||||
viewModel.FirstRunWizardShell.OpenCommand.Execute(null);
|
||||
Assert.True(viewModel.IsModalOpen);
|
||||
Assert.False(viewModel.AddServerCommand.CanExecute(null));
|
||||
Assert.False(viewModel.UpdatePromptShell.OpenCommand.CanExecute(null));
|
||||
Assert.False(Assert.Single(viewModel.Sessions).StopCommand.CanExecute(null));
|
||||
|
||||
// ICommand.Execute cannot bypass the modal gate.
|
||||
viewModel.AddServerCommand.Execute(null);
|
||||
Assert.False(viewModel.EditorDialog.IsOpen);
|
||||
Assert.Null(orchestrator.AddedServer);
|
||||
|
||||
viewModel.CloseActiveModal();
|
||||
Assert.False(viewModel.IsModalOpen);
|
||||
Assert.True(viewModel.AddServerCommand.CanExecute(null));
|
||||
|
||||
viewModel.AddServerCommand.Execute(null);
|
||||
Assert.True(viewModel.EditorDialog.IsOpen);
|
||||
Assert.False(viewModel.FirstRunWizardShell.OpenCommand.CanExecute(null));
|
||||
Assert.False(viewModel.ClearFinishedSessionsCommand.CanExecute(null));
|
||||
viewModel.CloseActiveModal();
|
||||
Assert.False(viewModel.EditorDialog.IsOpen);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ActiveSessionStopAndFinishedSessionClearUseCoreOwnership()
|
||||
{
|
||||
|
|
@ -320,6 +391,10 @@ public sealed class LauncherWindowViewModelTests
|
|||
|
||||
public LauncherCapability ProbeCapability { get; set; } = LauncherCapability.Available;
|
||||
|
||||
public LauncherCapability? AccountLaunchCapability { get; set; }
|
||||
|
||||
public bool IncludeCharacter { get; init; } = true;
|
||||
|
||||
public LauncherSessionSnapshot Session { get; set; } = CreateSession();
|
||||
|
||||
public Func<CancellationToken, Task<LauncherSessionSnapshot>>? LaunchHandler { get; set; }
|
||||
|
|
@ -344,7 +419,7 @@ public sealed class LauncherWindowViewModelTests
|
|||
|
||||
public (LaunchMode Mode, IReadOnlyList<string> Plugins, IReadOnlyList<string> Commands)? SettingsUpdate { get; private set; }
|
||||
|
||||
public (string Server, string Account, string Character, LaunchMode Mode)? LaunchRequest { get; private set; }
|
||||
public (string Server, string Account, string? Character, LaunchMode Mode)? LaunchRequest { get; private set; }
|
||||
|
||||
public (string Server, string Account)? ProbeRequest { get; private set; }
|
||||
|
||||
|
|
@ -362,6 +437,12 @@ public sealed class LauncherWindowViewModelTests
|
|||
public LauncherCapability GetLaunchCapability(LaunchMode mode) =>
|
||||
Platform.ForLaunchMode(mode);
|
||||
|
||||
public LauncherCapability GetAccountLaunchCapability(
|
||||
string serverName,
|
||||
string accountName,
|
||||
LaunchMode mode) =>
|
||||
AccountLaunchCapability ?? GetLaunchCapability(mode);
|
||||
|
||||
public LauncherCapability GetProbeCapability(string serverName, string accountName) =>
|
||||
ProbeCapability;
|
||||
|
||||
|
|
@ -428,7 +509,7 @@ public sealed class LauncherWindowViewModelTests
|
|||
public Task<LauncherSessionSnapshot> LaunchAsync(
|
||||
string serverName,
|
||||
string accountName,
|
||||
string characterName,
|
||||
string? characterName,
|
||||
LaunchMode mode,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
|
@ -481,7 +562,7 @@ public sealed class LauncherWindowViewModelTests
|
|||
Error: null,
|
||||
CreatedAt: DateTimeOffset.UnixEpoch);
|
||||
|
||||
private static LauncherServerSnapshot CreateServerSnapshot() => new(
|
||||
private LauncherServerSnapshot CreateServerSnapshot() => new(
|
||||
"Local ACE",
|
||||
"127.0.0.1",
|
||||
9000,
|
||||
|
|
@ -489,18 +570,21 @@ public sealed class LauncherWindowViewModelTests
|
|||
new LauncherAccountSnapshot(
|
||||
"Local ACE",
|
||||
"testaccount",
|
||||
[
|
||||
new LauncherCharacterSnapshot(
|
||||
"Local ACE",
|
||||
"testaccount",
|
||||
"+Acdream",
|
||||
"0x5000000A",
|
||||
LaunchMode.GuiSelect,
|
||||
["Existing.Plugin"],
|
||||
["/tell someone, ready"],
|
||||
HasRunningSession: true,
|
||||
SessionStatus: "Connected."),
|
||||
],
|
||||
IncludeCharacter
|
||||
?
|
||||
[
|
||||
new LauncherCharacterSnapshot(
|
||||
"Local ACE",
|
||||
"testaccount",
|
||||
"+Acdream",
|
||||
"0x5000000A",
|
||||
LaunchMode.GuiSelect,
|
||||
["Existing.Plugin"],
|
||||
["/tell someone, ready"],
|
||||
HasRunningSession: true,
|
||||
SessionStatus: "Connected."),
|
||||
]
|
||||
: [],
|
||||
HasRunningActivity: true,
|
||||
ActivityStatus: "Connected."),
|
||||
]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue