Files
LWLT-AIBOT/control-plane/test/operation-timing.test.ts

152 lines
5.2 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
OPERATION_TIMING_SCHEMA_VERSION,
sanitizeOperationTiming
} from '../src/operation-timing.js';
test('control plane keeps only the operation timing allowlisted shape', () => {
const sanitized = sanitizeOperationTiming({
schema_version: OPERATION_TIMING_SCHEMA_VERSION,
status: 'completed',
total_ms: 12_345.6,
stage_count: 2,
started_at: '2026-08-25T00:00:00.000Z',
customer: '测试客户',
stages: [{
stage: 'preflight',
status: 'completed',
duration_ms: 2_345.4,
url: 'https://example.invalid/private',
details: [{
step: 'network_wait.preflight_raw_instruction',
status: 'completed',
duration_ms: 1_800,
response_text: 'private',
counters: {
request_count: 4,
customer_name: 1,
invalid_negative: -1,
invalid_text: 'secret'
}
}]
}, {
stage: 'john_smith',
status: 'completed',
duration_ms: 100
}]
});
assert.deepEqual(sanitized, {
schema_version: OPERATION_TIMING_SCHEMA_VERSION,
status: 'completed',
total_ms: 12_346,
stage_count: 2,
stages: [{
stage: 'preflight',
status: 'completed',
duration_ms: 2_345,
details: [{
step: 'network_wait.preflight_raw_instruction',
status: 'completed',
duration_ms: 1_800,
counters: { request_count: 4 }
}]
}]
});
assert.equal(JSON.stringify(sanitized).includes('测试客户'), false);
assert.equal(JSON.stringify(sanitized).includes('example.invalid'), false);
assert.equal(JSON.stringify(sanitized).includes('response_text'), false);
});
test('control plane rejects unknown timing contracts', () => {
assert.equal(sanitizeOperationTiming(null), null);
assert.equal(sanitizeOperationTiming({ schema_version: 'other', stages: [] }), null);
assert.equal(sanitizeOperationTiming({ stages: [] }), null);
});
test('control plane accepts every plugin page-action timing code', () => {
const actions = [
'cleanup_completed_lifecycle_dialog',
'create_split_child_live',
'create_split_parent_live',
'export_confirmation_sources',
'inspect_operation_context',
'live_submit_approved',
'live_submit_lifecycle_operation',
'live_submit_team_batch_approved',
'open_order_form',
'open_team_batch_form',
'ping_order_frame',
'ping_team_batch_frame',
'preflight_lifecycle_operation',
'preflight_raw_instruction',
'preflight_team_batch_native',
'prepare_lifecycle_operation',
'resolve_lifecycle_operation',
'return_to_order_list',
'unknown_action',
'verify_lifecycle_operation',
'verify_order_marker',
'verify_team_batch_receipts'
];
const sanitized = sanitizeOperationTiming({
schema_version: OPERATION_TIMING_SCHEMA_VERSION,
status: 'completed',
total_ms: 1,
stages: [{
stage: 'browser_execution',
status: 'completed',
duration_ms: 1,
details: actions.map((action) => ({
step: `action_roundtrip.${action}`,
status: 'completed',
duration_ms: 1,
counters: { call_count: 1 }
}))
}]
});
const details = sanitized?.stages as Array<{ details?: Array<{ step: string }> }>;
assert.deepEqual(details[0]?.details?.map((detail) => detail.step), actions.map((action) => `action_roundtrip.${action}`));
});
test('control plane keeps the privacy-safe orchestration breakdown used to locate unattributed time', () => {
const safeDetails = [
{ step: 'storage_prune.local_history', counters: { removed_result_count: 8, protected_root_count: 2 } },
{ step: 'storage_read.result_state', counters: { result_count: 12, execution_count: 12, timing_count: 1 } },
{ step: 'storage_write.result_state', counters: { call_count: 1 } },
{ step: 'tab_lookup.cache_hit', counters: { cache_hit_count: 1 } },
{ step: 'preflight_lookup.parallel_wall', counters: { request_count: 4 } },
{ step: 'preflight_product_linkage', counters: { sample_count: 5, stable_sample_count: 4 } },
{ step: 'preflight_submit_intercept', counters: { submit_count: 1, quiet_wait_ms: 150 } }
];
const sanitized = sanitizeOperationTiming({
schema_version: OPERATION_TIMING_SCHEMA_VERSION,
status: 'completed',
total_ms: 10,
stages: [{
stage: 'preflight',
status: 'completed',
duration_ms: 10,
details: safeDetails.map((detail) => ({ ...detail, status: 'completed', duration_ms: 1 }))
}]
});
const stages = sanitized?.stages as Array<{ details?: Array<{ step: string }> }>;
assert.deepEqual(stages[0]?.details?.map((detail) => detail.step), safeDetails.map((detail) => detail.step));
const rejected = sanitizeOperationTiming({
schema_version: OPERATION_TIMING_SCHEMA_VERSION,
status: 'completed',
total_ms: 1,
stages: [{
stage: 'preflight',
status: 'completed',
duration_ms: 1,
details: [{ step: 'storage_read.customer_value', duration_ms: 1, counters: { customer_name: 1 } }]
}]
});
const rejectedStages = rejected?.stages as Array<{ details?: Array<unknown> }>;
assert.equal(rejectedStages[0]?.details, undefined);
});