Files
Jellify/scripts/maestro-android.js
Violet Caulfield 8bd28bfe00 com.jellify -> com.cosmonautical.jellify (#601)
* com.jellify -> com.cosmonautical.jellify

Update Android App ID to fall under the correct parent organization
2025-10-27 10:24:39 -05:00

178 lines
4.9 KiB
JavaScript

const { execSync, exec, spawn } = require('child_process')
const path = require('path')
const fs = require('fs')
// Read arguments from CLI
const [, , serverAddress, username] = process.argv
if (!serverAddress || !username) {
console.error('Usage: node runMaestro.js <server_address> <username>')
process.exit(1)
}
// Function to recursively find all YAML files in maestro/tests directory
function findYamlFiles(dir) {
const files = []
function scanDirectory(currentDir) {
const items = fs.readdirSync(currentDir)
for (const item of items) {
const fullPath = path.join(currentDir, item)
const stat = fs.statSync(fullPath)
if (stat.isDirectory()) {
scanDirectory(fullPath)
} else if (item.endsWith('.yaml') || item.endsWith('.yml')) {
files.push(fullPath)
}
}
}
scanDirectory(dir)
return files.sort() // Sort for consistent ordering
}
// Get all YAML files from maestro/tests directory
const MAESTRO_TESTS_DIR = './maestro/tests'
const FLOW_FILES = findYamlFiles(MAESTRO_TESTS_DIR)
console.log(`🔍 Found ${FLOW_FILES.length} YAML test files:`)
FLOW_FILES.forEach((file, index) => {
console.log(` ${index + 1}. ${file}`)
})
if (FLOW_FILES.length === 0) {
console.error('❌ No YAML test files found in maestro/testsdirectory')
process.exit(1)
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
async function stopRecording(pid, videoName, deviceVideoPath) {
try {
// Kill the adb screenrecord process
process.kill(pid, 'SIGINT')
// Wait 3 seconds for file to finalize
await sleep(3000)
// Pull the recorded file with custom name
execSync(`adb pull ${deviceVideoPath} ${videoName}`, { stdio: 'inherit' })
// Optionally delete the file on device
execSync(`adb shell rm ${deviceVideoPath}`)
console.log(`✅ Recording pulled and saved as ${videoName}`)
} catch (err) {
console.error('❌ Failed to stop or pull recording:', err.message)
}
}
async function runSingleTest(flowPath, serverAddress, username, testIndex) {
const flowName = path.basename(flowPath, '.yaml')
const relativePath = path.relative(MAESTRO_TESTS_DIR, flowPath)
const videoName = `test_${testIndex}_${flowName}.mp4`
const deviceVideoPath = `/sdcard/screen_${testIndex}_${flowName}.mp4`
console.log(`\n🚀 Starting test ${testIndex + 1}/${FLOW_FILES.length}: ${relativePath}`)
console.log(`📹 Video will be saved as: ${videoName}`)
// Start screen recording
const recording = spawn(
'adb',
['shell', 'screenrecord', '--time-limit=1800', deviceVideoPath],
{
stdio: 'ignore',
detached: true,
},
)
const pid = recording.pid
try {
const MAESTRO_PATH = path.join(process.env.HOME, '.maestro', 'bin', 'maestro')
const command = `${MAESTRO_PATH} test ${flowPath} \
--env server_address=${serverAddress} \
--env username=${username}`
const output = execSync(command, { stdio: 'inherit', env: process.env })
console.log(`✅ Test ${testIndex + 1} (${relativePath}) completed successfully`)
await stopRecording(pid, videoName, deviceVideoPath)
return { success: true, flowName, relativePath, videoName }
} catch (error) {
await stopRecording(pid, videoName, deviceVideoPath)
console.error(`❌ Test ${testIndex + 1} (${relativePath}) failed: ${error.message}`)
return { success: false, flowName, relativePath, videoName, error: error.message }
}
}
;(async () => {
console.log('📱 Installing app...')
execSync('adb install ./artifacts/app-universal-release.apk', {
stdio: 'inherit',
env: process.env,
})
console.log('🚀 Launching app...')
execSync(`adb shell monkey -p com.cosmonautical.jellify 1`, { stdio: 'inherit' })
// Wait a bit for app to launch
await sleep(2000)
const results = []
console.log(`\n🔄 Starting test suite with ${FLOW_FILES.length} tests...`)
for (let i = 0; i < FLOW_FILES.length; i++) {
const flowPath = FLOW_FILES[i]
// Check if flow file exists
if (!fs.existsSync(flowPath)) {
console.log(`⚠️ Skipping ${flowPath} - file not found`)
continue
}
const result = await runSingleTest(flowPath, serverAddress, username, i)
results.push(result)
// Wait between tests to ensure clean state
if (i < FLOW_FILES.length - 1) {
console.log('⏳ Waiting 3 seconds before next test...')
await sleep(3000)
}
}
// Print summary
console.log('\n📊 Test Results Summary:')
console.log('========================')
let passed = 0
let failed = 0
results.forEach((result, index) => {
const status = result.success ? '✅ PASS' : '❌ FAIL'
console.log(`${index + 1}. ${result.relativePath}: ${status}`)
if (result.success) {
passed++
} else {
failed++
console.log(` Error: ${result.error}`)
}
console.log(` Video: ${result.videoName}`)
})
console.log(`\n📈 Final Results: ${passed} passed, ${failed} failed`)
if (failed === 0) {
console.log('🎉 All tests passed!')
process.exit(0)
} else {
console.log('⚠️ Some tests failed. Check the videos for details.')
process.exit(1)
}
})()