import { test, describe } from 'node:test'; import assert from 'node:assert'; import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync } from 'fs'; import { join } from 'path'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // 导入要测试的模块 import { smartInject } from '../../lib/framework-inject.js'; describe('框架注入集成测试', () => { const testDir = join(__dirname, 'fixtures'); test.before(() => { if (!existsSync(testDir)) { mkdirSync(testDir, { recursive: true }); } }); test.after(() => { // 清理所有测试文件 const filesToClean = [ 'vite.config.js', 'vite.config.ts', 'next.config.js', 'app/layout.tsx', 'app/layout.js', 'pages/_document.tsx', 'pages/_document.js', 'test.html' ]; filesToClean.forEach(file => { const filePath = join(testDir, file); if (existsSync(filePath)) { rmSync(filePath); } }); const dirsToClean = ['app', 'pages']; dirsToClean.forEach(dir => { const dirPath = join(testDir, dir); if (existsSync(dirPath)) { rmSync(dirPath, { recursive: true }); } }); }); describe('Vite 项目注入', () => { test('应该成功注入到 Vite 配置文件', () => { // 创建 Vite 配置文件 const viteConfig = `import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], server: { port: 3000 } })`; writeFileSync(join(testDir, 'vite.config.js'), viteConfig); // 执行注入 const result = smartInject({ remote: 'http://localhost:9000/dev-monitor.js', dryRun: true, verbose: true }, testDir); assert.strictEqual(result, true); }); test('应该检查已存在的插件', () => { // 创建已有插件的 Vite 配置 const viteConfigWithPlugin = `import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [ react(), // dev-inject-plugin { name: 'dev-inject-plugin', transformIndexHtml(html) { if (process.env.NODE_ENV === 'development') { return html.replace('', ''); } return html; } } ], server: { port: 3000 } })`; writeFileSync(join(testDir, 'vite.config.js'), viteConfigWithPlugin); // 执行注入(应该检测到已存在) const result = smartInject({ remote: 'http://localhost:9000/dev-monitor.js', dryRun: true }, testDir); assert.strictEqual(result, true); }); test('应该处理没有 plugins 数组的情况', () => { // 创建没有 plugins 的配置 const simpleConfig = `export default { server: { port: 3000 } }`; writeFileSync(join(testDir, 'vite.config.js'), simpleConfig); const result = smartInject({ remote: '/scripts/monitor.js', dryRun: true }, testDir); assert.strictEqual(result, true); }); test('应该处理 TypeScript 配置文件', () => { const tsConfig = `import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()] })`; writeFileSync(join(testDir, 'vite.config.ts'), tsConfig); const result = smartInject({ remote: '/scripts/monitor.js', dryRun: true }, testDir); assert.strictEqual(result, true); }); }); describe('Next.js App Router 注入', () => { test('应该成功注入到 app/layout.tsx', () => { // 创建 Next.js App Router 结构 mkdirSync(join(testDir, 'app'), { recursive: true }); writeFileSync(join(testDir, 'next.config.js'), 'module.exports = {}'); const layoutContent = `import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Next.js App', description: 'Generated by create next app', } export default function RootLayout({ children, }: { children: React.ReactNode }) { return (
{children} ) }`; writeFileSync(join(testDir, 'app', 'layout.tsx'), layoutContent); const result = smartInject({ remote: 'http://localhost:9000/dev-monitor.js', dryRun: true }, testDir); assert.strictEqual(result, true); }); test('应该处理 app/layout.js', () => { mkdirSync(join(testDir, 'app'), { recursive: true }); writeFileSync(join(testDir, 'next.config.js'), 'module.exports = {}'); const jsLayout = `import './globals.css' export default function RootLayout({ children }) { return ( {children} ) }`; writeFileSync(join(testDir, 'app', 'layout.js'), jsLayout); const result = smartInject({ remote: '/scripts/monitor.js', dryRun: true }, testDir); assert.strictEqual(result, true); }); }); describe('Next.js Pages Router 注入', () => { test('应该成功注入到 pages/_document.tsx', () => { mkdirSync(join(testDir, 'pages'), { recursive: true }); writeFileSync(join(testDir, 'next.config.js'), 'module.exports = {}'); const documentContent = `import { Html, Head, Main, NextScript } from 'next/document' export default function Document() { return (