Files
esengine/packages/framework/math/tests/Vector2.test.ts
YHH 155411e743 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
2025-12-26 14:50:35 +08:00

263 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 });
});
});
});