UNPKG

smartui-migration-tool

Version:

Enterprise-grade CLI tool for migrating visual testing platforms to LambdaTest SmartUI

731 lines • 39.6 kB
"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; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TransformationManager = void 0; const chalk_1 = __importDefault(require("chalk")); const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); const Logger_1 = require("../utils/Logger"); const ProgressManager_1 = require("../utils/ProgressManager"); const ConfigTransformer_1 = require("./ConfigTransformer"); const PomTransformer_1 = require("./PomTransformer"); const ChangeTracker_1 = require("./ChangeTracker"); class TransformationManager { constructor(projectPath, verbose = false, selectedFiles = []) { this.projectPath = projectPath; this.verbose = verbose; this.selectedFiles = selectedFiles; this.changeTracker = new ChangeTracker_1.ChangeTracker(); } /** * Get the change tracker instance */ getChangeTracker() { return this.changeTracker; } /** * Complete migration and mark change tracking as finished */ completeMigration() { this.changeTracker.completeMigration(); } /** * Execute the transformation with user confirmation and backup options */ async executeTransformation(detectionResult, preview, options) { Logger_1.logger.verbose('Starting transformation execution...'); const result = { success: true, filesCreated: [], filesModified: [], filesBackedUp: [], errors: [], warnings: [] }; // Show backup recommendation this.showBackupRecommendation(); // Get user confirmation (skip if in auto mode or dry run) if (!options.dryRun && !options.yes) { const confirmed = await this.getUserConfirmation(preview, options); if (!confirmed) { console.log(chalk_1.default.yellow('Transformation cancelled by user.')); return result; } } else if (options.yes) { console.log(chalk_1.default.green('šŸ¤– Auto mode: Skipping user confirmation')); } // Create backups if requested if (options.createBackup && !options.dryRun) { await this.createBackups(preview, result); } // Execute transformations try { // Create progress bar for transformation const totalFiles = preview.configChanges.length + preview.codeChanges.length + preview.executionChanges.length; const progress = ProgressManager_1.ProgressManager.createTransformProgress(totalFiles, this.verbose); // Transform configurations progress.update(0, { title: 'Transforming configuration files' }); await this.executeConfigTransformation(detectionResult, preview.configChanges, options, result); // Transform code progress.update(preview.configChanges.length, { title: 'Transforming code files' }); await this.executeCodeTransformation(detectionResult, preview.codeChanges, options, result); // Transform execution files progress.update(preview.configChanges.length + preview.codeChanges.length, { title: 'Transforming execution files' }); await this.executeExecutionTransformation(detectionResult, preview.executionChanges, options, result); progress.complete({ title: 'Transformation completed successfully' }); } catch (error) { result.success = false; result.errors.push(`Transformation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); Logger_1.logger.verbose(`Transformation error: ${error instanceof Error ? error.message : 'Unknown error'}`); } // Show transformation summary this.showTransformationSummary(result); // Show current state of the code await this.showCurrentCodeState(); return result; } /** * Show backup recommendation */ showBackupRecommendation() { console.log(chalk_1.default.yellow.bold('\nšŸ›”ļø BACKUP RECOMMENDATION')); console.log(chalk_1.default.gray('─'.repeat(50))); console.log(chalk_1.default.yellow('āš ļø IMPORTANT: Before proceeding with the transformation, we strongly recommend:')); console.log(chalk_1.default.white(' 1. Creating a backup of your project directory')); console.log(chalk_1.default.white(' 2. Committing your current changes to version control')); console.log(chalk_1.default.white(' 3. Testing the transformation on a copy first')); console.log(chalk_1.default.gray('─'.repeat(50))); console.log(chalk_1.default.blue('šŸ’” For POC purposes, consider running this on a test directory first.')); console.log(chalk_1.default.blue(' Once you\'re confident with the results, you can run it on your real project.')); console.log(chalk_1.default.gray('─'.repeat(50))); } /** * Get user confirmation for the transformation */ async getUserConfirmation(preview, options) { const inquirer = await Promise.resolve().then(() => __importStar(require('inquirer'))); console.log(chalk_1.default.bold.blue('\nšŸ¤” TRANSFORMATION CONFIRMATION')); console.log(chalk_1.default.gray('='.repeat(50))); // Show detailed summary console.log(chalk_1.default.white(`\nThe migration will:`)); console.log(chalk_1.default.white(` • Modify ${preview.totalFiles} files`)); console.log(chalk_1.default.white(` • Migrate ${preview.totalSnapshots} snapshots`)); console.log(chalk_1.default.white(` • Create ${preview.configChanges.filter(c => c.changeType === 'CREATE').length} new files`)); console.log(chalk_1.default.white(` • Modify ${preview.configChanges.filter(c => c.changeType === 'MODIFY').length + preview.codeChanges.length + preview.executionChanges.length} existing files`)); if (preview.warnings.length > 0) { console.log(chalk_1.default.yellow(` • ${preview.warnings.length} warnings to review`)); } // Show detailed file breakdown console.log(chalk_1.default.bold('\nšŸ“‹ File Breakdown:')); if (preview.configChanges.length > 0) { console.log(chalk_1.default.blue(` Configuration files (${preview.configChanges.length}):`)); preview.configChanges.forEach(change => { const icon = change.changeType === 'CREATE' ? 'āž•' : 'āœļø'; console.log(chalk_1.default.blue(` ${icon} ${change.filePath} (${change.changes.length} changes)`)); }); } if (preview.codeChanges.length > 0) { console.log(chalk_1.default.green(` Code files (${preview.codeChanges.length}):`)); preview.codeChanges.forEach(change => { console.log(chalk_1.default.green(` āœļø ${change.filePath} (${change.changes.length} changes)`)); }); } if (preview.executionChanges.length > 0) { console.log(chalk_1.default.magenta(` Execution files (${preview.executionChanges.length}):`)); preview.executionChanges.forEach(change => { console.log(chalk_1.default.magenta(` āœļø ${change.filePath} (${change.changes.length} changes)`)); }); } // Show backup recommendation if (!options.createBackup) { console.log(chalk_1.default.bold.yellow('\nāš ļø BACKUP RECOMMENDATION')); console.log(chalk_1.default.yellow('We strongly recommend creating backups before transformation.')); console.log(chalk_1.default.yellow('Use --backup flag to automatically create backups.')); console.log(chalk_1.default.yellow('This ensures you can restore your original files if needed.')); } // Show POC recommendation console.log(chalk_1.default.bold.cyan('\nšŸ’” POC RECOMMENDATION')); console.log(chalk_1.default.cyan('For Proof of Concept (POC) purposes:')); console.log(chalk_1.default.cyan(' 1. Test the migration on a copy of your project first')); console.log(chalk_1.default.cyan(' 2. Verify the results in the copied directory')); console.log(chalk_1.default.cyan(' 3. Once confident, run it on your real project directory')); console.log(chalk_1.default.cyan(' 4. Always keep backups of your original files')); // Get confirmation with options const answer = await inquirer.default.prompt([ { type: 'list', name: 'action', message: 'What would you like to do?', choices: [ { name: 'āœ… Proceed with transformation (recommended with --backup)', value: 'proceed' }, { name: 'šŸ“‹ Show detailed changes for each file', value: 'detailed' }, { name: 'āŒ Cancel transformation', value: 'cancel' } ], default: 'proceed' } ]); if (answer['action'] === 'detailed') { await this.showDetailedChanges(preview); return await this.getUserConfirmation(preview, options); } if (answer['action'] === 'cancel') { return false; } // Final confirmation const finalAnswer = await inquirer.default.prompt([ { type: 'confirm', name: 'proceed', message: 'Are you absolutely sure you want to proceed with the transformation?', default: false } ]); if (!finalAnswer['proceed']) { return false; } // File-by-file confirmation if requested if (options.confirmEachFile) { const allChanges = [...preview.configChanges, ...preview.codeChanges, ...preview.executionChanges]; for (const change of allChanges) { const fileQuestion = { type: 'confirm', name: 'proceed', message: `Transform ${change.filePath}? (${change.changeType}, ${change.changes.length} changes)`, default: true, }; const fileAnswer = await inquirer.default.prompt([fileQuestion]); if (!fileAnswer['proceed']) { console.log(chalk_1.default.yellow(`Skipping ${change.filePath}`)); continue; } } } return true; } /** * Show detailed changes for each file */ async showDetailedChanges(preview) { console.log(chalk_1.default.bold.blue('\nšŸ“‹ DETAILED CHANGES')); console.log(chalk_1.default.gray('='.repeat(50))); const allChanges = [ ...preview.configChanges.map(c => ({ ...c, type: 'Configuration' })), ...preview.codeChanges.map(c => ({ ...c, type: 'Code' })), ...preview.executionChanges.map(c => ({ ...c, type: 'Execution' })) ]; for (const change of allChanges) { console.log(chalk_1.default.bold(`\nšŸ“„ ${change.filePath} (${change.type})`)); console.log(chalk_1.default.gray(`Change Type: ${change.changeType}`)); console.log(chalk_1.default.gray(`Total Changes: ${change.changes.length}`)); if (change.changes.length > 0) { console.log(chalk_1.default.gray('\nChanges:')); change.changes.forEach((changeDetail, index) => { const lineNum = changeDetail.lineNumber; const changeTypeIcon = changeDetail.changeType === 'ADD' ? '+' : changeDetail.changeType === 'DELETE' ? '-' : '~'; const changeColor = changeDetail.changeType === 'ADD' ? chalk_1.default.green : changeDetail.changeType === 'DELETE' ? chalk_1.default.red : chalk_1.default.yellow; console.log(chalk_1.default.gray(` ${index + 1}. Line ${lineNum}: ${changeTypeIcon} ${changeDetail.description}`)); // Show before/after for modifications if (changeDetail.changeType === 'MODIFY') { if (changeDetail.originalLine) { console.log(chalk_1.default.red(` - ${changeDetail.originalLine}`)); } if (changeDetail.newLine) { console.log(chalk_1.default.green(` + ${changeDetail.newLine}`)); } } else if (changeDetail.changeType === 'ADD' && changeDetail.newLine) { console.log(chalk_1.default.green(` + ${changeDetail.newLine}`)); } else if (changeDetail.changeType === 'DELETE' && changeDetail.originalLine) { console.log(chalk_1.default.red(` - ${changeDetail.originalLine}`)); } }); } if (change.warnings.length > 0) { console.log(chalk_1.default.yellow('\nWarnings:')); change.warnings.forEach(warning => { console.log(chalk_1.default.yellow(` • ${warning}`)); }); } } console.log(chalk_1.default.gray('\n' + '='.repeat(50))); } /** * Create backups of files that will be modified */ async createBackups(preview, result) { console.log(chalk_1.default.blue('\nšŸ“¦ Creating backups...')); const allChanges = [...preview.configChanges, ...preview.codeChanges, ...preview.executionChanges]; const backupDir = path_1.default.join(this.projectPath, '.smartui-backup'); try { await fs_1.promises.mkdir(backupDir, { recursive: true }); for (const change of allChanges) { if (change.changeType === 'MODIFY' && change.originalContent) { const backupPath = path_1.default.join(backupDir, `${change.filePath}.backup`); const backupDirPath = path_1.default.dirname(backupPath); await fs_1.promises.mkdir(backupDirPath, { recursive: true }); await fs_1.promises.writeFile(backupPath, change.originalContent, 'utf-8'); result.filesBackedUp.push(change.filePath); console.log(chalk_1.default.green(` āœ… Backed up: ${change.filePath}`)); } } console.log(chalk_1.default.green(`\nāœ… Created ${result.filesBackedUp.length} backup files in .smartui-backup/`)); } catch (error) { const errorMsg = `Failed to create backups: ${error instanceof Error ? error.message : 'Unknown error'}`; result.warnings.push(errorMsg); console.log(chalk_1.default.yellow(`āš ļø ${errorMsg}`)); } } /** * Execute configuration transformations */ async executeConfigTransformation(detectionResult, configChanges, options, result) { console.log(chalk_1.default.blue('\nšŸ“ Transforming configuration files...')); // Filter changes by selected files const changesToProcess = this.selectedFiles.length > 0 ? configChanges.filter(change => this.selectedFiles.includes(change.filePath) || this.selectedFiles.includes('.smartui.json')) : configChanges; // Transform package.json dependencies and scripts (always run when source platform detected) try { const configTransformer = new ConfigTransformer_1.ConfigTransformer(this.projectPath); await configTransformer.transformPackageJson(detectionResult); console.log(chalk_1.default.green(' āœ… Transformed package.json dependencies and scripts')); result.filesModified.push('package.json'); // Track package.json changes this.changeTracker.trackFileChange('package.json', 'MODIFY', undefined, // Original content not available here undefined, // New content not available here 'Transformed package.json dependencies and scripts for SmartUI migration', undefined, undefined, detectionResult.platform === 'Percy' ? 1 : 0 // Estimate dependency count ); } catch (error) { if (error.code !== 'ENOENT') { // Ignore if package.json doesn't exist const errorMsg = `Failed to transform package.json: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } // Transform .csproj files for C# projects if (detectionResult.language === 'C#') { try { const configTransformer = new ConfigTransformer_1.ConfigTransformer(this.projectPath); await configTransformer.transformCsprojFiles(detectionResult); console.log(chalk_1.default.green(' āœ… Transformed .csproj dependencies and packages')); // Track .csproj changes this.changeTracker.trackFileChange('*.csproj', 'MODIFY', undefined, // Original content not available here undefined, // New content not available here 'Transformed .csproj dependencies and packages for SmartUI migration', undefined, undefined, detectionResult.platform === 'Applitools' ? 1 : 0 // Estimate dependency count ); } catch (error) { const errorMsg = `Failed to transform .csproj files: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } // Transform CI/CD YAML files try { const configTransformer = new ConfigTransformer_1.ConfigTransformer(this.projectPath); await configTransformer.transformCICDFiles(detectionResult); console.log(chalk_1.default.green(' āœ… Transformed CI/CD YAML files')); } catch (error) { const errorMsg = `Failed to transform CI/CD files: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } // Transform POM.xml for Java projects (always run when Java platform detected) if (detectionResult.language === 'Java') { try { const pomTransformer = new PomTransformer_1.PomTransformer(this.projectPath); const pomResult = await pomTransformer.transformPomXml(detectionResult.platform); if (pomResult.success && pomResult.changes.length > 0) { await fs_1.promises.writeFile(path_1.default.join(this.projectPath, 'pom.xml'), pomResult.newContent, 'utf-8'); console.log(chalk_1.default.green(' āœ… Transformed POM.xml dependencies and plugins')); result.filesModified.push('pom.xml'); Logger_1.logger.verbose(`POM.xml changes: ${pomResult.changes.map(c => c.description).join(', ')}`); // Track POM.xml changes this.changeTracker.trackFileChange('pom.xml', 'MODIFY', undefined, // Original content not available here undefined, // New content not available here `Transformed POM.xml: ${pomResult.changes.map(c => c.description).join(', ')}`, undefined, undefined, pomResult.changes.length // Dependency count ); } else if (pomResult.success) { console.log(chalk_1.default.yellow(' āš ļø No POM.xml changes needed')); } else { const errorMsg = `Failed to transform POM.xml: ${pomResult.error}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } catch (error) { if (error.code !== 'ENOENT') { // Ignore if pom.xml doesn't exist const errorMsg = `Failed to transform POM.xml: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } } if (changesToProcess.length === 0) return; // Create progress bar for individual file processing const fileProgress = ProgressManager_1.ProgressManager.createFileProgress(changesToProcess.length, this.verbose); for (let i = 0; i < changesToProcess.length; i++) { const change = changesToProcess[i]; if (!change) continue; fileProgress.update(i, { title: `Processing ${change.filePath}` }); try { if (options.dryRun) { console.log(chalk_1.default.gray(` [DRY RUN] Would ${change.changeType.toLowerCase()} ${change.filePath}`)); continue; } const filePath = path_1.default.join(this.projectPath, change.filePath); const fileDir = path_1.default.dirname(filePath); await fs_1.promises.mkdir(fileDir, { recursive: true }); await fs_1.promises.writeFile(filePath, change.newContent, 'utf-8'); if (change.changeType === 'CREATE') { result.filesCreated.push(change.filePath); } else { result.filesModified.push(change.filePath); } console.log(chalk_1.default.green(` āœ… ${change.changeType === 'CREATE' ? 'Created' : 'Modified'}: ${change.filePath}`)); } catch (error) { const errorMsg = `Failed to transform ${change?.filePath || 'unknown file'}: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } fileProgress.complete({ title: 'Configuration files processed' }); } /** * Execute code transformations */ async executeCodeTransformation(detectionResult, codeChanges, options, result) { // Filter changes by selected files const changesToProcess = this.selectedFiles.length > 0 ? codeChanges.filter(change => this.selectedFiles.includes(change.filePath)) : codeChanges; if (changesToProcess.length === 0) return; console.log(chalk_1.default.green('\nšŸ’» Transforming code files...')); // Create progress bar for individual file processing const fileProgress = ProgressManager_1.ProgressManager.createFileProgress(changesToProcess.length, this.verbose); for (let i = 0; i < changesToProcess.length; i++) { const change = changesToProcess[i]; if (!change) continue; fileProgress.update(i, { title: `Processing ${change.filePath}` }); try { if (options.dryRun) { console.log(chalk_1.default.gray(` [DRY RUN] Would modify ${change.filePath} (${change.changes.length} changes)`)); continue; } const filePath = path_1.default.join(this.projectPath, change.filePath); await fs_1.promises.writeFile(filePath, change.newContent, 'utf-8'); result.filesModified.push(change.filePath); console.log(chalk_1.default.green(` āœ… Modified: ${change.filePath} (${change.changes.length} changes)`)); // Track code file changes this.changeTracker.trackFileChange(change.filePath, 'MODIFY', change.originalContent, change.newContent, `Transformed ${change.changes.length} visual testing calls to SmartUI`, undefined, change.changes.length // Snapshot count ); } catch (error) { const errorMsg = `Failed to transform ${change?.filePath || 'unknown file'}: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } fileProgress.complete({ title: 'Code files processed' }); } /** * Execute execution file transformations */ async executeExecutionTransformation(detectionResult, executionChanges, options, result) { // Filter changes by selected files const changesToProcess = this.selectedFiles.length > 0 ? executionChanges.filter(change => this.selectedFiles.includes(change.filePath)) : executionChanges; if (changesToProcess.length === 0) return; console.log(chalk_1.default.magenta('\nāš™ļø Transforming execution files...')); // Create progress bar for individual file processing const fileProgress = ProgressManager_1.ProgressManager.createFileProgress(changesToProcess.length, this.verbose); for (let i = 0; i < changesToProcess.length; i++) { const change = changesToProcess[i]; if (!change) continue; fileProgress.update(i, { title: `Processing ${change.filePath}` }); try { if (options.dryRun) { console.log(chalk_1.default.gray(` [DRY RUN] Would modify ${change.filePath} (${change.changes.length} changes)`)); continue; } const filePath = path_1.default.join(this.projectPath, change.filePath); await fs_1.promises.writeFile(filePath, change.newContent, 'utf-8'); result.filesModified.push(change.filePath); console.log(chalk_1.default.green(` āœ… Modified: ${change.filePath} (${change.changes.length} changes)`)); } catch (error) { const errorMsg = `Failed to transform ${change?.filePath || 'unknown file'}: ${error instanceof Error ? error.message : 'Unknown error'}`; result.errors.push(errorMsg); console.log(chalk_1.default.red(` āŒ ${errorMsg}`)); } } fileProgress.complete({ title: 'Execution files processed' }); } /** * Show transformation summary */ showTransformationSummary(result) { console.log(chalk_1.default.bold.blue('\nšŸ“Š TRANSFORMATION SUMMARY')); console.log(chalk_1.default.gray('='.repeat(50))); if (result.success) { console.log(chalk_1.default.green('āœ… Transformation completed successfully!')); } else { console.log(chalk_1.default.red('āŒ Transformation completed with errors')); } // Detailed file statistics console.log(chalk_1.default.bold('\nšŸ“ File Statistics:')); console.log(chalk_1.default.white(` • Files created: ${chalk_1.default.bold(result.filesCreated.length)}`)); console.log(chalk_1.default.white(` • Files modified: ${chalk_1.default.bold(result.filesModified.length)}`)); console.log(chalk_1.default.white(` • Files backed up: ${chalk_1.default.bold(result.filesBackedUp.length)}`)); console.log(chalk_1.default.white(` • Total files processed: ${chalk_1.default.bold(result.filesCreated.length + result.filesModified.length)}`)); // Show created files if (result.filesCreated.length > 0) { console.log(chalk_1.default.bold.green('\nšŸ“„ Files Created:')); result.filesCreated.forEach(file => { console.log(chalk_1.default.green(` āž• ${file}`)); }); } // Show modified files if (result.filesModified.length > 0) { console.log(chalk_1.default.bold.blue('\nāœļø Files Modified:')); result.filesModified.forEach(file => { console.log(chalk_1.default.blue(` āœļø ${file}`)); }); } // Show backed up files if (result.filesBackedUp.length > 0) { console.log(chalk_1.default.bold.yellow('\nšŸ“¦ Files Backed Up:')); result.filesBackedUp.forEach(file => { console.log(chalk_1.default.yellow(` šŸ“¦ ${file}`)); }); } // Show errors if (result.errors.length > 0) { console.log(chalk_1.default.bold.red('\nāŒ Errors:')); result.errors.forEach(error => { console.log(chalk_1.default.red(` • ${error}`)); }); } // Show warnings if (result.warnings.length > 0) { console.log(chalk_1.default.bold.yellow('\nāš ļø Warnings:')); result.warnings.forEach(warning => { console.log(chalk_1.default.yellow(` • ${warning}`)); }); } // Current state information console.log(chalk_1.default.bold.cyan('\nšŸ“‹ Current State of Your Code:')); console.log(chalk_1.default.cyan(' • All visual testing code has been migrated to SmartUI')); console.log(chalk_1.default.cyan(' • Configuration files have been updated')); console.log(chalk_1.default.cyan(' • Dependencies have been modified')); console.log(chalk_1.default.cyan(' • CI/CD scripts have been updated')); // Next steps console.log(chalk_1.default.bold.green('\nšŸš€ Next Steps:')); console.log(chalk_1.default.green(' 1. Install SmartUI dependencies: npm install @lambdatest/smartui-cli')); console.log(chalk_1.default.green(' 2. Configure your SmartUI credentials')); console.log(chalk_1.default.green(' 3. Update your test environment variables')); console.log(chalk_1.default.green(' 4. Run your migrated tests with SmartUI')); console.log(chalk_1.default.green(' 5. Check the SmartUI Dashboard for test results')); // Backup information if (result.filesBackedUp.length > 0) { console.log(chalk_1.default.bold.yellow('\nšŸ›”ļø Backup Information:')); console.log(chalk_1.default.yellow(` • ${result.filesBackedUp.length} files backed up to .smartui-backup/`)); console.log(chalk_1.default.yellow(' • Original files are safely preserved')); console.log(chalk_1.default.yellow(' • You can restore files if needed')); console.log(chalk_1.default.yellow(' • Keep backups until you\'re confident everything works')); } // POC guidance console.log(chalk_1.default.bold.cyan('\nšŸ’” POC Guidance:')); console.log(chalk_1.default.cyan(' • Test the migrated code in a development environment first')); console.log(chalk_1.default.cyan(' • Verify all tests run successfully with SmartUI')); console.log(chalk_1.default.cyan(' • Check that visual comparisons work as expected')); console.log(chalk_1.default.cyan(' • Once confident, deploy to your production environment')); // Support information console.log(chalk_1.default.bold.blue('\nšŸ†˜ Support:')); console.log(chalk_1.default.blue(' • Documentation: https://github.com/lambdatest/smartui-migration-tool')); console.log(chalk_1.default.blue(' • Issues: https://github.com/lambdatest/smartui-migration-tool/issues')); console.log(chalk_1.default.blue(' • SmartUI Docs: https://www.lambdatest.com/smart-ui')); console.log(chalk_1.default.gray('\n' + '='.repeat(50))); } /** * Show current state of the code after transformation */ async showCurrentCodeState() { console.log(chalk_1.default.bold.cyan('\nšŸ“‹ CURRENT STATE OF YOUR CODE')); console.log(chalk_1.default.gray('='.repeat(50))); try { // Check for SmartUI configuration const smartuiConfigPath = path_1.default.join(this.projectPath, '.smartui.json'); const configExists = await fs_1.promises.access(smartuiConfigPath).then(() => true).catch(() => false); if (configExists) { console.log(chalk_1.default.green('āœ… SmartUI configuration file (.smartui.json) is present')); try { const configContent = await fs_1.promises.readFile(smartuiConfigPath, 'utf-8'); const config = JSON.parse(configContent); console.log(chalk_1.default.gray(` • Project: ${config.project || 'Not specified'}`)); console.log(chalk_1.default.gray(` • Build Name: ${config.buildName || 'Not specified'}`)); console.log(chalk_1.default.gray(` • Branch: ${config.branch || 'Not specified'}`)); } catch (error) { console.log(chalk_1.default.yellow('āš ļø SmartUI configuration file exists but could not be parsed')); } } else { console.log(chalk_1.default.yellow('āš ļø SmartUI configuration file (.smartui.json) not found')); } // Check package.json for SmartUI dependencies const packageJsonPath = path_1.default.join(this.projectPath, 'package.json'); const packageExists = await fs_1.promises.access(packageJsonPath).then(() => true).catch(() => false); if (packageExists) { try { const packageContent = await fs_1.promises.readFile(packageJsonPath, 'utf-8'); const packageJson = JSON.parse(packageContent); const hasSmartUIDep = packageJson.dependencies && (packageJson.dependencies['@lambdatest/smartui-cli'] || packageJson.dependencies['@lambdatest/smartui']); if (hasSmartUIDep) { console.log(chalk_1.default.green('āœ… SmartUI dependencies are present in package.json')); } else { console.log(chalk_1.default.yellow('āš ļø SmartUI dependencies not found in package.json')); console.log(chalk_1.default.cyan(' Run: npm install @lambdatest/smartui-cli')); } } catch (error) { console.log(chalk_1.default.yellow('āš ļø Could not read package.json')); } } // Check for test files that might have been migrated const testFiles = await this.findTestFiles(); if (testFiles.length > 0) { console.log(chalk_1.default.green(`āœ… Found ${testFiles.length} test files that may have been migrated`)); testFiles.slice(0, 5).forEach(file => { console.log(chalk_1.default.gray(` • ${file}`)); }); if (testFiles.length > 5) { console.log(chalk_1.default.gray(` • ... and ${testFiles.length - 5} more files`)); } } // Check for backup directory const backupDir = path_1.default.join(this.projectPath, '.smartui-backup'); const backupExists = await fs_1.promises.access(backupDir).then(() => true).catch(() => false); if (backupExists) { console.log(chalk_1.default.green('āœ… Backup directory (.smartui-backup) exists')); try { const backupFiles = await fs_1.promises.readdir(backupDir); console.log(chalk_1.default.gray(` • ${backupFiles.length} backup files available`)); } catch (error) { console.log(chalk_1.default.yellow('āš ļø Could not read backup directory')); } } } catch (error) { console.log(chalk_1.default.red('āŒ Error checking current state:'), error); } console.log(chalk_1.default.gray('\n' + '='.repeat(50))); } /** * Find test files in the project */ async findTestFiles() { const testFiles = []; const testPatterns = [ '**/*.test.js', '**/*.test.ts', '**/*.spec.js', '**/*.spec.ts', '**/cypress/**/*.js', '**/cypress/**/*.ts', '**/tests/**/*.js', '**/tests/**/*.ts', '**/test/**/*.js', '**/test/**/*.ts' ]; try { const { glob } = await Promise.resolve().then(() => __importStar(require('fast-glob'))); for (const pattern of testPatterns) { const files = await glob(pattern, { cwd: this.projectPath }); testFiles.push(...files); } } catch (error) { // Fallback to basic file system search try { const files = await fs_1.promises.readdir(this.projectPath, { recursive: true }); testFiles.push(...files.filter(file => typeof file === 'string' && (file.includes('.test.') || file.includes('.spec.') || file.includes('cypress')))); } catch (error) { // Ignore errors in fallback } } return [...new Set(testFiles)]; // Remove duplicates } } exports.TransformationManager = TransformationManager; //# sourceMappingURL=TransformationManager.js.map