This commit is contained in:
@@ -226,6 +226,91 @@ test('exchange phone conflicts support HTTP error and business response without
|
||||
})
|
||||
})
|
||||
|
||||
test('exchange association handoff carries only the new asset and its bound phone as strings', async () => {
|
||||
const { getExchangePhoneAssociationQuery } = await loadModule(
|
||||
'src/utils/business/exchangeError.ts'
|
||||
)
|
||||
const newAsset = { asset_identifier: '89860624590014594318', associated_phones: ['19232713115'] }
|
||||
assert.deepEqual(
|
||||
getExchangePhoneAssociationQuery({ code: 1202, data: { phone: '19232713115' } }, newAsset),
|
||||
{
|
||||
asset_identifier: '89860624590014594318',
|
||||
phone: '19232713115'
|
||||
}
|
||||
)
|
||||
assert.deepEqual(
|
||||
getExchangePhoneAssociationQuery({ response: { data: { code: 1202 } } }, newAsset),
|
||||
{
|
||||
asset_identifier: '89860624590014594318',
|
||||
phone: '19232713115'
|
||||
}
|
||||
)
|
||||
assert.equal(getExchangePhoneAssociationQuery({ code: 1206 }, newAsset), undefined)
|
||||
assert.equal(
|
||||
getExchangePhoneAssociationQuery({ code: 1202, data: { phone: '19232713115' } }, {}),
|
||||
undefined
|
||||
)
|
||||
assert.equal(
|
||||
getExchangePhoneAssociationQuery(
|
||||
{ code: 1202 },
|
||||
{ asset_identifier: '89860624590014594318', associated_phones: [] }
|
||||
),
|
||||
undefined
|
||||
)
|
||||
assert.deepEqual(
|
||||
getExchangePhoneAssociationQuery({ code: 1202, data: { phone: '13900000000' } }, newAsset),
|
||||
{
|
||||
asset_identifier: '89860624590014594318',
|
||||
phone: '13900000000'
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
test('association preselection excludes old assets, different phones and invalid historical rows', async () => {
|
||||
const {
|
||||
getPhoneAssetAssociationTarget,
|
||||
getMatchingPhoneAssetAssociations,
|
||||
getPhoneAssetUnbindResultName
|
||||
} = await loadModule('src/utils/business/phoneAssetAssociation.ts')
|
||||
const target = getPhoneAssetAssociationTarget({
|
||||
asset_identifier: ' 89860624590014594318 ',
|
||||
phone: '19232713115'
|
||||
})
|
||||
const rows = [
|
||||
{ id: 1, asset_identifier: target.asset_identifier, phone: target.phone, status: 1 },
|
||||
{ id: 2, asset_identifier: '89860625770070732445', phone: target.phone, status: 1 },
|
||||
{ id: 3, asset_identifier: target.asset_identifier, phone: '13900000000', status: 1 },
|
||||
{ id: 4, asset_identifier: target.asset_identifier, phone: target.phone, status: 0 }
|
||||
]
|
||||
assert.deepEqual(
|
||||
getMatchingPhoneAssetAssociations(rows, target).map((row) => row.id),
|
||||
[1]
|
||||
)
|
||||
assert.deepEqual(getMatchingPhoneAssetAssociations(rows, { ...target, phone: '' }), [])
|
||||
assert.deepEqual(
|
||||
getPhoneAssetAssociationTarget({ asset_identifier: ['a', 'b'], phone: ['19232713115'] }),
|
||||
{ asset_identifier: '', phone: '' }
|
||||
)
|
||||
assert.equal(getPhoneAssetUnbindResultName(true), '解绑成功')
|
||||
assert.equal(getPhoneAssetUnbindResultName(false), '解绑失败')
|
||||
})
|
||||
|
||||
test('association page watches handoff changes, clears stale selections and retains manual unbind confirmation', async () => {
|
||||
const page = await readFile(
|
||||
'src/views/asset-management/phone-asset-association/index.vue',
|
||||
'utf8'
|
||||
)
|
||||
assert.match(page, /getPhoneAssetAssociationTarget\(route.query\)/)
|
||||
assert.match(page, /toggleRowSelection\(row, true\)/)
|
||||
assert.match(page, /requestId !== listRequestId/)
|
||||
assert.match(page, /getPhoneAssetUnbindResultName\(row.success\)/)
|
||||
assert.doesNotMatch(page, /prop="success"/)
|
||||
assert.match(page, /batchForm.confirmed = false/)
|
||||
assert.match(page, /batchFormRef.value\?\.validate/)
|
||||
const table = await readFile('src/components/core/tables/ArtTable.vue', 'utf8')
|
||||
assert.match(table, /clearSelection:.*clearSelection\(\)/)
|
||||
})
|
||||
|
||||
test('password validation errors accept backend message as well as msg', async () => {
|
||||
const { normalizeApiError } = await loadModule('src/utils/business/apiError.ts')
|
||||
for (const field of ['msg', 'message']) {
|
||||
|
||||
@@ -101,11 +101,55 @@ const exchange = {
|
||||
updated_at: time
|
||||
}
|
||||
|
||||
const associations = [
|
||||
{
|
||||
id: 101,
|
||||
asset_id: 1001,
|
||||
asset_type: 'iot_card',
|
||||
asset_identifier: exchange.new_asset_identifier,
|
||||
phone: '13800000000',
|
||||
status: 1,
|
||||
status_name: '有效',
|
||||
established_at: time
|
||||
},
|
||||
{
|
||||
id: 102,
|
||||
asset_id: 1001,
|
||||
asset_type: 'iot_card',
|
||||
asset_identifier: exchange.new_asset_identifier,
|
||||
phone: '13800000000',
|
||||
status: 0,
|
||||
status_name: '已失效',
|
||||
established_at: time
|
||||
},
|
||||
{
|
||||
id: 103,
|
||||
asset_id: 1002,
|
||||
asset_type: 'iot_card',
|
||||
asset_identifier: exchange.old_asset_identifier,
|
||||
phone: '13800000000',
|
||||
status: 1,
|
||||
status_name: '有效',
|
||||
established_at: time
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
asset_id: 1002,
|
||||
asset_type: 'iot_card',
|
||||
asset_identifier: exchange.old_asset_identifier,
|
||||
phone: '13900000000',
|
||||
status: 1,
|
||||
status_name: '有效',
|
||||
established_at: time
|
||||
}
|
||||
]
|
||||
|
||||
export const mockApiPlugin = {
|
||||
name: 'october-local-mock-api',
|
||||
configureServer(server) {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
const path = new URL(req.url, 'http://127.0.0.1').pathname
|
||||
const url = new URL(req.url, 'http://127.0.0.1')
|
||||
const path = url.pathname
|
||||
if (!path.startsWith('/api/')) return next()
|
||||
if (path === '/api/auth/login' || path === '/api/auth/me') {
|
||||
const user = {
|
||||
@@ -134,6 +178,37 @@ export const mockApiPlugin = {
|
||||
return
|
||||
}
|
||||
if (req.method !== 'GET') {
|
||||
if (path === '/api/admin/phone-asset-associations/batch-unbind') {
|
||||
let body = ''
|
||||
req.on('data', (chunk) => {
|
||||
body += chunk
|
||||
})
|
||||
req.on('end', () => {
|
||||
const request = JSON.parse(body)
|
||||
const items = request.assets.map((asset) => {
|
||||
const matches = associations.filter(
|
||||
(row) =>
|
||||
row.asset_id === asset.asset_id &&
|
||||
row.asset_type === asset.asset_type &&
|
||||
row.status === 1
|
||||
)
|
||||
matches.forEach((row) => {
|
||||
row.status = 0
|
||||
row.status_name = '已失效'
|
||||
})
|
||||
return { ...asset, success: true, unbound_count: matches.length, reason: '' }
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
code: 0,
|
||||
msg: 'mock',
|
||||
data: { success_count: items.length, fail_count: 0, items }
|
||||
})
|
||||
)
|
||||
})
|
||||
return
|
||||
}
|
||||
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
@@ -153,6 +228,15 @@ export const mockApiPlugin = {
|
||||
page_size: 20
|
||||
})
|
||||
let data = page([])
|
||||
if (path === '/api/admin/phone-asset-associations')
|
||||
data = page(
|
||||
associations.filter(
|
||||
(row) =>
|
||||
(!url.searchParams.get('asset_identifier') ||
|
||||
row.asset_identifier === url.searchParams.get('asset_identifier')) &&
|
||||
(!url.searchParams.get('phone') || row.phone === url.searchParams.get('phone'))
|
||||
)
|
||||
)
|
||||
if (path === '/api/admin/orders/1') data = order
|
||||
if (path === '/api/admin/exchanges') data = page([exchange])
|
||||
if (path === '/api/admin/exchanges/1') data = exchange
|
||||
|
||||
Reference in New Issue
Block a user