fix: advance NEXT past unplayable cuts
This commit is contained in:
@@ -312,6 +312,78 @@ public sealed class LegacyPlayoutWorkflowTests
|
||||
Assert.DoesNotContain("Next:5074:p0", engine.Calls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Next_WhenEnabledMiddleCueIsUnplayable_ConsumesOneNextAndFollowingNextPlaysThirdCue()
|
||||
{
|
||||
var engine = new RecordingEngine();
|
||||
var provider = new RecordingProvider(new Dictionary<string, (int, ScenePageSize?)>
|
||||
{
|
||||
["5001"] = (1, null),
|
||||
[LegacyPlaylistEntry.UnresolvedCutCode] = (1, null),
|
||||
["5088"] = (1, null)
|
||||
});
|
||||
provider.UnplayableCutCodes.Add(LegacyPlaylistEntry.UnresolvedCutCode);
|
||||
var workflow = new LegacyPlayoutWorkflow(engine, provider);
|
||||
LegacyPlaylistEntry[] playlist =
|
||||
[
|
||||
new("first", "5001"),
|
||||
new("unplayable", LegacyPlaylistEntry.UnresolvedCutCode),
|
||||
new("third", "5088")
|
||||
];
|
||||
Assert.True((await workflow.TakeSelectedAsync(playlist, 0)).IsSuccess);
|
||||
|
||||
await Assert.ThrowsAsync<LegacySceneDataException>(() => workflow.NextAsync());
|
||||
|
||||
Assert.Equal(1, workflow.State.CurrentCueIndexZeroBased);
|
||||
Assert.Equal("unplayable", workflow.State.CurrentEntryId);
|
||||
Assert.Equal(0, workflow.State.OnAirCueIndexZeroBased);
|
||||
Assert.Equal("first", workflow.State.OnAirEntryId);
|
||||
Assert.Equal("5001", workflow.State.OnAirCutCode);
|
||||
Assert.Equal(LegacyWorkflowNextKind.PlaylistNext, workflow.State.NextKind);
|
||||
Assert.Equal(
|
||||
["5001:0", LegacyPlaylistEntry.UnresolvedCutCode + ":0"],
|
||||
provider.Calls);
|
||||
Assert.DoesNotContain(engine.Calls, call => call.StartsWith("Next:", StringComparison.Ordinal));
|
||||
|
||||
var result = await workflow.NextAsync();
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(2, workflow.State.CurrentCueIndexZeroBased);
|
||||
Assert.Equal("third", workflow.State.CurrentEntryId);
|
||||
Assert.Equal(2, workflow.State.OnAirCueIndexZeroBased);
|
||||
Assert.Equal("third", workflow.State.OnAirEntryId);
|
||||
Assert.Equal("5088", workflow.State.OnAirCutCode);
|
||||
Assert.Equal("Next:5088:p0", engine.Calls[^1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Next_WhenOutcomeIsUnknown_DoesNotAdvanceTheProgressCursor()
|
||||
{
|
||||
var engine = new RecordingEngine();
|
||||
engine.NextResults.Enqueue(PlayoutResultCode.OutcomeUnknown);
|
||||
var provider = new RecordingProvider(new Dictionary<string, (int, ScenePageSize?)>
|
||||
{
|
||||
["5001"] = (1, null),
|
||||
["5088"] = (1, null)
|
||||
});
|
||||
var workflow = new LegacyPlayoutWorkflow(engine, provider);
|
||||
LegacyPlaylistEntry[] playlist =
|
||||
[
|
||||
new("first", "5001"),
|
||||
new("second", "5088")
|
||||
];
|
||||
Assert.True((await workflow.TakeSelectedAsync(playlist, 0)).IsSuccess);
|
||||
|
||||
var result = await workflow.NextAsync();
|
||||
|
||||
Assert.Equal(PlayoutResultCode.OutcomeUnknown, result.Code);
|
||||
Assert.Equal(0, workflow.State.CurrentCueIndexZeroBased);
|
||||
Assert.Equal("first", workflow.State.CurrentEntryId);
|
||||
Assert.Equal(0, workflow.State.OnAirCueIndexZeroBased);
|
||||
Assert.Equal("first", workflow.State.OnAirEntryId);
|
||||
Assert.Equal("5001", workflow.State.OnAirCutCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Next_WhenProgramAllRowsAreDisabled_EndsWithoutDispatchingTheEngine()
|
||||
{
|
||||
@@ -1128,6 +1200,8 @@ public sealed class LegacyPlayoutWorkflowTests
|
||||
|
||||
public List<string?> SelectionGraphicTypes { get; } = [];
|
||||
|
||||
public HashSet<string> UnplayableCutCodes { get; } = new(StringComparer.Ordinal);
|
||||
|
||||
public Func<string, int, string>? SceneNameOverride { get; init; }
|
||||
|
||||
public string? BuilderKey { get; init; }
|
||||
@@ -1142,6 +1216,11 @@ public sealed class LegacyPlayoutWorkflowTests
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
Calls.Add($"{entry.CutCode}:{pageIndexZeroBased}");
|
||||
SelectionGraphicTypes.Add(entry.Selection?.GraphicType);
|
||||
if (UnplayableCutCodes.Contains(entry.CutCode))
|
||||
{
|
||||
throw new LegacySceneDataException("The selected playlist row is not playable.");
|
||||
}
|
||||
|
||||
var definition = definitions[entry.CutCode];
|
||||
var name = SceneNameOverride?.Invoke(entry.CutCode, pageIndexZeroBased) ?? entry.CutCode;
|
||||
return Task.FromResult(new LegacySceneCuePage(
|
||||
@@ -1199,6 +1278,8 @@ public sealed class LegacyPlayoutWorkflowTests
|
||||
|
||||
public Queue<PlayoutResultCode> TakeInResults { get; } = [];
|
||||
|
||||
public Queue<PlayoutResultCode> NextResults { get; } = [];
|
||||
|
||||
public Queue<PlayoutResultCode> UpdateOnAirResults { get; } = [];
|
||||
|
||||
public Action? PrepareCallback { get; set; }
|
||||
@@ -1248,7 +1329,7 @@ public sealed class LegacyPlayoutWorkflowTests
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Calls.Add("Next:" + Describe(cue));
|
||||
return Success(PlayoutOperation.Next);
|
||||
return Complete(PlayoutOperation.Next, NextResults);
|
||||
}
|
||||
|
||||
public Task<PlayoutResult> UpdateOnAirAsync(
|
||||
|
||||
Reference in New Issue
Block a user