letsrunit 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -50,7 +50,7 @@ function installCli(env) {
50
50
  // src/setup/cucumber.ts
51
51
  import { existsSync as existsSync3, mkdirSync, readdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
52
52
  import { join as join3 } from "path";
53
- var BDD_IMPORT = "@letsrunit/bdd/define";
53
+ var BDD_IMPORT = "@letsrunit/cucumber";
54
54
  var CUCUMBER_CONFIG = `export default {
55
55
  require: ['features/support/**/*.js'],
56
56
  worldParameters: {
@@ -79,13 +79,13 @@ function installBdd(env) {
79
79
  const pkgPath = join3(env.cwd, "package.json");
80
80
  if (!existsSync3(pkgPath)) return false;
81
81
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
82
- const alreadyInstalled = "@letsrunit/bdd" in (pkg.devDependencies ?? {}) || "@letsrunit/bdd" in (pkg.dependencies ?? {});
82
+ const alreadyInstalled = "@letsrunit/cucumber" in (pkg.devDependencies ?? {}) || "@letsrunit/cucumber" in (pkg.dependencies ?? {});
83
83
  if (alreadyInstalled) return false;
84
84
  execPm(env, {
85
- npm: "install --save-dev @letsrunit/bdd",
86
- yarn: "add --dev @letsrunit/bdd",
87
- pnpm: "add -D @letsrunit/bdd",
88
- bun: "add -d @letsrunit/bdd"
85
+ npm: "install --save-dev @letsrunit/cucumber",
86
+ yarn: "add --dev @letsrunit/cucumber",
87
+ pnpm: "add -D @letsrunit/cucumber",
88
+ bun: "add -d @letsrunit/cucumber"
89
89
  });
90
90
  return true;
91
91
  }
@@ -217,7 +217,7 @@ function installPlaywrightBrowsers(env) {
217
217
  }
218
218
 
219
219
  // src/init.ts
220
- var BDD_IMPORT2 = "@letsrunit/bdd/define";
220
+ var BDD_IMPORT2 = "@letsrunit/cucumber";
221
221
  async function stepInstallCli(env) {
222
222
  if (isCliInstalled(env)) {
223
223
  log.success("@letsrunit/cli already installed");
@@ -247,11 +247,11 @@ async function stepEnsureCucumber(env, { yes: yes2 }) {
247
247
  }
248
248
  function stepSetupCucumber(env) {
249
249
  const result = setupCucumber(env);
250
- if (result.bddInstalled) log.success("@letsrunit/bdd installed");
250
+ if (result.bddInstalled) log.success("@letsrunit/cucumber installed");
251
251
  if (result.configResult === "created") {
252
252
  log.success("features/support/world.js created");
253
253
  } else if (result.configResult === "needs-manual-update") {
254
- log.warn("features/support/world.js exists but does not import @letsrunit/bdd.");
254
+ log.warn("features/support/world.js exists but does not import @letsrunit/cucumber.");
255
255
  note(`Add "import '${BDD_IMPORT2}';" to features/support/world.js`, "Action required");
256
256
  }
257
257
  if (result.featuresCreated) log.success("features/ directory created with example.feature");
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/init.ts","../src/detect.ts","../src/setup/cli.ts","../src/setup/cucumber.ts","../src/setup/github-actions.ts","../src/setup/playwright.ts","../src/bin.ts"],"sourcesContent":["import { confirm, intro, log, note, outro, spinner } from '@clack/prompts';\nimport { detectEnvironment, type Environment } from './detect.js';\nimport { installCli, isCliInstalled } from './setup/cli.js';\nimport { installCucumber, setupCucumber } from './setup/cucumber.js';\nimport { installGithubAction } from './setup/github-actions.js';\nimport { hasPlaywrightBrowsers, installPlaywrightBrowsers } from './setup/playwright.js';\n\nconst BDD_IMPORT = '@letsrunit/bdd/define';\n\nexport interface InitOptions {\n yes?: boolean;\n}\n\nasync function stepInstallCli(env: Environment): Promise<void> {\n if (isCliInstalled(env)) {\n log.success('@letsrunit/cli already installed');\n return;\n }\n\n const s = spinner();\n s.start('Installing @letsrunit/cli…');\n installCli(env);\n s.stop('@letsrunit/cli installed');\n}\n\nasync function stepEnsureCucumber(env: Environment, { yes }: InitOptions): Promise<boolean> {\n if (env.hasCucumber) return true;\n\n if (!yes && !env.isInteractive) {\n log.warn('@cucumber/cucumber not found. Install it to use letsrunit with Cucumber:');\n note('npm install --save-dev @cucumber/cucumber\\nThen run: npx letsrunit init', 'Setup Cucumber');\n return false;\n }\n\n if (!yes) {\n const install = await confirm({ message: '@cucumber/cucumber not found. Install it now?' });\n if (install !== true) return false;\n }\n\n const s = spinner();\n s.start('Installing @cucumber/cucumber…');\n installCucumber(env);\n s.stop('@cucumber/cucumber installed');\n return true;\n}\n\nfunction stepSetupCucumber(env: Environment): void {\n const result = setupCucumber(env);\n\n if (result.bddInstalled) log.success('@letsrunit/bdd installed');\n\n if (result.configResult === 'created') {\n log.success('features/support/world.js created');\n } else if (result.configResult === 'needs-manual-update') {\n log.warn('features/support/world.js exists but does not import @letsrunit/bdd.');\n note(`Add \"import '${BDD_IMPORT}';\" to features/support/world.js`, 'Action required');\n }\n\n if (result.featuresCreated) log.success('features/ directory created with example.feature');\n}\n\nasync function stepCheckPlaywrightBrowsers(env: Environment, { yes }: InitOptions): Promise<void> {\n if (hasPlaywrightBrowsers(env)) return;\n\n if (!yes && !env.isInteractive) {\n log.warn('Playwright Chromium browser not found.');\n note('npx playwright install chromium', 'Run to install browsers');\n return;\n }\n\n if (!yes) {\n const install = await confirm({ message: 'Playwright Chromium browser not found. Install it now?' });\n if (install !== true) return;\n }\n\n const s = spinner();\n s.start('Installing Playwright Chromium…');\n installPlaywrightBrowsers(env);\n s.stop('Playwright Chromium installed');\n}\n\nasync function stepAddGithubAction(env: Environment, { yes }: InitOptions): Promise<void> {\n if (!yes && !env.isInteractive) return;\n\n if (!yes) {\n const addAction = await confirm({ message: 'Add a GitHub Action to run features on push?' });\n if (addAction !== true) return;\n }\n\n const result = installGithubAction(env);\n if (result === 'created') {\n log.success('.github/workflows/letsrunit.yml created');\n } else {\n log.info('.github/workflows/letsrunit.yml already exists, skipped');\n }\n}\n\nexport async function init(options: InitOptions = {}): Promise<void> {\n intro('letsrunit init');\n\n const env = detectEnvironment();\n\n await stepInstallCli(env);\n\n const hasCucumber = await stepEnsureCucumber(env, options);\n if (hasCucumber) {\n stepSetupCucumber(env);\n await stepCheckPlaywrightBrowsers(env, options);\n await stepAddGithubAction(env, options);\n }\n\n outro('All done! Run npx letsrunit --help to get started.');\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'yarn' | 'pnpm' | 'bun' | 'npm';\n\nexport interface Environment {\n isInteractive: boolean;\n packageManager: PackageManager;\n nodeVersion: number;\n hasCucumber: boolean;\n cwd: string;\n}\n\nexport interface PackageManagerArgs {\n npm: string;\n yarn: string;\n pnpm: string;\n bun: string;\n}\n\nexport function detectEnvironment(): Environment {\n const cwd = process.cwd();\n const isInteractive = Boolean(process.stdout.isTTY && process.stdin.isTTY);\n\n let packageManager: PackageManager = 'npm';\n if (existsSync(join(cwd, 'yarn.lock'))) packageManager = 'yarn';\n else if (existsSync(join(cwd, 'pnpm-lock.yaml'))) packageManager = 'pnpm';\n else if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) packageManager = 'bun';\n\n const nodeVersion = parseInt(process.version.slice(1), 10);\n const hasCucumber = existsSync(join(cwd, 'node_modules', '@cucumber', 'cucumber', 'package.json'));\n\n return { isInteractive, packageManager, nodeVersion, hasCucumber, cwd };\n}\n\nfunction pmCmd(pm: string, args: PackageManagerArgs): string {\n if (pm === 'yarn') return `yarn ${args.yarn}`;\n if (pm === 'pnpm') return `pnpm ${args.pnpm}`;\n if (pm === 'bun') return `bun ${args.bun}`;\n return `npm ${args.npm}`;\n}\n\nexport function execPm(env: Pick<Environment, 'packageManager' | 'cwd'>, args: PackageManagerArgs) {\n const cmd = pmCmd(env.packageManager, args);\n return execSync(cmd, { stdio: 'inherit', cwd: env.cwd });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function isCliInstalled({ cwd }: Pick<Environment, 'cwd'>): boolean {\n const pkgPath = join(cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n return '@letsrunit/cli' in (pkg.devDependencies ?? {}) || '@letsrunit/cli' in (pkg.dependencies ?? {});\n}\n\nexport function installCli(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @letsrunit/cli',\n yarn: 'add --dev @letsrunit/cli',\n pnpm: 'add -D @letsrunit/cli',\n bun: 'add -d @letsrunit/cli',\n });\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nconst BDD_IMPORT = '@letsrunit/bdd/define';\n\nconst CUCUMBER_CONFIG = `export default {\n require: ['features/support/**/*.js'],\n worldParameters: {\n baseURL: 'http://localhost:3000',\n },\n};\n`;\n\nconst SUPPORT_FILE = `import { setDefaultTimeout } from '@cucumber/cucumber';\nimport '${BDD_IMPORT}';\n\nsetDefaultTimeout(30_000);\n`;\n\nconst EXAMPLE_FEATURE = `Feature: Example\n Scenario: Homepage loads\n Given I'm on the homepage\n`;\n\nexport type CucumberConfigResult = 'created' | 'skipped' | 'needs-manual-update';\n\nexport interface CucumberSetupResult {\n bddInstalled: boolean;\n configResult: CucumberConfigResult;\n featuresCreated: boolean;\n}\n\nexport function installCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @cucumber/cucumber',\n yarn: 'add --dev @cucumber/cucumber',\n pnpm: 'add -D @cucumber/cucumber',\n bun: 'add -d @cucumber/cucumber',\n });\n}\n\nfunction installBdd(env: Pick<Environment, 'packageManager' | 'cwd'>): boolean {\n const pkgPath = join(env.cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n const alreadyInstalled =\n '@letsrunit/bdd' in (pkg.devDependencies ?? {}) || '@letsrunit/bdd' in (pkg.dependencies ?? {});\n\n if (alreadyInstalled) return false;\n\n execPm(env, {\n npm: 'install --save-dev @letsrunit/bdd',\n yarn: 'add --dev @letsrunit/bdd',\n pnpm: 'add -D @letsrunit/bdd',\n bun: 'add -d @letsrunit/bdd',\n });\n\n return true;\n}\n\nfunction setupCucumberConfig({ cwd }: Pick<Environment, 'cwd'>): CucumberConfigResult {\n const supportDir = join(cwd, 'features', 'support');\n const supportPath = join(supportDir, 'world.js');\n\n if (existsSync(supportPath)) {\n const content = readFileSync(supportPath, 'utf-8');\n if (content.includes(BDD_IMPORT)) return 'skipped';\n return 'needs-manual-update';\n }\n\n const configPath = join(cwd, 'cucumber.js');\n if (!existsSync(configPath)) {\n writeFileSync(configPath, CUCUMBER_CONFIG, 'utf-8');\n }\n\n mkdirSync(supportDir, { recursive: true });\n writeFileSync(supportPath, SUPPORT_FILE, 'utf-8');\n return 'created';\n}\n\nfunction setupFeaturesDir({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (existsSync(join(cwd, 'features'))) {\n try {\n const hasFeatureFiles = readdirSync(join(cwd, 'features')).some((f) => f.endsWith('.feature'));\n if (hasFeatureFiles) return false;\n } catch {\n return false;\n }\n }\n\n try {\n const hasFeatureAtRoot = readdirSync(cwd).some((f) => f.endsWith('.feature'));\n if (hasFeatureAtRoot) return false;\n } catch {\n return false;\n }\n\n mkdirSync(join(cwd, 'features'), { recursive: true });\n writeFileSync(join(cwd, 'features', 'example.feature'), EXAMPLE_FEATURE, 'utf-8');\n return true;\n}\n\nexport function setupCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): CucumberSetupResult {\n const bddInstalled = installBdd(env);\n const configResult = setupCucumberConfig(env);\n const featuresCreated = setupFeaturesDir(env);\n return { bddInstalled, configResult, featuresCreated };\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { Environment } from '../detect.js';\n\nexport type GithubActionsResult = 'created' | 'skipped';\n\nfunction setupStepsFor({ packageManager, nodeVersion }: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n if (packageManager === 'yarn') return `\\\n - name: Enable Corepack\n run: corepack enable\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: yarn\n - name: Install dependencies\n run: yarn install --immutable`;\n if (packageManager === 'pnpm') return `\\\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: pnpm\n - name: Install dependencies\n run: pnpm install --frozen-lockfile`;\n if (packageManager === 'bun') return `\\\n - uses: oven-sh/setup-bun@v2\n - name: Install dependencies\n run: bun install --frozen-lockfile`;\n return `\\\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: npm\n - name: Install dependencies\n run: npm ci`;\n}\n\nfunction workflowYaml(env: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n const setupSteps = setupStepsFor(env);\n\n return `name: Features\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\njobs:\n features:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n${setupSteps}\n - name: Install Playwright browsers\n run: npx playwright install chromium --with-deps\n - name: Run features\n run: npx cucumber-js\n`;\n}\n\nexport function installGithubAction(env: Pick<Environment, 'packageManager' | 'nodeVersion' | 'cwd'>): GithubActionsResult {\n const workflowDir = join(env.cwd, '.github', 'workflows');\n const workflowPath = join(workflowDir, 'letsrunit.yml');\n\n if (existsSync(workflowPath)) return 'skipped';\n\n mkdirSync(workflowDir, { recursive: true });\n writeFileSync(workflowPath, workflowYaml(env), 'utf-8');\n return 'created';\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function hasPlaywrightBrowsers({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (!existsSync(join(cwd, 'node_modules', 'playwright-core', 'package.json'))) {\n return false;\n }\n try {\n const execPath = execSync(\n `node -e \"console.log(require('playwright-core').chromium.executablePath())\"`,\n { cwd, stdio: 'pipe', encoding: 'utf-8' },\n ).trim();\n return existsSync(execPath);\n } catch {\n return false;\n }\n}\n\nexport function installPlaywrightBrowsers(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'exec playwright install chromium',\n yarn: 'exec playwright install chromium',\n pnpm: 'exec playwright install chromium',\n bun: 'x playwright install chromium',\n });\n}\n","import { init } from './init.js';\n\nconst args = process.argv.slice(2);\nconst command = args.find((a) => !a.startsWith('-')) ?? 'init';\nconst yes = args.includes('--yes') || args.includes('-y');\n\nif (command === 'init') {\n init({ yes }).catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n} else {\n console.error(`Unknown command: ${command}`);\n console.error('Usage: letsrunit init [--yes]');\n process.exit(1);\n}\n"],"mappings":"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","names":["args","existsSync","join","join","existsSync","existsSync","readFileSync","join","join","existsSync","readFileSync","existsSync","mkdirSync","writeFileSync","join","execSync","existsSync","join","existsSync","join","execSync","BDD_IMPORT","yes"]}
1
+ {"version":3,"sources":["../src/init.ts","../src/detect.ts","../src/setup/cli.ts","../src/setup/cucumber.ts","../src/setup/github-actions.ts","../src/setup/playwright.ts","../src/bin.ts"],"sourcesContent":["import { confirm, intro, log, note, outro, spinner } from '@clack/prompts';\nimport { detectEnvironment, type Environment } from './detect.js';\nimport { installCli, isCliInstalled } from './setup/cli.js';\nimport { installCucumber, setupCucumber } from './setup/cucumber.js';\nimport { installGithubAction } from './setup/github-actions.js';\nimport { hasPlaywrightBrowsers, installPlaywrightBrowsers } from './setup/playwright.js';\n\nconst BDD_IMPORT = '@letsrunit/cucumber';\n\nexport interface InitOptions {\n yes?: boolean;\n}\n\nasync function stepInstallCli(env: Environment): Promise<void> {\n if (isCliInstalled(env)) {\n log.success('@letsrunit/cli already installed');\n return;\n }\n\n const s = spinner();\n s.start('Installing @letsrunit/cli…');\n installCli(env);\n s.stop('@letsrunit/cli installed');\n}\n\nasync function stepEnsureCucumber(env: Environment, { yes }: InitOptions): Promise<boolean> {\n if (env.hasCucumber) return true;\n\n if (!yes && !env.isInteractive) {\n log.warn('@cucumber/cucumber not found. Install it to use letsrunit with Cucumber:');\n note('npm install --save-dev @cucumber/cucumber\\nThen run: npx letsrunit init', 'Setup Cucumber');\n return false;\n }\n\n if (!yes) {\n const install = await confirm({ message: '@cucumber/cucumber not found. Install it now?' });\n if (install !== true) return false;\n }\n\n const s = spinner();\n s.start('Installing @cucumber/cucumber…');\n installCucumber(env);\n s.stop('@cucumber/cucumber installed');\n return true;\n}\n\nfunction stepSetupCucumber(env: Environment): void {\n const result = setupCucumber(env);\n\n if (result.bddInstalled) log.success('@letsrunit/cucumber installed');\n\n if (result.configResult === 'created') {\n log.success('features/support/world.js created');\n } else if (result.configResult === 'needs-manual-update') {\n log.warn('features/support/world.js exists but does not import @letsrunit/cucumber.');\n note(`Add \"import '${BDD_IMPORT}';\" to features/support/world.js`, 'Action required');\n }\n\n if (result.featuresCreated) log.success('features/ directory created with example.feature');\n}\n\nasync function stepCheckPlaywrightBrowsers(env: Environment, { yes }: InitOptions): Promise<void> {\n if (hasPlaywrightBrowsers(env)) return;\n\n if (!yes && !env.isInteractive) {\n log.warn('Playwright Chromium browser not found.');\n note('npx playwright install chromium', 'Run to install browsers');\n return;\n }\n\n if (!yes) {\n const install = await confirm({ message: 'Playwright Chromium browser not found. Install it now?' });\n if (install !== true) return;\n }\n\n const s = spinner();\n s.start('Installing Playwright Chromium…');\n installPlaywrightBrowsers(env);\n s.stop('Playwright Chromium installed');\n}\n\nasync function stepAddGithubAction(env: Environment, { yes }: InitOptions): Promise<void> {\n if (!yes && !env.isInteractive) return;\n\n if (!yes) {\n const addAction = await confirm({ message: 'Add a GitHub Action to run features on push?' });\n if (addAction !== true) return;\n }\n\n const result = installGithubAction(env);\n if (result === 'created') {\n log.success('.github/workflows/letsrunit.yml created');\n } else {\n log.info('.github/workflows/letsrunit.yml already exists, skipped');\n }\n}\n\nexport async function init(options: InitOptions = {}): Promise<void> {\n intro('letsrunit init');\n\n const env = detectEnvironment();\n\n await stepInstallCli(env);\n\n const hasCucumber = await stepEnsureCucumber(env, options);\n if (hasCucumber) {\n stepSetupCucumber(env);\n await stepCheckPlaywrightBrowsers(env, options);\n await stepAddGithubAction(env, options);\n }\n\n outro('All done! Run npx letsrunit --help to get started.');\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'yarn' | 'pnpm' | 'bun' | 'npm';\n\nexport interface Environment {\n isInteractive: boolean;\n packageManager: PackageManager;\n nodeVersion: number;\n hasCucumber: boolean;\n cwd: string;\n}\n\nexport interface PackageManagerArgs {\n npm: string;\n yarn: string;\n pnpm: string;\n bun: string;\n}\n\nexport function detectEnvironment(): Environment {\n const cwd = process.cwd();\n const isInteractive = Boolean(process.stdout.isTTY && process.stdin.isTTY);\n\n let packageManager: PackageManager = 'npm';\n if (existsSync(join(cwd, 'yarn.lock'))) packageManager = 'yarn';\n else if (existsSync(join(cwd, 'pnpm-lock.yaml'))) packageManager = 'pnpm';\n else if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) packageManager = 'bun';\n\n const nodeVersion = parseInt(process.version.slice(1), 10);\n const hasCucumber = existsSync(join(cwd, 'node_modules', '@cucumber', 'cucumber', 'package.json'));\n\n return { isInteractive, packageManager, nodeVersion, hasCucumber, cwd };\n}\n\nfunction pmCmd(pm: string, args: PackageManagerArgs): string {\n if (pm === 'yarn') return `yarn ${args.yarn}`;\n if (pm === 'pnpm') return `pnpm ${args.pnpm}`;\n if (pm === 'bun') return `bun ${args.bun}`;\n return `npm ${args.npm}`;\n}\n\nexport function execPm(env: Pick<Environment, 'packageManager' | 'cwd'>, args: PackageManagerArgs) {\n const cmd = pmCmd(env.packageManager, args);\n return execSync(cmd, { stdio: 'inherit', cwd: env.cwd });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function isCliInstalled({ cwd }: Pick<Environment, 'cwd'>): boolean {\n const pkgPath = join(cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n return '@letsrunit/cli' in (pkg.devDependencies ?? {}) || '@letsrunit/cli' in (pkg.dependencies ?? {});\n}\n\nexport function installCli(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @letsrunit/cli',\n yarn: 'add --dev @letsrunit/cli',\n pnpm: 'add -D @letsrunit/cli',\n bun: 'add -d @letsrunit/cli',\n });\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nconst BDD_IMPORT = '@letsrunit/cucumber';\n\nconst CUCUMBER_CONFIG = `export default {\n require: ['features/support/**/*.js'],\n worldParameters: {\n baseURL: 'http://localhost:3000',\n },\n};\n`;\n\nconst SUPPORT_FILE = `import { setDefaultTimeout } from '@cucumber/cucumber';\nimport '${BDD_IMPORT}';\n\nsetDefaultTimeout(30_000);\n`;\n\nconst EXAMPLE_FEATURE = `Feature: Example\n Scenario: Homepage loads\n Given I'm on the homepage\n`;\n\nexport type CucumberConfigResult = 'created' | 'skipped' | 'needs-manual-update';\n\nexport interface CucumberSetupResult {\n bddInstalled: boolean;\n configResult: CucumberConfigResult;\n featuresCreated: boolean;\n}\n\nexport function installCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @cucumber/cucumber',\n yarn: 'add --dev @cucumber/cucumber',\n pnpm: 'add -D @cucumber/cucumber',\n bun: 'add -d @cucumber/cucumber',\n });\n}\n\nfunction installBdd(env: Pick<Environment, 'packageManager' | 'cwd'>): boolean {\n const pkgPath = join(env.cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n const alreadyInstalled =\n '@letsrunit/cucumber' in (pkg.devDependencies ?? {}) || '@letsrunit/cucumber' in (pkg.dependencies ?? {});\n\n if (alreadyInstalled) return false;\n\n execPm(env, {\n npm: 'install --save-dev @letsrunit/cucumber',\n yarn: 'add --dev @letsrunit/cucumber',\n pnpm: 'add -D @letsrunit/cucumber',\n bun: 'add -d @letsrunit/cucumber',\n });\n\n return true;\n}\n\nfunction setupCucumberConfig({ cwd }: Pick<Environment, 'cwd'>): CucumberConfigResult {\n const supportDir = join(cwd, 'features', 'support');\n const supportPath = join(supportDir, 'world.js');\n\n if (existsSync(supportPath)) {\n const content = readFileSync(supportPath, 'utf-8');\n if (content.includes(BDD_IMPORT)) return 'skipped';\n return 'needs-manual-update';\n }\n\n const configPath = join(cwd, 'cucumber.js');\n if (!existsSync(configPath)) {\n writeFileSync(configPath, CUCUMBER_CONFIG, 'utf-8');\n }\n\n mkdirSync(supportDir, { recursive: true });\n writeFileSync(supportPath, SUPPORT_FILE, 'utf-8');\n return 'created';\n}\n\nfunction setupFeaturesDir({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (existsSync(join(cwd, 'features'))) {\n try {\n const hasFeatureFiles = readdirSync(join(cwd, 'features')).some((f) => f.endsWith('.feature'));\n if (hasFeatureFiles) return false;\n } catch {\n return false;\n }\n }\n\n try {\n const hasFeatureAtRoot = readdirSync(cwd).some((f) => f.endsWith('.feature'));\n if (hasFeatureAtRoot) return false;\n } catch {\n return false;\n }\n\n mkdirSync(join(cwd, 'features'), { recursive: true });\n writeFileSync(join(cwd, 'features', 'example.feature'), EXAMPLE_FEATURE, 'utf-8');\n return true;\n}\n\nexport function setupCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): CucumberSetupResult {\n const bddInstalled = installBdd(env);\n const configResult = setupCucumberConfig(env);\n const featuresCreated = setupFeaturesDir(env);\n return { bddInstalled, configResult, featuresCreated };\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { Environment } from '../detect.js';\n\nexport type GithubActionsResult = 'created' | 'skipped';\n\nfunction setupStepsFor({ packageManager, nodeVersion }: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n if (packageManager === 'yarn') return `\\\n - name: Enable Corepack\n run: corepack enable\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: yarn\n - name: Install dependencies\n run: yarn install --immutable`;\n if (packageManager === 'pnpm') return `\\\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: pnpm\n - name: Install dependencies\n run: pnpm install --frozen-lockfile`;\n if (packageManager === 'bun') return `\\\n - uses: oven-sh/setup-bun@v2\n - name: Install dependencies\n run: bun install --frozen-lockfile`;\n return `\\\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: npm\n - name: Install dependencies\n run: npm ci`;\n}\n\nfunction workflowYaml(env: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n const setupSteps = setupStepsFor(env);\n\n return `name: Features\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\njobs:\n features:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n${setupSteps}\n - name: Install Playwright browsers\n run: npx playwright install chromium --with-deps\n - name: Run features\n run: npx cucumber-js\n`;\n}\n\nexport function installGithubAction(env: Pick<Environment, 'packageManager' | 'nodeVersion' | 'cwd'>): GithubActionsResult {\n const workflowDir = join(env.cwd, '.github', 'workflows');\n const workflowPath = join(workflowDir, 'letsrunit.yml');\n\n if (existsSync(workflowPath)) return 'skipped';\n\n mkdirSync(workflowDir, { recursive: true });\n writeFileSync(workflowPath, workflowYaml(env), 'utf-8');\n return 'created';\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function hasPlaywrightBrowsers({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (!existsSync(join(cwd, 'node_modules', 'playwright-core', 'package.json'))) {\n return false;\n }\n try {\n const execPath = execSync(\n `node -e \"console.log(require('playwright-core').chromium.executablePath())\"`,\n { cwd, stdio: 'pipe', encoding: 'utf-8' },\n ).trim();\n return existsSync(execPath);\n } catch {\n return false;\n }\n}\n\nexport function installPlaywrightBrowsers(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'exec playwright install chromium',\n yarn: 'exec playwright install chromium',\n pnpm: 'exec playwright install chromium',\n bun: 'x playwright install chromium',\n });\n}\n","import { init } from './init.js';\n\nconst args = process.argv.slice(2);\nconst command = args.find((a) => !a.startsWith('-')) ?? 'init';\nconst yes = args.includes('--yes') || args.includes('-y');\n\nif (command === 'init') {\n init({ yes }).catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n} else {\n console.error(`Unknown command: ${command}`);\n console.error('Usage: letsrunit init [--yes]');\n process.exit(1);\n}\n"],"mappings":"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","names":["args","existsSync","join","join","existsSync","existsSync","readFileSync","join","join","existsSync","readFileSync","existsSync","mkdirSync","writeFileSync","join","execSync","existsSync","join","existsSync","join","execSync","BDD_IMPORT","yes"]}
package/dist/index.js CHANGED
@@ -48,7 +48,7 @@ function installCli(env) {
48
48
  // src/setup/cucumber.ts
49
49
  import { existsSync as existsSync3, mkdirSync, readdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
50
50
  import { join as join3 } from "path";
51
- var BDD_IMPORT = "@letsrunit/bdd/define";
51
+ var BDD_IMPORT = "@letsrunit/cucumber";
52
52
  var CUCUMBER_CONFIG = `export default {
53
53
  require: ['features/support/**/*.js'],
54
54
  worldParameters: {
@@ -77,13 +77,13 @@ function installBdd(env) {
77
77
  const pkgPath = join3(env.cwd, "package.json");
78
78
  if (!existsSync3(pkgPath)) return false;
79
79
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
80
- const alreadyInstalled = "@letsrunit/bdd" in (pkg.devDependencies ?? {}) || "@letsrunit/bdd" in (pkg.dependencies ?? {});
80
+ const alreadyInstalled = "@letsrunit/cucumber" in (pkg.devDependencies ?? {}) || "@letsrunit/cucumber" in (pkg.dependencies ?? {});
81
81
  if (alreadyInstalled) return false;
82
82
  execPm(env, {
83
- npm: "install --save-dev @letsrunit/bdd",
84
- yarn: "add --dev @letsrunit/bdd",
85
- pnpm: "add -D @letsrunit/bdd",
86
- bun: "add -d @letsrunit/bdd"
83
+ npm: "install --save-dev @letsrunit/cucumber",
84
+ yarn: "add --dev @letsrunit/cucumber",
85
+ pnpm: "add -D @letsrunit/cucumber",
86
+ bun: "add -d @letsrunit/cucumber"
87
87
  });
88
88
  return true;
89
89
  }
@@ -215,7 +215,7 @@ function installPlaywrightBrowsers(env) {
215
215
  }
216
216
 
217
217
  // src/init.ts
218
- var BDD_IMPORT2 = "@letsrunit/bdd/define";
218
+ var BDD_IMPORT2 = "@letsrunit/cucumber";
219
219
  async function stepInstallCli(env) {
220
220
  if (isCliInstalled(env)) {
221
221
  log.success("@letsrunit/cli already installed");
@@ -245,11 +245,11 @@ async function stepEnsureCucumber(env, { yes }) {
245
245
  }
246
246
  function stepSetupCucumber(env) {
247
247
  const result = setupCucumber(env);
248
- if (result.bddInstalled) log.success("@letsrunit/bdd installed");
248
+ if (result.bddInstalled) log.success("@letsrunit/cucumber installed");
249
249
  if (result.configResult === "created") {
250
250
  log.success("features/support/world.js created");
251
251
  } else if (result.configResult === "needs-manual-update") {
252
- log.warn("features/support/world.js exists but does not import @letsrunit/bdd.");
252
+ log.warn("features/support/world.js exists but does not import @letsrunit/cucumber.");
253
253
  note(`Add "import '${BDD_IMPORT2}';" to features/support/world.js`, "Action required");
254
254
  }
255
255
  if (result.featuresCreated) log.success("features/ directory created with example.feature");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/init.ts","../src/detect.ts","../src/setup/cli.ts","../src/setup/cucumber.ts","../src/setup/github-actions.ts","../src/setup/playwright.ts"],"sourcesContent":["import { confirm, intro, log, note, outro, spinner } from '@clack/prompts';\nimport { detectEnvironment, type Environment } from './detect.js';\nimport { installCli, isCliInstalled } from './setup/cli.js';\nimport { installCucumber, setupCucumber } from './setup/cucumber.js';\nimport { installGithubAction } from './setup/github-actions.js';\nimport { hasPlaywrightBrowsers, installPlaywrightBrowsers } from './setup/playwright.js';\n\nconst BDD_IMPORT = '@letsrunit/bdd/define';\n\nexport interface InitOptions {\n yes?: boolean;\n}\n\nasync function stepInstallCli(env: Environment): Promise<void> {\n if (isCliInstalled(env)) {\n log.success('@letsrunit/cli already installed');\n return;\n }\n\n const s = spinner();\n s.start('Installing @letsrunit/cli…');\n installCli(env);\n s.stop('@letsrunit/cli installed');\n}\n\nasync function stepEnsureCucumber(env: Environment, { yes }: InitOptions): Promise<boolean> {\n if (env.hasCucumber) return true;\n\n if (!yes && !env.isInteractive) {\n log.warn('@cucumber/cucumber not found. Install it to use letsrunit with Cucumber:');\n note('npm install --save-dev @cucumber/cucumber\\nThen run: npx letsrunit init', 'Setup Cucumber');\n return false;\n }\n\n if (!yes) {\n const install = await confirm({ message: '@cucumber/cucumber not found. Install it now?' });\n if (install !== true) return false;\n }\n\n const s = spinner();\n s.start('Installing @cucumber/cucumber…');\n installCucumber(env);\n s.stop('@cucumber/cucumber installed');\n return true;\n}\n\nfunction stepSetupCucumber(env: Environment): void {\n const result = setupCucumber(env);\n\n if (result.bddInstalled) log.success('@letsrunit/bdd installed');\n\n if (result.configResult === 'created') {\n log.success('features/support/world.js created');\n } else if (result.configResult === 'needs-manual-update') {\n log.warn('features/support/world.js exists but does not import @letsrunit/bdd.');\n note(`Add \"import '${BDD_IMPORT}';\" to features/support/world.js`, 'Action required');\n }\n\n if (result.featuresCreated) log.success('features/ directory created with example.feature');\n}\n\nasync function stepCheckPlaywrightBrowsers(env: Environment, { yes }: InitOptions): Promise<void> {\n if (hasPlaywrightBrowsers(env)) return;\n\n if (!yes && !env.isInteractive) {\n log.warn('Playwright Chromium browser not found.');\n note('npx playwright install chromium', 'Run to install browsers');\n return;\n }\n\n if (!yes) {\n const install = await confirm({ message: 'Playwright Chromium browser not found. Install it now?' });\n if (install !== true) return;\n }\n\n const s = spinner();\n s.start('Installing Playwright Chromium…');\n installPlaywrightBrowsers(env);\n s.stop('Playwright Chromium installed');\n}\n\nasync function stepAddGithubAction(env: Environment, { yes }: InitOptions): Promise<void> {\n if (!yes && !env.isInteractive) return;\n\n if (!yes) {\n const addAction = await confirm({ message: 'Add a GitHub Action to run features on push?' });\n if (addAction !== true) return;\n }\n\n const result = installGithubAction(env);\n if (result === 'created') {\n log.success('.github/workflows/letsrunit.yml created');\n } else {\n log.info('.github/workflows/letsrunit.yml already exists, skipped');\n }\n}\n\nexport async function init(options: InitOptions = {}): Promise<void> {\n intro('letsrunit init');\n\n const env = detectEnvironment();\n\n await stepInstallCli(env);\n\n const hasCucumber = await stepEnsureCucumber(env, options);\n if (hasCucumber) {\n stepSetupCucumber(env);\n await stepCheckPlaywrightBrowsers(env, options);\n await stepAddGithubAction(env, options);\n }\n\n outro('All done! Run npx letsrunit --help to get started.');\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'yarn' | 'pnpm' | 'bun' | 'npm';\n\nexport interface Environment {\n isInteractive: boolean;\n packageManager: PackageManager;\n nodeVersion: number;\n hasCucumber: boolean;\n cwd: string;\n}\n\nexport interface PackageManagerArgs {\n npm: string;\n yarn: string;\n pnpm: string;\n bun: string;\n}\n\nexport function detectEnvironment(): Environment {\n const cwd = process.cwd();\n const isInteractive = Boolean(process.stdout.isTTY && process.stdin.isTTY);\n\n let packageManager: PackageManager = 'npm';\n if (existsSync(join(cwd, 'yarn.lock'))) packageManager = 'yarn';\n else if (existsSync(join(cwd, 'pnpm-lock.yaml'))) packageManager = 'pnpm';\n else if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) packageManager = 'bun';\n\n const nodeVersion = parseInt(process.version.slice(1), 10);\n const hasCucumber = existsSync(join(cwd, 'node_modules', '@cucumber', 'cucumber', 'package.json'));\n\n return { isInteractive, packageManager, nodeVersion, hasCucumber, cwd };\n}\n\nfunction pmCmd(pm: string, args: PackageManagerArgs): string {\n if (pm === 'yarn') return `yarn ${args.yarn}`;\n if (pm === 'pnpm') return `pnpm ${args.pnpm}`;\n if (pm === 'bun') return `bun ${args.bun}`;\n return `npm ${args.npm}`;\n}\n\nexport function execPm(env: Pick<Environment, 'packageManager' | 'cwd'>, args: PackageManagerArgs) {\n const cmd = pmCmd(env.packageManager, args);\n return execSync(cmd, { stdio: 'inherit', cwd: env.cwd });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function isCliInstalled({ cwd }: Pick<Environment, 'cwd'>): boolean {\n const pkgPath = join(cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n return '@letsrunit/cli' in (pkg.devDependencies ?? {}) || '@letsrunit/cli' in (pkg.dependencies ?? {});\n}\n\nexport function installCli(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @letsrunit/cli',\n yarn: 'add --dev @letsrunit/cli',\n pnpm: 'add -D @letsrunit/cli',\n bun: 'add -d @letsrunit/cli',\n });\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nconst BDD_IMPORT = '@letsrunit/bdd/define';\n\nconst CUCUMBER_CONFIG = `export default {\n require: ['features/support/**/*.js'],\n worldParameters: {\n baseURL: 'http://localhost:3000',\n },\n};\n`;\n\nconst SUPPORT_FILE = `import { setDefaultTimeout } from '@cucumber/cucumber';\nimport '${BDD_IMPORT}';\n\nsetDefaultTimeout(30_000);\n`;\n\nconst EXAMPLE_FEATURE = `Feature: Example\n Scenario: Homepage loads\n Given I'm on the homepage\n`;\n\nexport type CucumberConfigResult = 'created' | 'skipped' | 'needs-manual-update';\n\nexport interface CucumberSetupResult {\n bddInstalled: boolean;\n configResult: CucumberConfigResult;\n featuresCreated: boolean;\n}\n\nexport function installCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @cucumber/cucumber',\n yarn: 'add --dev @cucumber/cucumber',\n pnpm: 'add -D @cucumber/cucumber',\n bun: 'add -d @cucumber/cucumber',\n });\n}\n\nfunction installBdd(env: Pick<Environment, 'packageManager' | 'cwd'>): boolean {\n const pkgPath = join(env.cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n const alreadyInstalled =\n '@letsrunit/bdd' in (pkg.devDependencies ?? {}) || '@letsrunit/bdd' in (pkg.dependencies ?? {});\n\n if (alreadyInstalled) return false;\n\n execPm(env, {\n npm: 'install --save-dev @letsrunit/bdd',\n yarn: 'add --dev @letsrunit/bdd',\n pnpm: 'add -D @letsrunit/bdd',\n bun: 'add -d @letsrunit/bdd',\n });\n\n return true;\n}\n\nfunction setupCucumberConfig({ cwd }: Pick<Environment, 'cwd'>): CucumberConfigResult {\n const supportDir = join(cwd, 'features', 'support');\n const supportPath = join(supportDir, 'world.js');\n\n if (existsSync(supportPath)) {\n const content = readFileSync(supportPath, 'utf-8');\n if (content.includes(BDD_IMPORT)) return 'skipped';\n return 'needs-manual-update';\n }\n\n const configPath = join(cwd, 'cucumber.js');\n if (!existsSync(configPath)) {\n writeFileSync(configPath, CUCUMBER_CONFIG, 'utf-8');\n }\n\n mkdirSync(supportDir, { recursive: true });\n writeFileSync(supportPath, SUPPORT_FILE, 'utf-8');\n return 'created';\n}\n\nfunction setupFeaturesDir({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (existsSync(join(cwd, 'features'))) {\n try {\n const hasFeatureFiles = readdirSync(join(cwd, 'features')).some((f) => f.endsWith('.feature'));\n if (hasFeatureFiles) return false;\n } catch {\n return false;\n }\n }\n\n try {\n const hasFeatureAtRoot = readdirSync(cwd).some((f) => f.endsWith('.feature'));\n if (hasFeatureAtRoot) return false;\n } catch {\n return false;\n }\n\n mkdirSync(join(cwd, 'features'), { recursive: true });\n writeFileSync(join(cwd, 'features', 'example.feature'), EXAMPLE_FEATURE, 'utf-8');\n return true;\n}\n\nexport function setupCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): CucumberSetupResult {\n const bddInstalled = installBdd(env);\n const configResult = setupCucumberConfig(env);\n const featuresCreated = setupFeaturesDir(env);\n return { bddInstalled, configResult, featuresCreated };\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { Environment } from '../detect.js';\n\nexport type GithubActionsResult = 'created' | 'skipped';\n\nfunction setupStepsFor({ packageManager, nodeVersion }: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n if (packageManager === 'yarn') return `\\\n - name: Enable Corepack\n run: corepack enable\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: yarn\n - name: Install dependencies\n run: yarn install --immutable`;\n if (packageManager === 'pnpm') return `\\\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: pnpm\n - name: Install dependencies\n run: pnpm install --frozen-lockfile`;\n if (packageManager === 'bun') return `\\\n - uses: oven-sh/setup-bun@v2\n - name: Install dependencies\n run: bun install --frozen-lockfile`;\n return `\\\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: npm\n - name: Install dependencies\n run: npm ci`;\n}\n\nfunction workflowYaml(env: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n const setupSteps = setupStepsFor(env);\n\n return `name: Features\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\njobs:\n features:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n${setupSteps}\n - name: Install Playwright browsers\n run: npx playwright install chromium --with-deps\n - name: Run features\n run: npx cucumber-js\n`;\n}\n\nexport function installGithubAction(env: Pick<Environment, 'packageManager' | 'nodeVersion' | 'cwd'>): GithubActionsResult {\n const workflowDir = join(env.cwd, '.github', 'workflows');\n const workflowPath = join(workflowDir, 'letsrunit.yml');\n\n if (existsSync(workflowPath)) return 'skipped';\n\n mkdirSync(workflowDir, { recursive: true });\n writeFileSync(workflowPath, workflowYaml(env), 'utf-8');\n return 'created';\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function hasPlaywrightBrowsers({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (!existsSync(join(cwd, 'node_modules', 'playwright-core', 'package.json'))) {\n return false;\n }\n try {\n const execPath = execSync(\n `node -e \"console.log(require('playwright-core').chromium.executablePath())\"`,\n { cwd, stdio: 'pipe', encoding: 'utf-8' },\n ).trim();\n return existsSync(execPath);\n } catch {\n return false;\n }\n}\n\nexport function installPlaywrightBrowsers(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'exec playwright install chromium',\n yarn: 'exec playwright install chromium',\n pnpm: 'exec playwright install chromium',\n bun: 'x playwright install chromium',\n });\n}\n"],"mappings":"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","names":["existsSync","join","join","existsSync","existsSync","readFileSync","join","join","existsSync","readFileSync","existsSync","mkdirSync","writeFileSync","join","execSync","existsSync","join","existsSync","join","execSync","BDD_IMPORT"]}
1
+ {"version":3,"sources":["../src/init.ts","../src/detect.ts","../src/setup/cli.ts","../src/setup/cucumber.ts","../src/setup/github-actions.ts","../src/setup/playwright.ts"],"sourcesContent":["import { confirm, intro, log, note, outro, spinner } from '@clack/prompts';\nimport { detectEnvironment, type Environment } from './detect.js';\nimport { installCli, isCliInstalled } from './setup/cli.js';\nimport { installCucumber, setupCucumber } from './setup/cucumber.js';\nimport { installGithubAction } from './setup/github-actions.js';\nimport { hasPlaywrightBrowsers, installPlaywrightBrowsers } from './setup/playwright.js';\n\nconst BDD_IMPORT = '@letsrunit/cucumber';\n\nexport interface InitOptions {\n yes?: boolean;\n}\n\nasync function stepInstallCli(env: Environment): Promise<void> {\n if (isCliInstalled(env)) {\n log.success('@letsrunit/cli already installed');\n return;\n }\n\n const s = spinner();\n s.start('Installing @letsrunit/cli…');\n installCli(env);\n s.stop('@letsrunit/cli installed');\n}\n\nasync function stepEnsureCucumber(env: Environment, { yes }: InitOptions): Promise<boolean> {\n if (env.hasCucumber) return true;\n\n if (!yes && !env.isInteractive) {\n log.warn('@cucumber/cucumber not found. Install it to use letsrunit with Cucumber:');\n note('npm install --save-dev @cucumber/cucumber\\nThen run: npx letsrunit init', 'Setup Cucumber');\n return false;\n }\n\n if (!yes) {\n const install = await confirm({ message: '@cucumber/cucumber not found. Install it now?' });\n if (install !== true) return false;\n }\n\n const s = spinner();\n s.start('Installing @cucumber/cucumber…');\n installCucumber(env);\n s.stop('@cucumber/cucumber installed');\n return true;\n}\n\nfunction stepSetupCucumber(env: Environment): void {\n const result = setupCucumber(env);\n\n if (result.bddInstalled) log.success('@letsrunit/cucumber installed');\n\n if (result.configResult === 'created') {\n log.success('features/support/world.js created');\n } else if (result.configResult === 'needs-manual-update') {\n log.warn('features/support/world.js exists but does not import @letsrunit/cucumber.');\n note(`Add \"import '${BDD_IMPORT}';\" to features/support/world.js`, 'Action required');\n }\n\n if (result.featuresCreated) log.success('features/ directory created with example.feature');\n}\n\nasync function stepCheckPlaywrightBrowsers(env: Environment, { yes }: InitOptions): Promise<void> {\n if (hasPlaywrightBrowsers(env)) return;\n\n if (!yes && !env.isInteractive) {\n log.warn('Playwright Chromium browser not found.');\n note('npx playwright install chromium', 'Run to install browsers');\n return;\n }\n\n if (!yes) {\n const install = await confirm({ message: 'Playwright Chromium browser not found. Install it now?' });\n if (install !== true) return;\n }\n\n const s = spinner();\n s.start('Installing Playwright Chromium…');\n installPlaywrightBrowsers(env);\n s.stop('Playwright Chromium installed');\n}\n\nasync function stepAddGithubAction(env: Environment, { yes }: InitOptions): Promise<void> {\n if (!yes && !env.isInteractive) return;\n\n if (!yes) {\n const addAction = await confirm({ message: 'Add a GitHub Action to run features on push?' });\n if (addAction !== true) return;\n }\n\n const result = installGithubAction(env);\n if (result === 'created') {\n log.success('.github/workflows/letsrunit.yml created');\n } else {\n log.info('.github/workflows/letsrunit.yml already exists, skipped');\n }\n}\n\nexport async function init(options: InitOptions = {}): Promise<void> {\n intro('letsrunit init');\n\n const env = detectEnvironment();\n\n await stepInstallCli(env);\n\n const hasCucumber = await stepEnsureCucumber(env, options);\n if (hasCucumber) {\n stepSetupCucumber(env);\n await stepCheckPlaywrightBrowsers(env, options);\n await stepAddGithubAction(env, options);\n }\n\n outro('All done! Run npx letsrunit --help to get started.');\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'yarn' | 'pnpm' | 'bun' | 'npm';\n\nexport interface Environment {\n isInteractive: boolean;\n packageManager: PackageManager;\n nodeVersion: number;\n hasCucumber: boolean;\n cwd: string;\n}\n\nexport interface PackageManagerArgs {\n npm: string;\n yarn: string;\n pnpm: string;\n bun: string;\n}\n\nexport function detectEnvironment(): Environment {\n const cwd = process.cwd();\n const isInteractive = Boolean(process.stdout.isTTY && process.stdin.isTTY);\n\n let packageManager: PackageManager = 'npm';\n if (existsSync(join(cwd, 'yarn.lock'))) packageManager = 'yarn';\n else if (existsSync(join(cwd, 'pnpm-lock.yaml'))) packageManager = 'pnpm';\n else if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) packageManager = 'bun';\n\n const nodeVersion = parseInt(process.version.slice(1), 10);\n const hasCucumber = existsSync(join(cwd, 'node_modules', '@cucumber', 'cucumber', 'package.json'));\n\n return { isInteractive, packageManager, nodeVersion, hasCucumber, cwd };\n}\n\nfunction pmCmd(pm: string, args: PackageManagerArgs): string {\n if (pm === 'yarn') return `yarn ${args.yarn}`;\n if (pm === 'pnpm') return `pnpm ${args.pnpm}`;\n if (pm === 'bun') return `bun ${args.bun}`;\n return `npm ${args.npm}`;\n}\n\nexport function execPm(env: Pick<Environment, 'packageManager' | 'cwd'>, args: PackageManagerArgs) {\n const cmd = pmCmd(env.packageManager, args);\n return execSync(cmd, { stdio: 'inherit', cwd: env.cwd });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function isCliInstalled({ cwd }: Pick<Environment, 'cwd'>): boolean {\n const pkgPath = join(cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n return '@letsrunit/cli' in (pkg.devDependencies ?? {}) || '@letsrunit/cli' in (pkg.dependencies ?? {});\n}\n\nexport function installCli(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @letsrunit/cli',\n yarn: 'add --dev @letsrunit/cli',\n pnpm: 'add -D @letsrunit/cli',\n bun: 'add -d @letsrunit/cli',\n });\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nconst BDD_IMPORT = '@letsrunit/cucumber';\n\nconst CUCUMBER_CONFIG = `export default {\n require: ['features/support/**/*.js'],\n worldParameters: {\n baseURL: 'http://localhost:3000',\n },\n};\n`;\n\nconst SUPPORT_FILE = `import { setDefaultTimeout } from '@cucumber/cucumber';\nimport '${BDD_IMPORT}';\n\nsetDefaultTimeout(30_000);\n`;\n\nconst EXAMPLE_FEATURE = `Feature: Example\n Scenario: Homepage loads\n Given I'm on the homepage\n`;\n\nexport type CucumberConfigResult = 'created' | 'skipped' | 'needs-manual-update';\n\nexport interface CucumberSetupResult {\n bddInstalled: boolean;\n configResult: CucumberConfigResult;\n featuresCreated: boolean;\n}\n\nexport function installCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'install --save-dev @cucumber/cucumber',\n yarn: 'add --dev @cucumber/cucumber',\n pnpm: 'add -D @cucumber/cucumber',\n bun: 'add -d @cucumber/cucumber',\n });\n}\n\nfunction installBdd(env: Pick<Environment, 'packageManager' | 'cwd'>): boolean {\n const pkgPath = join(env.cwd, 'package.json');\n if (!existsSync(pkgPath)) return false;\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {\n devDependencies?: Record<string, string>;\n dependencies?: Record<string, string>;\n };\n\n const alreadyInstalled =\n '@letsrunit/cucumber' in (pkg.devDependencies ?? {}) || '@letsrunit/cucumber' in (pkg.dependencies ?? {});\n\n if (alreadyInstalled) return false;\n\n execPm(env, {\n npm: 'install --save-dev @letsrunit/cucumber',\n yarn: 'add --dev @letsrunit/cucumber',\n pnpm: 'add -D @letsrunit/cucumber',\n bun: 'add -d @letsrunit/cucumber',\n });\n\n return true;\n}\n\nfunction setupCucumberConfig({ cwd }: Pick<Environment, 'cwd'>): CucumberConfigResult {\n const supportDir = join(cwd, 'features', 'support');\n const supportPath = join(supportDir, 'world.js');\n\n if (existsSync(supportPath)) {\n const content = readFileSync(supportPath, 'utf-8');\n if (content.includes(BDD_IMPORT)) return 'skipped';\n return 'needs-manual-update';\n }\n\n const configPath = join(cwd, 'cucumber.js');\n if (!existsSync(configPath)) {\n writeFileSync(configPath, CUCUMBER_CONFIG, 'utf-8');\n }\n\n mkdirSync(supportDir, { recursive: true });\n writeFileSync(supportPath, SUPPORT_FILE, 'utf-8');\n return 'created';\n}\n\nfunction setupFeaturesDir({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (existsSync(join(cwd, 'features'))) {\n try {\n const hasFeatureFiles = readdirSync(join(cwd, 'features')).some((f) => f.endsWith('.feature'));\n if (hasFeatureFiles) return false;\n } catch {\n return false;\n }\n }\n\n try {\n const hasFeatureAtRoot = readdirSync(cwd).some((f) => f.endsWith('.feature'));\n if (hasFeatureAtRoot) return false;\n } catch {\n return false;\n }\n\n mkdirSync(join(cwd, 'features'), { recursive: true });\n writeFileSync(join(cwd, 'features', 'example.feature'), EXAMPLE_FEATURE, 'utf-8');\n return true;\n}\n\nexport function setupCucumber(env: Pick<Environment, 'packageManager' | 'cwd'>): CucumberSetupResult {\n const bddInstalled = installBdd(env);\n const configResult = setupCucumberConfig(env);\n const featuresCreated = setupFeaturesDir(env);\n return { bddInstalled, configResult, featuresCreated };\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { Environment } from '../detect.js';\n\nexport type GithubActionsResult = 'created' | 'skipped';\n\nfunction setupStepsFor({ packageManager, nodeVersion }: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n if (packageManager === 'yarn') return `\\\n - name: Enable Corepack\n run: corepack enable\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: yarn\n - name: Install dependencies\n run: yarn install --immutable`;\n if (packageManager === 'pnpm') return `\\\n - uses: pnpm/action-setup@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: pnpm\n - name: Install dependencies\n run: pnpm install --frozen-lockfile`;\n if (packageManager === 'bun') return `\\\n - uses: oven-sh/setup-bun@v2\n - name: Install dependencies\n run: bun install --frozen-lockfile`;\n return `\\\n - uses: actions/setup-node@v4\n with:\n node-version: ${nodeVersion}\n cache: npm\n - name: Install dependencies\n run: npm ci`;\n}\n\nfunction workflowYaml(env: Pick<Environment, 'packageManager' | 'nodeVersion'>): string {\n const setupSteps = setupStepsFor(env);\n\n return `name: Features\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\njobs:\n features:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n${setupSteps}\n - name: Install Playwright browsers\n run: npx playwright install chromium --with-deps\n - name: Run features\n run: npx cucumber-js\n`;\n}\n\nexport function installGithubAction(env: Pick<Environment, 'packageManager' | 'nodeVersion' | 'cwd'>): GithubActionsResult {\n const workflowDir = join(env.cwd, '.github', 'workflows');\n const workflowPath = join(workflowDir, 'letsrunit.yml');\n\n if (existsSync(workflowPath)) return 'skipped';\n\n mkdirSync(workflowDir, { recursive: true });\n writeFileSync(workflowPath, workflowYaml(env), 'utf-8');\n return 'created';\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Environment, execPm } from '../detect.js';\n\nexport function hasPlaywrightBrowsers({ cwd }: Pick<Environment, 'cwd'>): boolean {\n if (!existsSync(join(cwd, 'node_modules', 'playwright-core', 'package.json'))) {\n return false;\n }\n try {\n const execPath = execSync(\n `node -e \"console.log(require('playwright-core').chromium.executablePath())\"`,\n { cwd, stdio: 'pipe', encoding: 'utf-8' },\n ).trim();\n return existsSync(execPath);\n } catch {\n return false;\n }\n}\n\nexport function installPlaywrightBrowsers(env: Pick<Environment, 'packageManager' | 'cwd'>): void {\n execPm(env, {\n npm: 'exec playwright install chromium',\n yarn: 'exec playwright install chromium',\n pnpm: 'exec playwright install chromium',\n bun: 'x playwright install chromium',\n });\n}\n"],"mappings":"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","names":["existsSync","join","join","existsSync","existsSync","readFileSync","join","join","existsSync","readFileSync","existsSync","mkdirSync","writeFileSync","join","execSync","existsSync","join","existsSync","join","execSync","BDD_IMPORT"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "letsrunit",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "Onboarding tool for letsrunit — run npx letsrunit init to get started",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/init.ts CHANGED
@@ -5,7 +5,7 @@ import { installCucumber, setupCucumber } from './setup/cucumber.js';
5
5
  import { installGithubAction } from './setup/github-actions.js';
6
6
  import { hasPlaywrightBrowsers, installPlaywrightBrowsers } from './setup/playwright.js';
7
7
 
8
- const BDD_IMPORT = '@letsrunit/bdd/define';
8
+ const BDD_IMPORT = '@letsrunit/cucumber';
9
9
 
10
10
  export interface InitOptions {
11
11
  yes?: boolean;
@@ -47,12 +47,12 @@ async function stepEnsureCucumber(env: Environment, { yes }: InitOptions): Promi
47
47
  function stepSetupCucumber(env: Environment): void {
48
48
  const result = setupCucumber(env);
49
49
 
50
- if (result.bddInstalled) log.success('@letsrunit/bdd installed');
50
+ if (result.bddInstalled) log.success('@letsrunit/cucumber installed');
51
51
 
52
52
  if (result.configResult === 'created') {
53
53
  log.success('features/support/world.js created');
54
54
  } else if (result.configResult === 'needs-manual-update') {
55
- log.warn('features/support/world.js exists but does not import @letsrunit/bdd.');
55
+ log.warn('features/support/world.js exists but does not import @letsrunit/cucumber.');
56
56
  note(`Add "import '${BDD_IMPORT}';" to features/support/world.js`, 'Action required');
57
57
  }
58
58
 
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from
2
2
  import { join } from 'node:path';
3
3
  import { type Environment, execPm } from '../detect.js';
4
4
 
5
- const BDD_IMPORT = '@letsrunit/bdd/define';
5
+ const BDD_IMPORT = '@letsrunit/cucumber';
6
6
 
7
7
  const CUCUMBER_CONFIG = `export default {
8
8
  require: ['features/support/**/*.js'],
@@ -50,15 +50,15 @@ function installBdd(env: Pick<Environment, 'packageManager' | 'cwd'>): boolean {
50
50
  };
51
51
 
52
52
  const alreadyInstalled =
53
- '@letsrunit/bdd' in (pkg.devDependencies ?? {}) || '@letsrunit/bdd' in (pkg.dependencies ?? {});
53
+ '@letsrunit/cucumber' in (pkg.devDependencies ?? {}) || '@letsrunit/cucumber' in (pkg.dependencies ?? {});
54
54
 
55
55
  if (alreadyInstalled) return false;
56
56
 
57
57
  execPm(env, {
58
- npm: 'install --save-dev @letsrunit/bdd',
59
- yarn: 'add --dev @letsrunit/bdd',
60
- pnpm: 'add -D @letsrunit/bdd',
61
- bun: 'add -d @letsrunit/bdd',
58
+ npm: 'install --save-dev @letsrunit/cucumber',
59
+ yarn: 'add --dev @letsrunit/cucumber',
60
+ pnpm: 'add -D @letsrunit/cucumber',
61
+ bun: 'add -d @letsrunit/cucumber',
62
62
  });
63
63
 
64
64
  return true;