async run()

in lib/runner.ts [314:426]


  async run(): Promise<number> {
    let testPassed: boolean;
    let plugins = this.plugins_ = new Plugins(this.config_);
    let pluginPostTestPromises: any;
    let browser_: any;
    let results: any;

    if (this.config_.framework !== 'explorer' && !this.config_.specs.length) {
      throw new Error('Spec patterns did not match any files.');
    }

    if (this.config_.webDriverLogDir || this.config_.highlightDelay) {
      this.config_.useBlockingProxy = true;
    }

    // 1) Setup environment
    // noinspection JSValidateTypes
    await this.driverprovider_.setupEnv();

    // 2) Create a browser and setup globals
    browser_ = await this.createBrowser(plugins);
    this.setupGlobals_(browser_);
    try {
      const session = await browser_.getSession();
      logger.debug(
          'WebDriver session successfully started with capabilities ' +
          util.inspect(session.getCapabilities()));
    } catch (err) {
      logger.error('Unable to start a WebDriver session.');
      throw err;
    }

    // 3) Setup plugins
    await plugins.setup();

    // 4) Execute test cases
    // Do the framework setup here so that jasmine and mocha globals are
    // available to the onPrepare function.
    let frameworkPath = '';
    if (this.config_.framework === 'jasmine' || this.config_.framework === 'jasmine2') {
      frameworkPath = './frameworks/jasmine.js';
    } else if (this.config_.framework === 'mocha') {
      frameworkPath = './frameworks/mocha.js';
    } else if (this.config_.framework === 'debugprint') {
      // Private framework. Do not use.
      frameworkPath = './frameworks/debugprint.js';
    } else if (this.config_.framework === 'explorer') {
      // Private framework. Do not use.
      frameworkPath = './frameworks/explorer.js';
    } else if (this.config_.framework === 'custom') {
      if (!this.config_.frameworkPath) {
        throw new Error(
            'When config.framework is custom, ' +
            'config.frameworkPath is required.');
      }
      frameworkPath = this.config_.frameworkPath;
    } else {
      throw new Error(
          'config.framework (' + this.config_.framework + ') is not a valid framework.');
    }

    if (this.config_.restartBrowserBetweenTests) {
      // TODO(sjelin): replace with warnings once `afterEach` support is required
      let restartDriver = async () => {
        if (!this.frameworkUsesAfterEach) {
          this.restartPromise = await browser_.restart();
        }
      };
      this.on('testPass', restartDriver);
      this.on('testFail', restartDriver);
    }

    // We need to save these promises to make sure they're run, but we
    // don't
    // want to delay starting the next test (because we can't, it's just
    // an event emitter).
    pluginPostTestPromises = [];

    this.on('testPass', (testInfo: any) => {
      pluginPostTestPromises.push(plugins.postTest(true, testInfo));
    });
    this.on('testFail', (testInfo: any) => {
      pluginPostTestPromises.push(plugins.postTest(false, testInfo));
    });
    logger.debug('Running with spec files ' + this.config_.specs);
    let testResults = await require(frameworkPath).run(this, this.config_.specs);

    // 5) Wait for postTest plugins to finish
    results = testResults;
    await Promise.all(pluginPostTestPromises);

    // 6) Teardown plugins
    await plugins.teardown();

    // 7) Teardown
    results = joinTestLogs(results, plugins.getResults());
    this.emit('testsDone', results);
    testPassed = results.failedCount === 0;
    if (this.driverprovider_.updateJob) {
      await this.driverprovider_.updateJob({'passed': testPassed});
    }
    await this.driverprovider_.teardownEnv();

    // 8) Let plugins do final cleanup
    await plugins.postResults();

    // 9) Exit process
    const exitCode = testPassed ? 0 : 1;

    await this.shutdown_();

    return this.exit_(exitCode);
  }