Files
juzi/rednote/test/config.test.cjs
T

52 lines
3.9 KiB
JavaScript

'use strict';
const { test } = require('node:test'), assert = require('node:assert/strict'), path = require('node:path');
const config = require('../../h5/lib/entry-config');
test('rednote rejects missing, shared data paths and wrong public prefixes before initializing storage', () => {
const root = path.resolve(__dirname, '../../h5');
assert.equal(config({}, root).mode, 'state');
const env = { JUZI_ENTRY_MODE: 'rednote', PUBLIC_BASE_URL: 'https://skin.example.test/rednote/' };
for (const dataRoot of [undefined, root, path.join(root, 'custom-data'), path.join(root, 'data'), path.join(root, 'data/subdir')]) {
assert.throws(() => config({ ...env, JUZI_DATA_ROOT: dataRoot }, root), /own JUZI_DATA_ROOT/);
}
assert.throws(() => config({ ...env, JUZI_DATA_ROOT: path.join(root, '../temp/rednote'), PUBLIC_BASE_URL: 'https://skin.example.test/state/' }, root), /rednote/);
assert.equal(config({ ...env, JUZI_DATA_ROOT: path.join(root, '../temp/rednote') }, root).channel, 'rednote');
assert.throws(() => config({ ...env, JUZI_DATA_ROOT: path.join(root, '../temp/original'), JUZI_PROTECTED_DATA_ROOT: path.join(root, '../temp/original') }, root), /own JUZI_DATA_ROOT/);
assert.throws(() => config({ ...env, JUZI_DATA_ROOT: path.join(root, '../temp/rednote'), NODE_ENV: 'production', PUBLIC_BASE_URL: 'http://skin.example.test/rednote/' }, root), /rednote/);
});
test('HTTPS browser cookies are secure and persistent, even when WeChat credentials exist', async () => {
const fs = require('node:fs'), os = require('node:os'), { Readable } = require('node:stream');
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'juzi-rednote-secure-'));
try {
const accounts = require('../../h5/lib/accounts')(dir, { JUZI_ENTRY_MODE: 'rednote', PUBLIC_BASE_URL: 'https://skin.example.test/rednote/', WECHAT_APP_ID: 'configured', WECHAT_APP_SECRET: 'fixture' });
assert.equal(accounts.wechatAvailable, false);
const headers = {};
const req = Readable.from([Buffer.from('{"consent":true}')]);
req.method = 'POST'; req.url = '/api/auth/browser'; req.headers = { host: 'skin.example.test', origin: 'https://skin.example.test' }; req.socket = { remoteAddress: '127.0.0.1' };
let response;
await accounts.route(req, { setHeader: (k, v) => { headers[k] = v; }, getHeader: k => headers[k], writeHead() {}, end: text => { response = JSON.parse(text); } }, '/api/auth/browser');
assert.match(headers['Set-Cookie'][0], /HttpOnly; SameSite=Lax; Max-Age=2592000; Secure$/);
assert.equal(response.user.kind, 'browser_persistent');
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
});
test('data-directory aliases cannot bypass protection of the original deployment', () => {
const fs = require('node:fs'), os = require('node:os');
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'juzi-rednote-path-'));
try {
const original = path.join(dir, 'original'), alias = path.join(dir, 'alias'); fs.mkdirSync(original);
fs.symlinkSync(original, alias, process.platform === 'win32' ? 'junction' : 'dir');
assert.throws(() => config({ JUZI_ENTRY_MODE: 'rednote', PUBLIC_BASE_URL: 'https://skin.example.test/rednote/',
JUZI_DATA_ROOT: path.join(alias, 'nested'), JUZI_PROTECTED_DATA_ROOT: original }, path.join(dir, 'h5')), /own JUZI_DATA_ROOT/);
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
});
test('new-channel provider requests serialize through body consumption and cap the queue', async () => {
let active = 0, peak = 0;
const gated = require('../../h5/lib/provider-gate')(async () => {
peak = Math.max(peak, ++active);
return { ok: true, status: 200, json: async () => { await new Promise(resolve => setTimeout(resolve, 10)); active--; return { ok: true }; } };
}, 2);
const a = gated('fixture'), b = gated('fixture');
await assert.rejects(gated('fixture'), /queue is full/);
assert.deepEqual(await (await a).json(), { ok: true }); await b;
assert.equal(peak, 1); assert.equal(active, 0);
});