Files
order_site/apps/backend/scripts/order-service-smoke.ts
T

282 lines
8.9 KiB
TypeScript

import assert from 'node:assert/strict'
import process from 'node:process'
import { closeDb, query } from '../src/db/client.js'
import { WORK_ORDER_STATUS } from '../src/domain/work-order-status.js'
import { createWorkOrder } from '../src/repositories/worker-platform/work-order-management-repo.js'
import type { WorkOrderRow } from '../src/repositories/worker-platform/types.js'
import {
publishAdminOrderServiceProfile,
saveAdminOrderServiceProfile,
type OrderServiceProfileConfig,
} from '../src/services/worker-platform/order-service-profile-service.js'
import {
getOrderServiceByPlatformOrderId,
submitOrderServiceMaterial,
} from '../src/services/worker-platform/order-service-public-service.js'
import { processDueOrderServiceAutoPublishJobs } from '../src/services/worker-platform/order-service-auto-publish-service.js'
import { randomId } from '../src/utils/random.js'
import { nowIso } from '../src/utils/time.js'
if (process.env.ORDER_SERVICE_SMOKE !== '1') {
throw new Error('请显式设置 ORDER_SERVICE_SMOKE=1 后运行;该脚本只用于本地测试库')
}
const categoryId = Number(process.env.ORDER_SERVICE_SMOKE_CATEGORY_ID || 1)
const platformOrderId = `SMOKE-${Date.now()}`
let workOrder: WorkOrderRow | null = null
let originalProfile: {
id: number
name: string
title: string
description: string
guideImage: Record<string, unknown>
fields: OrderServiceProfileConfig['fields']
screenshots: OrderServiceProfileConfig['screenshots']
autoPublish: OrderServiceProfileConfig['autoPublish']
submitText: string
successText: string
} | null = null
try {
const profileResult = await query<{
id: number
name: string
title: string
description: string
guide_image_json: Record<string, unknown>
fields_json: OrderServiceProfileConfig['fields']
screenshots_json: Record<string, unknown>
auto_publish_json: Record<string, unknown>
submit_text: string
success_text: string
current_version_id: number
}>(
`
SELECT p.*
FROM order_service_profiles p
WHERE p.category_id = $1
AND p.current_version_id IS NOT NULL
LIMIT 1
`,
[categoryId],
)
const profile = profileResult.rows[0]
assert.ok(profile, '测试分类缺少已发布订单服务配置')
originalProfile = {
id: Number(profile.id),
name: profile.name,
title: profile.title,
description: profile.description,
guideImage: profile.guide_image_json,
fields: profile.fields_json,
screenshots: profile.screenshots_json as OrderServiceProfileConfig['screenshots'],
autoPublish: profile.auto_publish_json as OrderServiceProfileConfig['autoPublish'],
submitText: profile.submit_text,
successText: profile.success_text,
}
const smokeFields: OrderServiceProfileConfig['fields'] = [
{
key: 'account',
label: '游戏账号',
type: 'text',
required: true,
placeholder: '请输入账号',
helpText: '',
options: [],
sortOrder: 10,
},
]
const saved = await saveAdminOrderServiceProfile({
categoryId,
name: '本地订单服务烟测',
title: '本地订单服务烟测',
description: '测试完成后自动恢复',
guideImage: {},
fields: smokeFields,
screenshots: {
enabled: false,
required: false,
minCount: 0,
maxCount: 3,
label: '截图',
helpText: '',
},
autoPublish: {
enabled: true,
requireVoucherConsume: true,
retryMax: 1,
},
submitText: '提交烟测资料',
successText: '烟测资料已提交',
})
const draftStatus = await query<{ status: string }>(
`SELECT status FROM order_service_profiles WHERE id = $1`,
[saved.profile.id],
)
assert.equal(draftStatus.rows[0]?.status, 'draft')
const stillPublished = await getPublishedProfile(categoryId)
assert.equal(stillPublished.title, originalProfile.title)
const published = await publishAdminOrderServiceProfile(saved.profile.id)
const publishedConfig = await getPublishedProfile(categoryId)
assert.equal(publishedConfig.title, '本地订单服务烟测')
workOrder = await createWorkOrder({
workOrderNo: `WKSMOKE${Date.now()}`,
platformOrderId,
productName: '订单服务烟测商品',
categoryId,
status: WORK_ORDER_STATUS.PENDING_MATERIAL,
rewardAmount: 100,
requiredDepositAmount: 0,
depositThresholdAmount: 0,
sharingEnabled: false,
sharingTotalQuantity: 1,
sharingUnitReward: 0,
timeoutMinutes: 30,
timeoutPolicy: 'reopen',
acceptanceMode: 'standard',
materialJson: JSON.stringify({ source: { smoke: true } }),
requirementJson: JSON.stringify({ fields: smokeFields }),
serviceProfileId: saved.profile.id,
serviceProfileVersionId: published.versionId,
serviceProfileSnapshotJson: JSON.stringify({
profileId: saved.profile.id,
categoryId,
versionId: published.versionId,
versionNo: published.versionNo,
config: publishedConfig,
}),
now: nowIso(),
})
assert.ok(workOrder, '创建烟测工单失败')
const publicInfo = await getOrderServiceByPlatformOrderId(platformOrderId)
assert.equal(publicInfo.items[0]?.title, '本地订单服务烟测')
assert.equal(publicInfo.items[0]?.canSubmit, true)
await saveAdminOrderServiceProfile({
categoryId,
name: '未发布修改',
title: '未发布修改不应泄漏',
description: 'draft-only',
guideImage: {},
fields: smokeFields,
screenshots: {
enabled: false,
required: false,
minCount: 0,
maxCount: 3,
label: '截图',
helpText: '',
},
autoPublish: {
enabled: true,
requireVoucherConsume: true,
retryMax: 1,
},
submitText: '不应泄漏',
successText: '不应泄漏',
})
const afterDraftEdit = await getOrderServiceByPlatformOrderId(platformOrderId)
assert.equal(afterDraftEdit.items[0]?.title, '本地订单服务烟测')
await submitOrderServiceMaterial(platformOrderId, {
workOrderId: workOrder.id,
fields: { account: 'smoke-account' },
screenshots: [],
})
await assert.rejects(() =>
submitOrderServiceMaterial(platformOrderId, {
workOrderId: workOrder?.id,
fields: { account: 'changed' },
screenshots: [],
}),
)
await waitForAutoPublishJob(workOrder.id)
const afterPublish = await getOrderServiceByPlatformOrderId(platformOrderId)
assert.equal(afterPublish.items[0]?.state, WORK_ORDER_STATUS.OPEN)
assert.match(afterPublish.items[0]?.message || '', /高峰期/)
const job = await query<{ status: string; attempt_count: number }>(
`SELECT status, attempt_count FROM order_service_auto_publish_jobs WHERE work_order_id = $1`,
[workOrder.id],
)
assert.equal(job.rows[0]?.status, 'succeeded')
console.log(
JSON.stringify(
{
ok: true,
categoryId,
profileId: saved.profile.id,
versionNo: published.versionNo,
platformOrderId,
finalStatus: afterPublish.items[0]?.state,
finalMessage: afterPublish.items[0]?.message,
},
null,
2,
),
)
} finally {
if (workOrder) {
await query('DELETE FROM work_orders WHERE id = $1', [workOrder.id]).catch(() => undefined)
}
if (originalProfile) {
const restored = await saveAdminOrderServiceProfile({
categoryId,
name: originalProfile.name,
title: originalProfile.title,
description: originalProfile.description,
guideImage: originalProfile.guideImage,
fields: originalProfile.fields,
screenshots: originalProfile.screenshots,
autoPublish: originalProfile.autoPublish,
submitText: originalProfile.submitText,
successText: originalProfile.successText,
}).catch(() => null)
if (restored) {
await publishAdminOrderServiceProfile(restored.profile.id).catch(() => undefined)
}
}
await closeDb()
}
async function getPublishedProfile(categoryIdValue: number) {
const result = await query<{ config_json: OrderServiceProfileConfig }>(
`
SELECT v.config_json
FROM order_service_profiles p
JOIN order_service_profile_versions v ON v.id = p.current_version_id
WHERE p.category_id = $1
LIMIT 1
`,
[categoryIdValue],
)
const config = result.rows[0]?.config_json
assert.ok(config, '未找到已发布订单服务配置')
return config
}
async function waitForAutoPublishJob(workOrderId: number) {
const deadline = Date.now() + 5_000
while (Date.now() < deadline) {
await Promise.all([
processDueOrderServiceAutoPublishJobs(10),
processDueOrderServiceAutoPublishJobs(10),
])
const result = await query<{ status: string }>(
`SELECT status FROM order_service_auto_publish_jobs WHERE work_order_id = $1`,
[workOrderId],
)
const status = result.rows[0]?.status
if (status === 'succeeded' || status === 'failed' || status === 'skipped') return
await new Promise((resolve) => setTimeout(resolve, 100))
}
throw new Error('自动发布任务在 5 秒内未结束')
}