318 lines
7.8 KiB
JavaScript
318 lines
7.8 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { bootstrapPortalAuthServices } from './portal-auth-services-bootstrap.mjs';
|
|
|
|
function createSetup(overrides = {}) {
|
|
const calls = [];
|
|
const pool = { id: 'pool' };
|
|
const planCatalogService = {
|
|
getPlan(planType) {
|
|
calls.push(['get-plan', planType]);
|
|
return { planType };
|
|
},
|
|
};
|
|
const userAuth = { id: 'user-auth' };
|
|
const sessionAccess = {
|
|
enabled: true,
|
|
id: 'session-access',
|
|
};
|
|
const wechatPayClient = {
|
|
enabled: true,
|
|
apiVersion: 'v3',
|
|
};
|
|
const wechatOAuthService = { enabled: true };
|
|
const rechargeService = { id: 'recharge' };
|
|
let subscriptionOptions;
|
|
let userAuthOptions;
|
|
let sessionAccessOptions;
|
|
let oauthArgs;
|
|
let rechargeArgs;
|
|
let userDataSpaceOptions;
|
|
|
|
const options = {
|
|
pool,
|
|
h5Root: '/app',
|
|
usersRoot: '/users',
|
|
env: {
|
|
H5_SIGNUP_BALANCE_CENTS: '750',
|
|
},
|
|
mindSearchConfigService: {
|
|
getEffectiveConfig() {
|
|
calls.push(['mind-search-config']);
|
|
return { enabled: true };
|
|
},
|
|
},
|
|
logger: {
|
|
log(message) {
|
|
calls.push(['log', message]);
|
|
},
|
|
},
|
|
async ensurePlanCatalogSchemaFn(receivedPool) {
|
|
assert.equal(receivedPool, pool);
|
|
calls.push(['plan-schema']);
|
|
},
|
|
createPlanCatalogServiceFn(receivedPool) {
|
|
assert.equal(receivedPool, pool);
|
|
calls.push(['plan-service']);
|
|
return planCatalogService;
|
|
},
|
|
createSubscriptionServiceFn(
|
|
receivedPool,
|
|
receivedOptions,
|
|
) {
|
|
assert.equal(receivedPool, pool);
|
|
calls.push(['subscription-service']);
|
|
subscriptionOptions = receivedOptions;
|
|
return { id: 'subscription' };
|
|
},
|
|
createUserAuthFn(receivedPool, receivedOptions) {
|
|
assert.equal(receivedPool, pool);
|
|
calls.push(['user-auth']);
|
|
userAuthOptions = receivedOptions;
|
|
return userAuth;
|
|
},
|
|
createUserDataSpaceServiceFn(receivedOptions) {
|
|
userDataSpaceOptions = receivedOptions;
|
|
return {
|
|
ensureReady() {
|
|
calls.push(['user-space-ready']);
|
|
return { ready: true };
|
|
},
|
|
};
|
|
},
|
|
createSessionAccessFn(receivedOptions) {
|
|
calls.push(['session-access']);
|
|
sessionAccessOptions = receivedOptions;
|
|
return sessionAccess;
|
|
},
|
|
isSessionBrokerEnabledFn() {
|
|
return true;
|
|
},
|
|
isSessionBrokerMetricsEnabledFn() {
|
|
return false;
|
|
},
|
|
resolveNormalizedRouterDecisionModeFn(receivedEnv) {
|
|
assert.equal(receivedEnv, options.env);
|
|
return 'off';
|
|
},
|
|
isSessionStreamReplayEnabledFn() {
|
|
return false;
|
|
},
|
|
loadWechatPayConfigFn() {
|
|
calls.push(['pay-config']);
|
|
return { merchantId: 'merchant' };
|
|
},
|
|
createWechatPayClientFn(config) {
|
|
calls.push(['pay-client', config]);
|
|
return wechatPayClient;
|
|
},
|
|
loadWechatOAuthConfigFn() {
|
|
calls.push(['oauth-config']);
|
|
return { appId: 'app-id' };
|
|
},
|
|
createWechatOAuthServiceFn(...args) {
|
|
calls.push(['oauth-service']);
|
|
oauthArgs = args;
|
|
return wechatOAuthService;
|
|
},
|
|
createRechargeServiceFn(...args) {
|
|
calls.push(['recharge-service']);
|
|
rechargeArgs = args;
|
|
return rechargeService;
|
|
},
|
|
...overrides,
|
|
};
|
|
|
|
return {
|
|
calls,
|
|
options,
|
|
pool,
|
|
planCatalogService,
|
|
userAuth,
|
|
sessionAccess,
|
|
wechatPayClient,
|
|
wechatOAuthService,
|
|
rechargeService,
|
|
getCaptured() {
|
|
return {
|
|
subscriptionOptions,
|
|
userAuthOptions,
|
|
sessionAccessOptions,
|
|
oauthArgs,
|
|
rechargeArgs,
|
|
userDataSpaceOptions,
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
test('requires the auth service bootstrap inputs', async () => {
|
|
await assert.rejects(
|
|
bootstrapPortalAuthServices(),
|
|
/requires pool, roots, and MindSearch config/,
|
|
);
|
|
});
|
|
|
|
test('preserves subscription, auth, and user-space wiring', async () => {
|
|
const setup = createSetup();
|
|
const result = await bootstrapPortalAuthServices(
|
|
setup.options,
|
|
);
|
|
let captured = setup.getCaptured();
|
|
|
|
assert.deepEqual(
|
|
setup.calls.slice(0, 4).map(([name]) => name),
|
|
[
|
|
'plan-schema',
|
|
'plan-service',
|
|
'subscription-service',
|
|
'user-auth',
|
|
],
|
|
);
|
|
assert.equal(
|
|
result.subscriptionService._planCatalogService,
|
|
setup.planCatalogService,
|
|
);
|
|
assert.deepEqual(
|
|
await captured.subscriptionOptions.getPlanAsync(
|
|
'pro',
|
|
),
|
|
{ planType: 'pro' },
|
|
);
|
|
assert.equal(captured.userAuthOptions.usersRoot, '/users');
|
|
assert.equal(captured.userAuthOptions.h5Root, '/app');
|
|
assert.equal(
|
|
captured.userAuthOptions.defaultSignupBalanceCents,
|
|
750,
|
|
);
|
|
assert.equal(
|
|
captured.userAuthOptions.subscriptionService,
|
|
result.subscriptionService,
|
|
);
|
|
assert.deepEqual(
|
|
captured.userAuthOptions.getMindSearchConfig(),
|
|
{ enabled: true },
|
|
);
|
|
assert.deepEqual(
|
|
await captured.userAuthOptions.provisionUserDataSpace({
|
|
userId: 'user-1',
|
|
workspaceRoot: '/workspace/user-1',
|
|
}),
|
|
{ ready: true },
|
|
);
|
|
captured = setup.getCaptured();
|
|
assert.deepEqual(captured.userDataSpaceOptions, {
|
|
workspaceRoot: '/workspace/user-1',
|
|
userId: 'user-1',
|
|
query: setup.pool,
|
|
});
|
|
assert.deepEqual(captured.sessionAccessOptions, {
|
|
userAuth: setup.userAuth,
|
|
enabled: true,
|
|
});
|
|
});
|
|
|
|
test('reports every enabled H5 session flag', async () => {
|
|
const setup = createSetup({
|
|
env: {
|
|
MEMIND_SSE_EVENT_TAXONOMY: ' TRUE ',
|
|
MEMIND_RUN_STREAM_REPLAY: 'yes',
|
|
MEMIND_H5_HTML_FINISH_GUARD: 'on',
|
|
},
|
|
isSessionBrokerMetricsEnabledFn: () => true,
|
|
resolveNormalizedRouterDecisionModeFn: () =>
|
|
'shadow',
|
|
isSessionStreamReplayEnabledFn: () => true,
|
|
});
|
|
|
|
const result = await bootstrapPortalAuthServices(
|
|
setup.options,
|
|
);
|
|
|
|
assert.deepEqual(result.h5SessionFlags, [
|
|
'MEMIND_SESSION_BROKER_ENABLED',
|
|
'MEMIND_SESSION_BROKER_METRICS',
|
|
'MEMIND_ROUTER_NORMALIZED_DECISION=shadow',
|
|
'MEMIND_SESSION_STREAM_REPLAY',
|
|
'MEMIND_SSE_EVENT_TAXONOMY',
|
|
'MEMIND_RUN_STREAM_REPLAY',
|
|
'MEMIND_H5_HTML_FINISH_GUARD',
|
|
]);
|
|
assert.ok(
|
|
setup.calls.some(
|
|
([kind, message]) =>
|
|
kind === 'log' &&
|
|
message ===
|
|
`[Portal] H5 session flags: ${result.h5SessionFlags.join(', ')}`,
|
|
),
|
|
);
|
|
});
|
|
|
|
test('preserves WeChat and recharge service wiring and logs', async () => {
|
|
const setup = createSetup();
|
|
const result = await bootstrapPortalAuthServices(
|
|
setup.options,
|
|
);
|
|
const captured = setup.getCaptured();
|
|
|
|
assert.deepEqual(captured.oauthArgs, [
|
|
setup.pool,
|
|
{ appId: 'app-id' },
|
|
{ userAuth: setup.userAuth },
|
|
]);
|
|
assert.deepEqual(captured.rechargeArgs, [
|
|
setup.pool,
|
|
{
|
|
userAuth: setup.userAuth,
|
|
wechatPay: setup.wechatPayClient,
|
|
},
|
|
]);
|
|
assert.equal(
|
|
result.wechatOAuthService,
|
|
setup.wechatOAuthService,
|
|
);
|
|
assert.equal(result.rechargeService, setup.rechargeService);
|
|
assert.ok(
|
|
setup.calls.some(
|
|
([kind, message]) =>
|
|
kind === 'log' &&
|
|
message === 'WeChat Pay recharge enabled (v3)',
|
|
),
|
|
);
|
|
assert.ok(
|
|
setup.calls.some(
|
|
([kind, message]) =>
|
|
kind === 'log' &&
|
|
message === 'WeChat OAuth login enabled',
|
|
),
|
|
);
|
|
});
|
|
|
|
test('keeps disabled integrations quiet and uses the balance default', async () => {
|
|
const setup = createSetup({
|
|
env: {},
|
|
createSessionAccessFn: () => ({ enabled: false }),
|
|
isSessionBrokerEnabledFn: () => false,
|
|
createWechatPayClientFn: () => ({ enabled: false }),
|
|
createWechatOAuthServiceFn: () => ({
|
|
enabled: false,
|
|
}),
|
|
});
|
|
|
|
const result = await bootstrapPortalAuthServices(
|
|
setup.options,
|
|
);
|
|
const captured = setup.getCaptured();
|
|
|
|
assert.equal(
|
|
captured.userAuthOptions.defaultSignupBalanceCents,
|
|
500,
|
|
);
|
|
assert.deepEqual(result.h5SessionFlags, []);
|
|
assert.deepEqual(
|
|
setup.calls.filter(([kind]) => kind === 'log'),
|
|
[],
|
|
);
|
|
}
|
|
);
|