@thinkwise/testwise 0.2.62 → 0.2.67
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/components/filter/ExcelStyleFilterPopup.ts +50 -10
- package/components/filter/ExcelStyleFilterPopupObjects.ts +29 -3
- package/components/grid/Grid.ts +33 -14
- package/components/grid/GridObjects.ts +0 -15
- package/controls/DateControl.ts +8 -9
- package/controls/DateControlObjects.ts +15 -0
- package/controls/FormComboBox.ts +12 -25
- package/controls/FormComboBoxObjects.ts +27 -0
- package/controls/GridColumnControl.ts +1 -1
- package/controls/GridColumnControlObjects.ts +1 -1
- package/controls/InputFieldControl.ts +11 -14
- package/controls/InputFieldControlObjects.ts +19 -0
- package/controls/LookupDropdown.ts +29 -30
- package/controls/LookupDropdownObjects.ts +19 -0
- package/dist/components/filter/ExcelStyleFilterPopup.d.ts +11 -1
- package/dist/components/filter/ExcelStyleFilterPopup.js +47 -5
- package/dist/components/filter/ExcelStyleFilterPopup.js.map +1 -1
- package/dist/components/filter/ExcelStyleFilterPopupObjects.d.ts +7 -0
- package/dist/components/filter/ExcelStyleFilterPopupObjects.js +14 -1
- package/dist/components/filter/ExcelStyleFilterPopupObjects.js.map +1 -1
- package/dist/components/grid/Grid.d.ts +3 -1
- package/dist/components/grid/Grid.js +18 -25
- package/dist/components/grid/Grid.js.map +1 -1
- package/dist/components/grid/GridObjects.d.ts +0 -4
- package/dist/components/grid/GridObjects.js +0 -6
- package/dist/components/grid/GridObjects.js.map +1 -1
- package/dist/controls/DateControl.d.ts +1 -2
- package/dist/controls/DateControl.js +7 -7
- package/dist/controls/DateControl.js.map +1 -1
- package/dist/controls/DateControlObjects.d.ts +8 -1
- package/dist/controls/DateControlObjects.js +8 -1
- package/dist/controls/DateControlObjects.js.map +1 -1
- package/dist/controls/FormComboBox.js +11 -16
- package/dist/controls/FormComboBox.js.map +1 -1
- package/dist/controls/FormComboBoxObjects.d.ts +12 -1
- package/dist/controls/FormComboBoxObjects.js +15 -1
- package/dist/controls/FormComboBoxObjects.js.map +1 -1
- package/dist/controls/GridColumnControl.js +1 -1
- package/dist/controls/GridColumnControl.js.map +1 -1
- package/dist/controls/GridColumnControlObjects.js +1 -1
- package/dist/controls/GridColumnControlObjects.js.map +1 -1
- package/dist/controls/InputFieldControl.d.ts +1 -3
- package/dist/controls/InputFieldControl.js +10 -11
- package/dist/controls/InputFieldControl.js.map +1 -1
- package/dist/controls/InputFieldControlObjects.d.ts +10 -1
- package/dist/controls/InputFieldControlObjects.js +10 -1
- package/dist/controls/InputFieldControlObjects.js.map +1 -1
- package/dist/controls/LookupDropdown.js +28 -25
- package/dist/controls/LookupDropdown.js.map +1 -1
- package/dist/controls/LookupDropdownObjects.d.ts +10 -0
- package/dist/controls/LookupDropdownObjects.js +11 -0
- package/dist/controls/LookupDropdownObjects.js.map +1 -0
- package/package.json +1 -1
|
@@ -2,27 +2,67 @@ import type { Locator, Page } from '@playwright/test';
|
|
|
2
2
|
import { ExcelStyleFilterPopupObjects } from './ExcelStyleFilterPopupObjects.js';
|
|
3
3
|
|
|
4
4
|
export class ExcelStyleFilterPopup {
|
|
5
|
-
private
|
|
5
|
+
private _objects: ExcelStyleFilterPopupObjects;
|
|
6
6
|
|
|
7
7
|
constructor(page: Page) {
|
|
8
|
-
this.
|
|
8
|
+
this._objects = new ExcelStyleFilterPopupObjects(page);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
async waitForOpen(): Promise<void> {
|
|
12
|
-
await this.
|
|
11
|
+
public async waitForOpen(): Promise<void> {
|
|
12
|
+
await (await this._objects.popup().all()).filter(async (element) => await element.isVisible());
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
intervalFilters(): Locator {
|
|
16
|
-
return this.
|
|
15
|
+
public intervalFilters(): Locator {
|
|
16
|
+
return this._objects.intervalFilters();
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
fromDateInput(fieldTestId: string): Locator {
|
|
20
|
-
return this.
|
|
19
|
+
public fromDateInput(fieldTestId: string): Locator {
|
|
20
|
+
return this._objects.fromDateInput(fieldTestId);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
public toDateInput(fieldTestId: string): Locator {
|
|
24
|
+
return this._objects.toDateInput(fieldTestId);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async waitForClose(): Promise<void> {
|
|
28
|
+
await (await this._objects.popup().all()).filter(async (element) => !(await element.isVisible()));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async clickSelectAll(fieldTestId: string): Promise<void> {
|
|
32
|
+
await this.waitForOpen();
|
|
33
|
+
await this._objects.checkboxSelectAllButton(fieldTestId).click();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public async clickCheckboxItem(fieldTestId: string, value: string): Promise<void> {
|
|
37
|
+
await this.waitForOpen();
|
|
38
|
+
|
|
39
|
+
await this._objects.checkboxItemButtons(fieldTestId).filter({ hasText: value }).click();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public checkboxItem(fieldTestId: string, value: string): Locator {
|
|
43
|
+
return this._objects.checkboxItemCheckboxes(fieldTestId).filter({ hasText: value });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public fromTimeInput(fieldTestId: string): Locator {
|
|
47
|
+
return this._objects.fromTimeInput(fieldTestId);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public toTimeInput(fieldTestId: string): Locator {
|
|
51
|
+
return this._objects.toTimeInput(fieldTestId);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public setFromTime = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
|
|
55
|
+
|
|
56
|
+
public setToTime = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
|
|
57
|
+
|
|
58
|
+
public setFromDate = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
|
|
59
|
+
|
|
60
|
+
public setToDate = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
|
|
61
|
+
|
|
62
|
+
private async fillAndEnter(fieldTestId: string, value: string): Promise<void> {
|
|
63
|
+
const input = this._objects.fromDateInput(fieldTestId);
|
|
64
|
+
|
|
24
65
|
await this.waitForOpen();
|
|
25
|
-
const input = this._excelStyleFilterPopupObjects.fromDateInput(fieldTestId);
|
|
26
66
|
await input.fill(value);
|
|
27
67
|
await input.press('Enter');
|
|
28
68
|
}
|
|
@@ -5,11 +5,10 @@ export class ExcelStyleFilterPopupObjects extends BaseComponentObjects {
|
|
|
5
5
|
private _page: Page;
|
|
6
6
|
|
|
7
7
|
constructor(page: Page) {
|
|
8
|
-
super(page
|
|
8
|
+
super(page);
|
|
9
9
|
this._page = page;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
public anchor = () => this._page.locator('[data-testid^="date-time-excel-filter__"]').first();
|
|
11
|
+
public popup = () => this._page.locator('[data-testid*="-excel-filter__"]');
|
|
13
12
|
|
|
14
13
|
public intervalFilters = () => this._page.getByTestId('excel-style-filter-popup__interval-filters');
|
|
15
14
|
|
|
@@ -17,4 +16,31 @@ export class ExcelStyleFilterPopupObjects extends BaseComponentObjects {
|
|
|
17
16
|
this._page
|
|
18
17
|
.getByTestId(`date-time-excel-filter__${fieldTestId}__from`)
|
|
19
18
|
.getByTestId(`form-field__${fieldTestId}__date__input`);
|
|
19
|
+
|
|
20
|
+
public toDateInput = (fieldTestId: string) =>
|
|
21
|
+
this._page
|
|
22
|
+
.getByTestId(`date-time-excel-filter__${fieldTestId}__to`)
|
|
23
|
+
.getByTestId(`form-field__${fieldTestId}__date__input`);
|
|
24
|
+
|
|
25
|
+
public checkboxList = (fieldTestId: string) =>
|
|
26
|
+
this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list"]`);
|
|
27
|
+
|
|
28
|
+
public checkboxSelectAllButton = (fieldTestId: string) =>
|
|
29
|
+
this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list-item-select-all-checkbox"]`);
|
|
30
|
+
|
|
31
|
+
public checkboxItemButtons = (fieldTestId: string) =>
|
|
32
|
+
this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list-item-button__"]`);
|
|
33
|
+
|
|
34
|
+
public checkboxItemCheckboxes = (fieldTestId: string) =>
|
|
35
|
+
this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list-item-checkbox__"]`);
|
|
36
|
+
|
|
37
|
+
public fromTimeInput = (fieldTestId: string) =>
|
|
38
|
+
this._page
|
|
39
|
+
.getByTestId(`date-time-excel-filter__${fieldTestId}__from`)
|
|
40
|
+
.getByTestId(`form-field__${fieldTestId}__time__input`);
|
|
41
|
+
|
|
42
|
+
public toTimeInput = (fieldTestId: string) =>
|
|
43
|
+
this._page
|
|
44
|
+
.getByTestId(`date-time-excel-filter__${fieldTestId}__to`)
|
|
45
|
+
.getByTestId(`form-field__${fieldTestId}__time__input`);
|
|
20
46
|
}
|
package/components/grid/Grid.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { Locator, Page } from '@playwright/test';
|
|
2
2
|
import { pollUntil } from '../../helpers/Poll.js';
|
|
3
3
|
import { escapeRegex } from '../../helpers/RegexHelper.js';
|
|
4
|
+
import { ExcelStyleFilterPopup } from '../index.js';
|
|
4
5
|
import { GridObjects } from './GridObjects.js';
|
|
5
6
|
|
|
6
7
|
export class Grid {
|
|
7
8
|
private _gridObjects: GridObjects;
|
|
8
9
|
private _page: Page;
|
|
10
|
+
private _excelStyleFilterPopup: ExcelStyleFilterPopup;
|
|
9
11
|
|
|
10
12
|
constructor(gridContext: Locator) {
|
|
11
13
|
this._gridObjects = new GridObjects(gridContext.page(), gridContext);
|
|
12
14
|
this._page = gridContext.page();
|
|
15
|
+
this._excelStyleFilterPopup = new ExcelStyleFilterPopup(this._page);
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
protected get page() {
|
|
@@ -57,8 +60,11 @@ export class Grid {
|
|
|
57
60
|
* @param columnName - The name of the column for which to open the filter popup.
|
|
58
61
|
* @returns A promise that resolves when the filter popup is opened.
|
|
59
62
|
*/
|
|
60
|
-
public openExcelStyleFilterPopup = async (
|
|
61
|
-
const filterIcon =
|
|
63
|
+
public openExcelStyleFilterPopup = async (columnNameOrHeader: string | Locator) => {
|
|
64
|
+
const filterIcon =
|
|
65
|
+
typeof columnNameOrHeader === 'string'
|
|
66
|
+
? this._gridObjects.menuIconByColumnHeaderName(columnNameOrHeader)
|
|
67
|
+
: columnNameOrHeader.getByTestId('grid__custom__filter__icon');
|
|
62
68
|
await filterIcon.click({ force: true });
|
|
63
69
|
};
|
|
64
70
|
|
|
@@ -127,34 +133,47 @@ export class Grid {
|
|
|
127
133
|
* await grid.filterByColumnValueExcelStyle('Status', 'Active');
|
|
128
134
|
* await grid.filterByColumnValueExcelStyle('Status', 'Pending', false);
|
|
129
135
|
*/
|
|
136
|
+
|
|
130
137
|
public async filterByColumnValueExcelStyle(
|
|
131
138
|
columnName: string,
|
|
132
139
|
valueToSelect: string,
|
|
140
|
+
deselectAll?: boolean
|
|
141
|
+
): Promise<void>;
|
|
142
|
+
public async filterByColumnValueExcelStyle(
|
|
143
|
+
columnHeader: Locator,
|
|
144
|
+
valueToSelect: string,
|
|
145
|
+
deselectAll?: boolean
|
|
146
|
+
): Promise<void>;
|
|
147
|
+
public async filterByColumnValueExcelStyle(
|
|
148
|
+
columnNameOrHeader: string | Locator,
|
|
149
|
+
valueToSelect: string,
|
|
133
150
|
deselectAll: boolean = true
|
|
134
151
|
): Promise<void> {
|
|
135
|
-
await this.openExcelStyleFilterPopup(
|
|
152
|
+
await this.openExcelStyleFilterPopup(columnNameOrHeader);
|
|
136
153
|
|
|
137
154
|
// Get column ID from header and normalize it (snake_case -> kebab-case)
|
|
138
|
-
const header =
|
|
155
|
+
const header =
|
|
156
|
+
typeof columnNameOrHeader === 'string'
|
|
157
|
+
? this._gridObjects.columnHeaderByName(columnNameOrHeader)
|
|
158
|
+
: columnNameOrHeader;
|
|
139
159
|
const rawColumnId = await header.getAttribute('col-id');
|
|
140
160
|
if (!rawColumnId) {
|
|
141
|
-
throw new Error(
|
|
161
|
+
throw new Error(
|
|
162
|
+
`Could not find col-id for column${typeof columnNameOrHeader === 'string' ? ` "${columnNameOrHeader}"` : ''}`
|
|
163
|
+
);
|
|
142
164
|
}
|
|
143
165
|
const columnId = rawColumnId.toLowerCase().replace(/_/g, '-');
|
|
144
166
|
|
|
145
|
-
const popup = this._gridObjects.excelStyleFilterPopup(columnId);
|
|
146
|
-
await
|
|
167
|
+
//const popup = this._gridObjects.excelStyleFilterPopup(columnId);
|
|
168
|
+
await this._excelStyleFilterPopup.waitForOpen();
|
|
147
169
|
|
|
148
170
|
if (deselectAll) {
|
|
149
|
-
await this.
|
|
171
|
+
await this._excelStyleFilterPopup.clickSelectAll(columnId);
|
|
150
172
|
}
|
|
151
173
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
await
|
|
155
|
-
|
|
156
|
-
await this._gridObjects.mainHeader.click(); // Click outside to close the popup
|
|
157
|
-
await popup.waitFor({ state: 'detached' });
|
|
174
|
+
await this._excelStyleFilterPopup.clickCheckboxItem(columnId, valueToSelect);
|
|
175
|
+
await this._gridObjects.mainHeader.click();
|
|
176
|
+
await this._excelStyleFilterPopup.waitForClose();
|
|
158
177
|
}
|
|
159
178
|
|
|
160
179
|
/**
|
|
@@ -2,11 +2,8 @@ import type { Locator, Page } from '@playwright/test';
|
|
|
2
2
|
import { BaseComponentObjects } from '../BaseComponentObjects.js';
|
|
3
3
|
|
|
4
4
|
export class GridObjects extends BaseComponentObjects {
|
|
5
|
-
private _page: Page;
|
|
6
|
-
|
|
7
5
|
constructor(page: Page, context: Locator | null = null) {
|
|
8
6
|
super(page, context);
|
|
9
|
-
this._page = page;
|
|
10
7
|
}
|
|
11
8
|
|
|
12
9
|
public columnHeaderByText = (text: string) => this.context.locator('[role="columnheader"]', { hasText: text });
|
|
@@ -33,18 +30,6 @@ export class GridObjects extends BaseComponentObjects {
|
|
|
33
30
|
|
|
34
31
|
public columnByRowLocator = (rowLocator: Locator) => rowLocator.locator('.ag-cell');
|
|
35
32
|
|
|
36
|
-
public excelStyleFilterPopup = (columnId: string) => this._page.getByTestId(`lookup-excel-filter__${columnId}__list`);
|
|
37
|
-
|
|
38
|
-
public excelStyleFilterSelectAllCheckbox = (columnId: string) =>
|
|
39
|
-
this._page.locator(
|
|
40
|
-
`[data-testid="lookup-excel-filter__${columnId}__list-item-select-all-checkbox"] input[type="checkbox"]`
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
public excelStyleFilterPopupOptionByText = (columnId: string, optionText: RegExp) =>
|
|
44
|
-
this._page
|
|
45
|
-
.locator(`[data-testid^="lookup-excel-filter__${columnId}__list-item-button"]`)
|
|
46
|
-
.filter({ hasText: optionText });
|
|
47
|
-
|
|
48
33
|
public gridCell = () => this.context.locator('[role="gridcell"]');
|
|
49
34
|
|
|
50
35
|
public noRowsOverlay = () => this.context.locator('.ag-overlay-no-rows-center');
|
package/controls/DateControl.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* biome-ignore-all lint/suspicious/noExplicitAny: reason42 */
|
|
3
3
|
import type { Locator } from '@playwright/test';
|
|
4
|
+
import { DateControlObjects } from './DateControlObjects.js';
|
|
4
5
|
|
|
5
6
|
export type IDateControl = Locator & IDateControlCore;
|
|
6
7
|
|
|
@@ -12,12 +13,10 @@ export type IDateControlCore = {
|
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
export class DateControl implements IDateControlCore {
|
|
15
|
-
private
|
|
16
|
-
private _inputLocator: Locator;
|
|
16
|
+
private _objects: DateControlObjects;
|
|
17
17
|
|
|
18
18
|
constructor(context: Locator, id: string) {
|
|
19
|
-
this.
|
|
20
|
-
this._inputLocator = this._dateFieldLocator.locator('input');
|
|
19
|
+
this._objects = new DateControlObjects(context, id);
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
/**
|
|
@@ -30,20 +29,20 @@ export class DateControl implements IDateControlCore {
|
|
|
30
29
|
public async fill(value: string): Promise<void> {
|
|
31
30
|
const numbersOnlyValue = value.replace(/\D/g, '');
|
|
32
31
|
|
|
33
|
-
await this.
|
|
34
|
-
await this.
|
|
32
|
+
await this._objects.fieldInput().focus();
|
|
33
|
+
await this._objects.fieldInput().pressSequentially(numbersOnlyValue);
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
public async clear(): Promise<void> {
|
|
38
|
-
await this.
|
|
37
|
+
await this._objects.fieldInput().fill('');
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
public async inputValue(): Promise<string> {
|
|
42
|
-
return await this.
|
|
41
|
+
return await this._objects.fieldInput().inputValue();
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
public inputElement(): Locator {
|
|
46
|
-
return this.
|
|
45
|
+
return this._objects.fieldInput();
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export class DateControlObjects {
|
|
4
|
+
private _context: Locator;
|
|
5
|
+
private _id: string;
|
|
6
|
+
|
|
7
|
+
constructor(context: Locator, id: string) {
|
|
8
|
+
this._context = context;
|
|
9
|
+
this._id = id;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public fieldInput = (): Locator => this._context;
|
|
13
|
+
|
|
14
|
+
public dateField = (): Locator => this._context.getByTestId(`form-field__${this._id}`);
|
|
15
|
+
}
|
package/controls/FormComboBox.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* biome-ignore-all lint/suspicious/noExplicitAny: Reason42 */
|
|
3
3
|
import type { Locator } from '@playwright/test';
|
|
4
|
+
import { FormComboBoxObjects } from './FormComboBoxObjects.js';
|
|
4
5
|
|
|
5
6
|
export type IFormComboBox = Locator & IFormComboBoxCore;
|
|
6
7
|
|
|
@@ -12,44 +13,30 @@ export type IFormComboBoxCore = {
|
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
class FormComboBox implements IFormComboBoxCore {
|
|
15
|
-
private
|
|
16
|
-
private _autoCompleteMenu: Locator;
|
|
17
|
-
private _id: string;
|
|
16
|
+
private _objects: FormComboBoxObjects;
|
|
18
17
|
|
|
19
18
|
constructor(context: Locator, id: string) {
|
|
20
|
-
this.
|
|
21
|
-
this._formFieldLocator = context.getByTestId(`form-field__${id}`);
|
|
22
|
-
this._autoCompleteMenu = context.getByTestId(`form-field__${id}__select__options-list`);
|
|
19
|
+
this._objects = new FormComboBoxObjects(context, id);
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
async selectOption(optionText: string): Promise<void> {
|
|
26
|
-
await this.
|
|
27
|
-
|
|
28
|
-
await this.
|
|
29
|
-
|
|
30
|
-
const optionTextLowercase = optionText.toLowerCase();
|
|
31
|
-
|
|
32
|
-
await this._autoCompleteMenu.getByTestId(`form-field__${this._id}__select__${optionTextLowercase}__text`).click();
|
|
23
|
+
await this._objects.fieldInput().click();
|
|
24
|
+
await this._objects.autoCompleteMenu().waitFor({ state: 'visible' });
|
|
25
|
+
await this._objects.option(optionText).click();
|
|
33
26
|
}
|
|
34
27
|
|
|
35
28
|
async getValidationMessage(): Promise<string> {
|
|
36
|
-
await this.
|
|
37
|
-
return await this.
|
|
29
|
+
await this._objects.validationMessage().waitFor({ state: 'visible' });
|
|
30
|
+
return await this._objects.validationMessage().innerText();
|
|
38
31
|
}
|
|
39
32
|
async clearByClick(): Promise<void> {
|
|
40
|
-
await this.
|
|
33
|
+
await this._objects.clearButton().click();
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
async lookupSelect(optionToSelect: string): Promise<void> {
|
|
44
|
-
await this.
|
|
45
|
-
|
|
46
|
-
await this.
|
|
47
|
-
|
|
48
|
-
const optionToSelectLowercase = optionToSelect.toLowerCase();
|
|
49
|
-
|
|
50
|
-
await this._autoCompleteMenu
|
|
51
|
-
.getByTestId(`form-field__${this._id}__select__${optionToSelectLowercase}__text`)
|
|
52
|
-
.click();
|
|
37
|
+
await this._objects.fieldInput().fill(optionToSelect);
|
|
38
|
+
await this._objects.autoCompleteMenu().waitFor({ state: 'visible' });
|
|
39
|
+
await this._objects.option(optionToSelect).click();
|
|
53
40
|
}
|
|
54
41
|
}
|
|
55
42
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export class FormComboBoxObjects {
|
|
4
|
+
private _context: Locator;
|
|
5
|
+
private _id: string;
|
|
6
|
+
|
|
7
|
+
constructor(context: Locator, id: string) {
|
|
8
|
+
this._context = context;
|
|
9
|
+
this._id = id;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public field = (): Locator => this._context.getByTestId(`form-field__${this._id}`);
|
|
13
|
+
|
|
14
|
+
public autoCompleteMenu = (): Locator =>
|
|
15
|
+
this._context.page().getByTestId(`form-field__${this._id}__select__options-list`);
|
|
16
|
+
|
|
17
|
+
public option = (optionText: string): Locator => {
|
|
18
|
+
const optionTextLowercase = optionText.toLowerCase();
|
|
19
|
+
return this.autoCompleteMenu().getByTestId(`form-field__${this._id}__select__${optionTextLowercase}__text`);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
public clearButton = (): Locator => this.field().locator('Button[aria-label="Clear"]');
|
|
23
|
+
|
|
24
|
+
public validationMessage = (): Locator => this.field().locator('.TooltipContainer p');
|
|
25
|
+
|
|
26
|
+
public fieldInput = (): Locator => this.field().locator('input');
|
|
27
|
+
}
|
|
@@ -44,7 +44,7 @@ class GridColumnControl implements IGridColumnControlCore {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
public async filterByColumnValueExcelStyle(value: string, deselectAll?: boolean): Promise<void> {
|
|
47
|
-
await this._grid.filterByColumnValueExcelStyle(this.
|
|
47
|
+
await this._grid.filterByColumnValueExcelStyle(this._objects.columnHeader(), value, deselectAll);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -11,7 +11,7 @@ export class GridColumnControlObjects extends BaseComponentObjects {
|
|
|
11
11
|
|
|
12
12
|
public column = () => this.context.locator(`[col-id="${this._id}"]`);
|
|
13
13
|
|
|
14
|
-
public columnHeader = () => this.
|
|
14
|
+
public columnHeader = () => this.context.locator(`[col-id="${this._id}"][role="columnheader"]`);
|
|
15
15
|
|
|
16
16
|
public cellByValue = (value: RegExp) =>
|
|
17
17
|
this.column().locator('[role="button"]', {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/** biome-ignore-all lint/suspicious/noExplicitAny: reason42 */
|
|
3
3
|
import type { Locator } from '@playwright/test';
|
|
4
|
+
import { InputFieldControlObjects } from './InputFieldControlObjects.js';
|
|
4
5
|
|
|
5
6
|
export type IInputFieldControl = Locator & ICoreInputFieldControl;
|
|
6
7
|
|
|
@@ -15,43 +16,39 @@ export type ICoreInputFieldControl = {
|
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export class InputFieldControl implements ICoreInputFieldControl {
|
|
18
|
-
private
|
|
19
|
-
private _inputLocator: Locator;
|
|
20
|
-
private _id: string;
|
|
19
|
+
private _objects: InputFieldControlObjects;
|
|
21
20
|
|
|
22
21
|
constructor(context: Locator, id: string) {
|
|
23
|
-
this.
|
|
24
|
-
this._formFieldLocator = context.getByTestId(`form-field__${id}`);
|
|
25
|
-
this._inputLocator = this._formFieldLocator.locator('input');
|
|
22
|
+
this._objects = new InputFieldControlObjects(context, id);
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
public async getValidationMessage(): Promise<string> {
|
|
29
|
-
await this.
|
|
30
|
-
return await this.
|
|
26
|
+
await this._objects.validationMessage().waitFor({ state: 'visible' });
|
|
27
|
+
return await this._objects.validationMessage().innerText();
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
public async fill(value: string): Promise<void> {
|
|
34
|
-
await this.
|
|
31
|
+
await this._objects.fieldInput().fill(value);
|
|
35
32
|
}
|
|
36
33
|
|
|
37
34
|
public async click(): Promise<void> {
|
|
38
|
-
await this.
|
|
35
|
+
await this._objects.fieldInput().click();
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
public async clear(): Promise<void> {
|
|
42
|
-
await this.
|
|
39
|
+
await this._objects.fieldInput().fill('');
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
public async inputValue(): Promise<string> {
|
|
46
|
-
return await this.
|
|
43
|
+
return await this._objects.fieldInput().inputValue();
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
public inputElement(): Locator {
|
|
50
|
-
return this.
|
|
47
|
+
return this._objects.fieldInput();
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
public async getLabelText(): Promise<string> {
|
|
54
|
-
let returnText = (await this.
|
|
51
|
+
let returnText = (await this._objects.fieldLabel().textContent()) || '';
|
|
55
52
|
|
|
56
53
|
returnText = returnText.replace(/\s+/g, ' ').trim();
|
|
57
54
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export class InputFieldControlObjects {
|
|
4
|
+
private _context: Locator;
|
|
5
|
+
private _id: string;
|
|
6
|
+
|
|
7
|
+
constructor(context: Locator, id: string) {
|
|
8
|
+
this._context = context;
|
|
9
|
+
this._id = id;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public formField = (): Locator => this._context.getByTestId(`form-field__${this._id}`);
|
|
13
|
+
|
|
14
|
+
public fieldInput = (): Locator => this.formField().locator('input');
|
|
15
|
+
|
|
16
|
+
public fieldLabel = (): Locator => this.formField().getByTestId(`form-field__${this._id}__label`);
|
|
17
|
+
|
|
18
|
+
public validationMessage = (): Locator => this.formField().locator('.TooltipContainer p');
|
|
19
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/** biome-ignore-all lint/suspicious/noExplicitAny: needed flexibility */
|
|
3
3
|
import type { Locator } from '@playwright/test';
|
|
4
4
|
import { escapeRegex } from '../helpers/RegexHelper.js';
|
|
5
|
+
import { LookupDropdownObjects } from './LookupDropdownObjects.js';
|
|
5
6
|
|
|
6
7
|
export type ILookupDropdown = Locator & ILookupDropdownCore;
|
|
7
8
|
|
|
@@ -16,18 +17,14 @@ export type ILookupDropdownCore = {
|
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
class LookupDropdown implements ILookupDropdownCore {
|
|
19
|
-
private
|
|
20
|
-
private _formFieldLocator: Locator;
|
|
21
|
-
private _inputLocator: Locator;
|
|
20
|
+
private _objects: LookupDropdownObjects;
|
|
22
21
|
|
|
23
22
|
constructor(context: Locator, id: string) {
|
|
24
|
-
this.
|
|
25
|
-
this._formFieldLocator = context.getByTestId(`form-field__${this._id}`);
|
|
26
|
-
this._inputLocator = this._formFieldLocator.locator('input');
|
|
23
|
+
this._objects = new LookupDropdownObjects(context, id);
|
|
27
24
|
}
|
|
28
25
|
|
|
29
26
|
public async getLabelText(): Promise<string> {
|
|
30
|
-
let returnText = (await this.
|
|
27
|
+
let returnText = (await this._objects.label().textContent()) || '';
|
|
31
28
|
|
|
32
29
|
returnText = returnText.replace(/\s+/g, ' ').trim();
|
|
33
30
|
|
|
@@ -35,69 +32,71 @@ class LookupDropdown implements ILookupDropdownCore {
|
|
|
35
32
|
}
|
|
36
33
|
|
|
37
34
|
public async lookupSelect(optionToSelect: string): Promise<void> {
|
|
38
|
-
await this.
|
|
35
|
+
await this._objects.input().fill(optionToSelect);
|
|
39
36
|
await this.select(optionToSelect);
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
public async inputValue(): Promise<string> {
|
|
43
|
-
return await this.
|
|
40
|
+
return await this._objects.input().inputValue();
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
public async clear(): Promise<void> {
|
|
47
|
-
await this.
|
|
44
|
+
await this._objects.input().fill('');
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
public async selectOption(optionText: string): Promise<void> {
|
|
51
|
-
await this.
|
|
48
|
+
await this._objects.input().click();
|
|
52
49
|
await this.select(optionText);
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
public async getValidationMessage(): Promise<string> {
|
|
56
|
-
await this.
|
|
57
|
-
return await this.
|
|
53
|
+
await this._objects.validationMessage().waitFor({ state: 'visible' });
|
|
54
|
+
return await this._objects.validationMessage().innerText();
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
public async fill(value: string): Promise<void> {
|
|
61
58
|
await Promise.all([
|
|
62
|
-
this.
|
|
59
|
+
this._objects
|
|
60
|
+
.input()
|
|
63
61
|
.page()
|
|
64
62
|
.waitForResponse((response) => response.url().includes('/list_') && response.request().method() === 'GET'),
|
|
65
|
-
this.
|
|
63
|
+
this._objects.input().click()
|
|
66
64
|
]);
|
|
67
65
|
|
|
68
66
|
await Promise.all([
|
|
69
|
-
this.
|
|
67
|
+
this._objects
|
|
68
|
+
.input()
|
|
70
69
|
.page()
|
|
71
70
|
.waitForResponse((response) => response.url().includes('/list_') && response.request().method() === 'GET'),
|
|
72
|
-
this.
|
|
71
|
+
this._objects.input().fill(value)
|
|
73
72
|
]);
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
private async select(optionToSelect: string) {
|
|
77
76
|
const optionsToSelectRegex = new RegExp(`^${escapeRegex(optionToSelect)}$`, 'i');
|
|
78
77
|
|
|
79
|
-
await this.
|
|
80
|
-
await this.
|
|
78
|
+
await this._objects.input().page().getByTestId('autocomplete__menu').getByText(optionsToSelectRegex).click();
|
|
79
|
+
await this._objects
|
|
80
|
+
.input()
|
|
81
81
|
.page()
|
|
82
|
-
.waitForFunction((el) => document.activeElement === el, await this.
|
|
82
|
+
.waitForFunction((el) => document.activeElement === el, await this._objects.input().elementHandle());
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
export function createLookupDropdown(context: Locator, id: string): ILookupDropdown {
|
|
87
87
|
const dropdown = new LookupDropdown(context, id);
|
|
88
|
+
const customProps = new Set(Object.getOwnPropertyNames(LookupDropdown.prototype).filter((p) => p !== 'constructor'));
|
|
88
89
|
|
|
89
|
-
return new Proxy(
|
|
90
|
+
return new Proxy(context, {
|
|
90
91
|
get(target, prop, receiver) {
|
|
91
|
-
if (prop
|
|
92
|
-
|
|
92
|
+
if (customProps.has(prop as string)) {
|
|
93
|
+
const value = (dropdown as any)[prop];
|
|
94
|
+
if (typeof value === 'function') {
|
|
95
|
+
return value.bind(dropdown);
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
93
98
|
}
|
|
94
|
-
|
|
95
|
-
const value = (dropdown as any)[prop];
|
|
96
|
-
|
|
97
|
-
if (typeof value === 'function') {
|
|
98
|
-
return value.bind(dropdown);
|
|
99
|
-
}
|
|
100
|
-
return value;
|
|
99
|
+
return Reflect.get(target, prop, receiver);
|
|
101
100
|
}
|
|
102
101
|
}) as unknown as ILookupDropdown;
|
|
103
102
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export class LookupDropdownObjects {
|
|
4
|
+
private _id: string;
|
|
5
|
+
private _context: Locator;
|
|
6
|
+
|
|
7
|
+
constructor(context: Locator, id: string) {
|
|
8
|
+
this._context = context;
|
|
9
|
+
this._id = id;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public formField = (): Locator => this._context.getByTestId(`form-field__${this._id}`);
|
|
13
|
+
|
|
14
|
+
public label = (): Locator => this.formField().getByTestId(`form-field__${this._id}__label`);
|
|
15
|
+
|
|
16
|
+
public input = (): Locator => this.formField().locator('input');
|
|
17
|
+
|
|
18
|
+
public validationMessage = (): Locator => this.formField().locator('.TooltipContainer p');
|
|
19
|
+
}
|