UNPKG

@rstest/core

Version:
1,145 lines (1,123 loc) 33.5 kB
import 'module'; /*#__PURE__*/ import.meta.url; import { __webpack_require__ } from "./rslib-runtime.js"; import "./1157.js"; import "./2672.js"; import { node_process } from "./3278.js"; import { Ie, Me, ye, M, dist_Y, Se, ve, pD, xe } from "./0~9348.js"; __webpack_require__.add({ "../../node_modules/.pnpm/@vercel+detect-agent@1.0.0/node_modules/@vercel/detect-agent/dist/index.js" (module, __unused_rspack_exports, __webpack_require__) { var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all)=>{ for(var name in all)__defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc)=>{ if (from && "object" == typeof from || "function" == typeof from) { for (let key of __getOwnPropNames(from))if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ()=>from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod)=>__copyProps(__defProp({}, "__esModule", { value: true }), mod); var src_exports = {}; __export(src_exports, { KNOWN_AGENTS: ()=>KNOWN_AGENTS, determineAgent: ()=>determineAgent }); module.exports = __toCommonJS(src_exports); var import_promises = __webpack_require__("node:fs/promises"); var import_node_fs = __webpack_require__("fs"); const DEVIN_LOCAL_PATH = "/opt/.devin"; const CURSOR = "cursor"; const CURSOR_CLI = "cursor-cli"; const CLAUDE = "claude"; const DEVIN = "devin"; const REPLIT = "replit"; const GEMINI = "gemini"; const CODEX = "codex"; const KNOWN_AGENTS = { CURSOR, CURSOR_CLI, CLAUDE, DEVIN, REPLIT, GEMINI, CODEX }; async function determineAgent() { if (process.env.AI_AGENT) { const name = process.env.AI_AGENT.trim(); if (name) return { isAgent: true, agent: { name } }; } if (process.env.CURSOR_TRACE_ID) return { isAgent: true, agent: { name: CURSOR } }; if (process.env.CURSOR_AGENT) return { isAgent: true, agent: { name: CURSOR_CLI } }; if (process.env.GEMINI_CLI) return { isAgent: true, agent: { name: GEMINI } }; if (process.env.CODEX_SANDBOX) return { isAgent: true, agent: { name: CODEX } }; if (process.env.CLAUDECODE || process.env.CLAUDE_CODE) return { isAgent: true, agent: { name: CLAUDE } }; if (process.env.REPL_ID) return { isAgent: true, agent: { name: REPLIT } }; try { await (0, import_promises.access)(DEVIN_LOCAL_PATH, import_node_fs.constants.F_OK); return { isAgent: true, agent: { name: DEVIN } }; } catch (error) {} return { isAgent: false, agent: void 0 }; } } }); const constants_AGENTS = [ "npm", "yarn", "yarn@berry", "pnpm", "pnpm@6", "bun", "deno" ]; const LOCKS = { "bun.lock": "bun", "bun.lockb": "bun", "deno.lock": "deno", "pnpm-lock.yaml": "pnpm", "pnpm-workspace.yaml": "pnpm", "yarn.lock": "yarn", "package-lock.json": "npm", "npm-shrinkwrap.json": "npm" }; const INSTALL_METADATA = { "node_modules/.deno/": "deno", "node_modules/.pnpm/": "pnpm", "node_modules/.yarn-state.yml": "yarn", "node_modules/.yarn_integrity": "yarn", "node_modules/.package-lock.json": "npm", ".pnp.cjs": "yarn", ".pnp.js": "yarn", "bun.lock": "bun", "bun.lockb": "bun" }; const promises_ = __webpack_require__("node:fs/promises"); const external_node_path_ = __webpack_require__("node:path"); async function pathExists(path2, type) { try { const stat = await promises_["default"].stat(path2); return "file" === type ? stat.isFile() : stat.isDirectory(); } catch { return false; } } function* lookup(cwd = node_process.cwd()) { let directory = external_node_path_["default"].resolve(cwd); const { root } = external_node_path_["default"].parse(directory); while(directory && directory !== root){ yield directory; directory = external_node_path_["default"].dirname(directory); } } async function parsePackageJson(filepath, options) { if (!filepath || !await pathExists(filepath, "file")) return null; return await handlePackageManager(filepath, options); } async function detect(options = {}) { const { cwd, strategies = [ "lockfile", "packageManager-field", "devEngines-field" ] } = options; let stopDir; if ("string" == typeof options.stopDir) { const resolved = external_node_path_["default"].resolve(options.stopDir); stopDir = (dir)=>dir === resolved; } else stopDir = options.stopDir; for (const directory of lookup(cwd)){ for (const strategy of strategies)switch(strategy){ case "lockfile": for (const lock of Object.keys(LOCKS))if (await pathExists(external_node_path_["default"].join(directory, lock), "file")) { const name = LOCKS[lock]; const result = await parsePackageJson(external_node_path_["default"].join(directory, "package.json"), options); if (result) return result; return { name, agent: name }; } break; case "packageManager-field": case "devEngines-field": { const result = await parsePackageJson(external_node_path_["default"].join(directory, "package.json"), options); if (result) return result; break; } case "install-metadata": for (const metadata of Object.keys(INSTALL_METADATA)){ const fileOrDir = metadata.endsWith("/") ? "dir" : "file"; if (await pathExists(external_node_path_["default"].join(directory, metadata), fileOrDir)) { const name = INSTALL_METADATA[metadata]; const agent = "yarn" === name ? isMetadataYarnClassic(metadata) ? "yarn" : "yarn@berry" : name; return { name, agent }; } } break; } if (stopDir?.(directory)) break; } return null; } function getNameAndVer(pkg) { const handelVer = (version)=>version?.match(/\d+(\.\d+){0,2}/)?.[0] ?? version; if ("string" == typeof pkg.packageManager) { const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@"); return { name, ver: handelVer(ver) }; } if ("string" == typeof pkg.devEngines?.packageManager?.name) return { name: pkg.devEngines.packageManager.name, ver: handelVer(pkg.devEngines.packageManager.version) }; } async function handlePackageManager(filepath, options) { try { const content = await promises_["default"].readFile(filepath, "utf8"); const pkg = options.packageJsonParser ? await options.packageJsonParser(content, filepath) : JSON.parse(content); let agent; const nameAndVer = getNameAndVer(pkg); if (nameAndVer) { const name = nameAndVer.name; const ver = nameAndVer.ver; let version = ver; if ("yarn" === name && ver && Number.parseInt(ver) > 1) { agent = "yarn@berry"; version = "berry"; return { name, agent, version }; } if ("pnpm" === name && ver && Number.parseInt(ver) < 7) { agent = "pnpm@6"; return { name, agent, version }; } if (!constants_AGENTS.includes(name)) return options.onUnknown?.(pkg.packageManager) ?? null; agent = name; return { name, agent, version }; } } catch {} return null; } function isMetadataYarnClassic(metadataPath) { return metadataPath.endsWith(".yarn_integrity"); } const external_node_fs_ = __webpack_require__("fs"); function getUniqueBaseName(dir, baseName, ext) { const fullPath = external_node_path_["default"].join(dir, `${baseName}${ext}`); if (!external_node_fs_["default"].existsSync(fullPath)) return baseName; let suffix = 1; while(external_node_fs_["default"].existsSync(external_node_path_["default"].join(dir, `${baseName}_${suffix}${ext}`)))suffix++; return `${baseName}_${suffix}`; } function ensureDir(dir) { if (!external_node_fs_["default"].existsSync(dir)) external_node_fs_["default"].mkdirSync(dir, { recursive: true }); } function writeFile(filePath, content) { external_node_fs_["default"].writeFileSync(filePath, content, 'utf-8'); } function readPackageJson(cwd) { const pkgPath = external_node_path_["default"].join(cwd, 'package.json'); if (!external_node_fs_["default"].existsSync(pkgPath)) return null; try { const content = external_node_fs_["default"].readFileSync(pkgPath, 'utf-8'); return JSON.parse(content); } catch { return null; } } function updatePackageJsonScripts(cwd, scripts) { const pkgPath = external_node_path_["default"].join(cwd, 'package.json'); let pkg; if (external_node_fs_["default"].existsSync(pkgPath)) { const content = external_node_fs_["default"].readFileSync(pkgPath, 'utf-8'); pkg = JSON.parse(content); } else pkg = {}; const existingScripts = pkg.scripts ?? {}; pkg.scripts = { ...existingScripts, ...scripts }; external_node_fs_["default"].writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf-8'); } function updatePackageJsonDevDeps(cwd, deps) { const pkgPath = external_node_path_["default"].join(cwd, 'package.json'); let pkg; if (external_node_fs_["default"].existsSync(pkgPath)) { const content = external_node_fs_["default"].readFileSync(pkgPath, 'utf-8'); pkg = JSON.parse(content); } else pkg = {}; const existingDevDeps = pkg.devDependencies ?? {}; for (const [name, version] of Object.entries(deps))if (!existingDevDeps[name]) existingDevDeps[name] = version; pkg.devDependencies = existingDevDeps; external_node_fs_["default"].writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf-8'); } async function detectPackageManagerAgent(cwd) { const result = await detect({ cwd }); return result?.agent ?? 'npm'; } function detectTestDir(cwd) { const candidates = [ 'tests', 'test', '__tests__', 'src/__tests__' ]; for (const dir of candidates){ const fullPath = external_node_path_["default"].join(cwd, dir); if (external_node_fs_["default"].existsSync(fullPath) && external_node_fs_["default"].statSync(fullPath).isDirectory()) return dir; } return 'tests'; } function detectReact(pkg) { const deps = pkg.dependencies ?? {}; const devDeps = pkg.devDependencies ?? {}; const reactVersion = deps.react ?? devDeps.react ?? null; if (reactVersion) { const cleanVersion = reactVersion.replace(/^[\^~>=<]+/, ''); return { detected: true, version: cleanVersion }; } return { detected: false, version: null }; } function detectTypeScript(cwd) { return external_node_fs_["default"].existsSync(external_node_path_["default"].join(cwd, 'tsconfig.json')); } async function detectProject(cwd) { const pkg = readPackageJson(cwd); const { detected: hasReact, version: reactVersion } = pkg ? detectReact(pkg) : { detected: false, version: null }; const hasTypeScript = detectTypeScript(cwd); const testDir = detectTestDir(cwd); const agent = await detectPackageManagerAgent(cwd); return { framework: hasReact ? 'react' : null, language: hasTypeScript ? 'ts' : 'js', testDir, agent, reactVersion }; } function dashDashArg(agent, agentCommand) { return (args)=>{ if (args.length > 1) return [ agent, agentCommand, args[0], "--", ...args.slice(1) ]; return [ agent, agentCommand, args[0] ]; }; } function denoExecute() { return (args)=>[ "deno", "run", `npm:${args[0]}`, ...args.slice(1) ]; } const npm = { agent: [ "npm", 0 ], run: dashDashArg("npm", "run"), install: [ "npm", "i", 0 ], frozen: [ "npm", "ci", 0 ], global: [ "npm", "i", "-g", 0 ], add: [ "npm", "i", 0 ], upgrade: [ "npm", "update", 0 ], "upgrade-interactive": null, dedupe: [ "npm", "dedupe", 0 ], execute: [ "npx", 0 ], "execute-local": [ "npx", 0 ], uninstall: [ "npm", "uninstall", 0 ], global_uninstall: [ "npm", "uninstall", "-g", 0 ] }; const yarn = { agent: [ "yarn", 0 ], run: [ "yarn", "run", 0 ], install: [ "yarn", "install", 0 ], frozen: [ "yarn", "install", "--frozen-lockfile", 0 ], global: [ "yarn", "global", "add", 0 ], add: [ "yarn", "add", 0 ], upgrade: [ "yarn", "upgrade", 0 ], "upgrade-interactive": [ "yarn", "upgrade-interactive", 0 ], dedupe: null, execute: [ "npx", 0 ], "execute-local": dashDashArg("yarn", "exec"), uninstall: [ "yarn", "remove", 0 ], global_uninstall: [ "yarn", "global", "remove", 0 ] }; const yarnBerry = { ...yarn, frozen: [ "yarn", "install", "--immutable", 0 ], upgrade: [ "yarn", "up", 0 ], "upgrade-interactive": [ "yarn", "up", "-i", 0 ], dedupe: [ "yarn", "dedupe", 0 ], execute: [ "yarn", "dlx", 0 ], "execute-local": [ "yarn", "exec", 0 ], global: [ "npm", "i", "-g", 0 ], global_uninstall: [ "npm", "uninstall", "-g", 0 ] }; const pnpm = { agent: [ "pnpm", 0 ], run: [ "pnpm", "run", 0 ], install: [ "pnpm", "i", 0 ], frozen: [ "pnpm", "i", "--frozen-lockfile", 0 ], global: [ "pnpm", "add", "-g", 0 ], add: [ "pnpm", "add", 0 ], upgrade: [ "pnpm", "update", 0 ], "upgrade-interactive": [ "pnpm", "update", "-i", 0 ], dedupe: [ "pnpm", "dedupe", 0 ], execute: [ "pnpm", "dlx", 0 ], "execute-local": [ "pnpm", "exec", 0 ], uninstall: [ "pnpm", "remove", 0 ], global_uninstall: [ "pnpm", "remove", "--global", 0 ] }; const bun = { agent: [ "bun", 0 ], run: [ "bun", "run", 0 ], install: [ "bun", "install", 0 ], frozen: [ "bun", "install", "--frozen-lockfile", 0 ], global: [ "bun", "add", "-g", 0 ], add: [ "bun", "add", 0 ], upgrade: [ "bun", "update", 0 ], "upgrade-interactive": [ "bun", "update", "-i", 0 ], dedupe: null, execute: [ "bun", "x", 0 ], "execute-local": [ "bun", "x", 0 ], uninstall: [ "bun", "remove", 0 ], global_uninstall: [ "bun", "remove", "-g", 0 ] }; const deno = { agent: [ "deno", 0 ], run: [ "deno", "task", 0 ], install: [ "deno", "install", 0 ], frozen: [ "deno", "install", "--frozen", 0 ], global: [ "deno", "install", "-g", 0 ], add: [ "deno", "add", 0 ], upgrade: [ "deno", "outdated", "--update", 0 ], "upgrade-interactive": [ "deno", "outdated", "--update", 0 ], dedupe: null, execute: denoExecute(), "execute-local": [ "deno", "task", "--eval", 0 ], uninstall: [ "deno", "remove", 0 ], global_uninstall: [ "deno", "uninstall", "-g", 0 ] }; const COMMANDS = { npm: npm, yarn: yarn, "yarn@berry": yarnBerry, pnpm: pnpm, "pnpm@6": { ...pnpm, run: dashDashArg("pnpm", "run") }, bun: bun, deno: deno }; function resolveCommand(agent, command, args) { const value = COMMANDS[agent][command]; return constructCommand(value, args); } function constructCommand(value, args) { if (null == value) return null; const list = "function" == typeof value ? value(args) : value.flatMap((v)=>{ if ("number" == typeof v) return args; return [ v ]; }); return { command: list[0], args: list.slice(1) }; } function getConfigTemplate() { return `import { defineConfig } from '@rstest/core'; export default defineConfig({ browser: { enabled: true, }, }); `; } function getReactComponentTemplate(lang) { if ('ts' === lang) return `import { useState } from 'react'; export default function Counter({ initial = 0 }: { initial?: number }) { const [count, setCount] = useState(initial); return ( <div> <p>Count: {count}</p> <button type="button" onClick={() => setCount((c) => c + 1)}> Increment </button> <button type="button" onClick={() => setCount((c) => c - 1)}> Decrement </button> </div> ); } `; return `import { useState } from 'react'; export default function Counter({ initial = 0 }) { const [count, setCount] = useState(initial); return ( <div> <p>Count: {count}</p> <button type="button" onClick={() => setCount((c) => c + 1)}> Increment </button> <button type="button" onClick={() => setCount((c) => c - 1)}> Decrement </button> </div> ); } `; } function getReactTestTemplate(lang) { const componentExt = 'ts' === lang ? 'tsx' : 'jsx'; return `import { expect, test } from '@rstest/core'; import { render } from '@rstest/browser-react'; import Counter from './Counter.${componentExt}'; test('increments count on button click', async () => { const screen = await render(<Counter initial={5} />); await expect.element(screen.getByText('Count: 5')).toBeInTheDocument(); await screen.getByRole('button', { name: 'Increment' }).click(); await expect.element(screen.getByText('Count: 6')).toBeInTheDocument(); }); `; } function getVanillaComponentTemplate(lang) { if ('ts' === lang) return `export function createCounter(initial = 0): HTMLElement { let count = initial; const container = document.createElement('div'); const display = document.createElement('p'); const incBtn = document.createElement('button'); const decBtn = document.createElement('button'); display.textContent = \`Count: \${count}\`; incBtn.textContent = 'Increment'; decBtn.textContent = 'Decrement'; incBtn.addEventListener('click', () => { count++; display.textContent = \`Count: \${count}\`; }); decBtn.addEventListener('click', () => { count--; display.textContent = \`Count: \${count}\`; }); container.append(display, incBtn, decBtn); return container; } `; return `export function createCounter(initial = 0) { let count = initial; const container = document.createElement('div'); const display = document.createElement('p'); const incBtn = document.createElement('button'); const decBtn = document.createElement('button'); display.textContent = \`Count: \${count}\`; incBtn.textContent = 'Increment'; decBtn.textContent = 'Decrement'; incBtn.addEventListener('click', () => { count++; display.textContent = \`Count: \${count}\`; }); decBtn.addEventListener('click', () => { count--; display.textContent = \`Count: \${count}\`; }); container.append(display, incBtn, decBtn); return container; } `; } function getVanillaTestTemplate(lang) { const ext = 'ts' === lang ? 'ts' : 'js'; return `import { expect, test } from '@rstest/core'; import { page } from '@rstest/browser'; import { createCounter } from './Counter.${ext}'; test('increments count on button click', async () => { document.body.appendChild(createCounter(5)); await expect.element(page.getByText('Count: 5')).toBeInTheDocument(); await page.getByRole('button', { name: 'Increment' }).click(); await expect.element(page.getByText('Count: 6')).toBeInTheDocument(); }); `; } function getDependenciesWithVersions(framework, provider, rstestVersion) { const deps = { '@rstest/browser': `^${rstestVersion}`, '@testing-library/dom': '^10.0.0' }; if ('playwright' === provider) deps.playwright = "^1.49.1"; if ('react' === framework) deps['@rstest/browser-react'] = `^${rstestVersion}`; return deps; } function getInstallCommand(agent) { const resolved = resolveCommand(agent, 'install', []); if (!resolved) return 'npm install'; return [ resolved.command, ...resolved.args ].join(' '); } function getPlaywrightInstallCommand(agent, _provider) { const resolved = resolveCommand(agent, 'execute', [ 'playwright', 'install', '--with-deps' ]); if (!resolved) return 'npx playwright install --with-deps'; return [ resolved.command, ...resolved.args ].join(' '); } function getRunCommand(agent) { const resolved = resolveCommand(agent, 'run', [ 'test:browser' ]); if (!resolved) return 'npm run test:browser'; return [ resolved.command, ...resolved.args ].join(' '); } function getConfigFileName() { return 'rstest.browser.config.ts'; } const dist = __webpack_require__("../../node_modules/.pnpm/@vercel+detect-agent@1.0.0/node_modules/@vercel/detect-agent/dist/index.js"); const picocolors = __webpack_require__("../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"); var picocolors_default = /*#__PURE__*/ __webpack_require__.n(picocolors); async function create(options = {}) { const cwd = process.cwd(); const { yes: nonInteractive } = options; const projectInfo = await detectProject(cwd); const { isAgent } = await (0, dist.determineAgent)(); if (nonInteractive) await createNonInteractive(cwd, projectInfo); else await createInteractive(cwd, projectInfo, isAgent); } function computeFilePreview(cwd, projectInfo) { const { language, testDir, framework } = projectInfo; const effectiveFramework = 'react' === framework ? 'react' : 'vanilla'; const configFile = getConfigFileName(); let componentExt; let testExt; if ('react' === effectiveFramework) { componentExt = 'ts' === language ? '.tsx' : '.jsx'; testExt = 'ts' === language ? '.test.tsx' : '.test.jsx'; } else { componentExt = 'ts' === language ? '.ts' : '.js'; testExt = 'ts' === language ? '.test.ts' : '.test.js'; } const testDirPath = external_node_path_["default"].join(cwd, testDir); const baseName = getUniqueBaseName(testDirPath, 'Counter', componentExt); return { configFile, componentFile: `${testDir}/${baseName}${componentExt}`, testFile: `${testDir}/${baseName}${testExt}`, framework: effectiveFramework }; } async function createNonInteractive(cwd, projectInfo) { const { agent, testDir, framework, reactVersion } = projectInfo; const provider = 'playwright'; console.log(); console.log(picocolors_default().cyan('◆'), picocolors_default().bold('rstest init browser --yes')); console.log(); console.log(' Detecting project...'); if ('react' === framework && reactVersion) console.log(picocolors_default().green(' ✓'), `Found React ${reactVersion}`); else if ('react' === framework) console.log(picocolors_default().green(' ✓'), 'Found React'); else console.log(picocolors_default().yellow(' ⚠'), 'Framework not detected, generating vanilla DOM example'); console.log(picocolors_default().green(' ✓'), 'Using playwright as browser provider'); console.log(picocolors_default().green(' ✓'), `Test directory: ${testDir}/`); console.log(); const createdFiles = await generateFiles(cwd, projectInfo, provider); console.log(' Created files:'); for (const file of createdFiles)console.log(` - ${file}`); console.log(' - Updated package.json'); console.log(); console.log(' Next steps:'); console.log(` ${getInstallCommand(agent)}`); console.log(` ${getPlaywrightInstallCommand(agent, provider)}`); console.log(` ${getRunCommand(agent)}`); console.log(); console.log(picocolors_default().green('└'), 'Done!'); } async function createInteractive(cwd, projectInfo, isAgent) { const { agent, language, testDir, framework, reactVersion } = projectInfo; const effectiveFramework = 'react' === framework ? 'react' : 'vanilla'; Ie(picocolors_default().bgCyan(picocolors_default().black(' rstest init browser '))); const detectionLines = []; if ('react' === framework && reactVersion) detectionLines.push(`${picocolors_default().green('✓')} Found React ${reactVersion}`); else if ('react' === framework) detectionLines.push(`${picocolors_default().green('✓')} Found React`); else detectionLines.push(`${picocolors_default().yellow('⚠')} Framework not detected, will generate vanilla DOM example`); detectionLines.push(`${picocolors_default().green('✓')} Found ${'ts' === language ? 'TypeScript' : 'JavaScript'}`); detectionLines.push(`${picocolors_default().green('✓')} Test directory: ${testDir}/`); Me(detectionLines.join('\n'), 'Detecting project...'); if (isAgent) M.info(`AI Agent detected. For non-interactive mode, run:\n ${picocolors_default().cyan('npx rstest init browser --yes')}`); const providerSelection = await ve({ message: 'Choose a browser provider (so far, only Playwright)', options: [ { value: 'playwright', label: 'Playwright', hint: 'recommended' } ] }); if (pD(providerSelection)) { xe('Operation cancelled.'); process.exit(0); } const provider = providerSelection; const preview = computeFilePreview(cwd, projectInfo); const deps = getDependenciesWithVersions(effectiveFramework, provider, "0.7.9"); const depsList = Object.entries(deps).map(([name, version])=>`${name}@${version}`).join(', '); const previewLines = [ `${picocolors_default().cyan('+')} Create ${preview.configFile}`, `${picocolors_default().cyan('+')} Create ${preview.componentFile}`, `${picocolors_default().cyan('+')} Create ${preview.testFile}`, `${picocolors_default().yellow('~')} Modify package.json`, ' - Add "test:browser" script', ` - Add devDependencies: ${picocolors_default().dim(depsList)}` ]; Me(previewLines.join('\n'), 'Changes to be made'); const confirmed = await ye({ message: 'Proceed with these changes?', initialValue: true }); if (pD(confirmed) || !confirmed) { xe('Operation cancelled.'); process.exit(0); } const s = dist_Y(); s.start('Creating files...'); const createdFiles = await generateFiles(cwd, projectInfo, provider); s.stop('Created files'); const fileLines = createdFiles.map((f)=>`${picocolors_default().green('✓')} Created ${f}`); fileLines.push(`${picocolors_default().green('✓')} Updated package.json`); Me(fileLines.join('\n'), 'Files'); const nextStepsLines = [ `${picocolors_default().bold('1.')} Install dependencies:`, ` ${picocolors_default().cyan(getInstallCommand(agent))}`, '', `${picocolors_default().bold('2.')} Install Playwright browsers:`, ` ${picocolors_default().cyan(getPlaywrightInstallCommand(agent, provider))}`, '', `${picocolors_default().bold('3.')} Run your tests:`, ` ${picocolors_default().cyan(getRunCommand(agent))}` ]; Me(nextStepsLines.join('\n'), 'Next steps'); Se(picocolors_default().green('Done! Happy testing with Rstest!')); } async function generateFiles(cwd, projectInfo, provider) { const { language, testDir, framework } = projectInfo; const effectiveFramework = 'react' === framework ? 'react' : 'vanilla'; const createdFiles = []; const configFileName = getConfigFileName(); const configPath = external_node_path_["default"].join(cwd, configFileName); writeFile(configPath, getConfigTemplate()); createdFiles.push(configFileName); const testDirPath = external_node_path_["default"].join(cwd, testDir); ensureDir(testDirPath); let componentExt; let testExt; if ('react' === effectiveFramework) { componentExt = 'ts' === language ? '.tsx' : '.jsx'; testExt = 'ts' === language ? '.test.tsx' : '.test.jsx'; } else { componentExt = 'ts' === language ? '.ts' : '.js'; testExt = 'ts' === language ? '.test.ts' : '.test.js'; } const baseName = getUniqueBaseName(testDirPath, 'Counter', componentExt); const componentFileName = `${baseName}${componentExt}`; const componentPath = external_node_path_["default"].join(testDirPath, componentFileName); 'react' === effectiveFramework ? writeFile(componentPath, getReactComponentTemplate(language)) : writeFile(componentPath, getVanillaComponentTemplate(language)); createdFiles.push(`${testDir}/${componentFileName}`); const testFileName = `${baseName}${testExt}`; const testPath = external_node_path_["default"].join(testDirPath, testFileName); let testContent; if ('react' === effectiveFramework) { testContent = getReactTestTemplate(language); if ('Counter' !== baseName) testContent = testContent.replace(/from '\.\/Counter\.(tsx|jsx)'/, `from './${baseName}.$1'`); } else { testContent = getVanillaTestTemplate(language); if ('Counter' !== baseName) testContent = testContent.replace(/from '\.\/Counter\.(ts|js)'/, `from './${baseName}.$1'`); } writeFile(testPath, testContent); createdFiles.push(`${testDir}/${testFileName}`); updatePackageJsonScripts(cwd, { 'test:browser': 'rstest --config=rstest.browser.config.ts' }); const deps = getDependenciesWithVersions(effectiveFramework, provider, "0.7.9"); updatePackageJsonDevDeps(cwd, deps); return createdFiles; } export { create };