d5-testing-library 2.0.0-alpha.1 → 2.0.0-alpha.10
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-QX5S7TDU.mjs} +1 -1
- package/dist/{ListForm-NEBCZD4X.mjs → ListForm-4DCCOHKJ.mjs} +1 -1
- package/dist/{TreeView-T3PIDSZQ.mjs → TreeView-RDCA3LGU.mjs} +1 -1
- package/dist/{chunk-75NROWLM.mjs → chunk-GSTA5R4B.mjs} +233 -43
- package/dist/cjs/d5-testing-library.cjs +248 -42
- 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
|
}
|
|
@@ -552,7 +556,7 @@ var init_SelectBoxEditor = __esm({
|
|
|
552
556
|
const inputEl = this.getInputLocator();
|
|
553
557
|
await inputEl.click();
|
|
554
558
|
try {
|
|
555
|
-
await inputEl.
|
|
559
|
+
await inputEl.pressSequentially(value + "");
|
|
556
560
|
await inputEl.press("Enter");
|
|
557
561
|
await dropDownOptionClick(value, this.page, false);
|
|
558
562
|
} catch {
|
|
@@ -655,12 +659,12 @@ var init_TagBox = __esm({
|
|
|
655
659
|
try {
|
|
656
660
|
await dropDownOptionClick(value, this.page, false);
|
|
657
661
|
} catch {
|
|
658
|
-
await input.
|
|
662
|
+
await input.pressSequentially(value + "");
|
|
659
663
|
await dropDownOptionClick(value, this.page, true);
|
|
660
664
|
}
|
|
661
665
|
await this.waitOptionSelection(value);
|
|
662
666
|
if (value !== lastElement) {
|
|
663
|
-
await input.
|
|
667
|
+
await input.pressSequentially("");
|
|
664
668
|
}
|
|
665
669
|
}
|
|
666
670
|
async confirmSelection() {
|
|
@@ -1057,7 +1061,6 @@ var init_SingleDateEditor = __esm({
|
|
|
1057
1061
|
init_BaseDateEditor();
|
|
1058
1062
|
init_utils();
|
|
1059
1063
|
init_ClearButtonStrategy();
|
|
1060
|
-
init_src();
|
|
1061
1064
|
SingleDateEditor = class extends BaseDateEditor {
|
|
1062
1065
|
constructor(parentCssSelector, elementCssSelector, page) {
|
|
1063
1066
|
super(parentCssSelector, elementCssSelector, page);
|
|
@@ -1080,11 +1083,7 @@ var init_SingleDateEditor = __esm({
|
|
|
1080
1083
|
}
|
|
1081
1084
|
async setValue(value) {
|
|
1082
1085
|
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);
|
|
1086
|
+
await this.setDateValue(value);
|
|
1088
1087
|
} else {
|
|
1089
1088
|
throw new Error(`Value is incorrect. It should be a Date object`);
|
|
1090
1089
|
}
|
|
@@ -1180,7 +1179,7 @@ var init_DateEditor = __esm({
|
|
|
1180
1179
|
});
|
|
1181
1180
|
|
|
1182
1181
|
// 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,
|
|
1182
|
+
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
1183
|
var init_HeaderFilterDictionary = __esm({
|
|
1185
1184
|
"src/pageObjects/elements/Editors/HeaderFilterDictionary.ts"() {
|
|
1186
1185
|
"use strict";
|
|
@@ -1193,12 +1192,11 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1193
1192
|
CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
|
|
1194
1193
|
SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
|
|
1195
1194
|
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
1195
|
dropDownHeaderFilterDictionaryOptionClick = async (optionValue, page, dataTEST = "", delay = true) => {
|
|
1198
1196
|
const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
|
|
1199
1197
|
const calendarPopover = page.locator(calendarPopoverSelector);
|
|
1200
1198
|
const customOptionList = calendarPopover.locator(`.${CUSTOM_OPTION_LIST_SELECTOR}`);
|
|
1201
|
-
const optElement = customOptionList.locator(
|
|
1199
|
+
const optElement = customOptionList.locator(`.${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}`, { hasText: optionValue });
|
|
1202
1200
|
try {
|
|
1203
1201
|
await optElement.waitFor({ state: "visible", timeout: delay ? void 0 : 600 });
|
|
1204
1202
|
await optElement.click();
|
|
@@ -1222,28 +1220,28 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1222
1220
|
await this.selectOption(inputEl, value, lastElement);
|
|
1223
1221
|
}
|
|
1224
1222
|
}
|
|
1225
|
-
async waitOptionSelection() {
|
|
1226
|
-
|
|
1227
|
-
await selectedItem.waitFor({ state: "visible" });
|
|
1223
|
+
async waitOptionSelection(value) {
|
|
1224
|
+
await this.page.locator(`${TAG_BOX_LIST_ITEM_SELECTOR}`).filter({ hasText: value }).first().waitFor({ state: "visible" });
|
|
1228
1225
|
}
|
|
1229
1226
|
async selectOption(inputEl, value, lastElement) {
|
|
1230
1227
|
try {
|
|
1231
|
-
await inputEl.
|
|
1228
|
+
await inputEl.pressSequentially(value + "");
|
|
1232
1229
|
const dataTEST = await this.getDataTestId();
|
|
1233
1230
|
await dropDownHeaderFilterDictionaryOptionClick(value, this.page, dataTEST);
|
|
1234
1231
|
if (value !== lastElement) {
|
|
1235
|
-
await inputEl.
|
|
1232
|
+
await inputEl.pressSequentially("");
|
|
1236
1233
|
}
|
|
1237
1234
|
} catch (error) {
|
|
1238
1235
|
throw error;
|
|
1239
1236
|
}
|
|
1240
|
-
await this.waitOptionSelection();
|
|
1237
|
+
await this.waitOptionSelection(value);
|
|
1241
1238
|
}
|
|
1242
1239
|
async getHeaderFilterDictionaryInputValue() {
|
|
1243
1240
|
if (await this.isHeaderFilterDictionaryEmpty()) {
|
|
1244
1241
|
return [];
|
|
1245
1242
|
}
|
|
1246
1243
|
const tags = this.page.locator(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER2} ${TAGS_SELECTOR2}`);
|
|
1244
|
+
await tags.first().waitFor({ state: "visible" });
|
|
1247
1245
|
const count = await tags.count();
|
|
1248
1246
|
const values = [];
|
|
1249
1247
|
for (let i = 0; i < count; i++) {
|
|
@@ -1269,6 +1267,125 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1269
1267
|
}
|
|
1270
1268
|
});
|
|
1271
1269
|
|
|
1270
|
+
// src/pageObjects/elements/Editors/FileUploader.ts
|
|
1271
|
+
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;
|
|
1272
|
+
var init_FileUploader = __esm({
|
|
1273
|
+
"src/pageObjects/elements/Editors/FileUploader.ts"() {
|
|
1274
|
+
"use strict";
|
|
1275
|
+
init_AbstractElementWithParent();
|
|
1276
|
+
FILE_NAME_SELECTOR = ".file-text";
|
|
1277
|
+
FILE_SIZE_ATTRIBUTE = "data-filesize";
|
|
1278
|
+
FILE_DATE_ATTRIBUTE = "data-moddate";
|
|
1279
|
+
FILE_TYPE_ATTRIBUTE = "data-filetype";
|
|
1280
|
+
SELECT_FILE_BUTTON_SELECTOR = ".select-file-button";
|
|
1281
|
+
DOWNLOAD_FILE_BUTTON_SELECTOR = ".download-file-button";
|
|
1282
|
+
METADATA_SELECTOR = ".file-text-file-info-wrapper";
|
|
1283
|
+
CLEAR_BUTTON_SELECTOR = ".clear-button";
|
|
1284
|
+
FileUploader = class extends AbstractElementWithParent {
|
|
1285
|
+
constructor(parentCssSelector, elementCssSelector, page) {
|
|
1286
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Returns the metadata container element for the uploaded file.
|
|
1290
|
+
* Returns null when metadata is not rendered or not visible.
|
|
1291
|
+
*/
|
|
1292
|
+
async getMedataElement() {
|
|
1293
|
+
const root = this.getFullCssSelector();
|
|
1294
|
+
const locator = this.page.locator(`${root} ${METADATA_SELECTOR}`);
|
|
1295
|
+
if (!await locator.isVisible()) return null;
|
|
1296
|
+
return locator;
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Returns the name of the uploaded file, or null if not present.
|
|
1300
|
+
*/
|
|
1301
|
+
async getFileName() {
|
|
1302
|
+
const root = this.getFullCssSelector();
|
|
1303
|
+
const locator = this.page.locator(`${root} ${FILE_NAME_SELECTOR}`);
|
|
1304
|
+
if (!await locator.isVisible()) return null;
|
|
1305
|
+
const text = await locator.innerText();
|
|
1306
|
+
return text?.trim() || null;
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Returns the size of the uploaded file, or null if not present.
|
|
1310
|
+
*/
|
|
1311
|
+
async getFileSize() {
|
|
1312
|
+
const element = await this.getMedataElement();
|
|
1313
|
+
if (!element) return null;
|
|
1314
|
+
const result = (await element.getAttribute(FILE_SIZE_ATTRIBUTE))?.trim();
|
|
1315
|
+
return isNaN(+result) ? null : +result;
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Returns the upload/modification date of the file, or null if not present.
|
|
1319
|
+
*/
|
|
1320
|
+
async getFileDate() {
|
|
1321
|
+
const element = await this.getMedataElement();
|
|
1322
|
+
if (!element) return null;
|
|
1323
|
+
const fileModDate = (await element.getAttribute(FILE_DATE_ATTRIBUTE))?.trim();
|
|
1324
|
+
return fileModDate ? new Date(fileModDate) : null;
|
|
1325
|
+
}
|
|
1326
|
+
/**
|
|
1327
|
+
* Returns the MIME/content type of the uploaded file from metadata.
|
|
1328
|
+
* Returns null when the type attribute is absent or empty.
|
|
1329
|
+
*/
|
|
1330
|
+
async getFileType() {
|
|
1331
|
+
const element = await this.getMedataElement();
|
|
1332
|
+
if (!element) return null;
|
|
1333
|
+
const fileType = (await element.getAttribute(FILE_TYPE_ATTRIBUTE))?.trim();
|
|
1334
|
+
return fileType || null;
|
|
1335
|
+
}
|
|
1336
|
+
/**
|
|
1337
|
+
* Returns current file information: name, size and upload/modification date.
|
|
1338
|
+
* Returns null if no file is uploaded.
|
|
1339
|
+
*/
|
|
1340
|
+
async getValue() {
|
|
1341
|
+
const name = await this.getFileName();
|
|
1342
|
+
const size = await this.getFileSize();
|
|
1343
|
+
const date = await this.getFileDate();
|
|
1344
|
+
const type2 = await this.getFileType();
|
|
1345
|
+
if (!name && !size && !date && !type2) return null;
|
|
1346
|
+
return { FileName: name, FileSize: size, FileType: type2, ModDate: date };
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Uploads a file by clicking the select-file-button and providing the file path.
|
|
1350
|
+
* @param filePath - Absolute or relative path to the file on disk.
|
|
1351
|
+
*/
|
|
1352
|
+
async setValue(filePath) {
|
|
1353
|
+
const root = this.getFullCssSelector();
|
|
1354
|
+
const fileChooserPromise = this.page.waitForEvent("filechooser");
|
|
1355
|
+
await this.page.locator(`${root} ${SELECT_FILE_BUTTON_SELECTOR}`).click();
|
|
1356
|
+
const fileChooser = await fileChooserPromise;
|
|
1357
|
+
await fileChooser.setFiles(filePath);
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Downloads the currently uploaded file by clicking the download-file-button.
|
|
1361
|
+
* Returns the suggested file name of the downloaded file.
|
|
1362
|
+
*/
|
|
1363
|
+
async download() {
|
|
1364
|
+
const root = this.getFullCssSelector();
|
|
1365
|
+
const buttonLocator = this.page.locator(
|
|
1366
|
+
`${root} ${DOWNLOAD_FILE_BUTTON_SELECTOR}`
|
|
1367
|
+
);
|
|
1368
|
+
if (await buttonLocator.isHidden()) return "";
|
|
1369
|
+
const downloadPromise = this.page.waitForEvent("download");
|
|
1370
|
+
await buttonLocator.click();
|
|
1371
|
+
const download = await downloadPromise;
|
|
1372
|
+
return download.suggestedFilename();
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Removes the currently uploaded file by clicking the delete-file-button.
|
|
1376
|
+
* Does nothing if no file is uploaded.
|
|
1377
|
+
*/
|
|
1378
|
+
async clear() {
|
|
1379
|
+
if (await this.getValue() === null) return;
|
|
1380
|
+
const root = this.getFullCssSelector();
|
|
1381
|
+
const deleteButton = this.page.locator(`${root} ${CLEAR_BUTTON_SELECTOR}`);
|
|
1382
|
+
if (await deleteButton.isHidden()) return;
|
|
1383
|
+
await deleteButton.click();
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
|
|
1272
1389
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
1273
1390
|
var editorFactory;
|
|
1274
1391
|
var init_editorFactory = __esm({
|
|
@@ -1286,6 +1403,7 @@ var init_editorFactory = __esm({
|
|
|
1286
1403
|
init_ButtonGroup();
|
|
1287
1404
|
init_DateEditor();
|
|
1288
1405
|
init_HeaderFilterDictionary();
|
|
1406
|
+
init_FileUploader();
|
|
1289
1407
|
editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
1290
1408
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, page);
|
|
1291
1409
|
const classString = await elementInstance.getClasses();
|
|
@@ -1306,6 +1424,8 @@ var init_editorFactory = __esm({
|
|
|
1306
1424
|
return new ButtonGroup(parentCssSelector, elementCssSelector, page);
|
|
1307
1425
|
if (classString.includes("header-filter-dictionary" /* HeaderFilterDictionary */))
|
|
1308
1426
|
return new HeaderFilterDictionary(parentCssSelector, elementCssSelector, page);
|
|
1427
|
+
if (classString.includes("file-uploader" /* FileUploader */))
|
|
1428
|
+
return new FileUploader(parentCssSelector, elementCssSelector, page);
|
|
1309
1429
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
1310
1430
|
};
|
|
1311
1431
|
}
|
|
@@ -1385,6 +1505,15 @@ function createSubSystemTestId(itemName) {
|
|
|
1385
1505
|
function createEditorButtonTestId(itemName) {
|
|
1386
1506
|
return `${"editor-button" /* EDITOR_BUTTON */}-${itemName}`;
|
|
1387
1507
|
}
|
|
1508
|
+
function createLabelFieldTestId(formName, itemName) {
|
|
1509
|
+
return `${"label" /* LABEL */}-${createFieldTestId(formName, itemName)}`;
|
|
1510
|
+
}
|
|
1511
|
+
function createLabelDocFilterTestId(formName, itemName) {
|
|
1512
|
+
return `${"label" /* LABEL */}-${createDocFilterTestId(formName, itemName)}`;
|
|
1513
|
+
}
|
|
1514
|
+
function createLabelLayoutFilterTestId(formName, itemName) {
|
|
1515
|
+
return `${"label" /* LABEL */}-${createLayoutFilterTestId(formName, itemName)}`;
|
|
1516
|
+
}
|
|
1388
1517
|
var init_createDataTestId = __esm({
|
|
1389
1518
|
"src/utils/createDataTestId.ts"() {
|
|
1390
1519
|
"use strict";
|
|
@@ -1863,7 +1992,7 @@ var init_AbstractForm = __esm({
|
|
|
1863
1992
|
async exists() {
|
|
1864
1993
|
try {
|
|
1865
1994
|
const container = this.page.locator(this.containerCssSelector);
|
|
1866
|
-
await waitElementIsVisible_default({ locator: container });
|
|
1995
|
+
await waitElementIsVisible_default({ locator: container, timeout: 3e3 });
|
|
1867
1996
|
return true;
|
|
1868
1997
|
} catch (error) {
|
|
1869
1998
|
return false;
|
|
@@ -1996,14 +2125,14 @@ var init_Cell = __esm({
|
|
|
1996
2125
|
}
|
|
1997
2126
|
return getDate(value);
|
|
1998
2127
|
}
|
|
1999
|
-
async
|
|
2128
|
+
async getLocator() {
|
|
2000
2129
|
if (this._index == null) {
|
|
2001
2130
|
this.index = await this.getCellIndex();
|
|
2002
2131
|
}
|
|
2003
|
-
return this.
|
|
2132
|
+
return this.syncLocator();
|
|
2004
2133
|
}
|
|
2005
2134
|
async getValue() {
|
|
2006
|
-
const cellEl = await this.
|
|
2135
|
+
const cellEl = await this.getLocator();
|
|
2007
2136
|
const cellElClass = await cellEl.getAttribute("class") ?? "";
|
|
2008
2137
|
if (cellElClass.includes("boolean-column" /* Boolean */)) return this.getBooleanValue(cellEl);
|
|
2009
2138
|
if (cellElClass.includes("tags-column" /* Tags */)) return this.getTagsValue(cellEl);
|
|
@@ -2151,9 +2280,9 @@ var init_Column = __esm({
|
|
|
2151
2280
|
constructor({ parentCssSelector, headerCssSelector, name, caption, index, page }) {
|
|
2152
2281
|
super(parentCssSelector, "", page);
|
|
2153
2282
|
this._name = name;
|
|
2283
|
+
this.headerCssSelector = headerCssSelector;
|
|
2154
2284
|
this.index = index;
|
|
2155
2285
|
this._caption = caption;
|
|
2156
|
-
this.headerCssSelector = headerCssSelector;
|
|
2157
2286
|
}
|
|
2158
2287
|
set index(index) {
|
|
2159
2288
|
this._index = index;
|
|
@@ -2162,9 +2291,9 @@ var init_Column = __esm({
|
|
|
2162
2291
|
get index() {
|
|
2163
2292
|
return this._index;
|
|
2164
2293
|
}
|
|
2165
|
-
async
|
|
2294
|
+
async getLocator() {
|
|
2166
2295
|
await this.getIndex();
|
|
2167
|
-
return this.
|
|
2296
|
+
return this.syncLocator();
|
|
2168
2297
|
}
|
|
2169
2298
|
async getColumnHeaderIndexBy(cssSelector) {
|
|
2170
2299
|
const column = this.page.locator(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`);
|
|
@@ -2177,7 +2306,7 @@ var init_Column = __esm({
|
|
|
2177
2306
|
return this.getColumnHeaderIndexBy(getColumnByNameCssSelector(this._name));
|
|
2178
2307
|
}
|
|
2179
2308
|
async caption() {
|
|
2180
|
-
const el = await this.
|
|
2309
|
+
const el = await this.getLocator();
|
|
2181
2310
|
const text = await el.innerText();
|
|
2182
2311
|
return text?.trim() ?? null;
|
|
2183
2312
|
}
|
|
@@ -2230,6 +2359,25 @@ var init_EditorButton = __esm({
|
|
|
2230
2359
|
}
|
|
2231
2360
|
});
|
|
2232
2361
|
|
|
2362
|
+
// src/pageObjects/elements/EditorTitle.ts
|
|
2363
|
+
var CAPTION_TEXT_CLASS, EditorTitle;
|
|
2364
|
+
var init_EditorTitle = __esm({
|
|
2365
|
+
"src/pageObjects/elements/EditorTitle.ts"() {
|
|
2366
|
+
"use strict";
|
|
2367
|
+
init_AbstractElementWithParent();
|
|
2368
|
+
CAPTION_TEXT_CLASS = " .caption-text";
|
|
2369
|
+
EditorTitle = class extends AbstractElementWithParent {
|
|
2370
|
+
constructor({ parentCssSelector, elementCssSelector, page }) {
|
|
2371
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
2372
|
+
}
|
|
2373
|
+
async getTitle() {
|
|
2374
|
+
const captionElement = this.getLocator().locator(CAPTION_TEXT_CLASS);
|
|
2375
|
+
return captionElement.innerText();
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
});
|
|
2380
|
+
|
|
2233
2381
|
// src/pageObjects/elements/AbstractEditor.ts
|
|
2234
2382
|
var AbstractEditor;
|
|
2235
2383
|
var init_AbstractEditor2 = __esm({
|
|
@@ -2238,10 +2386,13 @@ var init_AbstractEditor2 = __esm({
|
|
|
2238
2386
|
init_AbstractElementWithParent();
|
|
2239
2387
|
init_Editors();
|
|
2240
2388
|
init_EditorButton();
|
|
2389
|
+
init_EditorTitle();
|
|
2241
2390
|
AbstractEditor = class extends AbstractElementWithParent {
|
|
2242
2391
|
editor;
|
|
2243
|
-
|
|
2392
|
+
_titleCssSelector;
|
|
2393
|
+
constructor({ parentCssSelector, elementCssSelector, titleCssSelector, page }) {
|
|
2244
2394
|
super(parentCssSelector, elementCssSelector, page);
|
|
2395
|
+
this._titleCssSelector = titleCssSelector;
|
|
2245
2396
|
}
|
|
2246
2397
|
async initEditor() {
|
|
2247
2398
|
if (!this.editor) {
|
|
@@ -2337,6 +2488,32 @@ var init_AbstractEditor2 = __esm({
|
|
|
2337
2488
|
button(name) {
|
|
2338
2489
|
return new EditorButton(this.getFullCssSelector(), name, this.page);
|
|
2339
2490
|
}
|
|
2491
|
+
/**
|
|
2492
|
+
* Повертає загловок едітора
|
|
2493
|
+
* @example
|
|
2494
|
+
* expect(await formEdit.field('NumberFld').title()).toBe('Title1');
|
|
2495
|
+
* expect(await formEdit.field('TextFld').title()).toBe('Title2`);
|
|
2496
|
+
*/
|
|
2497
|
+
async title() {
|
|
2498
|
+
return new EditorTitle({
|
|
2499
|
+
elementCssSelector: this._titleCssSelector,
|
|
2500
|
+
parentCssSelector: this.parentCssSelector,
|
|
2501
|
+
page: this.page
|
|
2502
|
+
}).getTitle();
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2505
|
+
* Вивантажує файл і повертає назву файла. Доступний тільки для поля FileUploader.
|
|
2506
|
+
* @example
|
|
2507
|
+
* const fileName = await formEdit.field('FileField').downloadFile();
|
|
2508
|
+
* expect(filename()).toBe('file.pdf');
|
|
2509
|
+
*/
|
|
2510
|
+
async download() {
|
|
2511
|
+
await this.initEditor();
|
|
2512
|
+
if (!this.editor.download) {
|
|
2513
|
+
throw new Error("download is only available for the FileUploader field type.");
|
|
2514
|
+
}
|
|
2515
|
+
return this.editor.download();
|
|
2516
|
+
}
|
|
2340
2517
|
};
|
|
2341
2518
|
}
|
|
2342
2519
|
});
|
|
@@ -2351,7 +2528,12 @@ var init_FormField = __esm({
|
|
|
2351
2528
|
init_AbstractEditor2();
|
|
2352
2529
|
FormField = class extends AbstractEditor {
|
|
2353
2530
|
constructor(parentCssSelector, formName, name, page) {
|
|
2354
|
-
super(
|
|
2531
|
+
super({
|
|
2532
|
+
parentCssSelector,
|
|
2533
|
+
elementCssSelector: byTestIdCssSelector(createFieldTestId(formName, name)),
|
|
2534
|
+
titleCssSelector: byTestIdCssSelector(createLabelFieldTestId(formName, name)),
|
|
2535
|
+
page
|
|
2536
|
+
});
|
|
2355
2537
|
}
|
|
2356
2538
|
};
|
|
2357
2539
|
}
|
|
@@ -2525,6 +2707,7 @@ var init_Table = __esm({
|
|
|
2525
2707
|
this.getRowByIndex(index);
|
|
2526
2708
|
return new Column({
|
|
2527
2709
|
parentCssSelector: this.getFullCssSelector(),
|
|
2710
|
+
headerCssSelector: this.headerCssSelector,
|
|
2528
2711
|
page: this.page,
|
|
2529
2712
|
index
|
|
2530
2713
|
});
|
|
@@ -2637,7 +2820,7 @@ var init_Table = __esm({
|
|
|
2637
2820
|
[row] = await this.getSelectedRows();
|
|
2638
2821
|
}
|
|
2639
2822
|
if (!row) throw new Error("No row available row for context menu");
|
|
2640
|
-
const cellElement = await row.getCell(fieldName).
|
|
2823
|
+
const cellElement = await row.getCell(fieldName).getLocator();
|
|
2641
2824
|
await cellElement.click({ button: "right" });
|
|
2642
2825
|
});
|
|
2643
2826
|
}
|
|
@@ -2696,10 +2879,14 @@ var init_Table = __esm({
|
|
|
2696
2879
|
* console.log('Таблиця містить 5 рядків');
|
|
2697
2880
|
*/
|
|
2698
2881
|
async waitRowsCount(count) {
|
|
2699
|
-
await wait(
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2882
|
+
await wait(
|
|
2883
|
+
async () => {
|
|
2884
|
+
const rowsCount = await this.getRowElements().count();
|
|
2885
|
+
return rowsCount === count;
|
|
2886
|
+
},
|
|
2887
|
+
this.page,
|
|
2888
|
+
`Rows count not equal: ${count}`
|
|
2889
|
+
);
|
|
2703
2890
|
}
|
|
2704
2891
|
};
|
|
2705
2892
|
}
|
|
@@ -2951,6 +3138,7 @@ var init_ToolbarItem = __esm({
|
|
|
2951
3138
|
init_locators();
|
|
2952
3139
|
init_ToolbarMenu();
|
|
2953
3140
|
init_waitElementIsVisible();
|
|
3141
|
+
init_wait();
|
|
2954
3142
|
GROUP_BUTTON_CLASS = "toolbar-group-button";
|
|
2955
3143
|
toolbarItemSelector = (form, name) => byTestIdCssSelector(`ftb-${form}-${name}`);
|
|
2956
3144
|
ToolbarItem = class extends AbstractElementWithParent {
|
|
@@ -2974,7 +3162,10 @@ var init_ToolbarItem = __esm({
|
|
|
2974
3162
|
async click() {
|
|
2975
3163
|
try {
|
|
2976
3164
|
await this.init();
|
|
2977
|
-
await
|
|
3165
|
+
await wait(async () => {
|
|
3166
|
+
const element = this._button.getLocator();
|
|
3167
|
+
return await element.isEnabled() && await element.isVisible();
|
|
3168
|
+
}, this.page);
|
|
2978
3169
|
await this._button.click();
|
|
2979
3170
|
} catch (error) {
|
|
2980
3171
|
throw new Error(`Cannot click on toolbar item: ${this._itemName}`);
|
|
@@ -3149,7 +3340,12 @@ var init_FormFilterField = __esm({
|
|
|
3149
3340
|
formName;
|
|
3150
3341
|
name;
|
|
3151
3342
|
constructor(parentCssSelector, formName, name, page) {
|
|
3152
|
-
super(
|
|
3343
|
+
super({
|
|
3344
|
+
parentCssSelector,
|
|
3345
|
+
elementCssSelector: byTestIdCssSelector(createLayoutFilterTestId(formName, name)),
|
|
3346
|
+
titleCssSelector: byTestIdCssSelector(createLabelLayoutFilterTestId(formName, name)),
|
|
3347
|
+
page
|
|
3348
|
+
});
|
|
3153
3349
|
this.formName = formName;
|
|
3154
3350
|
this.name = name;
|
|
3155
3351
|
}
|
|
@@ -3263,7 +3459,12 @@ var init_PanelFilterField = __esm({
|
|
|
3263
3459
|
formName;
|
|
3264
3460
|
name;
|
|
3265
3461
|
constructor(parentCssSelector, formName, name, page) {
|
|
3266
|
-
super(
|
|
3462
|
+
super({
|
|
3463
|
+
parentCssSelector,
|
|
3464
|
+
elementCssSelector: byTestIdCssSelector(createDocFilterTestId(formName, name)),
|
|
3465
|
+
titleCssSelector: byTestIdCssSelector(createLabelDocFilterTestId(formName, name)),
|
|
3466
|
+
page
|
|
3467
|
+
});
|
|
3267
3468
|
this.formName = formName;
|
|
3268
3469
|
this.name = name;
|
|
3269
3470
|
}
|
|
@@ -3431,7 +3632,12 @@ var init_HeaderFilterField = __esm({
|
|
|
3431
3632
|
init_AbstractEditor2();
|
|
3432
3633
|
HeaderFilterField = class extends AbstractEditor {
|
|
3433
3634
|
constructor(parentCssSelector, formName, name, page) {
|
|
3434
|
-
super(
|
|
3635
|
+
super({
|
|
3636
|
+
parentCssSelector,
|
|
3637
|
+
elementCssSelector: byTestIdCssSelector(createHeaderFilterTestId(formName, name)),
|
|
3638
|
+
titleCssSelector: "",
|
|
3639
|
+
page
|
|
3640
|
+
});
|
|
3435
3641
|
}
|
|
3436
3642
|
async getValue() {
|
|
3437
3643
|
return super.getValue();
|
|
@@ -3493,7 +3699,7 @@ var init_ColumnFilter = __esm({
|
|
|
3493
3699
|
await this.getCancelButton().click();
|
|
3494
3700
|
}
|
|
3495
3701
|
async initFilter() {
|
|
3496
|
-
const columnEl = await this._column.
|
|
3702
|
+
const columnEl = await this._column.getLocator();
|
|
3497
3703
|
await columnEl.hover();
|
|
3498
3704
|
const headerFilterIcon = columnEl.locator(HEADER_FILTER_ICON);
|
|
3499
3705
|
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;
|