@effectionx/bdd 0.1.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.
Files changed (40) hide show
  1. package/README.md +171 -0
  2. package/esm/_dnt.shims.d.ts +2 -0
  3. package/esm/_dnt.shims.d.ts.map +1 -0
  4. package/esm/_dnt.shims.js +57 -0
  5. package/esm/deps/jsr.io/@std/assert/1.0.14/assertion_error.d.ts +26 -0
  6. package/esm/deps/jsr.io/@std/assert/1.0.14/assertion_error.d.ts.map +1 -0
  7. package/esm/deps/jsr.io/@std/assert/1.0.14/assertion_error.js +30 -0
  8. package/esm/deps/jsr.io/@std/internal/1.0.10/assertion_state.d.ts +150 -0
  9. package/esm/deps/jsr.io/@std/internal/1.0.10/assertion_state.d.ts.map +1 -0
  10. package/esm/deps/jsr.io/@std/internal/1.0.10/assertion_state.js +237 -0
  11. package/esm/deps/jsr.io/@std/testing/1.0.15/_test_suite.d.ts +78 -0
  12. package/esm/deps/jsr.io/@std/testing/1.0.15/_test_suite.d.ts.map +1 -0
  13. package/esm/deps/jsr.io/@std/testing/1.0.15/_test_suite.js +385 -0
  14. package/esm/deps/jsr.io/@std/testing/1.0.15/bdd.d.ts +336 -0
  15. package/esm/deps/jsr.io/@std/testing/1.0.15/bdd.d.ts.map +1 -0
  16. package/esm/deps/jsr.io/@std/testing/1.0.15/bdd.js +1057 -0
  17. package/esm/mod.d.ts +13 -0
  18. package/esm/mod.d.ts.map +1 -0
  19. package/esm/mod.js +47 -0
  20. package/esm/package.json +3 -0
  21. package/package.json +31 -0
  22. package/script/_dnt.shims.d.ts +2 -0
  23. package/script/_dnt.shims.d.ts.map +1 -0
  24. package/script/_dnt.shims.js +60 -0
  25. package/script/deps/jsr.io/@std/assert/1.0.14/assertion_error.d.ts +26 -0
  26. package/script/deps/jsr.io/@std/assert/1.0.14/assertion_error.d.ts.map +1 -0
  27. package/script/deps/jsr.io/@std/assert/1.0.14/assertion_error.js +34 -0
  28. package/script/deps/jsr.io/@std/internal/1.0.10/assertion_state.d.ts +150 -0
  29. package/script/deps/jsr.io/@std/internal/1.0.10/assertion_state.d.ts.map +1 -0
  30. package/script/deps/jsr.io/@std/internal/1.0.10/assertion_state.js +275 -0
  31. package/script/deps/jsr.io/@std/testing/1.0.15/_test_suite.d.ts +78 -0
  32. package/script/deps/jsr.io/@std/testing/1.0.15/_test_suite.d.ts.map +1 -0
  33. package/script/deps/jsr.io/@std/testing/1.0.15/_test_suite.js +389 -0
  34. package/script/deps/jsr.io/@std/testing/1.0.15/bdd.d.ts +336 -0
  35. package/script/deps/jsr.io/@std/testing/1.0.15/bdd.d.ts.map +1 -0
  36. package/script/deps/jsr.io/@std/testing/1.0.15/bdd.js +1068 -0
  37. package/script/mod.d.ts +13 -0
  38. package/script/mod.d.ts.map +1 -0
  39. package/script/mod.js +52 -0
  40. package/script/package.json +3 -0
@@ -0,0 +1,1068 @@
1
+ "use strict";
2
+ // Copyright 2018-2025 the Deno authors. MIT license.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.it = it;
5
+ exports.test = test;
6
+ exports.beforeAll = beforeAll;
7
+ exports.before = before;
8
+ exports.afterAll = afterAll;
9
+ exports.after = after;
10
+ exports.beforeEach = beforeEach;
11
+ exports.afterEach = afterEach;
12
+ exports.describe = describe;
13
+ /**
14
+ * A {@link https://en.wikipedia.org/wiki/Behavior-driven_development | BDD} interface
15
+ * to `Deno.test()` API.
16
+ *
17
+ * With `@std/testing/bdd` module you can write your tests in a familiar format for
18
+ * grouping tests and adding setup/teardown hooks used by other JavaScript testing
19
+ * frameworks like Jasmine, Jest, and Mocha.
20
+ *
21
+ * The `describe` function creates a block that groups together several related
22
+ * tests. The `it` function registers an individual test case.
23
+ *
24
+ * ## Hooks
25
+ *
26
+ * There are 4 types of hooks available for test suites. A test suite can have
27
+ * multiples of each type of hook, they will be called in the order that they are
28
+ * registered. The `afterEach` and `afterAll` hooks will be called whether or not
29
+ * the test case passes. The *All hooks will be called once for the whole group
30
+ * while the *Each hooks will be called for each individual test case.
31
+ *
32
+ * - `beforeAll`: Runs before all of the tests in the group.
33
+ * - `afterAll`: Runs after all of the tests in the group finish.
34
+ * - `beforeEach`: Runs before each of the individual test cases in the group.
35
+ * - `afterEach`: Runs after each of the individual test cases in the group.
36
+ *
37
+ * If a hook is registered at the top level, a global test suite will be registered
38
+ * and all tests will belong to it. Hooks registered at the top level must be
39
+ * registered before any individual test cases or test suites.
40
+ *
41
+ * ## Focusing tests
42
+ *
43
+ * If you would like to run only specific test cases, you can do so by calling
44
+ * `it.only` instead of `it`. If you would like to run only specific test suites,
45
+ * you can do so by calling `describe.only` instead of `describe`.
46
+ *
47
+ * There is one limitation to this when using the flat test grouping style. When
48
+ * `describe` is called without being nested, it registers the test with
49
+ * `Deno.test`. If a child test case or suite is registered with `it.only` or
50
+ * `describe.only`, it will be scoped to the top test suite instead of the file. To
51
+ * make them the only tests that run in the file, you would need to register the
52
+ * top test suite with `describe.only` too.
53
+ *
54
+ * ## Ignoring tests
55
+ *
56
+ * If you would like to not run specific individual test cases, you can do so by
57
+ * calling `it.ignore` instead of `it`. If you would like to not run specific test
58
+ * suites, you can do so by calling `describe.ignore` instead of `describe`.
59
+ *
60
+ * ## Sanitization options
61
+ *
62
+ * Like `Deno.TestDefinition`, the `DescribeDefinition` and `ItDefinition` have
63
+ * sanitization options. They work in the same way.
64
+ *
65
+ * - `sanitizeExit`: Ensure the test case does not prematurely cause the process to
66
+ * exit, for example via a call to Deno.exit. Defaults to true.
67
+ * - `sanitizeOps`: Check that the number of async completed ops after the test is
68
+ * the same as number of dispatched ops. Defaults to true.
69
+ * - `sanitizeResources`: Ensure the test case does not "leak" resources - ie. the
70
+ * resource table after the test has exactly the same contents as before the
71
+ * test. Defaults to true.
72
+ *
73
+ * ## Permissions option
74
+ *
75
+ * Like `Deno.TestDefinition`, the `DescribeDefinition` and `ItDefinition` have a
76
+ * `permissions` option. They specify the permissions that should be used to run an
77
+ * individual test case or test suite. Set this to `"inherit"` to keep the calling
78
+ * thread's permissions. Set this to `"none"` to revoke all permissions.
79
+ *
80
+ * This setting defaults to `"inherit"`.
81
+ *
82
+ * There is currently one limitation to this, you cannot use the permissions option
83
+ * on an individual test case or test suite that belongs to another test suite.
84
+ * That's because internally those tests are registered with `t.step` which does
85
+ * not support the permissions option.
86
+ *
87
+ * ## Comparing to Deno\.test
88
+ *
89
+ * The default way of writing tests is using `Deno.test` and `t.step`. The
90
+ * `describe` and `it` functions have similar call signatures to `Deno.test`,
91
+ * making it easy to switch between the default style and the behavior-driven
92
+ * development style of writing tests. Internally, `describe` and `it` are
93
+ * registering tests with `Deno.test` and `t.step`.
94
+ *
95
+ * Below is an example of a test file using `Deno.test` and `t.step`. In the
96
+ * following sections there are examples of how the same test could be written with
97
+ * `describe` and `it` using nested test grouping, flat test grouping, or a mix of
98
+ * both styles.
99
+ *
100
+ * ```ts
101
+ * import {
102
+ * assertEquals,
103
+ * assertStrictEquals,
104
+ * assertThrows,
105
+ * } from "@std/assert";
106
+ *
107
+ * class User {
108
+ * static users: Map<string, User> = new Map();
109
+ * name: string;
110
+ * age?: number;
111
+ *
112
+ * constructor(name: string) {
113
+ * if (User.users.has(name)) {
114
+ * throw new Deno.errors.AlreadyExists(`User ${name} already exists`);
115
+ * }
116
+ * this.name = name;
117
+ * User.users.set(name, this);
118
+ * }
119
+ *
120
+ * getAge(): number {
121
+ * if (!this.age) {
122
+ * throw new Error("Age unknown");
123
+ * }
124
+ * return this.age;
125
+ * }
126
+ *
127
+ * setAge(age: number) {
128
+ * this.age = age;
129
+ * }
130
+ * }
131
+ *
132
+ * Deno.test("User.users initially empty", () => {
133
+ * assertEquals(User.users.size, 0);
134
+ * });
135
+ *
136
+ * Deno.test("User constructor", () => {
137
+ * try {
138
+ * const user = new User("Kyle");
139
+ * assertEquals(user.name, "Kyle");
140
+ * assertStrictEquals(User.users.get("Kyle"), user);
141
+ * } finally {
142
+ * User.users.clear();
143
+ * }
144
+ * });
145
+ *
146
+ * Deno.test("User age", async (t) => {
147
+ * const user = new User("Kyle");
148
+ *
149
+ * await t.step("getAge", () => {
150
+ * assertThrows(() => user.getAge(), Error, "Age unknown");
151
+ * user.age = 18;
152
+ * assertEquals(user.getAge(), 18);
153
+ * });
154
+ *
155
+ * await t.step("setAge", () => {
156
+ * user.setAge(18);
157
+ * assertEquals(user.getAge(), 18);
158
+ * });
159
+ * });
160
+ * ```
161
+ *
162
+ * ### Nested test grouping
163
+ *
164
+ * Tests created within the callback of a `describe` function call will belong to
165
+ * the new test suite it creates. The hooks can be created within it or be added to
166
+ * the options argument for describe.
167
+ *
168
+ * ```ts
169
+ * import {
170
+ * assertEquals,
171
+ * assertStrictEquals,
172
+ * assertThrows,
173
+ * } from "@std/assert";
174
+ * import {
175
+ * afterEach,
176
+ * beforeEach,
177
+ * describe,
178
+ * it,
179
+ * } from "@std/testing/bdd";
180
+ *
181
+ * class User {
182
+ * static users: Map<string, User> = new Map();
183
+ * name: string;
184
+ * age?: number;
185
+ *
186
+ * constructor(name: string) {
187
+ * if (User.users.has(name)) {
188
+ * throw new Deno.errors.AlreadyExists(`User ${name} already exists`);
189
+ * }
190
+ * this.name = name;
191
+ * User.users.set(name, this);
192
+ * }
193
+ *
194
+ * getAge(): number {
195
+ * if (!this.age) {
196
+ * throw new Error("Age unknown");
197
+ * }
198
+ * return this.age;
199
+ * }
200
+ *
201
+ * setAge(age: number) {
202
+ * this.age = age;
203
+ * }
204
+ * }
205
+ *
206
+ * describe("User", () => {
207
+ * it("users initially empty", () => {
208
+ * assertEquals(User.users.size, 0);
209
+ * });
210
+ *
211
+ * it("constructor", () => {
212
+ * try {
213
+ * const user = new User("Kyle");
214
+ * assertEquals(user.name, "Kyle");
215
+ * assertStrictEquals(User.users.get("Kyle"), user);
216
+ * } finally {
217
+ * User.users.clear();
218
+ * }
219
+ * });
220
+ *
221
+ * describe("age", () => {
222
+ * let user: User;
223
+ *
224
+ * beforeEach(() => {
225
+ * user = new User("Kyle");
226
+ * });
227
+ *
228
+ * afterEach(() => {
229
+ * User.users.clear();
230
+ * });
231
+ *
232
+ * it("getAge", function () {
233
+ * assertThrows(() => user.getAge(), Error, "Age unknown");
234
+ * user.age = 18;
235
+ * assertEquals(user.getAge(), 18);
236
+ * });
237
+ *
238
+ * it("setAge", function () {
239
+ * user.setAge(18);
240
+ * assertEquals(user.getAge(), 18);
241
+ * });
242
+ * });
243
+ * });
244
+ * ```
245
+ *
246
+ * ### Flat test grouping
247
+ *
248
+ * The `describe` function returns a unique symbol that can be used to reference
249
+ * the test suite for adding tests to it without having to create them within a
250
+ * callback. The gives you the ability to have test grouping without any extra
251
+ * indentation in front of the grouped tests.
252
+ *
253
+ * ```ts
254
+ * import {
255
+ * assertEquals,
256
+ * assertStrictEquals,
257
+ * assertThrows,
258
+ * } from "@std/assert";
259
+ * import {
260
+ * describe,
261
+ * it,
262
+ * } from "@std/testing/bdd";
263
+ *
264
+ * class User {
265
+ * static users: Map<string, User> = new Map();
266
+ * name: string;
267
+ * age?: number;
268
+ *
269
+ * constructor(name: string) {
270
+ * if (User.users.has(name)) {
271
+ * throw new Deno.errors.AlreadyExists(`User ${name} already exists`);
272
+ * }
273
+ * this.name = name;
274
+ * User.users.set(name, this);
275
+ * }
276
+ *
277
+ * getAge(): number {
278
+ * if (!this.age) {
279
+ * throw new Error("Age unknown");
280
+ * }
281
+ * return this.age;
282
+ * }
283
+ *
284
+ * setAge(age: number) {
285
+ * this.age = age;
286
+ * }
287
+ * }
288
+ *
289
+ * const userTests = describe("User");
290
+ *
291
+ * it(userTests, "users initially empty", () => {
292
+ * assertEquals(User.users.size, 0);
293
+ * });
294
+ *
295
+ * it(userTests, "constructor", () => {
296
+ * try {
297
+ * const user = new User("Kyle");
298
+ * assertEquals(user.name, "Kyle");
299
+ * assertStrictEquals(User.users.get("Kyle"), user);
300
+ * } finally {
301
+ * User.users.clear();
302
+ * }
303
+ * });
304
+ *
305
+ * const ageTests = describe({
306
+ * name: "age",
307
+ * suite: userTests,
308
+ * beforeEach(this: { user: User }) {
309
+ * this.user = new User("Kyle");
310
+ * },
311
+ * afterEach() {
312
+ * User.users.clear();
313
+ * },
314
+ * });
315
+ *
316
+ * it(ageTests, "getAge", function () {
317
+ * const { user } = this;
318
+ * assertThrows(() => user.getAge(), Error, "Age unknown");
319
+ * user.age = 18;
320
+ * assertEquals(user.getAge(), 18);
321
+ * });
322
+ *
323
+ * it(ageTests, "setAge", function () {
324
+ * const { user } = this;
325
+ * user.setAge(18);
326
+ * assertEquals(user.getAge(), 18);
327
+ * });
328
+ * ```
329
+ *
330
+ * ### Mixed test grouping
331
+ *
332
+ * Both nested test grouping and flat test grouping can be used together. This can
333
+ * be useful if you'd like to create deep groupings without all the extra
334
+ * indentation in front of each line.
335
+ *
336
+ * ```ts
337
+ * import {
338
+ * assertEquals,
339
+ * assertStrictEquals,
340
+ * assertThrows,
341
+ * } from "@std/assert";
342
+ * import {
343
+ * describe,
344
+ * it,
345
+ * } from "@std/testing/bdd";
346
+ *
347
+ * class User {
348
+ * static users: Map<string, User> = new Map();
349
+ * name: string;
350
+ * age?: number;
351
+ *
352
+ * constructor(name: string) {
353
+ * if (User.users.has(name)) {
354
+ * throw new Deno.errors.AlreadyExists(`User ${name} already exists`);
355
+ * }
356
+ * this.name = name;
357
+ * User.users.set(name, this);
358
+ * }
359
+ *
360
+ * getAge(): number {
361
+ * if (!this.age) {
362
+ * throw new Error("Age unknown");
363
+ * }
364
+ * return this.age;
365
+ * }
366
+ *
367
+ * setAge(age: number) {
368
+ * this.age = age;
369
+ * }
370
+ * }
371
+ *
372
+ * describe("User", () => {
373
+ * it("users initially empty", () => {
374
+ * assertEquals(User.users.size, 0);
375
+ * });
376
+ *
377
+ * it("constructor", () => {
378
+ * try {
379
+ * const user = new User("Kyle");
380
+ * assertEquals(user.name, "Kyle");
381
+ * assertStrictEquals(User.users.get("Kyle"), user);
382
+ * } finally {
383
+ * User.users.clear();
384
+ * }
385
+ * });
386
+ *
387
+ * const ageTests = describe({
388
+ * name: "age",
389
+ * beforeEach(this: { user: User }) {
390
+ * this.user = new User("Kyle");
391
+ * },
392
+ * afterEach() {
393
+ * User.users.clear();
394
+ * },
395
+ * });
396
+ *
397
+ * it(ageTests, "getAge", function () {
398
+ * const { user } = this;
399
+ * assertThrows(() => user.getAge(), Error, "Age unknown");
400
+ * user.age = 18;
401
+ * assertEquals(user.getAge(), 18);
402
+ * });
403
+ *
404
+ * it(ageTests, "setAge", function () {
405
+ * const { user } = this;
406
+ * user.setAge(18);
407
+ * assertEquals(user.getAge(), 18);
408
+ * });
409
+ * });
410
+ * ```
411
+ *
412
+ * @module
413
+ */
414
+ const assertion_state_js_1 = require("../../internal/1.0.10/assertion_state.js");
415
+ const assertion_error_js_1 = require("../../assert/1.0.14/assertion_error.js");
416
+ const _test_suite_js_1 = require("./_test_suite.js");
417
+ /** Generates an ItDefinition from ItArgs. */
418
+ function itDefinition(...args) {
419
+ let [suiteOptionsOrNameOrFn, optionsOrNameOrFn, optionsOrFn, fn,] = args;
420
+ let suite = undefined;
421
+ let name;
422
+ let options;
423
+ if (typeof suiteOptionsOrNameOrFn === "object" &&
424
+ typeof suiteOptionsOrNameOrFn.symbol === "symbol") {
425
+ suite = suiteOptionsOrNameOrFn;
426
+ }
427
+ else {
428
+ fn = optionsOrFn;
429
+ optionsOrFn = optionsOrNameOrFn;
430
+ optionsOrNameOrFn = suiteOptionsOrNameOrFn;
431
+ }
432
+ if (typeof optionsOrNameOrFn === "string") {
433
+ name = optionsOrNameOrFn;
434
+ if (typeof optionsOrFn === "function") {
435
+ fn = optionsOrFn;
436
+ options = {};
437
+ }
438
+ else {
439
+ options = optionsOrFn;
440
+ if (!fn)
441
+ fn = options.fn;
442
+ }
443
+ }
444
+ else if (typeof optionsOrNameOrFn === "function") {
445
+ fn = optionsOrNameOrFn;
446
+ name = fn.name;
447
+ options = {};
448
+ }
449
+ else {
450
+ options = optionsOrNameOrFn;
451
+ if (typeof optionsOrFn === "function") {
452
+ fn = optionsOrFn;
453
+ }
454
+ else {
455
+ fn = options.fn;
456
+ }
457
+ name = options.name ?? fn.name;
458
+ }
459
+ return {
460
+ ...(suite !== undefined ? { suite } : {}),
461
+ ...options,
462
+ name,
463
+ fn,
464
+ };
465
+ }
466
+ /**
467
+ * Registers an individual test case.
468
+ *
469
+ * @example Usage
470
+ * ```ts
471
+ * import { describe, it } from "@std/testing/bdd";
472
+ * import { assertEquals } from "@std/assert";
473
+ *
474
+ * describe("example", () => {
475
+ * it("should pass", () => {
476
+ * // test case
477
+ * assertEquals(2 + 2, 4);
478
+ * });
479
+ * });
480
+ * ```
481
+ *
482
+ * @typeParam T The self type of the function to implement the test case
483
+ * @param args The test case
484
+ */
485
+ function it(...args) {
486
+ if (_test_suite_js_1.TestSuiteInternal.runningCount > 0) {
487
+ throw new Error("Cannot register new test cases after already registered test cases start running");
488
+ }
489
+ const assertionState = (0, assertion_state_js_1.getAssertionState)();
490
+ const options = itDefinition(...args);
491
+ const { suite } = options;
492
+ const testSuite = suite
493
+ ? _test_suite_js_1.TestSuiteInternal.suites.get(suite.symbol)
494
+ : _test_suite_js_1.TestSuiteInternal.current;
495
+ if (!_test_suite_js_1.TestSuiteInternal.started)
496
+ _test_suite_js_1.TestSuiteInternal.started = true;
497
+ if (testSuite) {
498
+ _test_suite_js_1.TestSuiteInternal.addStep(testSuite, options);
499
+ }
500
+ else {
501
+ const { name, fn, ignore, only, permissions, sanitizeExit = _test_suite_js_1.globalSanitizersState.sanitizeExit, sanitizeOps = _test_suite_js_1.globalSanitizersState.sanitizeOps, sanitizeResources = _test_suite_js_1.globalSanitizersState.sanitizeResources, } = options;
502
+ const opts = {
503
+ name,
504
+ async fn(t) {
505
+ _test_suite_js_1.TestSuiteInternal.runningCount++;
506
+ try {
507
+ await fn.call({}, t);
508
+ }
509
+ finally {
510
+ _test_suite_js_1.TestSuiteInternal.runningCount--;
511
+ }
512
+ try {
513
+ if (assertionState.checkAssertionErrorState()) {
514
+ throw new assertion_error_js_1.AssertionError("Expected at least one assertion to be called but received none");
515
+ }
516
+ if (assertionState.checkAssertionCountSatisfied()) {
517
+ throw new assertion_error_js_1.AssertionError(`Expected exactly ${assertionState.assertionCount} ${assertionState.assertionCount === 1 ? "assertion" : "assertions"} to be called, ` +
518
+ `but received ${assertionState.assertionTriggeredCount}`);
519
+ }
520
+ }
521
+ finally {
522
+ assertionState.resetAssertionState();
523
+ }
524
+ },
525
+ };
526
+ if (ignore !== undefined) {
527
+ opts.ignore = ignore;
528
+ }
529
+ if (only !== undefined) {
530
+ opts.only = only;
531
+ }
532
+ if (permissions !== undefined) {
533
+ opts.permissions = permissions;
534
+ }
535
+ if (sanitizeExit !== undefined) {
536
+ opts.sanitizeExit = sanitizeExit;
537
+ }
538
+ if (sanitizeOps !== undefined) {
539
+ opts.sanitizeOps = sanitizeOps;
540
+ }
541
+ if (sanitizeResources !== undefined) {
542
+ opts.sanitizeResources = sanitizeResources;
543
+ }
544
+ _test_suite_js_1.TestSuiteInternal.registerTest(opts);
545
+ }
546
+ }
547
+ /**
548
+ * Only execute this test case.
549
+ *
550
+ * @example Usage
551
+ * ```ts
552
+ * import { describe, it } from "@std/testing/bdd";
553
+ * import { assertEquals } from "@std/assert";
554
+ *
555
+ * describe("example", () => {
556
+ * it("should pass", () => {
557
+ * assertEquals(2 + 2, 4);
558
+ * });
559
+ *
560
+ * it.only("should pass too", () => {
561
+ * assertEquals(3 + 4, 7);
562
+ * });
563
+ * });
564
+ * ```
565
+ *
566
+ * @param args The test case
567
+ */
568
+ it.only = function itOnly(...args) {
569
+ const options = itDefinition(...args);
570
+ return it({
571
+ ...options,
572
+ only: true,
573
+ });
574
+ };
575
+ /**
576
+ * Ignore this test case.
577
+ *
578
+ * @example Usage
579
+ * ```ts
580
+ * import { describe, it } from "@std/testing/bdd";
581
+ * import { assertEquals } from "@std/assert";
582
+ *
583
+ * describe("example", () => {
584
+ * it("should pass", () => {
585
+ * assertEquals(2 + 2, 4);
586
+ * });
587
+ *
588
+ * it.ignore("should pass too", () => {
589
+ * assertEquals(3 + 4, 7);
590
+ * });
591
+ * });
592
+ * ```
593
+ *
594
+ * @param args The test case
595
+ */
596
+ it.ignore = function itIgnore(...args) {
597
+ const options = itDefinition(...args);
598
+ return it({
599
+ ...options,
600
+ ignore: true,
601
+ });
602
+ };
603
+ /** Skip this test case.
604
+ *
605
+ * @example Usage
606
+ * ```ts
607
+ * import { describe, it } from "@std/testing/bdd";
608
+ * import { assertEquals } from "@std/assert";
609
+ *
610
+ * describe("example", () => {
611
+ * it("should pass", () => {
612
+ * assertEquals(2 + 2, 4);
613
+ * });
614
+ *
615
+ * it.skip("should pass too", () => {
616
+ * assertEquals(3 + 4, 7);
617
+ * });
618
+ * });
619
+ * ```
620
+ *
621
+ * @param args The test case
622
+ */
623
+ it.skip = function itSkip(...args) {
624
+ it.ignore(...args);
625
+ };
626
+ /**
627
+ * Alias of {@linkcode it}
628
+ *
629
+ * Registers an individual test case.
630
+ *
631
+ * @example Usage
632
+ * ```ts
633
+ * import { test } from "@std/testing/bdd";
634
+ * import { assertEquals } from "@std/assert";
635
+ *
636
+ * test("a test case", () => {
637
+ * // test case
638
+ * assertEquals(2 + 2, 4);
639
+ * });
640
+ * ```
641
+ *
642
+ * @typeParam T The self type of the function to implement the test case
643
+ * @param args The test case
644
+ */
645
+ function test(...args) {
646
+ it(...args);
647
+ }
648
+ /**
649
+ * Only execute this test case.
650
+ *
651
+ * @example Usage
652
+ * ```ts
653
+ * import { describe, test } from "@std/testing/bdd";
654
+ * import { assertEquals } from "@std/assert";
655
+ *
656
+ * describe("example", () => {
657
+ * test("should pass", () => {
658
+ * assertEquals(2 + 2, 4);
659
+ * });
660
+ *
661
+ * test.only("should pass too", () => {
662
+ * assertEquals(3 + 4, 7);
663
+ * });
664
+ * });
665
+ * ```
666
+ *
667
+ * @param args The test case
668
+ */
669
+ test.only = function itOnly(...args) {
670
+ it.only(...args);
671
+ };
672
+ /**
673
+ * Ignore this test case.
674
+ *
675
+ * @example Usage
676
+ * ```ts
677
+ * import { describe, test } from "@std/testing/bdd";
678
+ * import { assertEquals } from "@std/assert";
679
+ *
680
+ * describe("example", () => {
681
+ * test("should pass", () => {
682
+ * assertEquals(2 + 2, 4);
683
+ * });
684
+ *
685
+ * test.ignore("should pass too", () => {
686
+ * assertEquals(3 + 4, 7);
687
+ * });
688
+ * });
689
+ * ```
690
+ *
691
+ * @param args The test case
692
+ */
693
+ test.ignore = function itIgnore(...args) {
694
+ it.ignore(...args);
695
+ };
696
+ /** Skip this test case.
697
+ *
698
+ * @example Usage
699
+ * ```ts
700
+ * import { describe, test } from "@std/testing/bdd";
701
+ * import { assertEquals } from "@std/assert";
702
+ *
703
+ * describe("example", () => {
704
+ * test("should pass", () => {
705
+ * assertEquals(2 + 2, 4);
706
+ * });
707
+ *
708
+ * test.skip("should pass too", () => {
709
+ * assertEquals(3 + 4, 7);
710
+ * });
711
+ * });
712
+ * ```
713
+ *
714
+ * @param args The test case
715
+ */
716
+ test.skip = function itSkip(...args) {
717
+ it.ignore(...args);
718
+ };
719
+ function addHook(name, fn) {
720
+ if (!_test_suite_js_1.TestSuiteInternal.current) {
721
+ if (_test_suite_js_1.TestSuiteInternal.started) {
722
+ throw new Error("Cannot add global hooks after a global test is registered");
723
+ }
724
+ _test_suite_js_1.TestSuiteInternal.current = new _test_suite_js_1.TestSuiteInternal({
725
+ name: "global",
726
+ [name]: fn,
727
+ });
728
+ }
729
+ else {
730
+ _test_suite_js_1.TestSuiteInternal.setHook(_test_suite_js_1.TestSuiteInternal.current, name, fn);
731
+ }
732
+ }
733
+ /**
734
+ * Run some shared setup before all of the tests in the group.
735
+ * Useful for async setup in `describe` blocks. Outside them,
736
+ * top-level initialization code should be used instead.
737
+ *
738
+ * @example Usage
739
+ * ```ts
740
+ * import { describe, it, beforeAll } from "@std/testing/bdd";
741
+ * import { assertEquals } from "@std/assert";
742
+ *
743
+ * beforeAll(() => {
744
+ * console.log("beforeAll");
745
+ * });
746
+ *
747
+ * describe("example", () => {
748
+ * it("should pass", () => {
749
+ * // test case
750
+ * assertEquals(2 + 2, 4);
751
+ * });
752
+ * });
753
+ * ```
754
+ *
755
+ * @typeParam T The self type of the function
756
+ * @param fn The function to implement the setup behavior.
757
+ */
758
+ function beforeAll(fn) {
759
+ addHook("beforeAll", fn);
760
+ }
761
+ /**
762
+ * Alias of {@linkcode beforeAll}
763
+ *
764
+ * Run some shared setup before all of the tests in the suite.
765
+ *
766
+ * @example Usage
767
+ * ```ts
768
+ * import { describe, it, before } from "@std/testing/bdd";
769
+ * import { assertEquals } from "@std/assert";
770
+ *
771
+ * before(() => {
772
+ * console.log("before");
773
+ * });
774
+ *
775
+ * describe("example", () => {
776
+ * it("should pass", () => {
777
+ * // test case
778
+ * assertEquals(2 + 2, 4);
779
+ * });
780
+ * });
781
+ * ```
782
+ *
783
+ * @typeParam T The self type of the function
784
+ * @param fn The function to implement the setup behavior.
785
+ */
786
+ function before(fn) {
787
+ beforeAll(fn);
788
+ }
789
+ /**
790
+ * Run some shared teardown after all of the tests in the suite.
791
+ *
792
+ * @example Usage
793
+ * ```ts
794
+ * import { describe, it, afterAll } from "@std/testing/bdd";
795
+ * import { assertEquals } from "@std/assert";
796
+ *
797
+ * afterAll(() => {
798
+ * console.log("afterAll");
799
+ * });
800
+ *
801
+ * describe("example", () => {
802
+ * it("should pass", () => {
803
+ * // test case
804
+ * assertEquals(2 + 2, 4);
805
+ * });
806
+ * });
807
+ * ```
808
+ *
809
+ * @typeParam T The self type of the function
810
+ * @param fn The function to implement the teardown behavior.
811
+ */
812
+ function afterAll(fn) {
813
+ addHook("afterAll", fn);
814
+ }
815
+ /**
816
+ * Alias of {@linkcode afterAll}.
817
+ *
818
+ * Run some shared teardown after all of the tests in the suite.
819
+ *
820
+ * @example Usage
821
+ * ```ts
822
+ * import { describe, it, after } from "@std/testing/bdd";
823
+ * import { assertEquals } from "@std/assert";
824
+ *
825
+ * after(() => {
826
+ * console.log("after");
827
+ * });
828
+ *
829
+ * describe("example", () => {
830
+ * it("should pass", () => {
831
+ * // test case
832
+ * assertEquals(2 + 2, 4);
833
+ * });
834
+ * });
835
+ * ```
836
+ *
837
+ * @typeParam T The self type of the function
838
+ * @param fn The function to implement the teardown behavior.
839
+ */
840
+ function after(fn) {
841
+ afterAll(fn);
842
+ }
843
+ /**
844
+ * Run some shared setup before each test in the suite.
845
+ *
846
+ * @example Usage
847
+ * ```ts
848
+ * import { describe, it, beforeEach } from "@std/testing/bdd";
849
+ * import { assertEquals } from "@std/assert";
850
+ *
851
+ * beforeEach(() => {
852
+ * console.log("beforeEach");
853
+ * });
854
+ *
855
+ * describe("example", () => {
856
+ * it("should pass", () => {
857
+ * // test case
858
+ * assertEquals(2 + 2, 4);
859
+ * });
860
+ * });
861
+ * ```
862
+ *
863
+ * @typeParam T The self type of the function
864
+ * @param fn The function to implement the shared setup behavior
865
+ */
866
+ function beforeEach(fn) {
867
+ addHook("beforeEach", fn);
868
+ }
869
+ /**
870
+ * Run some shared teardown after each test in the suite.
871
+ *
872
+ * @example Usage
873
+ * ```ts
874
+ * import { describe, it, afterEach } from "@std/testing/bdd";
875
+ * import { assertEquals } from "@std/assert";
876
+ *
877
+ * afterEach(() => {
878
+ * console.log("afterEach");
879
+ * });
880
+ *
881
+ * describe("example", () => {
882
+ * it("should pass", () => {
883
+ * // test case
884
+ * assertEquals(2 + 2, 4);
885
+ * });
886
+ * });
887
+ * ```
888
+ *
889
+ * @typeParam T The self type of the function
890
+ * @param fn The function to implement the shared teardown behavior
891
+ */
892
+ function afterEach(fn) {
893
+ addHook("afterEach", fn);
894
+ }
895
+ /** Generates a DescribeDefinition from DescribeArgs. */
896
+ function describeDefinition(...args) {
897
+ let [suiteOptionsOrNameOrFn, optionsOrNameOrFn, optionsOrFn, fn,] = args;
898
+ let suite = undefined;
899
+ let name;
900
+ let options;
901
+ if (typeof suiteOptionsOrNameOrFn === "object" &&
902
+ typeof suiteOptionsOrNameOrFn.symbol === "symbol") {
903
+ suite = suiteOptionsOrNameOrFn;
904
+ }
905
+ else {
906
+ fn = optionsOrFn;
907
+ optionsOrFn = optionsOrNameOrFn;
908
+ optionsOrNameOrFn = suiteOptionsOrNameOrFn;
909
+ }
910
+ if (typeof optionsOrNameOrFn === "string") {
911
+ name = optionsOrNameOrFn;
912
+ if (typeof optionsOrFn === "function") {
913
+ fn = optionsOrFn;
914
+ options = {};
915
+ }
916
+ else {
917
+ options = optionsOrFn ?? {};
918
+ if (fn === undefined) {
919
+ fn = options.fn;
920
+ }
921
+ }
922
+ }
923
+ else if (typeof optionsOrNameOrFn === "function") {
924
+ fn = optionsOrNameOrFn;
925
+ name = fn.name;
926
+ options = {};
927
+ }
928
+ else {
929
+ options = optionsOrNameOrFn ?? {};
930
+ if (typeof optionsOrFn === "function") {
931
+ fn = optionsOrFn;
932
+ }
933
+ else {
934
+ fn = options.fn;
935
+ }
936
+ name = options.name ?? fn?.name ?? "";
937
+ }
938
+ if (suite === undefined) {
939
+ suite = options.suite;
940
+ }
941
+ if (suite === undefined && _test_suite_js_1.TestSuiteInternal.current) {
942
+ const { symbol } = _test_suite_js_1.TestSuiteInternal.current;
943
+ suite = { symbol };
944
+ }
945
+ return {
946
+ ...options,
947
+ suite: suite,
948
+ name,
949
+ fn: fn,
950
+ };
951
+ }
952
+ /**
953
+ * Registers a test suite.
954
+ *
955
+ * @example Usage
956
+ * ```ts
957
+ * import { describe, it } from "@std/testing/bdd";
958
+ * import { assertEquals } from "@std/assert";
959
+ *
960
+ * describe("example", () => {
961
+ * it("should pass", () => {
962
+ * // test case
963
+ * assertEquals(2 + 2, 4);
964
+ * });
965
+ * });
966
+ * ```
967
+ *
968
+ * @typeParam T The self type of the test suite body.
969
+ * @param args The test suite body.
970
+ * @returns The test suite
971
+ */
972
+ function describe(...args) {
973
+ if (_test_suite_js_1.TestSuiteInternal.runningCount > 0) {
974
+ throw new Error("Cannot register new test suites after already registered test cases start running");
975
+ }
976
+ const options = describeDefinition(...args);
977
+ if (!_test_suite_js_1.TestSuiteInternal.started)
978
+ _test_suite_js_1.TestSuiteInternal.started = true;
979
+ const { symbol } = new _test_suite_js_1.TestSuiteInternal(options);
980
+ return { symbol };
981
+ }
982
+ /**
983
+ * Only execute this test suite.
984
+ *
985
+ * @example Usage
986
+ * ```ts
987
+ * import { describe, it, beforeAll } from "@std/testing/bdd";
988
+ * import { assertEquals } from "@std/assert";
989
+ *
990
+ * describe("example", () => {
991
+ * it("should pass", () => {
992
+ * assertEquals(2 + 2, 4);
993
+ * });
994
+ * });
995
+ *
996
+ * // Only this test suite will run
997
+ * describe.only("example 2", () => {
998
+ * it("should pass too", () => {
999
+ * assertEquals(3 + 4, 7);
1000
+ * });
1001
+ * });
1002
+ * ```
1003
+ *
1004
+ * @param args The test suite body
1005
+ */
1006
+ describe.only = function describeOnly(...args) {
1007
+ const options = describeDefinition(...args);
1008
+ return describe({
1009
+ ...options,
1010
+ only: true,
1011
+ });
1012
+ };
1013
+ /**
1014
+ * Ignore the test suite.
1015
+ *
1016
+ * @example Usage
1017
+ * ```ts
1018
+ * import { describe, it, beforeAll } from "@std/testing/bdd";
1019
+ * import { assertEquals } from "@std/assert";
1020
+ *
1021
+ * describe("example", () => {
1022
+ * it("should pass", () => {
1023
+ * assertEquals(2 + 2, 4);
1024
+ * });
1025
+ * });
1026
+ *
1027
+ * describe.ignore("example 2", () => {
1028
+ * it("should pass too", () => {
1029
+ * assertEquals(3 + 4, 7);
1030
+ * });
1031
+ * });
1032
+ * ```
1033
+ *
1034
+ * @param args The test suite body
1035
+ */
1036
+ describe.ignore = function describeIgnore(...args) {
1037
+ const options = describeDefinition(...args);
1038
+ return describe({
1039
+ ...options,
1040
+ ignore: true,
1041
+ });
1042
+ };
1043
+ /**
1044
+ * Skip the test suite.
1045
+ *
1046
+ * @example Usage
1047
+ * ```ts
1048
+ * import { describe, it, beforeAll } from "@std/testing/bdd";
1049
+ * import { assertEquals } from "@std/assert";
1050
+ *
1051
+ * describe("example", () => {
1052
+ * it("should pass", () => {
1053
+ * assertEquals(2 + 2, 4);
1054
+ * });
1055
+ * });
1056
+ *
1057
+ * describe.skip("example 2", () => {
1058
+ * it("should pass too", () => {
1059
+ * assertEquals(3 + 4, 7);
1060
+ * });
1061
+ * });
1062
+ * ```
1063
+ *
1064
+ * @param args The test suite body
1065
+ */
1066
+ describe.skip = function describeSkip(...args) {
1067
+ return describe.ignore(...args);
1068
+ };