From c0c6e218331b68970b28d4d0fbb2cf9f0a3b726f Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 2 Oct 2026 23:37:38 +0800 Subject: [PATCH] style(tests): normalize platform command fixture line endings --- scripts/admin-test-env-modules/orders.mjs | 158 +++++++++++----------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/scripts/admin-test-env-modules/orders.mjs b/scripts/admin-test-env-modules/orders.mjs index bd142f731..c85d77c77 100644 --- a/scripts/admin-test-env-modules/orders.mjs +++ b/scripts/admin-test-env-modules/orders.mjs @@ -75,85 +75,85 @@ export async function verifyPlatformDraftEdit(context, tenantId, orderId, mercha context.assert(MODULE, 'Platform重放与拒绝不重复写入', null, orderPersistenceFacts(stable) === orderPersistenceFacts(edited), 'order/cargo/parties/history', CONTRACT_OPTIONS) return stable } -export async function verifyPlatformSubmitCancel(context, tenantId, payload, policy) { - const base = '/api/platform/v1/orders/first-leg' - const scope = `tenantId=${encodeURIComponent(tenantId)}` - const proofs = context.createdResources.orders.platformLifecycle = [] - for (const action of ['submit', 'cancel']) { - const draftPayload = { ...structuredClone(payload), ...fixtureInboundCode(policy, `${context.marker}-PLATFORM-${action}`), - customerRemark: `${context.marker} Platform ${action} independent draft` } - const created = await context.request('POST', `${base}?${scope}`, draftPayload, context.token, - { 'Idempotency-Key': key(context, `platform-${action}-create`) }) - const orderId = id(context.apiSuccess(MODULE, `Platform ${action} 创建本轮独立草稿`, created)) - if (!orderId) throw new Error(`Platform ${action} fixture order missing`) - const path = `${base}/${encodeURIComponent(orderId)}?${scope}` - const mutationPath = `${base}/${encodeURIComponent(orderId)}/${action}?${scope}` - const proof = { action, tenantId, orderId, commands: [], checks: [] } - proofs.push(proof) - const assertFact = (label, response, passed, evidence) => { - context.assert(MODULE, `Platform ${action} ${label}`, response, passed, evidence, CONTRACT_OPTIONS) - if (!passed) throw new Error(`Platform ${action} ${label}`) - } - const read = async label => { - const response = await context.request('GET', path) - const detail = context.apiSuccess(MODULE, `Platform ${action} ${label}`, response) - assertFact('详情身份与完整事实集合', response, id(detail?.order?.id) === orderId && id(detail?.order?.tenantId) === id(tenantId) - && Number.isSafeInteger(detail.order.version) && detail.order.version >= 0 - && ['cargoes','parties','internalNotes','statusHistory'].every(field => Array.isArray(detail[field])), 'exact-customer/order/version/aggregate') - return detail - } - const same = (label, before, after) => assertFact(label, null, orderPersistenceFacts(before) === orderPersistenceFacts(after), 'state/version/cargo/parties/notes/history unchanged') - const original = await read('冻结首次草稿版本') - assertFact('取消与提交前置仅为未履约草稿', created, original.order.status === 'DRAFT', 'DRAFT-only') - // Advance through an actual edit, so stale version 0 remains valid input rather than Min(0) validation failure. - const editCommand = freezeOrderCommand(original, key(context, `platform-${action}-prepare-edit`), { draft: draftPayload }) - context.apiSuccess(MODULE, `Platform ${action} 形成真实旧页面版本`, - await context.request('PUT', path, editCommand.body, context.token, editCommand.headers)) - const current = await read('冻结动作首次有效请求版本') - assertFact('编辑后仍为草稿且版本增加', null, current.order.status === 'DRAFT' && current.order.version > original.order.version, 'old-page-version-created') - const extra = action === 'cancel' ? { reason: `${context.marker} independent draft cancellation` } : {} - const command = freezeOrderCommand(current, key(context, `platform-${action}-execute`), extra) - proof.originalVersion = original.order.version - proof.command = command - const send = async (label, body, headers) => { - proof.commands.push({ label, path: mutationPath, body: structuredClone(body), headers: structuredClone(headers) }) - return context.request('POST', mutationPath, body, context.token, headers) - } - const reject = async (label, body, headers, code, expected, statuses = [200]) => { - const response = await send(label, body, headers) - assertFact(label, response, statuses.includes(response?.http) && String(response.body?.code) === code, `expected=${code}`) - same(`${label}后零漂移`, expected, await read(`${label}后回查`)) - proof.checks.push({ label, code }) - } - await reject('首次旧页面版本拒绝', { ...extra, expectedVersion: original.order.version }, - { 'Idempotency-Key': key(context, `platform-${action}-stale-first`) }, 'A0409', current) - await reject('首次缺版本拒绝', extra, - { 'Idempotency-Key': key(context, `platform-${action}-missing-version`) }, 'A0422', current) - await reject('首次缺幂等键拒绝', command.body, {}, 'A0400', current, [200,400]) - context.apiSuccess(MODULE, `Platform ${action} 原版本原键成功`, await send('success', command.body, command.headers)) - const completed = await read('成功后的事实快照') - const expectedStatus = action === 'submit' ? 'SUBMITTED' : 'CANCELLED' - const oldHistoryIds = new Set(current.statusHistory.map(row => id(row.id))) - const added = completed.statusHistory.filter(row => !oldHistoryIds.has(id(row.id))) - assertFact('成功状态版本与唯一动作历史', null, completed.order.status === expectedStatus && completed.order.version > current.order.version - && added.length === 1 && added[0].action === expectedStatus && added[0].fromStatus === 'DRAFT' && added[0].toStatus === expectedStatus - && Boolean(added[0].operatorId && added[0].occurredAt) - && (action !== 'cancel' || added[0].reason === extra.reason), 'one attributed lifecycle history') - assertFact('成功后货物旧历史及业务身份保留', null, - ['cargoes','parties','internalNotes'].every(field => JSON.stringify(current[field]) === JSON.stringify(completed[field])) - && JSON.stringify(current.statusHistory) === JSON.stringify(completed.statusHistory.filter(row => oldHistoryIds.has(id(row.id)))) - && ['id','tenantId','customerId','orderNo'].every(field => current.order[field] === completed.order[field]), 'no unrelated mutations') - context.apiSuccess(MODULE, `Platform ${action} 原键原版本精确重放成功`, await send('replay', command.body, command.headers)) - same('成功重放后零漂移', completed, await read('原键重放后回查')) - const changed = action === 'submit' ? { expectedVersion: completed.order.version } : { ...command.body, reason: `${extra.reason}-changed` } - await reject('原键异载荷拒绝', changed, command.headers, 'A0409', completed) - await reject('新键重复动作拒绝', { ...extra, expectedVersion: completed.order.version }, - { 'Idempotency-Key': key(context, `platform-${action}-repeat-new-key`) }, 'A0409', completed) - proof.finalStatus = expectedStatus - proof.finalFactsSha256 = createHash('sha256').update(orderPersistenceFacts(completed)).digest('hex') - } - return proofs -} +export async function verifyPlatformSubmitCancel(context, tenantId, payload, policy) { + const base = '/api/platform/v1/orders/first-leg' + const scope = `tenantId=${encodeURIComponent(tenantId)}` + const proofs = context.createdResources.orders.platformLifecycle = [] + for (const action of ['submit', 'cancel']) { + const draftPayload = { ...structuredClone(payload), ...fixtureInboundCode(policy, `${context.marker}-PLATFORM-${action}`), + customerRemark: `${context.marker} Platform ${action} independent draft` } + const created = await context.request('POST', `${base}?${scope}`, draftPayload, context.token, + { 'Idempotency-Key': key(context, `platform-${action}-create`) }) + const orderId = id(context.apiSuccess(MODULE, `Platform ${action} 创建本轮独立草稿`, created)) + if (!orderId) throw new Error(`Platform ${action} fixture order missing`) + const path = `${base}/${encodeURIComponent(orderId)}?${scope}` + const mutationPath = `${base}/${encodeURIComponent(orderId)}/${action}?${scope}` + const proof = { action, tenantId, orderId, commands: [], checks: [] } + proofs.push(proof) + const assertFact = (label, response, passed, evidence) => { + context.assert(MODULE, `Platform ${action} ${label}`, response, passed, evidence, CONTRACT_OPTIONS) + if (!passed) throw new Error(`Platform ${action} ${label}`) + } + const read = async label => { + const response = await context.request('GET', path) + const detail = context.apiSuccess(MODULE, `Platform ${action} ${label}`, response) + assertFact('详情身份与完整事实集合', response, id(detail?.order?.id) === orderId && id(detail?.order?.tenantId) === id(tenantId) + && Number.isSafeInteger(detail.order.version) && detail.order.version >= 0 + && ['cargoes','parties','internalNotes','statusHistory'].every(field => Array.isArray(detail[field])), 'exact-customer/order/version/aggregate') + return detail + } + const same = (label, before, after) => assertFact(label, null, orderPersistenceFacts(before) === orderPersistenceFacts(after), 'state/version/cargo/parties/notes/history unchanged') + const original = await read('冻结首次草稿版本') + assertFact('取消与提交前置仅为未履约草稿', created, original.order.status === 'DRAFT', 'DRAFT-only') + // Advance through an actual edit, so stale version 0 remains valid input rather than Min(0) validation failure. + const editCommand = freezeOrderCommand(original, key(context, `platform-${action}-prepare-edit`), { draft: draftPayload }) + context.apiSuccess(MODULE, `Platform ${action} 形成真实旧页面版本`, + await context.request('PUT', path, editCommand.body, context.token, editCommand.headers)) + const current = await read('冻结动作首次有效请求版本') + assertFact('编辑后仍为草稿且版本增加', null, current.order.status === 'DRAFT' && current.order.version > original.order.version, 'old-page-version-created') + const extra = action === 'cancel' ? { reason: `${context.marker} independent draft cancellation` } : {} + const command = freezeOrderCommand(current, key(context, `platform-${action}-execute`), extra) + proof.originalVersion = original.order.version + proof.command = command + const send = async (label, body, headers) => { + proof.commands.push({ label, path: mutationPath, body: structuredClone(body), headers: structuredClone(headers) }) + return context.request('POST', mutationPath, body, context.token, headers) + } + const reject = async (label, body, headers, code, expected, statuses = [200]) => { + const response = await send(label, body, headers) + assertFact(label, response, statuses.includes(response?.http) && String(response.body?.code) === code, `expected=${code}`) + same(`${label}后零漂移`, expected, await read(`${label}后回查`)) + proof.checks.push({ label, code }) + } + await reject('首次旧页面版本拒绝', { ...extra, expectedVersion: original.order.version }, + { 'Idempotency-Key': key(context, `platform-${action}-stale-first`) }, 'A0409', current) + await reject('首次缺版本拒绝', extra, + { 'Idempotency-Key': key(context, `platform-${action}-missing-version`) }, 'A0422', current) + await reject('首次缺幂等键拒绝', command.body, {}, 'A0400', current, [200,400]) + context.apiSuccess(MODULE, `Platform ${action} 原版本原键成功`, await send('success', command.body, command.headers)) + const completed = await read('成功后的事实快照') + const expectedStatus = action === 'submit' ? 'SUBMITTED' : 'CANCELLED' + const oldHistoryIds = new Set(current.statusHistory.map(row => id(row.id))) + const added = completed.statusHistory.filter(row => !oldHistoryIds.has(id(row.id))) + assertFact('成功状态版本与唯一动作历史', null, completed.order.status === expectedStatus && completed.order.version > current.order.version + && added.length === 1 && added[0].action === expectedStatus && added[0].fromStatus === 'DRAFT' && added[0].toStatus === expectedStatus + && Boolean(added[0].operatorId && added[0].occurredAt) + && (action !== 'cancel' || added[0].reason === extra.reason), 'one attributed lifecycle history') + assertFact('成功后货物旧历史及业务身份保留', null, + ['cargoes','parties','internalNotes'].every(field => JSON.stringify(current[field]) === JSON.stringify(completed[field])) + && JSON.stringify(current.statusHistory) === JSON.stringify(completed.statusHistory.filter(row => oldHistoryIds.has(id(row.id)))) + && ['id','tenantId','customerId','orderNo'].every(field => current.order[field] === completed.order[field]), 'no unrelated mutations') + context.apiSuccess(MODULE, `Platform ${action} 原键原版本精确重放成功`, await send('replay', command.body, command.headers)) + same('成功重放后零漂移', completed, await read('原键重放后回查')) + const changed = action === 'submit' ? { expectedVersion: completed.order.version } : { ...command.body, reason: `${extra.reason}-changed` } + await reject('原键异载荷拒绝', changed, command.headers, 'A0409', completed) + await reject('新键重复动作拒绝', { ...extra, expectedVersion: completed.order.version }, + { 'Idempotency-Key': key(context, `platform-${action}-repeat-new-key`) }, 'A0409', completed) + proof.finalStatus = expectedStatus + proof.finalFactsSha256 = createHash('sha256').update(orderPersistenceFacts(completed)).digest('hex') + } + return proofs +} export function fixtureInboundCode(policy, marker) { if (policy?.mode === 'AUTO' && policy.manualEntryRequired === false) return {} if (policy?.mode !== 'LEGACY_MANUAL' || policy.manualEntryRequired !== true || !marker) {