Files
mini-viewer/server/test-db.js
T
2026-09-29 01:14:24 +08:00

108 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// MySQL 存储层自测:会往库里写几条 TEST- 开头的测试数据,跑完自动删掉
// 用法:node server/test-db.js(需要 config.js 里配好 db)
const assert = require('assert')
const store = require('./store.js')
const { getPool, settings } = require('./db.js')
const TEST_OPENID = 'oTestStoreUser'
async function main() {
if (store.backend !== 'mysql') {
throw new Error('现在走的是 JSONL 后端:请在 config.js 里配好 db(库名 + 账号)再跑这个自测')
}
await store.ready()
const outTradeNo = 'TEST' + Date.now()
const createdAt = Date.now()
try {
await store.saveOrder({
outTradeNo,
openid: TEST_OPENID,
productId: '10001',
env: 0,
amount: 3900,
status: 'created',
createdAt,
})
const created = await store.get(outTradeNo)
assert.strictEqual(created.openid, TEST_OPENID)
assert.strictEqual(created.amount, 3900)
assert.strictEqual(created.code, '', '刚下单时不该有激活码')
assert.strictEqual(created.createdAt, createdAt)
// 时间列要是可读的 DATETIME(不是时间戳),且毫秒能原样存取
const [columnTypes] = await getPool().query(
`SELECT DATA_TYPE FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'codes' AND COLUMN_NAME = 'created_at'`,
[settings.database]
)
assert.strictEqual(columnTypes[0].DATA_TYPE, 'datetime', '时间列应该是 DATETIME,不该是时间戳')
const delivered = await store.assignCode(outTradeNo, { wxOrderId: 'wx-test-1', paidFee: 3900 })
assert.ok(/^[0-9A-HJKMNP-TV-Z]{4}(-[0-9A-HJKMNP-TV-Z]{4}){3}$/.test(delivered.code), delivered.code)
assert.strictEqual(delivered.status, 'delivered')
// 幂等:同一单再发一次还是同一张码(唯一索引挡住)
const again = await store.assignCode(outTradeNo, {})
assert.strictEqual(again.code, delivered.code)
let mine = await store.listByOpenid(TEST_OPENID)
assert.deepStrictEqual(mine.map((o) => o.code), [delivered.code])
await store.markNotified(outTradeNo)
assert.strictEqual((await store.get(outTradeNo)).notified, true)
// 退款后码作废:从「我的」和待发货里都消失,但记录还在
await store.markRefunded(outTradeNo, 'R' + outTradeNo)
mine = await store.listByOpenid(TEST_OPENID)
assert.deepStrictEqual(mine, [], '退款后不该再出现在我的激活码里')
const [codeRows] = await getPool().query('SELECT status FROM codes WHERE out_trade_no = ?', [outTradeNo])
assert.strictEqual(codeRows[0].status, 'revoked')
// 价目表播种:至少有四个道具,价格和 MP 后台一致
const goods = await store.listGoods()
assert.ok(goods.length >= 4, 'goods 表应该有播种的价目表')
assert.strictEqual(goods.find((g) => g.productId === '10000').price, 9900)
assert.strictEqual(goods.find((g) => g.productId === '90001').price, 10)
// 文案配置表:默认值会播种进去,备注列告诉你在哪显示
const settings = await store.getSettings()
assert.strictEqual(settings['buy.title'], '选择套餐')
const [copyRows] = await getPool().query(`SELECT remark FROM settings WHERE cfg_key = 'buy.title'`)
assert.strictEqual(copyRows[0].remark, '开通页的大标题')
const stats = await store.stats()
assert.ok(stats.orders >= 1)
assert.ok(stats.users >= 1, '用户表应该有记录')
// 用户表:首次使用时间建一次就不该再被覆盖,管理员标志默认 0
const [userRows] = await getPool().query('SELECT * FROM users WHERE openid = ?', [TEST_OPENID])
assert.strictEqual(userRows.length, 1)
assert.strictEqual(userRows[0].is_admin, 0)
const firstSeen = userRows[0].created_at.getTime()
await store.touchUser(TEST_OPENID)
const [againUsers] = await getPool().query('SELECT created_at, last_seen_at FROM users WHERE openid = ?', [TEST_OPENID])
assert.strictEqual(againUsers[0].created_at.getTime(), firstSeen, '首次使用时间不该被覆盖')
assert.ok(againUsers[0].last_seen_at.getTime() >= firstSeen)
// 管理员标志从 users.is_admin 读
assert.strictEqual((await store.getUser(TEST_OPENID)).isAdmin, false)
await getPool().query('UPDATE users SET is_admin = 1 WHERE openid = ?', [TEST_OPENID])
assert.strictEqual((await store.getUser(TEST_OPENID)).isAdmin, true)
console.log(`数据库自测通过(当前库里 ${stats.orders} 笔单 / ${stats.codes} 个码 / ${stats.users} 个用户)`)
} finally {
// 收尾:把测试数据删掉,别脏了真库
await getPool().query('DELETE FROM codes WHERE out_trade_no = ?', [outTradeNo])
await getPool().query('DELETE FROM orders WHERE out_trade_no = ?', [outTradeNo])
await getPool().query('DELETE FROM users WHERE openid = ?', [TEST_OPENID])
await getPool().end()
}
}
main().catch((err) => {
console.error('数据库自测失败:', err.message)
process.exit(1)
})