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,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Globals and Snippets Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads shared configuration from:
|
|
5
|
+
* - globals.json - Shared variables across all test files
|
|
6
|
+
* - snippets/ - Reusable block sequences (composite blocks)
|
|
7
|
+
*/
|
|
8
|
+
import { TestStep } from '../core';
|
|
9
|
+
export interface GlobalsConfig {
|
|
10
|
+
variables?: Record<string, unknown>;
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
testIdAttribute?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface SnippetDefinition {
|
|
17
|
+
name: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
category?: string;
|
|
20
|
+
color?: string;
|
|
21
|
+
params?: SnippetParam[];
|
|
22
|
+
steps: TestStep[];
|
|
23
|
+
}
|
|
24
|
+
export interface SnippetParam {
|
|
25
|
+
name: string;
|
|
26
|
+
type: 'string' | 'number' | 'boolean' | 'any';
|
|
27
|
+
default?: unknown;
|
|
28
|
+
description?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Set the directory to look for globals.json and snippets/
|
|
32
|
+
*/
|
|
33
|
+
export declare function setGlobalsDirectory(dir: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get the current globals directory
|
|
36
|
+
*/
|
|
37
|
+
export declare function getGlobalsDirectory(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Load globals.json from the globals directory
|
|
40
|
+
*/
|
|
41
|
+
export declare function loadGlobals(): GlobalsConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Get the loaded globals
|
|
44
|
+
*/
|
|
45
|
+
export declare function getGlobals(): GlobalsConfig;
|
|
46
|
+
/**
|
|
47
|
+
* Get global variables
|
|
48
|
+
*/
|
|
49
|
+
export declare function getGlobalVariables(): Record<string, unknown>;
|
|
50
|
+
/**
|
|
51
|
+
* Get the configured test ID attribute (defaults to 'data-testid')
|
|
52
|
+
*/
|
|
53
|
+
export declare function getTestIdAttribute(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Set the test ID attribute and persist to globals.json
|
|
56
|
+
*/
|
|
57
|
+
export declare function setTestIdAttribute(attribute: string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Discover snippet files in the snippets directory
|
|
60
|
+
*/
|
|
61
|
+
export declare function discoverSnippets(): string[];
|
|
62
|
+
/**
|
|
63
|
+
* Load a specific snippet by name
|
|
64
|
+
*/
|
|
65
|
+
export declare function loadSnippet(snippetName: string): SnippetDefinition | null;
|
|
66
|
+
/**
|
|
67
|
+
* Load all discovered snippets
|
|
68
|
+
*/
|
|
69
|
+
export declare function loadAllSnippets(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Get a loaded snippet by name
|
|
72
|
+
*/
|
|
73
|
+
export declare function getSnippet(snippetName: string): SnippetDefinition | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Get all loaded snippets
|
|
76
|
+
*/
|
|
77
|
+
export declare function getAllSnippets(): SnippetDefinition[];
|
|
78
|
+
/**
|
|
79
|
+
* Initialize globals and snippets from a directory
|
|
80
|
+
*/
|
|
81
|
+
export declare function initializeGlobalsAndSnippets(dir?: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Clear loaded globals and snippets
|
|
84
|
+
*/
|
|
85
|
+
export declare function clearGlobalsAndSnippets(): void;
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Globals and Snippets Loader
|
|
4
|
+
*
|
|
5
|
+
* Loads shared configuration from:
|
|
6
|
+
* - globals.json - Shared variables across all test files
|
|
7
|
+
* - snippets/ - Reusable block sequences (composite blocks)
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.setGlobalsDirectory = setGlobalsDirectory;
|
|
44
|
+
exports.getGlobalsDirectory = getGlobalsDirectory;
|
|
45
|
+
exports.loadGlobals = loadGlobals;
|
|
46
|
+
exports.getGlobals = getGlobals;
|
|
47
|
+
exports.getGlobalVariables = getGlobalVariables;
|
|
48
|
+
exports.getTestIdAttribute = getTestIdAttribute;
|
|
49
|
+
exports.setTestIdAttribute = setTestIdAttribute;
|
|
50
|
+
exports.discoverSnippets = discoverSnippets;
|
|
51
|
+
exports.loadSnippet = loadSnippet;
|
|
52
|
+
exports.loadAllSnippets = loadAllSnippets;
|
|
53
|
+
exports.getSnippet = getSnippet;
|
|
54
|
+
exports.getAllSnippets = getAllSnippets;
|
|
55
|
+
exports.initializeGlobalsAndSnippets = initializeGlobalsAndSnippets;
|
|
56
|
+
exports.clearGlobalsAndSnippets = clearGlobalsAndSnippets;
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
const path = __importStar(require("path"));
|
|
59
|
+
const core_1 = require("../core");
|
|
60
|
+
// Store loaded globals and snippets
|
|
61
|
+
let globalsDirectory = process.cwd();
|
|
62
|
+
let loadedGlobals = {};
|
|
63
|
+
const loadedSnippets = new Map();
|
|
64
|
+
/**
|
|
65
|
+
* Set the directory to look for globals.json and snippets/
|
|
66
|
+
*/
|
|
67
|
+
function setGlobalsDirectory(dir) {
|
|
68
|
+
globalsDirectory = path.isAbsolute(dir) ? dir : path.join(process.cwd(), dir);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the current globals directory
|
|
72
|
+
*/
|
|
73
|
+
function getGlobalsDirectory() {
|
|
74
|
+
return globalsDirectory;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Load globals.json from the globals directory
|
|
78
|
+
*/
|
|
79
|
+
function loadGlobals() {
|
|
80
|
+
const globalsPath = path.join(globalsDirectory, 'globals.json');
|
|
81
|
+
if (!fs.existsSync(globalsPath)) {
|
|
82
|
+
console.log(`No globals.json found at ${globalsPath}`);
|
|
83
|
+
return {};
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const content = fs.readFileSync(globalsPath, 'utf-8');
|
|
87
|
+
loadedGlobals = JSON.parse(content);
|
|
88
|
+
console.log(`Loaded globals from ${globalsPath}`);
|
|
89
|
+
return loadedGlobals;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error(`Failed to load globals.json:`, error);
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get the loaded globals
|
|
98
|
+
*/
|
|
99
|
+
function getGlobals() {
|
|
100
|
+
return loadedGlobals;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get global variables
|
|
104
|
+
*/
|
|
105
|
+
function getGlobalVariables() {
|
|
106
|
+
return loadedGlobals.variables || {};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the configured test ID attribute (defaults to 'data-testid')
|
|
110
|
+
*/
|
|
111
|
+
function getTestIdAttribute() {
|
|
112
|
+
return loadedGlobals.testIdAttribute || 'data-testid';
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Set the test ID attribute and persist to globals.json
|
|
116
|
+
*/
|
|
117
|
+
function setTestIdAttribute(attribute) {
|
|
118
|
+
const config = loadedGlobals;
|
|
119
|
+
config.testIdAttribute = attribute;
|
|
120
|
+
saveGlobals();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Save globals.json to disk
|
|
124
|
+
*/
|
|
125
|
+
function saveGlobals() {
|
|
126
|
+
const globalsPath = path.join(globalsDirectory, 'globals.json');
|
|
127
|
+
try {
|
|
128
|
+
fs.writeFileSync(globalsPath, JSON.stringify(loadedGlobals, null, 2), 'utf-8');
|
|
129
|
+
console.log(`Saved globals to ${globalsPath}`);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error(`Failed to save globals.json:`, error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Discover snippet files in the snippets directory
|
|
137
|
+
*/
|
|
138
|
+
function discoverSnippets() {
|
|
139
|
+
const snippetsDir = path.join(globalsDirectory, 'snippets');
|
|
140
|
+
if (!fs.existsSync(snippetsDir)) {
|
|
141
|
+
console.log(`No snippets directory found at ${snippetsDir}`);
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
const files = fs.readdirSync(snippetsDir);
|
|
145
|
+
const snippets = [];
|
|
146
|
+
for (const file of files) {
|
|
147
|
+
if (file.endsWith('.snippet.json') || file.endsWith('.testblocks.json')) {
|
|
148
|
+
const snippetName = file.replace(/\.(snippet|testblocks)\.json$/, '');
|
|
149
|
+
snippets.push(snippetName);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
console.log(`Discovered ${snippets.length} snippet(s): ${snippets.join(', ')}`);
|
|
153
|
+
return snippets;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Load a specific snippet by name
|
|
157
|
+
*/
|
|
158
|
+
function loadSnippet(snippetName) {
|
|
159
|
+
if (loadedSnippets.has(snippetName)) {
|
|
160
|
+
return loadedSnippets.get(snippetName);
|
|
161
|
+
}
|
|
162
|
+
const snippetsDir = path.join(globalsDirectory, 'snippets');
|
|
163
|
+
const snippetPath = path.join(snippetsDir, `${snippetName}.snippet.json`);
|
|
164
|
+
const altPath = path.join(snippetsDir, `${snippetName}.testblocks.json`);
|
|
165
|
+
let filePath = null;
|
|
166
|
+
if (fs.existsSync(snippetPath)) {
|
|
167
|
+
filePath = snippetPath;
|
|
168
|
+
}
|
|
169
|
+
else if (fs.existsSync(altPath)) {
|
|
170
|
+
filePath = altPath;
|
|
171
|
+
}
|
|
172
|
+
if (!filePath) {
|
|
173
|
+
console.error(`Snippet not found: ${snippetName}`);
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
178
|
+
const snippet = JSON.parse(content);
|
|
179
|
+
// Ensure name is set
|
|
180
|
+
if (!snippet.name) {
|
|
181
|
+
snippet.name = snippetName;
|
|
182
|
+
}
|
|
183
|
+
loadedSnippets.set(snippetName, snippet);
|
|
184
|
+
console.log(`Loaded snippet: ${snippetName}`);
|
|
185
|
+
// Register as a block
|
|
186
|
+
registerSnippetAsBlock(snippet);
|
|
187
|
+
return snippet;
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
console.error(`Failed to load snippet ${snippetName}:`, error);
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Load all discovered snippets
|
|
196
|
+
*/
|
|
197
|
+
function loadAllSnippets() {
|
|
198
|
+
const snippetNames = discoverSnippets();
|
|
199
|
+
for (const name of snippetNames) {
|
|
200
|
+
loadSnippet(name);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Register a snippet as a custom composite block
|
|
205
|
+
*/
|
|
206
|
+
function registerSnippetAsBlock(snippet) {
|
|
207
|
+
const blockType = `snippet_${snippet.name.toLowerCase().replace(/[^a-z0-9]/g, '_')}`;
|
|
208
|
+
// Check if already registered
|
|
209
|
+
if ((0, core_1.getBlock)(blockType)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const blockDef = {
|
|
213
|
+
type: blockType,
|
|
214
|
+
category: snippet.category || 'Snippets',
|
|
215
|
+
color: snippet.color || '#795548',
|
|
216
|
+
tooltip: snippet.description || `Snippet: ${snippet.name}`,
|
|
217
|
+
inputs: (snippet.params || []).map(param => ({
|
|
218
|
+
name: param.name.toUpperCase(),
|
|
219
|
+
type: 'field',
|
|
220
|
+
fieldType: param.type === 'number' ? 'number' : 'text',
|
|
221
|
+
default: param.default,
|
|
222
|
+
})),
|
|
223
|
+
previousStatement: true,
|
|
224
|
+
nextStatement: true,
|
|
225
|
+
execute: async (params, context) => {
|
|
226
|
+
context.logger.info(`Executing snippet: ${snippet.name}`);
|
|
227
|
+
// Set snippet parameters as variables
|
|
228
|
+
if (snippet.params) {
|
|
229
|
+
for (const param of snippet.params) {
|
|
230
|
+
const value = params[param.name.toUpperCase()] ?? param.default;
|
|
231
|
+
context.variables.set(`snippet_${param.name}`, value);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Return the steps to be executed by the executor
|
|
235
|
+
return {
|
|
236
|
+
compoundAction: `snippet:${snippet.name}`,
|
|
237
|
+
steps: snippet.steps,
|
|
238
|
+
_summary: `Run snippet: ${snippet.name}`,
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
(0, core_1.registerBlock)(blockDef);
|
|
243
|
+
console.log(`Registered snippet block: ${blockType}`);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get a loaded snippet by name
|
|
247
|
+
*/
|
|
248
|
+
function getSnippet(snippetName) {
|
|
249
|
+
return loadedSnippets.get(snippetName);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Get all loaded snippets
|
|
253
|
+
*/
|
|
254
|
+
function getAllSnippets() {
|
|
255
|
+
return Array.from(loadedSnippets.values());
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Initialize globals and snippets from a directory
|
|
259
|
+
*/
|
|
260
|
+
function initializeGlobalsAndSnippets(dir) {
|
|
261
|
+
if (dir) {
|
|
262
|
+
setGlobalsDirectory(dir);
|
|
263
|
+
}
|
|
264
|
+
loadGlobals();
|
|
265
|
+
loadAllSnippets();
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Clear loaded globals and snippets
|
|
269
|
+
*/
|
|
270
|
+
function clearGlobalsAndSnippets() {
|
|
271
|
+
loadedGlobals = {};
|
|
272
|
+
loadedSnippets.clear();
|
|
273
|
+
}
|