MatchMaster/server/laf-cloud/tests/login-ios-reborn.test.mjs

57 lines
3.0 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import { stripTypeScriptTypes } from 'node:module';
// Exercise the real login recovery function without contacting the payment provider.
const source = await readFile(new URL('../functions/login.ts', import.meta.url), 'utf8');
const recoverySource = source.slice(source.indexOf('async function getIosOrder('), source.indexOf('async function sead('));
const buildRecovery = new Function('db', 'getOrder', 'sead', 'getClientIp', 'JungleConfig', `return (${stripTypeScriptTypes(recoverySource)});`);
function fixture(itemid, extra = {}) {
const user = { _id: 'user-1', openid: 'openid-1', rebornGiftTime: 0, rebornGiftCount: 3, pay_user: false };
const order = { outTradeNo: 'order-1', openid: user.openid, state: 0, type: 'ios', itemid, ...extra };
const providerCalls = [];
const db = { collection(name) {
const documents = name === 'users' ? [user] : [order];
return { where(query) {
const matched = documents.filter(row => Object.entries(query).every(([key, value]) => row[key] === value));
return {
async get() { return { data: structuredClone(matched) }; },
async getOne() { return { data: structuredClone(matched[0]) }; },
async update(patch) { matched.forEach(row => Object.assign(row, patch)); },
async remove() { assert.fail('recoverable activity orders must not be deleted'); },
};
} };
} };
const recover = buildRecovery(db, async orderId => {
providerCalls.push(orderId);
return { trade_state: 'SUCCESS' };
}, () => {}, () => '', { getJunglePaidTierByProductId: () => null });
return { user, order, providerCalls, recover };
}
for (const itemid of ['reborn_Gift', 'reborn_Gift_2', 'reborn_Gift_3', 'reborn_Gift_4', 'reborn_Gift_5']) {
test(`login preserves main iOS recovery for ${itemid} until client confirms delivery`, async () => {
const { user, order, providerCalls, recover } = fixture(itemid);
const before = Date.now();
const pending = await recover(user.openid, {});
assert.equal(user.rebornGiftCount, 0);
assert(user.rebornGiftTime >= before);
assert.equal(user.pay_user, true);
assert.equal(order.state, 1, 'confirmed payment stays pending for client reward delivery');
assert.deepEqual(pending.map(row => row.outTradeNo), ['order-1']);
assert.deepEqual(providerCalls, ['order-1']);
assert.deepEqual(await recover(user.openid, {}), [], 'state=1 goes through ordinary login recovery next time');
assert.deepEqual(providerCalls, ['order-1'], 'no second provider query for confirmed payment');
});
}
test('disabled gold miner orders never enter legacy iOS recovery', async () => {
const { user, order, providerCalls, recover } = fixture('gold_miner', { goldMiner: { confirmedAt: 0 }, time: 1 });
assert.deepEqual(await recover(user.openid, {}), []);
assert.deepEqual(providerCalls, []);
assert.equal(order.state, 0);
assert.equal(user.rebornGiftCount, 3);
});