release: prepare 0629001 portal updates
This commit is contained in:
@@ -3,6 +3,7 @@ import { describe, it } from 'node:test';
|
||||
import {
|
||||
PLAN_CATALOG,
|
||||
createSubscriptionService,
|
||||
ensurePlanCatalogSchema,
|
||||
getPlanDef,
|
||||
tokensToCallsApprox,
|
||||
} from './billing-subscription.mjs';
|
||||
@@ -20,6 +21,12 @@ describe('PLAN_CATALOG', () => {
|
||||
assert.equal(PLAN_CATALOG.free.priceCents, 0);
|
||||
});
|
||||
|
||||
it('uses expanded token allowance defaults', () => {
|
||||
assert.equal(PLAN_CATALOG.free.periodTokens, 450_000);
|
||||
assert.equal(PLAN_CATALOG.lite.periodTokens, 3_600_000);
|
||||
assert.equal(PLAN_CATALOG.standard.periodTokens, 13_500_000);
|
||||
});
|
||||
|
||||
it('pro plan has unlimited tokens (0)', () => {
|
||||
assert.equal(PLAN_CATALOG.pro.periodTokens, 0);
|
||||
});
|
||||
@@ -47,8 +54,31 @@ describe('tokensToCallsApprox', () => {
|
||||
});
|
||||
|
||||
it('calculates approximate calls', () => {
|
||||
assert.equal(tokensToCallsApprox(150_000), 50); // free ~50 calls
|
||||
assert.equal(tokensToCallsApprox(1_200_000), 400); // lite ~400 calls
|
||||
assert.equal(tokensToCallsApprox(450_000), 150); // free ~150 calls
|
||||
assert.equal(tokensToCallsApprox(3_600_000), 1200); // lite ~1200 calls
|
||||
});
|
||||
});
|
||||
|
||||
describe('ensurePlanCatalogSchema', () => {
|
||||
it('expands legacy default token allowances without overwriting custom values', async () => {
|
||||
const queries = [];
|
||||
const pool = {
|
||||
async query(sql, params = []) {
|
||||
queries.push({ sql, params });
|
||||
if (sql.includes('COUNT(*) AS cnt')) return [[{ cnt: 1 }]];
|
||||
return [{ affectedRows: 1 }];
|
||||
},
|
||||
};
|
||||
|
||||
await ensurePlanCatalogSchema(pool);
|
||||
|
||||
const planUpdates = queries.filter(({ sql }) => sql.includes('UPDATE h5_plan_catalog'));
|
||||
const subUpdates = queries.filter(({ sql }) => sql.includes('UPDATE h5_subscriptions'));
|
||||
|
||||
assert.ok(planUpdates.some(({ params }) => params[0] === 450_000 && params[2] === 'free' && params[3] === 150_000));
|
||||
assert.ok(planUpdates.some(({ params }) => params[0] === 3_600_000 && params[2] === 'lite' && params[3] === 1_200_000));
|
||||
assert.ok(planUpdates.some(({ params }) => params[0] === 13_500_000 && params[2] === 'standard' && params[3] === 4_500_000));
|
||||
assert.equal(subUpdates.length, 3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -210,4 +240,61 @@ describe('createSubscriptionService', () => {
|
||||
assert.match(result.message, /未知套餐/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('processAutoRenewals', () => {
|
||||
it('uses DB-backed plan definitions for renewed subscriptions', async () => {
|
||||
const expiredSub = makeSubRow({
|
||||
plan_type: 'lite',
|
||||
auto_renew: 1,
|
||||
expires_at: Date.now() - 1000,
|
||||
balance_cents: 9999,
|
||||
});
|
||||
const conn = {
|
||||
queries: [],
|
||||
async query(sql, params) {
|
||||
this.queries.push({ sql, params });
|
||||
if (sql.includes('SELECT balance_cents')) return [[{ balance_cents: 9999 }]];
|
||||
return [{ affectedRows: 1 }];
|
||||
},
|
||||
async beginTransaction() {},
|
||||
async commit() {},
|
||||
async rollback() {},
|
||||
release() {},
|
||||
};
|
||||
const pool = {
|
||||
async query(sql) {
|
||||
if (sql.includes('FROM h5_subscriptions s')) return [[expiredSub]];
|
||||
return [[]];
|
||||
},
|
||||
async getConnection() { return conn; },
|
||||
};
|
||||
const svc = createSubscriptionService(pool, {
|
||||
getPlanAsync: async (planType) => planType === 'lite'
|
||||
? {
|
||||
name: '轻量版',
|
||||
priceCents: 990,
|
||||
periodTokens: 9_999_000,
|
||||
periodImages: 50,
|
||||
modelTier: 'basic',
|
||||
overageRate: 0.45,
|
||||
periodDays: 30,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
|
||||
const originalLog = console.log;
|
||||
console.log = () => {};
|
||||
try {
|
||||
const result = await svc.processAutoRenewals();
|
||||
assert.equal(result.renewed, 1);
|
||||
} finally {
|
||||
console.log = originalLog;
|
||||
}
|
||||
|
||||
const insert = conn.queries.find(({ sql }) => sql.includes('INSERT INTO h5_subscriptions'));
|
||||
assert.ok(insert);
|
||||
assert.equal(insert.params[3], 9_999_000);
|
||||
assert.equal(insert.params[8], 0.45);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user