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