smartui-migration-tool
Version:
Enterprise-grade CLI tool for migrating visual testing platforms to LambdaTest SmartUI
587 lines (566 loc) โข 19.1 kB
JavaScript
"use strict";
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnvironmentManager = void 0;
const path = __importStar(require("path"));
const fs = __importStar(require("fs/promises"));
const Logger_1 = require("../utils/Logger");
class EnvironmentManager {
constructor(projectPath, verbose = false) {
this.projectPath = projectPath;
this.verbose = verbose;
}
/**
* Setup CI/CD environment for SmartUI
*/
async setupCIEnvironment(ciType) {
if (this.verbose)
Logger_1.logger.debug(`Setting up ${ciType} environment...`);
const environment = await this.generateCIEnvironment(ciType);
await this.writeCIConfig(ciType, environment);
return environment;
}
/**
* Generate environment setup scripts
*/
async generateEnvironmentScripts() {
if (this.verbose)
Logger_1.logger.debug('Generating environment setup scripts...');
const scripts = {
setup: this.generateSetupScript(),
test: this.generateTestScript(),
cleanup: this.generateCleanupScript(),
validate: this.generateValidationScript()
};
// Write scripts to project
await this.writeScripts(scripts);
return scripts;
}
/**
* Validate environment configuration
*/
async validateEnvironment() {
const errors = [];
const warnings = [];
const suggestions = [];
// Check for required environment variables
const requiredVars = ['LT_USERNAME', 'LT_ACCESS_KEY'];
for (const varName of requiredVars) {
if (!process.env[varName]) {
errors.push(`Required environment variable ${varName} is not set`);
}
}
// Check for optional but recommended variables
const optionalVars = ['LT_PROJECT_TOKEN', 'SMARTUI_BROWSER', 'SMARTUI_VIEWPORT'];
for (const varName of optionalVars) {
if (!process.env[varName]) {
warnings.push(`Optional environment variable ${varName} is not set`);
suggestions.push(`Consider setting ${varName} for better SmartUI configuration`);
}
}
// Check for .smartui.json
try {
await fs.access(path.join(this.projectPath, '.smartui.json'));
}
catch {
errors.push('.smartui.json configuration file not found');
suggestions.push('Run the migration tool to generate SmartUI configuration');
}
// Check for .env file
try {
await fs.access(path.join(this.projectPath, '.env'));
}
catch {
warnings.push('.env file not found');
suggestions.push('Create .env file with your SmartUI credentials');
}
return {
valid: errors.length === 0,
errors,
warnings,
suggestions
};
}
/**
* Generate environment variables template
*/
generateEnvironmentVariables() {
return [
{
name: 'LT_USERNAME',
value: '${LT_USERNAME}',
description: 'LambdaTest username for SmartUI authentication',
required: true,
secret: false
},
{
name: 'LT_ACCESS_KEY',
value: '${LT_ACCESS_KEY}',
description: 'LambdaTest access key for SmartUI authentication',
required: true,
secret: true
},
{
name: 'LT_PROJECT_TOKEN',
value: '${LT_PROJECT_TOKEN}',
description: 'SmartUI project token for test organization',
required: false,
secret: true
},
{
name: 'SMARTUI_BROWSER',
value: 'chrome',
description: 'Default browser for SmartUI tests',
required: false,
secret: false
},
{
name: 'SMARTUI_VIEWPORT',
value: '1920x1080',
description: 'Default viewport size for SmartUI tests',
required: false,
secret: false
},
{
name: 'SMARTUI_TIMEOUT',
value: '30000',
description: 'Screenshot timeout in milliseconds',
required: false,
secret: false
},
{
name: 'SMARTUI_THRESHOLD',
value: '0.1',
description: 'Visual comparison threshold (0.0-1.0)',
required: false,
secret: false
}
];
}
// Private methods
async generateCIEnvironment(ciType) {
const environmentVariables = this.generateEnvironmentVariables();
switch (ciType.toLowerCase()) {
case 'github-actions':
return this.generateGitHubActionsConfig(environmentVariables);
case 'jenkins':
return this.generateJenkinsConfig(environmentVariables);
case 'gitlab-ci':
return this.generateGitLabCIConfig(environmentVariables);
case 'azure-devops':
return this.generateAzureDevOpsConfig(environmentVariables);
case 'circleci':
return this.generateCircleCIConfig(environmentVariables);
case 'travis-ci':
return this.generateTravisCIConfig(environmentVariables);
default:
throw new Error(`Unsupported CI type: ${ciType}`);
}
}
generateGitHubActionsConfig(envVars) {
const config = {
name: 'SmartUI Visual Testing',
on: {
push: { branches: ['main', 'develop'] },
pull_request: { branches: ['main'] }
},
jobs: {
'smartui-tests': {
'runs-on': 'ubuntu-latest',
steps: [
{
name: 'Checkout code',
uses: 'actions/checkout@v3'
},
{
name: 'Setup Node.js',
uses: 'actions/setup-node@v3',
with: {
'node-version': '18'
}
},
{
name: 'Install dependencies',
run: 'npm install'
},
{
name: 'Run SmartUI tests',
run: 'npm run test:smartui',
env: {
LT_USERNAME: '${{ secrets.LT_USERNAME }}',
LT_ACCESS_KEY: '${{ secrets.LT_ACCESS_KEY }}',
LT_PROJECT_TOKEN: '${{ secrets.LT_PROJECT_TOKEN }}'
}
}
]
}
}
};
return {
type: 'github-actions',
config,
environmentVariables: envVars,
scripts: ['npm run test:smartui']
};
}
generateJenkinsConfig(envVars) {
const config = {
pipeline: {
agent: 'any',
environment: {
LT_USERNAME: '${LT_USERNAME}',
LT_ACCESS_KEY: '${LT_ACCESS_KEY}',
LT_PROJECT_TOKEN: '${LT_PROJECT_TOKEN}'
},
stages: [
{
stage: 'Checkout',
steps: ['git checkout']
},
{
stage: 'Install Dependencies',
steps: ['npm install']
},
{
stage: 'Run SmartUI Tests',
steps: ['npm run test:smartui']
}
]
}
};
return {
type: 'jenkins',
config,
environmentVariables: envVars,
scripts: ['npm run test:smartui']
};
}
generateGitLabCIConfig(envVars) {
const config = {
image: 'node:18',
stages: ['test'],
smartui_tests: {
stage: 'test',
script: [
'npm install',
'npm run test:smartui'
],
variables: {
LT_USERNAME: '$LT_USERNAME',
LT_ACCESS_KEY: '$LT_ACCESS_KEY',
LT_PROJECT_TOKEN: '$LT_PROJECT_TOKEN'
}
}
};
return {
type: 'gitlab-ci',
config,
environmentVariables: envVars,
scripts: ['npm run test:smartui']
};
}
generateAzureDevOpsConfig(envVars) {
const config = {
trigger: ['main', 'develop'],
pool: {
vmImage: 'ubuntu-latest'
},
variables: {
LT_USERNAME: '$(LT_USERNAME)',
LT_ACCESS_KEY: '$(LT_ACCESS_KEY)',
LT_PROJECT_TOKEN: '$(LT_PROJECT_TOKEN)'
},
steps: [
{
task: 'NodeTool@0',
inputs: {
versionSpec: '18.x'
}
},
{
script: 'npm install',
displayName: 'Install dependencies'
},
{
script: 'npm run test:smartui',
displayName: 'Run SmartUI tests'
}
]
};
return {
type: 'azure-devops',
config,
environmentVariables: envVars,
scripts: ['npm run test:smartui']
};
}
generateCircleCIConfig(envVars) {
const config = {
version: 2.1,
jobs: {
smartui_tests: {
docker: [
{
image: 'cimg/node:18.0'
}
],
steps: [
'checkout',
{
run: 'npm install'
},
{
run: 'npm run test:smartui',
environment: {
LT_USERNAME: '$LT_USERNAME',
LT_ACCESS_KEY: '$LT_ACCESS_KEY',
LT_PROJECT_TOKEN: '$LT_PROJECT_TOKEN'
}
}
]
}
},
workflows: {
version: 2,
smartui_workflow: {
jobs: ['smartui_tests']
}
}
};
return {
type: 'circleci',
config,
environmentVariables: envVars,
scripts: ['npm run test:smartui']
};
}
generateTravisCIConfig(envVars) {
const config = {
language: 'node_js',
node_js: ['18'],
script: ['npm run test:smartui'],
env: {
global: [
'LT_USERNAME=$LT_USERNAME',
'LT_ACCESS_KEY=$LT_ACCESS_KEY',
'LT_PROJECT_TOKEN=$LT_PROJECT_TOKEN'
]
}
};
return {
type: 'travis-ci',
config,
environmentVariables: envVars,
scripts: ['npm run test:smartui']
};
}
async writeCIConfig(ciType, environment) {
const configPath = this.getCIConfigPath(ciType);
const configContent = this.formatCIConfig(ciType, environment.config);
// Create directory if it doesn't exist
const configDir = path.dirname(configPath);
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(configPath, configContent, 'utf-8');
if (this.verbose)
Logger_1.logger.debug(`${ciType} configuration written to ${configPath}`);
}
getCIConfigPath(ciType) {
const configPaths = {
'github-actions': '.github/workflows/smartui.yml',
'jenkins': 'Jenkinsfile',
'gitlab-ci': '.gitlab-ci.yml',
'azure-devops': 'azure-pipelines.yml',
'circleci': '.circleci/config.yml',
'travis-ci': '.travis.yml'
};
return path.join(this.projectPath, configPaths[ciType] || 'ci-config.yml');
}
formatCIConfig(ciType, config) {
switch (ciType.toLowerCase()) {
case 'github-actions':
case 'jenkins':
case 'gitlab-ci':
case 'azure-devops':
case 'circleci':
case 'travis-ci':
return `# SmartUI ${ciType} Configuration
# Generated by SmartUI Migration Tool
${JSON.stringify(config, null, 2)}`;
default:
return JSON.stringify(config, null, 2);
}
}
generateSetupScript() {
return `#!/bin/bash
# SmartUI Environment Setup Script
echo "๐ง Setting up SmartUI environment..."
# Check if .env file exists
if [ ! -f .env ]; then
echo "๐ Creating .env file..."
cat > .env << EOF
# SmartUI Configuration
LT_USERNAME=your_username_here
LT_ACCESS_KEY=your_access_key_here
LT_PROJECT_TOKEN=your_project_token_here
SMARTUI_BROWSER=chrome
SMARTUI_VIEWPORT=1920x1080
SMARTUI_TIMEOUT=30000
SMARTUI_THRESHOLD=0.1
EOF
echo "โ ๏ธ Please edit .env file with your credentials"
else
echo "โ
.env file already exists"
fi
# Load environment variables
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
echo "โ
Environment variables loaded"
fi
# Validate required variables
if [ -z "$LT_USERNAME" ] || [ -z "$LT_ACCESS_KEY" ]; then
echo "โ Required environment variables not set"
echo " Please set LT_USERNAME and LT_ACCESS_KEY in .env file"
exit 1
fi
echo "โ
SmartUI environment setup complete"
`;
}
generateTestScript() {
return `#!/bin/bash
# SmartUI Test Runner Script
echo "๐งช Running SmartUI tests..."
# Load environment variables
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
fi
# Check if SmartUI config exists
if [ ! -f .smartui.json ]; then
echo "โ .smartui.json not found. Please run migration tool first."
exit 1
fi
# Run tests based on project type
if [ -f package.json ]; then
echo "๐ฆ Running Node.js tests..."
npm run test:smartui
elif [ -f pom.xml ]; then
echo "โ Running Maven tests..."
mvn test -Dtest=*SmartUITest
elif [ -f build.gradle ]; then
echo "๐ Running Gradle tests..."
./gradlew test --tests "*SmartUITest"
elif [ -f requirements.txt ]; then
echo "๐ Running Python tests..."
python -m pytest tests/test_smartui.py
else
echo "โ ๏ธ Unknown project type. Please run tests manually."
fi
echo "โ
SmartUI tests completed"
`;
}
generateCleanupScript() {
return `#!/bin/bash
# SmartUI Cleanup Script
echo "๐งน Cleaning up SmartUI artifacts..."
# Remove temporary files
rm -f smartui-*.log
rm -f smartui-*.tmp
rm -rf .smartui-temp
# Clean up test artifacts
rm -rf test-results/
rm -rf screenshots/
rm -rf reports/
echo "โ
Cleanup completed"
`;
}
generateValidationScript() {
return `#!/bin/bash
# SmartUI Validation Script
echo "๐ Validating SmartUI configuration..."
# Check for required files
required_files=(".smartui.json" ".env")
for file in "\${required_files[@]}"; do
if [ ! -f "\$file" ]; then
echo "โ Required file missing: \$file"
exit 1
else
echo "โ
Found: \$file"
fi
done
# Load environment variables
if [ -f .env ]; then
export \$(cat .env | grep -v '^#' | xargs)
fi
# Validate required environment variables
required_vars=("LT_USERNAME" "LT_ACCESS_KEY")
for var in "\${required_vars[@]}"; do
if [ -z "\${!var}" ]; then
echo "โ Required environment variable not set: \$var"
exit 1
else
echo "โ
Environment variable set: \$var"
fi
done
# Validate SmartUI config
if command -v jq &> /dev/null; then
if jq empty .smartui.json 2>/dev/null; then
echo "โ
.smartui.json is valid JSON"
else
echo "โ .smartui.json is not valid JSON"
exit 1
fi
else
echo "โ ๏ธ jq not found, skipping JSON validation"
fi
echo "โ
SmartUI configuration validation passed"
`;
}
async writeScripts(scripts) {
const scriptFiles = [
{ name: 'setup-smartui.sh', content: scripts.setup },
{ name: 'test-smartui.sh', content: scripts.test },
{ name: 'cleanup-smartui.sh', content: scripts.cleanup },
{ name: 'validate-smartui.sh', content: scripts.validate }
];
for (const script of scriptFiles) {
const scriptPath = path.join(this.projectPath, script.name);
await fs.writeFile(scriptPath, script.content, 'utf-8');
await fs.chmod(scriptPath, 0o755);
}
if (this.verbose)
Logger_1.logger.debug('Environment scripts written to project');
}
}
exports.EnvironmentManager = EnvironmentManager;
//# sourceMappingURL=EnvironmentManager.js.map