282 lines
8.9 KiB
TypeScript
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 秒内未结束')
|
|
}
|