feat: complete legacy UI and playout parity migration

This commit is contained in:
2026-07-15 13:11:38 +09:00
parent f14800656b
commit 6e0c275fdd
108 changed files with 43738 additions and 560 deletions

View File

@@ -109,6 +109,22 @@ public sealed class LegacyManualFinancialScreenServiceTests
Assert.Null(record.Slices[2]);
}
[Fact]
public async Task Revenue_storage_maps_Oracle_empty_strings_returned_as_null()
{
var table = EmptyTable(ManualFinancialScreenKind.RevenueComposition);
table.Rows.Add("A", DBNull.Value, "SMOKE_100", DBNull.Value, DBNull.Value,
DBNull.Value, DBNull.Value, Version);
var result = await new LegacyManualFinancialScreenService(new RecordingQueryExecutor(table))
.SearchAsync(ManualFinancialScreenKind.RevenueComposition);
var record = Assert.IsType<ManualRevenueCompositionRecord>(result.Items[0].Record);
Assert.Equal(string.Empty, record.BaseDate);
Assert.Equal(new ManualRevenueSlice("SMOKE", "100", 100d), record.Slices[0]);
Assert.All(record.Slices.Skip(1), Assert.Null);
}
[Fact]
public async Task Growth_storage_maps_four_named_series_and_four_periods()
{

View File

@@ -242,6 +242,52 @@ public sealed class LegacyPlayoutWorkflowTests
Assert.Equal("5001", workflow.State.OnAirCutCode);
}
[Fact]
public async Task PrepareAndTakeIn_LoadsOnceAndCallsPrepareThenTakeIn()
{
var engine = new RecordingEngine();
var provider = new RecordingProvider(new Dictionary<string, (int, ScenePageSize?)>
{
["5001"] = (1, null)
});
var workflow = new LegacyPlayoutWorkflow(engine, provider);
var result = await workflow.PrepareAndTakeInAsync(
[new("disabled", "5006", false), new("selected", "5001")],
0);
Assert.True(result.IsSuccess);
Assert.Equal(PlayoutOperation.TakeIn, result.Operation);
Assert.Equal(["5001:0"], provider.Calls);
Assert.Equal(["Prepare:5001:p0", "TakeIn"], engine.Calls);
Assert.Equal(1, workflow.State.CurrentCueIndexZeroBased);
Assert.Null(workflow.State.PreparedCutCode);
Assert.Equal("5001", workflow.State.OnAirCutCode);
Assert.Equal("selected", workflow.State.CurrentEntryId);
}
[Fact]
public async Task PrepareAndTakeIn_WhenTakeInFails_RetainsPreparedStateWithoutRetry()
{
var engine = new RecordingEngine();
engine.TakeInResults.Enqueue(PlayoutResultCode.OutcomeUnknown);
var provider = new RecordingProvider(new Dictionary<string, (int, ScenePageSize?)>
{
["5074"] = (6, ScenePageSize.Five)
});
var workflow = new LegacyPlayoutWorkflow(engine, provider);
var result = await workflow.PrepareAndTakeInAsync([new("selected", "5074")], 0);
Assert.Equal(PlayoutResultCode.OutcomeUnknown, result.Code);
Assert.Equal(["5074:0"], provider.Calls);
Assert.Equal(["Prepare:5074:p0", "TakeIn"], engine.Calls);
Assert.Equal("5074", workflow.State.PreparedCutCode);
Assert.Null(workflow.State.OnAirCutCode);
Assert.Equal("selected", workflow.State.CurrentEntryId);
Assert.Equal(LegacyWorkflowNextKind.PageNext, workflow.State.NextKind);
}
[Fact]
public async Task TakeIn_WhenFreshPrepareIsOutcomeUnknown_DoesNotPlayOrReplacePreparedState()
{
@@ -537,6 +583,8 @@ public sealed class LegacyPlayoutWorkflowTests
public Queue<PlayoutResultCode> PrepareResults { get; } = [];
public Queue<PlayoutResultCode> TakeInResults { get; } = [];
public Queue<PlayoutResultCode> UpdateOnAirResults { get; } = [];
public Action? PrepareCallback { get; set; }
@@ -578,7 +626,7 @@ public sealed class LegacyPlayoutWorkflowTests
public Task<PlayoutResult> TakeInAsync(CancellationToken cancellationToken = default)
{
Calls.Add("TakeIn");
return Success(PlayoutOperation.TakeIn);
return Complete(PlayoutOperation.TakeIn, TakeInResults);
}
public Task<PlayoutResult> NextAsync(