UNPKG

next-start-cli

Version:

This is a CLI tool to create a nextjs project and add the necessary dependencies and configurations

215 lines (182 loc) 6.38 kB
import { createSpinner } from "nanospinner"; import chalk from "chalk"; import fs from "fs/promises"; import path from "path"; import { execa } from "execa"; import inquirer from "inquirer"; export const setupUnitTestFramework = async (project, noGit = false) => { console.log(chalk.gray("─".repeat(50))); console.log(chalk.green(`Setting up unit test framework for ${project}`)); // Add test framework selection with skip option const { setupTests } = await inquirer.prompt({ type: "list", name: "setupTests", message: "Select a unit testing framework", choices: [ { name: "Vitest", value: "vitest" }, { name: "Jest", value: "jest" }, { name: "Skip unit testing", value: "skip" }, ], default: "vitest", }); // Exit early if user chose to skip if (setupTests === "skip") { console.log(chalk.yellow("Skipping test framework setup...")); return; } // Install selected testing framework const testFramework = setupTests; // Just for clarity console.log(chalk.cyan(`Installing ${testFramework} testing framework...`)); try { if (testFramework === "vitest") { await execa("yarn", [ "add", "--dev", "vitest", "@vitejs/plugin-react", "jsdom", "@testing-library/react", "@testing-library/jest-dom", "@testing-library/dom", "vite-tsconfig-paths", ], { stdio: "inherit" }); // Create vitest config const vitestConfig = ` import { defineConfig } from 'vitest/config' import react from '@vitejs/plugin-react' import tsconfigPaths from 'vite-tsconfig-paths' export default defineConfig({ plugins: [tsconfigPaths(), react()], test: { environment: 'jsdom', }, });`; await fs.writeFile( path.join(process.cwd(), "vitest.config.mts"), vitestConfig, "utf8" ); // Create test setup file const setupDir = path.join(process.cwd(), "src", "__test__"); await fs.mkdir(setupDir, { recursive: true }); const setupContent = `import '@testing-library/jest-dom';`; await fs.writeFile(path.join(setupDir, "setup.ts"), setupContent, "utf8"); // Update package.json scripts const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse( await fs.readFile(packageJsonPath, "utf8") ); packageJson.scripts = { ...packageJson.scripts, test: "vitest run", "test:watch": "vitest", "test:ui": "vitest --ui", coverage: "vitest run --coverage", }; await fs.writeFile( packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8" ); // Create page test file for Vitest const pageTestDir = path.join(process.cwd(), "src", "__tests__"); await fs.mkdir(pageTestDir, { recursive: true }); const pageTestContent = `import { expect, test } from 'vitest' import { render, screen } from '@testing-library/react' import Home from '../app/(client)/page' test('Home', () => { render(<Home />) expect(screen.getByRole('heading', { level: 1, name: 'Home' })).toBeDefined() })`; await fs.writeFile( path.join(pageTestDir, "page.test.tsx"), pageTestContent, "utf8" ); console.log(chalk.green("✓ Created page test file")); } else if (testFramework === "jest") { // Install Jest await execa("yarn", [ "add", "--dev", "jest", "jest-environment-jsdom", "@testing-library/react", "@testing-library/dom", "@testing-library/jest-dom", "ts-node", ], { stdio: "inherit" }); // Create Jest config const jestConfig = ` import type { Config } from 'jest' import nextJest from 'next/jest.js' const createJestConfig = nextJest({ // Provide the path to your Next.js app to load next.config.js and .env files in your test environment dir: './', }) // Add any custom config to be passed to Jest const config: Config = { coverageProvider: 'v8', testEnvironment: 'jsdom', // Add more setup options before each test is run setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'], } // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async export default createJestConfig(config)`; await fs.writeFile( path.join(process.cwd(), "jest.config.ts"), jestConfig, "utf8" ); // Create Jest setup file const jestSetup = `import "@testing-library/jest-dom";`; await fs.writeFile( path.join(process.cwd(), "jest.setup.ts"), jestSetup, "utf8" ); // Update package.json scripts const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse( await fs.readFile(packageJsonPath, "utf8") ); packageJson.scripts = { ...packageJson.scripts, test: "jest", "test:watch": "jest --watch", coverage: "jest --coverage", }; await fs.writeFile( packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8" ); // Create page test file for Jest const pageTestDir = path.join(process.cwd(), "src", "__tests__"); await fs.mkdir(pageTestDir, { recursive: true }); const pageTestContent = `import "@testing-library/jest-dom"; import { render, screen } from "@testing-library/react"; import Home from "../app/(client)/page"; describe("Home", () => { it("renders a heading", () => { render(<Home />); const heading = screen.getByRole("heading", { level: 1 }); expect(heading).toBeInTheDocument(); }); });`; await fs.writeFile( path.join(pageTestDir, "page.test.tsx"), pageTestContent, "utf8" ); console.log(chalk.green("✓ Created page test file")); } console.log(chalk.green(`✓ ${testFramework} testing framework installed successfully`)); } catch (error) { console.error(chalk.red(`Failed to set up ${testFramework}: ${error.message}`)); console.error(chalk.red(`Error details: ${error.stack}`)); } console.log(chalk.gray("─".repeat(50))); console.log(chalk.green(`\n✅ Testing framework setup completed`)); console.log(chalk.yellow(`Run tests with: yarn test`)); };