@testsmith/testblocks 0.6.0 → 0.8.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 (71) hide show
  1. package/dist/cli/executor.d.ts +4 -1
  2. package/dist/cli/executor.js +101 -5
  3. package/dist/cli/index.js +148 -4
  4. package/dist/cli/reporters/ConsoleReporter.d.ts +12 -0
  5. package/dist/cli/reporters/ConsoleReporter.js +39 -0
  6. package/dist/cli/reporters/HTMLReporter.d.ts +19 -0
  7. package/dist/cli/reporters/HTMLReporter.js +506 -0
  8. package/dist/cli/reporters/JSONReporter.d.ts +15 -0
  9. package/dist/cli/reporters/JSONReporter.js +80 -0
  10. package/dist/cli/reporters/JUnitReporter.d.ts +19 -0
  11. package/dist/cli/reporters/JUnitReporter.js +105 -0
  12. package/dist/cli/reporters/index.d.ts +17 -0
  13. package/dist/cli/reporters/index.js +31 -0
  14. package/dist/cli/reporters/types.d.ts +28 -0
  15. package/dist/cli/reporters/types.js +2 -0
  16. package/dist/cli/reporters/utils.d.ts +31 -0
  17. package/dist/cli/reporters/utils.js +136 -0
  18. package/dist/cli/reporters.d.ts +13 -62
  19. package/dist/cli/reporters.js +16 -719
  20. package/dist/client/assets/index-Boo8ZrY_.js +2195 -0
  21. package/dist/client/assets/{index-dXniUrbi.js.map → index-Boo8ZrY_.js.map} +1 -1
  22. package/dist/client/assets/index-OxNH9dW-.css +1 -0
  23. package/dist/client/index.html +2 -2
  24. package/dist/core/blocks/api.js +3 -6
  25. package/dist/core/blocks/assertions.d.ts +31 -0
  26. package/dist/core/blocks/assertions.js +72 -0
  27. package/dist/core/blocks/index.d.ts +1 -0
  28. package/dist/core/blocks/index.js +6 -1
  29. package/dist/core/blocks/lifecycle.js +5 -3
  30. package/dist/core/blocks/logic.js +2 -3
  31. package/dist/core/blocks/playwright/assertions.d.ts +5 -0
  32. package/dist/core/blocks/playwright/assertions.js +321 -0
  33. package/dist/core/blocks/playwright/index.d.ts +17 -0
  34. package/dist/core/blocks/playwright/index.js +49 -0
  35. package/dist/core/blocks/playwright/interactions.d.ts +5 -0
  36. package/dist/core/blocks/playwright/interactions.js +191 -0
  37. package/dist/core/blocks/playwright/navigation.d.ts +5 -0
  38. package/dist/core/blocks/playwright/navigation.js +133 -0
  39. package/dist/core/blocks/playwright/retrieval.d.ts +5 -0
  40. package/dist/core/blocks/playwright/retrieval.js +144 -0
  41. package/dist/core/blocks/playwright/types.d.ts +65 -0
  42. package/dist/core/blocks/playwright/types.js +5 -0
  43. package/dist/core/blocks/playwright/utils.d.ts +26 -0
  44. package/dist/core/blocks/playwright/utils.js +137 -0
  45. package/dist/core/blocks/playwright.d.ts +13 -2
  46. package/dist/core/blocks/playwright.js +14 -761
  47. package/dist/core/executor/BaseTestExecutor.d.ts +60 -0
  48. package/dist/core/executor/BaseTestExecutor.js +297 -0
  49. package/dist/core/executor/index.d.ts +1 -0
  50. package/dist/core/executor/index.js +5 -0
  51. package/dist/core/index.d.ts +1 -0
  52. package/dist/core/index.js +4 -0
  53. package/dist/core/types.d.ts +12 -0
  54. package/dist/core/utils/blocklyParser.d.ts +18 -0
  55. package/dist/core/utils/blocklyParser.js +84 -0
  56. package/dist/core/utils/dataLoader.d.ts +9 -0
  57. package/dist/core/utils/dataLoader.js +117 -0
  58. package/dist/core/utils/index.d.ts +2 -0
  59. package/dist/core/utils/index.js +12 -0
  60. package/dist/core/utils/logger.d.ts +14 -0
  61. package/dist/core/utils/logger.js +48 -0
  62. package/dist/core/utils/variableResolver.d.ts +24 -0
  63. package/dist/core/utils/variableResolver.js +92 -0
  64. package/dist/server/executor.d.ts +6 -0
  65. package/dist/server/executor.js +207 -47
  66. package/dist/server/globals.d.ts +6 -1
  67. package/dist/server/globals.js +7 -0
  68. package/dist/server/startServer.js +15 -0
  69. package/package.json +1 -1
  70. package/dist/client/assets/index-dXniUrbi.js +0 -2193
  71. package/dist/client/assets/index-oTTttNKd.css +0 -1
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.navigationBlocks = void 0;
4
+ const utils_1 = require("./utils");
5
+ /**
6
+ * Navigation and waiting blocks for Playwright
7
+ */
8
+ exports.navigationBlocks = [
9
+ // Navigate to URL
10
+ {
11
+ type: 'web_navigate',
12
+ category: 'Web',
13
+ color: '#E91E63',
14
+ tooltip: 'Navigate to a URL',
15
+ inputs: [
16
+ { name: 'URL', type: 'field', fieldType: 'text', required: true },
17
+ { name: 'WAIT_UNTIL', type: 'field', fieldType: 'dropdown', options: [['Load', 'load'], ['DOM Content Loaded', 'domcontentloaded'], ['Network Idle', 'networkidle']], default: 'load' },
18
+ ],
19
+ previousStatement: true,
20
+ nextStatement: true,
21
+ execute: async (params, context) => {
22
+ const page = context.page;
23
+ const url = (0, utils_1.resolveVariables)(params.URL, context);
24
+ const waitUntil = params.WAIT_UNTIL;
25
+ context.logger.info(`Navigating to ${url}`);
26
+ await page.goto(url, { waitUntil });
27
+ return {
28
+ _summary: url,
29
+ url,
30
+ waitUntil,
31
+ };
32
+ },
33
+ },
34
+ // Wait for Element
35
+ {
36
+ type: 'web_wait_for_element',
37
+ category: 'Web',
38
+ color: '#9C27B0',
39
+ tooltip: 'Wait for an element to appear/disappear',
40
+ inputs: [
41
+ { name: 'SELECTOR', type: 'field', fieldType: 'text', required: true },
42
+ { name: 'STATE', type: 'field', fieldType: 'dropdown', options: [['Visible', 'visible'], ['Hidden', 'hidden'], ['Attached', 'attached'], ['Detached', 'detached']] },
43
+ { name: 'TIMEOUT', type: 'field', fieldType: 'number', default: 30000 },
44
+ ],
45
+ previousStatement: true,
46
+ nextStatement: true,
47
+ execute: async (params, context) => {
48
+ const page = context.page;
49
+ const selector = (0, utils_1.resolveSelector)(params, context);
50
+ const state = params.STATE;
51
+ const timeout = params.TIMEOUT;
52
+ context.logger.info(`Waiting for ${selector} to be ${state}`);
53
+ await page.waitForSelector(selector, { state, timeout });
54
+ return {
55
+ _summary: `${params.SELECTOR} is ${state}`,
56
+ selector,
57
+ state,
58
+ };
59
+ },
60
+ },
61
+ // Wait for URL
62
+ {
63
+ type: 'web_wait_for_url',
64
+ category: 'Web',
65
+ color: '#9C27B0',
66
+ tooltip: 'Wait for URL to match',
67
+ inputs: [
68
+ { name: 'URL', type: 'field', fieldType: 'text', required: true },
69
+ { name: 'TIMEOUT', type: 'field', fieldType: 'number', default: 30000 },
70
+ ],
71
+ previousStatement: true,
72
+ nextStatement: true,
73
+ execute: async (params, context) => {
74
+ const page = context.page;
75
+ const url = (0, utils_1.resolveVariables)(params.URL, context);
76
+ const timeout = params.TIMEOUT;
77
+ context.logger.info(`Waiting for URL to match: ${url}`);
78
+ await page.waitForURL(url, { timeout });
79
+ return {
80
+ _summary: url,
81
+ url,
82
+ };
83
+ },
84
+ },
85
+ // Wait (pause)
86
+ {
87
+ type: 'web_wait',
88
+ category: 'Web',
89
+ color: '#9C27B0',
90
+ tooltip: 'Wait for a specified time',
91
+ inputs: [
92
+ { name: 'MILLISECONDS', type: 'field', fieldType: 'number', default: 1000 },
93
+ ],
94
+ previousStatement: true,
95
+ nextStatement: true,
96
+ execute: async (params, context) => {
97
+ const page = context.page;
98
+ const ms = params.MILLISECONDS;
99
+ context.logger.info(`Waiting ${ms}ms`);
100
+ await page.waitForTimeout(ms);
101
+ return {
102
+ _summary: `${ms}ms`,
103
+ milliseconds: ms,
104
+ };
105
+ },
106
+ },
107
+ // Take Screenshot
108
+ {
109
+ type: 'web_screenshot',
110
+ category: 'Web',
111
+ color: '#607D8B',
112
+ tooltip: 'Take a screenshot',
113
+ inputs: [
114
+ { name: 'NAME', type: 'field', fieldType: 'text', default: 'screenshot' },
115
+ { name: 'FULL_PAGE', type: 'field', fieldType: 'checkbox', default: false },
116
+ ],
117
+ previousStatement: true,
118
+ nextStatement: true,
119
+ execute: async (params, context) => {
120
+ const page = context.page;
121
+ const name = params.NAME;
122
+ const fullPage = params.FULL_PAGE;
123
+ context.logger.info(`Taking screenshot: ${name}`);
124
+ const buffer = await page.screenshot({ fullPage });
125
+ return {
126
+ _summary: `${name}${fullPage ? ' (full page)' : ''}`,
127
+ name,
128
+ fullPage,
129
+ buffer: buffer.toString('base64'),
130
+ };
131
+ },
132
+ },
133
+ ];
@@ -0,0 +1,5 @@
1
+ import { BlockDefinition } from '../../types';
2
+ /**
3
+ * Data retrieval blocks for Playwright (get text, attributes, values)
4
+ */
5
+ export declare const retrievalBlocks: BlockDefinition[];
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.retrievalBlocks = void 0;
4
+ const utils_1 = require("./utils");
5
+ /**
6
+ * Data retrieval blocks for Playwright (get text, attributes, values)
7
+ */
8
+ exports.retrievalBlocks = [
9
+ // Get Text Content
10
+ {
11
+ type: 'web_get_text',
12
+ category: 'Web',
13
+ color: '#2196F3',
14
+ tooltip: 'Get text content of an element',
15
+ inputs: [
16
+ { name: 'SELECTOR', type: 'field', fieldType: 'text', required: true },
17
+ ],
18
+ output: { type: 'String' },
19
+ execute: async (params, context) => {
20
+ const page = context.page;
21
+ const selector = (0, utils_1.resolveSelector)(params, context);
22
+ const text = await page.textContent(selector);
23
+ context.logger.debug(`Text content of ${selector}: "${text}"`);
24
+ const displayText = text && text.length > 40 ? text.substring(0, 40) + '...' : text;
25
+ return {
26
+ _summary: `"${displayText}"`,
27
+ _value: text,
28
+ selector,
29
+ text,
30
+ };
31
+ },
32
+ },
33
+ // Get Attribute
34
+ {
35
+ type: 'web_get_attribute',
36
+ category: 'Web',
37
+ color: '#2196F3',
38
+ tooltip: 'Get attribute value of an element',
39
+ inputs: [
40
+ { name: 'SELECTOR', type: 'field', fieldType: 'text', required: true },
41
+ { name: 'ATTRIBUTE', type: 'field', fieldType: 'text', required: true },
42
+ ],
43
+ output: { type: 'String' },
44
+ execute: async (params, context) => {
45
+ const page = context.page;
46
+ const selector = (0, utils_1.resolveSelector)(params, context);
47
+ const attribute = params.ATTRIBUTE;
48
+ const value = await page.getAttribute(selector, attribute);
49
+ context.logger.debug(`Attribute ${attribute} of ${selector}: "${value}"`);
50
+ return {
51
+ _summary: `${attribute} = "${value}"`,
52
+ _value: value,
53
+ selector,
54
+ attribute,
55
+ value,
56
+ };
57
+ },
58
+ },
59
+ // Get Input Value
60
+ {
61
+ type: 'web_get_input_value',
62
+ category: 'Web',
63
+ color: '#2196F3',
64
+ tooltip: 'Get current value of an input field',
65
+ inputs: [
66
+ { name: 'SELECTOR', type: 'field', fieldType: 'text', required: true },
67
+ ],
68
+ output: { type: 'String' },
69
+ execute: async (params, context) => {
70
+ const page = context.page;
71
+ const selector = (0, utils_1.resolveSelector)(params, context);
72
+ const value = await page.inputValue(selector);
73
+ context.logger.debug(`Input value of ${selector}: "${value}"`);
74
+ const displayValue = value.length > 40 ? value.substring(0, 40) + '...' : value;
75
+ return {
76
+ _summary: `"${displayValue}"`,
77
+ _value: value,
78
+ selector,
79
+ value,
80
+ };
81
+ },
82
+ },
83
+ // Get Page Title
84
+ {
85
+ type: 'web_get_title',
86
+ category: 'Web',
87
+ color: '#2196F3',
88
+ tooltip: 'Get the page title',
89
+ inputs: [],
90
+ output: { type: 'String' },
91
+ execute: async (params, context) => {
92
+ const page = context.page;
93
+ const title = await page.title();
94
+ context.logger.debug(`Page title: "${title}"`);
95
+ return {
96
+ _summary: `"${title}"`,
97
+ _value: title,
98
+ title,
99
+ };
100
+ },
101
+ },
102
+ // Get Current URL
103
+ {
104
+ type: 'web_get_url',
105
+ category: 'Web',
106
+ color: '#2196F3',
107
+ tooltip: 'Get the current URL',
108
+ inputs: [],
109
+ output: { type: 'String' },
110
+ execute: async (params, context) => {
111
+ const page = context.page;
112
+ const url = page.url();
113
+ context.logger.debug(`Current URL: "${url}"`);
114
+ return {
115
+ _summary: url,
116
+ _value: url,
117
+ url,
118
+ };
119
+ },
120
+ },
121
+ // Count Elements
122
+ {
123
+ type: 'web_count_elements',
124
+ category: 'Web',
125
+ color: '#2196F3',
126
+ tooltip: 'Count the number of elements matching a selector',
127
+ inputs: [
128
+ { name: 'SELECTOR', type: 'field', fieldType: 'text', required: true },
129
+ ],
130
+ output: { type: 'Number' },
131
+ execute: async (params, context) => {
132
+ const page = context.page;
133
+ const selector = (0, utils_1.resolveSelector)(params, context);
134
+ const count = await page.locator(selector).count();
135
+ context.logger.debug(`Found ${count} elements matching ${selector}`);
136
+ return {
137
+ _summary: `${count} elements`,
138
+ _value: count,
139
+ selector,
140
+ count,
141
+ };
142
+ },
143
+ },
144
+ ];
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Type definitions for Playwright (we use dynamic import at runtime)
3
+ */
4
+ export interface PlaywrightLocator {
5
+ click(options?: {
6
+ timeout?: number;
7
+ }): Promise<void>;
8
+ fill(value: string): Promise<void>;
9
+ type(text: string, options?: {
10
+ delay?: number;
11
+ }): Promise<void>;
12
+ selectOption(values: string | string[]): Promise<string[]>;
13
+ check(): Promise<void>;
14
+ uncheck(): Promise<void>;
15
+ hover(): Promise<void>;
16
+ focus(): Promise<void>;
17
+ press(key: string): Promise<void>;
18
+ textContent(): Promise<string | null>;
19
+ getAttribute(name: string): Promise<string | null>;
20
+ inputValue(): Promise<string>;
21
+ isVisible(): Promise<boolean>;
22
+ isEnabled(): Promise<boolean>;
23
+ isChecked(): Promise<boolean>;
24
+ count(): Promise<number>;
25
+ }
26
+ export interface PlaywrightPage {
27
+ goto(url: string, options?: {
28
+ waitUntil?: string;
29
+ }): Promise<unknown>;
30
+ click(selector: string, options?: {
31
+ timeout?: number;
32
+ }): Promise<void>;
33
+ fill(selector: string, value: string): Promise<void>;
34
+ type(selector: string, text: string, options?: {
35
+ delay?: number;
36
+ }): Promise<void>;
37
+ selectOption(selector: string, values: string | string[]): Promise<string[]>;
38
+ check(selector: string): Promise<void>;
39
+ uncheck(selector: string): Promise<void>;
40
+ waitForSelector(selector: string, options?: {
41
+ state?: string;
42
+ timeout?: number;
43
+ }): Promise<unknown>;
44
+ waitForTimeout(timeout: number): Promise<void>;
45
+ waitForURL(url: string | RegExp, options?: {
46
+ timeout?: number;
47
+ }): Promise<void>;
48
+ screenshot(options?: {
49
+ path?: string;
50
+ fullPage?: boolean;
51
+ }): Promise<Buffer>;
52
+ textContent(selector: string): Promise<string | null>;
53
+ getAttribute(selector: string, name: string): Promise<string | null>;
54
+ inputValue(selector: string): Promise<string>;
55
+ isVisible(selector: string): Promise<boolean>;
56
+ isEnabled(selector: string): Promise<boolean>;
57
+ isChecked(selector: string): Promise<boolean>;
58
+ evaluate<T>(fn: () => T): Promise<T>;
59
+ locator(selector: string): PlaywrightLocator;
60
+ title(): Promise<string>;
61
+ url(): string;
62
+ press(selector: string, key: string): Promise<void>;
63
+ hover(selector: string): Promise<void>;
64
+ focus(selector: string): Promise<void>;
65
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * Type definitions for Playwright (we use dynamic import at runtime)
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,26 @@
1
+ import { ExecutionContext } from '../../types';
2
+ export declare function getExpect(): Promise<any>;
3
+ /**
4
+ * Execute a web assertion with soft assertion support
5
+ * Wraps Playwright's expect() to handle soft assertion mode
6
+ */
7
+ export declare function executeWebAssertion(context: ExecutionContext, assertionFn: () => Promise<void>, errorMessage: string, details?: {
8
+ stepType?: string;
9
+ expected?: unknown;
10
+ actual?: unknown;
11
+ }): Promise<void>;
12
+ /**
13
+ * Resolve ${variable} placeholders in text
14
+ * Supports dot notation for object properties (e.g., ${user.email})
15
+ */
16
+ export declare function resolveVariables(text: string, context: ExecutionContext): string;
17
+ /**
18
+ * Resolve a selector based on its type
19
+ * - For 'testid:value' format: constructs [testIdAttribute="value"] using the global testIdAttribute
20
+ * - For other formats: returns the selector as-is
21
+ */
22
+ export declare function resolveSelector(params: Record<string, unknown>, context: ExecutionContext): string;
23
+ /**
24
+ * Get a display-friendly version of the selector (strips testid: prefix)
25
+ */
26
+ export declare function getDisplaySelector(params: Record<string, unknown>, context: ExecutionContext): string;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getExpect = getExpect;
37
+ exports.executeWebAssertion = executeWebAssertion;
38
+ exports.resolveVariables = resolveVariables;
39
+ exports.resolveSelector = resolveSelector;
40
+ exports.getDisplaySelector = getDisplaySelector;
41
+ // Import Playwright's expect for assertions with auto-waiting
42
+ // We use dynamic import with string concatenation to prevent Vite from
43
+ // trying to bundle the playwright package (which is Node.js-only)
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ let playwrightExpect = null;
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ async function getExpect() {
48
+ if (!playwrightExpect) {
49
+ // Use string concatenation to hide import from Vite's static analysis
50
+ const moduleName = '@playwright' + '/test';
51
+ const { expect } = await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
52
+ playwrightExpect = expect;
53
+ }
54
+ return playwrightExpect;
55
+ }
56
+ /**
57
+ * Execute a web assertion with soft assertion support
58
+ * Wraps Playwright's expect() to handle soft assertion mode
59
+ */
60
+ async function executeWebAssertion(context, assertionFn, errorMessage, details) {
61
+ try {
62
+ await assertionFn();
63
+ }
64
+ catch (err) {
65
+ if (context.softAssertions) {
66
+ // Soft assertion mode - collect error
67
+ const softError = {
68
+ message: err.message || errorMessage,
69
+ stepType: details?.stepType,
70
+ expected: details?.expected,
71
+ actual: details?.actual,
72
+ timestamp: new Date().toISOString(),
73
+ };
74
+ if (!context.softAssertionErrors) {
75
+ context.softAssertionErrors = [];
76
+ }
77
+ context.softAssertionErrors.push(softError);
78
+ context.logger.warn(`Soft assertion failed: ${softError.message}`);
79
+ }
80
+ else {
81
+ // Hard assertion mode - re-throw
82
+ throw err;
83
+ }
84
+ }
85
+ }
86
+ /**
87
+ * Resolve ${variable} placeholders in text
88
+ * Supports dot notation for object properties (e.g., ${user.email})
89
+ */
90
+ function resolveVariables(text, context) {
91
+ return text.replace(/\$\{([\w.]+)\}/g, (match, path) => {
92
+ const parts = path.split('.');
93
+ const varName = parts[0];
94
+ let value = context.variables.get(varName);
95
+ // Handle dot notation for nested object access
96
+ if (parts.length > 1 && value !== undefined && value !== null) {
97
+ for (let i = 1; i < parts.length; i++) {
98
+ if (value === undefined || value === null)
99
+ break;
100
+ value = value[parts[i]];
101
+ }
102
+ }
103
+ if (value === undefined || value === null)
104
+ return match;
105
+ if (typeof value === 'object')
106
+ return JSON.stringify(value);
107
+ return String(value);
108
+ });
109
+ }
110
+ /**
111
+ * Resolve a selector based on its type
112
+ * - For 'testid:value' format: constructs [testIdAttribute="value"] using the global testIdAttribute
113
+ * - For other formats: returns the selector as-is
114
+ */
115
+ function resolveSelector(params, context) {
116
+ const rawSelector = resolveVariables(params.SELECTOR, context);
117
+ // Check for testid: prefix (e.g., "testid:nav-sign-in")
118
+ if (rawSelector.startsWith('testid:')) {
119
+ const testIdValue = rawSelector.substring(7); // Remove 'testid:' prefix
120
+ const testIdAttr = context.testIdAttribute || 'data-testid';
121
+ return `[${testIdAttr}="${testIdValue}"]`;
122
+ }
123
+ return rawSelector;
124
+ }
125
+ /**
126
+ * Get a display-friendly version of the selector (strips testid: prefix)
127
+ */
128
+ function getDisplaySelector(params, context) {
129
+ const rawSelector = params.SELECTOR;
130
+ // For testid: prefix, show the actual CSS selector that will be used
131
+ if (rawSelector.startsWith('testid:')) {
132
+ const testIdValue = rawSelector.substring(7);
133
+ const testIdAttr = context.testIdAttribute || 'data-testid';
134
+ return `[${testIdAttr}="${testIdValue}"]`;
135
+ }
136
+ return rawSelector;
137
+ }
@@ -1,2 +1,13 @@
1
- import { BlockDefinition } from '../types';
2
- export declare const playwrightBlocks: BlockDefinition[];
1
+ /**
2
+ * Playwright blocks - Re-export from modular structure
3
+ *
4
+ * This file re-exports all Playwright blocks from the playwright/ directory
5
+ * for backwards compatibility. The blocks are now organized in:
6
+ * - playwright/navigation.ts - Navigate, wait, screenshot
7
+ * - playwright/interactions.ts - Click, fill, type, select, checkbox, hover
8
+ * - playwright/retrieval.ts - Get text, attributes, values, title, URL
9
+ * - playwright/assertions.ts - Visibility, text, value assertions
10
+ * - playwright/utils.ts - Shared utilities (resolveVariables, resolveSelector)
11
+ * - playwright/types.ts - TypeScript interfaces
12
+ */
13
+ export { playwrightBlocks } from './playwright/index';