feat(image): 新建 knowai-core:1.0.0 镜像并完成推送
Some checks reported errors
continuous-integration/drone/push Build was killed

- 搭建 api、auth、utils 等逻辑模块
- 通过 tsc、eslint、vitest 测试验证

BREAKING CHANGE: 新镜像分支
This commit is contained in:
tobegold574
2025-11-10 20:20:25 +08:00
commit 6a81b7bb13
73 changed files with 10511 additions and 0 deletions

159
test/utils/test-helpers.ts Normal file
View File

@@ -0,0 +1,159 @@
/**
* 测试工具函数
* 提供测试中常用的辅助函数
*/
import { vi } from 'vitest';
// 等待指定时间(和await一起用)
export function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 等待下一个事件循环(和await一起用)
export function nextTick(): Promise<void> {
return new Promise(resolve => setTimeout(resolve, 0));
}
// 创建一个可控制的Promise(将promise的控制权提取到外部)
export function createControlledPromise<T = any>() {
// 用闭包把内部函数暴露到外部
let resolve: (value: T) => void;
let reject: (reason?: any) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return {
promise,
resolve: resolve!,
reject: reject!
};
}
// 模拟localStorage(闭包)
export function createMockLocalStorage() {
let store: Record<string, string> = {};
return {
getItem: vi.fn((key: string) => store[key] || null),
setItem: vi.fn((key: string, value: string) => {
store[key] = value;
}),
removeItem: vi.fn((key: string) => {
delete store[key];
}),
clear: vi.fn(() => {
store = {};
}),
get length() {
return Object.keys(store).length;
},
key: vi.fn((index: number) => {
const keys = Object.keys(store);
return keys[index] || null;
})
};
}
// 模拟sessionStorage
export function createMockSessionStorage() {
return createMockLocalStorage();
}
// 创建一个可读写的流
// 创建一个可读写的事件流
export function createMockStream() {
const listeners: Record<string, Function[]> = {};
// 先创建对象引用
const stream = {
on: vi.fn((event: string, callback: Function) => {
if (!listeners[event]) {
listeners[event] = [];
}
listeners[event].push(callback);
return stream; // 使用对象引用而不是 this
}),
emit: vi.fn((event: string, ...args: any[]) => {
if (listeners[event]) {
listeners[event].forEach(callback => callback(...args));
}
return stream; // 使用对象引用
}),
once: vi.fn((event: string, callback: Function) => {
const onceWrapper = (...args: any[]) => {
callback(...args);
// 移除监听器
if (listeners[event]) {
listeners[event] = listeners[event].filter(cb => cb !== onceWrapper);
}
};
return stream.on(event, onceWrapper); // 使用对象引用
}),
removeListener: vi.fn((event: string, callback: Function) => {
if (listeners[event]) {
listeners[event] = listeners[event].filter(cb => cb !== callback);
}
return stream; // 使用对象引用
}),
removeAllListeners: vi.fn((event?: string) => {
if (event) {
delete listeners[event];
} else {
Object.keys(listeners).forEach(key => {
delete listeners[key];
});
}
return stream; // 使用对象引用
})
};
return stream;
}
// 模拟IntersectionObserver
export function createMockIntersectionObserver() {
const callbacks: Function[] = [];
return {
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
root: null,
rootMargin: '',
thresholds: [],
constructor: vi.fn((callback: Function) => {
callbacks.push(callback);
return {
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn()
};
})
};
}
// 模拟ResizeObserver
export function createMockResizeObserver() {
const callbacks: Function[] = [];
return {
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
constructor: vi.fn((callback: Function) => {
callbacks.push(callback);
return {
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn()
};
})
};
}