@raiken/cli
Version:
CLI tool for Raiken - AI-powered Playwright test generator
297 lines (293 loc) • 11.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initializeProject = initializeProject;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const chalk_1 = __importDefault(require("chalk"));
const project_detector_1 = require("./project-detector");
async function initializeProject(projectPath, force = false) {
const projectInfo = await (0, project_detector_1.detectProject)(projectPath);
console.log(chalk_1.default.blue(`📁 Setting up ${projectInfo.type} project: ${projectInfo.name}`));
// 1. Create test directory
await createTestDirectory(projectPath, projectInfo);
// 2. Create test-results directory structure
await createTestResultsDirectory(projectPath);
// 3. Create Raiken configuration
await createRaikenConfig(projectPath, projectInfo, force);
// 4. Set up Playwright configuration
await setupPlaywrightConfig(projectPath, projectInfo, force);
// 5. Update package.json scripts
await updatePackageScripts(projectPath, projectInfo);
// 6. Create example test
await createExampleTest(projectPath, projectInfo);
// 7. Install Playwright browsers
await installPlaywrightBrowsers(projectPath, projectInfo);
console.log(chalk_1.default.green('✓ Project initialization complete'));
}
async function createTestDirectory(projectPath, projectInfo) {
const testDirPath = path.join(projectPath, projectInfo.testDir);
try {
await fs.access(testDirPath);
console.log(chalk_1.default.yellow(`⚠ Test directory ${projectInfo.testDir}/ already exists`));
}
catch {
await fs.mkdir(testDirPath, { recursive: true });
console.log(chalk_1.default.green(`✓ Created test directory: ${projectInfo.testDir}/`));
}
}
async function createTestResultsDirectory(projectPath) {
const testResultsPath = path.join(projectPath, 'test-results');
const reportsPath = path.join(testResultsPath, 'reports');
try {
// Create test-results directory
await fs.mkdir(testResultsPath, { recursive: true });
// Create reports subdirectory
await fs.mkdir(reportsPath, { recursive: true });
// Create .gitignore to exclude test artifacts from version control
const gitignorePath = path.join(testResultsPath, '.gitignore');
const gitignoreContent = `# Test artifacts
*
!.gitignore
!reports/
reports/*.json
`;
try {
await fs.access(gitignorePath);
console.log(chalk_1.default.yellow('⚠ test-results/.gitignore already exists'));
}
catch {
await fs.writeFile(gitignorePath, gitignoreContent);
console.log(chalk_1.default.green('✓ Created test-results/.gitignore'));
}
console.log(chalk_1.default.green('✓ Created test-results/ directory structure'));
}
catch (error) {
console.log(chalk_1.default.yellow('⚠ Could not create test-results directory structure'));
}
}
async function createRaikenConfig(projectPath, projectInfo, force) {
const configPath = path.join(projectPath, 'raiken.config.json');
const config = {
projectType: projectInfo.type,
testDirectory: projectInfo.testDir,
playwrightConfig: 'playwright.config.ts',
outputFormats: ['typescript'],
ai: {
provider: 'openrouter',
model: 'anthropic/claude-3.5-sonnet'
},
features: {
video: true,
screenshots: true,
tracing: false,
network: true
},
browser: {
defaultBrowser: 'chromium',
headless: true,
timeout: 30000,
retries: 1
}
};
try {
await fs.access(configPath);
if (!force) {
console.log(chalk_1.default.yellow('⚠ raiken.config.json already exists (use --force to overwrite)'));
return;
}
}
catch {
// File doesn't exist, proceed
}
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
console.log(chalk_1.default.green('✓ Created raiken.config.json'));
}
async function setupPlaywrightConfig(projectPath, projectInfo, force) {
const configPath = path.join(projectPath, 'playwright.config.ts');
const config = `import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './${projectInfo.testDir}',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:${getDefaultPort(projectInfo.type)}',
trace: 'on-first-retry',
video: 'retain-on-failure',
screenshot: 'only-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
// Additional browsers can be enabled by uncommenting:
// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },
// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },
],
webServer: {
command: '${getDevCommand(projectInfo)}',
port: ${getDefaultPort(projectInfo.type)},
reuseExistingServer: !process.env.CI,
},
});
`;
try {
await fs.access(configPath);
if (!force) {
console.log(chalk_1.default.yellow('⚠ playwright.config.ts already exists (use --force to overwrite)'));
return;
}
}
catch {
// File doesn't exist, proceed
}
await fs.writeFile(configPath, config);
console.log(chalk_1.default.green('✓ Created playwright.config.ts'));
}
async function updatePackageScripts(projectPath, projectInfo) {
const packageJsonPath = path.join(projectPath, 'package.json');
try {
const packageContent = await fs.readFile(packageJsonPath, 'utf-8');
const packageJson = JSON.parse(packageContent);
const newScripts = {
'test:e2e': 'playwright test',
'test:e2e:ui': 'playwright test --ui',
'test:e2e:debug': 'playwright test --debug',
'raiken': 'raiken start'
};
packageJson.scripts = { ...packageJson.scripts, ...newScripts };
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
console.log(chalk_1.default.green('✓ Updated package.json scripts'));
}
catch (error) {
console.log(chalk_1.default.yellow('⚠ Could not update package.json scripts'));
}
}
async function createExampleTest(projectPath, projectInfo) {
const testPath = path.join(projectPath, projectInfo.testDir, 'example.spec.ts');
try {
await fs.access(testPath);
console.log(chalk_1.default.yellow('⚠ Example test already exists'));
return;
}
catch {
// File doesn't exist, create it
}
const exampleTest = `import { test, expect } from '@playwright/test';
test('example test', async ({ page }) => {
await page.goto('/');
// Example: Check if the page loads
await expect(page).toHaveTitle(/.*${projectInfo.name}.*/i);
// Add your test steps here
// await page.click('button[data-testid="my-button"]');
// await expect(page.getByText('Success!')).toBeVisible();
});
`;
await fs.writeFile(testPath, exampleTest);
console.log(chalk_1.default.green(`✓ Created example test: ${projectInfo.testDir}/example.spec.ts`));
}
function getDefaultPort(projectType) {
switch (projectType) {
case 'nextjs':
case 'react':
case 'nuxt':
return 3000;
case 'svelte':
case 'vite':
return 5173;
case 'angular':
return 4200;
default:
return 3000;
}
}
function getDevCommand(projectInfo) {
if (projectInfo.scripts.dev)
return 'npm run dev';
if (projectInfo.scripts.start)
return 'npm run start';
if (projectInfo.scripts.serve)
return 'npm run serve';
return 'npm run dev';
}
async function installPlaywrightBrowsers(projectPath, projectInfo) {
// Only install browsers if Playwright is already a dependency
if (!projectInfo.hasPlaywright) {
console.log(chalk_1.default.yellow('⚠ Playwright not detected as dependency, skipping browser installation'));
return;
}
console.log(chalk_1.default.blue('📦 Installing Playwright browsers...'));
try {
const { spawn } = require('child_process');
return new Promise((resolve, reject) => {
const child = spawn('npx', ['playwright', 'install'], {
cwd: projectPath,
stdio: 'inherit' // Show output to user
});
child.on('close', (code) => {
if (code === 0) {
console.log(chalk_1.default.green('✓ Playwright browsers installed successfully'));
resolve();
}
else {
console.log(chalk_1.default.yellow('⚠ Playwright browser installation failed, you may need to run "npx playwright install" manually'));
resolve(); // Don't fail the entire setup
}
});
child.on('error', (error) => {
console.log(chalk_1.default.yellow(`⚠ Could not install Playwright browsers: ${error.message}`));
console.log(chalk_1.default.gray(' You can install them manually with: npx playwright install'));
resolve(); // Don't fail the entire setup
});
});
}
catch (error) {
console.log(chalk_1.default.yellow('⚠ Could not install Playwright browsers, you may need to run "npx playwright install" manually'));
}
}
//# sourceMappingURL=project-initializer.js.map