feat: migrate legacy playout workflow and scenes
This commit is contained in:
@@ -48,6 +48,21 @@ test("TAKE IN and TAKE OUT preserve the native state prerequisites", () => {
|
||||
null);
|
||||
});
|
||||
|
||||
test("Refresh faults block mutations but preserve emergency TAKE OUT", () => {
|
||||
const faulted = ready({
|
||||
refreshFaulted: true,
|
||||
engineState: "PROGRAM",
|
||||
onAirCode: "5001"
|
||||
});
|
||||
for (const command of ["prepare", "take-in", "next"]) {
|
||||
assert.equal(safety.commandBlockReason(faulted, command), "refresh-fault");
|
||||
}
|
||||
assert.equal(safety.commandBlockReason(faulted, "take-out"), null);
|
||||
assert.equal(
|
||||
safety.canClearCommandError({ code: "REFRESH_FAULT", nonClearable: true }, false),
|
||||
false);
|
||||
});
|
||||
|
||||
test("Browser response timeout follows the bounded native operation timeout", () => {
|
||||
assert.equal(safety.responseTimeoutFromNative(5000), 10000);
|
||||
assert.equal(safety.responseTimeoutFromNative(300000), 305000);
|
||||
@@ -75,3 +90,54 @@ test("Late or mismatched native responses cannot complete a pending command", ()
|
||||
false);
|
||||
assert.equal(safety.matchesPendingCommand(null, { requestId: "REQ-2", command: "next" }), false);
|
||||
});
|
||||
|
||||
test("Timeout and OutcomeUnknown errors cannot clear the session quarantine", () => {
|
||||
assert.equal(
|
||||
safety.canClearCommandError({ code: "WEB_TIMEOUT", outcomeUnknown: true }, true),
|
||||
false);
|
||||
assert.equal(
|
||||
safety.canClearCommandError({ code: "OUTCOME_UNKNOWN", outcomeUnknown: true }, false),
|
||||
false);
|
||||
assert.equal(
|
||||
safety.canClearCommandError({ code: "DATABASE_UNAVAILABLE", outcomeUnknown: false }, false),
|
||||
true);
|
||||
});
|
||||
|
||||
test("Playlist snapshot locks before PREPARE completes and through TAKE OUT", () => {
|
||||
assert.equal(safety.playlistSnapshotLocked(ready()), false);
|
||||
assert.equal(safety.playlistSnapshotLocked(ready({ pending: true })), true);
|
||||
assert.equal(safety.playlistSnapshotLocked(ready({ outcomeUnknown: true })), true);
|
||||
assert.equal(
|
||||
safety.playlistSnapshotLocked(ready({ engineState: "PREPARED", preparedCode: "5001" })),
|
||||
true);
|
||||
assert.equal(
|
||||
safety.playlistSnapshotLocked(ready({ engineState: "PROGRAM", onAirCode: "5001" })),
|
||||
true);
|
||||
});
|
||||
|
||||
test("A database refresh fault clears only after TAKE OUT resets refresh state", () => {
|
||||
const fault = {
|
||||
code: "DATABASE_UNAVAILABLE",
|
||||
message: "Read failed",
|
||||
nonClearable: true,
|
||||
isRefreshFault: true
|
||||
};
|
||||
assert.equal(fault.code, "DATABASE_UNAVAILABLE");
|
||||
assert.equal(fault.nonClearable, true);
|
||||
assert.equal(fault.isRefreshFault, true);
|
||||
assert.equal(safety.shouldClearRefreshError(fault, true), false);
|
||||
assert.equal(safety.shouldClearRefreshError(fault, false), true);
|
||||
|
||||
const unrelated = { code: "SCENE_DATA_INVALID", outcomeUnknown: false };
|
||||
assert.equal(safety.shouldClearRefreshError(unrelated, false), false);
|
||||
});
|
||||
|
||||
test("Stored conditional aliases preserve the exact builder owner", () => {
|
||||
const catalog = [
|
||||
{ builderKey: "s5032", code: "5032", aliases: ["5032", "8018", "8032"] },
|
||||
{ builderKey: "s8018", code: "8018", aliases: ["8018", "8032", "5032"] }
|
||||
];
|
||||
assert.equal(safety.resolveStoredCatalogIndex(catalog, "s5032", "8018"), 0);
|
||||
assert.equal(safety.resolveStoredCatalogIndex(catalog, "s8018", "5032"), 1);
|
||||
assert.equal(safety.resolveStoredCatalogIndex(catalog, "", "8032"), 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user