agents-cli-automation 1.0.6 → 1.0.8

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.
@@ -0,0 +1,461 @@
1
+ name: Create Playwright Framework - UI Testing (JavaScript)
2
+ description: Creates a production-ready Playwright UI automation framework in JavaScript (ES Modules) with all dependencies, fixtures, and test configurations.
3
+ argument-hint: "framework requirements, e.g., 'JavaScript with UI tests'"
4
+
5
+ ---
6
+
7
+ # Playwright UI Testing Framework - JavaScript (ES Modules)
8
+
9
+ This agent creates a production-ready Playwright framework in modern JavaScript (ES Modules) optimized for UI automation.
10
+
11
+ ## Capabilities
12
+ - **JavaScript (ES Modules)** - Chromium only with latest syntax
13
+ - No build step required - direct ES modules support
14
+ - UI, component, and end-to-end testing
15
+ - **Playwright BDD** - Gherkin format with step definitions
16
+ - **Page Object Model (POM)** - Reusable page classes
17
+ - **Fixtures** - Pre-built browser & page fixtures
18
+ - **Parallel execution** - Tests run simultaneously for speed
19
+ - Test data support (JSON, CSV, YAML)
20
+ - Form helpers for complex interactions
21
+ - Scalable folder structure with best practices
22
+
23
+ ## Prerequisites
24
+ - Node.js 18+ installed
25
+ - npm or yarn
26
+
27
+ ## Setup Instructions
28
+
29
+ ### 1. Install Dependencies (Chromium Only)
30
+ ```bash
31
+ npm install
32
+ npm install --save-dev @cucumber/cucumber csv-parser js-yaml
33
+ npx playwright install chromium
34
+ ```
35
+
36
+ ### 2. Update package.json
37
+ Add `"type": "module"` for ES modules support:
38
+ ```json
39
+ {
40
+ "type": "module",
41
+ "scripts": {
42
+ "start": "node server.js",
43
+ "test": "playwright test",
44
+ "test:headed": "playwright test --headed",
45
+ "test:debug": "playwright test --debug",
46
+ "test:ui": "playwright test --ui",
47
+ "test:bdd": "npx @cucumber/cucumber-js",
48
+ "test:bdd:report": "npx @cucumber/cucumber-js --format json:cucumber-report.json"
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### 3. Playwright Configuration (playwright.config.js - ES Module)
54
+ ```javascript
55
+ export default {
56
+ testDir: './tests/specs',
57
+ fullyParallel: true,
58
+ workers: process.env.CI ? 1 : 4,
59
+ retries: 1,
60
+ timeout: 30000,
61
+ expect: {
62
+ timeout: 5000,
63
+ },
64
+ use: {
65
+ browserName: 'chromium',
66
+ headless: true,
67
+ screenshot: 'only-on-failure',
68
+ video: 'retain-on-failure',
69
+ trace: 'on-first-retry',
70
+ },
71
+ webServer: {
72
+ command: 'npm start',
73
+ url: 'http://localhost:3000',
74
+ reuseExistingServer: !process.env.CI,
75
+ },
76
+ reporter: [
77
+ ['html'],
78
+ ['json', { outputFile: 'test-results/results.json' }],
79
+ ],
80
+ };
81
+ ```
82
+
83
+ ### 4. Project Structure
84
+ ```
85
+ project/
86
+ ├── tests/
87
+ │ ├── fixtures/
88
+ │ │ └── base.fixture.js # Shared fixtures
89
+ │ ├── pages/
90
+ │ │ ├── BasePage.js # Base page object
91
+ │ │ ├── LoginPage.js # Login page object
92
+ │ │ ├── InventoryPage.js # Inventory page object
93
+ │ │ └── FormPage.js # Form page object
94
+ │ ├── utils/ # Utility functions
95
+ │ │ ├── dataReader.js
96
+ │ │ ├── formHelper.js
97
+ │ │ └── testData.js
98
+ │ ├── data/ # Test data files
99
+ │ │ ├── users.json
100
+ │ │ ├── formData.csv
101
+ │ │ └── config.yaml
102
+ │ ├── features/ # BDD Gherkin scenarios
103
+ │ │ ├── login.feature
104
+ │ │ └── shopping.feature
105
+ │ ├── steps/ # BDD Step definitions
106
+ │ │ ├── loginSteps.js
107
+ │ │ └── shoppingSteps.js
108
+ │ └── specs/
109
+ │ ├── saucedemo.spec.js # Traditional tests
110
+ │ └── formTest.spec.js
111
+ ├── cucumber.js # Cucumber config
112
+ ├── playwright.config.js # Playwright config
113
+ └── package.json
114
+ ```
115
+
116
+ ### 5. Cucumber Configuration (cucumber.js)
117
+ ```javascript
118
+ export default {
119
+ default: {
120
+ paths: ['tests/features/**/*.feature'],
121
+ require: ['tests/steps/**/*.js'],
122
+ format: ['progress', 'html:cucumber-report.html'],
123
+ parallel: 4,
124
+ worldParameters: {
125
+ appUrl: 'https://www.saucedemo.com/',
126
+ }
127
+ }
128
+ };
129
+ ```
130
+
131
+ ### 6. Data Reader Utility (tests/utils/dataReader.js)
132
+ ```javascript
133
+ import fs from 'fs';
134
+ import path from 'path';
135
+ import csv from 'csv-parser';
136
+ import yaml from 'js-yaml';
137
+ import { fileURLToPath } from 'url';
138
+
139
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
140
+ const DATA_DIR = path.join(path.resolve(__dirname, '..'), 'data');
141
+
142
+ export class DataReader {
143
+ // Read JSON file
144
+ static readJSON(filename) {
145
+ const filePath = path.join(DATA_DIR, filename);
146
+ const data = fs.readFileSync(filePath, 'utf-8');
147
+ return JSON.parse(data);
148
+ }
149
+
150
+ // Read YAML file
151
+ static readYAML(filename) {
152
+ const filePath = path.join(DATA_DIR, filename);
153
+ const data = fs.readFileSync(filePath, 'utf-8');
154
+ return yaml.load(data);
155
+ }
156
+
157
+ // Read CSV file (returns array of objects)
158
+ static async readCSV(filename) {
159
+ const filePath = path.join(DATA_DIR, filename);
160
+ return new Promise((resolve, reject) => {
161
+ const records = [];
162
+ fs.createReadStream(filePath)
163
+ .pipe(csv())
164
+ .on('data', (data) => records.push(data))
165
+ .on('end', () => resolve(records))
166
+ .on('error', reject);
167
+ });
168
+ }
169
+
170
+ // Get single record by ID or key
171
+ static getRecordByKey(data, key, value) {
172
+ if (Array.isArray(data)) {
173
+ return data.find(record => record[key] === value);
174
+ }
175
+ return undefined;
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### 7. Form Helper Utility (tests/utils/formHelper.js)
181
+ ```javascript
182
+ export class FormHelper {
183
+ constructor(page) {
184
+ this.page = page;
185
+ }
186
+
187
+ // Fill text input
188
+ async fillInput(selector, value) {
189
+ await this.page.fill(selector, value);
190
+ }
191
+
192
+ // Fill textarea
193
+ async fillTextArea(selector, value) {
194
+ await this.page.locator(selector).clear();
195
+ await this.page.locator(selector).type(value, { delay: 50 });
196
+ }
197
+
198
+ // Select option from dropdown (non-select element)
199
+ async selectDropdown(dropdownSelector, optionText) {
200
+ await this.page.click(dropdownSelector);
201
+ await this.page.click(`text="${optionText}"`);
202
+ }
203
+
204
+ // Select radio button by label text
205
+ async selectRadioButton(labelText) {
206
+ const label = this.page.locator(`label:has-text("${labelText}")`);
207
+ const radioId = await label.getAttribute('for');
208
+ if (radioId) {
209
+ await this.page.locator(`#${radioId}`).click();
210
+ }
211
+ }
212
+
213
+ // Check checkbox by label text
214
+ async checkCheckbox(labelText) {
215
+ const label = this.page.locator(`label:has-text("${labelText}")`);
216
+ const checkboxId = await label.getAttribute('for');
217
+ if (checkboxId) {
218
+ const checkbox = this.page.locator(`#${checkboxId}`);
219
+ if (!(await checkbox.isChecked())) {
220
+ await checkbox.click();
221
+ }
222
+ }
223
+ }
224
+
225
+ // Select multiple checkboxes
226
+ async checkMultiple(labels) {
227
+ for (const label of labels) {
228
+ await this.checkCheckbox(label);
229
+ }
230
+ }
231
+
232
+ // Verify form value
233
+ async getInputValue(selector) {
234
+ return await this.page.inputValue(selector);
235
+ }
236
+
237
+ // Verify checkbox is checked
238
+ async isCheckboxChecked(labelText) {
239
+ const label = this.page.locator(`label:has-text("${labelText}")`);
240
+ const checkboxId = await label.getAttribute('for');
241
+ return checkboxId ? await this.page.locator(`#${checkboxId}`).isChecked() : false;
242
+ }
243
+ }
244
+ ```
245
+
246
+ ### 8. Test Data Manager (tests/utils/testData.js)
247
+ ```javascript
248
+ import { DataReader } from './dataReader.js';
249
+
250
+ export class TestDataManager {
251
+ static loadUsers() {
252
+ return DataReader.readJSON('users.json');
253
+ }
254
+
255
+ static async loadFormData() {
256
+ return await DataReader.readCSV('formData.csv');
257
+ }
258
+
259
+ static loadConfig() {
260
+ return DataReader.readYAML('config.yaml');
261
+ }
262
+
263
+ static getUserByUsername(username) {
264
+ const data = this.loadUsers();
265
+ return DataReader.getRecordByKey(data.users, 'username', username);
266
+ }
267
+
268
+ static async getFormDataByScenario(scenarioName) {
269
+ const data = await this.loadFormData();
270
+ return DataReader.getRecordByKey(data, 'scenario', scenarioName);
271
+ }
272
+ }
273
+ ```
274
+
275
+ ### 9. Base Page (tests/pages/BasePage.js)
276
+ ```javascript
277
+ export class BasePage {
278
+ constructor(page) {
279
+ this.page = page;
280
+ }
281
+
282
+ async navigateTo(url) {
283
+ await this.page.goto(url);
284
+ }
285
+
286
+ async click(selector) {
287
+ await this.page.click(selector);
288
+ }
289
+
290
+ async fill(selector, text) {
291
+ await this.page.fill(selector, text);
292
+ }
293
+
294
+ async getText(selector) {
295
+ return await this.page.textContent(selector);
296
+ }
297
+
298
+ async waitForElement(selector, timeout = 5000) {
299
+ await this.page.waitForSelector(selector, { timeout });
300
+ }
301
+
302
+ async isVisible(selector) {
303
+ return await this.page.locator(selector).isVisible();
304
+ }
305
+ }
306
+ ```
307
+
308
+ ### 10. Page Object - Login (tests/pages/LoginPage.js)
309
+ ```javascript
310
+ import { BasePage } from './BasePage.js';
311
+
312
+ export class LoginPage extends BasePage {
313
+ constructor(page) {
314
+ super(page);
315
+ this.usernameField = '[data-test="username"]';
316
+ this.passwordField = '[data-test="password"]';
317
+ this.loginButton = '[data-test="login-button"]';
318
+ }
319
+
320
+ async goto() {
321
+ await this.page.goto('https://www.saucedemo.com/');
322
+ }
323
+
324
+ async login(username, password) {
325
+ await this.page.fill(this.usernameField, username);
326
+ await this.page.fill(this.passwordField, password);
327
+ await this.page.click(this.loginButton);
328
+ await this.page.waitForURL('**/inventory.html');
329
+ }
330
+
331
+ async isLoaded() {
332
+ return await this.page.locator(this.usernameField).isVisible();
333
+ }
334
+ }
335
+ ```
336
+
337
+ ### 11. Fixtures Setup (tests/fixtures/base.fixture.js)
338
+ ```javascript
339
+ import { test as base, expect } from '@playwright/test';
340
+ import { LoginPage } from '../pages/LoginPage.js';
341
+ import { InventoryPage } from '../pages/InventoryPage.js';
342
+ import { FormPage } from '../pages/FormPage.js';
343
+
344
+ export const test = base.extend({
345
+ loginPage: async ({ page }, use) => {
346
+ const loginPage = new LoginPage(page);
347
+ await use(loginPage);
348
+ },
349
+
350
+ inventoryPage: async ({ page }, use) => {
351
+ const inventoryPage = new InventoryPage(page);
352
+ await use(inventoryPage);
353
+ },
354
+
355
+ formPage: async ({ page }, use) => {
356
+ const formPage = new FormPage(page);
357
+ await use(formPage);
358
+ },
359
+
360
+ authenticatedUser: async ({ page, loginPage }, use) => {
361
+ await loginPage.goto();
362
+ await loginPage.login('standard_user', 'secret_sauce');
363
+ await use({ page, loginPage });
364
+ },
365
+ });
366
+
367
+ export { expect };
368
+ ```
369
+
370
+ ### 12. Simple Test Example (tests/specs/saucedemo.spec.js)
371
+ ```javascript
372
+ import { test, expect } from '../fixtures/base.fixture.js';
373
+
374
+ test.describe('SauceDemo E2E Tests', () => {
375
+ test('Login with valid credentials', async ({ loginPage, page }) => {
376
+ await loginPage.goto();
377
+ await loginPage.login('standard_user', 'secret_sauce');
378
+ expect(page.url()).toContain('inventory.html');
379
+ });
380
+
381
+ test('Add product to cart', async ({ authenticatedUser, inventoryPage }) => {
382
+ await inventoryPage.addProductToCart();
383
+ const cartCount = await inventoryPage.getCartCount();
384
+ expect(cartCount).toBe('1');
385
+ });
386
+ });
387
+ ```
388
+
389
+ ### 13. BDD Feature Example (tests/features/login.feature)
390
+ ```gherkin
391
+ Feature: Login to SauceDemo
392
+ As a user
393
+ I want to login to the application
394
+ So that I can access the inventory
395
+
396
+ Scenario: User logs in with valid credentials
397
+ Given I navigate to the SauceDemo application
398
+ When I login with username "standard_user" and password "secret_sauce"
399
+ Then I should see the inventory page
400
+ ```
401
+
402
+ ### 14. Test Data Files
403
+
404
+ **tests/data/users.json**
405
+ ```json
406
+ {
407
+ "users": [
408
+ {
409
+ "id": "1",
410
+ "username": "standard_user",
411
+ "password": "secret_sauce",
412
+ "email": "user@example.com",
413
+ "firstName": "John",
414
+ "lastName": "Doe"
415
+ }
416
+ ]
417
+ }
418
+ ```
419
+
420
+ **tests/data/config.yaml**
421
+ ```yaml
422
+ app:
423
+ url: https://www.saucedemo.com/
424
+ timeout: 30000
425
+ users:
426
+ standard:
427
+ username: standard_user
428
+ password: secret_sauce
429
+ ```
430
+
431
+ ## Run Tests
432
+
433
+ ```bash
434
+ # Run all tests in parallel
435
+ npm test
436
+
437
+ # Run specific test file
438
+ npm test tests/specs/saucedemo.spec.js
439
+
440
+ # Run with headed browser
441
+ npm run test:headed
442
+
443
+ # Debug mode
444
+ npm run test:debug
445
+
446
+ # Run BDD scenarios
447
+ npm run test:bdd
448
+ ```
449
+
450
+ ## Best Practices
451
+ ✅ **Page Object Model** - Encapsulate all selectors in page classes
452
+ ✅ **Fixtures** - Reusable page objects and setup/teardown
453
+ ✅ **Test Data** - Externalize data in JSON, CSV, YAML
454
+ ✅ **Form Helpers** - Handle dropdowns, radios, checkboxes
455
+ ✅ **BDD Support** - Write scenarios in Gherkin
456
+ ✅ **Parallel Execution** - 4 workers by default
457
+ ✅ **Chromium Only** - Single browser for consistency
458
+ ✅ **Modern ES Modules** - Clean import/export syntax
459
+ ✅ **No Build Step** - Node.js 18+ direct ES module support
460
+
461
+ **Note:** This framework uses JavaScript with ES Modules, Chromium only, and parallel execution. Start by copying the project structure and customizing page objects for your application.
@@ -0,0 +1,69 @@
1
+ name: automation.md description: Describe what this custom agent does and when to use it. argument-hint: The inputs this agent expects, e.g., "a task to implement" or "a question to answer". tools: ['read', 'create_file', 'apply_patch', 'run_in_terminal', 'file_search', 'grep_search', 'manage_todo_list'] --- This agent documents and automates reproducing the repository layout, minimal file placeholders, and recommended developer commands so a new user can recreate the same workspace and run the test suites. When to use - When a new contributor needs to scaffold a local copy of this project structure and install the tooling to run tests and Playwright flows. Inputs (argument-hint) - task (required): one of scaffold, verify, describe. - targetPath (optional): filesystem path where scaffolding should be created. Defaults to repository root. - installDeps (optional boolean): when true, agent will install Node dependencies and Playwright browsers. - force (optional boolean): when true, allow overwriting placeholder files (use with caution). Capabilities / Behavior - Read the repo layout and create any missing directories listed in the standard layout. - Create placeholder files for missing source files (short header + file path + TODO notes). - Optionally install Node dependencies and Playwright browsers when installDeps=true. - Run verification commands (npm test, npx playwright test --list) and return concise logs. Prerequisites - Node.js (v16+) and npm (or pnpm) installed. - Internet access for package installation. Scaffolded layout (representative)
2
+ bitbucket-pipelines.yml
3
+ package.json
4
+ playwright.config.ts
5
+ tsconfig.json
6
+ core/
7
+ api/
8
+ apiClient.ts
9
+ auth/
10
+ roles.ts
11
+ db/
12
+ connection.ts
13
+ queries.ts
14
+ permission/
15
+ permission.schd-group.ts
16
+ permission.types.ts
17
+ playwright-report/
18
+ index.html
19
+ screenshots/
20
+ test-results/
21
+ tests/
22
+ api/
23
+ schd-group-create.api.spec.ts
24
+ data/
25
+ facilityFormData.json
26
+ db/
27
+ 01-connection.db.spec.ts
28
+ fixtures/
29
+ pages.fixture.ts
30
+ test.fixture.ts
31
+ types/
32
+ formField.ts
33
+ ui/
34
+ features/
35
+ booking.feature
36
+ scheduling-groups.feature
37
+ page/
38
+ HomePage.ts
39
+ steps/
40
+ booking.steps.ts
41
+ scheduling-groups.steps.ts
42
+ utils/
43
+ formFiller.ts
44
+ readJson.ts
45
+ workflows/
46
+ facilities/
47
+ api/
48
+ db/
49
+ invariants/
50
+ schd-group/
51
+ api/
52
+ schd-group.api.ts
53
+ db/
54
+ schd-group.queries.ts
55
+ invariants/
56
+ api.invariants.ts
57
+ db.invariants.ts
58
+ permission.invariants.ts
59
+ Scaffold steps (task: scaffold) 1. Validate targetPath exists or create it. 2. Create the directory tree above (only new directories created). 3. For each file that exists in source repo, copy content. For files missing, create a placeholder containing: header, expected responsibilities, and TODO pointers. 4. If installDeps=true, run npm ci (or npm install) and npx playwright install (or npx playwright install --with-deps on some systems). 5. Run a lightweight verification: npm test or npx playwright test --list depending on scripts. Suggested commands (PowerShell / cross-platform)
60
+ powershell
61
+ # install dependencies
62
+ npm ci
63
+ # install Playwright browsers
64
+ npx playwright install
65
+ # run unit/api tests
66
+ npm test
67
+ # run Playwright E2E tests
68
+ npx playwright test
69
+ Outputs - Created directories and placeholder files in targetPath. - Verification logs for dependency install and sample test runs. - A summary list of any placeholders that require manual editing. Safety & constraints - The agent will not overwrite existing non-placeholder files unless force=true is set. - The agent will not embed secrets into scaffolded files; secrets must be provided separately. Example usages - Scaffold without installing deps: { "task": "scaffold", "installDeps": false } - Scaffold + install deps: { "task": "scaffold", "installDeps": true } - Describe repo: { "task": "describe" } Maintainer notes - Update this file when adding/removing top-level folders or CI config. - Keep prerequisites in sync with package.json and CI definitions. --- Automation agent specification end.