"use strict"
var __createBinding =
  (this && this.__createBinding) ||
  (Object.create
    ? function (o, m, k, k2) {
        if (k2 === undefined) k2 = k
        Object.defineProperty(o, k2, {
          enumerable: true,
          get: function () {
            return m[k]
          }
        })
      }
    : function (o, m, k, k2) {
        if (k2 === undefined) k2 = k
        o[k2] = m[k]
      })
var __setModuleDefault =
  (this && this.__setModuleDefault) ||
  (Object.create
    ? function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v })
      }
    : function (o, v) {
        o["default"] = v
      })
var __importStar =
  (this && this.__importStar) ||
  function (mod) {
    if (mod && mod.__esModule) return mod
    var result = {}
    if (mod != null)
      for (var k in mod)
        if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
          __createBinding(result, mod, k)
    __setModuleDefault(result, mod)
    return result
  }
var _a, _b
Object.defineProperty(exports, "__esModule", { value: true })
exports.foldM =
  exports.forEachExec =
  exports.provideLayer =
  exports.annotated =
  exports.annotate =
  exports.transform =
  exports.test =
  exports.suite =
  exports.Spec =
  exports.SpecTypeId =
  exports.TestCase =
  exports.SuiteCase =
  exports.concreteSpecCase =
  exports.SpecCase =
  exports.SpecCaseTypeId =
    void 0
const tracing_1 = __importStar(require("../../Tracing"))
const tracing_2 = __importStar(require("../../Tracing"))
const fileName_1 = "(@effect-ts/system): _src/Testing/Spec/index.ts"
const Chunk = __importStar(require("../../Collections/Immutable/Chunk"))
const Tuple = __importStar(require("../../Collections/Immutable/Tuple"))
const T = __importStar(require("../../Effect"))
const Function_1 = require("../../Function")
const M = __importStar(require("../../Managed"))
const O = __importStar(require("../../Option"))
const Annotations = __importStar(require("../Annotations"))
const TAM = __importStar(require("../TestAnnotationMap"))
exports.SpecCaseTypeId = Symbol.for("@effect-ts/system/Testing/SpecCase")
class SpecCase {
  constructor() {
    this[_a] = exports.SpecCaseTypeId
  }
  map(f) {
    concreteSpecCase(this)
    switch (this._tag) {
      case "SuiteCase": {
        return new SuiteCase(
          this.label,
          M.map_(this.specs, (_) => _.map(f), fileName_1 + ":35:17"),
          this.exec
        )
      }
      case "TestCase": {
        return new TestCase(this.label, this.test, this.annotations)
      }
    }
  }
}
exports.SpecCase = SpecCase
;(_a = exports.SpecCaseTypeId), T._R, T._E, T._T, T._A
function concreteSpecCase(_) {
  //
}
exports.concreteSpecCase = concreteSpecCase
class SuiteCase extends SpecCase {
  constructor(label, specs, exec) {
    super()
    this.label = label
    this.specs = specs
    this.exec = exec
    this._tag = "SuiteCase"
  }
}
exports.SuiteCase = SuiteCase
class TestCase extends SpecCase {
  constructor(label, test, annotations) {
    super()
    this.label = label
    this.test = test
    this.annotations = annotations
    this._tag = "TestCase"
  }
}
exports.TestCase = TestCase
exports.SpecTypeId = Symbol.for("@effect-ts/system/Testing/Spec")
/**
 * A `Spec[R, E, T]` is the backbone of _ZIO Test_. Every spec is either a
 * suite, which contains other specs, or a test of type `T`. All specs require
 * an environment of type `R` and may potentially fail with an error of type
 * `E`.
 */
class Spec {
  constructor(caseValue) {
    this.caseValue = caseValue
    this[_b] = exports.SpecTypeId
  }
}
exports.Spec = Spec
;(_b = exports.SpecTypeId), T._R, T._E, T._T
function suite(label, specs, exec) {
  return new Spec(new SuiteCase(label, specs, exec))
}
exports.suite = suite
function test(label, test, annotations) {
  return new Spec(new TestCase(label, test, annotations))
}
exports.test = test
/**
 * Transforms the spec one layer at a time.
 */
function transform(f) {
  return (spec) => {
    concreteSpecCase(spec.caseValue)
    switch (spec.caseValue._tag) {
      case "SuiteCase": {
        return new Spec(
          f(
            new SuiteCase(
              spec.caseValue.label,
              M.map_(
                spec.caseValue.specs,
                (_) => _.map(transform(f)),
                fileName_1 + ":127:21"
              ),
              spec.caseValue.exec
            )
          )
        )
      }
      case "TestCase": {
        return new Spec(f(spec.caseValue))
      }
    }
  }
}
exports.transform = transform
/**
 * Annotates each test in this spec with the specified test annotation.
 */
function annotate(key, value) {
  return (self) =>
    transform((specCase) => {
      concreteSpecCase(specCase)
      switch (specCase._tag) {
        case "SuiteCase": {
          return specCase
        }
        case "TestCase": {
          return new TestCase(
            specCase.label,
            specCase.test,
            TAM.annotate(key, value)(specCase.annotations)
          )
        }
      }
    })(self)
}
exports.annotate = annotate
/**
 * Returns a new spec with the annotation map at each node.
 */
function annotated(self) {
  return transform((specCase) => {
    concreteSpecCase(specCase)
    switch (specCase._tag) {
      case "SuiteCase": {
        return new SuiteCase(
          specCase.label,
          M.mapError_(
            specCase.specs,
            (_) => Tuple.tuple(_, TAM.TestAnnotationMap.empty),
            fileName_1 + ":183:24"
          ),
          specCase.exec
        )
      }
      case "TestCase": {
        return new TestCase(
          specCase.label,
          Annotations.withAnnotation(specCase.test),
          specCase.annotations
        )
      }
    }
  })(self)
}
exports.annotated = annotated
function provideLayer(layer) {
  return (self) =>
    transform((_) => {
      concreteSpecCase(_)
      switch (_._tag) {
        case "SuiteCase":
          return new SuiteCase(
            _.label,
            M.provideLayer_(_.specs, layer, fileName_1 + ":209:58"),
            _.exec
          )
        case "TestCase":
          return new TestCase(_.label, T.provideLayer_(_.test, layer), _.annotations)
      }
    })(self)
}
exports.provideLayer = provideLayer
function forEachExec(defExec, failure, success) {
  return (self) =>
    foldM(defExec)((_) => {
      concreteSpecCase(_)
      switch (_._tag) {
        case "SuiteCase": {
          const v = _
          return M.foldCause_(
            v.specs,
            (e) => test(v.label, failure(e), TAM.TestAnnotationMap.empty),
            (t) => suite(v.label, M.succeed(t, fileName_1 + ":236:48"), v.exec),
            fileName_1 + ":234:26"
          )
        }
        case "TestCase": {
          const v = _
          return T.toManaged(
            T.foldCause_(
              v.test,
              (e) => test(v.label, failure(e), v.annotations),
              (e) => test(v.label, success(e), v.annotations),
              fileName_1 + ":245:26"
            )
          )
        }
      }
    })(self)
}
exports.forEachExec = forEachExec
function foldM(defExec) {
  return (f) => (self) => {
    concreteSpecCase(self.caseValue)
    switch (self.caseValue._tag) {
      case "SuiteCase": {
        const v = self.caseValue
        return M.foldCauseM_(
          v.specs,
          (c) => f(new SuiteCase(v.label, M.halt(c, fileName_1 + ":268:53"), v.exec)),
          (_) =>
            M.chain_(
              M.forEachExec_(
                _,
                O.getOrElse_(v.exec, () => defExec),
                (s) => M.release(foldM(defExec)(f)(s), fileName_1 + ":274:75"),
                fileName_1 + ":272:32"
              ),
              (z) =>
                f(
                  new SuiteCase(
                    v.label,
                    M.succeed(Chunk.toArray(z), fileName_1 + ":277:55"),
                    v.exec
                  )
                ),
              fileName_1 + ":276:26"
            ),
          fileName_1 + ":267:25"
        )
      }
      case "TestCase":
        return f(self.caseValue)
    }
  }
}
exports.foldM = foldM
//# sourceMappingURL=index.js.map
