testblocks 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.
- package/LICENSE +21 -0
- package/README.md +333 -0
- package/dist/cli/executor.d.ts +32 -0
- package/dist/cli/executor.js +517 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +411 -0
- package/dist/cli/reporters.d.ts +62 -0
- package/dist/cli/reporters.js +451 -0
- package/dist/client/assets/index-4hbFPUhP.js +2087 -0
- package/dist/client/assets/index-4hbFPUhP.js.map +1 -0
- package/dist/client/assets/index-Dnk1ti7l.css +1 -0
- package/dist/client/index.html +25 -0
- package/dist/core/blocks/api.d.ts +2 -0
- package/dist/core/blocks/api.js +610 -0
- package/dist/core/blocks/data-driven.d.ts +2 -0
- package/dist/core/blocks/data-driven.js +245 -0
- package/dist/core/blocks/index.d.ts +15 -0
- package/dist/core/blocks/index.js +71 -0
- package/dist/core/blocks/lifecycle.d.ts +2 -0
- package/dist/core/blocks/lifecycle.js +199 -0
- package/dist/core/blocks/logic.d.ts +2 -0
- package/dist/core/blocks/logic.js +357 -0
- package/dist/core/blocks/playwright.d.ts +2 -0
- package/dist/core/blocks/playwright.js +764 -0
- package/dist/core/blocks/procedures.d.ts +5 -0
- package/dist/core/blocks/procedures.js +321 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +44 -0
- package/dist/core/plugins.d.ts +66 -0
- package/dist/core/plugins.js +118 -0
- package/dist/core/types.d.ts +153 -0
- package/dist/core/types.js +2 -0
- package/dist/server/codegenManager.d.ts +54 -0
- package/dist/server/codegenManager.js +259 -0
- package/dist/server/codegenParser.d.ts +17 -0
- package/dist/server/codegenParser.js +598 -0
- package/dist/server/executor.d.ts +37 -0
- package/dist/server/executor.js +672 -0
- package/dist/server/globals.d.ts +85 -0
- package/dist/server/globals.js +273 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +361 -0
- package/dist/server/plugins.d.ts +55 -0
- package/dist/server/plugins.js +206 -0
- package/package.json +103 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logicBlocks = void 0;
|
|
4
|
+
// Logic and Control Flow Blocks
|
|
5
|
+
exports.logicBlocks = [
|
|
6
|
+
// Set Variable
|
|
7
|
+
{
|
|
8
|
+
type: 'logic_set_variable',
|
|
9
|
+
category: 'Logic',
|
|
10
|
+
color: '#795548',
|
|
11
|
+
tooltip: 'Set a variable value',
|
|
12
|
+
inputs: [
|
|
13
|
+
{ name: 'NAME', type: 'field', fieldType: 'text', required: true },
|
|
14
|
+
{ name: 'VALUE', type: 'value', required: true },
|
|
15
|
+
],
|
|
16
|
+
previousStatement: true,
|
|
17
|
+
nextStatement: true,
|
|
18
|
+
execute: async (params, context) => {
|
|
19
|
+
const name = params.NAME;
|
|
20
|
+
const value = params.VALUE;
|
|
21
|
+
context.variables.set(name, value);
|
|
22
|
+
context.logger.debug(`Set variable ${name} = ${JSON.stringify(value)}`);
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
// Get Variable
|
|
26
|
+
{
|
|
27
|
+
type: 'logic_get_variable',
|
|
28
|
+
category: 'Logic',
|
|
29
|
+
color: '#795548',
|
|
30
|
+
tooltip: 'Get a variable value',
|
|
31
|
+
inputs: [
|
|
32
|
+
{ name: 'NAME', type: 'field', fieldType: 'text', required: true },
|
|
33
|
+
],
|
|
34
|
+
output: { type: ['String', 'Number', 'Boolean', 'Object', 'Array'] },
|
|
35
|
+
execute: async (params, context) => {
|
|
36
|
+
const name = params.NAME;
|
|
37
|
+
return context.variables.get(name);
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
// If Condition
|
|
41
|
+
{
|
|
42
|
+
type: 'logic_if',
|
|
43
|
+
category: 'Logic',
|
|
44
|
+
color: '#5C6BC0',
|
|
45
|
+
tooltip: 'Execute blocks if condition is true',
|
|
46
|
+
inputs: [
|
|
47
|
+
{ name: 'CONDITION', type: 'value', check: 'Boolean', required: true },
|
|
48
|
+
{ name: 'DO', type: 'statement' },
|
|
49
|
+
{ name: 'ELSE', type: 'statement' },
|
|
50
|
+
],
|
|
51
|
+
previousStatement: true,
|
|
52
|
+
nextStatement: true,
|
|
53
|
+
execute: async (params, _context) => {
|
|
54
|
+
const condition = params.CONDITION;
|
|
55
|
+
if (condition && params.DO) {
|
|
56
|
+
// Execute DO block - handled by executor
|
|
57
|
+
return { branch: 'DO' };
|
|
58
|
+
}
|
|
59
|
+
else if (!condition && params.ELSE) {
|
|
60
|
+
// Execute ELSE block - handled by executor
|
|
61
|
+
return { branch: 'ELSE' };
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
// Compare Values
|
|
66
|
+
{
|
|
67
|
+
type: 'logic_compare',
|
|
68
|
+
category: 'Logic',
|
|
69
|
+
color: '#5C6BC0',
|
|
70
|
+
tooltip: 'Compare two values',
|
|
71
|
+
inputs: [
|
|
72
|
+
{ name: 'A', type: 'value', required: true },
|
|
73
|
+
{ name: 'OP', type: 'field', fieldType: 'dropdown', options: [['=', 'eq'], ['≠', 'neq'], ['<', 'lt'], ['≤', 'lte'], ['>', 'gt'], ['≥', 'gte'], ['contains', 'contains']] },
|
|
74
|
+
{ name: 'B', type: 'value', required: true },
|
|
75
|
+
],
|
|
76
|
+
output: { type: 'Boolean' },
|
|
77
|
+
execute: async (params, _context) => {
|
|
78
|
+
const a = params.A;
|
|
79
|
+
const b = params.B;
|
|
80
|
+
const op = params.OP;
|
|
81
|
+
switch (op) {
|
|
82
|
+
case 'eq':
|
|
83
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
84
|
+
case 'neq':
|
|
85
|
+
return JSON.stringify(a) !== JSON.stringify(b);
|
|
86
|
+
case 'lt':
|
|
87
|
+
return a < b;
|
|
88
|
+
case 'lte':
|
|
89
|
+
return a <= b;
|
|
90
|
+
case 'gt':
|
|
91
|
+
return a > b;
|
|
92
|
+
case 'gte':
|
|
93
|
+
return a >= b;
|
|
94
|
+
case 'contains':
|
|
95
|
+
if (typeof a === 'string')
|
|
96
|
+
return a.includes(b);
|
|
97
|
+
if (Array.isArray(a))
|
|
98
|
+
return a.includes(b);
|
|
99
|
+
return false;
|
|
100
|
+
default:
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
// Boolean Operations
|
|
106
|
+
{
|
|
107
|
+
type: 'logic_boolean_op',
|
|
108
|
+
category: 'Logic',
|
|
109
|
+
color: '#5C6BC0',
|
|
110
|
+
tooltip: 'Combine boolean values',
|
|
111
|
+
inputs: [
|
|
112
|
+
{ name: 'A', type: 'value', check: 'Boolean', required: true },
|
|
113
|
+
{ name: 'OP', type: 'field', fieldType: 'dropdown', options: [['and', 'and'], ['or', 'or']] },
|
|
114
|
+
{ name: 'B', type: 'value', check: 'Boolean', required: true },
|
|
115
|
+
],
|
|
116
|
+
output: { type: 'Boolean' },
|
|
117
|
+
execute: async (params) => {
|
|
118
|
+
const a = params.A;
|
|
119
|
+
const b = params.B;
|
|
120
|
+
const op = params.OP;
|
|
121
|
+
return op === 'and' ? a && b : a || b;
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
// Not
|
|
125
|
+
{
|
|
126
|
+
type: 'logic_not',
|
|
127
|
+
category: 'Logic',
|
|
128
|
+
color: '#5C6BC0',
|
|
129
|
+
tooltip: 'Negate a boolean value',
|
|
130
|
+
inputs: [
|
|
131
|
+
{ name: 'VALUE', type: 'value', check: 'Boolean', required: true },
|
|
132
|
+
],
|
|
133
|
+
output: { type: 'Boolean' },
|
|
134
|
+
execute: async (params) => {
|
|
135
|
+
return !params.VALUE;
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
// Loop (repeat n times)
|
|
139
|
+
{
|
|
140
|
+
type: 'logic_repeat',
|
|
141
|
+
category: 'Logic',
|
|
142
|
+
color: '#5C6BC0',
|
|
143
|
+
tooltip: 'Repeat blocks a specified number of times',
|
|
144
|
+
inputs: [
|
|
145
|
+
{ name: 'TIMES', type: 'field', fieldType: 'number', default: 10, required: true },
|
|
146
|
+
{ name: 'DO', type: 'statement' },
|
|
147
|
+
],
|
|
148
|
+
previousStatement: true,
|
|
149
|
+
nextStatement: true,
|
|
150
|
+
execute: async (params, _context) => {
|
|
151
|
+
const times = params.TIMES;
|
|
152
|
+
return { loop: true, times, statement: 'DO' };
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
// For Each
|
|
156
|
+
{
|
|
157
|
+
type: 'logic_foreach',
|
|
158
|
+
category: 'Logic',
|
|
159
|
+
color: '#5C6BC0',
|
|
160
|
+
tooltip: 'Iterate over an array',
|
|
161
|
+
inputs: [
|
|
162
|
+
{ name: 'ARRAY', type: 'value', check: 'Array', required: true },
|
|
163
|
+
{ name: 'VAR', type: 'field', fieldType: 'text', default: 'item', required: true },
|
|
164
|
+
{ name: 'DO', type: 'statement' },
|
|
165
|
+
],
|
|
166
|
+
previousStatement: true,
|
|
167
|
+
nextStatement: true,
|
|
168
|
+
execute: async (params, _context) => {
|
|
169
|
+
const array = params.ARRAY;
|
|
170
|
+
const varName = params.VAR;
|
|
171
|
+
return { loop: true, array, varName, statement: 'DO' };
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
// Try/Catch
|
|
175
|
+
{
|
|
176
|
+
type: 'logic_try_catch',
|
|
177
|
+
category: 'Logic',
|
|
178
|
+
color: '#5C6BC0',
|
|
179
|
+
tooltip: 'Handle errors gracefully',
|
|
180
|
+
inputs: [
|
|
181
|
+
{ name: 'TRY', type: 'statement' },
|
|
182
|
+
{ name: 'CATCH', type: 'statement' },
|
|
183
|
+
],
|
|
184
|
+
previousStatement: true,
|
|
185
|
+
nextStatement: true,
|
|
186
|
+
execute: async (_params, _context) => {
|
|
187
|
+
return { tryCatch: true };
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
// Log Message
|
|
191
|
+
{
|
|
192
|
+
type: 'logic_log',
|
|
193
|
+
category: 'Logic',
|
|
194
|
+
color: '#607D8B',
|
|
195
|
+
tooltip: 'Log a message',
|
|
196
|
+
inputs: [
|
|
197
|
+
{ name: 'LEVEL', type: 'field', fieldType: 'dropdown', options: [['Info', 'info'], ['Warning', 'warn'], ['Error', 'error'], ['Debug', 'debug']] },
|
|
198
|
+
{ name: 'MESSAGE', type: 'field', fieldType: 'text', required: true },
|
|
199
|
+
],
|
|
200
|
+
previousStatement: true,
|
|
201
|
+
nextStatement: true,
|
|
202
|
+
execute: async (params, context) => {
|
|
203
|
+
const level = params.LEVEL || 'info';
|
|
204
|
+
const message = resolveVariables(params.MESSAGE, context);
|
|
205
|
+
context.logger[level](message);
|
|
206
|
+
return { _message: message, _summary: message };
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
// Comment (no-op, for documentation)
|
|
210
|
+
{
|
|
211
|
+
type: 'logic_comment',
|
|
212
|
+
category: 'Logic',
|
|
213
|
+
color: '#9E9E9E',
|
|
214
|
+
tooltip: 'Add a comment (does nothing)',
|
|
215
|
+
inputs: [
|
|
216
|
+
{ name: 'TEXT', type: 'field', fieldType: 'text', default: 'Comment' },
|
|
217
|
+
],
|
|
218
|
+
previousStatement: true,
|
|
219
|
+
nextStatement: true,
|
|
220
|
+
execute: async () => {
|
|
221
|
+
// No-op
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
// Text/String block
|
|
225
|
+
{
|
|
226
|
+
type: 'logic_text',
|
|
227
|
+
category: 'Logic',
|
|
228
|
+
color: '#795548',
|
|
229
|
+
tooltip: 'A text value',
|
|
230
|
+
inputs: [
|
|
231
|
+
{ name: 'TEXT', type: 'field', fieldType: 'text', default: '' },
|
|
232
|
+
],
|
|
233
|
+
output: { type: 'String' },
|
|
234
|
+
execute: async (params, context) => {
|
|
235
|
+
return resolveVariables(params.TEXT, context);
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
// Number block
|
|
239
|
+
{
|
|
240
|
+
type: 'logic_number',
|
|
241
|
+
category: 'Logic',
|
|
242
|
+
color: '#795548',
|
|
243
|
+
tooltip: 'A number value',
|
|
244
|
+
inputs: [
|
|
245
|
+
{ name: 'NUM', type: 'field', fieldType: 'number', default: 0 },
|
|
246
|
+
],
|
|
247
|
+
output: { type: 'Number' },
|
|
248
|
+
execute: async (params) => {
|
|
249
|
+
return params.NUM;
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
// Boolean block
|
|
253
|
+
{
|
|
254
|
+
type: 'logic_boolean',
|
|
255
|
+
category: 'Logic',
|
|
256
|
+
color: '#795548',
|
|
257
|
+
tooltip: 'A boolean value',
|
|
258
|
+
inputs: [
|
|
259
|
+
{ name: 'BOOL', type: 'field', fieldType: 'dropdown', options: [['true', 'true'], ['false', 'false']] },
|
|
260
|
+
],
|
|
261
|
+
output: { type: 'Boolean' },
|
|
262
|
+
execute: async (params) => {
|
|
263
|
+
return params.BOOL === 'true';
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
// Create Object
|
|
267
|
+
{
|
|
268
|
+
type: 'logic_object',
|
|
269
|
+
category: 'Logic',
|
|
270
|
+
color: '#795548',
|
|
271
|
+
tooltip: 'Create a JSON object',
|
|
272
|
+
inputs: [
|
|
273
|
+
{ name: 'JSON', type: 'field', fieldType: 'text', default: '{}' },
|
|
274
|
+
],
|
|
275
|
+
output: { type: 'Object' },
|
|
276
|
+
execute: async (params, context) => {
|
|
277
|
+
const json = resolveVariables(params.JSON, context);
|
|
278
|
+
return JSON.parse(json);
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
// Create Array
|
|
282
|
+
{
|
|
283
|
+
type: 'logic_array',
|
|
284
|
+
category: 'Logic',
|
|
285
|
+
color: '#795548',
|
|
286
|
+
tooltip: 'Create an array',
|
|
287
|
+
inputs: [
|
|
288
|
+
{ name: 'JSON', type: 'field', fieldType: 'text', default: '[]' },
|
|
289
|
+
],
|
|
290
|
+
output: { type: 'Array' },
|
|
291
|
+
execute: async (params, context) => {
|
|
292
|
+
const json = resolveVariables(params.JSON, context);
|
|
293
|
+
return JSON.parse(json);
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
// Fail Test
|
|
297
|
+
{
|
|
298
|
+
type: 'logic_fail',
|
|
299
|
+
category: 'Logic',
|
|
300
|
+
color: '#f44336',
|
|
301
|
+
tooltip: 'Fail the test with a message',
|
|
302
|
+
inputs: [
|
|
303
|
+
{ name: 'MESSAGE', type: 'field', fieldType: 'text', default: 'Test failed' },
|
|
304
|
+
],
|
|
305
|
+
previousStatement: true,
|
|
306
|
+
execute: async (params, context) => {
|
|
307
|
+
const message = resolveVariables(params.MESSAGE, context);
|
|
308
|
+
throw new Error(message);
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
// Assert
|
|
312
|
+
{
|
|
313
|
+
type: 'logic_assert',
|
|
314
|
+
category: 'Logic',
|
|
315
|
+
color: '#FF9800',
|
|
316
|
+
tooltip: 'Assert a condition is true',
|
|
317
|
+
inputs: [
|
|
318
|
+
{ name: 'CONDITION', type: 'value', check: 'Boolean', required: true },
|
|
319
|
+
{ name: 'MESSAGE', type: 'field', fieldType: 'text', default: 'Assertion failed' },
|
|
320
|
+
],
|
|
321
|
+
previousStatement: true,
|
|
322
|
+
nextStatement: true,
|
|
323
|
+
execute: async (params, context) => {
|
|
324
|
+
const condition = params.CONDITION;
|
|
325
|
+
const message = resolveVariables(params.MESSAGE, context);
|
|
326
|
+
if (!condition) {
|
|
327
|
+
throw new Error(message);
|
|
328
|
+
}
|
|
329
|
+
context.logger.info('✓ Assertion passed');
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
];
|
|
333
|
+
// Helper function
|
|
334
|
+
function resolveVariables(text, context) {
|
|
335
|
+
// Match ${varName} or ${varName.property.path}
|
|
336
|
+
return text.replace(/\$\{([\w.]+)\}/g, (match, path) => {
|
|
337
|
+
const parts = path.split('.');
|
|
338
|
+
const varName = parts[0];
|
|
339
|
+
let value = context.variables.get(varName);
|
|
340
|
+
// Navigate through object properties if path has dots
|
|
341
|
+
if (parts.length > 1 && value !== undefined && value !== null) {
|
|
342
|
+
for (let i = 1; i < parts.length; i++) {
|
|
343
|
+
if (value === undefined || value === null)
|
|
344
|
+
break;
|
|
345
|
+
value = value[parts[i]];
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (value === undefined || value === null) {
|
|
349
|
+
return match; // Keep original if not found
|
|
350
|
+
}
|
|
351
|
+
// Return stringified value
|
|
352
|
+
if (typeof value === 'object') {
|
|
353
|
+
return JSON.stringify(value);
|
|
354
|
+
}
|
|
355
|
+
return String(value);
|
|
356
|
+
});
|
|
357
|
+
}
|