d5-testing-library 2.0.0-alpha.7 → 2.0.0-alpha.9
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/dist/{FormEdit-3SOUFQYD.mjs → FormEdit-6RENNFXE.mjs} +1 -1
- package/dist/{ListForm-5PVPUASR.mjs → ListForm-DFVWW3GH.mjs} +1 -1
- package/dist/{TreeView-Q2LHHV2B.mjs → TreeView-DQ3DAI2C.mjs} +1 -1
- package/dist/{chunk-WQR3N5X2.mjs → chunk-ZSUCWPIH.mjs} +136 -9
- package/dist/cjs/d5-testing-library.cjs +142 -7
- package/dist/cjs/d5-testing-library.d.ts +10 -1
- package/dist/d5-testing-library.d.mts +10 -1
- package/dist/d5-testing-library.legacy-esm.js +1 -1
- package/dist/d5-testing-library.mjs +1 -1
- package/package.json +1 -1
|
@@ -3320,15 +3320,15 @@ async function classDependencyInjector(formType) {
|
|
|
3320
3320
|
let SubFormFactoryClass;
|
|
3321
3321
|
switch (formType) {
|
|
3322
3322
|
case "1" /* LIST */:
|
|
3323
|
-
SubFormFactoryClass = (await import("./ListForm-
|
|
3323
|
+
SubFormFactoryClass = (await import("./ListForm-DFVWW3GH.mjs")).default;
|
|
3324
3324
|
break;
|
|
3325
3325
|
case "3" /* TREE */:
|
|
3326
|
-
SubFormFactoryClass = (await import("./TreeView-
|
|
3326
|
+
SubFormFactoryClass = (await import("./TreeView-DQ3DAI2C.mjs")).default;
|
|
3327
3327
|
break;
|
|
3328
3328
|
case "2" /* EDIT */:
|
|
3329
3329
|
case "99" /* FREE_FORM */:
|
|
3330
3330
|
case "4" /* REPORT */:
|
|
3331
|
-
SubFormFactoryClass = (await import("./FormEdit-
|
|
3331
|
+
SubFormFactoryClass = (await import("./FormEdit-6RENNFXE.mjs")).default;
|
|
3332
3332
|
break;
|
|
3333
3333
|
default:
|
|
3334
3334
|
throw new Error(`Unsupported form type ${formType}`);
|
|
@@ -3787,6 +3787,7 @@ var ControlClass = /* @__PURE__ */ ((ControlClass2) => {
|
|
|
3787
3787
|
ControlClass2["BooleanSelector"] = "buttons-group";
|
|
3788
3788
|
ControlClass2["ButtonGroup"] = "button-group-field";
|
|
3789
3789
|
ControlClass2["HeaderFilterDictionary"] = "header-filter-dictionary";
|
|
3790
|
+
ControlClass2["FileUploader"] = "file-uploader";
|
|
3790
3791
|
return ControlClass2;
|
|
3791
3792
|
})(ControlClass || {});
|
|
3792
3793
|
|
|
@@ -5103,12 +5104,11 @@ var DX_TEXTEDITOR_EMPTY3 = "dx-texteditor-empty";
|
|
|
5103
5104
|
var CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
|
|
5104
5105
|
var SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
|
|
5105
5106
|
var TAG_BOX_LIST_ITEM_SELECTOR = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
|
|
5106
|
-
var combinedOptionHeaderFilterDictValueXpath = (value) => `//div[contains(@class, '${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}') and contains(text(), '${value}')]`;
|
|
5107
5107
|
var dropDownHeaderFilterDictionaryOptionClick = async (optionValue, page, dataTEST = "", delay = true) => {
|
|
5108
5108
|
const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
|
|
5109
5109
|
const calendarPopover = page.locator(calendarPopoverSelector);
|
|
5110
5110
|
const customOptionList = calendarPopover.locator(`.${CUSTOM_OPTION_LIST_SELECTOR}`);
|
|
5111
|
-
const optElement = customOptionList.locator(
|
|
5111
|
+
const optElement = customOptionList.locator(`.${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}`, { hasText: optionValue });
|
|
5112
5112
|
try {
|
|
5113
5113
|
await optElement.waitFor({ state: "visible", timeout: delay ? void 0 : 600 });
|
|
5114
5114
|
await optElement.click();
|
|
@@ -5132,9 +5132,8 @@ var HeaderFilterDictionary = class extends AbstractDXEditorWithInput {
|
|
|
5132
5132
|
await this.selectOption(inputEl, value, lastElement);
|
|
5133
5133
|
}
|
|
5134
5134
|
}
|
|
5135
|
-
async waitOptionSelection() {
|
|
5136
|
-
|
|
5137
|
-
await selectedItem.waitFor({ state: "visible" });
|
|
5135
|
+
async waitOptionSelection(value) {
|
|
5136
|
+
await this.page.locator(`${TAG_BOX_LIST_ITEM_SELECTOR}`).filter({ hasText: value }).first().waitFor({ state: "visible" });
|
|
5138
5137
|
}
|
|
5139
5138
|
async selectOption(inputEl, value, lastElement) {
|
|
5140
5139
|
try {
|
|
@@ -5147,13 +5146,14 @@ var HeaderFilterDictionary = class extends AbstractDXEditorWithInput {
|
|
|
5147
5146
|
} catch (error) {
|
|
5148
5147
|
throw error;
|
|
5149
5148
|
}
|
|
5150
|
-
await this.waitOptionSelection();
|
|
5149
|
+
await this.waitOptionSelection(value);
|
|
5151
5150
|
}
|
|
5152
5151
|
async getHeaderFilterDictionaryInputValue() {
|
|
5153
5152
|
if (await this.isHeaderFilterDictionaryEmpty()) {
|
|
5154
5153
|
return [];
|
|
5155
5154
|
}
|
|
5156
5155
|
const tags = this.page.locator(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER2} ${TAGS_SELECTOR2}`);
|
|
5156
|
+
await tags.first().waitFor({ state: "visible" });
|
|
5157
5157
|
const count = await tags.count();
|
|
5158
5158
|
const values = [];
|
|
5159
5159
|
for (let i = 0; i < count; i++) {
|
|
@@ -5177,6 +5177,118 @@ var HeaderFilterDictionary = class extends AbstractDXEditorWithInput {
|
|
|
5177
5177
|
}
|
|
5178
5178
|
};
|
|
5179
5179
|
|
|
5180
|
+
// src/pageObjects/elements/Editors/FileUploader.ts
|
|
5181
|
+
var FILE_NAME_SELECTOR = ".file-text";
|
|
5182
|
+
var FILE_SIZE_ATTRIBUTE = "data-filesize";
|
|
5183
|
+
var FILE_DATE_ATTRIBUTE = "data-moddate";
|
|
5184
|
+
var FILE_TYPE_ATTRIBUTE = "data-filetype";
|
|
5185
|
+
var SELECT_FILE_BUTTON_SELECTOR = ".select-file-button";
|
|
5186
|
+
var DOWNLOAD_FILE_BUTTON_SELECTOR = ".download-file-button";
|
|
5187
|
+
var METADATA_SELECTOR = ".file-text-file-info-wrapper";
|
|
5188
|
+
var CLEAR_BUTTON_SELECTOR = ".clear-button";
|
|
5189
|
+
var FileUploader = class extends AbstractElementWithParent {
|
|
5190
|
+
constructor(parentCssSelector, elementCssSelector, page) {
|
|
5191
|
+
super(parentCssSelector, elementCssSelector, page);
|
|
5192
|
+
}
|
|
5193
|
+
/**
|
|
5194
|
+
* Returns the metadata container element for the uploaded file.
|
|
5195
|
+
* Returns null when metadata is not rendered or not visible.
|
|
5196
|
+
*/
|
|
5197
|
+
async getMedataElement() {
|
|
5198
|
+
const root = this.getFullCssSelector();
|
|
5199
|
+
const locator = this.page.locator(`${root} ${METADATA_SELECTOR}`);
|
|
5200
|
+
if (!await locator.isVisible()) return null;
|
|
5201
|
+
return locator;
|
|
5202
|
+
}
|
|
5203
|
+
/**
|
|
5204
|
+
* Returns the name of the uploaded file, or null if not present.
|
|
5205
|
+
*/
|
|
5206
|
+
async getFileName() {
|
|
5207
|
+
const root = this.getFullCssSelector();
|
|
5208
|
+
const locator = this.page.locator(`${root} ${FILE_NAME_SELECTOR}`);
|
|
5209
|
+
if (!await locator.isVisible()) return null;
|
|
5210
|
+
const text = await locator.innerText();
|
|
5211
|
+
return text?.trim() || null;
|
|
5212
|
+
}
|
|
5213
|
+
/**
|
|
5214
|
+
* Returns the size of the uploaded file, or null if not present.
|
|
5215
|
+
*/
|
|
5216
|
+
async getFileSize() {
|
|
5217
|
+
const element = await this.getMedataElement();
|
|
5218
|
+
if (!element) return null;
|
|
5219
|
+
const result = (await element.getAttribute(FILE_SIZE_ATTRIBUTE))?.trim();
|
|
5220
|
+
return isNaN(+result) ? null : +result;
|
|
5221
|
+
}
|
|
5222
|
+
/**
|
|
5223
|
+
* Returns the upload/modification date of the file, or null if not present.
|
|
5224
|
+
*/
|
|
5225
|
+
async getFileDate() {
|
|
5226
|
+
const element = await this.getMedataElement();
|
|
5227
|
+
if (!element) return null;
|
|
5228
|
+
const fileModDate = (await element.getAttribute(FILE_DATE_ATTRIBUTE))?.trim();
|
|
5229
|
+
return fileModDate ? new Date(fileModDate) : null;
|
|
5230
|
+
}
|
|
5231
|
+
/**
|
|
5232
|
+
* Returns the MIME/content type of the uploaded file from metadata.
|
|
5233
|
+
* Returns null when the type attribute is absent or empty.
|
|
5234
|
+
*/
|
|
5235
|
+
async getFileType() {
|
|
5236
|
+
const element = await this.getMedataElement();
|
|
5237
|
+
if (!element) return null;
|
|
5238
|
+
const fileType = (await element.getAttribute(FILE_TYPE_ATTRIBUTE))?.trim();
|
|
5239
|
+
return fileType || null;
|
|
5240
|
+
}
|
|
5241
|
+
/**
|
|
5242
|
+
* Returns current file information: name, size and upload/modification date.
|
|
5243
|
+
* Returns null if no file is uploaded.
|
|
5244
|
+
*/
|
|
5245
|
+
async getValue() {
|
|
5246
|
+
const name = await this.getFileName();
|
|
5247
|
+
const size = await this.getFileSize();
|
|
5248
|
+
const date = await this.getFileDate();
|
|
5249
|
+
const type2 = await this.getFileType();
|
|
5250
|
+
if (!name && !size && !date && !type2) return null;
|
|
5251
|
+
return { FileName: name, FileSize: size, FileType: type2, ModDate: date };
|
|
5252
|
+
}
|
|
5253
|
+
/**
|
|
5254
|
+
* Uploads a file by clicking the select-file-button and providing the file path.
|
|
5255
|
+
* @param filePath - Absolute or relative path to the file on disk.
|
|
5256
|
+
*/
|
|
5257
|
+
async setValue(filePath) {
|
|
5258
|
+
const root = this.getFullCssSelector();
|
|
5259
|
+
const fileChooserPromise = this.page.waitForEvent("filechooser");
|
|
5260
|
+
await this.page.locator(`${root} ${SELECT_FILE_BUTTON_SELECTOR}`).click();
|
|
5261
|
+
const fileChooser = await fileChooserPromise;
|
|
5262
|
+
await fileChooser.setFiles(filePath);
|
|
5263
|
+
}
|
|
5264
|
+
/**
|
|
5265
|
+
* Downloads the currently uploaded file by clicking the download-file-button.
|
|
5266
|
+
* Returns the suggested file name of the downloaded file.
|
|
5267
|
+
*/
|
|
5268
|
+
async download() {
|
|
5269
|
+
const root = this.getFullCssSelector();
|
|
5270
|
+
const buttonLocator = this.page.locator(
|
|
5271
|
+
`${root} ${DOWNLOAD_FILE_BUTTON_SELECTOR}`
|
|
5272
|
+
);
|
|
5273
|
+
if (await buttonLocator.isHidden()) return "";
|
|
5274
|
+
const downloadPromise = this.page.waitForEvent("download");
|
|
5275
|
+
await buttonLocator.click();
|
|
5276
|
+
const download = await downloadPromise;
|
|
5277
|
+
return download.suggestedFilename();
|
|
5278
|
+
}
|
|
5279
|
+
/**
|
|
5280
|
+
* Removes the currently uploaded file by clicking the delete-file-button.
|
|
5281
|
+
* Does nothing if no file is uploaded.
|
|
5282
|
+
*/
|
|
5283
|
+
async clear() {
|
|
5284
|
+
if (await this.getValue() === null) return;
|
|
5285
|
+
const root = this.getFullCssSelector();
|
|
5286
|
+
const deleteButton = this.page.locator(`${root} ${CLEAR_BUTTON_SELECTOR}`);
|
|
5287
|
+
if (await deleteButton.isHidden()) return;
|
|
5288
|
+
await deleteButton.click();
|
|
5289
|
+
}
|
|
5290
|
+
};
|
|
5291
|
+
|
|
5180
5292
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
5181
5293
|
var editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
5182
5294
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, page);
|
|
@@ -5198,6 +5310,8 @@ var editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
|
5198
5310
|
return new ButtonGroup(parentCssSelector, elementCssSelector, page);
|
|
5199
5311
|
if (classString.includes("header-filter-dictionary" /* HeaderFilterDictionary */))
|
|
5200
5312
|
return new HeaderFilterDictionary(parentCssSelector, elementCssSelector, page);
|
|
5313
|
+
if (classString.includes("file-uploader" /* FileUploader */))
|
|
5314
|
+
return new FileUploader(parentCssSelector, elementCssSelector, page);
|
|
5201
5315
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
5202
5316
|
};
|
|
5203
5317
|
|
|
@@ -5352,6 +5466,19 @@ var AbstractEditor = class extends AbstractElementWithParent {
|
|
|
5352
5466
|
page: this.page
|
|
5353
5467
|
}).getTitle();
|
|
5354
5468
|
}
|
|
5469
|
+
/**
|
|
5470
|
+
* Вивантажує файл і повертає назву файла. Доступний тільки для поля FileUploader.
|
|
5471
|
+
* @example
|
|
5472
|
+
* const fileName = await formEdit.field('FileField').downloadFile();
|
|
5473
|
+
* expect(filename()).toBe('file.pdf');
|
|
5474
|
+
*/
|
|
5475
|
+
async download() {
|
|
5476
|
+
await this.initEditor();
|
|
5477
|
+
if (!this.editor.download) {
|
|
5478
|
+
throw new Error("download is only available for the FileUploader field type.");
|
|
5479
|
+
}
|
|
5480
|
+
return this.editor.download();
|
|
5481
|
+
}
|
|
5355
5482
|
};
|
|
5356
5483
|
|
|
5357
5484
|
// src/pageObjects/elements/FormField.ts
|
|
@@ -406,6 +406,7 @@ var init_types = __esm({
|
|
|
406
406
|
ControlClass2["BooleanSelector"] = "buttons-group";
|
|
407
407
|
ControlClass2["ButtonGroup"] = "button-group-field";
|
|
408
408
|
ControlClass2["HeaderFilterDictionary"] = "header-filter-dictionary";
|
|
409
|
+
ControlClass2["FileUploader"] = "file-uploader";
|
|
409
410
|
return ControlClass2;
|
|
410
411
|
})(ControlClass || {});
|
|
411
412
|
}
|
|
@@ -1178,7 +1179,7 @@ var init_DateEditor = __esm({
|
|
|
1178
1179
|
});
|
|
1179
1180
|
|
|
1180
1181
|
// src/pageObjects/elements/Editors/HeaderFilterDictionary.ts
|
|
1181
|
-
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;
|
|
1182
1183
|
var init_HeaderFilterDictionary = __esm({
|
|
1183
1184
|
"src/pageObjects/elements/Editors/HeaderFilterDictionary.ts"() {
|
|
1184
1185
|
"use strict";
|
|
@@ -1191,12 +1192,11 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1191
1192
|
CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
|
|
1192
1193
|
SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
|
|
1193
1194
|
TAG_BOX_LIST_ITEM_SELECTOR = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
|
|
1194
|
-
combinedOptionHeaderFilterDictValueXpath = (value) => `//div[contains(@class, '${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}') and contains(text(), '${value}')]`;
|
|
1195
1195
|
dropDownHeaderFilterDictionaryOptionClick = async (optionValue, page, dataTEST = "", delay = true) => {
|
|
1196
1196
|
const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
|
|
1197
1197
|
const calendarPopover = page.locator(calendarPopoverSelector);
|
|
1198
1198
|
const customOptionList = calendarPopover.locator(`.${CUSTOM_OPTION_LIST_SELECTOR}`);
|
|
1199
|
-
const optElement = customOptionList.locator(
|
|
1199
|
+
const optElement = customOptionList.locator(`.${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}`, { hasText: optionValue });
|
|
1200
1200
|
try {
|
|
1201
1201
|
await optElement.waitFor({ state: "visible", timeout: delay ? void 0 : 600 });
|
|
1202
1202
|
await optElement.click();
|
|
@@ -1220,9 +1220,8 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1220
1220
|
await this.selectOption(inputEl, value, lastElement);
|
|
1221
1221
|
}
|
|
1222
1222
|
}
|
|
1223
|
-
async waitOptionSelection() {
|
|
1224
|
-
|
|
1225
|
-
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" });
|
|
1226
1225
|
}
|
|
1227
1226
|
async selectOption(inputEl, value, lastElement) {
|
|
1228
1227
|
try {
|
|
@@ -1235,13 +1234,14 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1235
1234
|
} catch (error) {
|
|
1236
1235
|
throw error;
|
|
1237
1236
|
}
|
|
1238
|
-
await this.waitOptionSelection();
|
|
1237
|
+
await this.waitOptionSelection(value);
|
|
1239
1238
|
}
|
|
1240
1239
|
async getHeaderFilterDictionaryInputValue() {
|
|
1241
1240
|
if (await this.isHeaderFilterDictionaryEmpty()) {
|
|
1242
1241
|
return [];
|
|
1243
1242
|
}
|
|
1244
1243
|
const tags = this.page.locator(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER2} ${TAGS_SELECTOR2}`);
|
|
1244
|
+
await tags.first().waitFor({ state: "visible" });
|
|
1245
1245
|
const count = await tags.count();
|
|
1246
1246
|
const values = [];
|
|
1247
1247
|
for (let i = 0; i < count; i++) {
|
|
@@ -1267,6 +1267,125 @@ var init_HeaderFilterDictionary = __esm({
|
|
|
1267
1267
|
}
|
|
1268
1268
|
});
|
|
1269
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
|
+
|
|
1270
1389
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
1271
1390
|
var editorFactory;
|
|
1272
1391
|
var init_editorFactory = __esm({
|
|
@@ -1284,6 +1403,7 @@ var init_editorFactory = __esm({
|
|
|
1284
1403
|
init_ButtonGroup();
|
|
1285
1404
|
init_DateEditor();
|
|
1286
1405
|
init_HeaderFilterDictionary();
|
|
1406
|
+
init_FileUploader();
|
|
1287
1407
|
editorFactory = async (parentCssSelector, elementCssSelector, page) => {
|
|
1288
1408
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, page);
|
|
1289
1409
|
const classString = await elementInstance.getClasses();
|
|
@@ -1304,6 +1424,8 @@ var init_editorFactory = __esm({
|
|
|
1304
1424
|
return new ButtonGroup(parentCssSelector, elementCssSelector, page);
|
|
1305
1425
|
if (classString.includes("header-filter-dictionary" /* HeaderFilterDictionary */))
|
|
1306
1426
|
return new HeaderFilterDictionary(parentCssSelector, elementCssSelector, page);
|
|
1427
|
+
if (classString.includes("file-uploader" /* FileUploader */))
|
|
1428
|
+
return new FileUploader(parentCssSelector, elementCssSelector, page);
|
|
1307
1429
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
1308
1430
|
};
|
|
1309
1431
|
}
|
|
@@ -2379,6 +2501,19 @@ var init_AbstractEditor2 = __esm({
|
|
|
2379
2501
|
page: this.page
|
|
2380
2502
|
}).getTitle();
|
|
2381
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
|
+
}
|
|
2382
2517
|
};
|
|
2383
2518
|
}
|
|
2384
2519
|
});
|
|
@@ -96,6 +96,7 @@ interface Editor {
|
|
|
96
96
|
clear?(): Promise<void>;
|
|
97
97
|
isReadonly?(): Promise<boolean>;
|
|
98
98
|
isDisabled?(): Promise<boolean>;
|
|
99
|
+
download?(): Promise<string>;
|
|
99
100
|
}
|
|
100
101
|
declare enum ControlClass {
|
|
101
102
|
Text = "text-control",
|
|
@@ -109,7 +110,8 @@ declare enum ControlClass {
|
|
|
109
110
|
SingleDateRange = "single-date-range-control",
|
|
110
111
|
BooleanSelector = "buttons-group",
|
|
111
112
|
ButtonGroup = "button-group-field",
|
|
112
|
-
HeaderFilterDictionary = "header-filter-dictionary"
|
|
113
|
+
HeaderFilterDictionary = "header-filter-dictionary",
|
|
114
|
+
FileUploader = "file-uploader"
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
interface ClearStrategy {
|
|
@@ -418,6 +420,13 @@ declare class AbstractEditor extends AbstractElementWithParent implements Editor
|
|
|
418
420
|
* expect(await formEdit.field('TextFld').title()).toBe('Title2`);
|
|
419
421
|
*/
|
|
420
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>;
|
|
421
430
|
}
|
|
422
431
|
|
|
423
432
|
declare class FormField extends AbstractEditor {
|
|
@@ -96,6 +96,7 @@ interface Editor {
|
|
|
96
96
|
clear?(): Promise<void>;
|
|
97
97
|
isReadonly?(): Promise<boolean>;
|
|
98
98
|
isDisabled?(): Promise<boolean>;
|
|
99
|
+
download?(): Promise<string>;
|
|
99
100
|
}
|
|
100
101
|
declare enum ControlClass {
|
|
101
102
|
Text = "text-control",
|
|
@@ -109,7 +110,8 @@ declare enum ControlClass {
|
|
|
109
110
|
SingleDateRange = "single-date-range-control",
|
|
110
111
|
BooleanSelector = "buttons-group",
|
|
111
112
|
ButtonGroup = "button-group-field",
|
|
112
|
-
HeaderFilterDictionary = "header-filter-dictionary"
|
|
113
|
+
HeaderFilterDictionary = "header-filter-dictionary",
|
|
114
|
+
FileUploader = "file-uploader"
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
interface ClearStrategy {
|
|
@@ -418,6 +420,13 @@ declare class AbstractEditor extends AbstractElementWithParent implements Editor
|
|
|
418
420
|
* expect(await formEdit.field('TextFld').title()).toBe('Title2`);
|
|
419
421
|
*/
|
|
420
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>;
|
|
421
430
|
}
|
|
422
431
|
|
|
423
432
|
declare class FormField extends AbstractEditor {
|