@testsmith/testblocks 0.1.0 → 0.2.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.
- package/dist/cli/executor.d.ts +1 -0
- package/dist/cli/executor.js +32 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/reporters.js +324 -43
- package/dist/client/assets/index-DbvW1Eh_.css +1 -0
- package/dist/client/assets/index-q27f2_ju.js +2193 -0
- package/dist/client/assets/index-q27f2_ju.js.map +1 -0
- package/dist/client/index.html +2 -2
- package/dist/core/types.d.ts +7 -0
- package/dist/server/executor.d.ts +1 -0
- package/dist/server/executor.js +32 -1
- package/dist/server/index.js +64 -6
- package/package.json +1 -1
- package/dist/client/assets/index-Cq84-VIf.js +0 -2137
- package/dist/client/assets/index-Cq84-VIf.js.map +0 -1
- package/dist/client/assets/index-Dnk1ti7l.css +0 -1
package/dist/client/index.html
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
overflow: hidden;
|
|
17
17
|
}
|
|
18
18
|
</style>
|
|
19
|
-
<script type="module" crossorigin src="/assets/index-
|
|
20
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
19
|
+
<script type="module" crossorigin src="/assets/index-q27f2_ju.js"></script>
|
|
20
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DbvW1Eh_.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
|
23
23
|
<div id="root"></div>
|
package/dist/core/types.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare class TestExecutor {
|
|
|
17
17
|
constructor(options?: ExecutorOptions);
|
|
18
18
|
initialize(): Promise<void>;
|
|
19
19
|
cleanup(): Promise<void>;
|
|
20
|
+
private requiresBrowser;
|
|
20
21
|
runTestFile(testFile: TestFile): Promise<TestResult[]>;
|
|
21
22
|
private runLifecycleSteps;
|
|
22
23
|
/**
|
package/dist/server/executor.js
CHANGED
|
@@ -130,13 +130,44 @@ class TestExecutor {
|
|
|
130
130
|
this.context = null;
|
|
131
131
|
this.browser = null;
|
|
132
132
|
}
|
|
133
|
+
requiresBrowser(testFile) {
|
|
134
|
+
const hasWebStep = (steps) => {
|
|
135
|
+
return steps.some(step => step.type.startsWith('web_'));
|
|
136
|
+
};
|
|
137
|
+
const hasWebStepInState = (state) => {
|
|
138
|
+
const steps = this.extractStepsFromBlocklyState(state);
|
|
139
|
+
return hasWebStep(steps);
|
|
140
|
+
};
|
|
141
|
+
// Check beforeAll/afterAll hooks
|
|
142
|
+
if (testFile.beforeAll && hasWebStepInState(testFile.beforeAll))
|
|
143
|
+
return true;
|
|
144
|
+
if (testFile.afterAll && hasWebStepInState(testFile.afterAll))
|
|
145
|
+
return true;
|
|
146
|
+
if (testFile.beforeEach && hasWebStepInState(testFile.beforeEach))
|
|
147
|
+
return true;
|
|
148
|
+
if (testFile.afterEach && hasWebStepInState(testFile.afterEach))
|
|
149
|
+
return true;
|
|
150
|
+
// Check all tests
|
|
151
|
+
for (const test of testFile.tests) {
|
|
152
|
+
if (hasWebStepInState(test.steps))
|
|
153
|
+
return true;
|
|
154
|
+
if (test.beforeEach && hasWebStepInState(test.beforeEach))
|
|
155
|
+
return true;
|
|
156
|
+
if (test.afterEach && hasWebStepInState(test.afterEach))
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
133
161
|
async runTestFile(testFile) {
|
|
134
162
|
const results = [];
|
|
135
163
|
// Register custom blocks from procedures
|
|
136
164
|
if (testFile.procedures) {
|
|
137
165
|
this.registerCustomBlocksFromProcedures(testFile.procedures);
|
|
138
166
|
}
|
|
139
|
-
|
|
167
|
+
// Only initialize browser if test file contains web steps
|
|
168
|
+
if (this.requiresBrowser(testFile)) {
|
|
169
|
+
await this.initialize();
|
|
170
|
+
}
|
|
140
171
|
// Create shared execution context for lifecycle hooks
|
|
141
172
|
const sharedContext = {
|
|
142
173
|
variables: new Map(Object.entries({
|
package/dist/server/index.js
CHANGED
|
@@ -27,6 +27,59 @@ const globalsDir = process.env.GLOBALS_DIR || path_1.default.join(process.cwd(),
|
|
|
27
27
|
}).catch(err => {
|
|
28
28
|
console.error('Failed to load plugins:', err);
|
|
29
29
|
});
|
|
30
|
+
/**
|
|
31
|
+
* Merge folder hooks into a test file.
|
|
32
|
+
* Folder hooks are ordered from outermost to innermost folder.
|
|
33
|
+
* - beforeAll: run parent hooks first, then child hooks, then test file hooks
|
|
34
|
+
* - afterAll: run test file hooks first, then child hooks, then parent hooks
|
|
35
|
+
* - beforeEach/afterEach: same pattern
|
|
36
|
+
*/
|
|
37
|
+
function mergeFolderHooksIntoTestFile(testFile, folderHooks) {
|
|
38
|
+
if (!folderHooks || folderHooks.length === 0) {
|
|
39
|
+
return testFile;
|
|
40
|
+
}
|
|
41
|
+
// Collect all steps from folder hooks (parent to child order is already provided)
|
|
42
|
+
const beforeAllSteps = [];
|
|
43
|
+
const afterAllSteps = [];
|
|
44
|
+
const beforeEachSteps = [];
|
|
45
|
+
const afterEachSteps = [];
|
|
46
|
+
// Parent to child order for beforeAll/beforeEach
|
|
47
|
+
for (const hooks of folderHooks) {
|
|
48
|
+
if (hooks.beforeAll)
|
|
49
|
+
beforeAllSteps.push(...hooks.beforeAll);
|
|
50
|
+
if (hooks.beforeEach)
|
|
51
|
+
beforeEachSteps.push(...hooks.beforeEach);
|
|
52
|
+
}
|
|
53
|
+
// Child to parent order for afterAll/afterEach
|
|
54
|
+
for (let i = folderHooks.length - 1; i >= 0; i--) {
|
|
55
|
+
const hooks = folderHooks[i];
|
|
56
|
+
if (hooks.afterAll)
|
|
57
|
+
afterAllSteps.unshift(...hooks.afterAll);
|
|
58
|
+
if (hooks.afterEach)
|
|
59
|
+
afterEachSteps.unshift(...hooks.afterEach);
|
|
60
|
+
}
|
|
61
|
+
// Merge with test file hooks
|
|
62
|
+
const merged = {
|
|
63
|
+
...testFile,
|
|
64
|
+
beforeAll: [
|
|
65
|
+
...beforeAllSteps,
|
|
66
|
+
...(testFile.beforeAll || []),
|
|
67
|
+
],
|
|
68
|
+
afterAll: [
|
|
69
|
+
...(testFile.afterAll || []),
|
|
70
|
+
...afterAllSteps,
|
|
71
|
+
],
|
|
72
|
+
beforeEach: [
|
|
73
|
+
...beforeEachSteps,
|
|
74
|
+
...(testFile.beforeEach || []),
|
|
75
|
+
],
|
|
76
|
+
afterEach: [
|
|
77
|
+
...(testFile.afterEach || []),
|
|
78
|
+
...afterEachSteps,
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
return merged;
|
|
82
|
+
}
|
|
30
83
|
const app = (0, express_1.default)();
|
|
31
84
|
const PORT = process.env.PORT || 3001;
|
|
32
85
|
app.use((0, cors_1.default)());
|
|
@@ -90,11 +143,13 @@ app.put('/api/globals/test-id-attribute', (req, res) => {
|
|
|
90
143
|
// Run tests
|
|
91
144
|
app.post('/api/run', async (req, res) => {
|
|
92
145
|
try {
|
|
93
|
-
const testFile = req.body;
|
|
146
|
+
const { testFile, folderHooks } = req.body;
|
|
94
147
|
if (!testFile || !testFile.tests) {
|
|
95
148
|
return res.status(400).json({ error: 'Invalid test file format' });
|
|
96
149
|
}
|
|
97
150
|
console.log(`Running ${testFile.tests.length} tests from "${testFile.name}"...`);
|
|
151
|
+
// Merge folder hooks into test file (parent to child order for beforeAll, child to parent for afterAll)
|
|
152
|
+
const mergedTestFile = mergeFolderHooksIntoTestFile(testFile, folderHooks || []);
|
|
98
153
|
// Merge global variables with test file variables
|
|
99
154
|
const globalVars = (0, globals_1.getGlobalVariables)();
|
|
100
155
|
const testIdAttr = (0, globals_1.getTestIdAttribute)();
|
|
@@ -105,7 +160,7 @@ app.post('/api/run', async (req, res) => {
|
|
|
105
160
|
testIdAttribute: testIdAttr, // Pass test ID attribute
|
|
106
161
|
baseDir: globalsDir, // Base directory for resolving relative file paths
|
|
107
162
|
});
|
|
108
|
-
const results = await executor.runTestFile(
|
|
163
|
+
const results = await executor.runTestFile(mergedTestFile);
|
|
109
164
|
const passed = results.filter(r => r.status === 'passed').length;
|
|
110
165
|
const failed = results.filter(r => r.status === 'failed').length;
|
|
111
166
|
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
@@ -124,12 +179,15 @@ app.post('/api/run', async (req, res) => {
|
|
|
124
179
|
// Run a single test
|
|
125
180
|
app.post('/api/run/:testId', async (req, res) => {
|
|
126
181
|
try {
|
|
127
|
-
const testFile = req.body;
|
|
182
|
+
const { testFile, folderHooks } = req.body;
|
|
128
183
|
const { testId } = req.params;
|
|
129
184
|
const test = testFile.tests.find(t => t.id === testId);
|
|
130
185
|
if (!test) {
|
|
131
186
|
return res.status(404).json({ error: `Test not found: ${testId}` });
|
|
132
187
|
}
|
|
188
|
+
// For single test runs, merge folder beforeEach/afterEach hooks
|
|
189
|
+
// (beforeAll/afterAll are handled at suite level)
|
|
190
|
+
const mergedTestFile = mergeFolderHooksIntoTestFile(testFile, folderHooks || []);
|
|
133
191
|
// Merge global variables
|
|
134
192
|
const globalVars = (0, globals_1.getGlobalVariables)();
|
|
135
193
|
const testIdAttr = (0, globals_1.getTestIdAttribute)();
|
|
@@ -141,11 +199,11 @@ app.post('/api/run/:testId', async (req, res) => {
|
|
|
141
199
|
baseDir: globalsDir, // Base directory for resolving relative file paths
|
|
142
200
|
});
|
|
143
201
|
// Register custom blocks from procedures before running the test
|
|
144
|
-
if (
|
|
145
|
-
executor.registerProcedures(
|
|
202
|
+
if (mergedTestFile.procedures) {
|
|
203
|
+
executor.registerProcedures(mergedTestFile.procedures);
|
|
146
204
|
}
|
|
147
205
|
await executor.initialize();
|
|
148
|
-
const result = await executor.runTest(test,
|
|
206
|
+
const result = await executor.runTest(test, mergedTestFile.variables);
|
|
149
207
|
await executor.cleanup();
|
|
150
208
|
res.json(result);
|
|
151
209
|
}
|