xunit.ts 2.0.0 → 3.0.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 (210) hide show
  1. package/README.md +25 -2
  2. package/cli.ts +9 -4
  3. package/dist/cli.js +4 -4
  4. package/dist/cli.js.map +1 -1
  5. package/dist/eslint.config.d.ts +3 -0
  6. package/dist/eslint.config.d.ts.map +1 -0
  7. package/dist/eslint.config.js +46 -0
  8. package/dist/eslint.config.js.map +1 -0
  9. package/dist/src/Assertions/Contains.d.ts +1 -1
  10. package/dist/src/Assertions/Contains.d.ts.map +1 -1
  11. package/dist/src/Assertions/Contains.js +2 -2
  12. package/dist/src/Assertions/Contains.js.map +1 -1
  13. package/dist/src/Assertions/Count.d.ts +1 -1
  14. package/dist/src/Assertions/Count.d.ts.map +1 -1
  15. package/dist/src/Assertions/Count.js +2 -2
  16. package/dist/src/Assertions/Count.js.map +1 -1
  17. package/dist/src/Assertions/Defined.d.ts +1 -1
  18. package/dist/src/Assertions/Defined.d.ts.map +1 -1
  19. package/dist/src/Assertions/Defined.js +2 -2
  20. package/dist/src/Assertions/Defined.js.map +1 -1
  21. package/dist/src/Assertions/DoesNotContain.d.ts +1 -1
  22. package/dist/src/Assertions/DoesNotContain.d.ts.map +1 -1
  23. package/dist/src/Assertions/DoesNotContain.js +2 -2
  24. package/dist/src/Assertions/DoesNotContain.js.map +1 -1
  25. package/dist/src/Assertions/DoesNotThrow.d.ts +1 -1
  26. package/dist/src/Assertions/DoesNotThrow.d.ts.map +1 -1
  27. package/dist/src/Assertions/DoesNotThrow.js +2 -2
  28. package/dist/src/Assertions/DoesNotThrow.js.map +1 -1
  29. package/dist/src/Assertions/Empty.d.ts +1 -1
  30. package/dist/src/Assertions/Empty.d.ts.map +1 -1
  31. package/dist/src/Assertions/Empty.js +2 -2
  32. package/dist/src/Assertions/Empty.js.map +1 -1
  33. package/dist/src/Assertions/Equal.d.ts +1 -1
  34. package/dist/src/Assertions/Equal.d.ts.map +1 -1
  35. package/dist/src/Assertions/Equal.js +2 -2
  36. package/dist/src/Assertions/Equal.js.map +1 -1
  37. package/dist/src/Assertions/False.d.ts +1 -1
  38. package/dist/src/Assertions/False.d.ts.map +1 -1
  39. package/dist/src/Assertions/False.js +2 -2
  40. package/dist/src/Assertions/False.js.map +1 -1
  41. package/dist/src/Assertions/InstanceOf.d.ts +1 -1
  42. package/dist/src/Assertions/InstanceOf.d.ts.map +1 -1
  43. package/dist/src/Assertions/InstanceOf.js +2 -2
  44. package/dist/src/Assertions/InstanceOf.js.map +1 -1
  45. package/dist/src/Assertions/NotEmpty.d.ts +1 -1
  46. package/dist/src/Assertions/NotEmpty.d.ts.map +1 -1
  47. package/dist/src/Assertions/NotEmpty.js +2 -2
  48. package/dist/src/Assertions/NotEmpty.js.map +1 -1
  49. package/dist/src/Assertions/NotEqual.d.ts +1 -1
  50. package/dist/src/Assertions/NotEqual.d.ts.map +1 -1
  51. package/dist/src/Assertions/NotEqual.js +2 -2
  52. package/dist/src/Assertions/NotEqual.js.map +1 -1
  53. package/dist/src/Assertions/NotNull.d.ts +1 -1
  54. package/dist/src/Assertions/NotNull.d.ts.map +1 -1
  55. package/dist/src/Assertions/NotNull.js +2 -2
  56. package/dist/src/Assertions/NotNull.js.map +1 -1
  57. package/dist/src/Assertions/Null.d.ts +1 -1
  58. package/dist/src/Assertions/Null.d.ts.map +1 -1
  59. package/dist/src/Assertions/Null.js +2 -2
  60. package/dist/src/Assertions/Null.js.map +1 -1
  61. package/dist/src/Assertions/StringContains.js +3 -3
  62. package/dist/src/Assertions/StringContains.js.map +1 -1
  63. package/dist/src/Assertions/StringDoesNotContain.js +3 -3
  64. package/dist/src/Assertions/StringDoesNotContain.js.map +1 -1
  65. package/dist/src/Assertions/StringDoesNotEndWith.d.ts.map +1 -1
  66. package/dist/src/Assertions/StringDoesNotEndWith.js +3 -5
  67. package/dist/src/Assertions/StringDoesNotEndWith.js.map +1 -1
  68. package/dist/src/Assertions/StringDoesNotMatch.d.ts +1 -1
  69. package/dist/src/Assertions/StringDoesNotMatch.d.ts.map +1 -1
  70. package/dist/src/Assertions/StringDoesNotMatch.js +2 -2
  71. package/dist/src/Assertions/StringDoesNotMatch.js.map +1 -1
  72. package/dist/src/Assertions/StringDoesNotStartWith.js +2 -2
  73. package/dist/src/Assertions/StringDoesNotStartWith.js.map +1 -1
  74. package/dist/src/Assertions/StringEndsWith.d.ts.map +1 -1
  75. package/dist/src/Assertions/StringEndsWith.js +3 -5
  76. package/dist/src/Assertions/StringEndsWith.js.map +1 -1
  77. package/dist/src/Assertions/StringMatches.d.ts +1 -1
  78. package/dist/src/Assertions/StringMatches.d.ts.map +1 -1
  79. package/dist/src/Assertions/StringMatches.js +2 -2
  80. package/dist/src/Assertions/StringMatches.js.map +1 -1
  81. package/dist/src/Assertions/StringStartsWith.js +2 -2
  82. package/dist/src/Assertions/StringStartsWith.js.map +1 -1
  83. package/dist/src/Assertions/Throws.d.ts +1 -1
  84. package/dist/src/Assertions/Throws.d.ts.map +1 -1
  85. package/dist/src/Assertions/Throws.js +3 -3
  86. package/dist/src/Assertions/Throws.js.map +1 -1
  87. package/dist/src/Assertions/True.d.ts +1 -1
  88. package/dist/src/Assertions/True.d.ts.map +1 -1
  89. package/dist/src/Assertions/True.js +2 -2
  90. package/dist/src/Assertions/True.js.map +1 -1
  91. package/dist/src/Assertions/Undefined.d.ts +1 -1
  92. package/dist/src/Assertions/Undefined.d.ts.map +1 -1
  93. package/dist/src/Assertions/Undefined.js +2 -2
  94. package/dist/src/Assertions/Undefined.js.map +1 -1
  95. package/dist/src/Assertions/index.d.ts +15 -15
  96. package/dist/src/Assertions/index.d.ts.map +1 -1
  97. package/dist/src/Assertions/index.js +15 -15
  98. package/dist/src/Assertions/index.js.map +1 -1
  99. package/dist/src/CLI.d.ts +1 -1
  100. package/dist/src/CLI.d.ts.map +1 -1
  101. package/dist/src/CLI.js +7 -6
  102. package/dist/src/CLI.js.map +1 -1
  103. package/dist/src/Factory.d.ts +1 -1
  104. package/dist/src/Factory.d.ts.map +1 -1
  105. package/dist/src/Factory.js +7 -7
  106. package/dist/src/Factory.js.map +1 -1
  107. package/dist/src/Framework/Test.d.ts +1 -1
  108. package/dist/src/Framework/Test.d.ts.map +1 -1
  109. package/dist/src/Framework/Test.js.map +1 -1
  110. package/dist/src/Framework/TestInfo.d.ts +5 -1
  111. package/dist/src/Framework/TestInfo.d.ts.map +1 -1
  112. package/dist/src/Framework/TestName.js +2 -2
  113. package/dist/src/Framework/TestName.js.map +1 -1
  114. package/dist/src/Framework/TestSuite.d.ts +2 -2
  115. package/dist/src/Framework/TestSuite.d.ts.map +1 -1
  116. package/dist/src/Framework/TestSuite.js +7 -6
  117. package/dist/src/Framework/TestSuite.js.map +1 -1
  118. package/dist/src/IO/FileSystem.d.ts +1 -1
  119. package/dist/src/IO/FileSystem.d.ts.map +1 -1
  120. package/dist/src/IO/FileSystem.js +4 -4
  121. package/dist/src/IO/FileSystem.js.map +1 -1
  122. package/dist/src/IO/Output.d.ts +1 -1
  123. package/dist/src/IO/Output.d.ts.map +1 -1
  124. package/dist/src/Reporters/ConsoleReporter.d.ts +4 -4
  125. package/dist/src/Reporters/ConsoleReporter.d.ts.map +1 -1
  126. package/dist/src/Reporters/ConsoleReporter.js +39 -28
  127. package/dist/src/Reporters/ConsoleReporter.js.map +1 -1
  128. package/dist/src/Reporters/FileReporter.d.ts +4 -4
  129. package/dist/src/Reporters/FileReporter.d.ts.map +1 -1
  130. package/dist/src/Reporters/FileReporter.js +0 -1
  131. package/dist/src/Reporters/FileReporter.js.map +1 -1
  132. package/dist/src/Reporters/JUnitReporter.d.ts.map +1 -1
  133. package/dist/src/Reporters/JUnitReporter.js +1 -1
  134. package/dist/src/Reporters/JUnitReporter.js.map +1 -1
  135. package/dist/src/Reporters/ResultReporter.d.ts +2 -2
  136. package/dist/src/Reporters/ResultReporter.d.ts.map +1 -1
  137. package/dist/src/Reporters/ResultReporter.js +1 -0
  138. package/dist/src/Reporters/ResultReporter.js.map +1 -1
  139. package/dist/src/Reporters/SonarReporter.d.ts.map +1 -1
  140. package/dist/src/Reporters/SonarReporter.js +2 -2
  141. package/dist/src/Reporters/SonarReporter.js.map +1 -1
  142. package/dist/src/Reporters/XMLReporter.d.ts +1 -1
  143. package/dist/src/Reporters/XMLReporter.d.ts.map +1 -1
  144. package/dist/src/Reporters/XMLReporter.js.map +1 -1
  145. package/dist/src/Runners/Runner.d.ts +3 -3
  146. package/dist/src/Runners/Runner.d.ts.map +1 -1
  147. package/dist/src/Runners/Runner.js +1 -1
  148. package/dist/src/Runners/Runner.js.map +1 -1
  149. package/dist/src/Runners/TestRunner.d.ts +4 -2
  150. package/dist/src/Runners/TestRunner.d.ts.map +1 -1
  151. package/dist/src/Runners/TestRunner.js +13 -8
  152. package/dist/src/Runners/TestRunner.js.map +1 -1
  153. package/dist/src/Runners/TestSuiteLoader.d.ts.map +1 -1
  154. package/dist/src/Runners/TestSuiteLoader.js +15 -11
  155. package/dist/src/Runners/TestSuiteLoader.js.map +1 -1
  156. package/dist/src/Runners/TestSuiteRunner.d.ts +4 -4
  157. package/dist/src/Runners/TestSuiteRunner.d.ts.map +1 -1
  158. package/dist/src/Runners/TestSuiteRunner.js +3 -3
  159. package/dist/src/Runners/TestSuiteRunner.js.map +1 -1
  160. package/dist/xunit.d.ts +2 -2
  161. package/dist/xunit.d.ts.map +1 -1
  162. package/dist/xunit.js +3 -3
  163. package/dist/xunit.js.map +1 -1
  164. package/eslint.config.ts +44 -0
  165. package/package.json +13 -9
  166. package/src/Assertions/Contains.ts +2 -2
  167. package/src/Assertions/Count.ts +2 -2
  168. package/src/Assertions/Defined.ts +2 -2
  169. package/src/Assertions/DoesNotContain.ts +2 -2
  170. package/src/Assertions/DoesNotThrow.ts +2 -2
  171. package/src/Assertions/Empty.ts +2 -2
  172. package/src/Assertions/Equal.ts +3 -2
  173. package/src/Assertions/False.ts +2 -2
  174. package/src/Assertions/InstanceOf.ts +2 -2
  175. package/src/Assertions/NotEmpty.ts +2 -2
  176. package/src/Assertions/NotEqual.ts +3 -2
  177. package/src/Assertions/NotNull.ts +2 -2
  178. package/src/Assertions/Null.ts +2 -2
  179. package/src/Assertions/StringContains.ts +2 -2
  180. package/src/Assertions/StringDoesNotContain.ts +2 -2
  181. package/src/Assertions/StringDoesNotEndWith.ts +2 -4
  182. package/src/Assertions/StringDoesNotMatch.ts +2 -2
  183. package/src/Assertions/StringDoesNotStartWith.ts +1 -1
  184. package/src/Assertions/StringEndsWith.ts +2 -4
  185. package/src/Assertions/StringMatches.ts +2 -2
  186. package/src/Assertions/StringStartsWith.ts +1 -1
  187. package/src/Assertions/Throws.ts +3 -3
  188. package/src/Assertions/True.ts +2 -2
  189. package/src/Assertions/Undefined.ts +2 -2
  190. package/src/Assertions/index.ts +15 -27
  191. package/src/CLI.ts +9 -6
  192. package/src/Factory.ts +11 -9
  193. package/src/Framework/Test.ts +1 -1
  194. package/src/Framework/TestInfo.ts +7 -1
  195. package/src/Framework/TestName.ts +2 -2
  196. package/src/Framework/TestSuite.ts +10 -8
  197. package/src/IO/FileSystem.ts +4 -4
  198. package/src/IO/Output.ts +1 -1
  199. package/src/Reporters/ConsoleReporter.ts +13 -11
  200. package/src/Reporters/FileReporter.ts +7 -5
  201. package/src/Reporters/JUnitReporter.ts +3 -2
  202. package/src/Reporters/ResultReporter.ts +4 -3
  203. package/src/Reporters/SonarReporter.ts +4 -2
  204. package/src/Reporters/XMLReporter.ts +2 -2
  205. package/src/Runners/Runner.ts +5 -5
  206. package/src/Runners/TestRunner.ts +19 -11
  207. package/src/Runners/TestSuiteLoader.ts +14 -7
  208. package/src/Runners/TestSuiteRunner.ts +7 -7
  209. package/tsconfig.json +3 -0
  210. package/xunit.ts +3 -4
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string contains a given substring
@@ -16,7 +16,7 @@ import { AssertionError } from "assert";
16
16
  * this.assert.stringContains(needle, haystack);
17
17
  */
18
18
  export default function StringContains(needle: string, haystack: string | null, message?: string) {
19
- if (haystack !== undefined && haystack !== null && haystack.indexOf(needle) > -1) {
19
+ if (haystack?.includes(needle)) {
20
20
  return;
21
21
  }
22
22
 
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string does not contain a given substring
@@ -16,7 +16,7 @@ import { AssertionError } from "assert";
16
16
  * this.assert.stringDoesNotContain(needle, haystack);
17
17
  */
18
18
  export default function StringDoesNotContain(needle: string, haystack: string | null, message?: string) {
19
- if (haystack === undefined || haystack === null || haystack.indexOf(needle) === -1) {
19
+ if (!haystack?.includes(needle)) {
20
20
  return;
21
21
  }
22
22
 
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string does not end with a given substring
@@ -16,9 +16,7 @@ import { AssertionError } from "assert";
16
16
  * this.assert.stringDoesNotEndWith(needle, haystack);
17
17
  */
18
18
  export default function StringDoesNotEndWith(needle: string, haystack: string | null, message?: string) {
19
- if (haystack === undefined || haystack === null
20
- || haystack.indexOf(needle) === -1
21
- || haystack.indexOf(needle) !== haystack.length - needle.length) {
19
+ if (!haystack?.endsWith(needle)) {
22
20
  return;
23
21
  }
24
22
 
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string does not match a given regular expression
@@ -15,7 +15,7 @@ import { AssertionError } from "assert";
15
15
  * @example
16
16
  * this.assert.stringDoesNotMatch(regex, haystack);
17
17
  */
18
- export default function StringDoesNotMatch(regex: RegExp, haystack: string | null, message?: string) {
18
+ export default function StringDoesNotMatch(regex: RegExp, haystack?: string | null, message?: string) {
19
19
  if (haystack === undefined || haystack === null || !regex.test(haystack)) {
20
20
  return;
21
21
  }
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string does not begin with a given substring
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string ends with a given substring
@@ -16,9 +16,7 @@ import { AssertionError } from "assert";
16
16
  * this.assert.stringEndsWith(needle, haystack);
17
17
  */
18
18
  export default function StringEndsWith(needle: string, haystack: string | null, message?: string) {
19
- if (haystack !== undefined && haystack !== null
20
- && haystack.indexOf(needle) > -1
21
- && haystack.indexOf(needle) === haystack.length - needle.length) {
19
+ if (haystack?.endsWith(needle)) {
22
20
  return;
23
21
  }
24
22
 
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string matches a given regular expression
@@ -15,7 +15,7 @@ import { AssertionError } from "assert";
15
15
  * @example
16
16
  * this.assert.stringMatches(regex, haystack);
17
17
  */
18
- export default function StringMatches(regex: RegExp, haystack: string | null, message?: string) {
18
+ export default function StringMatches(regex: RegExp, haystack?: string | null, message?: string) {
19
19
  if (haystack !== undefined && haystack !== null && regex.test(haystack)) {
20
20
  return;
21
21
  }
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a string begins with a given substring
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that an expression throws an error/exception
@@ -14,10 +14,10 @@ import { AssertionError } from "assert";
14
14
  * @example
15
15
  * this.assert.throws(() => expression);
16
16
  */
17
- export default function Throws(expression: () => any, message?: string) {
17
+ export default function Throws(expression: () => unknown, message?: string) {
18
18
  try {
19
19
  expression();
20
- } catch (exception) {
20
+ } catch {
21
21
  return;
22
22
  }
23
23
 
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a given expression evaluates to `true`
@@ -14,7 +14,7 @@ import { AssertionError } from "assert";
14
14
  * @example
15
15
  * this.assert.true(expression);
16
16
  */
17
- export default function True(expression: any, message?: string) {
17
+ export default function True(expression: unknown, message?: string) {
18
18
  if (expression === true) {
19
19
  return;
20
20
  }
@@ -1,4 +1,4 @@
1
- import { AssertionError } from "assert";
1
+ import { AssertionError } from "node:assert";
2
2
 
3
3
  /**
4
4
  * Asserts that a given value is equal to `undefined`
@@ -14,7 +14,7 @@ import { AssertionError } from "assert";
14
14
  * @example
15
15
  * this.assert.undefined(expression);
16
16
  */
17
- export default function Undefined(expression: any, message?: string) {
17
+ export default function Undefined(expression: unknown, message?: string) {
18
18
  if (expression === undefined) {
19
19
  return;
20
20
  }
@@ -1,39 +1,27 @@
1
- import is_true from "./True";
2
- import is_false from "./False";
3
-
4
- import is_undefined from "./Undefined";
1
+ import contains from "./Contains";
2
+ import count from "./Count";
5
3
  import is_defined from "./Defined";
6
-
7
- import is_null from "./Null";
8
- import not_null from "./NotNull";
9
-
10
- import equal from "./Equal";
11
- import not_equal from "./NotEqual";
12
-
4
+ import not_contains from "./DoesNotContain";
5
+ import does_not_throw from "./DoesNotThrow";
13
6
  import empty from "./Empty";
7
+ import equal from "./Equal";
8
+ import is_false from "./False";
9
+ import instance_of from "./InstanceOf";
14
10
  import not_empty from "./NotEmpty";
15
-
16
- import count from "./Count";
17
-
18
- import contains from "./Contains";
19
- import not_contains from "./DoesNotContain";
20
-
11
+ import not_equal from "./NotEqual";
12
+ import not_null from "./NotNull";
13
+ import is_null from "./Null";
21
14
  import string_contains from "./StringContains";
22
15
  import string_not_contains from "./StringDoesNotContain";
23
-
24
- import string_starts from "./StringStartsWith";
16
+ import string_not_ends from "./StringDoesNotEndWith";
17
+ import string_not_matches from "./StringDoesNotMatch";
25
18
  import string_not_starts from "./StringDoesNotStartWith";
26
-
27
19
  import string_ends from "./StringEndsWith";
28
- import string_not_ends from "./StringDoesNotEndWith";
29
-
30
20
  import string_matches from "./StringMatches";
31
- import string_not_matches from "./StringDoesNotMatch";
32
-
33
- import instance_of from "./InstanceOf";
34
-
21
+ import string_starts from "./StringStartsWith";
35
22
  import throws from "./Throws";
36
- import does_not_throw from "./DoesNotThrow";
23
+ import is_true from "./True";
24
+ import is_undefined from "./Undefined";
37
25
 
38
26
  export default new class AssertionLibrary {
39
27
  true = is_true;
package/src/CLI.ts CHANGED
@@ -1,10 +1,12 @@
1
- import Usage from "command-line-usage";
2
- import JUnitReporter from "./Reporters/JUnitReporter";
3
- import Process from "process";
1
+ import Process from "node:process";
2
+
4
3
  import Args from "command-line-args";
4
+ import Usage from "command-line-usage";
5
5
  import SafeRegex from "lodash.escaperegexp";
6
- import Runner from "./Runners/Runner";
6
+
7
+ import JUnitReporter from "./Reporters/JUnitReporter";
7
8
  import SonarReporter from "./Reporters/SonarReporter";
9
+ import Runner from "./Runners/Runner";
8
10
 
9
11
  export default class CLI {
10
12
  private static readonly options: Usage.OptionDefinition[] = [
@@ -97,9 +99,10 @@ export default class CLI {
97
99
  const runner = this.runnerFactory(args);
98
100
 
99
101
  try {
100
- const filters: string[] = args.filter ?? [];
102
+ const argFilter = args.filter as string[] | undefined;
103
+ const filters: string[] = argFilter ?? [];
101
104
  const regexFilters = filters.map((f: string) => new RegExp(SafeRegex(f)));
102
- const results = await runner.runAll(args.dir, regexFilters);
105
+ const results = await runner.runAll(args.dir as string, regexFilters);
103
106
  return Runner.allTestsPassed(results);
104
107
  } catch (error) {
105
108
  if (error instanceof Error) {
package/src/Factory.ts CHANGED
@@ -1,15 +1,17 @@
1
+ import fs from "node:fs/promises";
2
+
1
3
  import Args from "command-line-args";
2
- import ConsoleReporter from "./Reporters/ConsoleReporter";
4
+
3
5
  import FileSystem from "./IO/FileSystem";
4
- import JUnitReporter from "./Reporters/JUnitReporter";
5
6
  import Output from "./IO/Output";
7
+ import ConsoleReporter from "./Reporters/ConsoleReporter";
8
+ import JUnitReporter from "./Reporters/JUnitReporter";
6
9
  import ResultReporter from "./Reporters/ResultReporter";
10
+ import SonarReporter from "./Reporters/SonarReporter";
7
11
  import Runner from "./Runners/Runner";
8
12
  import TestRunner from "./Runners/TestRunner";
9
13
  import TestSuiteLoader from "./Runners/TestSuiteLoader";
10
14
  import TestSuiteRunner from "./Runners/TestSuiteRunner";
11
- import fs from "fs/promises";
12
- import SonarReporter from "./Reporters/SonarReporter";
13
15
 
14
16
  export default class Factory {
15
17
  static readonly file_system = new FileSystem(fs);
@@ -23,11 +25,11 @@ export default class Factory {
23
25
  return new Runner(loader, test_suite_runner, reporters);
24
26
  }
25
27
 
26
- static Reporters(args: Args.CommandLineOptions): ReadonlyArray<ResultReporter> {
28
+ static Reporters(args: Args.CommandLineOptions): readonly ResultReporter[] {
27
29
  return [
28
- !args.quiet ? new ConsoleReporter(new Output(process.stdout)) : null,
29
- args.junit !== undefined ? new JUnitReporter(Factory.file_system, args.junit ?? JUnitReporter.defaultFileName) : null,
30
- args.sonar !== undefined ? new SonarReporter(Factory.file_system, args.sonar ?? SonarReporter.defaultFileName) : null
31
- ].filter(r => r !== null) as ResultReporter[];
30
+ args.quiet ? null : new ConsoleReporter(new Output(process.stdout)),
31
+ args.junit === undefined ? null : new JUnitReporter(Factory.file_system, args.junit as string | undefined ?? JUnitReporter.defaultFileName),
32
+ args.sonar === undefined ? null : new SonarReporter(Factory.file_system, args.sonar as string | undefined ?? SonarReporter.defaultFileName)
33
+ ].filter(r => r !== null);
32
34
  }
33
35
  }
@@ -1,6 +1,6 @@
1
- import TestSuite from "./TestSuite";
2
1
  import TestInfo from "./TestInfo";
3
2
  import TestName from "./TestName";
3
+ import TestSuite from "./TestSuite";
4
4
 
5
5
  /**
6
6
  * Annotates a test method within a {@link TestSuite}
@@ -1,2 +1,8 @@
1
- type TestInfo = TypedPropertyDescriptor<() => Promise<void>>;
1
+ type AsyncTest = () => Promise<void>;
2
+ type SyncTest = () => void;
3
+
4
+ export type AsyncTestInfo = TypedPropertyDescriptor<AsyncTest>;
5
+ export type SyncTestInfo = TypedPropertyDescriptor<SyncTest>;
6
+
7
+ type TestInfo = AsyncTestInfo | SyncTestInfo;
2
8
  export default TestInfo;
@@ -1,8 +1,8 @@
1
1
  export default class TestName {
2
2
  static toSentenceCase(test_name: string) {
3
3
  const result = test_name
4
- .replace(/_([A-Z])/gi, (substring: string, match: string) => match.toUpperCase())
5
- .replace(/([A-Z])/g, " $1")
4
+ .replaceAll(/_([A-Z])/gi, (substring: string, match: string) => match.toUpperCase())
5
+ .replaceAll(/([A-Z])/g, " $1")
6
6
  .trim();
7
7
  return result.charAt(0).toUpperCase() + result.slice(1);
8
8
  }
@@ -1,5 +1,5 @@
1
- import TestInfo from "./TestInfo";
2
1
  import AssertionLibrary from "../Assertions";
2
+ import TestInfo from "./TestInfo";
3
3
 
4
4
  /**
5
5
  * Defines a container of tests
@@ -13,12 +13,10 @@ import AssertionLibrary from "../Assertions";
13
13
  export default abstract class TestSuite {
14
14
  assert = AssertionLibrary;
15
15
 
16
- private tests: Record<string, TestInfo> = {};
16
+ private tests?: Record<string, TestInfo> = {};
17
17
 
18
18
  addTest(name: string, info: TestInfo) {
19
- if (this.tests === undefined || this.tests === null) {
20
- this.tests = {};
21
- }
19
+ this.tests ??= {};
22
20
  this.tests[name] = info;
23
21
  }
24
22
 
@@ -33,14 +31,18 @@ export default abstract class TestSuite {
33
31
  }
34
32
 
35
33
  filteredTests(filters: RegExp[]) {
36
- if (!this.tests)
34
+ const tests = this.tests;
35
+ if (tests === undefined)
37
36
  return {};
38
37
 
38
+ const keys = Object.keys(tests)
39
+ .filter(k => filters.map(f => f.test(`${this.constructor.name}.${tests[k].value?.name}`)).some(Boolean));
40
+
39
41
  const filtered: Record<string, TestInfo> = {};
40
- const keys = Object.keys(this.tests).filter(k => filters.map(f => f.test(`${this.constructor.name}.${this.tests[k].value?.name}`)).filter(m => m).length > 0);
41
42
  keys.forEach(k => {
42
- filtered[k] = this.tests[k];
43
+ filtered[k] = tests[k];
43
44
  });
45
+
44
46
  return filtered;
45
47
  }
46
48
  }
@@ -1,5 +1,5 @@
1
- import fs_promises from "fs/promises";
2
- import path from "path";
1
+ import fs_promises from "node:fs/promises";
2
+ import path from "node:path";
3
3
 
4
4
  export default class FileSystem {
5
5
 
@@ -10,7 +10,7 @@ export default class FileSystem {
10
10
 
11
11
  static extension(file: string) {
12
12
  const match = this.matchExtension.exec(file);
13
- return match !== undefined && match !== null && match.length > 1
13
+ return match && match.length > 1
14
14
  ? match[1]
15
15
  : "";
16
16
  }
@@ -27,7 +27,7 @@ export default class FileSystem {
27
27
  : [ item_path ]);
28
28
  }
29
29
  return files;
30
- } catch (e) {
30
+ } catch {
31
31
  return [];
32
32
  }
33
33
  }
package/src/IO/Output.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { WriteStream } from "tty";
1
+ import { WriteStream } from "node:tty";
2
2
 
3
3
  export default class Output {
4
4
 
@@ -1,11 +1,14 @@
1
- import ResultReporter from "./ResultReporter";
2
- import TestSuite from "../Framework/TestSuite";
3
- import Output from "../IO/Output";
4
- import TestName from "../Framework/TestName";
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { AssertionError } from "node:assert";
3
+
5
4
  import colors from "colors";
6
- import { AssertionError } from "assert";
7
- import TestSuiteResults from "../Framework/TestSuiteResults";
5
+
8
6
  import { ResultType } from "../Framework/ResultType";
7
+ import TestName from "../Framework/TestName";
8
+ import TestSuite from "../Framework/TestSuite";
9
+ import TestSuiteResults from "../Framework/TestSuiteResults";
10
+ import Output from "../IO/Output";
11
+ import ResultReporter from "./ResultReporter";
9
12
 
10
13
  export default class ConsoleReporter implements ResultReporter {
11
14
 
@@ -42,11 +45,10 @@ export default class ConsoleReporter implements ResultReporter {
42
45
  testErrored(suite: TestSuite, test_name: string, error: Error, duration: number): void {
43
46
  this.out.write(` (${Math.round(duration)} ms)`);
44
47
  this.out.overwrite(` ${colors.red("✘")}\n`);
45
- this.out.writeLine(` ${error.stack}`);
48
+ this.out.writeLine(` ${error.stack ?? ""}`);
46
49
  this.out.writeLine();
47
50
  }
48
51
 
49
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
52
  testIncomplete(suite: TestSuite, test_name: string): void {
51
53
  this.out.overwrite(` ${colors.yellow("?")}\n`);
52
54
  }
@@ -61,15 +63,15 @@ export default class ConsoleReporter implements ResultReporter {
61
63
  this.out.writeLine();
62
64
  }
63
65
 
64
- runCompleted(suites: Record<string, TestSuiteResults>): void {
66
+ async runCompleted(suites: Record<string, TestSuiteResults>): Promise<void> {
65
67
  const results = Object.values(suites);
66
68
  if (!results.length) {
67
69
  this.out.writeLine("No tests found!");
68
- return;
70
+ return Promise.resolve();
69
71
  }
70
72
 
71
73
  const sum = (result_type?: ResultType) => results
72
- .map((suite_result) => result_type !== undefined ? suite_result.count(result_type) : suite_result.total())
74
+ .map((suite_result) => result_type === undefined ? suite_result.total() : suite_result.count(result_type))
73
75
  .reduce((acc, current) => acc + current, 0);
74
76
 
75
77
  const result = (result_type?: ResultType, color: (string: string) => string = colors.white) => {
@@ -1,11 +1,13 @@
1
- import ResultReporter from "./ResultReporter";
2
- import TestSuiteResults from "../Framework/TestSuiteResults";
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { AssertionError } from "node:assert";
3
+
3
4
  import TestSuite from "../Framework/TestSuite";
4
- import { AssertionError } from "assert";
5
+ import TestSuiteResults from "../Framework/TestSuiteResults";
5
6
  import FileSystem from "../IO/FileSystem";
7
+ import ResultReporter from "./ResultReporter";
6
8
 
7
9
  export default abstract class FileReporter implements ResultReporter {
8
- /* eslint-disable @typescript-eslint/no-unused-vars */
10
+
9
11
  constructor(protected readonly file_system: FileSystem, protected readonly path: string) {
10
12
  }
11
13
 
@@ -41,5 +43,5 @@ export default abstract class FileReporter implements ResultReporter {
41
43
  return;
42
44
  }
43
45
 
44
- abstract runCompleted(results: Record<string, TestSuiteResults>): void;
46
+ abstract runCompleted(results: Record<string, TestSuiteResults>): Promise<void>;
45
47
  }
@@ -1,8 +1,9 @@
1
- import TestSuiteResults from "../Framework/TestSuiteResults";
2
1
  import xml from "xml";
3
- import TestName from "../Framework/TestName";
2
+
4
3
  import { ResultType } from "../Framework/ResultType";
4
+ import TestName from "../Framework/TestName";
5
5
  import TestResult from "../Framework/TestResult";
6
+ import TestSuiteResults from "../Framework/TestSuiteResults";
6
7
  import XMLReporter from "./XMLReporter";
7
8
 
8
9
  export default class JUnitReporter extends XMLReporter {
@@ -1,5 +1,6 @@
1
+ import { AssertionError } from "node:assert";
2
+
1
3
  import TestSuite from "../Framework/TestSuite";
2
- import { AssertionError } from "assert";
3
4
  import TestSuiteResults from "../Framework/TestSuiteResults";
4
5
 
5
6
  export default interface ResultReporter {
@@ -19,5 +20,5 @@ export default interface ResultReporter {
19
20
 
20
21
  suiteCompleted(suite: TestSuite, results: TestSuiteResults): void;
21
22
 
22
- runCompleted(results: Record<string, TestSuiteResults>): void;
23
- }
23
+ runCompleted(results: Record<string, TestSuiteResults>): Promise<void>;
24
+ };
@@ -1,9 +1,11 @@
1
- import TestSuiteResults from "../Framework/TestSuiteResults";
1
+ import path from "node:path";
2
+
2
3
  import xml from "xml";
4
+
3
5
  import { ResultType } from "../Framework/ResultType";
4
6
  import TestResult from "../Framework/TestResult";
7
+ import TestSuiteResults from "../Framework/TestSuiteResults";
5
8
  import XMLReporter from "./XMLReporter";
6
- import path from "path";
7
9
 
8
10
  export default class SonarReporter extends XMLReporter {
9
11
  static readonly defaultFileName: string = "sonar.xml";
@@ -1,5 +1,5 @@
1
- import FileReporter from "./FileReporter";
2
- import TestSuiteResults from "../Framework/TestSuiteResults";
1
+ import TestSuiteResults from "../Framework/TestSuiteResults";
2
+ import FileReporter from "./FileReporter";
3
3
 
4
4
  export default abstract class XMLReporter extends FileReporter {
5
5
  async runCompleted(results: Record<string, TestSuiteResults>): Promise<void> {
@@ -1,12 +1,12 @@
1
+ import { ResultType } from "../Framework/ResultType";
2
+ import TestSuiteResults from "../Framework/TestSuiteResults";
3
+ import ResultReporter from "../Reporters/ResultReporter";
1
4
  import TestSuiteLoader from "./TestSuiteLoader";
2
5
  import TestSuiteRunner from "./TestSuiteRunner";
3
- import ResultReporter from "../Reporters/ResultReporter";
4
- import TestSuiteResults from "../Framework/TestSuiteResults";
5
- import { ResultType } from "../Framework/ResultType";
6
6
 
7
7
  export default class Runner {
8
8
 
9
- constructor(private readonly loader: TestSuiteLoader, private readonly runner: TestSuiteRunner, private readonly reporters: ReadonlyArray<ResultReporter>) {
9
+ constructor(private readonly loader: TestSuiteLoader, private readonly runner: TestSuiteRunner, private readonly reporters: readonly ResultReporter[]) {
10
10
  }
11
11
 
12
12
  static allTestsPassed(results: Record<string, TestSuiteResults>): boolean {
@@ -16,7 +16,7 @@ export default class Runner {
16
16
  }
17
17
 
18
18
  async runAll(dir: string, filters: RegExp[]): Promise<Record<string, TestSuiteResults>> {
19
- await Promise.all(this.reporters.map(r => r.runStarted()));
19
+ this.reporters.map(r => r.runStarted());
20
20
  const results: Record<string, TestSuiteResults> = {};
21
21
  const suites = await this.loader.loadTestSuites(dir, filters);
22
22
  for (const file of Object.keys(suites)) {
@@ -1,13 +1,14 @@
1
- import TestInfo from "../Framework/TestInfo";
2
- import TestSuite from "../Framework/TestSuite";
1
+ import { AssertionError } from "node:assert";
2
+
3
3
  import { ResultType } from "../Framework/ResultType";
4
- import ResultReporter from "../Reporters/ResultReporter";
4
+ import TestInfo, { AsyncTestInfo, SyncTestInfo } from "../Framework/TestInfo";
5
5
  import TestResult from "../Framework/TestResult";
6
- import { AssertionError } from "assert";
6
+ import TestSuite from "../Framework/TestSuite";
7
+ import ResultReporter from "../Reporters/ResultReporter";
7
8
 
8
9
  export default class TestRunner {
9
10
 
10
- constructor(private readonly reporters: ReadonlyArray<ResultReporter>) {
11
+ constructor(private readonly reporters: readonly ResultReporter[]) {
11
12
  }
12
13
 
13
14
  private static msSince(start: [ number, number ]) {
@@ -15,29 +16,36 @@ export default class TestRunner {
15
16
  return duration[0] * 1_000 + duration[1] / 1_000_000;
16
17
  }
17
18
 
19
+ private static isSyncTest = (test?: TestInfo): test is SyncTestInfo|undefined => test !== undefined;
20
+ private static isAsyncTest = (test?: TestInfo): test is AsyncTestInfo|undefined => test !== undefined;
21
+
18
22
  async runTest(name: string, info: TestInfo, suite: TestSuite): Promise<TestResult> {
19
- await Promise.all(this.reporters.map(r => r.testStarted(suite, name)));
23
+ this.reporters.map(r => r.testStarted(suite, name));
20
24
  if (info.value === undefined) {
21
- await Promise.all(this.reporters.map(r => r.testIncomplete(suite, name)));
25
+ this.reporters.map(r => r.testIncomplete(suite, name));
22
26
  return new TestResult(ResultType.Incomplete, 0);
23
27
  }
24
28
 
25
29
  const start = process.hrtime();
26
30
  try {
27
- await info.value.call(suite);
31
+ if (TestRunner.isAsyncTest(info))
32
+ await info.value.call(suite);
33
+ else if (TestRunner.isSyncTest(info))
34
+ info.value.call(suite);
35
+
28
36
  const duration = TestRunner.msSince(start);
29
- await Promise.all(this.reporters.map(r => r.testPassed(suite, name, duration)));
37
+ this.reporters.map(r => r.testPassed(suite, name, duration));
30
38
  return new TestResult(ResultType.Passed, duration);
31
39
 
32
40
  } catch (error) {
33
41
  const duration = TestRunner.msSince(start);
34
42
  const typedError = error as Error;
35
43
  if (typedError instanceof AssertionError) {
36
- await Promise.all(this.reporters.map(r => r.testFailed(suite, name, typedError, duration)));
44
+ this.reporters.map(r => r.testFailed(suite, name, typedError, duration));
37
45
  return new TestResult(ResultType.Failed, duration, typedError);
38
46
  }
39
47
 
40
- await Promise.all(this.reporters.map(r => r.testErrored(suite, name, typedError, duration)));
48
+ this.reporters.map(r => r.testErrored(suite, name, typedError, duration));
41
49
  return new TestResult(ResultType.Error, duration, typedError);
42
50
  }
43
51
  }