"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Test = exports.Suite = exports.Spec = void 0;

/**
 * Copyright Microsoft Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
class Base {
  constructor(title) {
    this.title = void 0;
    this.file = '';
    this.line = 0;
    this.column = 0;
    this.parent = void 0;
    this._only = false;
    this._requireFile = '';
    this.title = title;
  }

  titlePath() {
    if (!this.parent) return [];
    if (!this.title) return this.parent.titlePath();
    return [...this.parent.titlePath(), this.title];
  }

  fullTitle() {
    return this.titlePath().join(' ');
  }

}

class Spec extends Base {
  constructor(title, fn, ordinalInFile, testType) {
    super(title);
    this.suite = void 0;
    this.fn = void 0;
    this.tests = [];
    this._ordinalInFile = void 0;
    this._testType = void 0;
    this.fn = fn;
    this._ordinalInFile = ordinalInFile;
    this._testType = testType;
  }

  ok() {
    return !this.tests.find(r => !r.ok());
  }

  _testFullTitle(projectName) {
    return (projectName ? `[${projectName}] ` : '') + this.fullTitle();
  }

}

exports.Spec = Spec;

class Suite extends Base {
  constructor(...args) {
    super(...args);
    this.suites = [];
    this.specs = [];
    this._fixtureOverrides = {};
    this._entries = [];
    this._hooks = [];
    this._timeout = void 0;
    this._annotations = [];
    this._modifiers = [];
  }

  _addSpec(spec) {
    spec.parent = this;
    spec.suite = this;
    this.specs.push(spec);

    this._entries.push(spec);
  }

  _addSuite(suite) {
    suite.parent = this;
    this.suites.push(suite);

    this._entries.push(suite);
  }

  findTest(fn) {
    for (const entry of this._entries) {
      if (entry instanceof Suite) {
        if (entry.findTest(fn)) return true;
      } else {
        for (const test of entry.tests) {
          if (fn(test)) return true;
        }
      }
    }

    return false;
  }

  findSpec(fn) {
    for (const entry of this._entries) {
      if (entry instanceof Suite) {
        if (entry.findSpec(fn)) return true;
      } else {
        if (fn(entry)) return true;
      }
    }

    return false;
  }

  findSuite(fn) {
    if (fn(this)) return true;

    for (const suite of this.suites) {
      if (suite.findSuite(fn)) return true;
    }

    return false;
  }

  totalTestCount() {
    let total = 0;

    for (const suite of this.suites) total += suite.totalTestCount();

    for (const spec of this.specs) total += spec.tests.length;

    return total;
  }

  _allSpecs() {
    const result = [];
    this.findSpec(test => {
      result.push(test);
    });
    return result;
  }

  _getOnlyItems() {
    const items = [];
    if (this._only) items.push(this);

    for (const suite of this.suites) items.push(...suite._getOnlyItems());

    items.push(...this.specs.filter(spec => spec._only));
    return items;
  }

  _buildFixtureOverrides() {
    return this.parent ? { ...this.parent._buildFixtureOverrides(),
      ...this._fixtureOverrides
    } : this._fixtureOverrides;
  }

}

exports.Suite = Suite;

class Test {
  constructor(spec) {
    this.spec = void 0;
    this.results = [];
    this.skipped = false;
    this.expectedStatus = 'passed';
    this.timeout = 0;
    this.annotations = [];
    this.projectName = '';
    this.retries = 0;
    this._id = '';
    this._repeatEachIndex = 0;
    this._projectIndex = 0;
    this._workerHash = '';
    this.spec = spec;
  }

  status() {
    if (this.skipped) return 'skipped'; // List mode bail out.

    if (!this.results.length) return 'skipped';
    if (this.results.length === 1 && this.expectedStatus === this.results[0].status) return 'expected';
    let hasPassedResults = false;

    for (const result of this.results) {
      // Missing status is Ok when running in shards mode.
      if (!result.status) return 'skipped';
      if (result.status === this.expectedStatus) hasPassedResults = true;
    }

    if (hasPassedResults) return 'flaky';
    return 'unexpected';
  }

  ok() {
    const status = this.status();
    return status === 'expected' || status === 'flaky' || status === 'skipped';
  }

  fullTitle() {
    return this.spec._testFullTitle(this.projectName);
  }

  _appendTestResult() {
    const result = {
      retry: this.results.length,
      workerIndex: 0,
      duration: 0,
      stdout: [],
      stderr: []
    };
    this.results.push(result);
    return result;
  }

}

exports.Test = Test;
//# sourceMappingURL=test.js.map