Files
kra-new/scripts/sw_analytics_page_smoke.cjs
T

63 lines
5.6 KiB
JavaScript

// 真实 Chrome 核对统计筛选、排序、分页和全量汇总;业务接口使用受控数据。
const fs = require('node:fs/promises')
const path = require('node:path')
const assert = require('node:assert/strict')
const { chromium } = require(process.env.SW_PLAYWRIGHT_MODULE || 'playwright')
;(async () => {
const token = (await fs.readFile(path.join(process.env.TEMP, 'sw-kra-http-test-token'), 'utf8')).trim()
const browser = await chromium.launch({ channel: 'chrome', headless: true })
const reports = []
try {
for (const kind of ['channel', 'game']) {
const context = await browser.newContext({ viewport: { width: 1600, height: 1000 } })
await context.addInitScript(value => localStorage.setItem('token', value), token)
const page = await context.newPage(), queries = [], errors = []
let unavailable = false
const routeName = kind === 'channel' ? 'channelData' : 'gameData'
page.on('pageerror', error => errors.push(error.message))
await page.route('http://127.0.0.1:8080/api/**', async route => {
const request = route.request(), url = new URL(request.url()), api = url.pathname.slice(4)
if (api === `/sw/${routeName}/list`) {
queries.push(Object.fromEntries(url.searchParams))
const pageNum = Number(url.searchParams.get('pageNum') || 1)
const metrics = { newRegisterCount: 2, activeCount: 4, payUserCount: 1, newPayUserCount: 1, totalPay: '10.00', payRate: '25.00', arpu: '2.50', arppu: '10.00' }
const row = { ...metrics, sourceDb: 'lx', sourceDbLabel: '龙翔', promoteId: pageNum, promoteName: `测试渠道${pageNum}`, promoteType: 1, busierName: '游戏商务', gameId: pageNum, gameName: `测试游戏${pageNum}` }
const summary = { ...metrics, gameName: '全部游戏', promoteName: '全部渠道', newRegisterCount: 60, activeCount: 100, payUserCount: 20, newPayUserCount: 10, totalPay: '1000.00', payRate: '20.00', arpu: '10.00', arppu: '50.00' }
return route.fulfill({ json: { code: 0, data: { rows: unavailable ? [] : [row], total: unavailable ? 0 : 21, channelCount: unavailable ? null : 21, totalRegisterCount: unavailable ? null : 60, totalPayAmount: unavailable ? null : '1000.00', avgPayRate: unavailable ? null : '20.00', summary: unavailable ? null : summary, beginTime: url.searchParams.get('beginTime'), endTime: url.searchParams.get('endTime'), available: !unavailable } } })
}
if (api === '/sw/serverAnalysis/games') return route.fulfill({ json: { code: 0, data: [{ sourceDb: 'lx', gameId: 1, gameName: '筛选游戏' }] } })
const response = await route.fetch({ url: 'http://127.0.0.1:18000' + api + url.search, headers: { ...request.headers(), 'x-token': token } })
return route.fulfill({ response })
})
await page.goto(`http://127.0.0.1:8080/#/layout/sw-DataAnalysis/${kind === 'channel' ? 'ChannelDataStatistics' : 'GameAnalytics'}`)
await page.getByText(kind === 'channel' ? '测试渠道1' : '测试游戏1', { exact: true }).waitFor()
assert.equal((Date.parse(queries[0].endTime) - Date.parse(queries[0].beginTime)) / 86400000, 29)
const totals = kind === 'channel' ? page.locator('.report-cards') : page.locator('.el-table__footer-wrapper')
await totals.getByText('¥1,000.00', { exact: true }).waitFor()
assert.equal(await page.getByRole('button', { name: '导出', exact: true }).count(), 0)
await page.locator('.el-pagination .btn-next').click()
await page.getByText(kind === 'channel' ? '测试渠道2' : '测试游戏2', { exact: true }).waitFor()
assert.equal(queries.at(-1).pageNum, '2')
await totals.getByText('¥1,000.00', { exact: true }).waitFor()
const form = page.locator('.kra-search-box')
await form.locator('.el-form-item').filter({ has: page.locator('label').getByText('游戏', { exact: true }) }).locator('.el-select__wrapper').click()
await page.getByRole('option', { name: '筛选游戏', exact: true }).click(); await page.keyboard.press('Escape')
if (kind === 'channel') await form.getByPlaceholder('渠道账号(模糊匹配)', { exact: true }).fill('测试')
await Promise.all([page.waitForResponse(response => response.url().includes(`/sw/${routeName}/list`) && response.url().includes('gameName=')), form.getByRole('button', { name: kind === 'channel' ? '搜索' : '查询', exact: true }).click()])
assert.equal(queries.at(-1).pageNum, '1'); assert.equal(queries.at(-1).gameName, '筛选游戏')
if (kind === 'channel') assert.equal(queries.at(-1).promoteName, '测试')
await page.locator('.el-loading-mask').first().waitFor({ state: 'hidden' })
await page.screenshot({ path: path.join(process.env.TEMP, `sw-${kind}-analytics.png`), animations: 'disabled' })
unavailable = true
await form.getByRole('button', { name: kind === 'channel' ? '搜索' : '查询', exact: true }).click()
await page.getByText('统计所需业务汇总尚未接入。', { exact: true }).waitFor()
assert.equal(await totals.getByText('¥1,000.00', { exact: true }).count(), 0)
assert.deepEqual(errors, [])
const report = { kind, passed: true, fullSummaryAcrossPages: true, filtersResetPage: true, platformAndGameFilters: true, noInventedExport: true, missingDataNotZero: true, pageErrors: errors }
reports.push(report); console.log(JSON.stringify(report)); await context.close()
}
await fs.writeFile('docs/sw6-to-kra/analytics-page-2026-11-04.json', JSON.stringify({ method: '真实 Chrome 渲染,受控业务数据;未写入真实数据', reports }, null, 2) + '\n')
} finally { await browser.close() }
})().catch(error => { console.error(error); process.exitCode = 1 })