81 lines
3.5 KiB
JavaScript
81 lines
3.5 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { createRequire } from 'node:module';
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const guard = require('../chrome-extension/ltjt-order-assistant/execution-guard.js');
|
|
|
|
test('a new ERP execution is accepted exactly once', () => {
|
|
assert.deepEqual(guard.acceptanceDecision(null, 'execution-1'), {
|
|
accepted: true,
|
|
status: 'accepted',
|
|
reason: ''
|
|
});
|
|
const existing = { execution_id: 'execution-1', state: 'running' };
|
|
const replay = guard.acceptanceDecision(existing, 'execution-1');
|
|
assert.equal(replay.accepted, false);
|
|
assert.equal(replay.status, 'already_started');
|
|
});
|
|
|
|
test('a different execution id for the same task is blocked', () => {
|
|
const result = guard.acceptanceDecision({ execution_id: 'execution-1', state: 'completed' }, 'execution-2');
|
|
assert.equal(result.accepted, false);
|
|
assert.equal(result.status, 'duplicate_blocked');
|
|
});
|
|
|
|
test('failures after the write boundary become uncertain', () => {
|
|
assert.equal(guard.failureState({ state: 'running' }), 'blocked');
|
|
assert.equal(guard.failureState({ state: 'write_started' }), 'uncertain');
|
|
assert.equal(guard.failureState({ state: 'submitted' }), 'uncertain');
|
|
assert.equal(guard.rootTaskId('TASK-1#2'), 'TASK-1');
|
|
});
|
|
|
|
test('an explicit network-before-submit block is safe to classify as no ERP write', () => {
|
|
const report = {
|
|
status: 'live_submit_blocked',
|
|
execution_phase: 'prewrite_blocked',
|
|
write_attempted: false,
|
|
no_erp_write: true,
|
|
submit_safety: { live_submit_attempted: false },
|
|
native_request: null,
|
|
server_response: null,
|
|
requery: null,
|
|
side_effects: [],
|
|
ajax_records: [{ prevented_from_network: true, network_request_attempted: false }]
|
|
};
|
|
assert.equal(guard.confirmedPrewriteNoErpWrite(report), true);
|
|
assert.equal(guard.confirmedPrewriteNoErpWrite({ ...report, write_attempted: true }), false);
|
|
assert.equal(guard.confirmedPrewriteNoErpWrite({
|
|
...report,
|
|
ajax_records: [{ prevented_from_network: false, network_request_attempted: true }]
|
|
}), false);
|
|
assert.equal(guard.confirmedPrewriteNoErpWrite({ ...report, side_effects: { unknown: true } }), false);
|
|
});
|
|
|
|
test('local extension history stays bounded without pruning active or uncertain roots', () => {
|
|
const tasks = {};
|
|
const results = {};
|
|
const executions = {};
|
|
for (let index = 1; index <= 6; index += 1) {
|
|
const taskId = `TASK-${index}`;
|
|
const updatedAt = `2026-08-${String(index).padStart(2, '0')}T00:00:00.000Z`;
|
|
tasks[taskId] = { task_id: taskId, updated_at: updatedAt };
|
|
results[taskId] = { status: 'completed', updated_at: updatedAt };
|
|
executions[taskId] = { state: 'completed', updated_at: updatedAt };
|
|
}
|
|
executions['TASK-1'] = { state: 'running', updated_at: '2026-08-01T00:00:00.000Z' };
|
|
results['TASK-2'] = { status: 'execution_uncertain', updated_at: '2026-08-02T00:00:00.000Z' };
|
|
tasks['TASK-6#1'] = { task_id: 'TASK-6#1', updated_at: '2026-08-06T00:00:01.000Z' };
|
|
results['TASK-6#1'] = { status: 'completed', updated_at: '2026-08-06T00:00:01.000Z' };
|
|
|
|
const pruned = guard.pruneLocalTaskHistory(
|
|
{ tasks, results, executions, timingStates: {} },
|
|
{ currentTaskId: 'TASK-3', terminalRootLimit: 2 }
|
|
);
|
|
|
|
assert.deepEqual(Object.keys(pruned.results).sort(), ['TASK-1', 'TASK-2', 'TASK-3', 'TASK-5', 'TASK-6', 'TASK-6#1']);
|
|
assert.equal(pruned.counters.protected_root_count, 3);
|
|
assert.equal(pruned.counters.removed_root_count, 1);
|
|
assert.equal(pruned.counters.removed_result_count, 1);
|
|
});
|