feat(campaign): add durable operator queue controls
This commit is contained in:
71
webui/tests/operator-queue-model.test.ts
Normal file
71
webui/tests/operator-queue-model.test.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
OPERATOR_QUEUE_REASON,
|
||||
operatorQueueActionBlocks,
|
||||
type OperatorQueueFacts,
|
||||
type OperatorQueuePermissions
|
||||
} from "../src/features/operator/operatorQueueModel.ts";
|
||||
|
||||
const everything: OperatorQueueFacts = {
|
||||
retryable: 2,
|
||||
outcomeUnknown: 1,
|
||||
queueableUnattempted: 3,
|
||||
queued: 4,
|
||||
paused: 5,
|
||||
cancellable: 14
|
||||
};
|
||||
|
||||
const allPermissions: OperatorQueuePermissions = {
|
||||
canRead: true,
|
||||
canControl: true,
|
||||
canRetry: true,
|
||||
canQueue: true,
|
||||
canReconcile: true
|
||||
};
|
||||
|
||||
test("enables every fixed queue action when state and permission allow it", () => {
|
||||
assert.deepEqual(operatorQueueActionBlocks(everything, allPermissions), {
|
||||
details: null,
|
||||
pause: null,
|
||||
resume: null,
|
||||
retry: null,
|
||||
"queue-unsent": null,
|
||||
reconcile: null,
|
||||
cancel: null
|
||||
});
|
||||
});
|
||||
|
||||
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 },
|
||||
allPermissions
|
||||
),
|
||||
{
|
||||
details: null,
|
||||
pause: OPERATOR_QUEUE_REASON.noQueued,
|
||||
resume: OPERATOR_QUEUE_REASON.noPaused,
|
||||
retry: OPERATOR_QUEUE_REASON.noFailed,
|
||||
"queue-unsent": OPERATOR_QUEUE_REASON.noUnsent,
|
||||
reconcile: OPERATOR_QUEUE_REASON.noUnknown,
|
||||
cancel: OPERATOR_QUEUE_REASON.noCancellable
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("permission explanations take precedence over queue state", () => {
|
||||
const noPermissions: OperatorQueuePermissions = {
|
||||
canRead: false,
|
||||
canControl: false,
|
||||
canRetry: false,
|
||||
canQueue: false,
|
||||
canReconcile: false
|
||||
};
|
||||
const blocks = operatorQueueActionBlocks(everything, noPermissions);
|
||||
assert.deepEqual(
|
||||
Object.values(blocks),
|
||||
Array.from({ length: 7 }, () => OPERATOR_QUEUE_REASON.permission)
|
||||
);
|
||||
});
|
||||
18
webui/tests/operator-queue-ui-structure.test.mjs
Normal file
18
webui/tests/operator-queue-ui-structure.test.mjs
Normal file
@@ -0,0 +1,18 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const source = readFileSync(resolve(here, "../src/features/operator/OperatorQueuePage.tsx"), "utf8");
|
||||
|
||||
assert.match(source, /<DataGrid/);
|
||||
assert.match(source, /<TableActionGroup actions=/);
|
||||
for (const action of ["details", "pause", "resume", "retry", "queue-unsent", "reconcile", "cancel"]) {
|
||||
assert.match(source, new RegExp(`id: "${action}"`));
|
||||
}
|
||||
assert.match(source, /useDeltaWatermarks/);
|
||||
assert.match(source, /window\.setInterval[\s\S]*10_000/);
|
||||
assert.match(source, /<ConfirmDialog[\s\S]*cancelTarget/);
|
||||
assert.doesNotMatch(source, /claim_token|eml_local_path|storage_key|smtp_transport_revision/);
|
||||
assert.doesNotMatch(source, /window\.alert\s*\(/);
|
||||
Reference in New Issue
Block a user