@smartbit4all/playwright-qa 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 (74) hide show
  1. package/README.md +334 -0
  2. package/dist/config/defaults.d.ts +18 -0
  3. package/dist/config/defaults.d.ts.map +1 -0
  4. package/dist/config/defaults.js +25 -0
  5. package/dist/config/defaults.js.map +1 -0
  6. package/dist/config/index.d.ts +7 -0
  7. package/dist/config/index.d.ts.map +1 -0
  8. package/dist/config/index.js +82 -0
  9. package/dist/config/index.js.map +1 -0
  10. package/dist/core/index.d.ts +11 -0
  11. package/dist/core/index.d.ts.map +1 -0
  12. package/dist/core/index.js +58 -0
  13. package/dist/core/index.js.map +1 -0
  14. package/dist/datapool/index.d.ts +29 -0
  15. package/dist/datapool/index.d.ts.map +1 -0
  16. package/dist/datapool/index.js +84 -0
  17. package/dist/datapool/index.js.map +1 -0
  18. package/dist/datapool/loader.d.ts +12 -0
  19. package/dist/datapool/loader.d.ts.map +1 -0
  20. package/dist/datapool/loader.js +68 -0
  21. package/dist/datapool/loader.js.map +1 -0
  22. package/dist/datapool/locale.d.ts +2 -0
  23. package/dist/datapool/locale.d.ts.map +1 -0
  24. package/dist/datapool/locale.js +60 -0
  25. package/dist/datapool/locale.js.map +1 -0
  26. package/dist/datapool/unique.d.ts +4 -0
  27. package/dist/datapool/unique.d.ts.map +1 -0
  28. package/dist/datapool/unique.js +17 -0
  29. package/dist/datapool/unique.js.map +1 -0
  30. package/dist/index.d.ts +6 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +37 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/screenshot/directory.d.ts +9 -0
  35. package/dist/screenshot/directory.d.ts.map +1 -0
  36. package/dist/screenshot/directory.js +122 -0
  37. package/dist/screenshot/directory.js.map +1 -0
  38. package/dist/screenshot/highlight.d.ts +10 -0
  39. package/dist/screenshot/highlight.d.ts.map +1 -0
  40. package/dist/screenshot/highlight.js +36 -0
  41. package/dist/screenshot/highlight.js.map +1 -0
  42. package/dist/screenshot/index.d.ts +12 -0
  43. package/dist/screenshot/index.d.ts.map +1 -0
  44. package/dist/screenshot/index.js +54 -0
  45. package/dist/screenshot/index.js.map +1 -0
  46. package/dist/seed/index.d.ts +41 -0
  47. package/dist/seed/index.d.ts.map +1 -0
  48. package/dist/seed/index.js +143 -0
  49. package/dist/seed/index.js.map +1 -0
  50. package/dist/steps/grid.steps.d.ts +21 -0
  51. package/dist/steps/grid.steps.d.ts.map +1 -0
  52. package/dist/steps/grid.steps.js +154 -0
  53. package/dist/steps/grid.steps.js.map +1 -0
  54. package/dist/steps/index.d.ts +4 -0
  55. package/dist/steps/index.d.ts.map +1 -0
  56. package/dist/steps/index.js +14 -0
  57. package/dist/steps/index.js.map +1 -0
  58. package/dist/steps/navigation.steps.d.ts +4 -0
  59. package/dist/steps/navigation.steps.d.ts.map +1 -0
  60. package/dist/steps/navigation.steps.js +79 -0
  61. package/dist/steps/navigation.steps.js.map +1 -0
  62. package/dist/steps/wait.d.ts +8 -0
  63. package/dist/steps/wait.d.ts.map +1 -0
  64. package/dist/steps/wait.js +14 -0
  65. package/dist/steps/wait.js.map +1 -0
  66. package/package.json +55 -0
  67. package/templates/ci/playwright-qa-pipeline.yml +54 -0
  68. package/templates/playwright-qa/datapools/.gitkeep +0 -0
  69. package/templates/playwright-qa/package.json +14 -0
  70. package/templates/playwright-qa/playwright.config.ts +20 -0
  71. package/templates/playwright-qa/steps/.gitkeep +0 -0
  72. package/templates/playwright-qa/suites/.gitkeep +0 -0
  73. package/templates/playwright-qa/tsconfig.json +11 -0
  74. package/templates/playwright-qa/types/.gitkeep +0 -0
package/README.md ADDED
@@ -0,0 +1,334 @@
1
+ # @smartbit4all/playwright-qa
2
+
3
+ Playwright-based testing and documentation framework. Provides screenshot utilities, typed datapools with locale support, and TestStep/TestSuite conventions.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @smartbit4all/playwright-qa
9
+ ```
10
+
11
+ Requires Node.js 20+ and Playwright as a peer dependency:
12
+
13
+ ```bash
14
+ npm install @playwright/test
15
+ npx playwright install --with-deps chromium
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```typescript
21
+ import { test } from '@playwright/test';
22
+ import { initSuite, screenshot } from '@smartbit4all/playwright-qa';
23
+
24
+ test.beforeAll(() => {
25
+ initSuite({ screenshotDir: './screenshots' });
26
+ });
27
+
28
+ test('take a screenshot', async ({ page }) => {
29
+ await page.goto('https://demo.playwright.dev/todomvc');
30
+ await screenshot(page, 'todomvc-home');
31
+ });
32
+ ```
33
+
34
+ ## Suite Setup
35
+
36
+ Every TestSuite should call `initSuite()` in `beforeAll`. This single call resets all internal state (config, datapools, screenshot directory, seed handlers) and optionally sets up the screenshot directory.
37
+
38
+ ```typescript
39
+ import { initSuite } from '@smartbit4all/playwright-qa';
40
+
41
+ // With screenshots — cleans the directory and initializes it
42
+ initSuite({ screenshotDir: './screenshots' });
43
+
44
+ // Without screenshots — tests run normally, screenshot calls return null
45
+ initSuite();
46
+ ```
47
+
48
+ When no `screenshotDir` is provided, all screenshot functions (`screenshot`, `screenshotHighlight`, `screenshotRegion`, `screenshotRegionHighlight`) become no-ops and return `null` instead of a file path. This means TestSteps that include screenshot calls work without modification — no conditional logic needed.
49
+
50
+ ## API Reference
51
+
52
+ ### Screenshot
53
+
54
+ ```typescript
55
+ import { screenshot, screenshotHighlight, screenshotRegion, screenshotRegionHighlight } from '@smartbit4all/playwright-qa';
56
+
57
+ // Full page screenshot — returns file path, or null if screenshots are disabled
58
+ await screenshot(page, 'page-name');
59
+ await screenshot(page, 'category/page-name'); // name path = subdirectory
60
+ await screenshot(page, 'page-name', { fullPage: true });
61
+
62
+ // Full page with highlighted element
63
+ await screenshotHighlight(page, 'name', '#selector');
64
+ await screenshotHighlight(page, 'name', '#selector', { style: 'subtle' });
65
+
66
+ // Region screenshot (single element)
67
+ await screenshotRegion(page, 'name', '#region-selector');
68
+
69
+ // Region with highlighted element inside
70
+ await screenshotRegionHighlight(page, 'name', '#region', '#highlight');
71
+ ```
72
+
73
+ All screenshot functions return `Promise<string | null>`. They return `null` when no screenshot directory has been configured (see [Suite Setup](#suite-setup)).
74
+
75
+ ### Datapool
76
+
77
+ ```typescript
78
+ import { datapool, configureDatapool } from '@smartbit4all/playwright-qa';
79
+
80
+ // Global configuration (typically in beforeAll)
81
+ configureDatapool({ locale: 'hu', basePath: './datapools' });
82
+
83
+ // Load a datapool
84
+ const companies = datapool<Company>('companies');
85
+
86
+ // Access items
87
+ const item = companies.byKey('it4all'); // by key (meta.key field, default: "code")
88
+ const derived = companies.derive('it4all', { name: 'Modified' }); // template + overrides
89
+ const first = companies.findFirst('city', 'Budapest'); // first match by field
90
+ const matches = companies.findAll('role', 'admin'); // all matches by field
91
+ const random = companies.random(); // random item
92
+ const all = companies.all(); // all items
93
+ const count = companies.count(); // count
94
+ ```
95
+
96
+ ## Built-in Steps
97
+
98
+ The package ships reusable TestSteps for common smartbit4all UI patterns (grid, tree navigation). These are available via a separate subpath import to keep them distinct from the core API:
99
+
100
+ ```typescript
101
+ import { selectGridRow, navigateInTree } from '@smartbit4all/playwright-qa/steps';
102
+ ```
103
+
104
+ ### Grid
105
+
106
+ ```typescript
107
+ import {
108
+ selectGridRow,
109
+ filterAndSelectGridRow,
110
+ applyGridFilters,
111
+ clearGridFilters,
112
+ } from '@smartbit4all/playwright-qa/steps';
113
+
114
+ // Find a row by table content (paginates automatically) and double-click it
115
+ await selectGridRow(page, { 'Azonosító': 'DOC-001' });
116
+
117
+ // Find by simple text match
118
+ await selectGridRow(page, 'DOC-001');
119
+
120
+ // Open the row's context menu and click an action
121
+ await selectGridRow(page, { 'Azonosító': 'DOC-001' }, 'Szerkesztés');
122
+
123
+ // Use the filter form above the grid, then select the row
124
+ await filterAndSelectGridRow(page, { 'Azonosító': 'DOC-001' });
125
+
126
+ // Apply/clear filters independently
127
+ await applyGridFilters(page, { 'Név': 'Teszt' });
128
+ await clearGridFilters(page);
129
+ ```
130
+
131
+ ### Navigation
132
+
133
+ ```typescript
134
+ import { navigateToMain, navigateInTree } from '@smartbit4all/playwright-qa/steps';
135
+
136
+ // Click the logo to return to the main screen
137
+ await navigateToMain(page);
138
+
139
+ // Navigate a tree (PrimeNG or Angular Material) — expands intermediate nodes, clicks the last one
140
+ await navigateInTree(page, ['Ügyek']);
141
+ await navigateInTree(page, ['Dokumentumok', 'Tender']);
142
+ ```
143
+
144
+ ### Utilities
145
+
146
+ ```typescript
147
+ import { waitForAngularIdle } from '@smartbit4all/playwright-qa/steps';
148
+
149
+ // Wait for Angular SPA to settle (double networkidle with pause)
150
+ await waitForAngularIdle(page);
151
+ ```
152
+
153
+ `waitForAngularIdle` is also available for project-specific steps that need the same wait pattern.
154
+
155
+ ## Developer Guide — Writing TestSteps
156
+
157
+ TestSteps are simple async functions that implement one atomic UI operation.
158
+
159
+ **Rules:**
160
+ - Receive data as parameters — never import or reference datapools
161
+ - Include locator logic, waits, technical assertions, and screenshots
162
+ - Group related steps in one file per entity/feature
163
+
164
+ ```typescript
165
+ // steps/company.steps.ts
166
+ import { Page } from '@playwright/test';
167
+ import { screenshot } from '@smartbit4all/playwright-qa';
168
+
169
+ export async function fillCompanyForm(page: Page, company: Company) {
170
+ await page.fill('[data-testid="company-name"]', company.name);
171
+ await page.fill('[data-testid="tax-number"]', company.taxNumber);
172
+ await screenshot(page, 'company/form-filled');
173
+ await page.click('[data-testid="save-button"]');
174
+ await page.waitForSelector('.success-toast');
175
+ await screenshot(page, 'company/saved');
176
+ }
177
+ ```
178
+
179
+ ## Organizer Guide — Writing TestSuites
180
+
181
+ TestSuites are Playwright `test.describe` blocks that read like a scenario script.
182
+
183
+ **Rules:**
184
+ - Call `initSuite()` in `beforeAll` to reset state and configure screenshots
185
+ - Initialize datapools in `beforeAll`
186
+ - Select data, then call TestSteps in order
187
+ - Add business-level assertions
188
+
189
+ ```typescript
190
+ // suites/company-management.suite.ts
191
+ import { test } from '@playwright/test';
192
+ import { initSuite, datapool, unique, type DataPool } from '@smartbit4all/playwright-qa';
193
+ import { navigateToMain, selectGridRow } from '@smartbit4all/playwright-qa/steps';
194
+ import { fillCompanyForm } from '../steps/company.steps';
195
+ import type { Company } from '../types';
196
+
197
+ test.describe('Company Management', () => {
198
+ let companies: DataPool<Company>;
199
+
200
+ test.beforeAll(() => {
201
+ initSuite({ screenshotDir: './screenshots' });
202
+ companies = datapool<Company>('companies');
203
+ });
204
+
205
+ test('Create new company', async ({ page }) => {
206
+ const company = companies.derive('it4all', { taxNumber: unique('TAX') });
207
+ await fillCompanyForm(page, company);
208
+ await navigateToMain(page);
209
+ await selectGridRow(page, { 'Adószám': company.taxNumber });
210
+ });
211
+ });
212
+ ```
213
+
214
+ ## Seed Framework
215
+
216
+ Seed populates application data from datapools — either via API or through the UI.
217
+
218
+ ### API Seeding
219
+
220
+ ```typescript
221
+ import { registerSeedHandler, seedViaApi } from '@smartbit4all/playwright-qa';
222
+
223
+ // Register a handler (project-specific)
224
+ registerSeedHandler<Company>('companies', {
225
+ seed: async (company, options) => {
226
+ await fetch(`${options.baseUrl}/api/companies`, {
227
+ method: 'POST',
228
+ headers: { Authorization: `Bearer ${options.authToken}` },
229
+ body: JSON.stringify(company),
230
+ });
231
+ },
232
+ });
233
+
234
+ // Seed all companies
235
+ const result = await seedViaApi('companies', { baseUrl, authToken });
236
+ console.log(`Seeded ${result.success}/${result.total}`);
237
+ ```
238
+
239
+ ### UI Seeding
240
+
241
+ ```typescript
242
+ import { registerUiSeedStep, seedViaUi } from '@smartbit4all/playwright-qa';
243
+
244
+ // Register a UI seed step (reuses your TestSteps)
245
+ registerUiSeedStep<Company>('companies', async (page, company) => {
246
+ await fillCompanyForm(page, company);
247
+ });
248
+
249
+ // Seed through the UI
250
+ const result = await seedViaUi(page, 'companies', { basePath: './datapools', locale: 'hu' });
251
+ ```
252
+
253
+ ### Seed Profiles
254
+
255
+ For complex data with dependencies, use seed profiles:
256
+
257
+ ```json
258
+ {
259
+ "name": "development-full",
260
+ "order": ["users", "organizations", "companies", "documents"],
261
+ "dependencies": {
262
+ "documents": ["companies", "users"],
263
+ "companies": ["organizations"]
264
+ }
265
+ }
266
+ ```
267
+
268
+ ```typescript
269
+ import { seed } from '@smartbit4all/playwright-qa';
270
+
271
+ const profile = JSON.parse(fs.readFileSync('seed-profiles/dev.json', 'utf-8'));
272
+ const results = await seed(profile, 'api', { baseUrl, authToken, basePath: './datapools' });
273
+ ```
274
+
275
+ ## CI Setup
276
+
277
+ ### Azure DevOps
278
+
279
+ 1. Copy `templates/ci/playwright-qa-pipeline.yml` to your project repo
280
+ 2. Set pipeline variables:
281
+ - `BASE_URL`: Your application URL (e.g., `https://staging.example.com`)
282
+ - `LOCALE`: Datapool locale (e.g., `hu`)
283
+ 3. The pipeline will:
284
+ - Run all Playwright tests
285
+ - Publish JUnit results to the Test tab
286
+ - Upload screenshots and HTML report as artifacts
287
+
288
+ ### Project Setup
289
+
290
+ Copy the `templates/playwright-qa/` directory to your project repo:
291
+
292
+ ```bash
293
+ cp -r node_modules/@smartbit4all/playwright-qa/templates/playwright-qa ./playwright-qa
294
+ cd playwright-qa
295
+ npm install
296
+ npx playwright install --with-deps chromium
297
+ ```
298
+
299
+ ## Development
300
+
301
+ ```bash
302
+ git clone <repo-url>
303
+ cd platform-playwright
304
+ npm install
305
+ npx playwright install --with-deps chromium
306
+ npm test
307
+ ```
308
+
309
+ ### Testing locally in a project
310
+
311
+ Use `npm link` to try the package in your own project without publishing:
312
+
313
+ ```bash
314
+ # In platform-playwright:
315
+ npm run build
316
+ npm link
317
+
318
+ # In your project:
319
+ npm link @smartbit4all/playwright-qa
320
+ ```
321
+
322
+ After linking, your project uses the local build directly. When you make changes to the package, rebuild with `npm run build` — no need to re-link.
323
+
324
+ To remove the link later:
325
+
326
+ ```bash
327
+ # In your project:
328
+ npm unlink @smartbit4all/playwright-qa
329
+ npm install
330
+ ```
331
+
332
+ ## License
333
+
334
+ LGPL-3.0-or-later
@@ -0,0 +1,18 @@
1
+ export interface HighlightStyle {
2
+ outline: string;
3
+ backgroundColor: string;
4
+ }
5
+ export interface ViewportSize {
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export interface PlatformPlaywrightConfig {
10
+ screenshotDir: string;
11
+ locale: string;
12
+ datapoolsDir: string;
13
+ highlightStylesFile: string;
14
+ viewport: ViewportSize;
15
+ }
16
+ export declare const defaultConfig: PlatformPlaywrightConfig;
17
+ export declare const defaultHighlightStyles: Record<string, HighlightStyle>;
18
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,eAAO,MAAM,aAAa,EAAE,wBAM3B,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAajE,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultHighlightStyles = exports.defaultConfig = void 0;
4
+ exports.defaultConfig = {
5
+ screenshotDir: './screenshots',
6
+ locale: 'en',
7
+ datapoolsDir: './datapools',
8
+ highlightStylesFile: './highlight-styles.json',
9
+ viewport: { width: 1920, height: 1080 },
10
+ };
11
+ exports.defaultHighlightStyles = {
12
+ default: {
13
+ outline: '3px solid red',
14
+ backgroundColor: 'rgba(255, 0, 0, 0.1)',
15
+ },
16
+ subtle: {
17
+ outline: '2px dashed gray',
18
+ backgroundColor: 'rgba(128, 128, 128, 0.05)',
19
+ },
20
+ success: {
21
+ outline: '3px solid green',
22
+ backgroundColor: 'rgba(0, 255, 0, 0.1)',
23
+ },
24
+ };
25
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";;;AAkBa,QAAA,aAAa,GAA6B;IACrD,aAAa,EAAE,eAAe;IAC9B,MAAM,EAAE,IAAI;IACZ,YAAY,EAAE,aAAa;IAC3B,mBAAmB,EAAE,yBAAyB;IAC9C,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;CACxC,CAAC;AAEW,QAAA,sBAAsB,GAAmC;IACpE,OAAO,EAAE;QACP,OAAO,EAAE,eAAe;QACxB,eAAe,EAAE,sBAAsB;KACxC;IACD,MAAM,EAAE;QACN,OAAO,EAAE,iBAAiB;QAC1B,eAAe,EAAE,2BAA2B;KAC7C;IACD,OAAO,EAAE;QACP,OAAO,EAAE,iBAAiB;QAC1B,eAAe,EAAE,sBAAsB;KACxC;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type PlatformPlaywrightConfig, type HighlightStyle, type ViewportSize } from './defaults';
2
+ export type { PlatformPlaywrightConfig, HighlightStyle, ViewportSize };
3
+ export declare function loadConfig(basePath?: string): PlatformPlaywrightConfig;
4
+ export declare function loadHighlightStyles(basePath?: string): Record<string, HighlightStyle>;
5
+ export declare function getHighlightStyle(name?: string, basePath?: string): HighlightStyle;
6
+ export declare function resetConfig(): void;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,wBAAwB,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAKvE,wBAAgB,UAAU,CAAC,QAAQ,GAAE,MAAsB,GAAG,wBAAwB,CAarF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAcpG;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAkB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,CAO7F;AAED,wBAAgB,WAAW,IAAI,IAAI,CAGlC"}
@@ -0,0 +1,82 @@
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.loadConfig = loadConfig;
37
+ exports.loadHighlightStyles = loadHighlightStyles;
38
+ exports.getHighlightStyle = getHighlightStyle;
39
+ exports.resetConfig = resetConfig;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const defaults_1 = require("./defaults");
43
+ let resolvedConfig = null;
44
+ let resolvedHighlightStyles = null;
45
+ function loadConfig(basePath = process.cwd()) {
46
+ if (resolvedConfig)
47
+ return resolvedConfig;
48
+ const configPath = path.resolve(basePath, 'playwright-qa.config.json');
49
+ let projectConfig = {};
50
+ if (fs.existsSync(configPath)) {
51
+ const raw = fs.readFileSync(configPath, 'utf-8');
52
+ projectConfig = JSON.parse(raw);
53
+ }
54
+ resolvedConfig = { ...defaults_1.defaultConfig, ...projectConfig };
55
+ return resolvedConfig;
56
+ }
57
+ function loadHighlightStyles(basePath = process.cwd()) {
58
+ if (resolvedHighlightStyles)
59
+ return resolvedHighlightStyles;
60
+ const config = loadConfig(basePath);
61
+ const stylesPath = path.resolve(basePath, config.highlightStylesFile);
62
+ let projectStyles = {};
63
+ if (fs.existsSync(stylesPath)) {
64
+ const raw = fs.readFileSync(stylesPath, 'utf-8');
65
+ projectStyles = JSON.parse(raw);
66
+ }
67
+ resolvedHighlightStyles = { ...defaults_1.defaultHighlightStyles, ...projectStyles };
68
+ return resolvedHighlightStyles;
69
+ }
70
+ function getHighlightStyle(name = 'default', basePath) {
71
+ const styles = loadHighlightStyles(basePath);
72
+ const style = styles[name];
73
+ if (!style) {
74
+ throw new Error(`Highlight style '${name}' not found. Available: ${Object.keys(styles).join(', ')}`);
75
+ }
76
+ return style;
77
+ }
78
+ function resetConfig() {
79
+ resolvedConfig = null;
80
+ resolvedHighlightStyles = null;
81
+ }
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,gCAaC;AAED,kDAcC;AAED,8CAOC;AAED,kCAGC;AA1DD,uCAAyB;AACzB,2CAA6B;AAC7B,yCAMoB;AAIpB,IAAI,cAAc,GAAoC,IAAI,CAAC;AAC3D,IAAI,uBAAuB,GAA0C,IAAI,CAAC;AAE1E,SAAgB,UAAU,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IACzD,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAE1C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IACvE,IAAI,aAAa,GAAsC,EAAE,CAAC;IAE1D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,cAAc,GAAG,EAAE,GAAG,wBAAa,EAAE,GAAG,aAAa,EAAE,CAAC;IACxD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAgB,mBAAmB,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAClE,IAAI,uBAAuB;QAAE,OAAO,uBAAuB,CAAC;IAE5D,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACtE,IAAI,aAAa,GAAmC,EAAE,CAAC;IAEvD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,uBAAuB,GAAG,EAAE,GAAG,iCAAsB,EAAE,GAAG,aAAa,EAAE,CAAC;IAC1E,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAAe,SAAS,EAAE,QAAiB;IAC3E,MAAM,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,2BAA2B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,WAAW;IACzB,cAAc,GAAG,IAAI,CAAC;IACtB,uBAAuB,GAAG,IAAI,CAAC;AACjC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface SuiteConfig {
2
+ locale: string;
3
+ baseUrl: string;
4
+ screenshotDir?: string;
5
+ }
6
+ export interface InitSuiteOptions {
7
+ screenshotDir?: string | null;
8
+ autoPrefix?: boolean;
9
+ }
10
+ export declare function initSuite(options?: InitSuiteOptions): void;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAiB1D"}
@@ -0,0 +1,58 @@
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.initSuite = initSuite;
37
+ const fs = __importStar(require("fs"));
38
+ const config_1 = require("../config");
39
+ const datapool_1 = require("../datapool");
40
+ const screenshot_1 = require("../screenshot");
41
+ const seed_1 = require("../seed");
42
+ function initSuite(options) {
43
+ (0, config_1.resetConfig)();
44
+ (0, datapool_1.resetDatapoolConfig)();
45
+ (0, screenshot_1.resetScreenshotDir)();
46
+ (0, seed_1.resetSeedHandlers)();
47
+ const screenshotDir = options?.screenshotDir;
48
+ if (screenshotDir) {
49
+ if (fs.existsSync(screenshotDir)) {
50
+ fs.rmSync(screenshotDir, { recursive: true });
51
+ }
52
+ (0, screenshot_1.initScreenshotDir)(screenshotDir);
53
+ }
54
+ if (options?.autoPrefix) {
55
+ (0, screenshot_1.setAutoPrefix)(true);
56
+ }
57
+ }
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,8BAiBC;AAlCD,uCAAyB;AACzB,sCAAwC;AACxC,0CAAkD;AAClD,8CAAqF;AACrF,kCAA4C;AAa5C,SAAgB,SAAS,CAAC,OAA0B;IAClD,IAAA,oBAAW,GAAE,CAAC;IACd,IAAA,8BAAmB,GAAE,CAAC;IACtB,IAAA,+BAAkB,GAAE,CAAC;IACrB,IAAA,wBAAiB,GAAE,CAAC;IAEpB,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,CAAC;IAC7C,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACjC,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,IAAA,8BAAiB,EAAC,aAAa,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACxB,IAAA,0BAAa,EAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { type DatapoolMeta } from './loader';
2
+ export type { DatapoolMeta } from './loader';
3
+ export { unique, uniqueSeq, resetUniqueSeq } from './unique';
4
+ export interface DatapoolOptions {
5
+ basePath?: string;
6
+ locale?: string;
7
+ }
8
+ export declare function configureDatapool(options: {
9
+ locale?: string;
10
+ basePath?: string;
11
+ }): void;
12
+ export declare function resetDatapoolConfig(): void;
13
+ export declare class DataPool<T> {
14
+ private items;
15
+ private locale;
16
+ private locales;
17
+ private keyField;
18
+ readonly meta: DatapoolMeta;
19
+ constructor(items: T[], meta: DatapoolMeta, locale: string);
20
+ byKey(key: string): T;
21
+ derive(key: string, overrides: Partial<T>): T;
22
+ findFirst<K extends keyof T>(field: K, value: T[K]): T;
23
+ findAll<K extends keyof T>(field: K, value: T[K]): T[];
24
+ random(): T;
25
+ all(): T[];
26
+ count(): number;
27
+ }
28
+ export declare function datapool<T>(name: string, options?: DatapoolOptions): DataPool<T>;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/datapool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAI/D,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK7D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGvF;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED,qBAAa,QAAQ,CAAC,CAAC;IACrB,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;gBAG1B,KAAK,EAAE,CAAC,EAAE,EACV,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM;IAShB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC;IAWrB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAK7C,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAUtD,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;IAKtD,MAAM,IAAI,CAAC;IAQX,GAAG,IAAI,CAAC,EAAE;IAMV,KAAK,IAAI,MAAM;CAGhB;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,QAAQ,CAAC,CAAC,CAAC,CAOpF"}