1import { assert, describe, it, layer, type Vitest } from "@effect/vitest"
2import { Effect, Layer } from "effect"
3
4const checkConcurrency = (
5 it: Vitest.MethodsNonLive,
6 concurrent: boolean,
7 options?: { readonly concurrent: boolean }
8) => {
9 let running = 0
10 let release!: () => void
11 const bothStarted = new Promise<void>((resolve) => {
12 release = resolve
13 })
14
15 for (const name of ["first", "second"]) {
16 it.effect(name, (ctx) =>
17 Effect.gen(function*() {
18 assert.strictEqual(ctx.task.concurrent ?? false, concurrent)
19 running++
20 if (running === 2) release()
21 try {
22 if (concurrent) {
23 yield* Effect.promise(() => bothStarted)
24 } else {
25 // Let another test start if the suite was accidentally made concurrent.
26 yield* Effect.promise(() => new Promise<void>((resolve) => setTimeout(resolve, 0)))
27 assert.strictEqual(running, 1)
28 }
29 } finally {
30 running--
31 }
32 }), options)
33 }
34}
35
36for (const [name, makeLayer] of [["layer", layer], ["it.layer", it.layer]] as const) {
37 describe(name, () => {
38 for (const concurrent of [false, true]) {
39 describe(`enclosing suite concurrent=${concurrent}`, { concurrent }, () => {
40 makeLayer(Layer.empty)("named layer inherits by default", (it) => {
41 checkConcurrency(it, concurrent)
42 })
43
44 makeLayer(Layer.empty, { concurrent: !concurrent })("named layer overrides enclosing suite", (it) => {
45 checkConcurrency(it, !concurrent)
46
47 it.layer(Layer.empty)("nested layer inherits", (it) => {
48 checkConcurrency(it, !concurrent)
49 })
50
51 it.layer(Layer.empty, { concurrent })("nested layer overrides parent", (it) => {
52 checkConcurrency(it, concurrent)
53 })
54
55 describe("test options override layer", () => {
56 checkConcurrency(it, concurrent, { concurrent })
57 })
58 })
59
60 describe("anonymous layer preserves enclosing suite", () => {
61 makeLayer(Layer.empty, { concurrent: !concurrent })((it) => {
62 checkConcurrency(it, concurrent)
63
64 it.layer(Layer.empty)("nested layer inherits enclosing suite", (it) => {
65 checkConcurrency(it, concurrent)
66 })
67 })
68 })
69 })
70 }
71 })
72}