@ -30,6 +30,7 @@
*
* @ requires child_process
* @ requires path
* @ requires fs
*
* @ author TimeSafari Team
* @ license MIT
@ -37,6 +38,166 @@
const { execSync } = require ( 'child_process' ) ;
const { join } = require ( 'path' ) ;
const { existsSync , mkdirSync , appendFileSync , readFileSync } = require ( 'fs' ) ;
// Format date as YYYY-MM-DD-HHMMSS
const getLogFileName = ( ) => {
const now = new Date ( ) ;
const date = now . toISOString ( ) . split ( 'T' ) [ 0 ] ;
const time = now . toTimeString ( ) . split ( ' ' ) [ 0 ] . replace ( /:/g , '' ) ;
return ` build_logs/ios-build- ${ date } - ${ time } .log ` ;
} ;
// Create logger function
const createLogger = ( logFile ) => {
return ( message ) => {
const timestamp = new Date ( ) . toISOString ( ) ;
const logMessage = ` [ ${ timestamp } ] ${ message } \n ` ;
console . log ( message ) ;
appendFileSync ( logFile , logMessage ) ;
} ;
} ;
// Check for iOS simulator
const checkSimulator = async ( log ) => {
log ( '🔍 Checking for iOS simulator...' ) ;
const simulators = execSync ( 'xcrun simctl list devices available' ) . toString ( ) ;
const bootedDevices = simulators . split ( '\n' )
. filter ( line => line . includes ( 'Booted' ) )
. map ( line => line . match ( /(.*?)\s+\((.*?)\)/ ) ? . [ 1 ] )
. filter ( Boolean ) ;
if ( bootedDevices . length === 0 ) {
throw new Error ( 'No iOS simulator running. Please start a simulator first.' ) ;
}
log ( ` 📱 Found ${ bootedDevices . length } simulator(s): ${ bootedDevices . join ( ', ' ) } ` ) ;
return bootedDevices ;
} ;
// Verify Xcode installation
const verifyXcodeInstallation = ( log ) => {
log ( '🔍 Checking Xcode installation...' ) ;
try {
execSync ( 'xcode-select -p' ) ;
log ( '✅ Xcode command line tools found' ) ;
} catch ( error ) {
throw new Error ( 'Xcode command line tools not found. Please install Xcode first.' ) ;
}
} ;
// Generate test data using generate_data.ts
const generateTestData = async ( log ) => {
log ( '🔄 Generating test data...' ) ;
try {
execSync ( 'npx ts-node test-scripts/generate_data.ts' , { stdio : 'inherit' } ) ;
log ( '✅ Test data generated successfully' ) ;
} catch ( error ) {
throw new Error ( ` Failed to generate test data: ${ error . message } ` ) ;
}
} ;
// Build web assets
const buildWebAssets = async ( log ) => {
log ( '🌐 Building web assets...' ) ;
execSync ( 'rm -rf dist' , { stdio : 'inherit' } ) ;
execSync ( 'npm run build:web' , { stdio : 'inherit' } ) ;
execSync ( 'npm run build:capacitor' , { stdio : 'inherit' } ) ;
log ( '✅ Web assets built successfully' ) ;
} ;
// Configure iOS project
const configureIosProject = async ( log ) => {
log ( '📱 Syncing Capacitor project...' ) ;
execSync ( 'npx cap sync ios' , { stdio : 'inherit' } ) ;
log ( '✅ Capacitor sync completed' ) ;
log ( '⚙️ Installing CocoaPods dependencies...' ) ;
execSync ( 'cd ios/App && pod install' , { stdio : 'inherit' } ) ;
log ( '✅ CocoaPods installation completed' ) ;
} ;
// Build and test iOS project
const buildAndTestIos = async ( log ) => {
log ( '🏗️ Building iOS project...' ) ;
execSync ( 'cd ios/App && xcodebuild clean -workspace App.xcworkspace -scheme App' , { stdio : 'inherit' } ) ;
log ( '✅ Xcode clean completed' ) ;
execSync ( 'cd ios/App && xcodebuild build-for-testing -workspace App.xcworkspace -scheme App -destination "platform=iOS Simulator,name=iPhone 14"' , { stdio : 'inherit' } ) ;
log ( '✅ Xcode build completed' ) ;
log ( '🧪 Running iOS tests...' ) ;
execSync ( 'cd ios/App && xcodebuild test-without-building -workspace App.xcworkspace -scheme App -destination "platform=iOS Simulator,name=iPhone 14"' , { stdio : 'inherit' } ) ;
log ( '✅ iOS tests completed' ) ;
} ;
// Run the app
const runIosApp = async ( log ) => {
log ( '📱 Running app in simulator...' ) ;
execSync ( 'npx cap run ios' , { stdio : 'inherit' } ) ;
log ( '✅ App launched successfully' ) ;
} ;
// Run deeplink tests
const runDeeplinkTests = async ( log ) => {
log ( '🔗 Starting deeplink tests...' ) ;
try {
// Load test data
const testEnv = JSON . parse ( readFileSync ( '.generated/test-env.json' , 'utf8' ) ) ;
const claimDetails = JSON . parse ( readFileSync ( '.generated/claim_details.json' , 'utf8' ) ) ;
const contacts = JSON . parse ( readFileSync ( '.generated/contacts.json' , 'utf8' ) ) ;
// Test URLs
const deeplinkTests = [
{
url : ` timesafari://claim/ ${ claimDetails . claim_id } ` ,
description : 'Claim view'
} ,
{
url : ` timesafari://claim-cert/ ${ claimDetails . claim_id } ` ,
description : 'Claim certificate view'
} ,
{
url : ` timesafari://claim-add-raw/ ${ claimDetails . claim_id } ` ,
description : 'Raw claim addition'
} ,
{
url : 'timesafari://did/test' ,
description : 'DID view with test identifier'
} ,
{
url : ` timesafari://did/ ${ testEnv . CONTACT1_DID } ` ,
description : 'DID view with contact DID'
} ,
{
url : ` timesafari://contact-edit/ ${ testEnv . CONTACT1_DID } ` ,
description : 'Contact editing'
} ,
{
url : ` timesafari://contacts/import?contacts= ${ encodeURIComponent ( JSON . stringify ( contacts ) ) } ` ,
description : 'Contacts import'
}
] ;
// Execute each test
for ( const test of deeplinkTests ) {
log ( ` \n 🔗 Testing deeplink: ${ test . description } ` ) ;
log ( ` URL: ${ test . url } ` ) ;
execSync ( ` xcrun simctl openurl booted " ${ test . url } " ` ) ;
log ( ` ✅ Successfully executed: ${ test . description } ` ) ;
// Wait between tests
await new Promise ( resolve => setTimeout ( resolve , 5000 ) ) ;
}
log ( '✅ All deeplink tests completed successfully' ) ;
} catch ( error ) {
log ( '❌ Deeplink tests failed' ) ;
throw error ;
}
} ;
/ * *
* Runs the complete iOS test suite including build and testing
@ -58,33 +219,35 @@ const { join } = require('path');
* } ) ;
* /
async function runIosTests ( ) {
// Create build_logs directory if it doesn't exist
if ( ! existsSync ( 'build_logs' ) ) {
mkdirSync ( 'build_logs' ) ;
}
const logFile = getLogFileName ( ) ;
const log = createLogger ( logFile ) ;
try {
// Sync Capacitor project with latest web build
// This ensures the iOS project has the latest web assets
execSync ( 'npx cap sync ios' , {
stdio : 'inherit' ,
// Inherit stdio to show real-time output
} ) ;
// Build and run tests using xcodebuild
execSync (
'cd ios && xcodebuild test ' +
'-workspace App/App.xcworkspace ' + // Workspace containing the project
'-scheme App ' + // The scheme to build and test
'-destination "platform=iOS Simulator,name=iPhone 14"' , // Target simulator
{
stdio : 'inherit' ,
// test: Builds and runs tests
// -workspace: Specifies the Xcode workspace
// -scheme: Specifies the scheme to test
// -destination: Specifies the target simulator
}
) ;
log ( '🚀 Starting iOS build and test process...' ) ;
// Generate test data first
await generateTestData ( log ) ;
await checkSimulator ( log ) ;
verifyXcodeInstallation ( log ) ;
await buildWebAssets ( log ) ;
await configureIosProject ( log ) ;
await buildAndTestIos ( log ) ;
await runIosApp ( log ) ;
// Run deeplink tests after app is installed
await runDeeplinkTests ( log ) ;
console . log ( '✅ iOS tests completed successfully' ) ;
log ( '🎉 iOS build and test process completed successfully' ) ;
log ( ` 📝 Full build log available at: ${ logFile } ` ) ;
} catch ( error ) {
// Log the error and exit with failure code
console . error ( '❌ iOS tests failed:' , error ) ;
log ( ` ❌ iOS tests failed: ${ error . message } ` ) ;
log ( ` 📝 Check build log for details: ${ logFile } ` ) ;
process . exit ( 1 ) ;
}
}