@effect/vitest 0.26.0 → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,82 +1,48 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
- import type { Tester, TesterContext } from "@vitest/expect"
5
- import * as Arbitrary from "effect/Arbitrary"
4
+
6
5
  import * as Cause from "effect/Cause"
7
6
  import * as Duration from "effect/Duration"
8
7
  import * as Effect from "effect/Effect"
9
- import * as Equal from "effect/Equal"
10
8
  import * as Exit from "effect/Exit"
11
- import * as fc from "effect/FastCheck"
12
- import * as Fiber from "effect/Fiber"
13
- import { flow, identity, pipe } from "effect/Function"
9
+ import { flow, pipe } from "effect/Function"
14
10
  import * as Layer from "effect/Layer"
15
- import * as Logger from "effect/Logger"
16
11
  import { isObject } from "effect/Predicate"
17
12
  import * as Schedule from "effect/Schedule"
18
13
  import * as Schema from "effect/Schema"
19
14
  import * as Scope from "effect/Scope"
20
- import * as TestEnvironment from "effect/TestContext"
21
- import type * as TestServices from "effect/TestServices"
22
- import * as Utils from "effect/Utils"
15
+ import * as fc from "effect/testing/FastCheck"
16
+ import * as TestClock from "effect/testing/TestClock"
17
+ import * as TestConsole from "effect/testing/TestConsole"
23
18
  import * as V from "vitest"
24
- import type * as Vitest from "../index.js"
25
-
26
- const defaultApi = Object.assign(V.it, { scopedFixtures: V.it.scoped })
27
-
28
- const runPromise = (ctx?: Vitest.TestContext) => <E, A>(effect: Effect.Effect<A, E>) =>
29
- Effect.gen(function*() {
30
- const exitFiber = yield* Effect.fork(Effect.exit(effect))
31
-
32
- ctx?.onTestFinished(() =>
33
- Fiber.interrupt(exitFiber).pipe(
34
- Effect.asVoid,
35
- Effect.runPromise
36
- )
37
- )
38
-
39
- const exit = yield* Fiber.join(exitFiber)
40
- if (Exit.isSuccess(exit)) {
41
- return () => exit.value
42
- } else {
43
- if (Cause.isInterruptedOnly(exit.cause)) {
44
- return () => {
45
- throw new Error("All fibers interrupted without errors.")
46
- }
47
- }
48
- const errors = Cause.prettyErrors(exit.cause)
49
- for (let i = 1; i < errors.length; i++) {
50
- yield* Effect.logError(errors[i])
51
- }
52
- return () => {
53
- throw errors[0]
54
- }
19
+ import type * as Vitest from "../index.ts"
20
+
21
+ const runPromise: <E, A>(
22
+ _: Effect.Effect<A, E, never>,
23
+ ctx?: V.TestContext | undefined
24
+ ) => Promise<A> = Effect.fnUntraced(function*<E, A>(effect: Effect.Effect<A, E>, _ctx?: Vitest.TestContext) {
25
+ const exit = yield* Effect.exit(effect)
26
+ if (Exit.isFailure(exit)) {
27
+ const errors = Cause.prettyErrors(exit.cause)
28
+ for (let i = 0; i < errors.length; i++) {
29
+ yield* Effect.logError(errors[i])
55
30
  }
56
- }).pipe((effect) => Effect.runPromise(effect, { signal: ctx?.signal })).then((f) => f())
31
+ }
32
+ return yield* exit
33
+ }, (effect, _, ctx) => Effect.runPromise(effect, { signal: ctx?.signal }))
57
34
 
58
35
  /** @internal */
59
- const runTest = (ctx?: Vitest.TestContext) => <E, A>(effect: Effect.Effect<A, E>) => runPromise(ctx)(effect)
36
+ const runTest = (ctx?: Vitest.TestContext) => <E, A>(effect: Effect.Effect<A, E>) => runPromise(effect, ctx)
60
37
 
61
38
  /** @internal */
62
- const TestEnv = TestEnvironment.TestContext.pipe(
63
- Layer.provide(Logger.remove(Logger.defaultLogger))
64
- )
39
+ export type TestContext = TestConsole.TestConsole | TestClock.TestClock
65
40
 
66
- /** @internal */
67
- function customTester(this: TesterContext, a: unknown, b: unknown, customTesters: Array<Tester>) {
68
- if (!Equal.isEqual(a) || !Equal.isEqual(b)) {
69
- return undefined
70
- }
71
- return Utils.structuralRegion(
72
- () => Equal.equals(a, b),
73
- (x, y) => this.equals(x, y, customTesters.filter((t) => t !== customTester))
74
- )
75
- }
41
+ const TestEnv = Layer.mergeAll(TestConsole.layer, TestClock.layer())
76
42
 
77
43
  /** @internal */
78
44
  export const addEqualityTesters = () => {
79
- V.expect.addEqualityTesters([customTester])
45
+ V.expect.addEqualityTesters([])
80
46
  }
81
47
 
82
48
  /** @internal */
@@ -85,7 +51,7 @@ const testOptions = (timeout?: number | V.TestOptions) => typeof timeout === "nu
85
51
  /** @internal */
86
52
  const makeTester = <R>(
87
53
  mapEffect: <A, E>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, never>,
88
- it: Vitest.API = defaultApi
54
+ it: V.TestAPI = V.it
89
55
  ): Vitest.Vitest.Tester<R> => {
90
56
  const run = <A, E, TestArgs extends Array<unknown>>(
91
57
  ctx: V.TestContext & object,
@@ -120,7 +86,12 @@ const makeTester = <R>(
120
86
 
121
87
  const prop: Vitest.Vitest.Tester<R>["prop"] = (name, arbitraries, self, timeout) => {
122
88
  if (Array.isArray(arbitraries)) {
123
- const arbs = arbitraries.map((arbitrary) => Schema.isSchema(arbitrary) ? Arbitrary.make(arbitrary) : arbitrary)
89
+ const arbs = arbitraries.map((arbitrary) => {
90
+ if (Schema.isSchema(arbitrary)) {
91
+ return Schema.toArbitrary(arbitrary)
92
+ }
93
+ return arbitrary as fc.Arbitrary<any>
94
+ })
124
95
  return it(
125
96
  name,
126
97
  testOptions(timeout),
@@ -129,6 +100,7 @@ const makeTester = <R>(
129
100
  fc.assert(
130
101
  // @ts-ignore
131
102
  fc.asyncProperty(...arbs, (...as) => run(ctx, [as as any, ctx], self)),
103
+ // @ts-ignore
132
104
  isObject(timeout) ? timeout?.fastCheck : {}
133
105
  )
134
106
  )
@@ -136,7 +108,11 @@ const makeTester = <R>(
136
108
 
137
109
  const arbs = fc.record(
138
110
  Object.keys(arbitraries).reduce(function(result, key) {
139
- result[key] = Schema.isSchema(arbitraries[key]) ? Arbitrary.make(arbitraries[key]) : arbitraries[key]
111
+ const arb: any = arbitraries[key]
112
+ if (Schema.isSchema(arb)) {
113
+ result[key] = Schema.toArbitrary(arb)
114
+ }
115
+ result[key] = arb
140
116
  return result
141
117
  }, {} as Record<string, fc.Arbitrary<any>>)
142
118
  )
@@ -150,6 +126,7 @@ const makeTester = <R>(
150
126
  fc.asyncProperty(arbs, (...as) =>
151
127
  // @ts-ignore
152
128
  run(ctx, [as[0] as any, ctx], self)),
129
+ // @ts-ignore
153
130
  isObject(timeout) ? timeout?.fastCheck : {}
154
131
  )
155
132
  )
@@ -161,7 +138,12 @@ const makeTester = <R>(
161
138
  /** @internal */
162
139
  export const prop: Vitest.Vitest.Methods["prop"] = (name, arbitraries, self, timeout) => {
163
140
  if (Array.isArray(arbitraries)) {
164
- const arbs = arbitraries.map((arbitrary) => Schema.isSchema(arbitrary) ? Arbitrary.make(arbitrary) : arbitrary)
141
+ const arbs = arbitraries.map((arbitrary) => {
142
+ if (Schema.isSchema(arbitrary)) {
143
+ throw new Error("Schemas are not supported yet")
144
+ }
145
+ return arbitrary
146
+ })
165
147
  return V.it(
166
148
  name,
167
149
  testOptions(timeout),
@@ -172,7 +154,11 @@ export const prop: Vitest.Vitest.Methods["prop"] = (name, arbitraries, self, tim
172
154
 
173
155
  const arbs = fc.record(
174
156
  Object.keys(arbitraries).reduce(function(result, key) {
175
- result[key] = Schema.isSchema(arbitraries[key]) ? Arbitrary.make(arbitraries[key]) : arbitraries[key]
157
+ const arb: any = arbitraries[key]
158
+ if (Schema.isSchema(arb)) {
159
+ throw new Error("Schemas are not supported yet")
160
+ }
161
+ result[key] = arb
176
162
  return result
177
163
  }, {} as Record<string, fc.Arbitrary<any>>)
178
164
  )
@@ -186,61 +172,54 @@ export const prop: Vitest.Vitest.Methods["prop"] = (name, arbitraries, self, tim
186
172
  }
187
173
 
188
174
  /** @internal */
189
- export const layer = <R, E, const ExcludeTestServices extends boolean = false>(
175
+ export const layer = <R, E>(
190
176
  layer_: Layer.Layer<R, E>,
191
177
  options?: {
192
178
  readonly memoMap?: Layer.MemoMap
193
179
  readonly timeout?: Duration.DurationInput
194
- readonly excludeTestServices?: ExcludeTestServices
180
+ readonly excludeTestServices?: boolean
195
181
  }
196
182
  ): {
197
- (f: (it: Vitest.Vitest.MethodsNonLive<R, ExcludeTestServices>) => void): void
183
+ (f: (it: Vitest.Vitest.MethodsNonLive<R>) => void): void
198
184
  (
199
185
  name: string,
200
- f: (it: Vitest.Vitest.MethodsNonLive<R, ExcludeTestServices>) => void
186
+ f: (it: Vitest.Vitest.MethodsNonLive<R>) => void
201
187
  ): void
202
188
  } =>
203
189
  (
204
190
  ...args: [
205
191
  name: string,
206
192
  f: (
207
- it: Vitest.Vitest.MethodsNonLive<R, ExcludeTestServices>
193
+ it: Vitest.Vitest.MethodsNonLive<R>
208
194
  ) => void
209
195
  ] | [
210
- f: (it: Vitest.Vitest.MethodsNonLive<R, ExcludeTestServices>) => void
196
+ f: (it: Vitest.Vitest.MethodsNonLive<R>) => void
211
197
  ]
212
198
  ) => {
213
199
  const excludeTestServices = options?.excludeTestServices ?? false
214
200
  const withTestEnv = excludeTestServices
215
- ? layer_ as Layer.Layer<R | TestServices.TestServices, E>
201
+ ? layer_ as Layer.Layer<R, E>
216
202
  : Layer.provideMerge(layer_, TestEnv)
217
203
  const memoMap = options?.memoMap ?? Effect.runSync(Layer.makeMemoMap)
218
204
  const scope = Effect.runSync(Scope.make())
219
- const runtimeEffect = Layer.toRuntimeWithMemoMap(withTestEnv, memoMap).pipe(
220
- Scope.extend(scope),
205
+ const contextEffect = Layer.buildWithMemoMap(withTestEnv, memoMap, scope).pipe(
221
206
  Effect.orDie,
222
207
  Effect.cached,
223
208
  Effect.runSync
224
209
  )
225
210
 
226
- const makeIt = (it: Vitest.API): Vitest.Vitest.MethodsNonLive<R, ExcludeTestServices> =>
211
+ const makeIt = (it: V.TestAPI): Vitest.Vitest.MethodsNonLive<R> =>
227
212
  Object.assign(it, {
228
- effect: makeTester<TestServices.TestServices | R>(
229
- (effect) => Effect.flatMap(runtimeEffect, (runtime) => effect.pipe(Effect.provide(runtime))),
230
- it
231
- ),
232
-
233
- prop,
234
-
235
- scoped: makeTester<TestServices.TestServices | Scope.Scope | R>(
213
+ effect: makeTester<R | Scope.Scope>(
236
214
  (effect) =>
237
- Effect.flatMap(runtimeEffect, (runtime) =>
215
+ Effect.flatMap(contextEffect, (context) =>
238
216
  effect.pipe(
239
217
  Effect.scoped,
240
- Effect.provide(runtime)
218
+ Effect.provide(context)
241
219
  )),
242
220
  it
243
221
  ),
222
+ prop,
244
223
  flakyTest,
245
224
  layer<R2, E2>(nestedLayer: Layer.Layer<R2, E2, R>, options?: {
246
225
  readonly timeout?: Duration.DurationInput
@@ -251,53 +230,57 @@ export const layer = <R, E, const ExcludeTestServices extends boolean = false>(
251
230
 
252
231
  if (args.length === 1) {
253
232
  V.beforeAll(
254
- () => runPromise()(Effect.asVoid(runtimeEffect)),
255
- options?.timeout ? Duration.toMillis(options.timeout) : undefined
233
+ () => runPromise(Effect.asVoid(contextEffect)),
234
+ options?.timeout ? Duration.toMillis(Duration.fromDurationInputUnsafe(options.timeout)) : undefined
256
235
  )
257
236
  V.afterAll(
258
- () => runPromise()(Scope.close(scope, Exit.void)),
259
- options?.timeout ? Duration.toMillis(options.timeout) : undefined
237
+ () => runPromise(Scope.close(scope, Exit.void)),
238
+ options?.timeout ? Duration.toMillis(Duration.fromDurationInputUnsafe(options.timeout)) : undefined
260
239
  )
261
- return args[0](makeIt(defaultApi))
240
+ return args[0](makeIt(V.it))
262
241
  }
263
242
 
264
243
  return V.describe(args[0], () => {
265
244
  V.beforeAll(
266
- () => runPromise()(Effect.asVoid(runtimeEffect)),
267
- options?.timeout ? Duration.toMillis(options.timeout) : undefined
245
+ () => runPromise(Effect.asVoid(contextEffect)),
246
+ options?.timeout ? Duration.toMillis(Duration.fromDurationInputUnsafe(options.timeout)) : undefined
268
247
  )
269
248
  V.afterAll(
270
- () => runPromise()(Scope.close(scope, Exit.void)),
271
- options?.timeout ? Duration.toMillis(options.timeout) : undefined
249
+ () => runPromise(Scope.close(scope, Exit.void)),
250
+ options?.timeout ? Duration.toMillis(Duration.fromDurationInputUnsafe(options.timeout)) : undefined
272
251
  )
273
- return args[1](makeIt(defaultApi))
252
+ return args[1](makeIt(V.it))
274
253
  })
275
254
  }
276
255
 
277
256
  /** @internal */
278
257
  export const flakyTest = <A, E, R>(
279
- self: Effect.Effect<A, E, R>,
258
+ self: Effect.Effect<A, E, R | Scope.Scope>,
280
259
  timeout: Duration.DurationInput = Duration.seconds(30)
281
260
  ) =>
282
261
  pipe(
283
- Effect.catchAllDefect(self, Effect.fail),
262
+ self,
263
+ Effect.scoped,
264
+ Effect.sandbox,
284
265
  Effect.retry(
285
266
  pipe(
286
267
  Schedule.recurs(10),
287
- Schedule.compose(Schedule.elapsed),
288
- Schedule.whileOutput(Duration.lessThanOrEqualTo(timeout))
268
+ Schedule.while((_) =>
269
+ Effect.succeed(Duration.isLessThanOrEqualTo(
270
+ Duration.fromDurationInputUnsafe(_.elapsed),
271
+ Duration.fromDurationInputUnsafe(timeout)
272
+ ))
273
+ )
289
274
  )
290
275
  ),
291
276
  Effect.orDie
292
277
  )
293
278
 
294
279
  /** @internal */
295
- export const makeMethods = (it: Vitest.API): Vitest.Vitest.Methods =>
280
+ export const makeMethods = (it: V.TestAPI): Vitest.Vitest.Methods =>
296
281
  Object.assign(it, {
297
- effect: makeTester<TestServices.TestServices>(Effect.provide(TestEnv), it),
298
- scoped: makeTester<TestServices.TestServices | Scope.Scope>(flow(Effect.scoped, Effect.provide(TestEnv)), it),
299
- live: makeTester<never>(identity, it),
300
- scopedLive: makeTester<Scope.Scope>(Effect.scoped, it),
282
+ effect: makeTester<Scope.Scope>(flow(Effect.scoped, Effect.provide(TestEnv)), it),
283
+ live: makeTester<Scope.Scope>(Effect.scoped, it),
301
284
  flakyTest,
302
285
  layer,
303
286
  prop
@@ -308,13 +291,9 @@ export const {
308
291
  /** @internal */
309
292
  effect,
310
293
  /** @internal */
311
- live,
312
- /** @internal */
313
- scoped,
314
- /** @internal */
315
- scopedLive
316
- } = makeMethods(defaultApi)
294
+ live
295
+ } = makeMethods(V.it)
317
296
 
318
297
  /** @internal */
319
298
  export const describeWrapped = (name: string, f: (it: Vitest.Vitest.Methods) => void): V.SuiteCollector =>
320
- V.describe(name, (it) => f(makeMethods(Object.assign(it, { scopedFixtures: it.scoped }))))
299
+ V.describe(name, (it) => f(makeMethods(it)))
package/src/utils.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @since 0.21.0
2
+ * @since 4.0.0
3
3
  */
4
4
  import type * as Cause from "effect/Cause"
5
- import * as Either from "effect/Either"
6
5
  import * as Equal from "effect/Equal"
7
6
  import * as Exit from "effect/Exit"
8
7
  import * as Option from "effect/Option"
9
8
  import * as Predicate from "effect/Predicate"
9
+ import * as Result from "effect/Result"
10
10
  import * as assert from "node:assert"
11
11
  import { assert as vassert } from "vitest"
12
12
 
@@ -17,7 +17,7 @@ import { assert as vassert } from "vitest"
17
17
  /**
18
18
  * Throws an `AssertionError` with the provided error message.
19
19
  *
20
- * @since 0.21.0
20
+ * @since 4.0.0
21
21
  */
22
22
  export function fail(message: string) {
23
23
  assert.fail(message)
@@ -26,7 +26,7 @@ export function fail(message: string) {
26
26
  /**
27
27
  * Asserts that `actual` is equal to `expected` using the `Equal.equals` trait.
28
28
  *
29
- * @since 0.21.0
29
+ * @since 4.0.0
30
30
  */
31
31
  export function deepStrictEqual<A>(actual: A, expected: A, message?: string, ..._: Array<never>) {
32
32
  assert.deepStrictEqual(actual, expected, message)
@@ -35,7 +35,7 @@ export function deepStrictEqual<A>(actual: A, expected: A, message?: string, ...
35
35
  /**
36
36
  * Asserts that `actual` is not equal to `expected` using the `Equal.equals` trait.
37
37
  *
38
- * @since 0.21.0
38
+ * @since 4.0.0
39
39
  */
40
40
  export function notDeepStrictEqual<A>(actual: A, expected: A, message?: string, ..._: Array<never>) {
41
41
  assert.notDeepStrictEqual(actual, expected, message)
@@ -44,7 +44,7 @@ export function notDeepStrictEqual<A>(actual: A, expected: A, message?: string,
44
44
  /**
45
45
  * Asserts that `actual` is equal to `expected` using the `Equal.equals` trait.
46
46
  *
47
- * @since 0.21.0
47
+ * @since 4.0.0
48
48
  */
49
49
  export function strictEqual<A>(actual: A, expected: A, message?: string, ..._: Array<never>) {
50
50
  assert.strictEqual(actual, expected, message)
@@ -53,7 +53,7 @@ export function strictEqual<A>(actual: A, expected: A, message?: string, ..._: A
53
53
  /**
54
54
  * Asserts that `actual` is equal to `expected` using the `Equal.equals` trait.
55
55
  *
56
- * @since 0.21.0
56
+ * @since 4.0.0
57
57
  */
58
58
  export function assertEquals<A>(actual: A, expected: A, message?: string, ..._: Array<never>) {
59
59
  if (!Equal.equals(actual, expected)) {
@@ -65,7 +65,7 @@ export function assertEquals<A>(actual: A, expected: A, message?: string, ..._:
65
65
  /**
66
66
  * Asserts that `thunk` does not throw an error.
67
67
  *
68
- * @since 0.21.0
68
+ * @since 4.0.0
69
69
  */
70
70
  export function doesNotThrow(thunk: () => void, message?: string, ..._: Array<never>) {
71
71
  assert.doesNotThrow(thunk, message)
@@ -78,7 +78,7 @@ export function doesNotThrow(thunk: () => void, message?: string, ..._: Array<ne
78
78
  /**
79
79
  * Asserts that `value` is an instance of `constructor`.
80
80
  *
81
- * @since 0.21.0
81
+ * @since 4.0.0
82
82
  */
83
83
  export function assertInstanceOf<C extends abstract new(...args: any) => any>(
84
84
  value: unknown,
@@ -86,14 +86,13 @@ export function assertInstanceOf<C extends abstract new(...args: any) => any>(
86
86
  message?: string,
87
87
  ..._: Array<never>
88
88
  ): asserts value is InstanceType<C> {
89
- // @ts-ignore
90
- vassert.instanceOf(value, constructor, message)
89
+ vassert.instanceOf(value, constructor as any, message)
91
90
  }
92
91
 
93
92
  /**
94
93
  * Asserts that `self` is `true`.
95
94
  *
96
- * @since 0.21.0
95
+ * @since 4.0.0
97
96
  */
98
97
  export function assertTrue(self: unknown, message?: string, ..._: Array<never>): asserts self {
99
98
  strictEqual(self, true, message)
@@ -102,7 +101,7 @@ export function assertTrue(self: unknown, message?: string, ..._: Array<never>):
102
101
  /**
103
102
  * Asserts that `self` is `false`.
104
103
  *
105
- * @since 0.21.0
104
+ * @since 4.0.0
106
105
  */
107
106
  export function assertFalse(self: boolean, message?: string, ..._: Array<never>) {
108
107
  strictEqual(self, false, message)
@@ -111,10 +110,10 @@ export function assertFalse(self: boolean, message?: string, ..._: Array<never>)
111
110
  /**
112
111
  * Asserts that `actual` includes `expected`.
113
112
  *
114
- * @since 0.21.0
113
+ * @since 4.0.0
115
114
  */
116
115
  export function assertInclude(actual: string | undefined, expected: string, ..._: Array<never>) {
117
- if (Predicate.isString(expected)) {
116
+ if (typeof expected === "string") {
118
117
  if (!actual?.includes(expected)) {
119
118
  fail(`Expected\n\n${actual}\n\nto include\n\n${expected}`)
120
119
  }
@@ -122,20 +121,20 @@ export function assertInclude(actual: string | undefined, expected: string, ..._
122
121
  }
123
122
 
124
123
  /**
125
- * Asserts that `actual` matches `regexp`.
124
+ * Asserts that `actual` matches `regExp`.
126
125
  *
127
- * @since 0.21.0
126
+ * @since 4.0.0
128
127
  */
129
- export function assertMatch(actual: string, regexp: RegExp, ..._: Array<never>) {
130
- if (!regexp.test(actual)) {
131
- fail(`Expected\n\n${actual}\n\nto match\n\n${regexp}`)
128
+ export function assertMatch(actual: string, regExp: RegExp, ..._: Array<never>) {
129
+ if (!regExp.test(actual)) {
130
+ fail(`Expected\n\n${actual}\n\nto match\n\n${regExp}`)
132
131
  }
133
132
  }
134
133
 
135
134
  /**
136
135
  * Asserts that `thunk` throws an error.
137
136
  *
138
- * @since 0.21.0
137
+ * @since 4.0.0
139
138
  */
140
139
  export function throws(thunk: () => void, error?: Error | ((u: unknown) => undefined), ..._: Array<never>) {
141
140
  try {
@@ -155,7 +154,7 @@ export function throws(thunk: () => void, error?: Error | ((u: unknown) => undef
155
154
  /**
156
155
  * Asserts that `thunk` throws an error.
157
156
  *
158
- * @since 0.21.0
157
+ * @since 4.0.0
159
158
  */
160
159
  export async function throwsAsync(
161
160
  thunk: () => Promise<void>,
@@ -183,16 +182,44 @@ export async function throwsAsync(
183
182
  /**
184
183
  * Asserts that `option` is `None`.
185
184
  *
186
- * @since 0.21.0
185
+ * @since 4.0.0
187
186
  */
188
187
  export function assertNone<A>(option: Option.Option<A>, ..._: Array<never>): asserts option is Option.None<never> {
189
188
  deepStrictEqual(option, Option.none())
190
189
  }
191
190
 
191
+ /**
192
+ * Asserts that `a` is not `undefined`.
193
+ *
194
+ * @since 4.0.0
195
+ */
196
+ export function assertDefined<A>(
197
+ a: A | undefined,
198
+ ..._: Array<never>
199
+ ): asserts a is Exclude<A, undefined> {
200
+ if (a === undefined) {
201
+ fail("Expected value to be defined")
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Asserts that `a` is `undefined`.
207
+ *
208
+ * @since 4.0.0
209
+ */
210
+ export function assertUndefined<A>(
211
+ a: A | undefined,
212
+ ..._: Array<never>
213
+ ): asserts a is undefined {
214
+ if (a !== undefined) {
215
+ fail("Expected value to be undefined")
216
+ }
217
+ }
218
+
192
219
  /**
193
220
  * Asserts that `option` is `Some`.
194
221
  *
195
- * @since 0.21.0
222
+ * @since 4.0.0
196
223
  */
197
224
  export function assertSome<A>(
198
225
  option: Option.Option<A>,
@@ -203,33 +230,33 @@ export function assertSome<A>(
203
230
  }
204
231
 
205
232
  // ----------------------------
206
- // Either
233
+ // Result
207
234
  // ----------------------------
208
235
 
209
236
  /**
210
- * Asserts that `either` is `Left`.
237
+ * Asserts that `result` is `Success`.
211
238
  *
212
- * @since 0.21.0
239
+ * @since 4.0.0
213
240
  */
214
- export function assertLeft<R, L>(
215
- either: Either.Either<R, L>,
216
- expected: L,
241
+ export function assertSuccess<A, E>(
242
+ result: Result.Result<A, E>,
243
+ expected: A,
217
244
  ..._: Array<never>
218
- ): asserts either is Either.Left<L, never> {
219
- deepStrictEqual(either, Either.left(expected))
245
+ ): asserts result is Result.Success<A, never> {
246
+ deepStrictEqual(result, Result.succeed(expected))
220
247
  }
221
248
 
222
249
  /**
223
- * Asserts that `either` is `Right`.
250
+ * Asserts that `result` is `Failure`.
224
251
  *
225
- * @since 0.21.0
252
+ * @since 4.0.0
226
253
  */
227
- export function assertRight<R, L>(
228
- either: Either.Either<R, L>,
229
- expected: R,
254
+ export function assertFailure<A, E>(
255
+ result: Result.Result<A, E>,
256
+ expected: E,
230
257
  ..._: Array<never>
231
- ): asserts either is Either.Right<never, R> {
232
- deepStrictEqual(either, Either.right(expected))
258
+ ): asserts result is Result.Failure<never, E> {
259
+ deepStrictEqual(result, Result.fail(expected))
233
260
  }
234
261
 
235
262
  // ----------------------------
@@ -239,9 +266,9 @@ export function assertRight<R, L>(
239
266
  /**
240
267
  * Asserts that `exit` is a failure.
241
268
  *
242
- * @since 0.21.0
269
+ * @since 4.0.0
243
270
  */
244
- export function assertFailure<A, E>(
271
+ export function assertExitFailure<A, E>(
245
272
  exit: Exit.Exit<A, E>,
246
273
  expected: Cause.Cause<E>,
247
274
  ..._: Array<never>
@@ -252,9 +279,9 @@ export function assertFailure<A, E>(
252
279
  /**
253
280
  * Asserts that `exit` is a success.
254
281
  *
255
- * @since 0.21.0
282
+ * @since 4.0.0
256
283
  */
257
- export function assertSuccess<A, E>(
284
+ export function assertExitSuccess<A, E>(
258
285
  exit: Exit.Exit<A, E>,
259
286
  expected: A,
260
287
  ..._: Array<never>