refactor: reorganize package structure and decouple framework packages (#338)
* refactor: reorganize package structure and decouple framework packages ## Package Structure Reorganization - Reorganized 55 packages into categorized subdirectories: - packages/framework/ - Generic framework (Laya/Cocos compatible) - packages/engine/ - ESEngine core modules - packages/rendering/ - Rendering modules (WASM dependent) - packages/physics/ - Physics modules - packages/streaming/ - World streaming - packages/network-ext/ - Network extensions - packages/editor/ - Editor framework and plugins - packages/rust/ - Rust WASM engine - packages/tools/ - Build tools and SDK ## Framework Package Decoupling - Decoupled behavior-tree and blueprint packages from ESEngine dependencies - Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent) - ESEngine-specific code moved to esengine/ subpath exports - Framework packages now usable with Cocos/Laya without ESEngine ## CI Configuration - Updated CI to only type-check and lint framework packages - Added type-check:framework and lint:framework scripts ## Breaking Changes - Package import paths changed due to directory reorganization - ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine') * fix: update es-engine file path after directory reorganization * docs: update README to focus on framework over engine * ci: only build framework packages, remove Rust/WASM dependencies * fix: remove esengine subpath from behavior-tree and blueprint builds ESEngine integration code will only be available in full engine builds. Framework packages are now purely engine-agnostic. * fix: move network-protocols to framework, build both in CI * fix: update workflow paths from packages/core to packages/framework/core * fix: exclude esengine folder from type-check in behavior-tree and blueprint * fix: update network tsconfig references to new paths * fix: add test:ci:framework to only test framework packages in CI * fix: only build core and math npm packages in CI * fix: exclude test files from CodeQL and fix string escaping security issue
This commit is contained in:
263
packages/framework/math/tests/Vector2.test.ts
Normal file
263
packages/framework/math/tests/Vector2.test.ts
Normal file
@@ -0,0 +1,263 @@
|
||||
import { Vector2 } from '../src/Vector2';
|
||||
|
||||
declare global {
|
||||
var expectFloatsEqual: (actual: number, expected: number, epsilon?: number) => void;
|
||||
}
|
||||
|
||||
describe('Vector2', () => {
|
||||
describe('构造函数和基础属性', () => {
|
||||
test('默认构造函数应创建零向量', () => {
|
||||
const v = new Vector2();
|
||||
expect(v.x).toBe(0);
|
||||
expect(v.y).toBe(0);
|
||||
});
|
||||
|
||||
test('应正确设置x和y值', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
expect(v.x).toBe(3);
|
||||
expect(v.y).toBe(4);
|
||||
});
|
||||
|
||||
test('length属性应正确计算', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
expect(v.length).toBe(5);
|
||||
});
|
||||
|
||||
test('lengthSquared属性应正确计算', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
expect(v.lengthSquared).toBe(25);
|
||||
});
|
||||
|
||||
test('angle属性应正确计算', () => {
|
||||
const v = new Vector2(1, 0);
|
||||
expect(v.angle).toBe(0);
|
||||
|
||||
const v2 = new Vector2(0, 1);
|
||||
expectFloatsEqual(v2.angle, Math.PI / 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('基础运算', () => {
|
||||
test('set方法应正确设置值', () => {
|
||||
const v = new Vector2();
|
||||
v.set(5, 6);
|
||||
expect(v.x).toBe(5);
|
||||
expect(v.y).toBe(6);
|
||||
});
|
||||
|
||||
test('copy方法应正确复制值', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
v2.copy(v1);
|
||||
expect(v2.x).toBe(1);
|
||||
expect(v2.y).toBe(2);
|
||||
});
|
||||
|
||||
test('clone方法应创建相同的新实例', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = v1.clone();
|
||||
expect(v2.x).toBe(1);
|
||||
expect(v2.y).toBe(2);
|
||||
expect(v2).not.toBe(v1);
|
||||
});
|
||||
|
||||
test('add方法应正确相加', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
v1.add(v2);
|
||||
expect(v1.x).toBe(4);
|
||||
expect(v1.y).toBe(6);
|
||||
});
|
||||
|
||||
test('subtract方法应正确相减', () => {
|
||||
const v1 = new Vector2(5, 7);
|
||||
const v2 = new Vector2(2, 3);
|
||||
v1.subtract(v2);
|
||||
expect(v1.x).toBe(3);
|
||||
expect(v1.y).toBe(4);
|
||||
});
|
||||
|
||||
test('multiply方法应正确数乘', () => {
|
||||
const v = new Vector2(2, 3);
|
||||
v.multiply(4);
|
||||
expect(v.x).toBe(8);
|
||||
expect(v.y).toBe(12);
|
||||
});
|
||||
|
||||
test('divide方法应正确数除', () => {
|
||||
const v = new Vector2(8, 12);
|
||||
v.divide(4);
|
||||
expect(v.x).toBe(2);
|
||||
expect(v.y).toBe(3);
|
||||
});
|
||||
|
||||
test('divide方法应在除以零时抛出错误', () => {
|
||||
const v = new Vector2(1, 2);
|
||||
expect(() => v.divide(0)).toThrow('不能除以零');
|
||||
});
|
||||
});
|
||||
|
||||
describe('向量运算', () => {
|
||||
test('dot方法应正确计算点积', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
expect(v1.dot(v2)).toBe(11); // 1*3 + 2*4 = 11
|
||||
});
|
||||
|
||||
test('cross方法应正确计算叉积', () => {
|
||||
const v1 = new Vector2(1, 0);
|
||||
const v2 = new Vector2(0, 1);
|
||||
expect(v1.cross(v2)).toBe(1);
|
||||
});
|
||||
|
||||
test('normalize方法应正确归一化向量', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
v.normalize();
|
||||
expectFloatsEqual(v.length, 1);
|
||||
expectFloatsEqual(v.x, 0.6);
|
||||
expectFloatsEqual(v.y, 0.8);
|
||||
});
|
||||
|
||||
test('零向量归一化应保持不变', () => {
|
||||
const v = new Vector2(0, 0);
|
||||
v.normalize();
|
||||
expect(v.x).toBe(0);
|
||||
expect(v.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('几何运算', () => {
|
||||
test('distanceTo方法应正确计算距离', () => {
|
||||
const v1 = new Vector2(0, 0);
|
||||
const v2 = new Vector2(3, 4);
|
||||
expect(v1.distanceTo(v2)).toBe(5);
|
||||
});
|
||||
|
||||
test('angleTo方法应正确计算夹角', () => {
|
||||
const v1 = new Vector2(1, 0);
|
||||
const v2 = new Vector2(0, 1);
|
||||
expectFloatsEqual(v1.angleTo(v2), Math.PI / 2);
|
||||
});
|
||||
|
||||
test('projectOnto方法应正确投影', () => {
|
||||
const v1 = new Vector2(2, 2);
|
||||
const v2 = new Vector2(1, 0);
|
||||
const projected = v1.projectOnto(v2);
|
||||
expect(projected.x).toBe(2);
|
||||
expect(projected.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('变换操作', () => {
|
||||
test('rotate方法应正确旋转向量(顺时针)', () => {
|
||||
// Clockwise rotation: (1, 0) rotated 90° clockwise = (0, -1)
|
||||
// 顺时针旋转:(1, 0) 顺时针旋转 90° = (0, -1)
|
||||
const v = new Vector2(1, 0);
|
||||
v.rotate(Math.PI / 2);
|
||||
expectFloatsEqual(v.x, 0, 1e-10);
|
||||
expectFloatsEqual(v.y, -1, 1e-10);
|
||||
});
|
||||
|
||||
test('reflect方法应正确反射向量', () => {
|
||||
const v = new Vector2(1, 1);
|
||||
const normal = new Vector2(0, 1);
|
||||
v.reflect(normal);
|
||||
expectFloatsEqual(v.x, 1);
|
||||
expectFloatsEqual(v.y, -1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('插值和限制', () => {
|
||||
test('lerp方法应正确插值', () => {
|
||||
const v1 = new Vector2(0, 0);
|
||||
const v2 = new Vector2(10, 10);
|
||||
v1.lerp(v2, 0.5);
|
||||
expect(v1.x).toBe(5);
|
||||
expect(v1.y).toBe(5);
|
||||
});
|
||||
|
||||
test('clampLength方法应正确限制长度', () => {
|
||||
const v = new Vector2(6, 8); // 长度为10
|
||||
v.clampLength(5);
|
||||
expectFloatsEqual(v.length, 5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('比较操作', () => {
|
||||
test('equals方法应正确比较向量', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(1, 2);
|
||||
const v3 = new Vector2(1.0001, 2);
|
||||
|
||||
expect(v1.equals(v2)).toBe(true);
|
||||
expect(v1.equals(v3, 0.001)).toBe(true);
|
||||
expect(v1.equals(v3, 0.00001)).toBe(false);
|
||||
});
|
||||
|
||||
test('exactEquals方法应检查完全相等', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(1, 2);
|
||||
const v3 = new Vector2(1.0001, 2);
|
||||
|
||||
expect(v1.exactEquals(v2)).toBe(true);
|
||||
expect(v1.exactEquals(v3)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('静态方法', () => {
|
||||
test('Vector2.add应创建新的相加结果', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
const result = Vector2.add(v1, v2);
|
||||
|
||||
expect(result.x).toBe(4);
|
||||
expect(result.y).toBe(6);
|
||||
expect(v1.x).toBe(1); // 原向量不变
|
||||
expect(v1.y).toBe(2);
|
||||
});
|
||||
|
||||
test('Vector2.fromAngle应从角度创建单位向量', () => {
|
||||
const v = Vector2.fromAngle(Math.PI / 2);
|
||||
expectFloatsEqual(v.x, 0, 1e-10);
|
||||
expectFloatsEqual(v.y, 1, 1e-10);
|
||||
});
|
||||
|
||||
test('Vector2.fromPolar应从极坐标创建向量', () => {
|
||||
const v = Vector2.fromPolar(5, 0);
|
||||
expect(v.x).toBe(5);
|
||||
expectFloatsEqual(v.y, 0, 1e-10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('静态常量', () => {
|
||||
test('静态常量应具有正确的值', () => {
|
||||
expect(Vector2.ZERO.x).toBe(0);
|
||||
expect(Vector2.ZERO.y).toBe(0);
|
||||
expect(Vector2.ONE.x).toBe(1);
|
||||
expect(Vector2.ONE.y).toBe(1);
|
||||
expect(Vector2.RIGHT.x).toBe(1);
|
||||
expect(Vector2.RIGHT.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('字符串转换', () => {
|
||||
test('toString应返回正确格式', () => {
|
||||
const v = new Vector2(1.2345, 2.6789);
|
||||
const str = v.toString();
|
||||
expect(str).toContain('1.234');
|
||||
expect(str).toContain('2.679');
|
||||
});
|
||||
|
||||
test('toArray应返回数组', () => {
|
||||
const v = new Vector2(1, 2);
|
||||
const arr = v.toArray();
|
||||
expect(arr).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
test('toObject应返回对象', () => {
|
||||
const v = new Vector2(1, 2);
|
||||
const obj = v.toObject();
|
||||
expect(obj).toEqual({ x: 1, y: 2 });
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user