初始化提交:go比特版本精简
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'refund-deadline-'));
|
||||
const Config = require('../src/core/config');
|
||||
Config.DATA_DIR = tempDir;
|
||||
Config.DB_PATH = path.join(tempDir, 'accounts.db');
|
||||
const database = require('../src/core/database');
|
||||
const {
|
||||
runRefundDeadlineCheck,
|
||||
deliverRefundDeadlineReport,
|
||||
_private,
|
||||
} = require('../src/services/refund_deadline_service');
|
||||
const deadlineSchedulerPrivate = require('../src/services/refund_deadline_scheduler')._private;
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
database.initDB();
|
||||
const columns = database.getDb().pragma('table_info(accounts)').map(row => row.name);
|
||||
assert(columns.includes('refund_deadline_at'));
|
||||
|
||||
const now = new Date('2026-08-26T08:00:00.000Z');
|
||||
const accounts = ['due@example.com', 'future@example.com', 'refunded@example.com', 'started@example.com'];
|
||||
for (const email of accounts) {
|
||||
database.upsertAccount({ email, password: `p-${email}`, recovery_email: `r-${email}`, secret_key: 'secret', status: '已充值提取' });
|
||||
database.updateAccountChatgptResult(email, '已登录', JSON.stringify({ accessToken: `session-${email}` }));
|
||||
}
|
||||
database.updateAccountRefundDeadline('due@example.com', '2026-08-26T07:59:00.000Z');
|
||||
database.updateAccountRefundDeadline('future@example.com', '2026-08-27T08:00:00.000Z');
|
||||
database.updateAccountRefundDeadline('refunded@example.com', '2026-08-26T07:59:00.000Z');
|
||||
database.updateAccountRefundDeadline('started@example.com', '2026-08-26T07:59:00.000Z');
|
||||
database.updateAccountRefundStatus('refunded@example.com', '已退款');
|
||||
database.updateAccountRefundProcessStatus('started@example.com', '已发起');
|
||||
|
||||
assert.deepStrictEqual(database.getDueRefundDeadlineAccounts(now).map(row => row.email), ['due@example.com']);
|
||||
const calls = [];
|
||||
let syncedRefundEntries = null;
|
||||
const result = await runRefundDeadlineCheck({
|
||||
database,
|
||||
now,
|
||||
loadRefundCredentials: async () => ({ accessToken: 'owner-token', proxies: ['socks5://proxy:1080'] }),
|
||||
executeRefund: async payload => {
|
||||
calls.push(payload.expectedEmail);
|
||||
return { success: true, cleanupOk: true };
|
||||
},
|
||||
syncRefundStatuses: async payload => {
|
||||
syncedRefundEntries = payload.entries.map(item => ({
|
||||
email: item.email,
|
||||
status: item.refundProcessStatus,
|
||||
result: item.refundResult,
|
||||
}));
|
||||
return { success: true, updatedCount: payload.entries.length, skippedCount: 0 };
|
||||
},
|
||||
delay: async () => {},
|
||||
});
|
||||
assert.strictEqual(result.dueCount, 1);
|
||||
assert.strictEqual(result.refundAttemptedCount, 1);
|
||||
assert.strictEqual(result.refundSuccessCount, 1);
|
||||
assert.deepStrictEqual(calls, ['due@example.com']);
|
||||
assert.deepStrictEqual(syncedRefundEntries, [
|
||||
{ email: 'due@example.com', status: '已发起', result: '成功' },
|
||||
], '截止时间退款结束后应只回写本轮已处理账号的退款流程状态');
|
||||
assert.strictEqual(database.getAccount('due@example.com').refund_process_status, '已发起');
|
||||
assert.strictEqual(database.getAccount('due@example.com').account_refund_status, '无状态');
|
||||
assert.match(result.text, /到期 1|提交 1|成功 1/);
|
||||
assert.strictEqual(result.files.length, 1);
|
||||
const csv = result.files[0].content.toString('utf8');
|
||||
assert(csv.includes('"未查询(截止时间触发)"'));
|
||||
assert(csv.includes('"due@example.com"'));
|
||||
|
||||
let delivered = null;
|
||||
await deliverRefundDeadlineReport(result, {
|
||||
database,
|
||||
sendReport: async payload => { delivered = payload; return { success: true }; },
|
||||
});
|
||||
assert(delivered);
|
||||
assert.strictEqual(delivered.files.length, 1);
|
||||
assert.strictEqual(_private.resultSignature(result.results), result.signature);
|
||||
|
||||
database.updateAccountsRefundDeadline(['future@example.com'], null);
|
||||
assert.strictEqual(database.getAccount('future@example.com').refund_deadline_at, null);
|
||||
|
||||
for (const email of ['offset-a@example.com', 'offset-b@example.com', 'offset-missing@example.com']) {
|
||||
database.upsertAccount({ email, status: '已充值提取' });
|
||||
}
|
||||
database.getDb().prepare('UPDATE accounts SET recharged_at = ? WHERE email = ?')
|
||||
.run('2026-08-26 01:00:00', 'offset-a@example.com');
|
||||
database.getDb().prepare('UPDATE accounts SET recharged_at = ? WHERE email = ?')
|
||||
.run('2026-08-26 03:30:00', 'offset-b@example.com');
|
||||
const offsetResult = database.updateAccountsRefundDeadlineFromRecharge([
|
||||
'offset-a@example.com', 'offset-b@example.com', 'offset-missing@example.com',
|
||||
], 90 * 60 * 1000);
|
||||
assert.strictEqual(offsetResult.count, 2);
|
||||
assert.strictEqual(offsetResult.skippedCount, 1);
|
||||
assert.strictEqual(database.getAccount('offset-a@example.com').refund_deadline_at, '2026-08-26T02:30:00.000Z');
|
||||
assert.strictEqual(database.getAccount('offset-b@example.com').refund_deadline_at, '2026-08-26T05:00:00.000Z');
|
||||
assert.strictEqual(database.getAccount('offset-missing@example.com').refund_deadline_at, null);
|
||||
|
||||
const intervalDb = {
|
||||
getSetting(key, fallback) {
|
||||
return key === 'refund_deadline_check_interval_seconds' ? '45' : fallback;
|
||||
},
|
||||
};
|
||||
assert.strictEqual(deadlineSchedulerPrivate.readIntervalSeconds(intervalDb), 45);
|
||||
assert.strictEqual(deadlineSchedulerPrivate.readIntervalSeconds({ getSetting: () => '1' }), 5);
|
||||
assert.strictEqual(deadlineSchedulerPrivate.readIntervalSeconds({ getSetting: () => '99999' }), 3600);
|
||||
|
||||
const root = path.join(__dirname, '..');
|
||||
const html = fs.readFileSync(path.join(root, 'public', 'index.html'), 'utf8');
|
||||
const app = fs.readFileSync(path.join(root, 'public', 'app.js'), 'utf8');
|
||||
const server = fs.readFileSync(path.join(root, 'server.js'), 'utf8');
|
||||
const accountRoutes = fs.readFileSync(path.join(root, 'src', 'routes', 'accounts.js'), 'utf8');
|
||||
assert.match(html, /退款截止时间/);
|
||||
assert.match(html, /截止检查间隔(秒)/);
|
||||
assert.match(html, /额度达到阈值或截止时间到达/);
|
||||
assert.match(html, /按每个账号的充值时间计算/);
|
||||
assert.match(html, /\+30分钟/);
|
||||
assert.match(html, /\+1天/);
|
||||
assert.match(html, /settings-select refund-deadline-unit-select/);
|
||||
assert.match(app, /\/api\/accounts\/batch\/refund-deadline/);
|
||||
assert.match(app, /mode:\s*'recharge_offset'/);
|
||||
assert.match(accountRoutes, /updateAccountsRefundDeadlineFromRecharge/);
|
||||
assert.match(server, /refund_deadline_scheduler/);
|
||||
|
||||
console.log('refund_deadline.test.js: PASS');
|
||||
} finally {
|
||||
try { database.getDb().close(); } catch (_) {}
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
})().catch(error => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user