147 lines
4.6 KiB
JavaScript
147 lines
4.6 KiB
JavaScript
/**
|
||
* animations.js 单元测试
|
||
* 覆盖 animationUtils 全部 API + createAnimation 工厂
|
||
*/
|
||
|
||
import { animationUtils, createAnimation, animationPresets } from '../src/animations.js';
|
||
import { ANIMATIONS } from '../src/constants.js';
|
||
|
||
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 始终返回 0(CSS 动画由浏览器管理)', () => {
|
||
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');
|
||
});
|
||
});
|