Files
zkxw/web-admin/src/utils/storage-slot-range-fill.test.ts
T
zlwuandCursor eae8743826 feat(web-admin): add storage slot range-fill helpers for product lines
Pure functions for copy-first-row attrs and same-box start/end slot pick.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 13:33:32 +08:00

117 lines
3.0 KiB
TypeScript

import { describe, it } from 'node:test'
import assert from 'node:assert/strict'
import {
copyFirstProductLineAttrs,
resolveStorageSlotRangeFill
} from './storage-slot-range-fill'
describe('copyFirstProductLineAttrs', () => {
it('copies spec/expectedCellCount/viability to other rows', () => {
const lines = [
{ specName: '1ml', expectedCellCount: 1.5, viability: 90, productCode: 'A' },
{ specName: '', expectedCellCount: undefined, viability: undefined, productCode: 'B' }
]
const r = copyFirstProductLineAttrs(lines)
assert.equal(r.ok, true)
assert.equal(lines[1].specName, '1ml')
assert.equal(lines[1].expectedCellCount, 1.5)
assert.equal(lines[1].viability, 90)
assert.equal(lines[1].productCode, 'B')
})
it('fails when fewer than 2 lines', () => {
const r = copyFirstProductLineAttrs([{ specName: 'x' }])
assert.equal(r.ok, false)
})
})
describe('resolveStorageSlotRangeFill', () => {
const box = 'node-1'
const slots = [
{
id: 's1',
orderNum: 1001,
facilityNodeId: box,
slotStatus: '空',
occupiedCount: 0,
slotCode: '1-1'
},
{
id: 's2',
orderNum: 1002,
facilityNodeId: box,
slotStatus: '空',
occupiedCount: 0,
slotCode: '1-2'
},
{
id: 's3',
orderNum: 1003,
facilityNodeId: box,
slotStatus: '占用',
occupiedCount: 1,
slotCode: '1-3'
},
{
id: 's4',
orderNum: 1004,
facilityNodeId: box,
slotStatus: '空',
occupiedCount: 0,
slotCode: '1-4'
}
]
it('fails when start/end different boxes', () => {
const r = resolveStorageSlotRangeFill({
slots: [{ ...slots[0] }, { ...slots[1], facilityNodeId: 'other', id: 'sx' }],
startSlotId: 's1',
endSlotId: 'sx',
emptyLineCount: 1,
formUsedSlotIds: []
})
assert.equal(r.ok, false)
assert.match(r.message, /同一盒子/)
})
it('fails when range contains occupied', () => {
const r = resolveStorageSlotRangeFill({
slots,
startSlotId: 's1',
endSlotId: 's4',
emptyLineCount: 2,
formUsedSlotIds: []
})
assert.equal(r.ok, false)
assert.match(r.message, /已占用/)
})
it('takes first N available in normalized range and skips form-used', () => {
const emptySlots = slots.filter((s) => s.id !== 's3')
const r = resolveStorageSlotRangeFill({
slots: emptySlots,
startSlotId: 's4',
endSlotId: 's1',
emptyLineCount: 2,
formUsedSlotIds: ['s2']
})
assert.equal(r.ok, true)
if (r.ok) {
assert.deepEqual(r.slotIds, ['s1', 's4'])
}
})
it('fails when available count < emptyLineCount', () => {
const emptySlots = slots.filter((s) => s.id !== 's3')
const r = resolveStorageSlotRangeFill({
slots: emptySlots,
startSlotId: 's1',
endSlotId: 's2',
emptyLineCount: 3,
formUsedSlotIds: []
})
assert.equal(r.ok, false)
assert.match(r.message, /不足/)
})
})