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
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
//.
|
|
@@ -2859,11 +2859,14 @@ var AbstractElement = class {
|
|
|
2859
2859
|
joinRelativeCssSelectors(selectors) {
|
|
2860
2860
|
return selectors.join(" ");
|
|
2861
2861
|
}
|
|
2862
|
-
|
|
2862
|
+
syncLocator() {
|
|
2863
2863
|
return this.page.locator(`css=${this.getFullCssSelector()}`);
|
|
2864
2864
|
}
|
|
2865
|
+
getLocator() {
|
|
2866
|
+
return this.syncLocator();
|
|
2867
|
+
}
|
|
2865
2868
|
async getAttribute(attr) {
|
|
2866
|
-
const locator = this.
|
|
2869
|
+
const locator = this.syncLocator();
|
|
2867
2870
|
if (await locator.isVisible()) {
|
|
2868
2871
|
return locator.getAttribute(attr);
|
|
2869
2872
|
}
|
|
@@ -2941,6 +2944,15 @@ function createSubSystemTestId(itemName) {
|
|
|
2941
2944
|
function createEditorButtonTestId(itemName) {
|
|
2942
2945
|
return `${"editor-button" /* EDITOR_BUTTON */}-${itemName}`;
|
|
2943
2946
|
}
|
|
2947
|
+
function createLabelFieldTestId(formName, itemName) {
|
|
2948
|
+
return `${"label" /* LABEL */}-${createFieldTestId(formName, itemName)}`;
|
|
2949
|
+
}
|
|
2950
|
+
function createLabelDocFilterTestId(formName, itemName) {
|
|
2951
|
+
return `${"label" /* LABEL */}-${createDocFilterTestId(formName, itemName)}`;
|
|
2952
|
+
}
|
|
2953
|
+
function createLabelLayoutFilterTestId(formName, itemName) {
|
|
2954
|
+
return `${"label" /* LABEL */}-${createLayoutFilterTestId(formName, itemName)}`;
|
|
2955
|
+
}
|
|
2944
2956
|
|
|
2945
2957
|
// src/pageObjects/AbstractElementWithParent.ts
|
|
2946
2958
|
var AbstractElementWithParent = class extends AbstractElement {
|
|
@@ -3263,7 +3275,7 @@ var AbstractForm = class extends AbstractPage {
|
|
|
3263
3275
|
async exists() {
|
|
3264
3276
|
try {
|
|
3265
3277
|
const container = this.page.locator(this.containerCssSelector);
|
|
3266
|
-
await waitElementIsVisible_default({ locator: container });
|
|
3278
|
+
await waitElementIsVisible_default({ locator: container, timeout: 3e3 });
|
|
3267
3279
|
return true;
|
|
3268
3280
|
} catch (error) {
|
|
3269
3281
|
return false;
|
|
@@ -3308,15 +3320,15 @@ async function classDependencyInjector(formType) {
|
|
|
3308
3320
|
let SubFormFactoryClass;
|
|
3309
3321
|
switch (formType) {
|
|
3310
3322
|
case "1" /* LIST */:
|
|
3311
|
-
SubFormFactoryClass = (await import("./ListForm-
|
|
3323
|
+
SubFormFactoryClass = (await import("./ListForm-DSQ4LR7B.mjs")).default;
|
|
3312
3324
|
break;
|
|
3313
3325
|
case "3" /* TREE */:
|
|
3314
|
-
SubFormFactoryClass = (await import("./TreeView-
|
|
3326
|
+
SubFormFactoryClass = (await import("./TreeView-HFUTD2JY.mjs")).default;
|
|
3315
3327
|
break;
|
|
3316
3328
|
case "2" /* EDIT */:
|
|
3317
3329
|
case "99" /* FREE_FORM */:
|
|
3318
3330
|
case "4" /* REPORT */:
|
|
3319
|
-
SubFormFactoryClass = (await import("./FormEdit-
|
|
3331
|
+
SubFormFactoryClass = (await import("./FormEdit-XTRS74QI.mjs")).default;
|
|
3320
3332
|
break;
|
|
3321
3333
|
default:
|
|
3322
3334
|
throw new Error(`Unsupported form type ${formType}`);
|
|
@@ -3478,14 +3490,14 @@ var Cell = class extends AbstractElementWithParent {
|
|
|
3478
3490
|
}
|
|
3479
3491
|
return getDate(value);
|
|
3480
3492
|
}
|
|
3481
|
-
async
|
|
3493
|
+
async getLocator() {
|
|
3482
3494
|
if (this._index == null) {
|
|
3483
3495
|
this.index = await this.getCellIndex();
|
|
3484
3496
|
}
|
|
3485
|
-
return this.
|
|
3497
|
+
return this.syncLocator();
|
|
3486
3498
|
}
|
|
3487
3499
|
async getValue() {
|
|
3488
|
-
const cellEl = await this.
|
|
3500
|
+
const cellEl = await this.getLocator();
|
|
3489
3501
|
const cellElClass = await cellEl.getAttribute("class") ?? "";
|
|
3490
3502
|
if (cellElClass.includes("boolean-column" /* Boolean */)) return this.getBooleanValue(cellEl);
|
|
3491
3503
|
if (cellElClass.includes("tags-column" /* Tags */)) return this.getTagsValue(cellEl);
|
|
@@ -3632,9 +3644,9 @@ var Column = class extends AbstractElementWithParent {
|
|
|
3632
3644
|
constructor({ parentCssSelector, headerCssSelector, name, caption, index, page }) {
|
|
3633
3645
|
super(parentCssSelector, "", page);
|
|
3634
3646
|
this._name = name;
|
|
3647
|
+
this.headerCssSelector = headerCssSelector;
|
|
3635
3648
|
this.index = index;
|
|
3636
3649
|
this._caption = caption;
|
|
3637
|
-
this.headerCssSelector = headerCssSelector;
|
|
3638
3650
|
}
|
|
3639
3651
|
set index(index) {
|
|
3640
3652
|
this._index = index;
|
|
@@ -3643,9 +3655,9 @@ var Column = class extends AbstractElementWithParent {
|
|
|
3643
3655
|
get index() {
|
|
3644
3656
|
return this._index;
|
|
3645
3657
|
}
|
|
3646
|
-
async
|
|
3658
|
+
async getLocator() {
|
|
3647
3659
|
await this.getIndex();
|
|
3648
|
-
return this.
|
|
3660
|
+
return this.syncLocator();
|
|
3649
3661
|
}
|
|
3650
3662
|
async getColumnHeaderIndexBy(cssSelector) {
|
|
3651
3663
|
const column = this.page.locator(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`);
|
|
@@ -3658,7 +3670,7 @@ var Column = class extends AbstractElementWithParent {
|
|
|
3658
3670
|
return this.getColumnHeaderIndexBy(getColumnByNameCssSelector(this._name));
|
|
3659
3671
|
}
|
|
3660
3672
|
async caption() {
|
|
3661
|
-
const el = await this.
|
|
3673
|
+
const el = await this.getLocator();
|
|
3662
3674
|
const text = await el.innerText();
|
|
3663
3675
|
return text?.trim() ?? null;
|
|
3664
3676
|
}
|
|
@@ -3723,7 +3735,7 @@ var AbstractDXEditorWithInput = class extends AbstractElementWithParent {
|
|
|
3723
3735
|
async setInputValue(value) {
|
|
3724
3736
|
const input = this.getInputLocator();
|
|
3725
3737
|
await input.click();
|
|
3726
|
-
await input.
|
|
3738
|
+
await input.pressSequentially(value + "");
|
|
3727
3739
|
await input.press("Enter");
|
|
3728
3740
|
}
|
|
3729
3741
|
async clear() {
|
|
@@ -3775,6 +3787,7 @@ var ControlClass = /* @__PURE__ */ ((ControlClass2) => {
|
|
|
3775
3787
|
ControlClass2["BooleanSelector"] = "buttons-group";
|
|
3776
3788
|
ControlClass2["ButtonGroup"] = "button-group-field";
|
|
3777
3789
|
ControlClass2["HeaderFilterDictionary"] = "header-filter-dictionary";
|
|
3790
|
+
ControlClass2["FileUploader"] = "file-uploader";
|
|
3778
3791
|
return ControlClass2;
|
|
3779
3792
|
})(ControlClass || {});
|
|
3780
3793
|
|
|
@@ -3798,7 +3811,7 @@ var CheckBox = class extends AbstractElementWithParent {
|
|
|
3798
3811
|
// src/utils/xpathHelper.ts
|
|
3799
3812
|
var XPathHelper = class {
|
|
3800
3813
|
static getClassAndValueXpath(cssClass, value) {
|
|
3801
|
-
return `div[contains(@class, '${cssClass}') and
|
|
3814
|
+
return `div[contains(@class, '${cssClass}') and .='${value}']`;
|
|
3802
3815
|
}
|
|
3803
3816
|
};
|
|
3804
3817
|
|
|
@@ -4157,7 +4170,12 @@ var FormFilterField = class extends AbstractEditor {
|
|
|
4157
4170
|
formName;
|
|
4158
4171
|
name;
|
|
4159
4172
|
constructor(parentCssSelector, formName, name, page) {
|
|
4160
|
-
super(
|
|
4173
|
+
super({
|
|
4174
|
+
parentCssSelector,
|
|
4175
|
+
elementCssSelector: byTestIdCssSelector(createLayoutFilterTestId(formName, name)),
|
|
4176
|
+
titleCssSelector: byTestIdCssSelector(createLabelLayoutFilterTestId(formName, name)),
|
|
4177
|
+
page
|
|
4178
|
+
});
|
|
4161
4179
|
this.formName = formName;
|
|
4162
4180
|
this.name = name;
|
|
4163
4181
|
}
|
|
@@ -4261,7 +4279,12 @@ var PanelFilterField = class extends AbstractEditor {
|
|
|
4261
4279
|
formName;
|
|
4262
4280
|
name;
|
|
4263
4281
|
constructor(parentCssSelector, formName, name, page) {
|
|
4264
|
-
super(
|
|
4282
|
+
super({
|
|
4283
|
+
parentCssSelector,
|
|
4284
|
+
elementCssSelector: byTestIdCssSelector(createDocFilterTestId(formName, name)),
|
|
4285
|
+
titleCssSelector: byTestIdCssSelector(createLabelDocFilterTestId(formName, name)),
|
|
4286
|
+
page
|
|
4287
|
+
});
|
|
4265
4288
|
this.formName = formName;
|
|
4266
4289
|
this.name = name;
|
|
4267
4290
|
}
|
|
@@ -4510,6 +4533,9 @@ var isDefined = function(value) {
|
|
|
4510
4533
|
var isString = function(object) {
|
|
4511
4534
|
return typeof object === "string";
|
|
4512
4535
|
};
|
|
4536
|
+
var isNumeric = function(object) {
|
|
4537
|
+
return typeof object === "number" && isFinite(object) || !isNaN(object - parseFloat(object));
|
|
4538
|
+
};
|
|
4513
4539
|
var isDate = function(object) {
|
|
4514
4540
|
return type(object) === "date";
|
|
4515
4541
|
};
|
|
@@ -4548,7 +4574,7 @@ var SelectBoxEditor = class extends AbstractDXEditorWithInput {
|
|
|
4548
4574
|
const inputEl = this.getInputLocator();
|
|
4549
4575
|
await inputEl.click();
|
|
4550
4576
|
try {
|
|
4551
|
-
await inputEl.
|
|
4577
|
+
await inputEl.pressSequentially(value + "");
|
|
4552
4578
|
await inputEl.press("Enter");
|
|
4553
4579
|
await dropDownOptionClick(value, this.page, false);
|
|
4554
4580
|
} catch {
|
|
@@ -4632,12 +4658,12 @@ var TagBox = class extends AbstractDXEditorWithInput {
|
|
|
4632
4658
|
try {
|
|
4633
4659
|
await dropDownOptionClick(value, this.page, false);
|
|
4634
4660
|
} catch {
|
|
4635
|
-
await input.
|
|
4661
|
+
await input.pressSequentially(value + "");
|
|
4636
4662
|
await dropDownOptionClick(value, this.page, true);
|
|
4637
4663
|
}
|
|
4638
4664
|
await this.waitOptionSelection(value);
|
|
4639
4665
|
if (value !== lastElement) {
|
|
4640
|
-
await input.
|
|
4666
|
+
await input.pressSequentially("");
|
|
4641
4667
|
}
|
|
4642
4668
|
}
|
|
4643
4669
|
async confirmSelection() {
|
|
@@ -5001,11 +5027,7 @@ var SingleDateEditor = class extends BaseDateEditor {
|
|
|
5001
5027
|
}
|
|
5002
5028
|
async setValue(value) {
|
|
5003
5029
|
if (value instanceof Date) {
|
|
5004
|
-
await
|
|
5005
|
-
await this.setDateValue(value);
|
|
5006
|
-
const updatedValue = await this.getValue();
|
|
5007
|
-
return updatedValue.toDateString() === value.toDateString();
|
|
5008
|
-
}, this.page);
|
|
5030
|
+
await this.setDateValue(value);
|
|
5009
5031
|
} else {
|
|
5010
5032
|
throw new Error(`Value is incorrect. It should be a Date object`);
|
|
5011
5033
|
}
|
|
@@ -5085,12 +5107,11 @@ var DX_TEXTEDITOR_EMPTY3 = "dx-texteditor-empty";
|
|
|
5085
5107
|
var CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
|
|
5086
5108
|
var SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
|
|
5087
5109
|
var TAG_BOX_LIST_ITEM_SELECTOR = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
|
|
5088
|
-
var combinedOptionHeaderFilterDictValueXpath = (value) => `//div[contains(@class, '${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}') and contains(text(), '${value}')]`;
|
|
5089
5110
|
var dropDownHeaderFilterDictionaryOptionClick = async (optionValue, page, dataTEST = "", delay = true) => {
|
|
5090
5111
|
const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
|
|
5091
5112
|
const calendarPopover = page.locator(calendarPopoverSelector);
|
|
5092
5113
|
const customOptionList = calendarPopover.locator(`.${CUSTOM_OPTION_LIST_SELECTOR}`);
|
|
5093
|
-
const optElement = customOptionList.locator(
|
|
5114
|
+
const optElement = customOptionList.locator(`.${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}`, { hasText: optionValue });
|
|
5094
5115
|
try {
|
|
5095
5116
|
await optElement.waitFor({ state: "visible", timeout: delay ? void 0 : 600 });
|
|
5096
5117
|
await optElement.click();
|
|
@@ -5114,28 +5135,28 @@ var HeaderFilterDictionary = class extends AbstractDXEditorWithInput {
|
|
|
5114
5135
|
await this.selectOption(inputEl, value, lastElement);
|
|
5115
5136
|
}
|
|
5116
5137
|
}
|
|
5117
|
-
async waitOptionSelection() {
|
|
5118
|
-
|
|
5119
|
-
await selectedItem.waitFor({ state: "visible" });
|
|
5138
|
+
async waitOptionSelection(value) {
|
|
5139
|
+
await this.page.locator(`${TAG_BOX_LIST_ITEM_SELECTOR}`).filter({ hasText: value }).first().waitFor({ state: "visible" });
|
|
5120
5140
|
}
|
|
5121
5141
|
async selectOption(inputEl, value, lastElement) {
|
|
5122
5142
|
try {
|
|
5123
|
-
await inputEl.
|
|
5143
|
+
await inputEl.pressSequentially(value + "");
|
|
5124
5144
|
const dataTEST = await this.getDataTestId();
|
|
5125
5145
|
await dropDownHeaderFilterDictionaryOptionClick(value, this.page, dataTEST);
|
|
5126
5146
|
if (value !== lastElement) {
|
|
5127
|
-
await inputEl.
|
|
5147
|
+
await inputEl.pressSequentially("");
|
|
5128
5148
|
}
|
|
5129
5149
|
} catch (error) {
|
|
5130
5150
|
throw error;
|
|
5131
5151
|
}
|
|
5132
|
-
await this.waitOptionSelection();
|
|
5152
|
+
await this.waitOptionSelection(value);
|
|
5133
5153
|
}
|
|
5134
5154
|
async getHeaderFilterDictionaryInputValue() {
|
|
5135
5155
|
if (await this.isHeaderFilterDictionaryEmpty()) {
|
|
5136
5156
|
return [];
|
|
5137
5157
|
}
|
|
5138
5158
|
const tags = this.page.locator(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER2} ${TAGS_SELECTOR2}`);
|
|
5159
|
+
await tags.first().waitFor({ state: "visible" });
|
|
5139
5160
|
const count = await tags.count();
|
|
5140
5161
|
const values = [];
|
|
5141
5162
|
for (let i = 0; i < count; i++) {
|
|
@@ -5159,6 +5180,122 @@ var HeaderFilterDictionary = class extends AbstractDXEditorWithInput {
|
|
|
5159
5180
|
}
|
|
5160
5181
|
};
|
|
5161
5182
|
|
|
5183
|
+
// src/pageObjects/elements/Editors/FileUploader.ts
|
|
5184
|
+
var FILE_NAME_SELECTOR = ".file-text";
|
|
5185
|
+
var FILE_SIZE_ATTRIBUTE = "data-filesize";
|
|
5186
|
+
var FILE_DATE_ATTRIBUTE = "data-moddate";
|
|
5187
|
+
var FILE_TYPE_ATTRIBUTE = "data-filetype";
|
|
5188
|
+
var SELECT_FILE_BUTTON_SELECTOR = ".select-file-button";
|
|
5189
|
+
var DOWNLOAD_FILE_BUTTON_SELECTOR = ".download-file-button";
|
|
5190
|
+
var METADATA_SELECTOR = ".file-text-file-info-wrapper";
|
|
5191
|
+
var CLEAR_BUTTON_SELECTOR = ".clear-button";
|
|
5192
|
+
var FileUploader = class extends AbstractElementWithParent {
|
|
5193
|
+
constructor(parentCssSelector, elementCssSelector, page) {
|
|
5194
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
5195
|
+
}
|
|
5196
|
+
/**
|
|
5197
|
+
* Returns the metadata container element for the uploaded file.
|
|
5198
|
+
* Returns null when metadata is not rendered or not visible.
|
|
5199
|
+
*/
|
|
5200
|
+
async getMedataElement() {
|
|
5201
|
+
const root = this.getFullCssSelector();
|
|
5202
|
+
const locator = this.page.locator(`${root} ${METADATA_SELECTOR}`);
|
|
5203
|
+
if (!await locator.isVisible()) return null;
|
|
5204
|
+
return locator;
|
|
5205
|
+
}
|
|
5206
|
+
/**
|
|
5207
|
+
* Returns the name of the uploaded file, or null if not present.
|
|
5208
|
+
*/
|
|
5209
|
+
async getFileName() {
|
|
5210
|
+
const root = this.getFullCssSelector();
|
|
5211
|
+
const locator = this.page.locator(`${root} ${FILE_NAME_SELECTOR}`);
|
|
5212
|
+
if (!await locator.isVisible()) return null;
|
|
5213
|
+
const text = await locator.innerText();
|
|
5214
|
+
return text?.trim() || null;
|
|
5215
|
+
}
|
|
5216
|
+
/**
|
|
5217
|
+
* Returns the size of the uploaded file, or null if not present.
|
|
5218
|
+
*/
|
|
5219
|
+
async getFileSize() {
|
|
5220
|
+
const element = await this.getMedataElement();
|
|
5221
|
+
if (!element) return null;
|
|
5222
|
+
const result = (await element.getAttribute(FILE_SIZE_ATTRIBUTE))?.trim();
|
|
5223
|
+
return isNaN(+result) ? null : +result;
|
|
5224
|
+
}
|
|
5225
|
+
/**
|
|
5226
|
+
* Returns the upload/modification date of the file, or null if not present.
|
|
5227
|
+
*/
|
|
5228
|
+
async getFileDate() {
|
|
5229
|
+
const element = await this.getMedataElement();
|
|
5230
|
+
if (!element) return null;
|
|
5231
|
+
const fileModDate = (await element.getAttribute(FILE_DATE_ATTRIBUTE))?.trim();
|
|
5232
|
+
if (isNumeric(+fileModDate)) {
|
|
5233
|
+
const dateString = (/* @__PURE__ */ new Date(+fileModDate)).toISOString();
|
|
5234
|
+
return new Date(dateString.split("T")[0]);
|
|
5235
|
+
}
|
|
5236
|
+
return fileModDate ? new Date(fileModDate.split("T")[0]) : null;
|
|
5237
|
+
}
|
|
5238
|
+
/**
|
|
5239
|
+
* Returns the MIME/content type of the uploaded file from metadata.
|
|
5240
|
+
* Returns null when the type attribute is absent or empty.
|
|
5241
|
+
*/
|
|
5242
|
+
async getFileType() {
|
|
5243
|
+
const element = await this.getMedataElement();
|
|
5244
|
+
if (!element) return null;
|
|
5245
|
+
const fileType = (await element.getAttribute(FILE_TYPE_ATTRIBUTE))?.trim();
|
|
5246
|
+
return fileType || null;
|
|
5247
|
+
}
|
|
5248
|
+
/**
|
|
5249
|
+
* Returns current file information: name, size and upload/modification date.
|
|
5250
|
+
* Returns null if no file is uploaded.
|
|
5251
|
+
*/
|
|
5252
|
+
async getValue() {
|
|
5253
|
+
const name = await this.getFileName();
|
|
5254
|
+
const size = await this.getFileSize();
|
|
5255
|
+
const date = await this.getFileDate();
|
|
5256
|
+
const type2 = await this.getFileType();
|
|
5257
|
+
if (!name && !size && !date && !type2) return null;
|
|
5258
|
+
return { FileName: name, FileSize: size, FileType: type2, ModDate: date };
|
|
5259
|
+
}
|
|
5260
|
+
/**
|
|
5261
|
+
* Uploads a file by clicking the select-file-button and providing the file path.
|
|
5262
|
+
* @param filePath - Absolute or relative path to the file on disk.
|
|
5263
|
+
*/
|
|
5264
|
+
async setValue(filePath) {
|
|
5265
|
+
const root = this.getFullCssSelector();
|
|
5266
|
+
const fileChooserPromise = this.page.waitForEvent("filechooser");
|
|
5267
|
+
await this.page.locator(`${root} ${SELECT_FILE_BUTTON_SELECTOR}`).click();
|
|
5268
|
+
const fileChooser = await fileChooserPromise;
|
|
5269
|
+
await fileChooser.setFiles(filePath);
|
|
5270
|
+
}
|
|
5271
|
+
/**
|
|
5272
|
+
* Downloads the currently uploaded file by clicking the download-file-button.
|
|
5273
|
+
* Returns the suggested file name of the downloaded file.
|
|
5274
|
+
*/
|
|
5275
|
+
async download() {
|
|
5276
|
+
const root = this.getFullCssSelector();
|
|
5277
|
+
const buttonLocator = this.page.locator(
|
|
5278
|
+
`${root} ${DOWNLOAD_FILE_BUTTON_SELECTOR}`
|
|
5279
|
+
);
|
|
5280
|
+
if (await buttonLocator.isHidden()) return "";
|
|
5281
|
+
const downloadPromise = this.page.waitForEvent("download");
|
|
5282
|
+
await buttonLocator.click();
|
|
5283
|
+
const download = await downloadPromise;
|
|
5284
|
+
return download.suggestedFilename();
|
|
5285
|
+
}
|
|
5286
|
+
/**
|
|
5287
|
+
* Removes the currently uploaded file by clicking the delete-file-button.
|
|
5288
|
+
* Does nothing if no file is uploaded.
|
|
5289
|
+
*/
|
|
5290
|
+
async clear() {
|
|
5291
|
+
if (await this.getValue() === null) return;
|
|
5292
|
+
const root = this.getFullCssSelector();
|
|
5293
|
+
const deleteButton = this.page.locator(`${root} ${CLEAR_BUTTON_SELECTOR}`);
|
|
5294
|
+
if (await deleteButton.isHidden()) return;
|
|
5295
|
+
await deleteButton.click();
|
|
5296
|
+
}
|
|
5297
|
+
};
|
|
5298
|
+
|
|
5162
5299
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
5163
5300
|
var editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
5164
5301
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, page);
|
|
@@ -5180,6 +5317,8 @@ var editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
|
5180
5317
|
return new ButtonGroup(parentCssSelector, elementCssSelector, page);
|
|
5181
5318
|
if (classString.includes("header-filter-dictionary" /* HeaderFilterDictionary */))
|
|
5182
5319
|
return new HeaderFilterDictionary(parentCssSelector, elementCssSelector, page);
|
|
5320
|
+
if (classString.includes("file-uploader" /* FileUploader */))
|
|
5321
|
+
return new FileUploader(parentCssSelector, elementCssSelector, page);
|
|
5183
5322
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
5184
5323
|
};
|
|
5185
5324
|
|
|
@@ -5207,11 +5346,25 @@ var EditorButton = class extends AbstractElementWithParent {
|
|
|
5207
5346
|
}
|
|
5208
5347
|
};
|
|
5209
5348
|
|
|
5349
|
+
// src/pageObjects/elements/EditorTitle.ts
|
|
5350
|
+
var CAPTION_TEXT_CLASS = " .caption-text";
|
|
5351
|
+
var EditorTitle = class extends AbstractElementWithParent {
|
|
5352
|
+
constructor({ parentCssSelector, elementCssSelector, page }) {
|
|
5353
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
5354
|
+
}
|
|
5355
|
+
async getTitle() {
|
|
5356
|
+
const captionElement = this.getLocator().locator(CAPTION_TEXT_CLASS);
|
|
5357
|
+
return captionElement.innerText();
|
|
5358
|
+
}
|
|
5359
|
+
};
|
|
5360
|
+
|
|
5210
5361
|
// src/pageObjects/elements/AbstractEditor.ts
|
|
5211
5362
|
var AbstractEditor = class extends AbstractElementWithParent {
|
|
5212
5363
|
editor;
|
|
5213
|
-
|
|
5364
|
+
_titleCssSelector;
|
|
5365
|
+
constructor({ parentCssSelector, elementCssSelector, titleCssSelector, page }) {
|
|
5214
5366
|
super(parentCssSelector, elementCssSelector, page);
|
|
5367
|
+
this._titleCssSelector = titleCssSelector;
|
|
5215
5368
|
}
|
|
5216
5369
|
async initEditor() {
|
|
5217
5370
|
if (!this.editor) {
|
|
@@ -5307,12 +5460,43 @@ var AbstractEditor = class extends AbstractElementWithParent {
|
|
|
5307
5460
|
button(name) {
|
|
5308
5461
|
return new EditorButton(this.getFullCssSelector(), name, this.page);
|
|
5309
5462
|
}
|
|
5463
|
+
/**
|
|
5464
|
+
* Повертає загловок едітора
|
|
5465
|
+
* @example
|
|
5466
|
+
* expect(await formEdit.field('NumberFld').title()).toBe('Title1');
|
|
5467
|
+
* expect(await formEdit.field('TextFld').title()).toBe('Title2`);
|
|
5468
|
+
*/
|
|
5469
|
+
async title() {
|
|
5470
|
+
return new EditorTitle({
|
|
5471
|
+
elementCssSelector: this._titleCssSelector,
|
|
5472
|
+
parentCssSelector: this.parentCssSelector,
|
|
5473
|
+
page: this.page
|
|
5474
|
+
}).getTitle();
|
|
5475
|
+
}
|
|
5476
|
+
/**
|
|
5477
|
+
* Вивантажує файл і повертає назву файла. Доступний тільки для поля FileUploader.
|
|
5478
|
+
* @example
|
|
5479
|
+
* const fileName = await formEdit.field('FileField').downloadFile();
|
|
5480
|
+
* expect(filename()).toBe('file.pdf');
|
|
5481
|
+
*/
|
|
5482
|
+
async download() {
|
|
5483
|
+
await this.initEditor();
|
|
5484
|
+
if (!this.editor.download) {
|
|
5485
|
+
throw new Error("download is only available for the FileUploader field type.");
|
|
5486
|
+
}
|
|
5487
|
+
return this.editor.download();
|
|
5488
|
+
}
|
|
5310
5489
|
};
|
|
5311
5490
|
|
|
5312
5491
|
// src/pageObjects/elements/FormField.ts
|
|
5313
5492
|
var FormField = class extends AbstractEditor {
|
|
5314
5493
|
constructor(parentCssSelector, formName, name, page) {
|
|
5315
|
-
super(
|
|
5494
|
+
super({
|
|
5495
|
+
parentCssSelector,
|
|
5496
|
+
elementCssSelector: byTestIdCssSelector(createFieldTestId(formName, name)),
|
|
5497
|
+
titleCssSelector: byTestIdCssSelector(createLabelFieldTestId(formName, name)),
|
|
5498
|
+
page
|
|
5499
|
+
});
|
|
5316
5500
|
}
|
|
5317
5501
|
};
|
|
5318
5502
|
|
|
@@ -5449,6 +5633,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
5449
5633
|
this.getRowByIndex(index);
|
|
5450
5634
|
return new Column({
|
|
5451
5635
|
parentCssSelector: this.getFullCssSelector(),
|
|
5636
|
+
headerCssSelector: this.headerCssSelector,
|
|
5452
5637
|
page: this.page,
|
|
5453
5638
|
index
|
|
5454
5639
|
});
|
|
@@ -5561,7 +5746,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
5561
5746
|
[row] = await this.getSelectedRows();
|
|
5562
5747
|
}
|
|
5563
5748
|
if (!row) throw new Error("No row available row for context menu");
|
|
5564
|
-
const cellElement = await row.getCell(fieldName).
|
|
5749
|
+
const cellElement = await row.getCell(fieldName).getLocator();
|
|
5565
5750
|
await cellElement.click({ button: "right" });
|
|
5566
5751
|
});
|
|
5567
5752
|
}
|
|
@@ -5620,10 +5805,14 @@ var Table = class extends AbstractElementWithParent {
|
|
|
5620
5805
|
* console.log('Таблиця містить 5 рядків');
|
|
5621
5806
|
*/
|
|
5622
5807
|
async waitRowsCount(count) {
|
|
5623
|
-
await wait(
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5808
|
+
await wait(
|
|
5809
|
+
async () => {
|
|
5810
|
+
const rowsCount = await this.getRowElements().count();
|
|
5811
|
+
return rowsCount === count;
|
|
5812
|
+
},
|
|
5813
|
+
this.page,
|
|
5814
|
+
`Rows count not equal: ${count}`
|
|
5815
|
+
);
|
|
5627
5816
|
}
|
|
5628
5817
|
};
|
|
5629
5818
|
|
|
@@ -5845,7 +6034,10 @@ var ToolbarItem = class extends AbstractElementWithParent {
|
|
|
5845
6034
|
async click() {
|
|
5846
6035
|
try {
|
|
5847
6036
|
await this.init();
|
|
5848
|
-
await
|
|
6037
|
+
await wait(async () => {
|
|
6038
|
+
const element = this._button.getLocator();
|
|
6039
|
+
return await element.isEnabled() && await element.isVisible();
|
|
6040
|
+
}, this.page);
|
|
5849
6041
|
await this._button.click();
|
|
5850
6042
|
} catch (error) {
|
|
5851
6043
|
throw new Error(`Cannot click on toolbar item: ${this._itemName}`);
|
|
@@ -5905,7 +6097,12 @@ var FormToolbar = class extends AbstractElementWithParent {
|
|
|
5905
6097
|
// src/pageObjects/elements/Filters/HeaderFilterField.ts
|
|
5906
6098
|
var HeaderFilterField = class extends AbstractEditor {
|
|
5907
6099
|
constructor(parentCssSelector, formName, name, page) {
|
|
5908
|
-
super(
|
|
6100
|
+
super({
|
|
6101
|
+
parentCssSelector,
|
|
6102
|
+
elementCssSelector: byTestIdCssSelector(createHeaderFilterTestId(formName, name)),
|
|
6103
|
+
titleCssSelector: "",
|
|
6104
|
+
page
|
|
6105
|
+
});
|
|
5909
6106
|
}
|
|
5910
6107
|
async getValue() {
|
|
5911
6108
|
return super.getValue();
|
|
@@ -5957,7 +6154,7 @@ var ColumnFilter = class {
|
|
|
5957
6154
|
await this.getCancelButton().click();
|
|
5958
6155
|
}
|
|
5959
6156
|
async initFilter() {
|
|
5960
|
-
const columnEl = await this._column.
|
|
6157
|
+
const columnEl = await this._column.getLocator();
|
|
5961
6158
|
await columnEl.hover();
|
|
5962
6159
|
const headerFilterIcon = columnEl.locator(HEADER_FILTER_ICON);
|
|
5963
6160
|
await headerFilterIcon.waitFor({ state: "visible" });
|