@vuu-ui/vuu-playwright-helpers 3.5.4 → 3.5.6
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 +19 -1
- package/package.json +2 -2
- package/src/PlaywrightPageObject.js +7 -0
- package/src/{Table.js → PwTable.js} +34 -10
- package/src/PwTableHeaderCell.js +15 -0
- package/src/index.js +3 -1
- package/types/PlaywrightPageObject.d.ts +5 -0
- package/types/{Table.d.ts → PwTable.d.ts} +17 -3
- package/types/PwTableHeaderCell.d.ts +8 -0
- package/types/index.d.ts +3 -1
package/README.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Playwright helpers for Vuu components.
|
|
4
4
|
|
|
5
|
+
All helpers extend `PlaywrightPageObject` and are instantiated from the Playwright `page`.
|
|
6
|
+
`PwTable` locates its target element using a default CSS selector, which can be
|
|
7
|
+
overridden at runtime. `PwTableHeaderCell` requires an explicit CSS selector.
|
|
8
|
+
|
|
5
9
|
```ts
|
|
6
|
-
|
|
10
|
+
// uses the default selector (.vuuTable)
|
|
11
|
+
const table = new PwTable(page);
|
|
12
|
+
// override the default selector
|
|
13
|
+
const table1 = new PwTable(page, '[data-testid="table-1"]');
|
|
14
|
+
|
|
15
|
+
const cell = await table.cell("currency", 2);
|
|
16
|
+
const header = table.headerCell("currency");
|
|
17
|
+
const isSelected = await header.isSelected;
|
|
18
|
+
await header.assertSelected();
|
|
19
|
+
await table.editCell("currency", 2, "USD"); // commits by default
|
|
20
|
+
await table.editCell("currency", 2, "EUR", "cancel");
|
|
7
21
|
```
|
|
22
|
+
|
|
23
|
+
Prefer `cell(colName, ariaRowIndex)` for new usage. `ariaRowIndex` is the 1-based
|
|
24
|
+
ARIA row index, including header rows (with one header, the first data row is 2).
|
|
25
|
+
The existing `locateCell` overloads remain available for gradual migration.
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.5.
|
|
2
|
+
"version": "3.5.6",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./src/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@vuu-ui/vuu-protocol-types": "3.5.
|
|
12
|
+
"@vuu-ui/vuu-protocol-types": "3.5.6"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
15
|
"@playwright/test": "^1.62.1"
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { expect } from "@playwright/test";
|
|
2
|
+
import { PlaywrightPageObject } from "./PlaywrightPageObject.js";
|
|
3
|
+
import { PwTableHeaderCell } from "./PwTableHeaderCell.js";
|
|
2
4
|
const byAriaRowIndex = (ariaRowIndex)=>`[aria-rowindex="${ariaRowIndex}"]:scope`;
|
|
3
5
|
const xpathStringLiteral = (value)=>{
|
|
4
6
|
if (!value.includes("'")) return `'${value}'`;
|
|
5
7
|
if (!value.includes('"')) return `"${value}"`;
|
|
6
8
|
return `concat('${value.split("'").join("', \"'\", '")}')`;
|
|
7
9
|
};
|
|
8
|
-
class
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
class PwTable extends PlaywrightPageObject {
|
|
11
|
+
cssSelector;
|
|
12
|
+
defaultCssSelector = ".vuuTable";
|
|
13
|
+
constructor(page, cssSelector){
|
|
14
|
+
super(page), this.cssSelector = cssSelector;
|
|
15
|
+
}
|
|
16
|
+
get #locator() {
|
|
17
|
+
return this.page.locator(this.cssSelector ?? this.defaultCssSelector);
|
|
12
18
|
}
|
|
13
19
|
get contentContainer() {
|
|
14
20
|
return this.#locator.locator(".vuuTable-contentContainer");
|
|
@@ -19,12 +25,30 @@ class TableOM {
|
|
|
19
25
|
row(row) {
|
|
20
26
|
return this.#locator.locator(`[aria-rowindex="${row}"]`);
|
|
21
27
|
}
|
|
28
|
+
cell(colName, ariaRowIndex) {
|
|
29
|
+
return this.locateCell(ariaRowIndex, colName);
|
|
30
|
+
}
|
|
31
|
+
async editCell(columnName, ariaRowIndex, value, action = "commit") {
|
|
32
|
+
const cell = await this.cell(columnName, ariaRowIndex);
|
|
33
|
+
await cell.dblclick();
|
|
34
|
+
const textbox = cell.getByRole("textbox");
|
|
35
|
+
await textbox.fill(value);
|
|
36
|
+
await expect(textbox).toHaveValue(value);
|
|
37
|
+
await textbox.press("commit" === action ? "Enter" : "Escape");
|
|
38
|
+
}
|
|
39
|
+
headerCell(columnName) {
|
|
40
|
+
const escapedColumnName = Array.from(columnName, (character)=>{
|
|
41
|
+
const code = character.charCodeAt(0);
|
|
42
|
+
return '"' === character || "\\" === character || code < 32 || 127 === code ? `\\${code.toString(16)} ` : character;
|
|
43
|
+
}).join("");
|
|
44
|
+
return new PwTableHeaderCell(this.page, `${this.cssSelector ?? this.defaultCssSelector} >> .vuuTableHeaderCell[data-column-name="${escapedColumnName}"]`);
|
|
45
|
+
}
|
|
22
46
|
locateCell(rowOrText, column) {
|
|
23
47
|
if ("number" == typeof rowOrText && "number" == typeof column) return this.#locator.locator(`[aria-rowindex="${rowOrText}"] > [aria-colindex="${column}"]`);
|
|
24
48
|
if ("number" == typeof rowOrText && "string" == typeof column) {
|
|
25
49
|
const columnHeader = this.#locator.locator(`xpath=.//*[@data-column-name=${xpathStringLiteral(column)}]`).first();
|
|
26
50
|
return columnHeader.getAttribute("aria-colindex").then((ariaColIndex)=>{
|
|
27
|
-
if (null === ariaColIndex) throw Error(`
|
|
51
|
+
if (null === ariaColIndex) throw Error(`PwTable, locateCell, column "${column}" does not have an aria-colindex`);
|
|
28
52
|
return this.#locator.locator(`[aria-rowindex="${rowOrText}"] > [aria-colindex="${ariaColIndex}"]`);
|
|
29
53
|
});
|
|
30
54
|
}
|
|
@@ -65,13 +89,13 @@ class TableOM {
|
|
|
65
89
|
const [cell, text, role] = this.getCellText(arg1, arg2, arg3, arg4);
|
|
66
90
|
const target = role ? cell.getByRole(role) : cell;
|
|
67
91
|
if (target) await expect(target).toHaveValue(text);
|
|
68
|
-
else throw Error("
|
|
92
|
+
else throw Error("PwTable, assertCellValue, invalid parameters");
|
|
69
93
|
}
|
|
70
94
|
async assertCellContent(arg1, arg2, arg3, arg4) {
|
|
71
95
|
const [cell, text, role] = this.getCellText(arg1, arg2, arg3, arg4);
|
|
72
96
|
const target = role ? cell.getByRole(role) : cell;
|
|
73
97
|
if (target) await expect(target).toHaveText(text);
|
|
74
|
-
else throw Error("
|
|
98
|
+
else throw Error("PwTable, assertCellContent, invalid parameters");
|
|
75
99
|
}
|
|
76
100
|
async assertCellIsFocused(rowOrCell, columnOrRole, role) {
|
|
77
101
|
let target;
|
|
@@ -80,7 +104,7 @@ class TableOM {
|
|
|
80
104
|
target = role ? cell.getByRole(role) : cell;
|
|
81
105
|
} else if ("number" != typeof rowOrCell) target = columnOrRole && "number" != typeof columnOrRole ? rowOrCell.getByRole(columnOrRole) : rowOrCell;
|
|
82
106
|
if (target) await expect(target).toBeFocused();
|
|
83
|
-
else throw Error("
|
|
107
|
+
else throw Error("PwTable, assertCellIsFocused, invalid parameters");
|
|
84
108
|
}
|
|
85
109
|
async assertCellIsEditing(rowOrCell, columnOrEditing, isEditing) {
|
|
86
110
|
let target;
|
|
@@ -97,7 +121,7 @@ class TableOM {
|
|
|
97
121
|
if (editing) return expect(target.locator(editControl)).toContainClass("vuuEditing");
|
|
98
122
|
return expect(target.locator(editControl)).not.toContainClass("vuuEditing");
|
|
99
123
|
}
|
|
100
|
-
throw Error("
|
|
124
|
+
throw Error("PwTable, assertCellIsEditing, invalid parameters");
|
|
101
125
|
}
|
|
102
126
|
async assertRenderedRows({ from, to }, renderBufferSize, totalRowCount, headerCount = 1) {
|
|
103
127
|
const leadingBufferedRows = from < renderBufferSize ? from : renderBufferSize;
|
|
@@ -126,4 +150,4 @@ class TableOM {
|
|
|
126
150
|
if (lastRendered > lastVisible) await expect(this.locateCell(2, lastVisible + 1)).not.toBeInViewport();
|
|
127
151
|
}
|
|
128
152
|
}
|
|
129
|
-
export {
|
|
153
|
+
export { PwTable };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { expect } from "@playwright/test";
|
|
2
|
+
import { PlaywrightPageObject } from "./PlaywrightPageObject.js";
|
|
3
|
+
class PwTableHeaderCell extends PlaywrightPageObject {
|
|
4
|
+
cssSelector;
|
|
5
|
+
constructor(page, cssSelector){
|
|
6
|
+
super(page), this.cssSelector = cssSelector;
|
|
7
|
+
}
|
|
8
|
+
get isSelected() {
|
|
9
|
+
return this.page.locator(this.cssSelector).evaluate((element)=>element.classList.contains("vuuTableHeaderCell-selected"));
|
|
10
|
+
}
|
|
11
|
+
async assertSelected() {
|
|
12
|
+
await expect(this.page.locator(this.cssSelector)).toContainClass("vuuTableHeaderCell-selected");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export { PwTableHeaderCell };
|
package/src/index.js
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import { type Locator } from "@playwright/test";
|
|
1
|
+
import { type Locator, type Page } from "@playwright/test";
|
|
2
2
|
import type { VuuRange } from "@vuu-ui/vuu-protocol-types";
|
|
3
|
+
import { PlaywrightPageObject } from "./PlaywrightPageObject";
|
|
4
|
+
import { PwTableHeaderCell } from "./PwTableHeaderCell";
|
|
3
5
|
type AriaRole = "cell" | "textbox" | "combobox";
|
|
4
|
-
export declare class
|
|
6
|
+
export declare class PwTable extends PlaywrightPageObject {
|
|
5
7
|
#private;
|
|
6
|
-
|
|
8
|
+
private readonly cssSelector?;
|
|
9
|
+
protected readonly defaultCssSelector = ".vuuTable";
|
|
10
|
+
/**
|
|
11
|
+
* @param page the Playwright page
|
|
12
|
+
* @param cssSelector optional selector for the Table, overrides defaultCssSelector
|
|
13
|
+
*/
|
|
14
|
+
constructor(page: Page, cssSelector?: string | undefined);
|
|
7
15
|
get contentContainer(): Locator;
|
|
8
16
|
get scrollbarContainer(): Locator;
|
|
9
17
|
/**
|
|
10
18
|
* row Locator by aria-index
|
|
11
19
|
*/
|
|
12
20
|
row(row: number): Locator;
|
|
21
|
+
/**
|
|
22
|
+
* Locate cell by column name and 1-based aria row index, including headers.
|
|
23
|
+
*/
|
|
24
|
+
cell(colName: string, ariaRowIndex: number): Promise<Locator>;
|
|
25
|
+
editCell(columnName: string, ariaRowIndex: number, value: string, action?: "commit" | "cancel"): Promise<void>;
|
|
26
|
+
headerCell(columnName: string): PwTableHeaderCell;
|
|
13
27
|
/**
|
|
14
28
|
* Locate cell by cell contents
|
|
15
29
|
* @param text
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Page } from "@playwright/test";
|
|
2
|
+
import { PlaywrightPageObject } from "./PlaywrightPageObject";
|
|
3
|
+
export declare class PwTableHeaderCell extends PlaywrightPageObject {
|
|
4
|
+
private readonly cssSelector;
|
|
5
|
+
constructor(page: Page, cssSelector: string);
|
|
6
|
+
get isSelected(): Promise<boolean>;
|
|
7
|
+
assertSelected(): Promise<void>;
|
|
8
|
+
}
|
package/types/index.d.ts
CHANGED