Files
order_site/apps/backend/src/services/claim/affiliate-dash-bind-state.test.ts
T

342 lines
8.4 KiB
TypeScript

import test from 'node:test'
import assert from 'node:assert/strict'
import {
AFFILIATE_DASH_BIND_REFRESH_FRESH_MS,
AFFILIATE_DASH_ORDER_SYNC_FRESH_MS,
canReuseAffiliateDashBindSnapshot,
isAffiliateDashBindSnapshotStale,
isAffiliateDashSnapshotFresh,
isRockAffiliateDashSku,
shouldRefuseRockRebind,
shouldRefreshAffiliateDashBindStateForSnapshot,
} from './kuaishou-cloud-claim-service.js'
test('isAffiliateDashBindSnapshotStale detects bind uuid that belongs to old uid', () => {
assert.equal(
isAffiliateDashBindSnapshotStale(
{
bindUuid: 'bind-old',
bindUrl: 'https://dash.example/bind-old',
expectedGameAccount: '111',
gameAccount: '111',
},
'222',
),
true,
)
})
test('isAffiliateDashBindSnapshotStale treats unknown bind uid as stale', () => {
assert.equal(
isAffiliateDashBindSnapshotStale(
{
bindUuid: 'bind-unknown',
bindUrl: 'https://dash.example/bind-unknown',
},
'222',
),
true,
)
})
test('isAffiliateDashBindSnapshotStale keeps current uid bind snapshot', () => {
assert.equal(
isAffiliateDashBindSnapshotStale(
{
bindUuid: 'bind-current',
bindUrl: 'https://dash.example/bind-current',
expectedGameAccount: '222',
gameAccount: '222',
},
'222',
),
false,
)
})
test('canReuseAffiliateDashBindSnapshot reuses pending current uid bind', () => {
assert.equal(
canReuseAffiliateDashBindSnapshot(
{
bindUuid: 'bind-current',
bindUrl: 'https://dash.example/bind-current',
expectedGameAccount: '222',
gameAccount: '222',
bound: false,
bindMismatch: false,
},
'222',
),
true,
)
})
test('canReuseAffiliateDashBindSnapshot refuses old uid bind', () => {
assert.equal(
canReuseAffiliateDashBindSnapshot(
{
bindUuid: 'bind-old',
bindUrl: 'https://dash.example/bind-old',
expectedGameAccount: '111',
gameAccount: '111',
bound: false,
bindMismatch: false,
},
'222',
),
false,
)
})
test('canReuseAffiliateDashBindSnapshot refuses bound snapshot without bound account', () => {
assert.equal(
canReuseAffiliateDashBindSnapshot(
{
bindUuid: 'bind-current',
bindUrl: 'https://dash.example/bind-current',
expectedGameAccount: '222',
gameAccount: '222',
bound: true,
boundAccount: '',
bindMismatch: false,
},
'222',
),
false,
)
})
test('canReuseAffiliateDashBindSnapshot reuses verified matching bound account', () => {
assert.equal(
canReuseAffiliateDashBindSnapshot(
{
bindUuid: 'bind-current',
bindUrl: 'https://dash.example/bind-current',
expectedGameAccount: '222',
gameAccount: '222',
bound: true,
boundAccount: '222',
bindMismatch: false,
},
'222',
),
true,
)
})
test('rock rebind is refused after mismatch or after a successful bind changes uid', () => {
assert.equal(isRockAffiliateDashSku('rock_black_tshirt'), true)
assert.equal(isRockAffiliateDashSku('top_black_elite_trainer'), false)
assert.equal(
shouldRefuseRockRebind({
sku: 'rock_black_tshirt',
bindUuid: 'bind-1',
bindMismatch: true,
}),
true,
)
// 方案 B:买家改回扫码真实账号时放行自愈,改第三个账号时拒绝
assert.equal(
shouldRefuseRockRebind(
{
sku: 'rock_black_tshirt',
bindUuid: 'bind-1',
boundAccount: '3454648872',
bindMismatch: true,
},
'3454648872',
),
false,
)
assert.equal(
shouldRefuseRockRebind(
{
sku: 'rock_black_tshirt',
bindUuid: 'bind-1',
boundAccount: '3454648872',
bindMismatch: true,
},
'9999999999',
),
true,
)
assert.equal(
shouldRefuseRockRebind(
{
sku: 'rock_black_tshirt',
bindUuid: 'bind-1',
bound: true,
boundAccount: '111',
expectedGameAccount: '111',
},
'222',
),
true,
)
assert.equal(
shouldRefuseRockRebind(
{
sku: 'rock_black_tshirt',
bindUuid: 'bind-1',
bound: false,
bindMismatch: false,
expectedGameAccount: '111',
},
'222',
),
false,
)
assert.equal(
shouldRefuseRockRebind(
{
sku: 'skin_other',
bindUuid: 'bind-1',
bindMismatch: true,
},
'222',
),
false,
)
})
test('canReuseAffiliateDashBindSnapshot refuses mismatched bound account', () => {
assert.equal(
canReuseAffiliateDashBindSnapshot(
{
bindUuid: 'bind-current',
bindUrl: 'https://dash.example/bind-current',
expectedGameAccount: '222',
gameAccount: '222',
bound: true,
boundAccount: '333',
bindMismatch: false,
},
'222',
),
false,
)
})
test('isAffiliateDashSnapshotFresh treats missing or future timestamps as stale', () => {
const now = Date.parse('2026-10-01T06:00:00.000Z')
assert.equal(isAffiliateDashSnapshotFresh(null, AFFILIATE_DASH_ORDER_SYNC_FRESH_MS, now), false)
assert.equal(isAffiliateDashSnapshotFresh('', AFFILIATE_DASH_ORDER_SYNC_FRESH_MS, now), false)
assert.equal(
isAffiliateDashSnapshotFresh('not-a-date', AFFILIATE_DASH_ORDER_SYNC_FRESH_MS, now),
false,
)
assert.equal(
isAffiliateDashSnapshotFresh(
'2026-10-01T06:00:01.000Z',
AFFILIATE_DASH_ORDER_SYNC_FRESH_MS,
now,
),
false,
)
})
test('order snapshot stays fresh for 45s and bind snapshot only for 15s', () => {
const now = Date.parse('2026-10-01T06:00:45.000Z')
assert.equal(
isAffiliateDashSnapshotFresh(
'2026-10-01T06:00:00.000Z',
AFFILIATE_DASH_ORDER_SYNC_FRESH_MS,
now,
),
false,
)
assert.equal(
isAffiliateDashSnapshotFresh(
'2026-10-01T06:00:01.000Z',
AFFILIATE_DASH_ORDER_SYNC_FRESH_MS,
now,
),
true,
)
assert.equal(
isAffiliateDashSnapshotFresh(
'2026-10-01T06:00:30.000Z',
AFFILIATE_DASH_BIND_REFRESH_FRESH_MS,
now,
),
false,
)
assert.equal(
isAffiliateDashSnapshotFresh(
'2026-10-01T06:00:31.000Z',
AFFILIATE_DASH_BIND_REFRESH_FRESH_MS,
now,
),
true,
)
})
test('claim detail skips affiliate-dash sync while the snapshot is fresh', async () => {
const { readFile } = await import('node:fs/promises')
const src = await readFile(new URL('./kuaishou-cloud-claim-service.ts', import.meta.url), 'utf8')
const detail = src.slice(
src.indexOf('export async function getKuaishouCloudClaimDetail'),
src.indexOf('export async function submitClaimUid'),
)
assert.ok(detail.includes('flow.mock?.enabled'))
assert.ok(detail.includes('isAffiliateDashSnapshotFresh(flow.lastSyncedAt'))
assert.ok(detail.includes('bindFlow.lastBindSyncedAt'))
assert.ok(
!detail.includes('snapshotOnly'),
'新鲜快照必须直接不调用同步;snapshotOnly 仍会 updateTask',
)
const refresh = src.slice(
src.indexOf('async function refreshAffiliateDashBindState'),
src.indexOf('function normalizeUid'),
)
assert.ok(
refresh.includes('lastBindSyncedAt: now'),
'成功拉取绑定结果后才记时间,失败不能挡住下一次',
)
})
test('shouldRefreshAffiliateDashBindStateForSnapshot keeps polling before submit', () => {
assert.equal(
shouldRefreshAffiliateDashBindStateForSnapshot({
taskStatus: 'waiting_binding',
orderStatus: 'paid',
submitStatus: '',
}),
true,
)
})
test('shouldRefreshAffiliateDashBindStateForSnapshot stops after submit starts', () => {
assert.equal(
shouldRefreshAffiliateDashBindStateForSnapshot({
taskStatus: 'redeeming',
orderStatus: 'delivering',
submitStatus: 'delivering',
}),
false,
)
})
test('shouldRefreshAffiliateDashBindStateForSnapshot stops after delivered', () => {
assert.equal(
shouldRefreshAffiliateDashBindStateForSnapshot({
taskStatus: 'redeemed',
orderStatus: 'delivered',
submitStatus: 'delivered',
}),
false,
)
})
test('shouldRefreshAffiliateDashBindStateForSnapshot stops for failed platform result', () => {
assert.equal(
shouldRefreshAffiliateDashBindStateForSnapshot({
taskStatus: 'retry_pending',
orderStatus: 'ship_failed',
submitStatus: '',
}),
false,
)
})