video-shuoshan/web/test/unit/inputBarStore.test.ts
zyc ffe92f7b15 Initial commit: 即梦视频生成平台
- web/: React + Vite + TypeScript 前端
- backend/: Django + DRF + SimpleJWT 后端
- prototype/: HTML 设计原型
- docs/: PRD 和设计评审文档
- test: 单元测试 + E2E 极限测试
2026-03-13 09:59:33 +08:00

272 lines
10 KiB
TypeScript

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { useInputBarStore } from '../../src/store/inputBar';
function createMockFile(name: string, type: string): File {
return new File(['mock'], name, { type });
}
describe('InputBar Store', () => {
beforeEach(() => {
useInputBarStore.getState().reset();
});
describe('Initial State', () => {
it('should have correct default values', () => {
const state = useInputBarStore.getState();
expect(state.generationType).toBe('video');
expect(state.mode).toBe('universal');
expect(state.model).toBe('seedance_2.0');
expect(state.aspectRatio).toBe('21:9');
expect(state.duration).toBe(15);
expect(state.prompt).toBe('');
expect(state.references).toEqual([]);
expect(state.firstFrame).toBeNull();
expect(state.lastFrame).toBeNull();
});
});
describe('Generation Type', () => {
it('should set generation type', () => {
useInputBarStore.getState().setGenerationType('image');
expect(useInputBarStore.getState().generationType).toBe('image');
});
});
describe('Model Selection', () => {
it('should set model', () => {
useInputBarStore.getState().setModel('seedance_2.0_fast');
expect(useInputBarStore.getState().model).toBe('seedance_2.0_fast');
});
});
describe('Aspect Ratio', () => {
it('should set aspect ratio and save as previous', () => {
useInputBarStore.getState().setAspectRatio('16:9');
const state = useInputBarStore.getState();
expect(state.aspectRatio).toBe('16:9');
expect(state.prevAspectRatio).toBe('16:9');
});
});
describe('Duration', () => {
it('should set duration in universal mode and save as previous', () => {
useInputBarStore.getState().setDuration(10);
const state = useInputBarStore.getState();
expect(state.duration).toBe(10);
expect(state.prevDuration).toBe(10);
});
it('should set duration in keyframe mode without saving as previous', () => {
useInputBarStore.getState().switchMode('keyframe');
useInputBarStore.getState().setDuration(10);
const state = useInputBarStore.getState();
expect(state.duration).toBe(10);
expect(state.prevDuration).toBe(15); // original default
});
});
describe('Prompt', () => {
it('should set prompt text', () => {
useInputBarStore.getState().setPrompt('test prompt');
expect(useInputBarStore.getState().prompt).toBe('test prompt');
});
});
describe('Universal References', () => {
it('should add references', () => {
const files = [createMockFile('img1.jpg', 'image/jpeg')];
useInputBarStore.getState().addReferences(files);
expect(useInputBarStore.getState().references).toHaveLength(1);
expect(useInputBarStore.getState().references[0].type).toBe('image');
});
it('should limit references to 5', () => {
const files = Array.from({ length: 6 }, (_, i) =>
createMockFile(`img${i}.jpg`, 'image/jpeg')
);
useInputBarStore.getState().addReferences(files);
expect(useInputBarStore.getState().references).toHaveLength(5);
});
it('should not add more when already at 5', () => {
const files = Array.from({ length: 5 }, (_, i) =>
createMockFile(`img${i}.jpg`, 'image/jpeg')
);
useInputBarStore.getState().addReferences(files);
expect(useInputBarStore.getState().references).toHaveLength(5);
useInputBarStore.getState().addReferences([createMockFile('extra.jpg', 'image/jpeg')]);
expect(useInputBarStore.getState().references).toHaveLength(5);
});
it('should detect video files correctly', () => {
const files = [createMockFile('vid.mp4', 'video/mp4')];
useInputBarStore.getState().addReferences(files);
expect(useInputBarStore.getState().references[0].type).toBe('video');
});
it('should remove a reference by id', () => {
const files = [createMockFile('img1.jpg', 'image/jpeg')];
useInputBarStore.getState().addReferences(files);
const id = useInputBarStore.getState().references[0].id;
useInputBarStore.getState().removeReference(id);
expect(useInputBarStore.getState().references).toHaveLength(0);
});
it('should call revokeObjectURL when removing reference', () => {
const files = [createMockFile('img1.jpg', 'image/jpeg')];
useInputBarStore.getState().addReferences(files);
const id = useInputBarStore.getState().references[0].id;
useInputBarStore.getState().removeReference(id);
expect(URL.revokeObjectURL).toHaveBeenCalled();
});
it('should clear all references', () => {
const files = [
createMockFile('img1.jpg', 'image/jpeg'),
createMockFile('img2.jpg', 'image/jpeg'),
];
useInputBarStore.getState().addReferences(files);
useInputBarStore.getState().clearReferences();
expect(useInputBarStore.getState().references).toHaveLength(0);
});
});
describe('Keyframe Frames', () => {
it('should set first frame', () => {
const file = createMockFile('first.jpg', 'image/jpeg');
useInputBarStore.getState().setFirstFrame(file);
const state = useInputBarStore.getState();
expect(state.firstFrame).not.toBeNull();
expect(state.firstFrame!.label).toBe('首帧');
});
it('should set last frame', () => {
const file = createMockFile('last.jpg', 'image/jpeg');
useInputBarStore.getState().setLastFrame(file);
const state = useInputBarStore.getState();
expect(state.lastFrame).not.toBeNull();
expect(state.lastFrame!.label).toBe('尾帧');
});
it('should clear first frame when setting null', () => {
useInputBarStore.getState().setFirstFrame(createMockFile('first.jpg', 'image/jpeg'));
useInputBarStore.getState().setFirstFrame(null);
expect(useInputBarStore.getState().firstFrame).toBeNull();
});
it('should revoke old URL when replacing frame', () => {
useInputBarStore.getState().setFirstFrame(createMockFile('a.jpg', 'image/jpeg'));
useInputBarStore.getState().setFirstFrame(createMockFile('b.jpg', 'image/jpeg'));
expect(URL.revokeObjectURL).toHaveBeenCalled();
});
});
describe('canSubmit', () => {
it('should return false when no content', () => {
expect(useInputBarStore.getState().canSubmit()).toBe(false);
});
it('should return true when prompt has text', () => {
useInputBarStore.getState().setPrompt('hello');
expect(useInputBarStore.getState().canSubmit()).toBe(true);
});
it('should return false for whitespace-only prompt', () => {
useInputBarStore.getState().setPrompt(' ');
expect(useInputBarStore.getState().canSubmit()).toBe(false);
});
it('should return true when universal references exist', () => {
useInputBarStore.getState().addReferences([createMockFile('img.jpg', 'image/jpeg')]);
expect(useInputBarStore.getState().canSubmit()).toBe(true);
});
it('should return true when first frame exists in keyframe mode', () => {
useInputBarStore.getState().switchMode('keyframe');
useInputBarStore.getState().setFirstFrame(createMockFile('first.jpg', 'image/jpeg'));
expect(useInputBarStore.getState().canSubmit()).toBe(true);
});
it('should return true when last frame exists in keyframe mode', () => {
useInputBarStore.getState().switchMode('keyframe');
useInputBarStore.getState().setLastFrame(createMockFile('last.jpg', 'image/jpeg'));
expect(useInputBarStore.getState().canSubmit()).toBe(true);
});
});
describe('Mode Switching', () => {
it('should switch to keyframe mode with correct defaults', () => {
useInputBarStore.getState().switchMode('keyframe');
const state = useInputBarStore.getState();
expect(state.mode).toBe('keyframe');
expect(state.duration).toBe(5);
expect(state.references).toEqual([]);
});
it('should clear universal references when switching to keyframe', () => {
useInputBarStore.getState().addReferences([createMockFile('img.jpg', 'image/jpeg')]);
useInputBarStore.getState().switchMode('keyframe');
expect(useInputBarStore.getState().references).toEqual([]);
});
it('should restore aspect ratio and duration when switching back to universal', () => {
useInputBarStore.getState().setAspectRatio('16:9');
useInputBarStore.getState().setDuration(10);
useInputBarStore.getState().switchMode('keyframe');
useInputBarStore.getState().switchMode('universal');
const state = useInputBarStore.getState();
expect(state.aspectRatio).toBe('16:9');
expect(state.duration).toBe(10);
});
it('should clear keyframe data when switching back to universal', () => {
useInputBarStore.getState().switchMode('keyframe');
useInputBarStore.getState().setFirstFrame(createMockFile('first.jpg', 'image/jpeg'));
useInputBarStore.getState().setLastFrame(createMockFile('last.jpg', 'image/jpeg'));
useInputBarStore.getState().switchMode('universal');
const state = useInputBarStore.getState();
expect(state.firstFrame).toBeNull();
expect(state.lastFrame).toBeNull();
});
it('should not do anything when switching to same mode', () => {
useInputBarStore.getState().setPrompt('test');
useInputBarStore.getState().switchMode('universal');
expect(useInputBarStore.getState().prompt).toBe('test');
});
it('should preserve prompt text across mode switches', () => {
useInputBarStore.getState().setPrompt('my prompt');
useInputBarStore.getState().switchMode('keyframe');
expect(useInputBarStore.getState().prompt).toBe('my prompt');
useInputBarStore.getState().switchMode('universal');
expect(useInputBarStore.getState().prompt).toBe('my prompt');
});
});
describe('Reset', () => {
it('should reset all state to defaults', () => {
useInputBarStore.getState().setPrompt('hello');
useInputBarStore.getState().setModel('seedance_2.0_fast');
useInputBarStore.getState().setAspectRatio('16:9');
useInputBarStore.getState().setDuration(5);
useInputBarStore.getState().addReferences([createMockFile('img.jpg', 'image/jpeg')]);
useInputBarStore.getState().reset();
const state = useInputBarStore.getState();
expect(state.prompt).toBe('');
expect(state.model).toBe('seedance_2.0');
expect(state.aspectRatio).toBe('21:9');
expect(state.duration).toBe(15);
expect(state.references).toEqual([]);
expect(state.mode).toBe('universal');
expect(state.generationType).toBe('video');
});
});
});