@apiquest/fracture 1.0.2 → 1.0.4
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/README.md +119 -0
- package/bin/cli.js +2 -2
- package/dist/CollectionRunner.js +3 -3
- package/dist/ScriptEngine.js +4 -4
- package/dist/cli/plugin-commands.d.ts.map +1 -1
- package/dist/cli/plugin-commands.js +2 -1
- package/dist/cli/plugin-commands.js.map +1 -1
- package/package.json +55 -50
- package/src/CollectionAnalyzer.ts +102 -102
- package/src/CollectionRunner.ts +1423 -1423
- package/src/CollectionRunner.types.ts +9 -9
- package/src/CollectionValidator.ts +289 -289
- package/src/ConsoleReporter.ts +143 -143
- package/src/CookieJar.ts +258 -258
- package/src/DagScheduler.ts +439 -439
- package/src/Logger.ts +85 -85
- package/src/PluginLoader.ts +126 -126
- package/src/PluginManager.ts +208 -208
- package/src/PluginResolver.ts +154 -154
- package/src/QuestAPI.ts +764 -764
- package/src/QuestAPI.types.ts +33 -33
- package/src/QuestTestAPI.ts +164 -164
- package/src/RequestFilter.ts +224 -224
- package/src/ScriptEngine.ts +219 -219
- package/src/ScriptValidator.ts +428 -428
- package/src/TaskGraph.ts +598 -598
- package/src/TestCounter.ts +109 -109
- package/src/VariableResolver.ts +114 -114
- package/src/cli/index.ts +480 -480
- package/src/cli/plugin-commands.ts +342 -341
- package/src/cli/plugin-discovery.ts +44 -44
- package/src/index.ts +24 -24
- package/src/utils.ts +52 -52
- package/tsconfig.json +20 -20
- package/tsconfig.test.json +5 -5
- package/vitest.config.ts +22 -22
- package/dist/ExecutionTree.d.ts +0 -77
- package/dist/ExecutionTree.d.ts.map +0 -1
- package/dist/ExecutionTree.js +0 -265
- package/dist/ExecutionTree.js.map +0 -1
- package/dist/fracture/src/CollectionAnalyzer.d.ts +0 -17
- package/dist/fracture/src/CollectionAnalyzer.d.ts.map +0 -1
- package/dist/fracture/src/CollectionAnalyzer.js +0 -70
- package/dist/fracture/src/CollectionAnalyzer.js.map +0 -1
- package/dist/fracture/src/CollectionRunner.d.ts +0 -39
- package/dist/fracture/src/CollectionRunner.d.ts.map +0 -1
- package/dist/fracture/src/CollectionRunner.js +0 -802
- package/dist/fracture/src/CollectionRunner.js.map +0 -1
- package/dist/fracture/src/CollectionRunner.types.d.ts +0 -8
- package/dist/fracture/src/CollectionRunner.types.d.ts.map +0 -1
- package/dist/fracture/src/CollectionRunner.types.js +0 -2
- package/dist/fracture/src/CollectionRunner.types.js.map +0 -1
- package/dist/fracture/src/CollectionValidator.d.ts +0 -14
- package/dist/fracture/src/CollectionValidator.d.ts.map +0 -1
- package/dist/fracture/src/CollectionValidator.js +0 -145
- package/dist/fracture/src/CollectionValidator.js.map +0 -1
- package/dist/fracture/src/ConsoleReporter.d.ts +0 -24
- package/dist/fracture/src/ConsoleReporter.d.ts.map +0 -1
- package/dist/fracture/src/ConsoleReporter.js +0 -123
- package/dist/fracture/src/ConsoleReporter.js.map +0 -1
- package/dist/fracture/src/CookieJar.d.ts +0 -70
- package/dist/fracture/src/CookieJar.d.ts.map +0 -1
- package/dist/fracture/src/CookieJar.js +0 -233
- package/dist/fracture/src/CookieJar.js.map +0 -1
- package/dist/fracture/src/ExecutionTree.d.ts +0 -77
- package/dist/fracture/src/ExecutionTree.d.ts.map +0 -1
- package/dist/fracture/src/ExecutionTree.js +0 -258
- package/dist/fracture/src/ExecutionTree.js.map +0 -1
- package/dist/fracture/src/Logger.d.ts +0 -25
- package/dist/fracture/src/Logger.d.ts.map +0 -1
- package/dist/fracture/src/Logger.js +0 -78
- package/dist/fracture/src/Logger.js.map +0 -1
- package/dist/fracture/src/PluginLoader.d.ts +0 -23
- package/dist/fracture/src/PluginLoader.d.ts.map +0 -1
- package/dist/fracture/src/PluginLoader.js +0 -102
- package/dist/fracture/src/PluginLoader.js.map +0 -1
- package/dist/fracture/src/PluginManager.d.ts +0 -64
- package/dist/fracture/src/PluginManager.d.ts.map +0 -1
- package/dist/fracture/src/PluginManager.js +0 -162
- package/dist/fracture/src/PluginManager.js.map +0 -1
- package/dist/fracture/src/PluginResolver.d.ts +0 -35
- package/dist/fracture/src/PluginResolver.d.ts.map +0 -1
- package/dist/fracture/src/PluginResolver.js +0 -128
- package/dist/fracture/src/PluginResolver.js.map +0 -1
- package/dist/fracture/src/QuestAPI.d.ts +0 -9
- package/dist/fracture/src/QuestAPI.d.ts.map +0 -1
- package/dist/fracture/src/QuestAPI.js +0 -679
- package/dist/fracture/src/QuestAPI.js.map +0 -1
- package/dist/fracture/src/QuestAPI.types.d.ts +0 -35
- package/dist/fracture/src/QuestAPI.types.d.ts.map +0 -1
- package/dist/fracture/src/QuestAPI.types.js +0 -3
- package/dist/fracture/src/QuestAPI.types.js.map +0 -1
- package/dist/fracture/src/QuestTestAPI.d.ts +0 -12
- package/dist/fracture/src/QuestTestAPI.d.ts.map +0 -1
- package/dist/fracture/src/QuestTestAPI.js +0 -133
- package/dist/fracture/src/QuestTestAPI.js.map +0 -1
- package/dist/fracture/src/ScriptEngine.d.ts +0 -21
- package/dist/fracture/src/ScriptEngine.d.ts.map +0 -1
- package/dist/fracture/src/ScriptEngine.js +0 -183
- package/dist/fracture/src/ScriptEngine.js.map +0 -1
- package/dist/fracture/src/ScriptValidator.d.ts +0 -68
- package/dist/fracture/src/ScriptValidator.d.ts.map +0 -1
- package/dist/fracture/src/ScriptValidator.js +0 -351
- package/dist/fracture/src/ScriptValidator.js.map +0 -1
- package/dist/fracture/src/TestCounter.d.ts +0 -18
- package/dist/fracture/src/TestCounter.d.ts.map +0 -1
- package/dist/fracture/src/TestCounter.js +0 -82
- package/dist/fracture/src/TestCounter.js.map +0 -1
- package/dist/fracture/src/VariableResolver.d.ts +0 -20
- package/dist/fracture/src/VariableResolver.d.ts.map +0 -1
- package/dist/fracture/src/VariableResolver.js +0 -100
- package/dist/fracture/src/VariableResolver.js.map +0 -1
- package/dist/fracture/src/cli/index.d.ts +0 -3
- package/dist/fracture/src/cli/index.d.ts.map +0 -1
- package/dist/fracture/src/cli/index.js +0 -347
- package/dist/fracture/src/cli/index.js.map +0 -1
- package/dist/fracture/src/cli/plugin-commands.d.ts +0 -6
- package/dist/fracture/src/cli/plugin-commands.d.ts.map +0 -1
- package/dist/fracture/src/cli/plugin-commands.js +0 -263
- package/dist/fracture/src/cli/plugin-commands.js.map +0 -1
- package/dist/fracture/src/cli/plugin-discovery.d.ts +0 -11
- package/dist/fracture/src/cli/plugin-discovery.d.ts.map +0 -1
- package/dist/fracture/src/cli/plugin-discovery.js +0 -64
- package/dist/fracture/src/cli/plugin-discovery.js.map +0 -1
- package/dist/fracture/src/index.d.ts +0 -13
- package/dist/fracture/src/index.d.ts.map +0 -1
- package/dist/fracture/src/index.js +0 -17
- package/dist/fracture/src/index.js.map +0 -1
- package/dist/fracture/src/utils.d.ts +0 -28
- package/dist/fracture/src/utils.d.ts.map +0 -1
- package/dist/fracture/src/utils.js +0 -48
- package/dist/fracture/src/utils.js.map +0 -1
- package/dist/plugin-auth/src/apikey-auth.d.ts +0 -3
- package/dist/plugin-auth/src/apikey-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/apikey-auth.js +0 -73
- package/dist/plugin-auth/src/apikey-auth.js.map +0 -1
- package/dist/plugin-auth/src/basic-auth.d.ts +0 -3
- package/dist/plugin-auth/src/basic-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/basic-auth.js +0 -61
- package/dist/plugin-auth/src/basic-auth.js.map +0 -1
- package/dist/plugin-auth/src/bearer-auth.d.ts +0 -3
- package/dist/plugin-auth/src/bearer-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/bearer-auth.js +0 -49
- package/dist/plugin-auth/src/bearer-auth.js.map +0 -1
- package/dist/plugin-auth/src/helpers.d.ts +0 -3
- package/dist/plugin-auth/src/helpers.d.ts.map +0 -1
- package/dist/plugin-auth/src/helpers.js +0 -8
- package/dist/plugin-auth/src/helpers.js.map +0 -1
- package/dist/plugin-auth/src/index.d.ts +0 -10
- package/dist/plugin-auth/src/index.d.ts.map +0 -1
- package/dist/plugin-auth/src/index.js +0 -25
- package/dist/plugin-auth/src/index.js.map +0 -1
- package/dist/plugin-auth/src/oauth2-auth.d.ts +0 -35
- package/dist/plugin-auth/src/oauth2-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/oauth2-auth.js +0 -266
- package/dist/plugin-auth/src/oauth2-auth.js.map +0 -1
- package/dist/plugin-http/src/index.d.ts +0 -4
- package/dist/plugin-http/src/index.d.ts.map +0 -1
- package/dist/plugin-http/src/index.js +0 -266
- package/dist/plugin-http/src/index.js.map +0 -1
- package/dist/plugin-vault-file/src/index.d.ts +0 -67
- package/dist/plugin-vault-file/src/index.d.ts.map +0 -1
- package/dist/plugin-vault-file/src/index.js +0 -171
- package/dist/plugin-vault-file/src/index.js.map +0 -1
- package/dist/types.d.ts +0 -374
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -13
- package/dist/types.js.map +0 -1
package/src/QuestAPI.types.ts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
// Type definitions for Quest API
|
|
2
|
-
|
|
3
|
-
export interface RequestConfig {
|
|
4
|
-
url: string;
|
|
5
|
-
method?: string;
|
|
6
|
-
header?: Record<string, string>;
|
|
7
|
-
headers?: Record<string, string>;
|
|
8
|
-
body?: string | RequestBody;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface RequestBody {
|
|
12
|
-
mode?: 'raw' | 'urlencoded' | 'formdata';
|
|
13
|
-
raw?: string;
|
|
14
|
-
urlencoded?: Array<{ key: string; value: string }>;
|
|
15
|
-
formdata?: Array<{ key: string; value: string }>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ResponseObject {
|
|
19
|
-
status: number;
|
|
20
|
-
statusText: string;
|
|
21
|
-
body: string;
|
|
22
|
-
headers: Record<string, string | string[]>;
|
|
23
|
-
time: number;
|
|
24
|
-
json(): unknown | null;
|
|
25
|
-
text(): string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface HistoryFilterCriteria {
|
|
29
|
-
path?: string;
|
|
30
|
-
name?: string;
|
|
31
|
-
iteration?: number;
|
|
32
|
-
id?: string;
|
|
33
|
-
}
|
|
1
|
+
// Type definitions for Quest API
|
|
2
|
+
|
|
3
|
+
export interface RequestConfig {
|
|
4
|
+
url: string;
|
|
5
|
+
method?: string;
|
|
6
|
+
header?: Record<string, string>;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
body?: string | RequestBody;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RequestBody {
|
|
12
|
+
mode?: 'raw' | 'urlencoded' | 'formdata';
|
|
13
|
+
raw?: string;
|
|
14
|
+
urlencoded?: Array<{ key: string; value: string }>;
|
|
15
|
+
formdata?: Array<{ key: string; value: string }>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ResponseObject {
|
|
19
|
+
status: number;
|
|
20
|
+
statusText: string;
|
|
21
|
+
body: string;
|
|
22
|
+
headers: Record<string, string | string[]>;
|
|
23
|
+
time: number;
|
|
24
|
+
json(): unknown | null;
|
|
25
|
+
text(): string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface HistoryFilterCriteria {
|
|
29
|
+
path?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
iteration?: number;
|
|
32
|
+
id?: string;
|
|
33
|
+
}
|
package/src/QuestTestAPI.ts
CHANGED
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
import type { TestResult } from '@apiquest/types';
|
|
2
|
-
import { ScriptType } from '@apiquest/types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Special error class for quest.skip()
|
|
6
|
-
*/
|
|
7
|
-
class SkipError extends Error {
|
|
8
|
-
public readonly skipReason: string;
|
|
9
|
-
|
|
10
|
-
constructor(message: string) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = 'SkipError';
|
|
13
|
-
this.skipReason = message;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function isPromise(value: unknown): value is Promise<void> {
|
|
18
|
-
return value !== null &&
|
|
19
|
-
value !== undefined &&
|
|
20
|
-
typeof value === 'object' &&
|
|
21
|
-
typeof (value as { then?: unknown }).then === 'function';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Creates the test API methods (quest.test, quest.skip, quest.fail)
|
|
26
|
-
* These methods allow scripts to define and control test assertions
|
|
27
|
-
*/
|
|
28
|
-
export function createQuestTestAPI(
|
|
29
|
-
tests: TestResult[],
|
|
30
|
-
scriptType: ScriptType,
|
|
31
|
-
emitAssertion: (test: TestResult) => void,
|
|
32
|
-
abortSignal?: AbortSignal
|
|
33
|
-
): {
|
|
34
|
-
test: (name: string, fn: () => void | Promise<void>) => void;
|
|
35
|
-
skip: (reason: string) => never;
|
|
36
|
-
fail: (message: string) => never;
|
|
37
|
-
} {
|
|
38
|
-
let isInsideTest = false;
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
/**
|
|
42
|
-
* Define a test assertion
|
|
43
|
-
* Can only be called in postRequestScript or plugin event scripts
|
|
44
|
-
*/
|
|
45
|
-
test(name: string, fn: () => void | Promise<void>) {
|
|
46
|
-
// Enforce: tests can only be called in request post scripts (never pre, folder, or collection)
|
|
47
|
-
const allowedScriptTypes = [
|
|
48
|
-
ScriptType.PostRequest,
|
|
49
|
-
ScriptType.PluginEvent
|
|
50
|
-
];
|
|
51
|
-
if (!allowedScriptTypes.includes(scriptType)) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`quest.test() can only be called in request post scripts. ` +
|
|
54
|
-
`Current script type: ${scriptType}. ` +
|
|
55
|
-
`Tests require request/response context and cannot be used in ` +
|
|
56
|
-
`collectionPost, folderPost, or pre-request scripts.`
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Check abort signal - skip test if already aborted
|
|
61
|
-
if (abortSignal?.aborted === true) {
|
|
62
|
-
const testResult: TestResult = {
|
|
63
|
-
name,
|
|
64
|
-
passed: false,
|
|
65
|
-
skipped: true,
|
|
66
|
-
error: 'Test skipped - execution aborted'
|
|
67
|
-
};
|
|
68
|
-
tests.push(testResult);
|
|
69
|
-
emitAssertion(testResult);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
isInsideTest = true;
|
|
74
|
-
try {
|
|
75
|
-
const result = fn();
|
|
76
|
-
|
|
77
|
-
// If fn returns a Promise, handle it
|
|
78
|
-
if (isPromise(result)) {
|
|
79
|
-
result
|
|
80
|
-
.then(() => {
|
|
81
|
-
const testResult: TestResult = {
|
|
82
|
-
name,
|
|
83
|
-
passed: true,
|
|
84
|
-
skipped: false
|
|
85
|
-
};
|
|
86
|
-
tests.push(testResult);
|
|
87
|
-
emitAssertion(testResult);
|
|
88
|
-
})
|
|
89
|
-
.catch((error: unknown) => {
|
|
90
|
-
// Check if this is a skip error
|
|
91
|
-
const testResult: TestResult = error instanceof SkipError
|
|
92
|
-
? {
|
|
93
|
-
name,
|
|
94
|
-
passed: false,
|
|
95
|
-
skipped: true,
|
|
96
|
-
error: error.skipReason
|
|
97
|
-
}
|
|
98
|
-
: {
|
|
99
|
-
name,
|
|
100
|
-
passed: false,
|
|
101
|
-
skipped: false,
|
|
102
|
-
error: (error as { message?: string }).message ?? String(error)
|
|
103
|
-
};
|
|
104
|
-
tests.push(testResult);
|
|
105
|
-
emitAssertion(testResult);
|
|
106
|
-
})
|
|
107
|
-
.finally(() => {
|
|
108
|
-
isInsideTest = false;
|
|
109
|
-
});
|
|
110
|
-
} else {
|
|
111
|
-
// Synchronous test
|
|
112
|
-
const testResult: TestResult = {
|
|
113
|
-
name,
|
|
114
|
-
passed: true,
|
|
115
|
-
skipped: false
|
|
116
|
-
};
|
|
117
|
-
tests.push(testResult);
|
|
118
|
-
emitAssertion(testResult);
|
|
119
|
-
isInsideTest = false;
|
|
120
|
-
}
|
|
121
|
-
} catch (error: unknown) {
|
|
122
|
-
// Check if this is a skip error
|
|
123
|
-
const testResult: TestResult = error instanceof SkipError
|
|
124
|
-
? {
|
|
125
|
-
name,
|
|
126
|
-
passed: false,
|
|
127
|
-
skipped: true,
|
|
128
|
-
error: error.skipReason // Include skip reason in error field
|
|
129
|
-
}
|
|
130
|
-
: {
|
|
131
|
-
name,
|
|
132
|
-
passed: false,
|
|
133
|
-
skipped: false,
|
|
134
|
-
error: (error as { message?: string }).message ?? String(error)
|
|
135
|
-
};
|
|
136
|
-
tests.push(testResult);
|
|
137
|
-
emitAssertion(testResult);
|
|
138
|
-
isInsideTest = false;
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Skip the current test
|
|
144
|
-
* Must be called inside quest.test() callback
|
|
145
|
-
*/
|
|
146
|
-
skip(reason: string): never {
|
|
147
|
-
if (!isInsideTest) {
|
|
148
|
-
throw new Error('quest.skip() must be called inside quest.test() callback');
|
|
149
|
-
}
|
|
150
|
-
throw new SkipError(reason);
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Fail the current test with custom message
|
|
155
|
-
* Must be called inside quest.test() callback
|
|
156
|
-
*/
|
|
157
|
-
fail(message: string): never {
|
|
158
|
-
if (!isInsideTest) {
|
|
159
|
-
throw new Error('quest.fail() must be called inside quest.test() callback');
|
|
160
|
-
}
|
|
161
|
-
throw new Error(message);
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
1
|
+
import type { TestResult } from '@apiquest/types';
|
|
2
|
+
import { ScriptType } from '@apiquest/types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Special error class for quest.skip()
|
|
6
|
+
*/
|
|
7
|
+
class SkipError extends Error {
|
|
8
|
+
public readonly skipReason: string;
|
|
9
|
+
|
|
10
|
+
constructor(message: string) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'SkipError';
|
|
13
|
+
this.skipReason = message;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isPromise(value: unknown): value is Promise<void> {
|
|
18
|
+
return value !== null &&
|
|
19
|
+
value !== undefined &&
|
|
20
|
+
typeof value === 'object' &&
|
|
21
|
+
typeof (value as { then?: unknown }).then === 'function';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates the test API methods (quest.test, quest.skip, quest.fail)
|
|
26
|
+
* These methods allow scripts to define and control test assertions
|
|
27
|
+
*/
|
|
28
|
+
export function createQuestTestAPI(
|
|
29
|
+
tests: TestResult[],
|
|
30
|
+
scriptType: ScriptType,
|
|
31
|
+
emitAssertion: (test: TestResult) => void,
|
|
32
|
+
abortSignal?: AbortSignal
|
|
33
|
+
): {
|
|
34
|
+
test: (name: string, fn: () => void | Promise<void>) => void;
|
|
35
|
+
skip: (reason: string) => never;
|
|
36
|
+
fail: (message: string) => never;
|
|
37
|
+
} {
|
|
38
|
+
let isInsideTest = false;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
/**
|
|
42
|
+
* Define a test assertion
|
|
43
|
+
* Can only be called in postRequestScript or plugin event scripts
|
|
44
|
+
*/
|
|
45
|
+
test(name: string, fn: () => void | Promise<void>) {
|
|
46
|
+
// Enforce: tests can only be called in request post scripts (never pre, folder, or collection)
|
|
47
|
+
const allowedScriptTypes = [
|
|
48
|
+
ScriptType.PostRequest,
|
|
49
|
+
ScriptType.PluginEvent
|
|
50
|
+
];
|
|
51
|
+
if (!allowedScriptTypes.includes(scriptType)) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`quest.test() can only be called in request post scripts. ` +
|
|
54
|
+
`Current script type: ${scriptType}. ` +
|
|
55
|
+
`Tests require request/response context and cannot be used in ` +
|
|
56
|
+
`collectionPost, folderPost, or pre-request scripts.`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check abort signal - skip test if already aborted
|
|
61
|
+
if (abortSignal?.aborted === true) {
|
|
62
|
+
const testResult: TestResult = {
|
|
63
|
+
name,
|
|
64
|
+
passed: false,
|
|
65
|
+
skipped: true,
|
|
66
|
+
error: 'Test skipped - execution aborted'
|
|
67
|
+
};
|
|
68
|
+
tests.push(testResult);
|
|
69
|
+
emitAssertion(testResult);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
isInsideTest = true;
|
|
74
|
+
try {
|
|
75
|
+
const result = fn();
|
|
76
|
+
|
|
77
|
+
// If fn returns a Promise, handle it
|
|
78
|
+
if (isPromise(result)) {
|
|
79
|
+
result
|
|
80
|
+
.then(() => {
|
|
81
|
+
const testResult: TestResult = {
|
|
82
|
+
name,
|
|
83
|
+
passed: true,
|
|
84
|
+
skipped: false
|
|
85
|
+
};
|
|
86
|
+
tests.push(testResult);
|
|
87
|
+
emitAssertion(testResult);
|
|
88
|
+
})
|
|
89
|
+
.catch((error: unknown) => {
|
|
90
|
+
// Check if this is a skip error
|
|
91
|
+
const testResult: TestResult = error instanceof SkipError
|
|
92
|
+
? {
|
|
93
|
+
name,
|
|
94
|
+
passed: false,
|
|
95
|
+
skipped: true,
|
|
96
|
+
error: error.skipReason
|
|
97
|
+
}
|
|
98
|
+
: {
|
|
99
|
+
name,
|
|
100
|
+
passed: false,
|
|
101
|
+
skipped: false,
|
|
102
|
+
error: (error as { message?: string }).message ?? String(error)
|
|
103
|
+
};
|
|
104
|
+
tests.push(testResult);
|
|
105
|
+
emitAssertion(testResult);
|
|
106
|
+
})
|
|
107
|
+
.finally(() => {
|
|
108
|
+
isInsideTest = false;
|
|
109
|
+
});
|
|
110
|
+
} else {
|
|
111
|
+
// Synchronous test
|
|
112
|
+
const testResult: TestResult = {
|
|
113
|
+
name,
|
|
114
|
+
passed: true,
|
|
115
|
+
skipped: false
|
|
116
|
+
};
|
|
117
|
+
tests.push(testResult);
|
|
118
|
+
emitAssertion(testResult);
|
|
119
|
+
isInsideTest = false;
|
|
120
|
+
}
|
|
121
|
+
} catch (error: unknown) {
|
|
122
|
+
// Check if this is a skip error
|
|
123
|
+
const testResult: TestResult = error instanceof SkipError
|
|
124
|
+
? {
|
|
125
|
+
name,
|
|
126
|
+
passed: false,
|
|
127
|
+
skipped: true,
|
|
128
|
+
error: error.skipReason // Include skip reason in error field
|
|
129
|
+
}
|
|
130
|
+
: {
|
|
131
|
+
name,
|
|
132
|
+
passed: false,
|
|
133
|
+
skipped: false,
|
|
134
|
+
error: (error as { message?: string }).message ?? String(error)
|
|
135
|
+
};
|
|
136
|
+
tests.push(testResult);
|
|
137
|
+
emitAssertion(testResult);
|
|
138
|
+
isInsideTest = false;
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Skip the current test
|
|
144
|
+
* Must be called inside quest.test() callback
|
|
145
|
+
*/
|
|
146
|
+
skip(reason: string): never {
|
|
147
|
+
if (!isInsideTest) {
|
|
148
|
+
throw new Error('quest.skip() must be called inside quest.test() callback');
|
|
149
|
+
}
|
|
150
|
+
throw new SkipError(reason);
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Fail the current test with custom message
|
|
155
|
+
* Must be called inside quest.test() callback
|
|
156
|
+
*/
|
|
157
|
+
fail(message: string): never {
|
|
158
|
+
if (!isInsideTest) {
|
|
159
|
+
throw new Error('quest.fail() must be called inside quest.test() callback');
|
|
160
|
+
}
|
|
161
|
+
throw new Error(message);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|