smartui-migration-tool
Version:
Enterprise-grade CLI tool for migrating visual testing platforms to LambdaTest SmartUI
492 lines (482 loc) • 19.2 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.SmartUIConfigGenerator = void 0;
const path = __importStar(require("path"));
const fs = __importStar(require("fs/promises"));
const Logger_1 = require("../utils/Logger");
class SmartUIConfigGenerator {
constructor(projectPath, verbose = false) {
this.projectPath = projectPath;
this.verbose = verbose;
}
/**
* Generate complete SmartUI configuration
*/
async generateSmartUIConfig(projectType, framework, language) {
if (this.verbose)
Logger_1.logger.debug('Generating SmartUI configuration...');
const config = {
project: {
name: await this.detectProjectName(),
type: projectType,
framework: framework,
language: language
},
browsers: await this.detectSupportedBrowsers(framework),
devices: await this.detectSupportedDevices(framework),
settings: await this.generateDefaultSettings(projectType, framework),
environments: await this.generateEnvironmentConfigs(projectType),
credentials: {
// Will be populated by user or environment variables
}
};
await this.writeSmartUIConfig(config);
return config;
}
/**
* Install SmartUI packages automatically
*/
async installPackages(framework, language) {
const result = {
success: true,
packagesInstalled: [],
errors: [],
warnings: []
};
try {
if (this.verbose)
Logger_1.logger.debug('Installing SmartUI packages...');
// Detect package manager
const packageManager = await this.detectPackageManager();
if (packageManager === 'npm' || packageManager === 'yarn' || packageManager === 'pnpm') {
await this.installNodePackages(framework, result);
}
else if (packageManager === 'maven') {
await this.installMavenPackages(framework, result);
}
else if (packageManager === 'gradle') {
await this.installGradlePackages(framework, result);
}
else if (packageManager === 'pip') {
await this.installPythonPackages(framework, result);
}
else {
result.warnings.push(`Unsupported package manager: ${packageManager}`);
}
}
catch (error) {
result.success = false;
result.errors.push(`Failed to install packages: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
return result;
}
/**
* Generate environment setup scripts
*/
async generateEnvironmentScripts() {
if (this.verbose)
Logger_1.logger.debug('Generating environment setup scripts...');
// Generate .env template
const envTemplate = this.generateEnvTemplate();
await fs.writeFile(path.join(this.projectPath, '.env.template'), envTemplate, 'utf-8');
// Generate environment setup script
const setupScript = this.generateSetupScript();
await fs.writeFile(path.join(this.projectPath, 'setup-smartui.sh'), setupScript, 'utf-8');
// Make script executable
await fs.chmod(path.join(this.projectPath, 'setup-smartui.sh'), 0o755);
if (this.verbose)
Logger_1.logger.debug('Environment setup scripts generated');
}
/**
* Validate SmartUI configuration
*/
async validateConfiguration() {
const errors = [];
const warnings = [];
try {
const configPath = path.join(this.projectPath, '.smartui.json');
const configContent = await fs.readFile(configPath, 'utf-8');
const config = JSON.parse(configContent);
// Validate required fields
if (!config.project.name) {
errors.push('Project name is required');
}
if (!config.project.framework) {
errors.push('Project framework is required');
}
if (!config.browsers || config.browsers.length === 0) {
warnings.push('No browsers configured');
}
if (!config.settings) {
errors.push('Settings configuration is required');
}
// Validate credentials (optional but recommended)
if (!config.credentials.username && !process.env['LT_USERNAME']) {
warnings.push('SmartUI username not configured. Set LT_USERNAME environment variable or update .smartui.json');
}
if (!config.credentials.accessKey && !process.env['LT_ACCESS_KEY']) {
warnings.push('SmartUI access key not configured. Set LT_ACCESS_KEY environment variable or update .smartui.json');
}
}
catch (error) {
errors.push(`Failed to read or parse .smartui.json: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
return {
valid: errors.length === 0,
errors,
warnings
};
}
// Private methods
async detectProjectName() {
try {
// Try package.json first
const packageJsonPath = path.join(this.projectPath, 'package.json');
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
return packageJson.name || path.basename(this.projectPath);
}
catch {
try {
// Try pom.xml
const pomPath = path.join(this.projectPath, 'pom.xml');
const pomContent = await fs.readFile(pomPath, 'utf-8');
const pomObject = await this.parsePomXml(pomContent);
return pomObject.project?.artifactId?.[0] || path.basename(this.projectPath);
}
catch {
return path.basename(this.projectPath);
}
}
}
async parsePomXml(content) {
// Simple XML parsing for artifactId
const artifactIdMatch = content.match(/<artifactId>([^<]+)<\/artifactId>/);
return {
project: {
artifactId: artifactIdMatch ? [artifactIdMatch[1]] : []
}
};
}
async detectSupportedBrowsers(framework) {
const browserMap = {
'Selenium': ['chrome', 'firefox', 'safari', 'edge'],
'Playwright': ['chrome', 'firefox', 'safari', 'edge', 'webkit'],
'Cypress': ['chrome', 'firefox', 'edge', 'webkit'],
'Puppeteer': ['chrome'],
'WebdriverIO': ['chrome', 'firefox', 'safari', 'edge'],
'Appium': ['chrome', 'safari']
};
return browserMap[framework] || ['chrome', 'firefox', 'safari', 'edge'];
}
async detectSupportedDevices(framework) {
const deviceMap = {
'Selenium': ['desktop', 'tablet', 'mobile'],
'Playwright': ['desktop', 'tablet', 'mobile'],
'Cypress': ['desktop', 'tablet', 'mobile'],
'Puppeteer': ['desktop'],
'WebdriverIO': ['desktop', 'tablet', 'mobile'],
'Appium': ['mobile', 'tablet']
};
return deviceMap[framework] || ['desktop', 'tablet', 'mobile'];
}
async generateDefaultSettings(projectType, framework) {
const baseSettings = {
screenshotTimeout: 30000,
comparisonThreshold: 0.1,
ignoreRegions: [],
fullPageScreenshot: true,
captureScrollbars: false,
ignoreAntialiasing: false,
ignoreColors: false,
ignoreDisplacements: false
};
// Add type-specific settings
switch (projectType.toLowerCase()) {
case 'web':
baseSettings.viewportSizes = [
{ width: 1920, height: 1080, name: 'Desktop Large' },
{ width: 1366, height: 768, name: 'Desktop Medium' },
{ width: 375, height: 667, name: 'Mobile' },
{ width: 768, height: 1024, name: 'Tablet' }
];
baseSettings.deviceTypes = ['desktop', 'tablet', 'mobile'];
break;
case 'mobile':
baseSettings.deviceTypes = ['mobile', 'tablet'];
baseSettings.viewportSizes = [
{ width: 375, height: 667, name: 'iPhone SE' },
{ width: 414, height: 896, name: 'iPhone 11' },
{ width: 768, height: 1024, name: 'iPad' }
];
break;
case 'desktop':
baseSettings.deviceTypes = ['desktop'];
baseSettings.viewportSizes = [
{ width: 1920, height: 1080, name: 'Full HD' },
{ width: 2560, height: 1440, name: '2K' },
{ width: 3840, height: 2160, name: '4K' }
];
break;
}
// Add framework-specific settings
if (framework === 'Cypress') {
baseSettings.layoutBreakpoints = [768, 1024, 1440];
}
return baseSettings;
}
async generateEnvironmentConfigs(projectType) {
const environments = [];
// Add common environments
environments.push({
name: 'local',
url: 'http://localhost:3000',
variables: {
NODE_ENV: 'development'
},
browsers: ['chrome'],
devices: ['desktop']
});
environments.push({
name: 'staging',
url: 'https://staging.example.com',
variables: {
NODE_ENV: 'staging'
},
browsers: ['chrome', 'firefox'],
devices: ['desktop', 'tablet']
});
environments.push({
name: 'production',
url: 'https://example.com',
variables: {
NODE_ENV: 'production'
},
browsers: ['chrome', 'firefox', 'safari', 'edge'],
devices: ['desktop', 'tablet', 'mobile']
});
return environments;
}
async writeSmartUIConfig(config) {
const configPath = path.join(this.projectPath, '.smartui.json');
const configContent = JSON.stringify(config, null, 2);
await fs.writeFile(configPath, configContent, 'utf-8');
if (this.verbose)
Logger_1.logger.debug(`SmartUI configuration written to ${configPath}`);
}
async detectPackageManager() {
// Check for package.json (Node.js)
try {
await fs.access(path.join(this.projectPath, 'package.json'));
return 'npm'; // Default to npm, could also check for yarn.lock or pnpm-lock.yaml
}
catch { }
// Check for pom.xml (Maven)
try {
await fs.access(path.join(this.projectPath, 'pom.xml'));
return 'maven';
}
catch { }
// Check for build.gradle (Gradle)
try {
await fs.access(path.join(this.projectPath, 'build.gradle'));
return 'gradle';
}
catch { }
// Check for requirements.txt (Python)
try {
await fs.access(path.join(this.projectPath, 'requirements.txt'));
return 'pip';
}
catch { }
return 'unknown';
}
async installNodePackages(framework, result) {
const packages = this.getNodePackages(framework);
for (const pkg of packages) {
try {
// In a real implementation, this would run npm install
result.packagesInstalled.push(pkg);
if (this.verbose)
Logger_1.logger.debug(`Would install: ${pkg}`);
}
catch (error) {
result.errors.push(`Failed to install ${pkg}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
async installMavenPackages(framework, result) {
const packages = this.getMavenPackages(framework);
for (const pkg of packages) {
try {
// In a real implementation, this would update pom.xml
result.packagesInstalled.push(pkg);
if (this.verbose)
Logger_1.logger.debug(`Would add Maven dependency: ${pkg}`);
}
catch (error) {
result.errors.push(`Failed to add Maven dependency ${pkg}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
async installGradlePackages(framework, result) {
const packages = this.getGradlePackages(framework);
for (const pkg of packages) {
try {
// In a real implementation, this would update build.gradle
result.packagesInstalled.push(pkg);
if (this.verbose)
Logger_1.logger.debug(`Would add Gradle dependency: ${pkg}`);
}
catch (error) {
result.errors.push(`Failed to add Gradle dependency ${pkg}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
async installPythonPackages(framework, result) {
const packages = this.getPythonPackages(framework);
for (const pkg of packages) {
try {
// In a real implementation, this would run pip install
result.packagesInstalled.push(pkg);
if (this.verbose)
Logger_1.logger.debug(`Would install Python package: ${pkg}`);
}
catch (error) {
result.errors.push(`Failed to install Python package ${pkg}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
getNodePackages(framework) {
const packageMap = {
'Selenium': ['@lambdatest/smartui-selenium'],
'Playwright': ['@lambdatest/smartui-playwright'],
'Cypress': ['@lambdatest/smartui-cypress'],
'Puppeteer': ['@lambdatest/smartui-puppeteer'],
'WebdriverIO': ['@lambdatest/smartui-webdriverio']
};
return packageMap[framework] || ['@lambdatest/smartui-cli'];
}
getMavenPackages(framework) {
const packageMap = {
'Selenium': ['com.lambdatest:smartui-selenium-java:1.0.0'],
'Playwright': ['com.lambdatest:smartui-playwright-java:1.0.0'],
'Appium': ['com.lambdatest:smartui-appium-java:1.0.0']
};
return packageMap[framework] || ['com.lambdatest:smartui-selenium-java:1.0.0'];
}
getGradlePackages(framework) {
const packageMap = {
'Selenium': ['com.lambdatest:smartui-selenium-java:1.0.0'],
'Playwright': ['com.lambdatest:smartui-playwright-java:1.0.0'],
'Appium': ['com.lambdatest:smartui-appium-java:1.0.0']
};
return packageMap[framework] || ['com.lambdatest:smartui-selenium-java:1.0.0'];
}
getPythonPackages(framework) {
const packageMap = {
'Selenium': ['lambdatest-smartui-selenium'],
'Playwright': ['lambdatest-smartui-playwright'],
'Pytest': ['lambdatest-smartui-pytest']
};
return packageMap[framework] || ['lambdatest-smartui-selenium'];
}
generateEnvTemplate() {
return `# SmartUI Configuration
# Copy this file to .env and fill in your credentials
# LambdaTest SmartUI Credentials
LT_USERNAME=your_username_here
LT_ACCESS_KEY=your_access_key_here
LT_PROJECT_TOKEN=your_project_token_here
# Optional: SmartUI Settings
SMARTUI_BROWSER=chrome
SMARTUI_VIEWPORT=1920x1080
SMARTUI_TIMEOUT=30000
SMARTUI_THRESHOLD=0.1
# Optional: Test Environment
TEST_ENV=staging
TEST_URL=https://staging.example.com
`;
}
generateSetupScript() {
return `#!/bin/bash
# SmartUI Setup Script
# This script helps you set up SmartUI for your project
echo "🚀 Setting up SmartUI for your project..."
# Check if .env file exists
if [ ! -f .env ]; then
echo "📝 Creating .env file from template..."
cp .env.template .env
echo "⚠️ Please edit .env file with your LambdaTest credentials"
echo " - LT_USERNAME: Your LambdaTest username"
echo " - LT_ACCESS_KEY: Your LambdaTest access key"
echo " - LT_PROJECT_TOKEN: Your SmartUI project token"
else
echo "✅ .env file already exists"
fi
# Check if .smartui.json exists
if [ ! -f .smartui.json ]; then
echo "❌ .smartui.json not found. Please run the migration tool first."
exit 1
else
echo "✅ .smartui.json found"
fi
# Install SmartUI packages
echo "📦 Installing SmartUI packages..."
# Detect package manager and install packages
if [ -f package.json ]; then
echo "📦 Installing Node.js packages..."
npm install /smartui-cli
elif [ -f pom.xml ]; then
echo "📦 Maven project detected. Please add SmartUI dependencies to pom.xml"
elif [ -f build.gradle ]; then
echo "📦 Gradle project detected. Please add SmartUI dependencies to build.gradle"
elif [ -f requirements.txt ]; then
echo "📦 Installing Python packages..."
pip install lambdatest-smartui-selenium
else
echo "⚠️ Unknown project type. Please install SmartUI packages manually."
fi
echo "✅ SmartUI setup complete!"
echo ""
echo "Next steps:"
echo "1. Edit .env file with your credentials"
echo "2. Run your tests with SmartUI"
echo "3. Check the SmartUI dashboard for results"
`;
}
}
exports.SmartUIConfigGenerator = SmartUIConfigGenerator;
//# sourceMappingURL=SmartUIConfigGenerator.js.map