26 包 monorepo(TS 全源码): - snowcat-core: NT 内核 API 封装 + listener(含 9.9.37 六回调适配)+ Packet 发包 - snowcat-onebot: OneBot v11 全动作 + MCP Streamable HTTP 适配器 + 稳定线 - snowcat-webui-frontend/backend: 雪猫控制台(React+HeroUI) - snowcat-shell: 单文件 bundle 出口(vite inlineDynamicImports) - snowcat-native: napi2native / MoeHoo / ffmpeg / pty 运行时 - 56 项 SnowLuma 独门动作移植(qzone 全家桶/群相册/装扮/闪照/收藏) - 工具件: 解包器/启动器/便携制作器/doctor GitHub 关联已全量指向 DandanLLab/SnowCatQQ
166 lines
5.5 KiB
TypeScript
166 lines
5.5 KiB
TypeScript
import { describe, expect, test } from 'vitest';
|
|
import { TypeCompiler } from '@sinclair/typebox/compiler';
|
|
import { Value } from '@sinclair/typebox/value';
|
|
import { Type } from '@sinclair/typebox';
|
|
|
|
import { OB11MessageDataSchema, OB11MessageSchema, OB11PostSendMsgSchema } from '../snowcat-onebot/types/message';
|
|
import { OB11MessageSchema as OB11ActionMessageSchema } from '../snowcat-onebot/action/schemas';
|
|
import { OneBotConfigSchema, loadConfig as loadOneBotConfig, OneBotConfig } from '../snowcat-onebot/config';
|
|
import { SnowCatConfigSchema } from '../snowcat-core/helper/config';
|
|
|
|
describe('SnowCat Schemas Compilation', () => {
|
|
test('should compile OB11MessageDataSchema without duplicate id error', () => {
|
|
expect(() => TypeCompiler.Compile(OB11MessageDataSchema)).not.toThrow();
|
|
});
|
|
|
|
test('should compile OB11MessageSchema without duplicate id error', () => {
|
|
expect(() => TypeCompiler.Compile(OB11MessageSchema)).not.toThrow();
|
|
});
|
|
|
|
test('should compile OB11ActionMessageSchema without duplicate id error', () => {
|
|
expect(() => TypeCompiler.Compile(OB11ActionMessageSchema)).not.toThrow();
|
|
});
|
|
|
|
test('should compile OB11PostSendMsgSchema without error', () => {
|
|
expect(() => TypeCompiler.Compile(OB11PostSendMsgSchema)).not.toThrow();
|
|
});
|
|
|
|
test('should compile QuickAction hybrid schema without error', () => {
|
|
const QASchema = Type.Object({
|
|
message: OB11PostSendMsgSchema,
|
|
quick_action: OB11ActionMessageSchema,
|
|
});
|
|
expect(() => TypeCompiler.Compile(QASchema)).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('SnowCat Schemas Validation & Coercion', () => {
|
|
test('should coerce numeric user_id to string in OB11PostSendMsgSchema', () => {
|
|
const payload = {
|
|
message_type: 'private',
|
|
user_id: 123456,
|
|
message: [{ type: 'text', data: { text: 'hello' } }],
|
|
};
|
|
|
|
let data: unknown = structuredClone(payload);
|
|
data = Value.Parse(OB11PostSendMsgSchema, data);
|
|
|
|
const compiler = TypeCompiler.Compile(OB11PostSendMsgSchema);
|
|
expect(compiler.Check(data)).toBe(true);
|
|
expect((data as Record<string, unknown>)['user_id']).toBe('123456');
|
|
});
|
|
|
|
test('should validate complex mixed messages correctly', () => {
|
|
const payload = {
|
|
message_type: 'group',
|
|
group_id: '654321',
|
|
message: 'this is a string message',
|
|
};
|
|
|
|
let data: unknown = structuredClone(payload);
|
|
data = Value.Parse(OB11PostSendMsgSchema, data);
|
|
|
|
const compiler = TypeCompiler.Compile(OB11PostSendMsgSchema);
|
|
expect(compiler.Check(data)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('SnowCat Configuration Loaders', () => {
|
|
test('OneBotConfig schemas should compile', () => {
|
|
expect(() => TypeCompiler.Compile(OneBotConfigSchema)).not.toThrow();
|
|
});
|
|
|
|
test('OneBotConfig should load and apply defaults correctly', () => {
|
|
const partialConfig: Partial<OneBotConfig> = {
|
|
network: {
|
|
httpServers: [{
|
|
port: 3000,
|
|
enable: true,
|
|
name: 'test',
|
|
host: '127.0.0.1',
|
|
enableCors: true,
|
|
enableWebsocket: false,
|
|
messagePostFormat: 'array',
|
|
token: '',
|
|
debug: false,
|
|
}],
|
|
httpSseServers: [],
|
|
httpClients: [],
|
|
websocketServers: [],
|
|
websocketClients: [],
|
|
plugins: [],
|
|
},
|
|
};
|
|
const loaded = loadOneBotConfig(partialConfig);
|
|
expect(loaded.network.httpServers[0]?.host).toBe('127.0.0.1');
|
|
expect(loaded.network.httpServers[0]?.enableCors).toBe(true);
|
|
expect(loaded.musicSignUrl).toBe('');
|
|
});
|
|
|
|
test('OneBotConfig websocketClients should apply verifyCertificate default', () => {
|
|
const partialConfig: Partial<OneBotConfig> = {
|
|
network: {
|
|
httpServers: [],
|
|
httpSseServers: [],
|
|
httpClients: [],
|
|
websocketServers: [],
|
|
websocketClients: [{
|
|
name: 'test-ws-client',
|
|
enable: true,
|
|
url: 'wss://example.com',
|
|
messagePostFormat: 'array',
|
|
reportSelfMessage: false,
|
|
reconnectInterval: 5000,
|
|
token: '',
|
|
debug: false,
|
|
heartInterval: 30000,
|
|
}],
|
|
plugins: [],
|
|
},
|
|
};
|
|
const loaded = loadOneBotConfig(partialConfig);
|
|
expect(loaded.network.websocketClients[0]?.verifyCertificate).toBe(true);
|
|
});
|
|
|
|
test('OneBotConfig websocketClients should preserve explicit verifyCertificate false', () => {
|
|
const partialConfig: Partial<OneBotConfig> = {
|
|
network: {
|
|
httpServers: [],
|
|
httpSseServers: [],
|
|
httpClients: [],
|
|
websocketServers: [],
|
|
websocketClients: [{
|
|
name: 'test-ws-client',
|
|
enable: true,
|
|
url: 'wss://example.com',
|
|
messagePostFormat: 'array',
|
|
reportSelfMessage: false,
|
|
reconnectInterval: 5000,
|
|
token: '',
|
|
debug: false,
|
|
heartInterval: 30000,
|
|
verifyCertificate: false,
|
|
}],
|
|
plugins: [],
|
|
},
|
|
};
|
|
const loaded = loadOneBotConfig(partialConfig);
|
|
expect(loaded.network.websocketClients[0]?.verifyCertificate).toBe(false);
|
|
});
|
|
|
|
test('NapcatConfig should compile and apply defaults', () => {
|
|
let compiled: ReturnType<typeof TypeCompiler.Compile> | undefined;
|
|
expect(() => {
|
|
compiled = TypeCompiler.Compile(SnowCatConfigSchema);
|
|
}).not.toThrow();
|
|
|
|
let data: unknown = {};
|
|
data = Value.Parse(SnowCatConfigSchema, data);
|
|
|
|
expect(compiled?.Check(data)).toBe(true);
|
|
const resolved = data as Record<string, unknown>;
|
|
expect(resolved['consoleLog']).toBe(true);
|
|
expect(resolved['consoleLogLevel']).toBe('info');
|
|
});
|
|
});
|