text: 'use strict';
  
  Object.defineProperty(exports, '__esModule', {
    value: true
  });
  exports.default = void 0;
  
  var _state = require('./state');
  
  var _types = require('./types');
  
  var _utils = require('./utils');
  
  /**
   * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   */
  const run = async () => {
    const {rootDescribeBlock} = (0, _state.getState)();
    await (0, _state.dispatch)({
      name: 'run_start'
    });
    await _runTestsForDescribeBlock(rootDescribeBlock);
    await (0, _state.dispatch)({
      name: 'run_finish'
    });
    return (0, _utils.makeRunResult)(
      (0, _state.getState)().rootDescribeBlock,
      (0, _state.getState)().unhandledErrors
    );
  };
  
  const _runTestsForDescribeBlock = async describeBlock => {
    await (0, _state.dispatch)({
      describeBlock,
      name: 'run_describe_start'
    });
    const {beforeAll, afterAll} = (0, _utils.getAllHooksForDescribe)(
      describeBlock
    );
  
    for (const hook of beforeAll) {
      await _callCircusHook({
        describeBlock,
        hook
      });
    } // Tests that fail and are retried we run after other tests
  
    const retryTimes = parseInt(global[_types.RETRY_TIMES], 10) || 0;
    const deferredRetryTests = [];
  
    for (const child of describeBlock.children) {
      switch (child.type) {
        case 'describeBlock': {
          await _runTestsForDescribeBlock(child);
          break;
        }
  
        case 'test': {
          const hasErrorsBeforeTestRun = child.errors.length > 0;
          await _runTest(child);
  
          if (
            hasErrorsBeforeTestRun === false &&
            retryTimes > 0 &&
            child.errors.length > 0
          ) {
            deferredRetryTests.push(child);
          }
  
          break;
        }
      }
    } // Re-run failed tests n-times if configured
  
    for (const test of deferredRetryTests) {
      let numRetriesAvailable = retryTimes;
  
      while (numRetriesAvailable > 0 && test.errors.length > 0) {
        // Clear errors so retries occur
        await (0, _state.dispatch)({
          name: 'test_retry',
          test
        });
        await _runTest(test);
        numRetriesAvailable--;
      }
    }
  
    for (const hook of afterAll) {
      await _callCircusHook({
        describeBlock,
        hook
      });
    }
  
    await (0, _state.dispatch)({
      describeBlock,
      name: 'run_describe_finish'
    });
  };
  
  const _runTest = async test => {
    await (0, _state.dispatch)({
      name: 'test_start',
      test
    });
    const testContext = Object.create(null);
    const {hasFocusedTests, testNamePattern} = (0, _state.getState)();
    const isSkipped =
      test.mode === 'skip' ||
      (hasFocusedTests && test.mode !== 'only') ||
      (testNamePattern && !testNamePattern.test((0, _utils.getTestID)(test)));
  
    if (isSkipped) {
      await (0, _state.dispatch)({
        name: 'test_skip',
        test
      });
      return;
    }
  
    if (test.mode === 'todo') {
      await (0, _state.dispatch)({
        name: 'test_todo',
        test
      });
      return;
    }
  
    const {afterEach, beforeEach} = (0, _utils.getEachHooksForTest)(test);
  
    for (const hook of beforeEach) {
      if (test.errors.length) {
        // If any of the before hooks failed already, we don't run any
        // hooks after that.
        break;
      }
  
      await _callCircusHook({
        hook,
        test,
        testContext
      });
    }
  
    await _callCircusTest(test, testContext);
  
    for (const hook of afterEach) {
      await _callCircusHook({
        hook,
        test,
        testContext
      });
    } // `afterAll` hooks should not affect test status (pass or fail), because if
    // we had a global `afterAll` hook it would block all existing tests until
    // this hook is executed. So we dispatch `test_done` right away.
  
    await (0, _state.dispatch)({
      name: 'test_done',
      test
    });
  };
  
  const _callCircusHook = async ({hook, test, describeBlock, testContext}) => {
    await (0, _state.dispatch)({
      hook,
      name: 'hook_start'
    });
    const timeout = hook.timeout || (0, _state.getState)().testTimeout;
  
    try {
      await (0, _utils.callAsyncCircusFn)(hook, testContext, {
        isHook: true,
        timeout
      });
      await (0, _state.dispatch)({
        describeBlock,
        hook,
        name: 'hook_success',
        test
      });
    } catch (error) {
      await (0, _state.dispatch)({
        describeBlock,
        error,
        hook,
        name: 'hook_failure',
        test
      });
    }
  };
  
  const _callCircusTest = async (test, testContext) => {
    await (0, _state.dispatch)({
      name: 'test_fn_start',
      test
    });
    const timeout = test.timeout || (0, _state.getState)().testTimeout;
    (0, _utils.invariant)(
      test.fn,
      `Tests with no 'fn' should have 'mode' set to 'skipped'`
    );
  
    if (test.errors.length) {
      return; // We don't run the test if there's already an error in before hooks.
    }
  
    try {
      await (0, _utils.callAsyncCircusFn)(test, testContext, {
        isHook: false,
        timeout
      });
      await (0, _state.dispatch)({
        name: 'test_fn_success',
        test
      });
    } catch (error) {
      await (0, _state.dispatch)({
        error,
        name: 'test_fn_failure',
        test
      });
    }
  };
  
  var _default = run;
  exports.default = _default;
  