@cutleryapp/agent 1.0.25 → 1.0.27

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.
@@ -14,11 +14,35 @@ class TestExecutor {
14
14
  this.activeBrowser = null;
15
15
  }
16
16
  async execute(testCase) {
17
+ // Data-driven: run once per row, merging row into test_variables
18
+ const dataRows = testCase.test_data || [];
19
+ if (dataRows.length > 1) {
20
+ console.log(`[executor] 🗂️ Data-driven: ${dataRows.length} rows`);
21
+ const allResults = [];
22
+ for (let i = 0; i < dataRows.length; i++) {
23
+ console.log(`[executor] 🗂️ Row ${i + 1}/${dataRows.length}:`, JSON.stringify(dataRows[i]));
24
+ const rowResult = await this.execute({
25
+ ...testCase,
26
+ test_variables: { ...(testCase.test_variables || {}), ...dataRows[i] },
27
+ test_data: [],
28
+ });
29
+ allResults.push(rowResult);
30
+ }
31
+ return {
32
+ success: allResults.every(r => r.success),
33
+ steps: allResults.flatMap((r, i) => r.steps.map(s => ({ ...s, step: `[Row ${i + 1}] ${s.step}` }))),
34
+ screenshots: allResults.flatMap(r => r.screenshots),
35
+ error: allResults.find(r => r.error)?.error,
36
+ };
37
+ }
17
38
  const result = { success: true, steps: [], screenshots: [] };
18
39
  if (!(0, fs_1.existsSync)(this.options.outputDir)) {
19
40
  (0, fs_1.mkdirSync)(this.options.outputDir, { recursive: true });
20
41
  }
21
- const variables = testCase.test_variables || {};
42
+ // Merge single data row into variables if present
43
+ const variables = dataRows.length === 1
44
+ ? { ...(testCase.test_variables || {}), ...dataRows[0] }
45
+ : testCase.test_variables || {};
22
46
  const baseUrlValue = this.options.baseUrl;
23
47
  console.log('[executor] test_variables received:', JSON.stringify(variables));
24
48
  console.log('[executor] baseUrl option:', baseUrlValue);
@@ -101,6 +125,39 @@ class TestExecutor {
101
125
  handled = true;
102
126
  }
103
127
  }
128
+ // 3a. Multi-field fill: "Fill firstname, lastname" → fill each with inferred value
129
+ if (!handled && /^(?:fill|type)\s+/i.test(raw) && !/\s+(?:in|into|with)\s+/i.test(raw)) {
130
+ const fieldsPart = raw.replace(/^(?:fill|type)\s+/i, "").trim();
131
+ const fields = fieldsPart.split(/,\s*/).map((f) => f.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
132
+ if (fields.length > 1) {
133
+ const valueMap = {
134
+ firstname: "John", first: "John", fname: "John",
135
+ lastname: "Smith", last: "Smith", lname: "Smith", surname: "Smith",
136
+ name: "John Smith", fullname: "John Smith",
137
+ email: "john.smith@example.com", emailaddress: "john.smith@example.com",
138
+ phone: "9876543210", mobile: "9876543210", phonenumber: "9876543210", mobilenumber: "9876543210",
139
+ address: "123 Test Street", currentaddress: "123 Test Street", streetaddress: "123 Test Street",
140
+ city: "New York", state: "New York",
141
+ zip: "10001", zipcode: "10001", postalcode: "10001",
142
+ dob: "01/01/1990", dateofbirth: "01/01/1990", birthdate: "01/01/1990",
143
+ age: "30", username: "john.smith",
144
+ password: "Test@1234", company: "Acme Corp",
145
+ subject: "Mathematics", subjects: "Mathematics",
146
+ message: "This is a test message.", comment: "Test comment.",
147
+ description: "Test description.",
148
+ };
149
+ for (const field of fields) {
150
+ const key = field.toLowerCase().replace(/[\s_-]+/g, "");
151
+ const value = valueMap[key] || "Test Value";
152
+ console.log(` ⌨️ Multi-fill: "${field}" → "${value}"`);
153
+ try {
154
+ await tryFill(page, field, value);
155
+ }
156
+ catch { /* ignore individual failures */ }
157
+ }
158
+ handled = true;
159
+ }
160
+ }
104
161
  // 3. Fill — smart selector strategies via MCP/Playwright
105
162
  if (!handled && (lower.includes("fill") || lower.includes("type") || lower.includes("enter"))) {
106
163
  const match = raw.match(/(?:enter|fill|type)\s+"([^"]+)"\s+(?:in|into)\s+(?:the\s+)?"?([^"]+?)"?\s*(?:field|input|box|area)?\s*$/i) ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cutleryapp/agent",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "description": "Local agent that connects your machine to the Cutlery QA platform and runs UI tests via Playwright",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {