feat: align legacy operator and playout behavior
This commit is contained in:
@@ -181,9 +181,12 @@ public sealed class LegacyOperatorControllerTests
|
||||
var candleRow = candle.Playlist[1];
|
||||
Assert.Equal("8051", candleRow.ToPlayoutEntry().CutCode);
|
||||
Assert.Equal(
|
||||
"MA5",
|
||||
string.Empty,
|
||||
Assert.IsType<MBN_STOCK_WEBVIEW.Core.Playout.Scenes.LegacySceneSelection>(
|
||||
candleRow.ToPlayoutEntry().Selection).GraphicType);
|
||||
Assert.Equal(
|
||||
"MA5",
|
||||
controller.CreatePlayoutRequest().Playlist[1].Selection!.GraphicType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -242,17 +245,24 @@ public sealed class LegacyOperatorControllerTests
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2);
|
||||
var rows = controller.Current.Playlist;
|
||||
controller.SelectPlaylistRow(rows[0].RowId, control: false, shift: false);
|
||||
controller.SelectPlaylistRow(rows[1].RowId, control: true, shift: false);
|
||||
|
||||
var last = controller.SelectPlaylistBoundary(last: true);
|
||||
Assert.True(last.Playlist[0].IsEnabled);
|
||||
Assert.True(last.Playlist[2].IsSelected);
|
||||
Assert.True(last.Playlist[2].IsActive);
|
||||
Assert.Equal(
|
||||
rows.Take(2).Select(row => row.RowId),
|
||||
last.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
|
||||
var toggled = controller.ToggleActivePlaylistRowEnabled();
|
||||
Assert.False(toggled.Playlist[2].IsEnabled);
|
||||
|
||||
var first = controller.SelectPlaylistBoundary(last: false);
|
||||
Assert.True(first.Playlist[0].IsSelected);
|
||||
Assert.False(first.Playlist[2].IsSelected);
|
||||
Assert.True(first.Playlist[0].IsActive);
|
||||
Assert.Equal(
|
||||
rows.Take(2).Select(row => row.RowId),
|
||||
first.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -307,7 +317,7 @@ public sealed class LegacyOperatorControllerTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MovingAverageFlagsAreCapturedInFixedCandleSelection()
|
||||
public void FixedCandleIdentityStaysStableWhileF8SamplesCurrentMovingAverages()
|
||||
{
|
||||
var controller = new LegacyOperatorController(Lookup());
|
||||
var candle = LegacyFixedActionCatalog.Default
|
||||
@@ -319,11 +329,23 @@ public sealed class LegacyOperatorControllerTests
|
||||
var state = controller.ActivateFixedAction(candle.Id);
|
||||
|
||||
Assert.Equal(
|
||||
"MA20",
|
||||
string.Empty,
|
||||
Assert.IsType<MBN_STOCK_WEBVIEW.Core.Playout.Scenes.LegacySceneSelection>(
|
||||
Assert.Single(state.Playlist).ToPlayoutEntry().Selection).GraphicType);
|
||||
Assert.Equal(
|
||||
"MA20",
|
||||
Assert.Single(controller.CreatePlayoutRequest().Playlist).Selection!.GraphicType);
|
||||
Assert.False(state.MovingAverages.Ma5);
|
||||
Assert.True(state.MovingAverages.Ma20);
|
||||
|
||||
controller.SetMovingAverages(ma5: true, ma20: false);
|
||||
|
||||
Assert.Equal(
|
||||
"MA5",
|
||||
Assert.Single(controller.CreatePlayoutRequest().Playlist).Selection!.GraphicType);
|
||||
Assert.Equal(
|
||||
string.Empty,
|
||||
Assert.Single(controller.Current.Playlist).PlayoutSelection!.GraphicType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -356,6 +378,9 @@ public sealed class LegacyOperatorControllerTests
|
||||
Assert.Equal("현재가", row.Subtype);
|
||||
Assert.Equal("005930", row.StockCode);
|
||||
Assert.Equal("5001", row.ToPlayoutEntry().CutCode);
|
||||
Assert.True(row.IsActive);
|
||||
Assert.False(row.IsSelected);
|
||||
Assert.Equal(0, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -558,6 +583,89 @@ public sealed class LegacyOperatorControllerTests
|
||||
Assert.All(state.Playlist, row => Assert.True(row.IsSelected));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckboxActivationChangesF8CandidateWithoutReplacingDeleteSelection()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2);
|
||||
var ids = controller.Current.Playlist.Select(row => row.RowId).ToArray();
|
||||
controller.SelectPlaylistRow(ids[0], control: false, shift: false);
|
||||
controller.SelectPlaylistRow(ids[1], control: true, shift: false);
|
||||
|
||||
var state = controller.ActivatePlaylistRow(ids[2]);
|
||||
|
||||
Assert.Equal(
|
||||
ids[..2],
|
||||
state.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
Assert.Equal(ids[2], Assert.Single(state.Playlist, row => row.IsActive).RowId);
|
||||
Assert.Equal(2, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckboxActivationDoesNotMoveTheFollowingShiftSelectionAnchor()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2, 4);
|
||||
var ids = controller.Current.Playlist.Select(row => row.RowId).ToArray();
|
||||
controller.SelectPlaylistRow(ids[1], control: false, shift: false);
|
||||
|
||||
controller.ActivatePlaylistRow(ids[3]);
|
||||
var range = controller.SelectPlaylistRow(ids[2], control: false, shift: true);
|
||||
|
||||
Assert.Equal(
|
||||
ids[1..3],
|
||||
range.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
Assert.Equal(ids[2], Assert.Single(range.Playlist, row => row.IsActive).RowId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HomeAndEndChangeOnlyTheF8CandidateAndKeepProgramPageProjection()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2, 4);
|
||||
var rows = controller.Current.Playlist;
|
||||
controller.SelectPlaylistRow(rows[1].RowId, control: false, shift: false);
|
||||
controller.SelectPlaylistRow(rows[3].RowId, control: true, shift: false);
|
||||
controller.ReflectSuccessfulPlayout(
|
||||
rows[1].RowId,
|
||||
pageIndexZeroBased: 1,
|
||||
pageCount: 3,
|
||||
synchronizeOperatorSelection: false);
|
||||
|
||||
var home = controller.SelectPlaylistBoundary(last: false);
|
||||
Assert.Equal(0, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
Assert.Equal("2/3", home.Playlist[1].PageText);
|
||||
Assert.True(home.Playlist[0].IsActive);
|
||||
Assert.Equal(
|
||||
[rows[1].RowId, rows[3].RowId],
|
||||
home.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
|
||||
var end = controller.SelectPlaylistBoundary(last: true);
|
||||
Assert.Equal(3, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
Assert.Equal("2/3", end.Playlist[1].PageText);
|
||||
Assert.True(end.Playlist[3].IsActive);
|
||||
|
||||
var shift = controller.SelectPlaylistRow(
|
||||
rows[2].RowId,
|
||||
control: false,
|
||||
shift: true);
|
||||
Assert.Equal(
|
||||
[rows[1].RowId, rows[2].RowId],
|
||||
shift.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstAppendedRowIsAnF8CandidateButNotAnImplicitDeleteSelection()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0);
|
||||
var before = controller.Current;
|
||||
|
||||
Assert.True(Assert.Single(before.Playlist).IsActive);
|
||||
Assert.DoesNotContain(before.Playlist, row => row.IsSelected);
|
||||
Assert.Equal(0, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
|
||||
var after = controller.DeleteSelectedPlaylistRows();
|
||||
Assert.Equal(before.Revision, after.Revision);
|
||||
Assert.Single(after.Playlist);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PlaylistEnabledSupportsIndividualToggleAndAllRows()
|
||||
{
|
||||
@@ -591,6 +699,73 @@ public sealed class LegacyOperatorControllerTests
|
||||
[initial[0].RowId, initial[2].RowId],
|
||||
state.Playlist.Select(row => row.RowId));
|
||||
Assert.DoesNotContain(state.Playlist, row => row.IsSelected);
|
||||
Assert.Equal(initial[2].RowId, Assert.Single(state.Playlist, row => row.IsActive).RowId);
|
||||
Assert.Equal(1, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeletePreservesAnIndependentCheckboxCandidateByStableIdentity()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2, 4);
|
||||
var initial = controller.Current.Playlist.ToArray();
|
||||
controller.SelectPlaylistRow(initial[0].RowId, control: false, shift: false);
|
||||
controller.SelectPlaylistRow(initial[1].RowId, control: true, shift: false);
|
||||
controller.ActivatePlaylistRow(initial[3].RowId);
|
||||
|
||||
var state = controller.DeleteSelectedPlaylistRows();
|
||||
|
||||
Assert.Equal(
|
||||
[initial[2].RowId, initial[3].RowId],
|
||||
state.Playlist.Select(row => row.RowId));
|
||||
Assert.DoesNotContain(state.Playlist, row => row.IsSelected);
|
||||
Assert.Equal(initial[3].RowId, Assert.Single(state.Playlist, row => row.IsActive).RowId);
|
||||
Assert.Equal(1, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteActiveCandidateChoosesTheNextSurvivorThenThePreviousAtEnd()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2, 4);
|
||||
var initial = controller.Current.Playlist.ToArray();
|
||||
controller.SelectPlaylistRow(initial[1].RowId, control: false, shift: false);
|
||||
|
||||
var afterMiddle = controller.DeleteSelectedPlaylistRows();
|
||||
|
||||
Assert.Equal(initial[2].RowId, Assert.Single(afterMiddle.Playlist, row => row.IsActive).RowId);
|
||||
Assert.Equal(1, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
|
||||
controller.SelectPlaylistRow(initial[3].RowId, control: false, shift: false);
|
||||
var afterLast = controller.DeleteSelectedPlaylistRows();
|
||||
|
||||
Assert.Equal(initial[2].RowId, Assert.Single(afterLast.Playlist, row => row.IsActive).RowId);
|
||||
Assert.Equal(1, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShiftSelectionAndDeleteAreNotLimitedToTheOriginalHundredRowBuffers()
|
||||
{
|
||||
var controller = new LegacyOperatorController(Lookup());
|
||||
await controller.SearchStocksAsync("삼성", LegacySearchTrigger.Button);
|
||||
controller.SelectStock(0);
|
||||
controller.CutPointerDown(1, false, false, 1, 24, 1_000);
|
||||
for (var index = 0; index < 101; index++)
|
||||
{
|
||||
controller.DropSelectedCutsOnPlaylist();
|
||||
}
|
||||
|
||||
var rows = controller.Current.Playlist;
|
||||
Assert.Equal(101, rows.Count);
|
||||
controller.SelectPlaylistRow(rows[0].RowId, control: false, shift: false);
|
||||
var selected = controller.SelectPlaylistRow(
|
||||
rows[^1].RowId,
|
||||
control: false,
|
||||
shift: true);
|
||||
Assert.Equal(101, selected.Playlist.Count(row => row.IsSelected));
|
||||
|
||||
var deleted = controller.DeleteSelectedPlaylistRows();
|
||||
|
||||
Assert.Empty(deleted.Playlist);
|
||||
Assert.Throws<InvalidOperationException>(() => controller.CreatePlayoutRequest());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -610,6 +785,21 @@ public sealed class LegacyOperatorControllerTests
|
||||
Assert.Equal(unchangedRevision, stillEmpty.Revision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstAppendAfterDeleteAllReestablishesTheVisibleF8Candidate()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1);
|
||||
controller.DeleteAllPlaylistRows();
|
||||
|
||||
controller.CutPointerDown(2, false, false, 1, 47, 10_000);
|
||||
var state = controller.DropSelectedCutsOnPlaylist();
|
||||
|
||||
var row = Assert.Single(state.Playlist);
|
||||
Assert.True(row.IsActive);
|
||||
Assert.False(row.IsSelected);
|
||||
Assert.Equal(0, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MoveUsesOnlyActiveRowAndCollapsesMultiSelectionToMovedRow()
|
||||
{
|
||||
@@ -626,12 +816,17 @@ public sealed class LegacyOperatorControllerTests
|
||||
Assert.Equal(
|
||||
initial[2].RowId,
|
||||
Assert.Single(moved.Playlist, row => row.IsSelected).RowId);
|
||||
Assert.Equal(initial[2].ToPlayoutEntry(), moved.Playlist[1].ToPlayoutEntry());
|
||||
Assert.Equal(initial[2].PageText, moved.Playlist[1].PageText);
|
||||
Assert.Equal(initial[2].RawCutLabel, moved.Playlist[1].RawCutLabel);
|
||||
Assert.Equal(1, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
|
||||
var restored = controller.MoveSelectedPlaylistRows(LegacyPlaylistMoveDirection.Down);
|
||||
Assert.Equal(initial.Select(row => row.RowId), restored.Playlist.Select(row => row.RowId));
|
||||
Assert.Equal(
|
||||
initial[2].RowId,
|
||||
Assert.Single(restored.Playlist, row => row.IsSelected).RowId);
|
||||
Assert.Equal(2, controller.CreatePlayoutRequest().SelectedIndexZeroBased);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -651,7 +846,7 @@ public sealed class LegacyOperatorControllerTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PlaylistDragMovesNoncontiguousSelectionAsOneOrderedBlockAndIsIdempotent()
|
||||
public async Task PlaylistDragMovesOnlySourceRowCollapsesSelectionAndIsIdempotent()
|
||||
{
|
||||
var controller = await ControllerWithPlaylistAsync(0, 1, 2, 4, 5, 6);
|
||||
var initial = controller.Current.Playlist.ToArray();
|
||||
@@ -666,16 +861,19 @@ public sealed class LegacyOperatorControllerTests
|
||||
Assert.Equal(
|
||||
[
|
||||
initial[0].RowId,
|
||||
initial[1].RowId,
|
||||
initial[2].RowId,
|
||||
initial[4].RowId,
|
||||
initial[1].RowId,
|
||||
initial[3].RowId,
|
||||
initial[5].RowId
|
||||
],
|
||||
moved.Playlist.Select(row => row.RowId));
|
||||
Assert.Equal(
|
||||
[initial[1].RowId, initial[3].RowId],
|
||||
moved.Playlist.Where(row => row.IsSelected).Select(row => row.RowId));
|
||||
initial[3].RowId,
|
||||
Assert.Single(moved.Playlist, row => row.IsSelected).RowId);
|
||||
Assert.Equal(
|
||||
initial[3].RowId,
|
||||
Assert.Single(moved.Playlist, row => row.IsActive).RowId);
|
||||
|
||||
var revision = moved.Revision;
|
||||
var duplicate = controller.ReorderPlaylistRows(
|
||||
@@ -686,6 +884,9 @@ public sealed class LegacyOperatorControllerTests
|
||||
Assert.Equal(
|
||||
moved.Playlist.Select(row => row.RowId),
|
||||
duplicate.Playlist.Select(row => row.RowId));
|
||||
Assert.Equal(
|
||||
initial[3].RowId,
|
||||
Assert.Single(duplicate.Playlist, row => row.IsSelected).RowId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user