cypress-bootstrap
Version:
Cypress Bootstrap is a project scaffolding tool that sets up a Cypress automation framework with a standardized folder structure and Page Object Model (POM) design. It helps teams quickly start testing with built-in best practices and sample specs.
198 lines (169 loc) • 6.19 kB
JavaScript
const fs = require('fs');
const path = require('path');
// Get the paths
const packageRoot = path.resolve(__dirname, '..');
const userProjectRoot = process.cwd();
// Skip if we're in the package directory (during development)
if (packageRoot === userProjectRoot) {
console.log('Running in package directory, skipping setup');
process.exit(0);
}
// Create the directory structure
const directories = [
'cypress',
'cypress/downloads',
'cypress/pages',
'cypress/reports',
'cypress/screenshots',
'cypress/support',
'cypress/testbase',
'cypress/testdata',
'cypress/tests',
'cypress/tests/api',
'cypress/tests/ui',
'cypress/videos',
];
// Create directories if they don't exist
directories.forEach(dir => {
const dirPath = path.join(userProjectRoot, dir);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
console.log(`Created directory: ${dir}`);
}
});
// Files that should be copied to the user's project and be modifiable
const filesToCopy = [
'cypress.config.ts',
'cypress.env.json',
'reporter-config.ts',
'tsconfig.json',
'.prettierrc',
'.prettierignore',
];
// Special case for gitignore (npm doesn't include .gitignore in packages)
const specialFiles = [{ source: 'gitignore', dest: '.gitignore' }];
// Copy files
filesToCopy.forEach(file => {
const sourcePath = path.join(packageRoot, file);
const destPath = path.join(userProjectRoot, file);
// Only copy if the source file exists and the destination file doesn't exist
if (fs.existsSync(sourcePath) && !fs.existsSync(destPath)) {
fs.copyFileSync(sourcePath, destPath);
console.log(`Copied file: ${file}`);
} else if (!fs.existsSync(sourcePath)) {
console.log(`Warning: Source file not found: ${file}, skipping`);
}
});
// Copy special files (with different source and destination names)
specialFiles.forEach(fileObj => {
const sourcePath = path.join(packageRoot, fileObj.source);
const destPath = path.join(userProjectRoot, fileObj.dest);
// Only copy if the source file exists and the destination file doesn't exist
if (fs.existsSync(sourcePath) && !fs.existsSync(destPath)) {
fs.copyFileSync(sourcePath, destPath);
console.log(`Copied file: ${fileObj.source} to ${fileObj.dest}`);
} else if (!fs.existsSync(sourcePath)) {
console.log(`Warning: Source file not found: ${fileObj.source}, skipping`);
}
});
// Copy directories that should be modifiable
const directoriesToCopy = [
'cypress/testbase',
'cypress/testdata',
'cypress/tests',
'cypress/support',
'cypress/pages',
'.husky',
];
// Function to copy a directory recursively
function copyDir(src, dest) {
// Create destination directory if it doesn't exist
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest, { recursive: true });
}
// Read source directory
const entries = fs.readdirSync(src, { withFileTypes: true });
// Copy each entry
for (const entry of entries) {
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
// Recursively copy subdirectories
copyDir(srcPath, destPath);
} else {
// Copy files if source exists and they don't exist in the destination
if (fs.existsSync(srcPath) && !fs.existsSync(destPath)) {
fs.copyFileSync(srcPath, destPath);
console.log(
`Copied file: ${path.relative(packageRoot, srcPath)} to ${path.relative(
userProjectRoot,
destPath
)}`
);
} else if (!fs.existsSync(srcPath)) {
console.log(
`Warning: Source file not found: ${path.relative(packageRoot, srcPath)}, skipping`
);
}
}
}
}
// Copy modifiable directories
directoriesToCopy.forEach(dir => {
const sourcePath = path.join(packageRoot, dir);
const destPath = path.join(userProjectRoot, dir);
if (fs.existsSync(sourcePath)) {
copyDir(sourcePath, destPath);
console.log(`Copied directory: ${dir}`);
}
});
// Install dependencies
console.log('Installing required dependencies...');
const { execSync } = require('child_process');
try {
// Read the package.json file from the package
const packageJsonPath = path.join(packageRoot, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
// Get the devDependencies
const devDependencies = packageJson.devDependencies || {};
// Create a temporary package.json with just the devDependencies if it doesn't exist
const userPackageJsonPath = path.join(userProjectRoot, 'package.json');
let userPackageJson = {};
if (fs.existsSync(userPackageJsonPath)) {
// Read existing package.json
userPackageJson = JSON.parse(fs.readFileSync(userPackageJsonPath, 'utf8'));
// Merge devDependencies
userPackageJson.devDependencies = {
...(userPackageJson.devDependencies || {}),
...devDependencies,
};
// Write updated package.json
fs.writeFileSync(userPackageJsonPath, JSON.stringify(userPackageJson, null, 2));
} else {
// Create a new package.json with minimal info and the devDependencies
userPackageJson = {
name: 'cypress-project',
version: '1.0.0',
description: 'Project using cypress-bootstrap',
devDependencies: devDependencies,
};
// Write new package.json
fs.writeFileSync(userPackageJsonPath, JSON.stringify(userPackageJson, null, 2));
}
console.log('Installing dependencies. This may take a few minutes...');
execSync('npm install', { cwd: userProjectRoot, stdio: 'inherit' });
console.log('Dependencies installed successfully!');
} catch (error) {
console.error('Error installing dependencies:', error.message);
console.log('Please run "npm install" manually to install the required dependencies.');
}
console.log('Setup completed successfully!');
console.log('You can now modify the following files and directories:');
console.log('- cypress.config.ts');
console.log('- cypress/testbase/');
console.log('- cypress/testdata/');
console.log('- cypress/tests/');
console.log('- tsconfig.json');
console.log('- reporter-config.ts');
console.log('- .gitignore');