Files
MetonaEditor/tests/animations.test.ts
T
thzxx e83fc211dc feat: v0.2.0 — TypeScript full rewrite, 95%+ core coverage
BREAKING CHANGE: All source files converted from JavaScript to TypeScript.
- 12 .ts source files with strict types, full EditorOptions/Plugin/Token interfaces
- 7 .ts test files, 610 total tests (27 new), 7 suites all passing
- tsc --noEmit: 0 errors
- rollup-plugin-typescript build: 5 artifacts (UMD/ESM/CJS/Min/DTS)
- @babel/preset-typescript for jest
- New tsconfig.json, updated babel/jest/rollup configs
- Coverage: parser 99.5%, utils 95.7%, themes 96.2%, core 88.8%, plugins 89.5%
- Removed types/ folder (types now inline in .ts + auto-generated .d.ts)
- Desktop-only, no backward compatibility
2026-07-24 22:28:38 +08:00

147 lines
4.6 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.
/**
* animations.js 单元测试
* 覆盖 animationUtils 全部 API + createAnimation 工厂
*/
import { animationUtils, createAnimation, animationPresets } from '../src/animations';
import { ANIMATIONS } from '../src/constants';
describe('animationUtils - 默认动画注册', () => {
test('默认动画已注册到 animationMap', () => {
const names = animationUtils.getAnimationNames();
// 与 constants.js 中 ANIMATIONS 的键一致
Object.keys(ANIMATIONS).forEach((name) => {
expect(names).toContain(name);
});
});
test('内置动画类型完整', () => {
const names = animationUtils.getAnimationNames();
expect(names).toEqual(expect.arrayContaining([
'slide', 'fade', 'scale', 'bounce', 'flip', 'rotate', 'zoom',
]));
});
});
describe('animationUtils - register / unregister / get', () => {
test('register 注册自定义动画', () => {
animationUtils.register('custom', {
enter: { opacity: 0 },
leave: { opacity: 0 },
duration: 500,
easing: 'ease-in',
});
const a = animationUtils.get('custom');
expect(a).not.toBeNull();
expect(a.name).toBe('custom');
expect(a.duration).toBe(500);
expect(a.easing).toBe('ease-in');
expect(a.enter).toEqual({ opacity: 0 });
});
test('register 缺省字段使用默认值', () => {
animationUtils.register('minimal', {});
const a = animationUtils.get('minimal');
expect(a.enter).toEqual({});
expect(a.leave).toEqual({});
expect(a.duration).toBe(300);
expect(a.easing).toBe('cubic-bezier(0.4, 0, 0.2, 1)');
});
test('unregister 移除动画', () => {
animationUtils.register('tmp', { duration: 100 });
expect(animationUtils.get('tmp')).not.toBeNull();
animationUtils.unregister('tmp');
// 移除后回退到 ANIMATIONS,但 'tmp' 不在 ANIMATIONS 中,返回 null
expect(animationUtils.get('tmp')).toBeNull();
});
test('get 不存在的动画返回 null', () => {
expect(animationUtils.get('non-existent-animation')).toBeNull();
});
test('get 内置动画返回配置', () => {
const a = animationUtils.get('slide');
expect(a).not.toBeNull();
// 内置动画直接存储 ANIMATIONS.slide 配置(不含 name 字段,只有 register() 才添加)
expect(a.duration).toBe(ANIMATIONS.slide.duration);
expect(a.enter).toEqual(ANIMATIONS.slide.enter);
});
});
describe('animationUtils - 查询 API', () => {
test('getAnimationNames 返回数组', () => {
const names = animationUtils.getAnimationNames();
expect(Array.isArray(names)).toBe(true);
expect(names.length).toBeGreaterThan(0);
});
test('getActiveCount 始终返回 0CSS 动画由浏览器管理)', () => {
expect(animationUtils.getActiveCount()).toBe(0);
});
test('cancelAll 不抛错(无操作)', () => {
expect(() => animationUtils.cancelAll()).not.toThrow();
});
});
describe('animationUtils - reset / destroy', () => {
test('reset 清除自定义动画并恢复内置', () => {
animationUtils.register('tmp1', {});
animationUtils.register('tmp2', {});
expect(animationUtils.getAnimationNames()).toContain('tmp1');
animationUtils.reset();
const names = animationUtils.getAnimationNames();
expect(names).not.toContain('tmp1');
expect(names).not.toContain('tmp2');
// 内置动画仍存在
expect(names).toContain('slide');
expect(names).toContain('fade');
});
test('destroy 清空所有动画', () => {
animationUtils.destroy();
expect(animationUtils.getAnimationNames()).toEqual([]);
// destroy 后 reset 可恢复
animationUtils.reset();
expect(animationUtils.getAnimationNames().length).toBeGreaterThan(0);
});
});
describe('createAnimation 工厂', () => {
test('返回完整动画对象', () => {
const a = createAnimation({
enter: { transform: 'translateX(10px)' },
leave: { transform: 'translateX(-10px)' },
duration: 600,
easing: 'linear',
});
expect(a.enter).toEqual({ transform: 'translateX(10px)' });
expect(a.leave).toEqual({ transform: 'translateX(-10px)' });
expect(a.duration).toBe(600);
expect(a.easing).toBe('linear');
});
test('缺省字段使用默认值', () => {
const a = createAnimation({});
expect(a.enter).toEqual({});
expect(a.leave).toEqual({});
expect(a.duration).toBe(300);
expect(a.easing).toBe('cubic-bezier(0.4, 0, 0.2, 1)');
});
test('无参数也能创建', () => {
const a = createAnimation();
expect(a).toBeDefined();
expect(a.duration).toBe(300);
});
});
describe('animationPresets', () => {
test('导出为对象', () => {
expect(typeof animationPresets).toBe('object');
});
});