feat: 完成分类、worksheet 接口开发,资源迁移到七牛

This commit is contained in:
R524809
2026-10-16 17:32:23 +08:00
parent e6ded00a4c
commit 8827110f2f
107 changed files with 12775 additions and 125 deletions
+110 -1
View File
@@ -2,7 +2,13 @@ import assert from 'node:assert/strict';
import { test } from 'node:test';
import { getServerConfig } from '../src/config/server-config';
const env = { JWT_SECRET: 'test-configuration-secret-12345678901234567890' };
const env = {
JWT_SECRET: 'test-configuration-secret-12345678901234567890',
DATABASE_URL:
'postgresql://test:test@127.0.0.1:1/doodle_test?schema=public',
WECHAT_MINI_APP_ID: 'wx0123456789abcdef',
WECHAT_MINI_APP_SECRET: 'test-only-wechat-secret',
};
test('启动配置必须提供有效 JWT 密钥,不使用共享默认密钥', () => {
for (const secret of [
@@ -33,6 +39,82 @@ test('Swagger 开发默认开启,生产默认关闭,支持显式开关', ()
);
});
test('真实登录接入后微信配置必须完整,缺省或留空都拒绝启动', () => {
for (const entry of [
{ WECHAT_MINI_APP_ID: undefined, WECHAT_MINI_APP_SECRET: undefined },
{ WECHAT_MINI_APP_ID: '', WECHAT_MINI_APP_SECRET: '' },
{ WECHAT_MINI_APP_ID: ' ', WECHAT_MINI_APP_SECRET: '\t' },
]) {
assert.throws(
() => getServerConfig({ ...env, ...entry }),
/WECHAT_MINI_APP/,
);
}
});
test('成对读取微信配置并去除首尾空白', () => {
const config = getServerConfig({
...env,
WECHAT_MINI_APP_ID: ' wx0123456789abcdef ',
WECHAT_MINI_APP_SECRET: ' test-only-wechat-secret ',
});
assert.equal(config.wechatMiniAppId, 'wx0123456789abcdef');
assert.equal(config.wechatMiniAppSecret, 'test-only-wechat-secret');
});
test('拒绝不完整或含内部空白的微信配置,错误不回显配置值', () => {
for (const entry of [
{
WECHAT_MINI_APP_ID: 'wx0123456789abcdef',
WECHAT_MINI_APP_SECRET: undefined,
},
{
WECHAT_MINI_APP_ID: undefined,
WECHAT_MINI_APP_SECRET: 'test-only-wechat-secret',
},
{
WECHAT_MINI_APP_ID: 'wx0123456789abcdef',
WECHAT_MINI_APP_SECRET: ' ',
},
{
WECHAT_MINI_APP_ID: 'wx0123 456789abcdef',
WECHAT_MINI_APP_SECRET: 'test-only-wechat-secret',
},
{
WECHAT_MINI_APP_ID: 'wx0123456789abcdef',
WECHAT_MINI_APP_SECRET: 'test-only\nwechat-secret',
},
]) {
assert.throws(
() => getServerConfig({ ...env, ...entry }),
(error: unknown) => {
assert.ok(error instanceof Error);
assert.match(error.message, /WECHAT_MINI_APP/);
for (const value of Object.values(entry)) {
if (value?.trim())
assert.ok(!error.message.includes(value));
}
return true;
},
);
}
});
test('数据库连接必须为 PostgreSQL public schema,校验不回显含密码的 URL', () => {
for (const databaseUrl of [
'',
'mysql://user:private-password@localhost/db',
'postgresql:///db',
'postgresql://localhost',
'postgresql://localhost/db?schema=other',
])
assert.throws(
() => getServerConfig({ ...env, DATABASE_URL: databaseUrl }),
/DATABASE_URL/,
);
assert.equal(getServerConfig(env).databaseUrl, env.DATABASE_URL);
});
test('拒绝非法 body、JWT 有效期、日志级别、布尔开关和跨域配置', () => {
for (const entry of [
{ API_BODY_LIMIT_BYTES: '0' },
@@ -55,3 +137,30 @@ test('拒绝非法 body、JWT 有效期、日志级别、布尔开关和跨域
['https://example.com', 'http://localhost:3001'],
);
});
test('题型新品窗口与公共资源域名校验,缺省域名不构造七牛地址', () => {
assert.equal(getServerConfig(env).worksheetNewWindowDays, 30);
assert.equal(getServerConfig(env).qiniuPublicDomain, null);
assert.equal(
getServerConfig({
...env,
QINIU_PUBLIC_DOMAIN: 'https://assets.example.test/',
}).qiniuPublicDomain,
'https://assets.example.test',
);
for (const value of ['0', '366', '1e2', ''])
assert.throws(() =>
getServerConfig({ ...env, WORKSHEET_NEW_WINDOW_DAYS: value }),
);
for (const value of [
'http://assets.example.test',
'https://user:secret@example.test',
'https://example.test/path',
'https://example.test?sign=private',
'https://example.test#hash',
])
assert.throws(
() => getServerConfig({ ...env, QINIU_PUBLIC_DOMAIN: value }),
/QINIU_PUBLIC_DOMAIN/,
);
});