@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
@@ -0,0 +1,41 @@
1
+ import type { Page } from '@playwright/test';
2
+ export interface SeedOptions {
3
+ baseUrl?: string;
4
+ authToken?: string;
5
+ }
6
+ export interface SeedHandler<T> {
7
+ seed(item: T, options: SeedOptions): Promise<void>;
8
+ }
9
+ export interface SeedResult {
10
+ datapool: string;
11
+ total: number;
12
+ success: number;
13
+ failed: number;
14
+ errors: Array<{
15
+ code: string;
16
+ error: string;
17
+ }>;
18
+ }
19
+ export interface SeedProfileJson {
20
+ name: string;
21
+ description?: string;
22
+ order: string[];
23
+ dependencies?: Record<string, string[]>;
24
+ }
25
+ export declare function resetSeedHandlers(): void;
26
+ export declare function registerSeedHandler<T>(datapoolName: string, handler: SeedHandler<T>): void;
27
+ export declare function registerUiSeedStep<T>(datapoolName: string, step: (page: Page, item: T) => Promise<void>): void;
28
+ export declare function seedViaApi(datapoolName: string, options: SeedOptions & {
29
+ basePath?: string;
30
+ locale?: string;
31
+ }): Promise<SeedResult>;
32
+ export declare function seedViaUi(page: Page, datapoolName: string, options: {
33
+ basePath?: string;
34
+ locale?: string;
35
+ }): Promise<SeedResult>;
36
+ export declare function seed(profile: SeedProfileJson, mode: 'api' | 'ui', options: SeedOptions & {
37
+ page?: Page;
38
+ basePath?: string;
39
+ locale?: string;
40
+ }): Promise<SeedResult[]>;
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/seed/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACzC;AAMD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GACtB,IAAI,CAEN;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAC3C,IAAI,CAEN;AAkCD,wBAAsB,UAAU,CAC9B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,WAAW,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,OAAO,CAAC,UAAU,CAAC,CAkCrB;AAED,wBAAsB,SAAS,CAC7B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,UAAU,CAAC,CAkCrB;AAED,wBAAsB,IAAI,CACxB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,KAAK,GAAG,IAAI,EAClB,OAAO,EAAE,WAAW,GAAG;IAAE,IAAI,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE,OAAO,CAAC,UAAU,EAAE,CAAC,CAgCvB"}
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resetSeedHandlers = resetSeedHandlers;
4
+ exports.registerSeedHandler = registerSeedHandler;
5
+ exports.registerUiSeedStep = registerUiSeedStep;
6
+ exports.seedViaApi = seedViaApi;
7
+ exports.seedViaUi = seedViaUi;
8
+ exports.seed = seed;
9
+ const datapool_1 = require("../datapool");
10
+ // Handler registry
11
+ const apiHandlers = new Map();
12
+ const uiHandlers = new Map();
13
+ function resetSeedHandlers() {
14
+ apiHandlers.clear();
15
+ uiHandlers.clear();
16
+ }
17
+ function registerSeedHandler(datapoolName, handler) {
18
+ apiHandlers.set(datapoolName, handler);
19
+ }
20
+ function registerUiSeedStep(datapoolName, step) {
21
+ uiHandlers.set(datapoolName, step);
22
+ }
23
+ // Topological sort
24
+ function topologicalSort(order, dependencies) {
25
+ const visited = new Set();
26
+ const result = [];
27
+ const visiting = new Set();
28
+ function visit(node) {
29
+ if (visiting.has(node)) {
30
+ throw new Error(`Circular dependency detected involving '${node}'`);
31
+ }
32
+ if (visited.has(node))
33
+ return;
34
+ visiting.add(node);
35
+ const deps = dependencies[node] || [];
36
+ for (const dep of deps) {
37
+ visit(dep);
38
+ }
39
+ visiting.delete(node);
40
+ visited.add(node);
41
+ result.push(node);
42
+ }
43
+ for (const node of order) {
44
+ visit(node);
45
+ }
46
+ return result;
47
+ }
48
+ async function seedViaApi(datapoolName, options) {
49
+ const handler = apiHandlers.get(datapoolName);
50
+ if (!handler) {
51
+ throw new Error(`No API seed handler registered for '${datapoolName}'`);
52
+ }
53
+ const pool = (0, datapool_1.datapool)(datapoolName, {
54
+ basePath: options.basePath,
55
+ locale: options.locale,
56
+ });
57
+ const items = pool.all();
58
+ const result = {
59
+ datapool: datapoolName,
60
+ total: items.length,
61
+ success: 0,
62
+ failed: 0,
63
+ errors: [],
64
+ };
65
+ for (const item of items) {
66
+ try {
67
+ await handler.seed(item, options);
68
+ result.success++;
69
+ }
70
+ catch (err) {
71
+ result.failed++;
72
+ result.errors.push({
73
+ code: item.code,
74
+ error: err instanceof Error ? err.message : String(err),
75
+ });
76
+ }
77
+ }
78
+ return result;
79
+ }
80
+ async function seedViaUi(page, datapoolName, options) {
81
+ const step = uiHandlers.get(datapoolName);
82
+ if (!step) {
83
+ throw new Error(`No UI seed step registered for '${datapoolName}'`);
84
+ }
85
+ const pool = (0, datapool_1.datapool)(datapoolName, {
86
+ basePath: options.basePath,
87
+ locale: options.locale,
88
+ });
89
+ const items = pool.all();
90
+ const result = {
91
+ datapool: datapoolName,
92
+ total: items.length,
93
+ success: 0,
94
+ failed: 0,
95
+ errors: [],
96
+ };
97
+ for (const item of items) {
98
+ try {
99
+ await step(page, item);
100
+ result.success++;
101
+ }
102
+ catch (err) {
103
+ result.failed++;
104
+ result.errors.push({
105
+ code: item.code,
106
+ error: err instanceof Error ? err.message : String(err),
107
+ });
108
+ }
109
+ }
110
+ return result;
111
+ }
112
+ async function seed(profile, mode, options) {
113
+ const sorted = topologicalSort(profile.order, profile.dependencies ?? {});
114
+ const results = [];
115
+ for (const datapoolName of sorted) {
116
+ console.log(`Seeding: ${datapoolName}...`);
117
+ let result;
118
+ try {
119
+ if (mode === 'api') {
120
+ result = await seedViaApi(datapoolName, options);
121
+ }
122
+ else {
123
+ if (!options.page) {
124
+ throw new Error('seedViaUi requires a Page instance in options.page');
125
+ }
126
+ result = await seedViaUi(options.page, datapoolName, options);
127
+ }
128
+ }
129
+ catch (err) {
130
+ result = {
131
+ datapool: datapoolName,
132
+ total: 0,
133
+ success: 0,
134
+ failed: 1,
135
+ errors: [{ code: datapoolName, error: err instanceof Error ? err.message : String(err) }],
136
+ };
137
+ }
138
+ console.log(` ${datapoolName}: ${result.success}/${result.total} OK, ${result.failed} failed`);
139
+ results.push(result);
140
+ }
141
+ return results;
142
+ }
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/seed/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { Page } from '@playwright/test';
2
+ export type RowFilter = string | Record<string, string>;
3
+ /**
4
+ * Finds a row in the grid by content match (paginating if needed) and performs an action.
5
+ * Does NOT use the filter form — searches through the actual table rows.
6
+ */
7
+ export declare function selectGridRow(page: Page, filter: RowFilter, action?: string): Promise<void>;
8
+ /**
9
+ * Uses the filter form above the grid to narrow results, then performs an action on the first match.
10
+ * The filter keys must match the labels above the filter inputs (e.g. "Azonosito", "Nev").
11
+ */
12
+ export declare function filterAndSelectGridRow(page: Page, filter: Record<string, string>, action?: string): Promise<void>;
13
+ /**
14
+ * Fills the filter form above the grid and clicks the search button.
15
+ */
16
+ export declare function applyGridFilters(page: Page, filter: Record<string, string>): Promise<void>;
17
+ /**
18
+ * Clears all filter inputs and re-triggers search.
19
+ */
20
+ export declare function clearGridFilters(page: Page): Promise<void>;
21
+ //# sourceMappingURL=grid.steps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.steps.d.ts","sourceRoot":"","sources":["../../src/steps/grid.steps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,kBAAkB,CAAC;AAItD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhG;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhE"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectGridRow = selectGridRow;
4
+ exports.filterAndSelectGridRow = filterAndSelectGridRow;
5
+ exports.applyGridFilters = applyGridFilters;
6
+ exports.clearGridFilters = clearGridFilters;
7
+ const test_1 = require("@playwright/test");
8
+ const wait_1 = require("./wait");
9
+ /**
10
+ * Finds a row in the grid by content match (paginating if needed) and performs an action.
11
+ * Does NOT use the filter form — searches through the actual table rows.
12
+ */
13
+ async function selectGridRow(page, filter, action) {
14
+ const table = page.locator('table');
15
+ await table.locator('tbody tr').first().waitFor({ timeout: 15000 });
16
+ const row = await findRowWithPagination(page, table, filter);
17
+ if (!action || action === 'default') {
18
+ await row.dblclick();
19
+ }
20
+ else {
21
+ await row.locator('td.mat-column-my_menu button').click();
22
+ await page.locator('.mat-mdc-menu-panel button.mat-mdc-menu-item', { hasText: action }).click();
23
+ }
24
+ }
25
+ /**
26
+ * Uses the filter form above the grid to narrow results, then performs an action on the first match.
27
+ * The filter keys must match the labels above the filter inputs (e.g. "Azonosito", "Nev").
28
+ */
29
+ async function filterAndSelectGridRow(page, filter, action) {
30
+ await applyGridFilters(page, filter);
31
+ const table = page.locator('table');
32
+ await table.locator('tbody tr').first().waitFor({ timeout: 15000 });
33
+ const row = await findRow(page, table, filter);
34
+ if (!action || action === 'default') {
35
+ await row.dblclick();
36
+ }
37
+ else {
38
+ await row.locator('td.mat-column-my_menu button').click();
39
+ await page.locator('.mat-mdc-menu-panel button.mat-mdc-menu-item', { hasText: action }).click();
40
+ }
41
+ }
42
+ /**
43
+ * Fills the filter form above the grid and clicks the search button.
44
+ */
45
+ async function applyGridFilters(page, filter) {
46
+ for (const [header, value] of Object.entries(filter)) {
47
+ const container = page.locator('div.container', {
48
+ has: page.locator('h4.smart-form-widget-label', { hasText: header }),
49
+ });
50
+ const filterInput = container.locator('input.mat-mdc-input-element');
51
+ await filterInput.fill(value);
52
+ }
53
+ await page.locator('button', { has: page.locator('mat-icon', { hasText: 'search' }) }).click();
54
+ await (0, wait_1.waitForAngularIdle)(page);
55
+ }
56
+ /**
57
+ * Clears all filter inputs and re-triggers search.
58
+ */
59
+ async function clearGridFilters(page) {
60
+ const clearButtons = page.locator('.textFieldButtons button');
61
+ const count = await clearButtons.count();
62
+ for (let i = 0; i < count; i++) {
63
+ await clearButtons.nth(i).click();
64
+ }
65
+ await page.locator('button', { has: page.locator('mat-icon', { hasText: 'search' }) }).click();
66
+ await (0, wait_1.waitForAngularIdle)(page);
67
+ }
68
+ // --- Private helpers ---
69
+ async function findRowWithPagination(page, table, filter) {
70
+ const maxPages = 20;
71
+ for (let pageNum = 0; pageNum < maxPages; pageNum++) {
72
+ const row = await findRowOnCurrentPage(page, table, filter);
73
+ if (row)
74
+ return row;
75
+ // Try to go to next page
76
+ const nextBtn = page.locator('.mat-mdc-paginator-navigation-next');
77
+ if (await nextBtn.isDisabled()) {
78
+ break;
79
+ }
80
+ await nextBtn.click();
81
+ await page.waitForLoadState('networkidle');
82
+ await page.waitForTimeout(300);
83
+ }
84
+ // Row not found on any page
85
+ const filterDesc = typeof filter === 'string'
86
+ ? filter
87
+ : Object.entries(filter).map(([k, v]) => `${k}="${v}"`).join(', ');
88
+ throw new Error(`Grid row not found after paginating through all pages. Filter: ${filterDesc}`);
89
+ }
90
+ async function findRowOnCurrentPage(page, table, filter) {
91
+ if (typeof filter === 'string') {
92
+ const row = table.locator('tbody tr', { hasText: filter }).first();
93
+ return await row.count() > 0 ? row : null;
94
+ }
95
+ const columnMap = await buildColumnMap(table);
96
+ const entries = Object.entries(filter);
97
+ const firstEntry = entries[0];
98
+ const columnId = columnMap.get(firstEntry[0]);
99
+ if (!columnId) {
100
+ throw new Error(`Column "${firstEntry[0]}" not found. Available: ${Array.from(columnMap.keys()).join(', ')}`);
101
+ }
102
+ let rowLocator = table.locator('tbody tr', {
103
+ has: page.locator(`td.mat-column-${columnId}`, { hasText: firstEntry[1] }),
104
+ });
105
+ for (let i = 1; i < entries.length; i++) {
106
+ const colId = columnMap.get(entries[i][0]);
107
+ if (!colId) {
108
+ throw new Error(`Column "${entries[i][0]}" not found. Available: ${Array.from(columnMap.keys()).join(', ')}`);
109
+ }
110
+ rowLocator = rowLocator.filter({
111
+ has: page.locator(`td.mat-column-${colId}`, { hasText: entries[i][1] }),
112
+ });
113
+ }
114
+ return await rowLocator.count() > 0 ? rowLocator.first() : null;
115
+ }
116
+ async function findRow(page, table, filter) {
117
+ if (typeof filter === 'string') {
118
+ return table.locator('tbody tr', { hasText: filter }).first();
119
+ }
120
+ const columnMap = await buildColumnMap(table);
121
+ const entries = Object.entries(filter);
122
+ const firstEntry = entries[0];
123
+ const columnId = columnMap.get(firstEntry[0]);
124
+ if (!columnId) {
125
+ throw new Error(`Column "${firstEntry[0]}" not found. Available: ${Array.from(columnMap.keys()).join(', ')}`);
126
+ }
127
+ let rowLocator = table.locator('tbody tr', {
128
+ has: page.locator(`td.mat-column-${columnId}`, { hasText: firstEntry[1] }),
129
+ });
130
+ for (let i = 1; i < entries.length; i++) {
131
+ const colId = columnMap.get(entries[i][0]);
132
+ if (!colId) {
133
+ throw new Error(`Column "${entries[i][0]}" not found. Available: ${Array.from(columnMap.keys()).join(', ')}`);
134
+ }
135
+ rowLocator = rowLocator.filter({
136
+ has: page.locator(`td.mat-column-${colId}`, { hasText: entries[i][1] }),
137
+ });
138
+ }
139
+ await (0, test_1.expect)(rowLocator.first()).toBeVisible({ timeout: 15000 });
140
+ return rowLocator.first();
141
+ }
142
+ async function buildColumnMap(table) {
143
+ const headers = await table.locator('th').all();
144
+ const columnMap = new Map();
145
+ for (const th of headers) {
146
+ const text = (await th.textContent())?.trim() ?? '';
147
+ const classList = await th.evaluate(el => Array.from(el.classList).find(c => c.startsWith('mat-column-')) ?? '');
148
+ if (text && classList) {
149
+ columnMap.set(text, classList.replace('mat-column-', ''));
150
+ }
151
+ }
152
+ return columnMap;
153
+ }
154
+ //# sourceMappingURL=grid.steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.steps.js","sourceRoot":"","sources":["../../src/steps/grid.steps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { waitForAngularIdle } from './wait';
2
+ export { selectGridRow, filterAndSelectGridRow, applyGridFilters, clearGridFilters, type RowFilter, } from './grid.steps';
3
+ export { navigateToMain, navigateInTree, } from './navigation.steps';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,EACd,cAAc,GACf,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.navigateInTree = exports.navigateToMain = exports.clearGridFilters = exports.applyGridFilters = exports.filterAndSelectGridRow = exports.selectGridRow = exports.waitForAngularIdle = void 0;
4
+ var wait_1 = require("./wait");
5
+ Object.defineProperty(exports, "waitForAngularIdle", { enumerable: true, get: function () { return wait_1.waitForAngularIdle; } });
6
+ var grid_steps_1 = require("./grid.steps");
7
+ Object.defineProperty(exports, "selectGridRow", { enumerable: true, get: function () { return grid_steps_1.selectGridRow; } });
8
+ Object.defineProperty(exports, "filterAndSelectGridRow", { enumerable: true, get: function () { return grid_steps_1.filterAndSelectGridRow; } });
9
+ Object.defineProperty(exports, "applyGridFilters", { enumerable: true, get: function () { return grid_steps_1.applyGridFilters; } });
10
+ Object.defineProperty(exports, "clearGridFilters", { enumerable: true, get: function () { return grid_steps_1.clearGridFilters; } });
11
+ var navigation_steps_1 = require("./navigation.steps");
12
+ Object.defineProperty(exports, "navigateToMain", { enumerable: true, get: function () { return navigation_steps_1.navigateToMain; } });
13
+ Object.defineProperty(exports, "navigateInTree", { enumerable: true, get: function () { return navigation_steps_1.navigateInTree; } });
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":";;;AAAA,+BAA4C;AAAnC,0GAAA,kBAAkB,OAAA;AAE3B,2CAMsB;AALpB,2GAAA,aAAa,OAAA;AACb,oHAAA,sBAAsB,OAAA;AACtB,8GAAA,gBAAgB,OAAA;AAChB,8GAAA,gBAAgB,OAAA;AAIlB,uDAG4B;AAF1B,kHAAA,cAAc,OAAA;AACd,kHAAA,cAAc,OAAA"}
@@ -0,0 +1,4 @@
1
+ import type { Page } from '@playwright/test';
2
+ export declare function navigateToMain(page: Page): Promise<void>;
3
+ export declare function navigateInTree(page: Page, path: string[]): Promise<void>;
4
+ //# sourceMappingURL=navigation.steps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.steps.d.ts","sourceRoot":"","sources":["../../src/steps/navigation.steps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI7C,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B9E"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.navigateToMain = navigateToMain;
4
+ exports.navigateInTree = navigateInTree;
5
+ const screenshot_1 = require("../screenshot");
6
+ const wait_1 = require("./wait");
7
+ async function navigateToMain(page) {
8
+ await page.locator('div.logo').click();
9
+ await page.waitForURL('**/main/**');
10
+ await (0, wait_1.waitForAngularIdle)(page);
11
+ await (0, screenshot_1.screenshot)(page, 'navigation/main-screen');
12
+ }
13
+ async function navigateInTree(page, path) {
14
+ const firstLabel = path[0];
15
+ const primeNode = page.locator(`[role="treeitem"][aria-label="${firstLabel}"]`);
16
+ const matNode = page.locator('.mat-tree-node', { has: page.locator(`.sm-tree-row-caption:text-is("${firstLabel}")`) });
17
+ // Wait for either tree type to appear
18
+ await Promise.race([
19
+ primeNode.first().waitFor({ timeout: 10000 }).catch(() => { }),
20
+ matNode.first().waitFor({ timeout: 10000 }).catch(() => { }),
21
+ ]);
22
+ const usePrime = await primeNode.count() > 0;
23
+ const useMat = !usePrime && await matNode.count() > 0;
24
+ for (let i = 0; i < path.length; i++) {
25
+ const label = path[i];
26
+ const isLast = i === path.length - 1;
27
+ if (usePrime) {
28
+ await navigatePrimeTreeNode(page, label, isLast);
29
+ }
30
+ else if (useMat) {
31
+ await navigateMatTreeNode(page, label, isLast);
32
+ }
33
+ else {
34
+ throw new Error(`Tree node "${firstLabel}" not found in any tree component`);
35
+ }
36
+ }
37
+ await (0, wait_1.waitForAngularIdle)(page);
38
+ await (0, screenshot_1.screenshot)(page, `navigation/tree-${path[path.length - 1]}`);
39
+ }
40
+ async function navigatePrimeTreeNode(page, label, select) {
41
+ const node = page.locator(`[role="treeitem"][aria-label="${label}"]`);
42
+ await node.waitFor();
43
+ if (select) {
44
+ const urlBefore = page.url();
45
+ await node.locator('.p-treenode-content').click();
46
+ await page.waitForURL(url => url.toString() !== urlBefore, { timeout: 5000 }).catch(() => { });
47
+ await (0, wait_1.waitForAngularIdle)(page);
48
+ }
49
+ else {
50
+ const alreadyExpanded = await node.evaluate(el => el.getAttribute('aria-expanded') === 'true');
51
+ if (!alreadyExpanded) {
52
+ const toggler = node.locator('.p-tree-toggler');
53
+ const isVisible = await toggler.evaluate(el => window.getComputedStyle(el).visibility === 'visible');
54
+ if (isVisible) {
55
+ await toggler.click();
56
+ await page.waitForTimeout(300);
57
+ }
58
+ }
59
+ }
60
+ }
61
+ async function navigateMatTreeNode(page, label, select) {
62
+ const node = page.locator('.mat-tree-node', { has: page.locator(`.sm-tree-row-caption:text-is("${label}")`) });
63
+ await node.waitFor();
64
+ const treeitem = page.locator(`[role="treeitem"]`, { has: node });
65
+ if (select) {
66
+ const urlBefore = page.url();
67
+ await node.locator('.sm-tree-row-caption').click();
68
+ await page.waitForURL(url => url.toString() !== urlBefore, { timeout: 5000 }).catch(() => { });
69
+ await (0, wait_1.waitForAngularIdle)(page);
70
+ }
71
+ else {
72
+ const alreadyExpanded = await treeitem.evaluate(el => el.getAttribute('aria-expanded') === 'true');
73
+ if (!alreadyExpanded) {
74
+ await node.locator('button').first().click();
75
+ await page.waitForTimeout(300);
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=navigation.steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.steps.js","sourceRoot":"","sources":["../../src/steps/navigation.steps.ts"],"names":[],"mappings":";;AAIA,wCAMC;AAED,wCA6BC;AAxCD,8CAA2C;AAC3C,iCAA4C;AAErC,KAAK,UAAU,cAAc,CAAC,IAAU;IAC7C,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;IACvC,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAEpC,MAAM,IAAA,yBAAkB,EAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAA,uBAAU,EAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;AACnD,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,IAAU,EAAE,IAAc;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,iCAAiC,UAAU,IAAI,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,iCAAiC,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC;IAEvH,sCAAsC;IACtC,MAAM,OAAO,CAAC,IAAI,CAAC;QACjB,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;KAC5D,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,CAAC,QAAQ,IAAI,MAAM,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAErC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,cAAc,UAAU,mCAAmC,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,MAAM,IAAA,yBAAkB,EAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAA,uBAAU,EAAC,IAAI,EAAE,mBAAmB,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,IAAU,EAAE,KAAa,EAAE,MAAe;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iCAAiC,KAAK,IAAI,CAAC,CAAC;IACtE,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IAErB,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,KAAK,EAAE,CAAC;QAClD,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC9F,MAAM,IAAA,yBAAkB,EAAC,IAAI,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,QAAQ,CACzC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM,CAClD,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YAChD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,QAAQ,CACtC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,UAAU,KAAK,SAAS,CAC3D,CAAC;YACF,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,IAAU,EAAE,KAAa,EAAE,MAAe;IAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,iCAAiC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/G,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IAErB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAElE,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;QACnD,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC9F,MAAM,IAAA,yBAAkB,EAAC,IAAI,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAC7C,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM,CAClD,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;YAC7C,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Page } from '@playwright/test';
2
+ /**
3
+ * Angular SPAs load in waves: route change -> initial render -> API calls -> data render.
4
+ * A single networkidle can fire in the gap between waves.
5
+ * This waits for two consecutive networkidle states with a pause between them.
6
+ */
7
+ export declare function waitForAngularIdle(page: Page): Promise<void>;
8
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../src/steps/wait.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlE"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.waitForAngularIdle = waitForAngularIdle;
4
+ /**
5
+ * Angular SPAs load in waves: route change -> initial render -> API calls -> data render.
6
+ * A single networkidle can fire in the gap between waves.
7
+ * This waits for two consecutive networkidle states with a pause between them.
8
+ */
9
+ async function waitForAngularIdle(page) {
10
+ await page.waitForLoadState('networkidle');
11
+ await page.waitForTimeout(500);
12
+ await page.waitForLoadState('networkidle');
13
+ }
14
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/steps/wait.ts"],"names":[],"mappings":";;AAOA,gDAIC;AATD;;;;GAIG;AACI,KAAK,UAAU,kBAAkB,CAAC,IAAU;IACjD,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;AAC7C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@smartbit4all/playwright-qa",
3
+ "version": "0.1.0",
4
+ "description": "Playwright-based testing and documentation framework for smartbit4all projects",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./steps": {
13
+ "types": "./dist/steps/index.d.ts",
14
+ "default": "./dist/steps/index.js"
15
+ }
16
+ },
17
+ "typesVersions": {
18
+ "*": {
19
+ "steps": ["dist/steps/index.d.ts"]
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "templates"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "test": "playwright test",
29
+ "prepublishOnly": "npm run build",
30
+ "publish:npm": "npm run test && npm publish --access public"
31
+ },
32
+ "engines": {
33
+ "node": ">=20.0.0"
34
+ },
35
+ "peerDependencies": {
36
+ "@playwright/test": ">=1.40.0"
37
+ },
38
+ "devDependencies": {
39
+ "@playwright/test": "^1.50.0",
40
+ "@types/node": "^25.2.3",
41
+ "typescript": "^5.7.0"
42
+ },
43
+ "keywords": [
44
+ "playwright",
45
+ "testing",
46
+ "screenshot",
47
+ "qa",
48
+ "smartbit4all"
49
+ ],
50
+ "license": "LGPL-3.0-or-later",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/nickkoo/playwright-qa.git"
54
+ }
55
+ }