@ryupold/vode 1.8.7 → 1.8.10

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.
package/test/helper.ts CHANGED
@@ -1,159 +1,350 @@
1
- import { children, ChildVode, PatchableState, tag, Vode } from "../src/vode";
2
- import { MockElement, MockText } from "./mocks";
1
+ import { children, ChildVode, PatchableState, props, tag, Vode } from "../src/vode";
2
+ import { FakeElement, FakeTextNode } from "./mocks";
3
+
4
+ // Helper to detect if we're in a browser environment with real DOM
5
+ const isBrowser = typeof window !== 'undefined' && typeof HTMLElement !== 'undefined';
6
+
7
+ // Type guards for real DOM elements
8
+ function isRealElement(node: any): node is HTMLElement {
9
+ return isBrowser && node instanceof HTMLElement;
10
+ }
11
+ function isRealTextNode(node: any): node is Text {
12
+ return isBrowser && node instanceof Text;
13
+ }
14
+
15
+ export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
16
+
17
+ function retry<T = void>(fn: () => Promise<T>, waitTime: number): Promise<T> {
18
+ const { promise, resolve, reject } = Promise.withResolvers<T>();
19
+
20
+ function retryInternal(timeLeft: number) {
21
+ const start = performance.now();
22
+ try {
23
+ const prom = fn();
24
+ if (typeof prom?.then === "function") {
25
+ prom.then(resolve).catch((err) => {
26
+ if (timeLeft >= 0) {
27
+ setTimeout(
28
+ () => retryInternal(timeLeft - (performance.now() - start)),
29
+ 10
30
+ );
31
+ } else {
32
+ reject(err);
33
+ }
34
+ });
35
+ } else {
36
+ resolve(prom);
37
+ }
38
+ } catch (err) {
39
+ if (timeLeft >= 0) {
40
+ setTimeout(() => {
41
+ retryInternal(timeLeft - (performance.now() - start))
42
+ }, 10);
43
+ } else {
44
+ reject(err);
45
+ }
46
+ }
47
+ }
48
+
49
+ retryInternal(waitTime);
50
+
51
+ return promise;
52
+ }
3
53
 
4
54
  export class Expectation {
5
55
  constructor(public readonly what: any) { }
6
56
 
7
- toBeA(type: "undefined" | "object" | "function" | "bigint" | "boolean" | "number" | "string" | "symbol") {
57
+ toBeNotHidden() {
58
+ if (document.hidden) {
59
+ throw new ExpectationError(this, `expect the document to be not hidden. if you run this in a real browser this means the window must be in focus in order for the tests to work.`);
60
+ }
61
+ }
62
+
63
+ toBeA(type: "undefined" | "object" | "function" | "bigint" | "boolean" | "number" | "string" | "symbol", failMessage?: string) {
8
64
  if (typeof this.what !== type) {
9
- throw new ExpectationError(this, `expected \n\ntypeof ${this.what}\n\nto be \n\n${type}`);
65
+ throw new ExpectationError(this, `expected \n\ntypeof ${this.what}\n\nto be \n\n${type}${failMessage ? `\n\n${failMessage}` : ""}`);
10
66
  }
11
67
  }
12
68
 
13
- toEqual(other: any) {
14
- function deepCompare(a: any, b: any, path: string[]): string[] | null {
15
- if (typeof a !== typeof b) {
16
- if (path.length === 0) path.push(``);
17
- path[path.length - 1] += ` (type: ${typeof a} != ${typeof b})`;
18
- return path;
19
- }
69
+ toBeGreaterThan(other: number, failMessage?: string) {
70
+ if (!(this.what > other)) {
71
+ throw new ExpectationError(this, `expected \n\n${this.what}\n\nto be >\n\n${other}${failMessage ? `\n\n${failMessage}` : ""}`);
72
+ }
73
+ }
20
74
 
21
- if (typeof a !== "object" || a === null) {
22
- if (path.length === 0) path.push(``);
23
- path[path.length - 1] += ` (value: ${a} != ${b})`;
24
- return a !== b ? path : null;
25
- }
75
+ toBeGreaterOrEqualThan(other: number, failMessage?: string) {
76
+ if (!(this.what >= other)) {
77
+ throw new ExpectationError(this, `expected \n\n${this.what}\n\nto be >= \n\n${other}${failMessage ? `\n\n${failMessage}` : ""}`);
78
+ }
79
+ }
80
+
81
+ toBeSmallerThan(other: number, failMessage?: string) {
82
+ if (!(this.what < other)) {
83
+ throw new ExpectationError(this, `expected \n\n${this.what}\n\nto be <\n\n${other}${failMessage ? `\n\n${failMessage}` : ""}`);
84
+ }
85
+ }
86
+
87
+ toBeSmallerOrEqual(other: number, failMessage?: string) {
88
+ if (!(this.what <= other)) {
89
+ throw new ExpectationError(this, `expected \n\n${this.what}\n\nto be <= \n\n${other}${failMessage ? `\n\n${failMessage}` : ""}`);
90
+ }
91
+ }
92
+
93
+ async toEqual(other: any, failMessage?: string, waitTimeMs: number = 100) {
94
+ return await retry(
95
+ async () => {
96
+ const failSuffix = failMessage ? `\n\n${failMessage}` : "";
26
97
 
27
- for (const prop of Object.entries(a)) {
28
- const [k, v] = prop;
29
- const result = deepCompare(v, b[k], [...path, k]);
30
- if (result) {
31
- return result;
98
+ function deepCompare(a: any, b: any, path: string[]): string[] | null {
99
+ if (typeof a !== typeof b) {
100
+ if (path.length === 0) path.push(``);
101
+ path[path.length - 1] += ` (type: ${typeof a} != ${typeof b})`;
102
+ return path;
103
+ }
104
+
105
+ if (typeof a !== "object" || a === null) {
106
+ if (path.length === 0) path.push(``);
107
+ path[path.length - 1] += ` (value: ${a} != ${b})`;
108
+ return a !== b ? path : null;
109
+ }
110
+
111
+ for (const prop of Object.entries(a)) {
112
+ const [k, v] = prop;
113
+ const result = deepCompare(v, b[k], [...path, k]);
114
+ if (result) {
115
+ return result;
116
+ }
117
+ }
118
+
119
+ for (const prop of Object.entries(b)) {
120
+ const [k, v] = prop;
121
+ const result = deepCompare(a[k], v, [...path, k]);
122
+ if (result) {
123
+ return result;
124
+ }
125
+ }
126
+
127
+ return null;
32
128
  }
33
- }
34
129
 
35
- for (const prop of Object.entries(b)) {
36
- const [k, v] = prop;
37
- const result = deepCompare(a[k], v, [...path, k]);
38
- if (result) {
39
- return result;
130
+ if (typeof this.what === "object" && typeof other === "object" && this.what !== null && other !== null) {
131
+ const unequal = deepCompare(this.what, other, []);
132
+ if (unequal) {
133
+ throw new ExpectationError(this, `expected \n\n${JSON.stringify(this.what, null, 2)}\n\n to equal \n\n${JSON.stringify(other, null, 2)}\n\nThey differ in: ${unequal.join(".")}${failSuffix}`);
134
+ }
40
135
  }
41
- }
136
+ else {
137
+ if (this.what !== other) {
138
+ throw new ExpectationError(this, `expected (${typeof this.what})\n\n${this.what}\n\nto equal (${typeof other})\n\n${other}${failSuffix}`);
139
+ }
140
+ }
141
+ },
142
+ waitTimeMs
143
+ );
144
+ }
42
145
 
43
- return null;
146
+ toSucceed<Result>(): Result {
147
+ if (typeof this.what !== "function") {
148
+ throw new ExpectationError(this, `expected a function\n\nbut it is a ${typeof this.what}`);
44
149
  }
150
+ return this.what();
151
+ }
45
152
 
46
- if (typeof this.what === "object" && typeof other === "object" && this.what !== null && other !== null) {
47
- const unequal = deepCompare(this.what, other, []);
48
- if (unequal) {
49
- throw new ExpectationError(this, `expected \n\n${JSON.stringify(this.what, null, 2)}\n\n to equal \n\n${JSON.stringify(other, null, 2)}\n\nThey differ in: ${unequal.join(".")}`);
50
- }
153
+ toFail(): Error {
154
+ if (typeof this.what !== "function") {
155
+ throw new ExpectationError(this, `expected a function\n\nbut it is a ${typeof this.what}`);
51
156
  }
52
- else {
53
- if (this.what !== other) {
54
- throw new ExpectationError(this, `expected (${typeof this.what})\n\n${this.what}\n\nto equal (${typeof other})\n\n${other}`);
55
- }
157
+
158
+ let r: any;
159
+ try {
160
+ r = this.what();
161
+ } catch (err: any) {
162
+ return err;
56
163
  }
164
+ throw new ExpectationError(this, `expected function to fail\n\nbut it succeeded with a result of type ${typeof r}\n\n${r}`);
57
165
  }
58
166
 
59
- toSucceed<Result>(...args: any): Result {
167
+ toSucceedAsync<Result>(waitTime: number = 100): Promise<Result> {
60
168
  if (typeof this.what !== "function") {
61
169
  throw new ExpectationError(this, `expected a function\n\nbut it is a ${typeof this.what}`);
62
170
  }
63
- return this.what(...args);
171
+ return retry<Result>(() => this.what(), waitTime);
64
172
  }
65
173
 
66
- toFail(...args: any): Error {
174
+ async toFailAsync(): Promise<Error> {
67
175
  if (typeof this.what !== "function") {
68
176
  throw new ExpectationError(this, `expected a function\n\nbut it is a ${typeof this.what}`);
69
177
  }
70
178
 
71
179
  let r: any;
72
180
  try {
73
- r = this.what(...args);
181
+ r = await this.what();
74
182
  } catch (err: any) {
75
183
  return err;
76
184
  }
77
185
  throw new ExpectationError(this, `expected function to fail\n\nbut it succeeded with a result of type ${typeof r}\n\n${r}`);
78
186
  }
79
187
 
80
- toMatch(v: ChildVode, state?: PatchableState) {
81
- if (this.what instanceof MockElement || this.what instanceof MockText || typeof this.what === "string" || Array.isArray(this.what) || typeof this.what === "function") {
82
- const that = this;
83
- function deepCompare(e: MockElement | MockText | ChildVode, cv: ChildVode, path: string[]): string[] | null {
188
+ async toMatch(v: ChildVode,
189
+ state?: PatchableState | null,
190
+ failMessage?: string,
191
+ waitTimeMs: number = 100
192
+ ) {
193
+ return await retry(
194
+ async () => {
195
+ const failSuffix = failMessage ? `\n\n${failMessage}` : "";
84
196
 
85
- // unwrap component
86
- while (typeof cv === "function") {
87
- if (!state) {
88
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na Component\n\nbut got no state passed in [toMatch]`);
89
- }
90
- cv = cv(state);
91
- }
92
- while (typeof e === "function") {
93
- if (!state) {
94
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na Component\n\nbut got no state passed in [toMatch]`);
95
- }
96
- e = e(state);
97
- }
197
+ // Support FakeElement, FakeTextNode, real HTMLElement, real Text nodes, strings, arrays, functions
198
+ if (this.what instanceof FakeElement || this.what instanceof FakeTextNode ||
199
+ isRealElement(this.what) || isRealTextNode(this.what) ||
200
+ typeof this.what === "string" || Array.isArray(this.what) || typeof this.what === "function") {
201
+ const that = this;
98
202
 
99
- if (typeof cv === "string" && e instanceof MockText) {
100
- if (cv !== e.wholeText) {
101
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node with\n${cv}\n\nbut text was\n${e.wholeText}`);
102
- }
103
- }
104
- else if (typeof cv === "string" && typeof e === "string") {
105
- if (cv !== e) {
106
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node with\n${cv}\n\nbut text was\n${e}`);
107
- }
108
- }
203
+ function deepCompare(e: FakeElement | FakeTextNode | HTMLElement | Text | ChildVode, cv: ChildVode, path: string[]): string[] | null {
109
204
 
110
- else if (Array.isArray(cv) && e instanceof MockElement) {
111
- if (tag(cv)?.toLocaleUpperCase() !== e.tagName.toUpperCase()) {
112
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)}>\n\nbut got <${e.tagName}>`);
113
- }
114
- const kids = children(cv) || [];
115
- for (let i = 0; i < kids.length; i++) {
116
- deepCompare(e.children[i], kids[i], [...path, `${tag(kids[i] as Vode) || "#text"}`]);
117
- }
118
- if (kids.length !== e.children.length) {
119
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\n${kids.length} children\n\nbut <${e.tagName}> has ${e.children.length} children`);
120
- }
121
- }
122
- else if (Array.isArray(cv) && Array.isArray(e)) {
123
- if (tag(cv)?.toLocaleUpperCase() !== tag(e)?.toUpperCase()) {
124
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element [${tag(cv)}]\n\nbut got [${tag(e)}]`);
125
- }
126
- const kids = children(cv) || [];
127
- const otherKids = children(e) || [];
128
- for (let i = 0; i < kids.length; i++) {
129
- deepCompare(otherKids[i], kids[i], [...path, `${tag(kids[i] as Vode) || "#text"}`]);
130
- }
131
- if (kids.length !== otherKids.length) {
132
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\n${kids.length} children\n\nbut [${tag(e)}] has ${otherKids.length} children`);
133
- }
134
- }
205
+ // unwrap component
206
+ while (typeof cv === "function") {
207
+ if (!state) {
208
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na Component\n\nbut got no state passed in [toMatch]${failSuffix}`);
209
+ }
210
+ cv = cv(state);
211
+ }
212
+ while (typeof e === "function") {
213
+ if (!state) {
214
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na Component\n\nbut got no state passed in [toMatch]${failSuffix}`);
215
+ }
216
+ e = e(state);
217
+ }
135
218
 
136
- else if (typeof cv === "string" && e instanceof MockElement) {
137
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node\n\nbut got <${e.tagName}>`);
138
- }
139
- else if (typeof cv === "string" && Array.isArray(e)) {
140
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node\n\nbut got [${tag(e)}]`);
141
- }
219
+ // string matches TextNode (fake or real)
220
+ if (typeof cv === "string" && (e instanceof FakeTextNode || isRealTextNode(e))) {
221
+ const text = e instanceof FakeTextNode ? e.wholeText : (e as Text).wholeText;
222
+ if (cv !== text) {
223
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node with\n${cv}\n\nbut text was\n${text}${failSuffix}`);
224
+ }
225
+ }
226
+ // string matches string
227
+ else if (typeof cv === "string" && typeof e === "string") {
228
+ if (cv !== e) {
229
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node with\n${cv}\n\nbut text was\n${e}${failSuffix}`);
230
+ }
231
+ }
142
232
 
143
- else if (Array.isArray(cv) && e instanceof MockText) {
144
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)}>\n\nbut got #text (${e.wholeText})`);
145
- }
146
- else if (Array.isArray(cv) && typeof e === "string") {
147
- throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)}>\n\nbut got #text (${e})`);
148
- }
233
+ // vode matches element (fake or real)
234
+ else if (Array.isArray(cv) && (e instanceof FakeElement || isRealElement(e))) {
235
+ const tagName = e instanceof FakeElement ? e.tagName : (e as HTMLElement).tagName;
236
+ if (tag(cv)?.toUpperCase() !== tagName.toUpperCase()) {
237
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)?.toUpperCase()}>\n\nbut got <${tagName.toUpperCase()}>${failSuffix}`);
238
+ }
149
239
 
150
- return null;
151
- }
240
+ // compare attributes/props
241
+ const properties = props(cv);
242
+ if (properties) {
243
+ for (const [k, val] of Object.entries(properties)) {
244
+ let attributeValue: string | null;
245
+ if (e instanceof FakeElement) {
246
+ attributeValue = e.fakeAttributes[k] ?? null;
247
+ } else {
248
+ attributeValue = (e as HTMLElement).getAttribute(k);
249
+ }
250
+ if (!attributeValue) {
251
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)?.toUpperCase()}>\n\nwith attribute [${k}="${val}"]\n\nbut it was not found${failSuffix}`);
252
+ }
253
+ if (attributeValue !== val) {
254
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)?.toUpperCase()}>\n\nwith attribute [${k}="${val}"]\n\nbut it was [${k}="${attributeValue}"]${failSuffix}`);
255
+ }
256
+ }
257
+ }
152
258
 
153
- deepCompare(this.what, v, [tag(v as Vode) || "#text"]);
154
- } else {
155
- throw new ExpectationError(this, `expected an element or text node\n\nbut it is a ${typeof this.what}\n${this.what}`);
156
- }
259
+ // compare children - handle browser text node normalization
260
+ const kids = children(cv) || [];
261
+ const childNodes = e instanceof FakeElement ? e.children : (e as HTMLElement).childNodes;
262
+
263
+ // Check if all kids are text (strings) - browsers may merge these
264
+ const allKidsAreText = kids.every(k => typeof k === "string");
265
+ if (allKidsAreText && isBrowser && kids.length > 1) {
266
+ // Browser likely merged text nodes - compare concatenated text
267
+ const expectedText = kids.join("");
268
+ const actualText = (e as HTMLElement).textContent || "";
269
+ if (expectedText !== actualText) {
270
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\ntext content "${expectedText}"\n\nbut got "${actualText}"${failSuffix}`);
271
+ }
272
+ } else {
273
+ // Normal child-by-child comparison
274
+ for (let i = 0; i < kids.length; i++) {
275
+ const childNode = e instanceof FakeElement
276
+ ? childNodes.item(i) as any
277
+ : childNodes.item(i) as any;
278
+ deepCompare(childNode, kids[i], [...path, `[${i}]${tag(kids[i] as Vode)?.toUpperCase() || "#text"}`]);
279
+ }
280
+ const childCount = e instanceof FakeElement ? e.children.length : (e as HTMLElement).childNodes.length;
281
+ if (kids.length !== childCount) {
282
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\n${kids.length} children\n\nbut <${tagName.toUpperCase()}> has ${childCount} children${failSuffix}`);
283
+ }
284
+ }
285
+ }
286
+ // vode matches vode
287
+ else if (Array.isArray(cv) && Array.isArray(e)) {
288
+ if (tag(cv)?.toUpperCase() !== tag(e)?.toUpperCase()) {
289
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na vode [${tag(cv)?.toUpperCase()}]\n\nbut got [${tag(e)?.toUpperCase()}]${failSuffix}`);
290
+ }
291
+
292
+ // compare attributes/props
293
+ const properties = props(cv);
294
+ const otherProperties = props(e) || {};
295
+ if (properties) {
296
+ for (const [k, val] of Object.entries(properties)) {
297
+ const attributeValue = otherProperties[k];
298
+ if (!attributeValue) {
299
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na vode [${tag(cv)?.toUpperCase()}]\n\nwith attribute [${k}="${val}"]\n\nbut it was not found${failSuffix}`);
300
+ }
301
+ if (attributeValue !== val) {
302
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na vode [${tag(cv)?.toUpperCase()}]\n\nwith attribute [${k}="${val}"]\n\nbut its value was [${k}="${attributeValue}"]${failSuffix}`);
303
+ }
304
+ }
305
+ }
306
+
307
+ // compare children
308
+ const kids = children(cv) || [];
309
+ const otherKids = children(e) || [];
310
+ for (let i = 0; i < kids.length; i++) {
311
+ deepCompare(otherKids[i], kids[i], [...path, `[${i}]${tag(kids[i] as Vode)?.toUpperCase() || "#text"}`]);
312
+ }
313
+ if (kids.length !== otherKids.length) {
314
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\n${kids.length} children\n\nbut [${tag(e)?.toUpperCase()}] has ${otherKids.length} children${failSuffix}`);
315
+ }
316
+ }
317
+
318
+ // mismatch between text and element (fake or real)
319
+ else if (typeof cv === "string" && (e instanceof FakeElement || isRealElement(e))) {
320
+ const tagName = e instanceof FakeElement ? e.tagName : (e as HTMLElement).tagName;
321
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node\n\nbut got <${tagName.toUpperCase()}>${failSuffix}`);
322
+ }
323
+ // mismatch between text and vode
324
+ else if (typeof cv === "string" && Array.isArray(e)) {
325
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\na text node\n\nbut got [${tag(e)?.toUpperCase()}]${failSuffix}`);
326
+ }
327
+
328
+ // mismatch between vode and text node (fake or real)
329
+ else if (Array.isArray(cv) && (e instanceof FakeTextNode || isRealTextNode(e))) {
330
+ const text = e instanceof FakeTextNode ? e.wholeText : (e as Text).wholeText;
331
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)?.toUpperCase()}>\n\nbut got #text (${text})${failSuffix}`);
332
+ }
333
+ // mismatch between vode and text
334
+ else if (Array.isArray(cv) && typeof e === "string") {
335
+ throw new ExpectationError(that, `expected at\n${path.join(" > ")}\n\nan element <${tag(cv)?.toUpperCase()}>\n\nbut got #text (${e})${failSuffix}`);
336
+ }
337
+
338
+ return null;
339
+ }
340
+
341
+ deepCompare(this.what, v, [`${tag(v as Vode)?.toUpperCase() || "#text"}`]);
342
+ } else {
343
+ throw new ExpectationError(this, `expected an element or text node\n\nbut it is a ${typeof this.what}\n${this.what}${failSuffix}`);
344
+ }
345
+ },
346
+ waitTimeMs
347
+ );
157
348
  }
158
349
  };
159
350
 
@@ -165,4 +356,4 @@ export class ExpectationError extends Error {
165
356
 
166
357
  export function expect(what: any) {
167
358
  return new Expectation(what);
168
- }
359
+ }
package/test/index.ts CHANGED
@@ -1,7 +1,3 @@
1
- import { resetMocks } from "./mocks";
2
- import { ExpectationError } from "./helper";
3
-
4
- //=== REGISTERED TESTS =========================================
5
1
  import vodeTests from "./tests-vode";
6
2
  import appTests from "./tests-app";
7
3
  import defuseTests from "./tests-defuse";
@@ -17,8 +13,12 @@ import mergeStyleTests from "./tests-mergeStyle";
17
13
  import mergePropsTests from "./tests-mergeProps";
18
14
  import stateContextTests from "./tests-state-context";
19
15
  import mountUnmountTests from "./tests-mount-unmount";
16
+ import exampleTests from "./tests-examples";
17
+ import catchTests from "./tests-catch";
18
+ import patchAdvancedTests from "./tests-patch-advanced";
19
+ import patchMergeTests from "./tests-patch-merge";
20
20
 
21
- const tests = {
21
+ export const tests = {
22
22
  ...vodeTests,
23
23
  ...appTests,
24
24
  ...defuseTests,
@@ -38,45 +38,8 @@ const tests = {
38
38
  ...mergePropsTests,
39
39
 
40
40
  ...stateContextTests,
41
- };
42
- //===================================================
43
-
44
- const count = {
45
- total: 0,
46
- passed: 0,
47
- failed: <string[]>[],
48
- }
49
- const line = "----------------------------------";
50
-
51
- for (const test of Object.entries(tests)) {
52
- count.total++;
53
- resetMocks();
54
- try {
55
- test[1]()
56
- count.passed++;
57
- console.log(`#${count.total} ${test[0]}\n-> 🟢 passed\n${line}`);
58
- } catch (err: any) {
59
- console.error(`#${count.total} ${test[0]}\n-> 🔴 failed`);
60
- if (err instanceof ExpectationError) {
61
- count.failed.push(`#${count.total} ${test[0]}\n-> 🔴 failed:\n${err.message}\n${line}`);
62
- }
63
- else {
64
- count.failed.push(`#${count.total} ${test[0]}\n-> 🔴 failed:\n${err.message}\n${err.stack}\n${line}`);
65
- }
66
- }
67
- }
68
-
69
- console.log(`
70
- total: ${count.total}
71
- passed: ${count.passed}
72
- failed: ${count.failed.length}
73
- `);
74
-
75
- if (count.passed === count.total) {
76
- console.log("\n\nall tests passed\n");
77
- }
78
- else {
79
- console.error(`${line.replaceAll("-", "=")}\nError summary:\n\n${count.failed.join(`\n${line}\n`)}`);
80
-
81
- throw "\n\nsome tests failed (see output)\n";
82
- }
41
+ ...exampleTests,
42
+ ...catchTests,
43
+ ...patchAdvancedTests,
44
+ ...patchMergeTests,
45
+ };