1eeffdb10STomasz Sapetaimport JUnitReportBuilder from 'junit-report-builder'; 2eeffdb10STomasz Sapetaimport path from 'path'; 3eeffdb10STomasz Sapeta 4eeffdb10STomasz Sapetaimport * as IOSSimulator from './IOSSimulator'; 5eeffdb10STomasz Sapetaimport * as Log from './Log'; 6eeffdb10STomasz Sapeta 7eeffdb10STomasz Sapetaconst TEST_SUITE_BUNDLE_ID = 'io.expo.testsuite'; 8eeffdb10STomasz Sapetaconst TEST_SUITE_END_SENTINEL = '[TEST-SUITE-END]'; 9eeffdb10STomasz Sapeta 10eeffdb10STomasz Sapeta// Keep this type in sync with test-suite 11eeffdb10STomasz Sapetatype TestSuiteResults = { 12eeffdb10STomasz Sapeta failed: number; 13eeffdb10STomasz Sapeta failures: string; 14eeffdb10STomasz Sapeta}; 15eeffdb10STomasz Sapeta 16eeffdb10STomasz Sapetaexport async function runTestSuiteOnIOSSimulatorAsync(simulatorId, archivePath, reportPath) { 17eeffdb10STomasz Sapeta Log.collapsed(`Running test-suite on the iOS simulator`); 18eeffdb10STomasz Sapeta if (!simulatorId) { 19eeffdb10STomasz Sapeta console.log(`Starting a new simulator`); 20eeffdb10STomasz Sapeta await IOSSimulator.startSimulatorAsync(); 21eeffdb10STomasz Sapeta simulatorId = 'booted'; 22eeffdb10STomasz Sapeta } 23eeffdb10STomasz Sapeta 24eeffdb10STomasz Sapeta console.log(`Installing test-suite on the simulator`); 25eeffdb10STomasz Sapeta await IOSSimulator.installSimulatorAppAsync(simulatorId, path.resolve(archivePath)); 26eeffdb10STomasz Sapeta console.log(`Streaming logs from the simulator`); 27*a272999eSBartosz Kaszubowski const resultsPromise = _streamSimulatorLogsAsync(simulatorId); 28eeffdb10STomasz Sapeta console.log(`Launching the test-suite app and waiting for tests to complete`); 29eeffdb10STomasz Sapeta await IOSSimulator.launchSimulatorAppAsync(simulatorId, TEST_SUITE_BUNDLE_ID); 30eeffdb10STomasz Sapeta 31*a272999eSBartosz Kaszubowski const results = await resultsPromise; 32eeffdb10STomasz Sapeta if (results.failed === 0) { 33eeffdb10STomasz Sapeta console.log(` All tests passed`); 34eeffdb10STomasz Sapeta } else { 35eeffdb10STomasz Sapeta console.error(` ${results.failed} ${results.failed === 1 ? 'test' : 'tests'} failed`); 36eeffdb10STomasz Sapeta } 37eeffdb10STomasz Sapeta 38eeffdb10STomasz Sapeta if (reportPath) { 39eeffdb10STomasz Sapeta _writeJUnitReport(results, reportPath); 40eeffdb10STomasz Sapeta console.log(`Saved test results to ${reportPath}`); 41eeffdb10STomasz Sapeta } 42eeffdb10STomasz Sapeta 43eeffdb10STomasz Sapeta return results; 44eeffdb10STomasz Sapeta} 45eeffdb10STomasz Sapeta 46eeffdb10STomasz Sapetafunction _streamSimulatorLogsAsync(simulatorId: string): Promise<TestSuiteResults> { 47eeffdb10STomasz Sapeta return new Promise((resolve, reject) => { 48*a272999eSBartosz Kaszubowski const logProcess = IOSSimulator.getSimulatorLogProcess( 49eeffdb10STomasz Sapeta simulatorId, 50eeffdb10STomasz Sapeta '(subsystem == "host.exp.Exponent") && (category == "test")' 51eeffdb10STomasz Sapeta ); 52*a272999eSBartosz Kaszubowski const logStream = new IOSSimulator.IOSLogStream(); 53eeffdb10STomasz Sapeta logProcess.stdout.pipe(logStream); 54eeffdb10STomasz Sapeta 55eeffdb10STomasz Sapeta logStream.on('data', (entry) => { 56eeffdb10STomasz Sapeta // Show the log messages in the CI log 57eeffdb10STomasz Sapeta console.log(entry.eventMessage); 58eeffdb10STomasz Sapeta 59eeffdb10STomasz Sapeta if (!entry.eventMessage.startsWith(TEST_SUITE_END_SENTINEL)) { 60eeffdb10STomasz Sapeta return; 61eeffdb10STomasz Sapeta } 62eeffdb10STomasz Sapeta 63eeffdb10STomasz Sapeta try { 64eeffdb10STomasz Sapeta logStream.removeAllListeners('data'); 65eeffdb10STomasz Sapeta 66*a272999eSBartosz Kaszubowski const resultsJson = entry.eventMessage.substring(TEST_SUITE_END_SENTINEL.length).trim(); 67*a272999eSBartosz Kaszubowski const results = JSON.parse(resultsJson); 68eeffdb10STomasz Sapeta resolve(results); 69eeffdb10STomasz Sapeta } catch (e) { 70eeffdb10STomasz Sapeta reject(e); 71eeffdb10STomasz Sapeta } finally { 72eeffdb10STomasz Sapeta console.log(`Terminating simulator log stream`); 73eeffdb10STomasz Sapeta logProcess.kill('SIGTERM'); 74eeffdb10STomasz Sapeta } 75eeffdb10STomasz Sapeta }); 76eeffdb10STomasz Sapeta }); 77eeffdb10STomasz Sapeta} 78eeffdb10STomasz Sapeta 79eeffdb10STomasz Sapetafunction _writeJUnitReport(results: TestSuiteResults, reportPath: string): void { 80*a272999eSBartosz Kaszubowski const builder = JUnitReportBuilder.newBuilder(); 81eeffdb10STomasz Sapeta // let suite = builder.testSuite().name('Test Suite'); 82eeffdb10STomasz Sapeta 83eeffdb10STomasz Sapeta // TODO: parse the results 84eeffdb10STomasz Sapeta 85eeffdb10STomasz Sapeta builder.writeTo(reportPath); 86eeffdb10STomasz Sapeta} 87