feat(mindspace): add SEO/GEO delivery, page template catalog, and admin hooks
Memind CI / Test, build, and release guards (push) Has been cancelled
Memind CI / Test, build, and release guards (push) Has been cancelled
Enable optional SEO/GEO injection and discovery routes for confirmed public pages while keeping private pages noindex. Add premium page template skills, portal catalog API, template shop UI, and Baidu push gated by memind_adm config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
buildInsufficientBalancePayload,
|
||||
createRechargeService,
|
||||
isAllowedRechargeAmount,
|
||||
loadRechargeConfig,
|
||||
} from './billing-recharge.mjs';
|
||||
@@ -32,3 +33,83 @@ test('buildInsufficientBalancePayload includes recharge hints', () => {
|
||||
assert.equal(payload.balanceCents, 0);
|
||||
assert.deepEqual(payload.suggestedTiers, [500, 1000]);
|
||||
});
|
||||
|
||||
test('fulfillOrder routes template_purchase to template catalog service', async () => {
|
||||
const orderRow = {
|
||||
id: 'order-tpl-1',
|
||||
user_id: 'user-1',
|
||||
amount_cents: 990,
|
||||
channel: 'wechat',
|
||||
status: 'pending',
|
||||
pay_mode: 'native',
|
||||
out_trade_no: 'TPTEST001',
|
||||
provider_txn: null,
|
||||
paid_at: null,
|
||||
expire_at: Date.now() + 60_000,
|
||||
created_at: Date.now(),
|
||||
code_url: null,
|
||||
h5_url: null,
|
||||
order_purpose: 'template_purchase',
|
||||
order_purpose_ref: 'page-template-travel',
|
||||
};
|
||||
const pool = {
|
||||
async getConnection() {
|
||||
const conn = {
|
||||
async beginTransaction() {},
|
||||
async commit() {},
|
||||
async rollback() {},
|
||||
async release() {},
|
||||
async query(sql, params = []) {
|
||||
const text = String(sql);
|
||||
if (text.includes('FROM h5_payment_orders WHERE id = ? FOR UPDATE')) {
|
||||
return [[orderRow], []];
|
||||
}
|
||||
if (text.includes('UPDATE h5_payment_orders') && text.includes("status = 'paid'")) {
|
||||
orderRow.status = 'paid';
|
||||
return [{ affectedRows: 1 }, []];
|
||||
}
|
||||
throw new Error(`Unhandled SQL: ${text.slice(0, 100)}`);
|
||||
},
|
||||
};
|
||||
return conn;
|
||||
},
|
||||
};
|
||||
let templateFulfillArgs = null;
|
||||
const templateCatalogService = {
|
||||
async fulfillWechatPurchaseLocked(args) {
|
||||
templateFulfillArgs = args;
|
||||
return {
|
||||
ok: true,
|
||||
skillName: 'page-template-travel',
|
||||
grantedSkills: ['page-template-travel'],
|
||||
balanceCents: 1200,
|
||||
};
|
||||
},
|
||||
};
|
||||
const userAuth = {
|
||||
async getUserById(userId) {
|
||||
return { id: userId, balance_cents: 1200 };
|
||||
},
|
||||
async recharge() {
|
||||
throw new Error('recharge should not run for template_purchase');
|
||||
},
|
||||
};
|
||||
const service = createRechargeService(pool, { userAuth, templateCatalogService });
|
||||
const result = await service.fulfillOrder(
|
||||
{
|
||||
id: orderRow.id,
|
||||
userId: orderRow.user_id,
|
||||
amountCents: orderRow.amount_cents,
|
||||
status: 'pending',
|
||||
orderPurpose: 'template_purchase',
|
||||
orderPurposeRef: 'page-template-travel',
|
||||
},
|
||||
{ trade_state: 'SUCCESS', amount: { total: 990 }, transaction_id: 'wx-txn-1' },
|
||||
);
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.skillName, 'page-template-travel');
|
||||
assert.deepEqual(result.grantedSkills, ['page-template-travel']);
|
||||
assert.equal(result.balanceCents, 1200);
|
||||
assert.ok(templateFulfillArgs);
|
||||
assert.equal(orderRow.status, 'paid');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user