121 lines
5.7 KiB
TypeScript
121 lines
5.7 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import { fileURLToPath } from 'node:url'
|
|
import test from 'node:test'
|
|
|
|
import {
|
|
resolveConsignmentPriceMinYuan,
|
|
resolveConsignmentQuantityLimit,
|
|
} from '../src/utils/consignment-publish-limits.ts'
|
|
|
|
test('寄售价允许低于1元:未配置最低价时输入框下限为0.01元', () => {
|
|
assert.equal(resolveConsignmentPriceMinYuan(0), 0.01)
|
|
assert.equal(resolveConsignmentPriceMinYuan(null), 0.01)
|
|
assert.equal(resolveConsignmentPriceMinYuan(73), 0.73)
|
|
assert.equal(resolveConsignmentPriceMinYuan(100), 1)
|
|
})
|
|
|
|
test('寄售数量上限按当前分类的 activeQuantity 计算剩余额度', () => {
|
|
const config = { inventoryLimit: { enabled: true, maxActiveQuantity: 10 } }
|
|
const remaining = resolveConsignmentQuantityLimit(config, 3)
|
|
assert.equal(remaining.enabled, true)
|
|
assert.equal(remaining.activeQuantity, 3)
|
|
assert.equal(remaining.remainingQuantity, 7)
|
|
assert.equal(remaining.blocked, false)
|
|
|
|
const full = resolveConsignmentQuantityLimit(config, 10)
|
|
assert.equal(full.remainingQuantity, 0)
|
|
assert.equal(full.blocked, true)
|
|
|
|
const over = resolveConsignmentQuantityLimit(config, 12)
|
|
assert.equal(over.remainingQuantity, 0)
|
|
assert.equal(over.blocked, true)
|
|
})
|
|
|
|
test('寄售数量限制关闭时不校验剩余额度', () => {
|
|
const disabled = resolveConsignmentQuantityLimit(
|
|
{ inventoryLimit: { enabled: false, maxActiveQuantity: 10 } },
|
|
100,
|
|
)
|
|
assert.equal(disabled.enabled, false)
|
|
assert.equal(disabled.remainingQuantity, 0)
|
|
assert.equal(disabled.blocked, false)
|
|
})
|
|
|
|
test('打手端发布页:价格与数量限制必须走同一套规则', () => {
|
|
const page = readFileSync(
|
|
fileURLToPath(new URL('../src/pages/worker/WorkerConsignmentPage.tsx', import.meta.url)),
|
|
'utf8',
|
|
)
|
|
assert.ok(page.includes('resolveConsignmentPriceMinYuan('), '价格下限必须走配置解析函数')
|
|
assert.ok(page.includes('min={priceMinYuan}'), '价格输入框必须使用配置最低价')
|
|
assert.ok(!page.includes('Math.max(100, minPriceFen)'), '提交校验不得再强制最低 1 元')
|
|
assert.ok(!page.includes("message.error('寄售价格不能少于1元')"), '不得再提示最低 1 元')
|
|
assert.ok(
|
|
page.includes('resolveConsignmentQuantityLimit('),
|
|
'数量上限必须按当前分类的 activeQuantity 计算',
|
|
)
|
|
assert.ok(page.includes('quantityLimit.remainingQuantity'), '必须展示剩余可寄卖数量')
|
|
assert.ok(page.includes('quantityLimit.blocked'), '达到上限时必须禁用提交')
|
|
assert.ok(page.includes('quantityLimit.activeQuantity'), '必须带入当前在售/待审核件数')
|
|
})
|
|
|
|
test('打手端发布页:发布成功、切回发布 tab、手动刷新都会同步最新寄售占用', () => {
|
|
const page = readFileSync(
|
|
fileURLToPath(new URL('../src/pages/worker/WorkerConsignmentPage.tsx', import.meta.url)),
|
|
'utf8',
|
|
)
|
|
|
|
// 含 activeQuantity 的配置查询不能有缓存,否则发布后仍显示旧额度
|
|
const queryStart = page.indexOf('const consignmentProfilesQuery = useQuery({')
|
|
const queryEnd = page.indexOf('const consignmentProfiles =', queryStart)
|
|
assert.ok(queryStart > 0 && queryEnd > queryStart, '必须存在寄卖配置查询')
|
|
assert.ok(
|
|
!page.slice(queryStart, queryEnd).includes('staleTime'),
|
|
'含 activeQuantity 的配置查询不得设置 staleTime',
|
|
)
|
|
|
|
// 发布成功后必须刷新配置占用,否则同一页面连续发布仍按旧额度提示
|
|
const publishStart = page.indexOf('async function handlePublishSubmit')
|
|
const publishEnd = page.indexOf('function resolveActionSubmissionId')
|
|
assert.ok(publishStart > 0 && publishEnd > publishStart, '必须存在发布提交处理函数')
|
|
assert.ok(
|
|
page.slice(publishStart, publishEnd).includes('consignmentProfilesQuery.refetch()'),
|
|
'发布成功后必须刷新寄卖配置占用',
|
|
)
|
|
|
|
// 切回「发布寄卖」tab 时必须失效缓存(客服审核/驳回后占用会变)
|
|
const effectStart = page.indexOf('切换标签页时自动刷新最新数据')
|
|
const effectEnd = page.indexOf('// 后端已按「一件货一行」聚合')
|
|
assert.ok(effectStart > 0 && effectEnd > effectStart, '必须存在切 tab 刷新逻辑')
|
|
assert.ok(
|
|
page.slice(effectStart, effectEnd).includes("queryKey: ['worker-consignment-profiles']"),
|
|
'切回发布 tab 必须失效寄卖配置缓存',
|
|
)
|
|
|
|
// 顶部「刷新」按钮必须同时刷新寄卖记录与剩余额度
|
|
const refreshStart = page.indexOf('loading={myConsignmentsQuery.isFetching')
|
|
const refreshEnd = page.indexOf('刷新', refreshStart)
|
|
assert.ok(refreshStart > 0 && refreshEnd > refreshStart, '必须存在顶部刷新按钮')
|
|
assert.ok(
|
|
page.slice(refreshStart, refreshEnd).includes('consignmentProfilesQuery.refetch()'),
|
|
'手动刷新必须同步刷新剩余寄卖额度',
|
|
)
|
|
})
|
|
|
|
test('打手端价格按单价展示并给出合计,避免把单价误读成整单总价', () => {
|
|
const page = readFileSync(
|
|
fileURLToPath(new URL('../src/pages/worker/WorkerConsignmentPage.tsx', import.meta.url)),
|
|
'utf8',
|
|
)
|
|
assert.ok(page.includes('label="寄售单价(元/件)"'), '发布页价格必须标明是单价')
|
|
assert.ok(page.includes('合计 ¥${totalPriceYuan.toFixed(2)}'), '发布页必须展示单价 × 数量的合计')
|
|
assert.ok(page.includes('title="修改寄卖单价"'), '改价弹窗标题必须标明是单价')
|
|
assert.ok(
|
|
page.includes('最高不能超过系统建议单价'),
|
|
'改价上限提示必须按单价口径,不能再说成整单建议价',
|
|
)
|
|
assert.ok(page.includes('按当前模板价实时计算'), '改价上限必须标明按当前模板价实时计算')
|
|
assert.ok(page.includes('高于最新模板价'), '当前售价高于模板价时必须提示先下调')
|
|
})
|