110 lines
4.0 KiB
C#
110 lines
4.0 KiB
C#
namespace Zcbot.WindowsNode.Tests;
|
|
|
|
public sealed class AnsysAcceptanceViewModelTests : IDisposable
|
|
{
|
|
private readonly string root = Path.Combine(
|
|
Path.GetTempPath(), "zcbot-ansys-view-model-tests", Guid.NewGuid().ToString("N"));
|
|
|
|
[Fact]
|
|
public async Task PassedAcceptanceEnablesTheMachineGateAfterConfirmation()
|
|
{
|
|
Directory.CreateDirectory(root);
|
|
var reportPath = Path.Combine(root, "acceptance-report.json");
|
|
var service = new FakeAnsysAcceptanceService(
|
|
new AdapterAcceptanceResult(true, reportPath, "passed"));
|
|
using var viewModel = new AnsysAcceptanceViewModel(service);
|
|
viewModel.ChooseReportDirectoryRequested += () => root;
|
|
viewModel.ConfirmRunRequested += () => true;
|
|
viewModel.ConfirmEnableGateRequested += () => true;
|
|
|
|
viewModel.RunCommand.Execute(null);
|
|
await WaitUntilAsync(() => !viewModel.IsRunning && service.RunCount == 1);
|
|
|
|
Assert.True(viewModel.CanEnableGate);
|
|
Assert.Equal("success", viewModel.Tone);
|
|
Assert.Contains(reportPath, viewModel.Message);
|
|
|
|
viewModel.EnableGateCommand.Execute(null);
|
|
|
|
Assert.True(service.IsGateEnabled);
|
|
Assert.False(viewModel.CanEnableGate);
|
|
Assert.Contains("重新启动", viewModel.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CancellationKeepsTheExecutionGateClosed()
|
|
{
|
|
Directory.CreateDirectory(root);
|
|
var service = new FakeAnsysAcceptanceService(null) { BlockRun = true };
|
|
using var viewModel = new AnsysAcceptanceViewModel(service);
|
|
viewModel.ChooseReportDirectoryRequested += () => root;
|
|
viewModel.ConfirmRunRequested += () => true;
|
|
|
|
viewModel.RunCommand.Execute(null);
|
|
await service.RunStarted.Task.WaitAsync(TimeSpan.FromSeconds(2));
|
|
viewModel.CancelCommand.Execute(null);
|
|
await WaitUntilAsync(() => !viewModel.IsRunning);
|
|
|
|
Assert.False(viewModel.CanEnableGate);
|
|
Assert.Equal("验收已停止,执行门保持关闭。", viewModel.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReportValidationRequiresAnExplicitPassedValue()
|
|
{
|
|
Directory.CreateDirectory(root);
|
|
var passed = Path.Combine(root, "passed.json");
|
|
var failed = Path.Combine(root, "failed.json");
|
|
File.WriteAllText(passed, "{\"passed\":true}");
|
|
File.WriteAllText(failed, "{\"passed\":false}");
|
|
|
|
Assert.True(AnsysAcceptanceService.ReportPassed(passed));
|
|
Assert.False(AnsysAcceptanceService.ReportPassed(failed));
|
|
Assert.False(AnsysAcceptanceService.ReportPassed(Path.Combine(root, "missing.json")));
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(root)) Directory.Delete(root, recursive: true);
|
|
}
|
|
|
|
private static async Task WaitUntilAsync(Func<bool> condition)
|
|
{
|
|
var deadline = DateTime.UtcNow.AddSeconds(2);
|
|
while (!condition() && DateTime.UtcNow < deadline)
|
|
{
|
|
await Task.Delay(10);
|
|
}
|
|
Assert.True(condition());
|
|
}
|
|
|
|
private sealed class FakeAnsysAcceptanceService(AdapterAcceptanceResult? result)
|
|
: IAnsysAcceptanceService
|
|
{
|
|
internal bool BlockRun { get; init; }
|
|
internal int RunCount { get; private set; }
|
|
internal TaskCompletionSource RunStarted { get; } = new(
|
|
TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
public bool IsAvailable => true;
|
|
public bool IsGateEnabled { get; private set; }
|
|
|
|
public async Task<AdapterAcceptanceResult> RunAsync(
|
|
string workRoot,
|
|
IProgress<string> progress,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
RunCount++;
|
|
RunStarted.TrySetResult();
|
|
progress.Report("running");
|
|
if (BlockRun)
|
|
{
|
|
await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken);
|
|
}
|
|
return result ?? throw new InvalidOperationException("missing result");
|
|
}
|
|
|
|
public void EnableGate(string reportPath) => IsGateEnabled = true;
|
|
}
|
|
}
|