feat(campaign): complete durable operator queue

This commit is contained in:
2026-07-22 09:31:33 +02:00
parent f095a3e2c7
commit 99d44eeb8d
5 changed files with 833 additions and 82 deletions

View File

@@ -3,6 +3,8 @@ import test from "node:test";
import {
OPERATOR_QUEUE_REASON,
campaignLifecycleTotals,
campaignVersionWorkItems,
operatorQueueActionBlocks,
type OperatorQueueFacts,
type OperatorQueuePermissions
@@ -12,13 +14,14 @@ const everything: OperatorQueueFacts = {
retryable: 2,
outcomeUnknown: 1,
queueableUnattempted: 3,
queued: 4,
pausable: 4,
paused: 5,
cancellable: 14
};
const allPermissions: OperatorQueuePermissions = {
canRead: true,
canOpenReport: true,
canControl: true,
canRetry: true,
canQueue: true,
@@ -28,6 +31,7 @@ const allPermissions: OperatorQueuePermissions = {
test("enables every fixed queue action when state and permission allow it", () => {
assert.deepEqual(operatorQueueActionBlocks(everything, allPermissions), {
details: null,
report: null,
pause: null,
resume: null,
retry: null,
@@ -40,11 +44,12 @@ test("enables every fixed queue action when state and permission allow it", () =
test("retains every unavailable action with a state-specific explanation", () => {
assert.deepEqual(
operatorQueueActionBlocks(
{ retryable: 0, outcomeUnknown: 0, queueableUnattempted: 0, queued: 0, paused: 0, cancellable: 0 },
{ retryable: 0, outcomeUnknown: 0, queueableUnattempted: 0, pausable: 0, paused: 0, cancellable: 0 },
allPermissions
),
{
details: null,
report: null,
pause: OPERATOR_QUEUE_REASON.noQueued,
resume: OPERATOR_QUEUE_REASON.noPaused,
retry: OPERATOR_QUEUE_REASON.noFailed,
@@ -58,6 +63,7 @@ test("retains every unavailable action with a state-specific explanation", () =>
test("permission explanations take precedence over queue state", () => {
const noPermissions: OperatorQueuePermissions = {
canRead: false,
canOpenReport: false,
canControl: false,
canRetry: false,
canQueue: false,
@@ -66,6 +72,43 @@ test("permission explanations take precedence over queue state", () => {
const blocks = operatorQueueActionBlocks(everything, noPermissions);
assert.deepEqual(
Object.values(blocks),
Array.from({ length: 7 }, () => OPERATOR_QUEUE_REASON.permissionDenied)
Array.from({ length: 8 }, () => OPERATOR_QUEUE_REASON.permissionDenied)
);
});
test("allows in-page job selection without report permission while keeping report access disabled", () => {
const blocks = operatorQueueActionBlocks(everything, {
...allPermissions,
canOpenReport: false
});
assert.equal(blocks.details, null);
assert.equal(blocks.report, OPERATOR_QUEUE_REASON.permissionDenied);
});
test("keeps historical active work visible after a new draft becomes current", () => {
const items = campaignVersionWorkItems(
"campaign-1",
"version-2",
[
{ id: "version-2", version_number: 2 },
{ id: "version-1", version_number: 1 }
],
{
"version-2": { state: "draft", queued: 0, failed: 0 },
"version-1": { state: "active", queued: 3, failed: 1 }
}
);
assert.deepEqual(items.map((item) => [item.versionId, item.isCurrent]), [
["version-2", true],
["version-1", false]
]);
assert.deepEqual(items[1].summary, { state: "active", queued: 3, failed: 1 });
});
test("campaign-wide lifecycle totals are not multiplied across version rows", () => {
assert.deepEqual(campaignLifecycleTotals([
{ pausable: 3, paused: 1, cancellable: 4 },
{ pausable: 0, paused: 2, cancellable: 2 }
]), { pausable: 3, paused: 3, cancellable: 6 });
});