'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});
exports.default = void 0;
function _chalk() {
  const data = _interopRequireDefault(require('chalk'));
  _chalk = function () {
    return data;
  };
  return data;
}
function _stripAnsi() {
  const data = _interopRequireDefault(require('strip-ansi'));
  _stripAnsi = function () {
    return data;
  };
  return data;
}
function _jestMessageUtil() {
  const data = require('jest-message-util');
  _jestMessageUtil = function () {
    return data;
  };
  return data;
}
function _jestUtil() {
  const data = require('jest-util');
  _jestUtil = function () {
    return data;
  };
  return data;
}
var _BaseReporter = _interopRequireDefault(require('./BaseReporter'));
function _interopRequireDefault(obj) {
  return obj && obj.__esModule ? obj : {default: obj};
}
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const titleSeparator = ' \u203A ';
const ICONS = _jestUtil().specialChars.ICONS;
class GitHubActionsReporter extends _BaseReporter.default {
  static filename = __filename;
  options;
  constructor(
    _globalConfig,
    reporterOptions = {
      silent: true
    }
  ) {
    super();
    this.options = {
      silent:
        typeof reporterOptions.silent === 'boolean'
          ? reporterOptions.silent
          : true
    };
  }
  onTestResult(test, testResult, aggregatedResults) {
    this.generateAnnotations(test, testResult);
    if (!this.options.silent) {
      this.printFullResult(test.context, testResult);
    }
    if (this.isLastTestSuite(aggregatedResults)) {
      this.printFailedTestLogs(test, aggregatedResults);
    }
  }
  generateAnnotations({context}, {testResults}) {
    testResults.forEach(result => {
      const title = [...result.ancestorTitles, result.title].join(
        titleSeparator
      );
      result.retryReasons?.forEach((retryReason, index) => {
        this.#createAnnotation({
          ...this.#getMessageDetails(retryReason, context.config),
          title: `RETRY ${index + 1}: ${title}`,
          type: 'warning'
        });
      });
      result.failureMessages.forEach(failureMessage => {
        this.#createAnnotation({
          ...this.#getMessageDetails(failureMessage, context.config),
          title,
          type: 'error'
        });
      });
    });
  }
  #getMessageDetails(failureMessage, config) {
    const {message, stack} = (0, _jestMessageUtil().separateMessageFromStack)(
      failureMessage
    );
    const stackLines = (0, _jestMessageUtil().getStackTraceLines)(stack);
    const topFrame = (0, _jestMessageUtil().getTopFrame)(stackLines);
    const normalizedStackLines = stackLines.map(line =>
      (0, _jestMessageUtil().formatPath)(line, config)
    );
    const messageText = [message, ...normalizedStackLines].join('\n');
    return {
      file: topFrame?.file,
      line: topFrame?.line,
      message: messageText
    };
  }
  #createAnnotation({file, line, message, title, type}) {
    message = (0, _stripAnsi().default)(
      // copied from: https://github.com/actions/toolkit/blob/main/packages/core/src/command.ts
      message.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A')
    );
    this.log(
      `\n::${type} file=${file},line=${line},title=${title}::${message}`
    );
  }
  isLastTestSuite(results) {
    const passedTestSuites = results.numPassedTestSuites;
    const failedTestSuites = results.numFailedTestSuites;
    const totalTestSuites = results.numTotalTestSuites;
    const computedTotal = passedTestSuites + failedTestSuites;
    if (computedTotal < totalTestSuites) {
      return false;
    } else if (computedTotal === totalTestSuites) {
      return true;
    } else {
      throw new Error(
        `Sum(${computedTotal}) of passed (${passedTestSuites}) and failed (${failedTestSuites}) test suites is greater than the total number of test suites (${totalTestSuites}). Please report the bug at https://github.com/jestjs/jest/issues`
      );
    }
  }
  printFullResult(context, results) {
    const rootDir = context.config.rootDir;
    let testDir = results.testFilePath.replace(rootDir, '');
    testDir = testDir.slice(1, testDir.length);
    const resultTree = this.getResultTree(
      results.testResults,
      testDir,
      results.perfStats
    );
    this.printResultTree(resultTree);
  }
  arrayEqual(a1, a2) {
    if (a1.length !== a2.length) {
      return false;
    }
    for (let index = 0; index < a1.length; index++) {
      const element = a1[index];
      if (element !== a2[index]) {
        return false;
      }
    }
    return true;
  }
  arrayChild(a1, a2) {
    if (a1.length - a2.length !== 1) {
      return false;
    }
    for (let index = 0; index < a2.length; index++) {
      const element = a2[index];
      if (element !== a1[index]) {
        return false;
      }
    }
    return true;
  }
  getResultTree(suiteResult, testPath, suitePerf) {
    const root = {
      children: [],
      name: testPath,
      passed: true,
      performanceInfo: suitePerf
    };
    const branches = [];
    suiteResult.forEach(element => {
      if (element.ancestorTitles.length === 0) {
        if (element.status === 'failed') {
          root.passed = false;
        }
        const duration = element.duration || 1;
        root.children.push({
          children: [],
          duration,
          name: element.title,
          status: element.status
        });
      } else {
        let alreadyInserted = false;
        for (let index = 0; index < branches.length; index++) {
          if (
            this.arrayEqual(branches[index], element.ancestorTitles.slice(0, 1))
          ) {
            alreadyInserted = true;
            break;
          }
        }
        if (!alreadyInserted) {
          branches.push(element.ancestorTitles.slice(0, 1));
        }
      }
    });
    branches.forEach(element => {
      const newChild = this.getResultChildren(suiteResult, element);
      if (!newChild.passed) {
        root.passed = false;
      }
      root.children.push(newChild);
    });
    return root;
  }
  getResultChildren(suiteResult, ancestors) {
    const node = {
      children: [],
      name: ancestors[ancestors.length - 1],
      passed: true
    };
    const branches = [];
    suiteResult.forEach(element => {
      let duration = element.duration;
      if (!duration || isNaN(duration)) {
        duration = 1;
      }
      if (this.arrayEqual(element.ancestorTitles, ancestors)) {
        if (element.status === 'failed') {
          node.passed = false;
        }
        node.children.push({
          children: [],
          duration,
          name: element.title,
          status: element.status
        });
      } else if (
        this.arrayChild(
          element.ancestorTitles.slice(0, ancestors.length + 1),
          ancestors
        )
      ) {
        let alreadyInserted = false;
        for (let index = 0; index < branches.length; index++) {
          if (
            this.arrayEqual(
              branches[index],
              element.ancestorTitles.slice(0, ancestors.length + 1)
            )
          ) {
            alreadyInserted = true;
            break;
          }
        }
        if (!alreadyInserted) {
          branches.push(element.ancestorTitles.slice(0, ancestors.length + 1));
        }
      }
    });
    branches.forEach(element => {
      const newChild = this.getResultChildren(suiteResult, element);
      if (!newChild.passed) {
        node.passed = false;
      }
      node.children.push(newChild);
    });
    return node;
  }
  printResultTree(resultTree) {
    let perfMs;
    if (resultTree.performanceInfo.slow) {
      perfMs = ` (${_chalk().default.red.inverse(
        `${resultTree.performanceInfo.runtime} ms`
      )})`;
    } else {
      perfMs = ` (${resultTree.performanceInfo.runtime} ms)`;
    }
    if (resultTree.passed) {
      this.startGroup(
        `${_chalk().default.bold.green.inverse('PASS')} ${
          resultTree.name
        }${perfMs}`
      );
      resultTree.children.forEach(child => {
        this.recursivePrintResultTree(child, true, 1);
      });
      this.endGroup();
    } else {
      this.log(
        `  ${_chalk().default.bold.red.inverse('FAIL')} ${
          resultTree.name
        }${perfMs}`
      );
      resultTree.children.forEach(child => {
        this.recursivePrintResultTree(child, false, 1);
      });
    }
  }
  recursivePrintResultTree(resultTree, alreadyGrouped, depth) {
    if (resultTree.children.length === 0) {
      if (!('duration' in resultTree)) {
        throw new Error('Expected a leaf. Got a node.');
      }
      let numberSpaces = depth;
      if (!alreadyGrouped) {
        numberSpaces++;
      }
      const spaces = '  '.repeat(numberSpaces);
      let resultSymbol;
      switch (resultTree.status) {
        case 'passed':
          resultSymbol = _chalk().default.green(ICONS.success);
          break;
        case 'failed':
          resultSymbol = _chalk().default.red(ICONS.failed);
          break;
        case 'todo':
          resultSymbol = _chalk().default.magenta(ICONS.todo);
          break;
        case 'pending':
        case 'skipped':
          resultSymbol = _chalk().default.yellow(ICONS.pending);
          break;
      }
      this.log(
        `${spaces + resultSymbol} ${resultTree.name} (${
          resultTree.duration
        } ms)`
      );
    } else {
      if (!('passed' in resultTree)) {
        throw new Error('Expected a node. Got a leaf');
      }
      if (resultTree.passed) {
        if (alreadyGrouped) {
          this.log('  '.repeat(depth) + resultTree.name);
          resultTree.children.forEach(child => {
            this.recursivePrintResultTree(child, true, depth + 1);
          });
        } else {
          this.startGroup('  '.repeat(depth) + resultTree.name);
          resultTree.children.forEach(child => {
            this.recursivePrintResultTree(child, true, depth + 1);
          });
          this.endGroup();
        }
      } else {
        this.log('  '.repeat(depth + 1) + resultTree.name);
        resultTree.children.forEach(child => {
          this.recursivePrintResultTree(child, false, depth + 1);
        });
      }
    }
  }
  printFailedTestLogs(context, testResults) {
    const rootDir = context.context.config.rootDir;
    const results = testResults.testResults;
    let written = false;
    results.forEach(result => {
      let testDir = result.testFilePath;
      testDir = testDir.replace(rootDir, '');
      testDir = testDir.slice(1, testDir.length);
      if (result.failureMessage) {
        if (!written) {
          this.log('');
          written = true;
        }
        this.startGroup(`Errors thrown in ${testDir}`);
        this.log(result.failureMessage);
        this.endGroup();
      }
    });
    return written;
  }
  startGroup(title) {
    this.log(`::group::${title}`);
  }
  endGroup() {
    this.log('::endgroup::');
  }
}
exports.default = GitHubActionsReporter;
