// @ts-nocheck import { describe, it, expect, vi, beforeEach } from 'vitest'; import appdevDesignModePlugin from '../packages/plugin/src/index'; import type { Plugin } from 'vite'; describe('@xagi/vite-plugin-design-mode', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('插件初始化', () => { it('应该创建插件实例', () => { const plugin = appdevDesignModePlugin(); expect(plugin).toBeDefined(); expect(plugin.name).toBe('@xagi/vite-plugin-design-mode'); }); it('应该使用默认选项', () => { const plugin = appdevDesignModePlugin(); expect(plugin).toBeDefined(); // 插件应该具有预期的方法 expect(typeof plugin.config).toBe('function'); expect(typeof plugin.configureServer).toBe('function'); expect(typeof plugin.transform).toBe('function'); expect(typeof plugin.transformIndexHtml).toBe('function'); expect(typeof plugin.buildStart).toBe('function'); expect(typeof plugin.buildEnd).toBe('function'); }); it('应该接受自定义选项', () => { const plugin = appdevDesignModePlugin({ enabled: false, verbose: true, attributePrefix: 'data-test', exclude: ['custom-exclude'], include: ['custom-include'], }); expect(plugin).toBeDefined(); expect(plugin.name).toBe('@xagi/vite-plugin-design-mode'); }); }); describe('config hook', () => { it('应该在开发模式下启用', () => { const plugin = appdevDesignModePlugin({ enabled: true }); const result = plugin.config?.({}, { command: 'serve' }); expect(result).toBeDefined(); expect(result?.define).toBeDefined(); expect(result?.define?.__APPDEV_DESIGN_MODE__).toBe(true); }); it('应该在构建模式下禁用(如果未启用生产模式)', () => { const plugin = appdevDesignModePlugin({ enabled: true, enableInProduction: false, }); const result = plugin.config?.({}, { command: 'build' }); expect(result).toEqual({}); }); it('应该在构建模式下启用(如果启用生产模式)', () => { const plugin = appdevDesignModePlugin({ enabled: true, enableInProduction: true, }); const result = plugin.config?.({}, { command: 'build' }); expect(result).toBeDefined(); expect(result?.define?.__APPDEV_DESIGN_MODE__).toBe(true); }); it('应该在禁用时返回空配置', () => { const plugin = appdevDesignModePlugin({ enabled: false }); const result = plugin.config?.({}, { command: 'serve' }); expect(result).toEqual({}); }); it('应该设置verbose标志', () => { const plugin = appdevDesignModePlugin({ verbose: true }); const result = plugin.config?.({}, { command: 'serve' }); expect(result?.define?.__APPDEV_DESIGN_MODE_VERBOSE__).toBe(true); }); }); describe('transform hook', () => { it('应该在禁用时返回原始代码', async () => { const plugin = appdevDesignModePlugin({ enabled: false }); const code = 'function App() { return
Test
; }'; const result = await plugin.transform?.(code, 'test.tsx', {}); expect(result).toBe(code); }); it('应该处理匹配的文件', async () => { const plugin = appdevDesignModePlugin({ enabled: true }); const code = 'function App() { return
Test
; }'; const result = await plugin.transform?.(code, 'src/App.tsx', {}); expect(result).toBeDefined(); // 应该被转换(添加了源码映射属性) if (typeof result === 'object' && result !== null) { expect(result.code).toBeDefined(); } }); it('应该排除node_modules中的文件', async () => { const plugin = appdevDesignModePlugin({ enabled: true }); const code = 'function App() { return
Test
; }'; const result = await plugin.transform?.(code, 'node_modules/test.tsx', {}); expect(result).toBe(code); }); it('应该处理转换错误', async () => { const plugin = appdevDesignModePlugin({ enabled: true, verbose: false, }); // 无效的代码应该返回原始代码 const code = 'invalid syntax {{{{'; const result = await plugin.transform?.(code, 'test.tsx', {}); expect(result).toBeDefined(); }); }); describe('shouldProcessFile', () => { it('应该处理匹配include模式的文件', async () => { const plugin = appdevDesignModePlugin({ enabled: true, include: ['**/*.tsx'], }); const code = 'function App() { return
Test
; }'; const result = await plugin.transform?.(code, 'src/App.tsx', {}); expect(result).toBeDefined(); }); it('应该排除匹配exclude模式的文件', async () => { const plugin = appdevDesignModePlugin({ enabled: true, exclude: ['test'], }); const code = 'function App() { return
Test
; }'; const result = await plugin.transform?.(code, 'test/App.tsx', {}); expect(result).toBe(code); }); it('应该处理glob模式', async () => { const plugin = appdevDesignModePlugin({ enabled: true, include: ['src/**/*.{ts,tsx}'], }); const code = 'function App() { return
Test
; }'; const result1 = await plugin.transform?.(code, 'src/App.tsx', {}); const result2 = await plugin.transform?.(code, 'src/components/Button.tsx', {}); expect(result1).toBeDefined(); expect(result2).toBeDefined(); }); }); describe('configureServer hook', () => { it('应该在开发模式下配置服务器', () => { const plugin = appdevDesignModePlugin({ enabled: true }); const mockServer = { config: { command: 'serve' as const, root: '/test', }, middlewares: { use: vi.fn(), }, } as any; plugin.configureServer?.(mockServer); expect(mockServer.middlewares.use).toHaveBeenCalled(); }); it('应该在禁用时不配置服务器', () => { const plugin = appdevDesignModePlugin({ enabled: false }); const mockServer = { config: { command: 'serve' as const, root: '/test', }, middlewares: { use: vi.fn(), }, } as any; plugin.configureServer?.(mockServer); // 不应该调用use(或者调用但立即返回) // 这里我们只检查不会抛出错误 expect(mockServer).toBeDefined(); }); }); describe('transformIndexHtml hook', () => { it('应该在启用时注入客户端脚本', () => { const plugin = appdevDesignModePlugin({ enabled: true }); const html = ''; const result = plugin.transformIndexHtml?.(html, { path: '/', filename: 'index.html', }); if (typeof result === 'object' && result !== null) { expect(result.tags).toBeDefined(); expect(result.tags?.length).toBeGreaterThan(0); expect(result.tags?.[0]?.tag).toBe('script'); } }); it('应该在禁用时不注入脚本', () => { const plugin = appdevDesignModePlugin({ enabled: false }); const html = ''; const result = plugin.transformIndexHtml?.(html, { path: '/', filename: 'index.html', }); expect(result).toBe(html); }); }); describe('buildStart 和 buildEnd hooks', () => { it('应该在verbose模式下输出日志', () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); const plugin = appdevDesignModePlugin({ verbose: true }); plugin.buildStart?.(); expect(consoleSpy).toHaveBeenCalledWith( '[appdev-design-mode] Plugin started' ); plugin.buildEnd?.(); expect(consoleSpy).toHaveBeenCalledWith( '[appdev-design-mode] Plugin ended' ); consoleSpy.mockRestore(); }); it('应该在非verbose模式下不输出日志', () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); const plugin = appdevDesignModePlugin({ verbose: false }); plugin.buildStart?.(); plugin.buildEnd?.(); expect(consoleSpy).not.toHaveBeenCalled(); consoleSpy.mockRestore(); }); }); });