d5-testing-library 2.0.0-alpha.1 → 2.0.0-alpha.11
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 -1
- package/dist/{FormEdit-I63LWQEH.mjs → FormEdit-XTRS74QI.mjs} +1 -1
- package/dist/{ListForm-NEBCZD4X.mjs → ListForm-DSQ4LR7B.mjs} +1 -1
- package/dist/{TreeView-T3PIDSZQ.mjs → TreeView-HFUTD2JY.mjs} +1 -1
- package/dist/{chunk-75NROWLM.mjs → chunk-I5BQCTAW.mjs} +240 -43
- package/dist/cjs/d5-testing-library.cjs +257 -43
- package/dist/cjs/d5-testing-library.d.ts +33 -10
- package/dist/d5-testing-library.d.mts +33 -10
- package/dist/d5-testing-library.legacy-esm.js +1 -1
- package/dist/d5-testing-library.mjs +1 -1
- package/package.json +2 -16
|
@@ -76,11 +76,14 @@ var init_AbstractElement = __esm({
|
|
|
76
76
|
joinRelativeCssSelectors(selectors) {
|
|
77
77
|
return selectors.join(" ");
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
syncLocator() {
|
|
80
80
|
return this.page.locator(`css=${this.getFullCssSelector()}`);
|
|
81
81
|
}
|
|
82
|
+
getLocator() {
|
|
83
|
+
return this.syncLocator();
|
|
84
|
+
}
|
|
82
85
|
async getAttribute(attr) {
|
|
83
|
-
const locator = this.
|
|
86
|
+
const locator = this.syncLocator();
|
|
84
87
|
if (await locator.isVisible()) {
|
|
85
88
|
return locator.getAttribute(attr);
|
|
86
89
|
}
|
|
@@ -329,7 +332,7 @@ var init_AbstractEditor = __esm({
|
|
|
329
332
|
async setInputValue(value) {
|
|
330
333
|
const input = this.getInputLocator();
|
|
331
334
|
await input.click();
|
|
332
|
-
await input.
|
|
335
|
+
await input.pressSequentially(value + "");
|
|
333
336
|
await input.press("Enter");
|
|
334
337
|
}
|
|
335
338
|
async clear() {
|
|
@@ -403,6 +406,7 @@ var init_types = __esm({
|
|
|
403
406
|
ControlClass2["BooleanSelector"] = "buttons-group";
|
|
404
407
|
ControlClass2["ButtonGroup"] = "button-group-field";
|
|
405
408
|
ControlClass2["HeaderFilterDictionary"] = "header-filter-dictionary";
|
|
409
|
+
ControlClass2["FileUploader"] = "file-uploader";
|
|
406
410
|
return ControlClass2;
|
|
407
411
|
})(ControlClass || {});
|
|
408
412
|
}
|
|
@@ -453,7 +457,7 @@ var init_xpathHelper = __esm({
|
|
|
453
457
|
"use strict";
|
|
454
458
|
XPathHelper = class {
|
|
455
459
|
static getClassAndValueXpath(cssClass, value) {
|
|
456
|
-
return `div[contains(@class, '${cssClass}') and
|
|
460
|
+
return `div[contains(@class, '${cssClass}') and .='${value}']`;
|
|
457
461
|
}
|
|
458
462
|
};
|
|
459
463
|
}
|
|
@@ -470,7 +474,7 @@ function isEmptyValue(value) {
|
|
|
470
474
|
}
|
|
471
475
|
return false;
|
|
472
476
|
}
|
|
473
|
-
var types, isObject, isEmptyObject, type, isNull, isArray, isDefined, isString, isDate, isArrayOfDates, isUndefined;
|
|
477
|
+
var types, isObject, isEmptyObject, type, isNull, isArray, isDefined, isString, isNumeric, isDate, isArrayOfDates, isUndefined;
|
|
474
478
|
var init_typesUtil = __esm({
|
|
475
479
|
"src/utils/typesUtil.ts"() {
|
|
476
480
|
"use strict";
|
|
@@ -503,6 +507,9 @@ var init_typesUtil = __esm({
|
|
|
503
507
|
isString = function(object) {
|
|
504
508
|
return typeof object === "string";
|
|
505
509
|
};
|
|
510
|
+
isNumeric = function(object) {
|
|
511
|
+
return typeof object === "number" && isFinite(object) || !isNaN(object - parseFloat(object));
|
|
512
|
+
};
|
|
506
513
|
isDate = function(object) {
|
|
507
514
|
return type(object) === "date";
|
|
508
515
|
};
|
|
@@ -552,7 +559,7 @@ var init_SelectBoxEditor = __esm({
|
|
|
552
559
|
const inputEl = this.getInputLocator();
|
|
553
560
|
await inputEl.click();
|
|
554
561
|
try {
|
|
555
|
-
await inputEl.
|
|
562
|
+
await inputEl.pressSequentially(value + "");
|
|
556
563
|
await inputEl.press("Enter");
|
|
557
564
|
await dropDownOptionClick(value, this.page, false);
|
|
558
565
|
} catch {
|
|
@@ -655,12 +662,12 @@ var init_TagBox = __esm({
|
|
|
655
662
|
try {
|
|
656
663
|
await dropDownOptionClick(value, this.page, false);
|
|
657
664
|
} catch {
|
|
658
|
-
await input.
|
|
665
|
+
await input.pressSequentially(value + "");
|
|
659
666
|
await dropDownOptionClick(value, this.page, true);
|
|
660
667
|
}
|
|
661
668
|
await this.waitOptionSelection(value);
|
|
662
669
|
if (value !== lastElement) {
|
|
663
|
-
await input.
|
|
670
|
+
await input.pressSequentially("");
|
|
664
671
|
}
|
|
665
672
|
}
|
|
666
673
|
async confirmSelection() {
|
|
@@ -1057,7 +1064,6 @@ var init_SingleDateEditor = __esm({
|
|
|
1057
1064
|
init_BaseDateEditor();
|
|
1058
1065
|
init_utils();
|
|
1059
1066
|
init_ClearButtonStrategy();
|
|
1060
|
-
init_src();
|
|
1061
1067
|
SingleDateEditor = class extends BaseDateEditor {
|
|
1062
1068
|
constructor(parentCssSelector, elementCssSelector, page) {
|
|
1063
1069
|
super(parentCssSelector, elementCssSelector, page);
|
|
@@ -1080,11 +1086,7 @@ var init_SingleDateEditor = __esm({
|
|
|
1080
1086
|
}
|
|
1081
1087
|
async setValue(value) {
|
|
1082
1088
|
if (value instanceof Date) {
|
|
1083
|
-
await
|
|
1084
|
-
await this.setDateValue(value);
|
|
1085
|
-
const updatedValue = await this.getValue();
|
|
1086
|
-
return updatedValue.toDateString() === value.toDateString();
|
|
1087
|
-
}, this.page);
|
|
1089
|
+
await this.setDateValue(value);
|
|
1088
1090
|
} else {
|
|
1089
1091
|
throw new Error(`Value is incorrect. It should be a Date object`);
|
|
1090
1092
|
}
|
|
@@ -1180,7 +1182,7 @@ var init_DateEditor = __esm({
|
|
|
1180
1182
|
});
|
|
1181
1183
|
|
|
1182
1184
|
// src/pageObjects/elements/Editors/HeaderFilterDictionary.ts
|
|
1183
|
-
var TAGS_SELECTOR2, DX_TAG_CONTAINER2, DX_TEXTEDITOR_EMPTY3, CUSTOM_OPTION_LIST_SELECTOR, SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2, TAG_BOX_LIST_ITEM_SELECTOR,
|
|
1185
|
+
var TAGS_SELECTOR2, DX_TAG_CONTAINER2, DX_TEXTEDITOR_EMPTY3, CUSTOM_OPTION_LIST_SELECTOR, SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2, TAG_BOX_LIST_ITEM_SELECTOR, dropDownHeaderFilterDictionaryOptionClick, HeaderFilterDictionary;
|
|
1184
1186
|
var init_HeaderFilterDictionary = __esm({
|
|
1185
1187
|
"src/pageObjects/elements/Editors/HeaderFilterDictionary.ts"() {
|
|
1186
1188
|
"use strict";
|
|
@@ -1193,12 +1195,11 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1193
1195
|
CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
|
|
1194
1196
|
SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
|
|
1195
1197
|
TAG_BOX_LIST_ITEM_SELECTOR = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
|
|
1196
|
-
combinedOptionHeaderFilterDictValueXpath = (value) => `//div[contains(@class, '${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}') and contains(text(), '${value}')]`;
|
|
1197
1198
|
dropDownHeaderFilterDictionaryOptionClick = async (optionValue, page, dataTEST = "", delay = true) => {
|
|
1198
1199
|
const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
|
|
1199
1200
|
const calendarPopover = page.locator(calendarPopoverSelector);
|
|
1200
1201
|
const customOptionList = calendarPopover.locator(`.${CUSTOM_OPTION_LIST_SELECTOR}`);
|
|
1201
|
-
const optElement = customOptionList.locator(
|
|
1202
|
+
const optElement = customOptionList.locator(`.${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}`, { hasText: optionValue });
|
|
1202
1203
|
try {
|
|
1203
1204
|
await optElement.waitFor({ state: "visible", timeout: delay ? void 0 : 600 });
|
|
1204
1205
|
await optElement.click();
|
|
@@ -1222,28 +1223,28 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1222
1223
|
await this.selectOption(inputEl, value, lastElement);
|
|
1223
1224
|
}
|
|
1224
1225
|
}
|
|
1225
|
-
async waitOptionSelection() {
|
|
1226
|
-
|
|
1227
|
-
await selectedItem.waitFor({ state: "visible" });
|
|
1226
|
+
async waitOptionSelection(value) {
|
|
1227
|
+
await this.page.locator(`${TAG_BOX_LIST_ITEM_SELECTOR}`).filter({ hasText: value }).first().waitFor({ state: "visible" });
|
|
1228
1228
|
}
|
|
1229
1229
|
async selectOption(inputEl, value, lastElement) {
|
|
1230
1230
|
try {
|
|
1231
|
-
await inputEl.
|
|
1231
|
+
await inputEl.pressSequentially(value + "");
|
|
1232
1232
|
const dataTEST = await this.getDataTestId();
|
|
1233
1233
|
await dropDownHeaderFilterDictionaryOptionClick(value, this.page, dataTEST);
|
|
1234
1234
|
if (value !== lastElement) {
|
|
1235
|
-
await inputEl.
|
|
1235
|
+
await inputEl.pressSequentially("");
|
|
1236
1236
|
}
|
|
1237
1237
|
} catch (error) {
|
|
1238
1238
|
throw error;
|
|
1239
1239
|
}
|
|
1240
|
-
await this.waitOptionSelection();
|
|
1240
|
+
await this.waitOptionSelection(value);
|
|
1241
1241
|
}
|
|
1242
1242
|
async getHeaderFilterDictionaryInputValue() {
|
|
1243
1243
|
if (await this.isHeaderFilterDictionaryEmpty()) {
|
|
1244
1244
|
return [];
|
|
1245
1245
|
}
|
|
1246
1246
|
const tags = this.page.locator(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER2} ${TAGS_SELECTOR2}`);
|
|
1247
|
+
await tags.first().waitFor({ state: "visible" });
|
|
1247
1248
|
const count = await tags.count();
|
|
1248
1249
|
const values = [];
|
|
1249
1250
|
for (let i = 0; i < count; i++) {
|
|
@@ -1269,6 +1270,130 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1269
1270
|
}
|
|
1270
1271
|
});
|
|
1271
1272
|
|
|
1273
|
+
// src/pageObjects/elements/Editors/FileUploader.ts
|
|
1274
|
+
var FILE_NAME_SELECTOR, FILE_SIZE_ATTRIBUTE, FILE_DATE_ATTRIBUTE, FILE_TYPE_ATTRIBUTE, SELECT_FILE_BUTTON_SELECTOR, DOWNLOAD_FILE_BUTTON_SELECTOR, METADATA_SELECTOR, CLEAR_BUTTON_SELECTOR, FileUploader;
|
|
1275
|
+
var init_FileUploader = __esm({
|
|
1276
|
+
"src/pageObjects/elements/Editors/FileUploader.ts"() {
|
|
1277
|
+
"use strict";
|
|
1278
|
+
init_AbstractElementWithParent();
|
|
1279
|
+
init_typesUtil();
|
|
1280
|
+
FILE_NAME_SELECTOR = ".file-text";
|
|
1281
|
+
FILE_SIZE_ATTRIBUTE = "data-filesize";
|
|
1282
|
+
FILE_DATE_ATTRIBUTE = "data-moddate";
|
|
1283
|
+
FILE_TYPE_ATTRIBUTE = "data-filetype";
|
|
1284
|
+
SELECT_FILE_BUTTON_SELECTOR = ".select-file-button";
|
|
1285
|
+
DOWNLOAD_FILE_BUTTON_SELECTOR = ".download-file-button";
|
|
1286
|
+
METADATA_SELECTOR = ".file-text-file-info-wrapper";
|
|
1287
|
+
CLEAR_BUTTON_SELECTOR = ".clear-button";
|
|
1288
|
+
FileUploader = class extends AbstractElementWithParent {
|
|
1289
|
+
constructor(parentCssSelector, elementCssSelector, page) {
|
|
1290
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* Returns the metadata container element for the uploaded file.
|
|
1294
|
+
* Returns null when metadata is not rendered or not visible.
|
|
1295
|
+
*/
|
|
1296
|
+
async getMedataElement() {
|
|
1297
|
+
const root = this.getFullCssSelector();
|
|
1298
|
+
const locator = this.page.locator(`${root} ${METADATA_SELECTOR}`);
|
|
1299
|
+
if (!await locator.isVisible()) return null;
|
|
1300
|
+
return locator;
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Returns the name of the uploaded file, or null if not present.
|
|
1304
|
+
*/
|
|
1305
|
+
async getFileName() {
|
|
1306
|
+
const root = this.getFullCssSelector();
|
|
1307
|
+
const locator = this.page.locator(`${root} ${FILE_NAME_SELECTOR}`);
|
|
1308
|
+
if (!await locator.isVisible()) return null;
|
|
1309
|
+
const text = await locator.innerText();
|
|
1310
|
+
return text?.trim() || null;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Returns the size of the uploaded file, or null if not present.
|
|
1314
|
+
*/
|
|
1315
|
+
async getFileSize() {
|
|
1316
|
+
const element = await this.getMedataElement();
|
|
1317
|
+
if (!element) return null;
|
|
1318
|
+
const result = (await element.getAttribute(FILE_SIZE_ATTRIBUTE))?.trim();
|
|
1319
|
+
return isNaN(+result) ? null : +result;
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Returns the upload/modification date of the file, or null if not present.
|
|
1323
|
+
*/
|
|
1324
|
+
async getFileDate() {
|
|
1325
|
+
const element = await this.getMedataElement();
|
|
1326
|
+
if (!element) return null;
|
|
1327
|
+
const fileModDate = (await element.getAttribute(FILE_DATE_ATTRIBUTE))?.trim();
|
|
1328
|
+
if (isNumeric(+fileModDate)) {
|
|
1329
|
+
const dateString = (/* @__PURE__ */ new Date(+fileModDate)).toISOString();
|
|
1330
|
+
return new Date(dateString.split("T")[0]);
|
|
1331
|
+
}
|
|
1332
|
+
return fileModDate ? new Date(fileModDate.split("T")[0]) : null;
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Returns the MIME/content type of the uploaded file from metadata.
|
|
1336
|
+
* Returns null when the type attribute is absent or empty.
|
|
1337
|
+
*/
|
|
1338
|
+
async getFileType() {
|
|
1339
|
+
const element = await this.getMedataElement();
|
|
1340
|
+
if (!element) return null;
|
|
1341
|
+
const fileType = (await element.getAttribute(FILE_TYPE_ATTRIBUTE))?.trim();
|
|
1342
|
+
return fileType || null;
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Returns current file information: name, size and upload/modification date.
|
|
1346
|
+
* Returns null if no file is uploaded.
|
|
1347
|
+
*/
|
|
1348
|
+
async getValue() {
|
|
1349
|
+
const name = await this.getFileName();
|
|
1350
|
+
const size = await this.getFileSize();
|
|
1351
|
+
const date = await this.getFileDate();
|
|
1352
|
+
const type2 = await this.getFileType();
|
|
1353
|
+
if (!name && !size && !date && !type2) return null;
|
|
1354
|
+
return { FileName: name, FileSize: size, FileType: type2, ModDate: date };
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Uploads a file by clicking the select-file-button and providing the file path.
|
|
1358
|
+
* @param filePath - Absolute or relative path to the file on disk.
|
|
1359
|
+
*/
|
|
1360
|
+
async setValue(filePath) {
|
|
1361
|
+
const root = this.getFullCssSelector();
|
|
1362
|
+
const fileChooserPromise = this.page.waitForEvent("filechooser");
|
|
1363
|
+
await this.page.locator(`${root} ${SELECT_FILE_BUTTON_SELECTOR}`).click();
|
|
1364
|
+
const fileChooser = await fileChooserPromise;
|
|
1365
|
+
await fileChooser.setFiles(filePath);
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Downloads the currently uploaded file by clicking the download-file-button.
|
|
1369
|
+
* Returns the suggested file name of the downloaded file.
|
|
1370
|
+
*/
|
|
1371
|
+
async download() {
|
|
1372
|
+
const root = this.getFullCssSelector();
|
|
1373
|
+
const buttonLocator = this.page.locator(
|
|
1374
|
+
`${root} ${DOWNLOAD_FILE_BUTTON_SELECTOR}`
|
|
1375
|
+
);
|
|
1376
|
+
if (await buttonLocator.isHidden()) return "";
|
|
1377
|
+
const downloadPromise = this.page.waitForEvent("download");
|
|
1378
|
+
await buttonLocator.click();
|
|
1379
|
+
const download = await downloadPromise;
|
|
1380
|
+
return download.suggestedFilename();
|
|
1381
|
+
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Removes the currently uploaded file by clicking the delete-file-button.
|
|
1384
|
+
* Does nothing if no file is uploaded.
|
|
1385
|
+
*/
|
|
1386
|
+
async clear() {
|
|
1387
|
+
if (await this.getValue() === null) return;
|
|
1388
|
+
const root = this.getFullCssSelector();
|
|
1389
|
+
const deleteButton = this.page.locator(`${root} ${CLEAR_BUTTON_SELECTOR}`);
|
|
1390
|
+
if (await deleteButton.isHidden()) return;
|
|
1391
|
+
await deleteButton.click();
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
|
|
1272
1397
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
1273
1398
|
var editorFactory;
|
|
1274
1399
|
var init_editorFactory = __esm({
|
|
@@ -1286,6 +1411,7 @@ var init_editorFactory = __esm({
|
|
|
1286
1411
|
init_ButtonGroup();
|
|
1287
1412
|
init_DateEditor();
|
|
1288
1413
|
init_HeaderFilterDictionary();
|
|
1414
|
+
init_FileUploader();
|
|
1289
1415
|
editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
1290
1416
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, page);
|
|
1291
1417
|
const classString = await elementInstance.getClasses();
|
|
@@ -1306,6 +1432,8 @@ var init_editorFactory = __esm({
|
|
|
1306
1432
|
return new ButtonGroup(parentCssSelector, elementCssSelector, page);
|
|
1307
1433
|
if (classString.includes("header-filter-dictionary" /* HeaderFilterDictionary */))
|
|
1308
1434
|
return new HeaderFilterDictionary(parentCssSelector, elementCssSelector, page);
|
|
1435
|
+
if (classString.includes("file-uploader" /* FileUploader */))
|
|
1436
|
+
return new FileUploader(parentCssSelector, elementCssSelector, page);
|
|
1309
1437
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
1310
1438
|
};
|
|
1311
1439
|
}
|
|
@@ -1385,6 +1513,15 @@ function createSubSystemTestId(itemName) {
|
|
|
1385
1513
|
function createEditorButtonTestId(itemName) {
|
|
1386
1514
|
return `${"editor-button" /* EDITOR_BUTTON */}-${itemName}`;
|
|
1387
1515
|
}
|
|
1516
|
+
function createLabelFieldTestId(formName, itemName) {
|
|
1517
|
+
return `${"label" /* LABEL */}-${createFieldTestId(formName, itemName)}`;
|
|
1518
|
+
}
|
|
1519
|
+
function createLabelDocFilterTestId(formName, itemName) {
|
|
1520
|
+
return `${"label" /* LABEL */}-${createDocFilterTestId(formName, itemName)}`;
|
|
1521
|
+
}
|
|
1522
|
+
function createLabelLayoutFilterTestId(formName, itemName) {
|
|
1523
|
+
return `${"label" /* LABEL */}-${createLayoutFilterTestId(formName, itemName)}`;
|
|
1524
|
+
}
|
|
1388
1525
|
var init_createDataTestId = __esm({
|
|
1389
1526
|
"src/utils/createDataTestId.ts"() {
|
|
1390
1527
|
"use strict";
|
|
@@ -1863,7 +2000,7 @@ var init_AbstractForm = __esm({
|
|
|
1863
2000
|
async exists() {
|
|
1864
2001
|
try {
|
|
1865
2002
|
const container = this.page.locator(this.containerCssSelector);
|
|
1866
|
-
await waitElementIsVisible_default({ locator: container });
|
|
2003
|
+
await waitElementIsVisible_default({ locator: container, timeout: 3e3 });
|
|
1867
2004
|
return true;
|
|
1868
2005
|
} catch (error) {
|
|
1869
2006
|
return false;
|
|
@@ -1996,14 +2133,14 @@ var init_Cell = __esm({
|
|
|
1996
2133
|
}
|
|
1997
2134
|
return getDate(value);
|
|
1998
2135
|
}
|
|
1999
|
-
async
|
|
2136
|
+
async getLocator() {
|
|
2000
2137
|
if (this._index == null) {
|
|
2001
2138
|
this.index = await this.getCellIndex();
|
|
2002
2139
|
}
|
|
2003
|
-
return this.
|
|
2140
|
+
return this.syncLocator();
|
|
2004
2141
|
}
|
|
2005
2142
|
async getValue() {
|
|
2006
|
-
const cellEl = await this.
|
|
2143
|
+
const cellEl = await this.getLocator();
|
|
2007
2144
|
const cellElClass = await cellEl.getAttribute("class") ?? "";
|
|
2008
2145
|
if (cellElClass.includes("boolean-column" /* Boolean */)) return this.getBooleanValue(cellEl);
|
|
2009
2146
|
if (cellElClass.includes("tags-column" /* Tags */)) return this.getTagsValue(cellEl);
|
|
@@ -2151,9 +2288,9 @@ var init_Column = __esm({
|
|
|
2151
2288
|
constructor({ parentCssSelector, headerCssSelector, name, caption, index, page }) {
|
|
2152
2289
|
super(parentCssSelector, "", page);
|
|
2153
2290
|
this._name = name;
|
|
2291
|
+
this.headerCssSelector = headerCssSelector;
|
|
2154
2292
|
this.index = index;
|
|
2155
2293
|
this._caption = caption;
|
|
2156
|
-
this.headerCssSelector = headerCssSelector;
|
|
2157
2294
|
}
|
|
2158
2295
|
set index(index) {
|
|
2159
2296
|
this._index = index;
|
|
@@ -2162,9 +2299,9 @@ var init_Column = __esm({
|
|
|
2162
2299
|
get index() {
|
|
2163
2300
|
return this._index;
|
|
2164
2301
|
}
|
|
2165
|
-
async
|
|
2302
|
+
async getLocator() {
|
|
2166
2303
|
await this.getIndex();
|
|
2167
|
-
return this.
|
|
2304
|
+
return this.syncLocator();
|
|
2168
2305
|
}
|
|
2169
2306
|
async getColumnHeaderIndexBy(cssSelector) {
|
|
2170
2307
|
const column = this.page.locator(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`);
|
|
@@ -2177,7 +2314,7 @@ var init_Column = __esm({
|
|
|
2177
2314
|
return this.getColumnHeaderIndexBy(getColumnByNameCssSelector(this._name));
|
|
2178
2315
|
}
|
|
2179
2316
|
async caption() {
|
|
2180
|
-
const el = await this.
|
|
2317
|
+
const el = await this.getLocator();
|
|
2181
2318
|
const text = await el.innerText();
|
|
2182
2319
|
return text?.trim() ?? null;
|
|
2183
2320
|
}
|
|
@@ -2230,6 +2367,25 @@ var init_EditorButton = __esm({
|
|
|
2230
2367
|
}
|
|
2231
2368
|
});
|
|
2232
2369
|
|
|
2370
|
+
// src/pageObjects/elements/EditorTitle.ts
|
|
2371
|
+
var CAPTION_TEXT_CLASS, EditorTitle;
|
|
2372
|
+
var init_EditorTitle = __esm({
|
|
2373
|
+
"src/pageObjects/elements/EditorTitle.ts"() {
|
|
2374
|
+
"use strict";
|
|
2375
|
+
init_AbstractElementWithParent();
|
|
2376
|
+
CAPTION_TEXT_CLASS = " .caption-text";
|
|
2377
|
+
EditorTitle = class extends AbstractElementWithParent {
|
|
2378
|
+
constructor({ parentCssSelector, elementCssSelector, page }) {
|
|
2379
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
2380
|
+
}
|
|
2381
|
+
async getTitle() {
|
|
2382
|
+
const captionElement = this.getLocator().locator(CAPTION_TEXT_CLASS);
|
|
2383
|
+
return captionElement.innerText();
|
|
2384
|
+
}
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
});
|
|
2388
|
+
|
|
2233
2389
|
// src/pageObjects/elements/AbstractEditor.ts
|
|
2234
2390
|
var AbstractEditor;
|
|
2235
2391
|
var init_AbstractEditor2 = __esm({
|
|
@@ -2238,10 +2394,13 @@ var init_AbstractEditor2 = __esm({
|
|
|
2238
2394
|
init_AbstractElementWithParent();
|
|
2239
2395
|
init_Editors();
|
|
2240
2396
|
init_EditorButton();
|
|
2397
|
+
init_EditorTitle();
|
|
2241
2398
|
AbstractEditor = class extends AbstractElementWithParent {
|
|
2242
2399
|
editor;
|
|
2243
|
-
|
|
2400
|
+
_titleCssSelector;
|
|
2401
|
+
constructor({ parentCssSelector, elementCssSelector, titleCssSelector, page }) {
|
|
2244
2402
|
super(parentCssSelector, elementCssSelector, page);
|
|
2403
|
+
this._titleCssSelector = titleCssSelector;
|
|
2245
2404
|
}
|
|
2246
2405
|
async initEditor() {
|
|
2247
2406
|
if (!this.editor) {
|
|
@@ -2337,6 +2496,32 @@ var init_AbstractEditor2 = __esm({
|
|
|
2337
2496
|
button(name) {
|
|
2338
2497
|
return new EditorButton(this.getFullCssSelector(), name, this.page);
|
|
2339
2498
|
}
|
|
2499
|
+
/**
|
|
2500
|
+
* Повертає загловок едітора
|
|
2501
|
+
* @example
|
|
2502
|
+
* expect(await formEdit.field('NumberFld').title()).toBe('Title1');
|
|
2503
|
+
* expect(await formEdit.field('TextFld').title()).toBe('Title2`);
|
|
2504
|
+
*/
|
|
2505
|
+
async title() {
|
|
2506
|
+
return new EditorTitle({
|
|
2507
|
+
elementCssSelector: this._titleCssSelector,
|
|
2508
|
+
parentCssSelector: this.parentCssSelector,
|
|
2509
|
+
page: this.page
|
|
2510
|
+
}).getTitle();
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* Вивантажує файл і повертає назву файла. Доступний тільки для поля FileUploader.
|
|
2514
|
+
* @example
|
|
2515
|
+
* const fileName = await formEdit.field('FileField').downloadFile();
|
|
2516
|
+
* expect(filename()).toBe('file.pdf');
|
|
2517
|
+
*/
|
|
2518
|
+
async download() {
|
|
2519
|
+
await this.initEditor();
|
|
2520
|
+
if (!this.editor.download) {
|
|
2521
|
+
throw new Error("download is only available for the FileUploader field type.");
|
|
2522
|
+
}
|
|
2523
|
+
return this.editor.download();
|
|
2524
|
+
}
|
|
2340
2525
|
};
|
|
2341
2526
|
}
|
|
2342
2527
|
});
|
|
@@ -2351,7 +2536,12 @@ var init_FormField = __esm({
|
|
|
2351
2536
|
init_AbstractEditor2();
|
|
2352
2537
|
FormField = class extends AbstractEditor {
|
|
2353
2538
|
constructor(parentCssSelector, formName, name, page) {
|
|
2354
|
-
super(
|
|
2539
|
+
super({
|
|
2540
|
+
parentCssSelector,
|
|
2541
|
+
elementCssSelector: byTestIdCssSelector(createFieldTestId(formName, name)),
|
|
2542
|
+
titleCssSelector: byTestIdCssSelector(createLabelFieldTestId(formName, name)),
|
|
2543
|
+
page
|
|
2544
|
+
});
|
|
2355
2545
|
}
|
|
2356
2546
|
};
|
|
2357
2547
|
}
|
|
@@ -2525,6 +2715,7 @@ var init_Table = __esm({
|
|
|
2525
2715
|
this.getRowByIndex(index);
|
|
2526
2716
|
return new Column({
|
|
2527
2717
|
parentCssSelector: this.getFullCssSelector(),
|
|
2718
|
+
headerCssSelector: this.headerCssSelector,
|
|
2528
2719
|
page: this.page,
|
|
2529
2720
|
index
|
|
2530
2721
|
});
|
|
@@ -2637,7 +2828,7 @@ var init_Table = __esm({
|
|
|
2637
2828
|
[row] = await this.getSelectedRows();
|
|
2638
2829
|
}
|
|
2639
2830
|
if (!row) throw new Error("No row available row for context menu");
|
|
2640
|
-
const cellElement = await row.getCell(fieldName).
|
|
2831
|
+
const cellElement = await row.getCell(fieldName).getLocator();
|
|
2641
2832
|
await cellElement.click({ button: "right" });
|
|
2642
2833
|
});
|
|
2643
2834
|
}
|
|
@@ -2696,10 +2887,14 @@ var init_Table = __esm({
|
|
|
2696
2887
|
* console.log('Таблиця містить 5 рядків');
|
|
2697
2888
|
*/
|
|
2698
2889
|
async waitRowsCount(count) {
|
|
2699
|
-
await wait(
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2890
|
+
await wait(
|
|
2891
|
+
async () => {
|
|
2892
|
+
const rowsCount = await this.getRowElements().count();
|
|
2893
|
+
return rowsCount === count;
|
|
2894
|
+
},
|
|
2895
|
+
this.page,
|
|
2896
|
+
`Rows count not equal: ${count}`
|
|
2897
|
+
);
|
|
2703
2898
|
}
|
|
2704
2899
|
};
|
|
2705
2900
|
}
|
|
@@ -2951,6 +3146,7 @@ var init_ToolbarItem = __esm({
|
|
|
2951
3146
|
init_locators();
|
|
2952
3147
|
init_ToolbarMenu();
|
|
2953
3148
|
init_waitElementIsVisible();
|
|
3149
|
+
init_wait();
|
|
2954
3150
|
GROUP_BUTTON_CLASS = "toolbar-group-button";
|
|
2955
3151
|
toolbarItemSelector = (form, name) => byTestIdCssSelector(`ftb-${form}-${name}`);
|
|
2956
3152
|
ToolbarItem = class extends AbstractElementWithParent {
|
|
@@ -2974,7 +3170,10 @@ var init_ToolbarItem = __esm({
|
|
|
2974
3170
|
async click() {
|
|
2975
3171
|
try {
|
|
2976
3172
|
await this.init();
|
|
2977
|
-
await
|
|
3173
|
+
await wait(async () => {
|
|
3174
|
+
const element = this._button.getLocator();
|
|
3175
|
+
return await element.isEnabled() && await element.isVisible();
|
|
3176
|
+
}, this.page);
|
|
2978
3177
|
await this._button.click();
|
|
2979
3178
|
} catch (error) {
|
|
2980
3179
|
throw new Error(`Cannot click on toolbar item: ${this._itemName}`);
|
|
@@ -3149,7 +3348,12 @@ var init_FormFilterField = __esm({
|
|
|
3149
3348
|
formName;
|
|
3150
3349
|
name;
|
|
3151
3350
|
constructor(parentCssSelector, formName, name, page) {
|
|
3152
|
-
super(
|
|
3351
|
+
super({
|
|
3352
|
+
parentCssSelector,
|
|
3353
|
+
elementCssSelector: byTestIdCssSelector(createLayoutFilterTestId(formName, name)),
|
|
3354
|
+
titleCssSelector: byTestIdCssSelector(createLabelLayoutFilterTestId(formName, name)),
|
|
3355
|
+
page
|
|
3356
|
+
});
|
|
3153
3357
|
this.formName = formName;
|
|
3154
3358
|
this.name = name;
|
|
3155
3359
|
}
|
|
@@ -3263,7 +3467,12 @@ var init_PanelFilterField = __esm({
|
|
|
3263
3467
|
formName;
|
|
3264
3468
|
name;
|
|
3265
3469
|
constructor(parentCssSelector, formName, name, page) {
|
|
3266
|
-
super(
|
|
3470
|
+
super({
|
|
3471
|
+
parentCssSelector,
|
|
3472
|
+
elementCssSelector: byTestIdCssSelector(createDocFilterTestId(formName, name)),
|
|
3473
|
+
titleCssSelector: byTestIdCssSelector(createLabelDocFilterTestId(formName, name)),
|
|
3474
|
+
page
|
|
3475
|
+
});
|
|
3267
3476
|
this.formName = formName;
|
|
3268
3477
|
this.name = name;
|
|
3269
3478
|
}
|
|
@@ -3431,7 +3640,12 @@ var init_HeaderFilterField = __esm({
|
|
|
3431
3640
|
init_AbstractEditor2();
|
|
3432
3641
|
HeaderFilterField = class extends AbstractEditor {
|
|
3433
3642
|
constructor(parentCssSelector, formName, name, page) {
|
|
3434
|
-
super(
|
|
3643
|
+
super({
|
|
3644
|
+
parentCssSelector,
|
|
3645
|
+
elementCssSelector: byTestIdCssSelector(createHeaderFilterTestId(formName, name)),
|
|
3646
|
+
titleCssSelector: "",
|
|
3647
|
+
page
|
|
3648
|
+
});
|
|
3435
3649
|
}
|
|
3436
3650
|
async getValue() {
|
|
3437
3651
|
return super.getValue();
|
|
@@ -3493,7 +3707,7 @@ var init_ColumnFilter = __esm({
|
|
|
3493
3707
|
await this.getCancelButton().click();
|
|
3494
3708
|
}
|
|
3495
3709
|
async initFilter() {
|
|
3496
|
-
const columnEl = await this._column.
|
|
3710
|
+
const columnEl = await this._column.getLocator();
|
|
3497
3711
|
await columnEl.hover();
|
|
3498
3712
|
const headerFilterIcon = columnEl.locator(HEADER_FILTER_ICON);
|
|
3499
3713
|
await headerFilterIcon.waitFor({ state: "visible" });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Locator, Page } from '@playwright/test';
|
|
2
2
|
import * as playwright_core from 'playwright-core';
|
|
3
3
|
|
|
4
4
|
type IConfig = {
|
|
@@ -9,13 +9,14 @@ type IConfig = {
|
|
|
9
9
|
};
|
|
10
10
|
declare function config(cfg?: IConfig): IConfig;
|
|
11
11
|
|
|
12
|
-
declare abstract class AbstractElement {
|
|
12
|
+
declare abstract class AbstractElement<TLocator extends Locator | Promise<Locator> = Locator> {
|
|
13
13
|
page: Page;
|
|
14
14
|
protected elementCssSelector: string;
|
|
15
15
|
protected constructor(page: Page, elementCssSelector?: string);
|
|
16
16
|
protected getFullCssSelector(): string;
|
|
17
17
|
protected joinRelativeCssSelectors(selectors: string[]): string;
|
|
18
|
-
|
|
18
|
+
protected syncLocator(): Locator;
|
|
19
|
+
getLocator(): TLocator;
|
|
19
20
|
getAttribute(attr: string): Promise<string>;
|
|
20
21
|
getClasses(): Promise<string>;
|
|
21
22
|
getDataTestId(): Promise<string>;
|
|
@@ -95,6 +96,7 @@ interface Editor {
|
|
|
95
96
|
clear?(): Promise<void>;
|
|
96
97
|
isReadonly?(): Promise<boolean>;
|
|
97
98
|
isDisabled?(): Promise<boolean>;
|
|
99
|
+
download?(): Promise<string>;
|
|
98
100
|
}
|
|
99
101
|
declare enum ControlClass {
|
|
100
102
|
Text = "text-control",
|
|
@@ -108,14 +110,15 @@ declare enum ControlClass {
|
|
|
108
110
|
SingleDateRange = "single-date-range-control",
|
|
109
111
|
BooleanSelector = "buttons-group",
|
|
110
112
|
ButtonGroup = "button-group-field",
|
|
111
|
-
HeaderFilterDictionary = "header-filter-dictionary"
|
|
113
|
+
HeaderFilterDictionary = "header-filter-dictionary",
|
|
114
|
+
FileUploader = "file-uploader"
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
interface ClearStrategy {
|
|
115
118
|
clear(editor: Editor): Promise<void>;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
declare abstract class AbstractElementWithParent extends AbstractElement {
|
|
121
|
+
declare abstract class AbstractElementWithParent<TLocator extends Locator | Promise<Locator> = Locator> extends AbstractElement<TLocator> {
|
|
119
122
|
protected parentCssSelector: string;
|
|
120
123
|
constructor(parentCssSelector: string, elementCssSelector: string, page: Page);
|
|
121
124
|
protected getFullCssSelector(): string;
|
|
@@ -347,7 +350,13 @@ declare class EditorButton extends AbstractElementWithParent {
|
|
|
347
350
|
|
|
348
351
|
declare class AbstractEditor extends AbstractElementWithParent implements Editor {
|
|
349
352
|
protected editor: Editor;
|
|
350
|
-
|
|
353
|
+
protected _titleCssSelector: string;
|
|
354
|
+
constructor({ parentCssSelector, elementCssSelector, titleCssSelector, page }: {
|
|
355
|
+
parentCssSelector: string;
|
|
356
|
+
elementCssSelector: string;
|
|
357
|
+
titleCssSelector: string;
|
|
358
|
+
page: Page;
|
|
359
|
+
});
|
|
351
360
|
protected initEditor(): Promise<void>;
|
|
352
361
|
/**
|
|
353
362
|
* Возвращает значение в поле
|
|
@@ -404,6 +413,20 @@ declare class AbstractEditor extends AbstractElementWithParent implements Editor
|
|
|
404
413
|
* await form.field('Name').button('editorButton).click()
|
|
405
414
|
*/
|
|
406
415
|
button(name: string): EditorButton;
|
|
416
|
+
/**
|
|
417
|
+
* Повертає загловок едітора
|
|
418
|
+
* @example
|
|
419
|
+
* expect(await formEdit.field('NumberFld').title()).toBe('Title1');
|
|
420
|
+
* expect(await formEdit.field('TextFld').title()).toBe('Title2`);
|
|
421
|
+
*/
|
|
422
|
+
title(): Promise<string>;
|
|
423
|
+
/**
|
|
424
|
+
* Вивантажує файл і повертає назву файла. Доступний тільки для поля FileUploader.
|
|
425
|
+
* @example
|
|
426
|
+
* const fileName = await formEdit.field('FileField').downloadFile();
|
|
427
|
+
* expect(filename()).toBe('file.pdf');
|
|
428
|
+
*/
|
|
429
|
+
download(): Promise<string>;
|
|
407
430
|
}
|
|
408
431
|
|
|
409
432
|
declare class FormField extends AbstractEditor {
|
|
@@ -500,7 +523,7 @@ declare class ToolbarItem extends AbstractElementWithParent implements Button {
|
|
|
500
523
|
get menu(): ToolbarMenu;
|
|
501
524
|
}
|
|
502
525
|
|
|
503
|
-
declare class Cell extends AbstractElementWithParent {
|
|
526
|
+
declare class Cell extends AbstractElementWithParent<Promise<Locator>> {
|
|
504
527
|
private _index;
|
|
505
528
|
private readonly getCellIndex;
|
|
506
529
|
constructor(parentCssSelector: string, getCellIndex: () => Promise<number>, page: Page, index?: number);
|
|
@@ -509,7 +532,7 @@ declare class Cell extends AbstractElementWithParent {
|
|
|
509
532
|
private getTagsValue;
|
|
510
533
|
private getNumberValue;
|
|
511
534
|
private getDateValue;
|
|
512
|
-
|
|
535
|
+
getLocator(): Promise<Locator>;
|
|
513
536
|
getValue(): Promise<string | number | 1 | 0 | string[] | Date | Date[] | null>;
|
|
514
537
|
getIndex(): number;
|
|
515
538
|
}
|
|
@@ -522,7 +545,7 @@ interface ConstructorParams$1 {
|
|
|
522
545
|
index?: number;
|
|
523
546
|
page: Page;
|
|
524
547
|
}
|
|
525
|
-
declare class Column extends AbstractElementWithParent {
|
|
548
|
+
declare class Column extends AbstractElementWithParent<Promise<Locator>> {
|
|
526
549
|
private _index;
|
|
527
550
|
private _caption;
|
|
528
551
|
private _name;
|
|
@@ -530,7 +553,7 @@ declare class Column extends AbstractElementWithParent {
|
|
|
530
553
|
constructor({ parentCssSelector, headerCssSelector, name, caption, index, page }: ConstructorParams$1);
|
|
531
554
|
private set index(value);
|
|
532
555
|
private get index();
|
|
533
|
-
|
|
556
|
+
getLocator(): Promise<Locator>;
|
|
534
557
|
private getColumnHeaderIndexBy;
|
|
535
558
|
private getIndexByCaption;
|
|
536
559
|
private getIndexByName;
|