Files
baiyue-firstleg/scripts/admin-test-env-modules/loading-history-noop-contract.test.mjs
T

71 lines
4.8 KiB
JavaScript
Raw Normal View History

2026-08-27 11:42:05 +08:00
import assert from 'node:assert/strict'
import { readdirSync, readFileSync } from 'node:fs'
import test from 'node:test'
import { isPureStatusNoop, visibleLoadingHistories } from './loading-history-noop.mjs'
const read = (relativeUrl) => readFileSync(new URL(relativeUrl, import.meta.url), 'utf8')
const firstlegServiceDirectory = new URL('../../firstleg/src/main/java/com/baiyue/firstleg/service/', import.meta.url)
const serviceSources = readdirSync(firstlegServiceDirectory)
.filter((name) => name.endsWith('.java'))
.map((name) => read(`../../firstleg/src/main/java/com/baiyue/firstleg/service/${name}`)).join('\n')
const smartLoading = read('../../firstleg/src/main/java/com/baiyue/firstleg/service/SmartLoadingService.java')
const smartLoadingTest = read('../../firstleg/src/test/java/com/baiyue/firstleg/service/SmartLoadingServiceTest.java')
const loadingDtos = read('../../firstleg/src/main/java/com/baiyue/firstleg/dto/LoadingListDtos.java')
const loadingRepository = read('../../firstleg/src/main/java/com/baiyue/firstleg/repository/LoadingListRepository.java')
const openapi = read('../../firstleg/src/main/resources/openapi/loading-lists-v1.yaml')
const adminApi = read('../../../apps/admin-web/src/modules/loading-lists/api/platformLoadingLists.ts')
const adminDrawer = read('../../../apps/admin-web/src/modules/loading-lists/components/LoadingListDetailDrawer.vue')
const adminTests = read('../../../apps/admin-web/src/modules/loading-lists/components/LoadingListsView.test.ts')
test('reference projection removes only pure STATUS_UPDATE no-ops', () => {
assert.equal(isPureStatusNoop({ actionType: 'STATUS_UPDATE', fromStatus: 'EDITING', toStatus: 'EDITING',
beforeSnapshot: '{"status":"EDITING","version":1}', afterSnapshot: '{"version":2,"status":"EDITING"}' }), true)
assert.equal(isPureStatusNoop({ actionType: 'STATUS_UPDATE', fromStatus: 'EDITING', toStatus: 'LOADING' }), false)
assert.equal(isPureStatusNoop({ actionType: 'STATUS_UPDATE', fromStatus: 'EDITING', toStatus: 'EDITING',
beforeSnapshot: '{"containerNo":null}', afterSnapshot: '{"containerNo":"MSCU1"}' }), false)
assert.equal(isPureStatusNoop({ actionType: 'PUSH_PRELOAD', fromStatus: 'EDITING', toStatus: 'EDITING' }), false)
})
test('deduplication uses stable event identity and never identical display text', () => {
const rows = visibleLoadingHistories([
{ historyId: '1', operationId: 'push-1', actionType: 'PUSH_PRELOAD', operationReason: '推送预装' },
{ historyId: '2', operationId: 'push-1', actionType: 'PUSH_PRELOAD', operationReason: '推送预装' },
{ historyId: '3', operationId: 'push-2', actionType: 'PUSH_PRELOAD', operationReason: '推送预装' },
{ historyId: '4', actionType: 'ADJUST_ITEM', operationReason: '相同文案' },
{ historyId: '5', actionType: 'ADJUST_ITEM', operationReason: '相同文案' },
])
assert.deepEqual(rows.map((row) => row.historyId), ['1', '3', '4', '5'])
})
2026-09-04 15:19:45 +08:00
test('backend never appends a generic STATUS_UPDATE and current operation replay is read-only', () => {
2026-08-27 11:42:05 +08:00
assert.doesNotMatch(serviceSources, /(?:history|appendHistory)\([^;]{0,500}"STATUS_UPDATE"/s)
2026-09-04 15:19:45 +08:00
assert.match(smartLoading, /private Plan replay\([\s\S]{0,900}sameRequestHash/)
assert.match(smartLoadingTest, /void replaysBeforeVersionCheck\(\)/)
assert.match(smartLoadingTest, /void exactWarehouseRemarkReplayIsReadOnly\(\)/)
assert.match(smartLoadingTest, /replaysBeforeVersionCheck[\s\S]{0,1200}verify\(repository, never\(\)\)\.candidate/)
assert.match(smartLoadingTest, /exactWarehouseRemarkReplayIsReadOnly[\s\S]{0,1200}verify\(repository, never\(\)\)\.updateRemarks/)
2026-08-27 11:42:05 +08:00
})
test('operationId is projected end-to-end for identity-based frontend deduplication', () => {
assert.match(loadingDtos, /record History\([\s\S]{0,180}String operationId/)
assert.match(loadingRepository, /new History\([\s\S]{0,180}getOperationId\(\)/)
assert.match(openapi, /OperationHistory:[\s\S]{0,500}operationId:/)
assert.match(adminApi, /interface LoadingHistory[\s\S]*?operationId:\s*string/)
2026-08-27 11:42:05 +08:00
assert.match(adminApi, /normalizeHistory[\s\S]{0,260}operationId:/)
})
test('Admin counts and renders the filtered history projection', () => {
assert.match(adminDrawer, /(?:visible|effective|filtered)Histories/)
assert.doesNotMatch(adminDrawer, /detail\.histories\.length\s*\}\}\s*条/)
assert.doesNotMatch(adminDrawer, /v-for="history in detail\.histories"/)
assert.match(adminDrawer, /STATUS_UPDATE/)
assert.match(adminDrawer, /operationId|eventId/)
})
test('Admin behavior contract covers no-op, identity duplicate, count and same-text distinct events', () => {
for (const marker of ['STATUS_UPDATE', 'operationId', 'PUSH_PRELOAD']) assert.match(adminTests, new RegExp(marker))
assert.match(adminTests, /(?:same text|same wording|相同文案|同文案)/i)
assert.match(adminTests, /(?:count|条)/i)
})