function id(value) { return value == null ? '' : String(value) } function validRelease(row) { return row && typeof row === 'object' && ['domestic', 'overseas'].includes(row.app) && ['apk', 'wgt'].includes(row.packageType) && typeof row.versionName === 'string' && row.versionName.length > 0 && Number.isSafeInteger(Number(row.versionCode)) && ['DRAFT', 'PUBLISHED', 'WITHDRAWN'].includes(row.status) && typeof row.current === 'boolean' && /^[a-f0-9]{64}$/i.test(String(row.sha256 || '')) && Number.isSafeInteger(Number(row.sizeBytes)) && Number(row.sizeBytes) > 0 } export async function run(context) { const module = 'pda-releases' const base = '/api/platform/v1/files/pda-releases' for (const app of ['domestic', 'overseas']) { const response = await context.request('GET', `${base}/${app}`) const releases = context.apiSuccess(module, `查询 ${app} PDA 发布列表`, response) context.assert(module, `${app} 发布列表结构与版本字段完整`, response, Array.isArray(releases) && releases.every(validRelease), `count=${Array.isArray(releases) ? releases.length : 'not-array'}`) const currentCount = Array.isArray(releases) ? releases.filter((row) => row.current === true).length : -1 context.assert(module, `${app} 当前生效版本不超过一个发布类型`, response, currentCount <= 2, `current=${currentCount}`) } const emptyUpload = await context.requestMultipart('POST', `${base}/domestic`, new FormData()) context.assert(module, '无安装包的上传被拒绝', emptyUpload, emptyUpload.http >= 400 || String(emptyUpload.body?.code) !== '200', `HTTP=${emptyUpload.http},code=${emptyUpload.body?.code ?? 'missing'}`) const missingId = '999999999999999' for (const action of ['publish', 'withdraw']) { const response = await context.request('POST', `${base}/${missingId}/${action}`, {}) context.assert(module, `不存在版本 ${action} 被拒绝`, response, response.http === 200 && ['A0403', 'A0404', 'A0409'].includes(String(response.body?.code)), `HTTP=${response.http},code=${response.body?.code ?? 'missing'}`) } context.addCoverageGap(module, 'pda-releases', '真实 APK/WGT 上传、发布、停发与下载', '脚本不上传真实安装包;需人工准备有效 domestic/overseas APK 或 WGT 后定向执行,避免伪造签名与版本号', 'not-implemented', { blocking: false }) }