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.
- package/README.md +127 -44
- package/package.json +1 -1
- package/src/commands/init.js +54 -15
- package/src/templates/playwright-agent-csharp.md +521 -0
- package/src/templates/playwright-agent-java.md +471 -0
- package/src/templates/playwright-agent-js.md +461 -0
- package/src/templates/playwright-agent-ts.md +69 -0
- package/src/templates/playwright-agent.md +1353 -47
|
@@ -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.
|