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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +333 -0
  3. package/dist/cli/executor.d.ts +32 -0
  4. package/dist/cli/executor.js +517 -0
  5. package/dist/cli/index.d.ts +2 -0
  6. package/dist/cli/index.js +411 -0
  7. package/dist/cli/reporters.d.ts +62 -0
  8. package/dist/cli/reporters.js +451 -0
  9. package/dist/client/assets/index-4hbFPUhP.js +2087 -0
  10. package/dist/client/assets/index-4hbFPUhP.js.map +1 -0
  11. package/dist/client/assets/index-Dnk1ti7l.css +1 -0
  12. package/dist/client/index.html +25 -0
  13. package/dist/core/blocks/api.d.ts +2 -0
  14. package/dist/core/blocks/api.js +610 -0
  15. package/dist/core/blocks/data-driven.d.ts +2 -0
  16. package/dist/core/blocks/data-driven.js +245 -0
  17. package/dist/core/blocks/index.d.ts +15 -0
  18. package/dist/core/blocks/index.js +71 -0
  19. package/dist/core/blocks/lifecycle.d.ts +2 -0
  20. package/dist/core/blocks/lifecycle.js +199 -0
  21. package/dist/core/blocks/logic.d.ts +2 -0
  22. package/dist/core/blocks/logic.js +357 -0
  23. package/dist/core/blocks/playwright.d.ts +2 -0
  24. package/dist/core/blocks/playwright.js +764 -0
  25. package/dist/core/blocks/procedures.d.ts +5 -0
  26. package/dist/core/blocks/procedures.js +321 -0
  27. package/dist/core/index.d.ts +5 -0
  28. package/dist/core/index.js +44 -0
  29. package/dist/core/plugins.d.ts +66 -0
  30. package/dist/core/plugins.js +118 -0
  31. package/dist/core/types.d.ts +153 -0
  32. package/dist/core/types.js +2 -0
  33. package/dist/server/codegenManager.d.ts +54 -0
  34. package/dist/server/codegenManager.js +259 -0
  35. package/dist/server/codegenParser.d.ts +17 -0
  36. package/dist/server/codegenParser.js +598 -0
  37. package/dist/server/executor.d.ts +37 -0
  38. package/dist/server/executor.js +672 -0
  39. package/dist/server/globals.d.ts +85 -0
  40. package/dist/server/globals.js +273 -0
  41. package/dist/server/index.d.ts +2 -0
  42. package/dist/server/index.js +361 -0
  43. package/dist/server/plugins.d.ts +55 -0
  44. package/dist/server/plugins.js +206 -0
  45. 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
+ }
@@ -0,0 +1,2 @@
1
+ import { TestExecutor } from './executor';
2
+ export { TestExecutor };