d5-testing-library 1.9.0-alpha.8 → 1.9.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.
- package/README.md +1 -0
- package/dist/FormEdit-VFV53QIZ.mjs +7 -0
- package/dist/ListForm-KIHLT7EU.mjs +7 -0
- package/dist/TreeView-TFBZB2UK.mjs +8 -0
- package/dist/{chunk-UFDW7PIX.mjs → chunk-EFNMD3S7.mjs} +1 -1
- package/dist/{chunk-F2Z574YJ.mjs → chunk-GVYXH7L3.mjs} +1 -1
- package/dist/{chunk-7WV6OWRZ.mjs → chunk-RPSLW2WB.mjs} +377 -61
- package/dist/{chunk-ZI4JD3RU.mjs → chunk-TSE33S3X.mjs} +144 -34
- package/dist/cjs/d5-testing-library.cjs +3442 -188
- package/dist/cjs/d5-testing-library.d.ts +74 -3
- package/dist/d5-testing-library.d.mts +74 -3
- package/dist/d5-testing-library.legacy-esm.js +2841 -7
- package/dist/d5-testing-library.mjs +2841 -7
- package/package.json +12 -12
- package/dist/FormEdit-377LRKDA.mjs +0 -7
- package/dist/ListForm-M2NWQRYX.mjs +0 -7
- package/dist/TreeView-SI5MHDCO.mjs +0 -8
|
@@ -17,8 +17,9 @@ import {
|
|
|
17
17
|
safeWait,
|
|
18
18
|
staleElementAction,
|
|
19
19
|
waitElementIsClickable_default,
|
|
20
|
-
waitElementIsVisible_default
|
|
21
|
-
|
|
20
|
+
waitElementIsVisible_default,
|
|
21
|
+
withCustomTimeouts_default
|
|
22
|
+
} from "./chunk-RPSLW2WB.mjs";
|
|
22
23
|
|
|
23
24
|
// src/pageObjects/elements/Table/Table.ts
|
|
24
25
|
import { By as By6 } from "selenium-webdriver";
|
|
@@ -76,21 +77,30 @@ var Cell = class extends AbstractElementWithParent {
|
|
|
76
77
|
async getDateValue(cellEl, cellElClass) {
|
|
77
78
|
const value = (await cellEl.getText()).trim();
|
|
78
79
|
if (value === "") return null;
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
const getDate = (stringDate) => {
|
|
81
|
+
const isWithTime = cellElClass.includes("with-time");
|
|
82
|
+
try {
|
|
83
|
+
if (isWithTime) {
|
|
84
|
+
const [datePart, timePart] = stringDate.split(", ");
|
|
85
|
+
const [day, month, year] = datePart.split(".").map(Number);
|
|
86
|
+
const [hours, minutes] = timePart.split(":").map(Number);
|
|
87
|
+
return new Date(year, month - 1, day, hours, minutes, 0, 0);
|
|
88
|
+
} else {
|
|
89
|
+
const [day, month, year] = stringDate.split(".").map(Number);
|
|
90
|
+
return new Date(Date.UTC(year, month - 1, day));
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`Error parsing date value "${stringDate}":`, error);
|
|
94
|
+
return null;
|
|
89
95
|
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
};
|
|
97
|
+
const periodValue = value.split(" - ");
|
|
98
|
+
if (periodValue.length > 1) {
|
|
99
|
+
const dateFrom = getDate(periodValue[0]);
|
|
100
|
+
const dateTo = getDate(periodValue[1]);
|
|
101
|
+
return [dateFrom, dateTo];
|
|
93
102
|
}
|
|
103
|
+
return getDate(value);
|
|
94
104
|
}
|
|
95
105
|
async getElement() {
|
|
96
106
|
if (this._index == null) {
|
|
@@ -117,6 +127,7 @@ var Cell = class extends AbstractElementWithParent {
|
|
|
117
127
|
var DX_SELECTION_CLASS = "dx-selection";
|
|
118
128
|
var DX_ROW_EDIT_CLASS = "dx-edit-row";
|
|
119
129
|
var DX_DATA_ROW_CLASS = "dx-data-row";
|
|
130
|
+
var FIRST_CLICKED_CELL_SELECTOR = 'td[aria-colindex="1"]';
|
|
120
131
|
var Row = class extends AbstractElementWithParent {
|
|
121
132
|
index;
|
|
122
133
|
getColumnBy;
|
|
@@ -157,15 +168,16 @@ var Row = class extends AbstractElementWithParent {
|
|
|
157
168
|
await staleElementAction(async () => {
|
|
158
169
|
const rowEl = await this.getElement();
|
|
159
170
|
const isSelected = (await this.getClasses()).includes(DX_SELECTION_CLASS);
|
|
171
|
+
const clickedElement = await rowEl.findElement(By3.css(FIRST_CLICKED_CELL_SELECTOR));
|
|
160
172
|
if (isSelected && !preserve) {
|
|
161
173
|
await this.driver.actions({ async: true }).keyUp(Key.CONTROL).perform();
|
|
162
174
|
}
|
|
163
175
|
if (preserve && !isSelected) {
|
|
164
176
|
await this.driver.actions({ async: true }).keyDown(Key.CONTROL).perform();
|
|
165
|
-
await click(
|
|
177
|
+
await click(clickedElement, this.driver);
|
|
166
178
|
return;
|
|
167
179
|
}
|
|
168
|
-
await click(
|
|
180
|
+
await click(clickedElement, this.driver);
|
|
169
181
|
});
|
|
170
182
|
await safeWait(
|
|
171
183
|
async () => {
|
|
@@ -490,9 +502,18 @@ var Table = class extends AbstractElementWithParent {
|
|
|
490
502
|
await this.selectRowByIndex(index, true);
|
|
491
503
|
}
|
|
492
504
|
}
|
|
493
|
-
|
|
505
|
+
getRowElements(timeout) {
|
|
494
506
|
const rowsFullCssSelector = `${this.getFullCssSelector()} ${this.tableContentCssSelector} .dx-row.dx-data-row`;
|
|
495
|
-
|
|
507
|
+
return withCustomTimeouts_default({
|
|
508
|
+
driver: this.driver,
|
|
509
|
+
timeout,
|
|
510
|
+
callback: () => {
|
|
511
|
+
return this.driver.findElements(By6.css(rowsFullCssSelector));
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
async getRows() {
|
|
516
|
+
const rows = await this.getRowElements();
|
|
496
517
|
const result = [];
|
|
497
518
|
rows.forEach((_, index) => {
|
|
498
519
|
const newRow = new Row(
|
|
@@ -578,6 +599,72 @@ var Table = class extends AbstractElementWithParent {
|
|
|
578
599
|
await contextMenu(cellElement, this.driver);
|
|
579
600
|
});
|
|
580
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* Отримує значення комірки таблиці за ім'ям комірки та індексом рядка.
|
|
604
|
+
*
|
|
605
|
+
* @param {string} cellName - Ім'я комірки (поля) в таблиці
|
|
606
|
+
* @param {number} rowIndex - Індекс рядка (починається з 0)
|
|
607
|
+
* @throws {Error} Викидає помилку, якщо rowIndex не вказано
|
|
608
|
+
* @returns {Promise<string>} Повертає значення комірки
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* const table = new Table(driver);
|
|
612
|
+
*
|
|
613
|
+
* // Отримання значення комірки 'Name' в першому рядку (індекс 0)
|
|
614
|
+
* const cellValue = await table.getCellValueByCellName('Name', 0);
|
|
615
|
+
* expect(cellValue).toBe('Очікуване значення');
|
|
616
|
+
*/
|
|
617
|
+
getCellValueByCellName(cellName, rowIndex) {
|
|
618
|
+
if (rowIndex == null) {
|
|
619
|
+
throw new Error("Error: getCellValue(): rowIndex is required");
|
|
620
|
+
}
|
|
621
|
+
const row = this.getRowByIndex(rowIndex);
|
|
622
|
+
return row.getCell(cellName).getValue();
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Перевіряє, чи є таблиця порожньою (не містить жодного рядка з даними).
|
|
626
|
+
*
|
|
627
|
+
* @returns {Promise<boolean>} Повертає true, якщо таблиця порожня, false - якщо містить рядки
|
|
628
|
+
*
|
|
629
|
+
* @example
|
|
630
|
+
* const table = new Table(driver);
|
|
631
|
+
*
|
|
632
|
+
* // Перевірка чи порожня таблиця
|
|
633
|
+
* const empty = await table.isEmpty();
|
|
634
|
+
* expect(empty).toBe(true);
|
|
635
|
+
*/
|
|
636
|
+
async isEmpty() {
|
|
637
|
+
try {
|
|
638
|
+
await this.waitRowsCount(0);
|
|
639
|
+
return true;
|
|
640
|
+
} catch {
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Очікує, поки кількість рядків у таблиці не стане рівною заданому значенню.
|
|
646
|
+
* Використовується для синхронізації тестів з динамічним завантаженням даних.
|
|
647
|
+
*
|
|
648
|
+
* @param {number} count - Очікувана кількість рядків у таблиці
|
|
649
|
+
* @returns {Promise<void>} Повертає Promise, який виконується, коли кількість рядків відповідає очікуваній
|
|
650
|
+
* @throws {Error} Викидає помилку, якщо очікування перевищує тайм-аут
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* const table = new Table(driver);
|
|
654
|
+
*
|
|
655
|
+
* // Очікування, поки таблиця не стане порожньою
|
|
656
|
+
* await table.waitRowsCount(0);
|
|
657
|
+
*
|
|
658
|
+
* // Очікування, поки в таблиці не з'явиться 5 рядків
|
|
659
|
+
* await table.waitRowsCount(5);
|
|
660
|
+
* console.log('Таблиця містить 5 рядків');
|
|
661
|
+
*/
|
|
662
|
+
async waitRowsCount(count) {
|
|
663
|
+
await safeWait(async () => {
|
|
664
|
+
const rows = await this.getRowElements(1e3);
|
|
665
|
+
return rows.length === count;
|
|
666
|
+
}, this.driver, `Rows count not equal: ${count}`);
|
|
667
|
+
}
|
|
581
668
|
};
|
|
582
669
|
|
|
583
670
|
// src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
|
|
@@ -589,6 +676,7 @@ var TOOLBAR_BUTTON_CLASS = "toolbar-button";
|
|
|
589
676
|
var TOOLBAR_BUTTON_TEXT_CLASS = "dx-button-text";
|
|
590
677
|
var getToolbarButtonSelector = (name) => `#${TOOLBAR_BUTTON_CLASS}-${name}`;
|
|
591
678
|
var getToolbarButtonTextSelector = (name) => `${getToolbarButtonSelector(name)} .${TOOLBAR_BUTTON_TEXT_CLASS}`;
|
|
679
|
+
var getToolbarButtonTextByTestIdSelector = (testId) => `${byTestIdCssSelector(testId)} .${TOOLBAR_BUTTON_TEXT_CLASS}`;
|
|
592
680
|
var ToolbarButton = class extends AbstractButton {
|
|
593
681
|
name;
|
|
594
682
|
constructor(parentCssSelector, name, driver) {
|
|
@@ -620,7 +708,8 @@ var ToolbarGroupButton = class extends AbstractButton {
|
|
|
620
708
|
}
|
|
621
709
|
async getTitle() {
|
|
622
710
|
try {
|
|
623
|
-
const
|
|
711
|
+
const buttonTestId = await this.getDataTestId();
|
|
712
|
+
const buttonTextContainer = await this.driver.findElement(By8.css(getToolbarButtonTextByTestIdSelector(buttonTestId)));
|
|
624
713
|
return await buttonTextContainer.getText();
|
|
625
714
|
} catch (_) {
|
|
626
715
|
return null;
|
|
@@ -1010,6 +1099,12 @@ var FormFilterField = class extends AbstractEditor {
|
|
|
1010
1099
|
const filterOperation = await this.initOperation();
|
|
1011
1100
|
return await filterOperation.getIsBlank();
|
|
1012
1101
|
}
|
|
1102
|
+
async isReadonly() {
|
|
1103
|
+
return super.isReadonly();
|
|
1104
|
+
}
|
|
1105
|
+
async isDisabled() {
|
|
1106
|
+
return super.isDisabled();
|
|
1107
|
+
}
|
|
1013
1108
|
};
|
|
1014
1109
|
|
|
1015
1110
|
// src/pageObjects/elements/Filters/FilterPanel.ts
|
|
@@ -1111,6 +1206,12 @@ var PanelFilterField = class extends AbstractEditor {
|
|
|
1111
1206
|
const filterOperation = await this.initOperation();
|
|
1112
1207
|
return await filterOperation.getIsBlank();
|
|
1113
1208
|
}
|
|
1209
|
+
async isReadonly() {
|
|
1210
|
+
return super.isReadonly();
|
|
1211
|
+
}
|
|
1212
|
+
async isDisabled() {
|
|
1213
|
+
return super.isDisabled();
|
|
1214
|
+
}
|
|
1114
1215
|
};
|
|
1115
1216
|
|
|
1116
1217
|
// src/pageObjects/elements/Filters/FilterPanel.ts
|
|
@@ -1183,12 +1284,18 @@ var HeaderFilterField = class extends AbstractEditor {
|
|
|
1183
1284
|
async remove(itemText) {
|
|
1184
1285
|
return super.remove(itemText);
|
|
1185
1286
|
}
|
|
1287
|
+
async isReadonly() {
|
|
1288
|
+
return super.isReadonly();
|
|
1289
|
+
}
|
|
1290
|
+
async isDisabled() {
|
|
1291
|
+
return super.isDisabled();
|
|
1292
|
+
}
|
|
1186
1293
|
};
|
|
1187
1294
|
|
|
1188
1295
|
// src/pageObjects/elements/Filters/ColumnFilter.ts
|
|
1189
1296
|
var APPLY_SELECTOR = ".apply-button";
|
|
1190
1297
|
var CANCEL_SELECTOR = ".cancel-button";
|
|
1191
|
-
var HEADER_FILTER_ICON = ".
|
|
1298
|
+
var HEADER_FILTER_ICON = ".indicators-container .filter-icon";
|
|
1192
1299
|
var HEADER_FILTER_CONTAINER = ".header-filter";
|
|
1193
1300
|
var HEADER_FILTER_BUTTONS = ".header-filter-buttons";
|
|
1194
1301
|
var ColumnFilter = class extends AbstractElement {
|
|
@@ -1222,24 +1329,15 @@ var ColumnFilter = class extends AbstractElement {
|
|
|
1222
1329
|
const columnEl = await this._column.getElement();
|
|
1223
1330
|
const actions = this.driver.actions({ async: true });
|
|
1224
1331
|
await actions.move({ origin: columnEl }).perform();
|
|
1225
|
-
const
|
|
1226
|
-
let headerFilterIcon =
|
|
1332
|
+
const headerFilterIconBy = By11.css(HEADER_FILTER_ICON);
|
|
1333
|
+
let headerFilterIcon = await columnEl.findElement(headerFilterIconBy);
|
|
1227
1334
|
await safeWait(
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
for (let element of elements) {
|
|
1231
|
-
if (await element.isDisplayed()) {
|
|
1232
|
-
headerFilterIcon = element;
|
|
1233
|
-
result = true;
|
|
1234
|
-
break;
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
return result;
|
|
1335
|
+
() => {
|
|
1336
|
+
return headerFilterIcon.isDisplayed();
|
|
1238
1337
|
},
|
|
1239
1338
|
this.driver,
|
|
1240
1339
|
`HeaderFilter "${this._name}" is not visible`
|
|
1241
1340
|
);
|
|
1242
|
-
if (!headerFilterIcon) throw new Error(`HeaderFilter "${this._name}" is not visible`);
|
|
1243
1341
|
await click(headerFilterIcon, this.driver);
|
|
1244
1342
|
const filter = new HeaderFilterField("", this._formName, this._name, this.driver);
|
|
1245
1343
|
const filterEl = await filter.getElement();
|
|
@@ -1359,6 +1457,18 @@ var ColumnFilter = class extends AbstractElement {
|
|
|
1359
1457
|
const filterOperation = await this.initOperation();
|
|
1360
1458
|
return await filterOperation.getIsBlank();
|
|
1361
1459
|
}
|
|
1460
|
+
async isReadonly() {
|
|
1461
|
+
const filter = await this.initFilter();
|
|
1462
|
+
const result = await filter.isReadonly();
|
|
1463
|
+
await this.cancel();
|
|
1464
|
+
return result;
|
|
1465
|
+
}
|
|
1466
|
+
async isDisabled() {
|
|
1467
|
+
const filter = await this.initFilter();
|
|
1468
|
+
const result = await filter.isDisabled();
|
|
1469
|
+
await this.cancel();
|
|
1470
|
+
return result;
|
|
1471
|
+
}
|
|
1362
1472
|
};
|
|
1363
1473
|
|
|
1364
1474
|
// src/pageObjects/elements/Forms/ListForm.ts
|