d5-testing-library 1.9.0 → 2.0.0-alpha.1
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-I63LWQEH.mjs +6 -0
- package/dist/ListForm-NEBCZD4X.mjs +6 -0
- package/dist/TreeView-T3PIDSZQ.mjs +6 -0
- package/dist/chunk-75NROWLM.mjs +6193 -0
- package/dist/cjs/d5-testing-library.cjs +1175 -1473
- package/dist/cjs/d5-testing-library.d.ts +126 -160
- package/dist/d5-testing-library.d.mts +126 -160
- package/dist/d5-testing-library.legacy-esm.js +14 -3174
- package/dist/d5-testing-library.mjs +14 -3174
- package/package.json +2 -1
- package/dist/FormEdit-VFV53QIZ.mjs +0 -7
- package/dist/ListForm-KIHLT7EU.mjs +0 -7
- package/dist/TreeView-TFBZB2UK.mjs +0 -8
- package/dist/chunk-EFNMD3S7.mjs +0 -22
- package/dist/chunk-GVYXH7L3.mjs +0 -75
- package/dist/chunk-RPSLW2WB.mjs +0 -1722
- package/dist/chunk-TSE33S3X.mjs +0 -1555
package/dist/chunk-TSE33S3X.mjs
DELETED
|
@@ -1,1555 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AbstractButton,
|
|
3
|
-
AbstractEditor,
|
|
4
|
-
AbstractElement,
|
|
5
|
-
AbstractElementWithParent,
|
|
6
|
-
Form,
|
|
7
|
-
FormField,
|
|
8
|
-
byTestId,
|
|
9
|
-
byTestIdCssSelector,
|
|
10
|
-
click,
|
|
11
|
-
contextMenu,
|
|
12
|
-
createDocFilterTestId,
|
|
13
|
-
createHeaderFilterTestId,
|
|
14
|
-
createLayoutFilterTestId,
|
|
15
|
-
createTableId,
|
|
16
|
-
fixElementStaleError,
|
|
17
|
-
safeWait,
|
|
18
|
-
staleElementAction,
|
|
19
|
-
waitElementIsClickable_default,
|
|
20
|
-
waitElementIsVisible_default,
|
|
21
|
-
withCustomTimeouts_default
|
|
22
|
-
} from "./chunk-RPSLW2WB.mjs";
|
|
23
|
-
|
|
24
|
-
// src/pageObjects/elements/Table/Table.ts
|
|
25
|
-
import { By as By6 } from "selenium-webdriver";
|
|
26
|
-
|
|
27
|
-
// src/pageObjects/elements/Table/elements/Row.ts
|
|
28
|
-
import { By as By3, Key } from "selenium-webdriver";
|
|
29
|
-
|
|
30
|
-
// src/pageObjects/elements/Table/elements/Cell.ts
|
|
31
|
-
import { By as By2 } from "selenium-webdriver";
|
|
32
|
-
|
|
33
|
-
// src/pageObjects/elements/Table/utils.ts
|
|
34
|
-
import { By } from "selenium-webdriver";
|
|
35
|
-
function getCssRowByIndexSelector(index) {
|
|
36
|
-
return `tr[aria-rowindex="${transformInputIndex(index)}"]`;
|
|
37
|
-
}
|
|
38
|
-
var getColumnByIndexCssSelector = (columnIndex) => `td[aria-colindex="${transformInputIndex(columnIndex)}"]`;
|
|
39
|
-
var getColumnByCaptionCssSelector = (caption) => `td[role="columnheader"][aria-label="Column ${caption}"]`;
|
|
40
|
-
var getColumnByNameCssSelector = (name) => `td[role="columnheader"][data-fieldname="${name}"]`;
|
|
41
|
-
function getCssCellByIndexSelector(index) {
|
|
42
|
-
return `td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`;
|
|
43
|
-
}
|
|
44
|
-
var transformInputIndex = (index) => index + 1;
|
|
45
|
-
var transformOutputIndex = (index) => +index - 1;
|
|
46
|
-
|
|
47
|
-
// src/pageObjects/elements/Table/elements/Cell.ts
|
|
48
|
-
var Cell = class extends AbstractElementWithParent {
|
|
49
|
-
_index;
|
|
50
|
-
getCellIndex;
|
|
51
|
-
constructor(parentCssSelector, getCellIndex, driver, index) {
|
|
52
|
-
super(parentCssSelector, getCssCellByIndexSelector(index), driver);
|
|
53
|
-
this.getCellIndex = getCellIndex;
|
|
54
|
-
this._index = index;
|
|
55
|
-
}
|
|
56
|
-
set index(index) {
|
|
57
|
-
this._index = index;
|
|
58
|
-
this.elementCssSelector = getCssCellByIndexSelector(index);
|
|
59
|
-
}
|
|
60
|
-
async getBooleanValue(cellEl) {
|
|
61
|
-
const booleanEl = await cellEl.findElement(By2.className("boolean-widget"));
|
|
62
|
-
return await booleanEl.getAttribute("aria-checked") === "true" ? 1 : 0;
|
|
63
|
-
}
|
|
64
|
-
async getTagsValue(cellEl) {
|
|
65
|
-
const tagsCssSelector = ".multiselect-container .multiselect-cell";
|
|
66
|
-
const tags = await cellEl.findElements(By2.css(tagsCssSelector));
|
|
67
|
-
const values = [];
|
|
68
|
-
for (const tag of tags) {
|
|
69
|
-
values.push(await tag.getAttribute("textContent"));
|
|
70
|
-
}
|
|
71
|
-
return values.length ? values : null;
|
|
72
|
-
}
|
|
73
|
-
async getNumberValue(cellEl) {
|
|
74
|
-
const value = (await cellEl.getText()).trim();
|
|
75
|
-
return value == "" ? null : Number.parseFloat(value);
|
|
76
|
-
}
|
|
77
|
-
async getDateValue(cellEl, cellElClass) {
|
|
78
|
-
const value = (await cellEl.getText()).trim();
|
|
79
|
-
if (value === "") return null;
|
|
80
|
-
const getDate = (stringDate) => {
|
|
81
|
-
const isWithTime = cellElClass.includes("with-time");
|
|
82
|
-
try {
|
|
83
|
-
if (isWithTime) {
|
|
84
|
-
const [datePart, timePart] = stringDate.split(", ");
|
|
85
|
-
const [day, month, year] = datePart.split(".").map(Number);
|
|
86
|
-
const [hours, minutes] = timePart.split(":").map(Number);
|
|
87
|
-
return new Date(year, month - 1, day, hours, minutes, 0, 0);
|
|
88
|
-
} else {
|
|
89
|
-
const [day, month, year] = stringDate.split(".").map(Number);
|
|
90
|
-
return new Date(Date.UTC(year, month - 1, day));
|
|
91
|
-
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error(`Error parsing date value "${stringDate}":`, error);
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
const periodValue = value.split(" - ");
|
|
98
|
-
if (periodValue.length > 1) {
|
|
99
|
-
const dateFrom = getDate(periodValue[0]);
|
|
100
|
-
const dateTo = getDate(periodValue[1]);
|
|
101
|
-
return [dateFrom, dateTo];
|
|
102
|
-
}
|
|
103
|
-
return getDate(value);
|
|
104
|
-
}
|
|
105
|
-
async getElement() {
|
|
106
|
-
if (this._index == null) {
|
|
107
|
-
this.index = await this.getCellIndex();
|
|
108
|
-
}
|
|
109
|
-
return super.getElement();
|
|
110
|
-
}
|
|
111
|
-
async getValue() {
|
|
112
|
-
const cellEl = await this.getElement();
|
|
113
|
-
const cellElClass = await cellEl.getAttribute("class");
|
|
114
|
-
if (cellElClass.includes("boolean-column" /* Boolean */)) return this.getBooleanValue(cellEl);
|
|
115
|
-
if (cellElClass.includes("tags-column" /* Tags */)) return this.getTagsValue(cellEl);
|
|
116
|
-
if (cellElClass.includes("number-column" /* Number */)) return this.getNumberValue(cellEl);
|
|
117
|
-
if (cellElClass.includes("date-column" /* Date */)) return this.getDateValue(cellEl, cellElClass);
|
|
118
|
-
const cellText = await cellEl.getText();
|
|
119
|
-
return cellText == "" ? null : cellText;
|
|
120
|
-
}
|
|
121
|
-
getIndex() {
|
|
122
|
-
return this._index;
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// src/pageObjects/elements/Table/elements/Row.ts
|
|
127
|
-
var DX_SELECTION_CLASS = "dx-selection";
|
|
128
|
-
var DX_ROW_EDIT_CLASS = "dx-edit-row";
|
|
129
|
-
var DX_DATA_ROW_CLASS = "dx-data-row";
|
|
130
|
-
var FIRST_CLICKED_CELL_SELECTOR = 'td[aria-colindex="1"]';
|
|
131
|
-
var Row = class extends AbstractElementWithParent {
|
|
132
|
-
index;
|
|
133
|
-
getColumnBy;
|
|
134
|
-
fixedTableContentCssSelector;
|
|
135
|
-
/**
|
|
136
|
-
* @param parentCssSelector
|
|
137
|
-
* @param fixedTableContentCssSelector
|
|
138
|
-
* @param index починається з 0 (в getCssRowByIndexSelector додається +1)
|
|
139
|
-
* @param driver
|
|
140
|
-
* @param getColumnBy
|
|
141
|
-
*/
|
|
142
|
-
constructor(parentCssSelector, fixedTableContentCssSelector, index, driver, getColumnBy) {
|
|
143
|
-
super(parentCssSelector, getCssRowByIndexSelector(index), driver);
|
|
144
|
-
this.index = index;
|
|
145
|
-
this.getColumnBy = getColumnBy;
|
|
146
|
-
this.fixedTableContentCssSelector = fixedTableContentCssSelector;
|
|
147
|
-
}
|
|
148
|
-
_getCell({ index, name, title }) {
|
|
149
|
-
return new Cell(
|
|
150
|
-
this.getFullCssSelector(),
|
|
151
|
-
() => {
|
|
152
|
-
return this.getColumnBy({ title, name }).getIndex();
|
|
153
|
-
},
|
|
154
|
-
this.driver,
|
|
155
|
-
index
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
getCellByIndex(index) {
|
|
159
|
-
return this._getCell({ index });
|
|
160
|
-
}
|
|
161
|
-
getCell(name) {
|
|
162
|
-
return this._getCell({ name });
|
|
163
|
-
}
|
|
164
|
-
getCellByTitle(title) {
|
|
165
|
-
return this._getCell({ title });
|
|
166
|
-
}
|
|
167
|
-
async select(preserve = false) {
|
|
168
|
-
await staleElementAction(async () => {
|
|
169
|
-
const rowEl = await this.getElement();
|
|
170
|
-
const isSelected = (await this.getClasses()).includes(DX_SELECTION_CLASS);
|
|
171
|
-
const clickedElement = await rowEl.findElement(By3.css(FIRST_CLICKED_CELL_SELECTOR));
|
|
172
|
-
if (isSelected && !preserve) {
|
|
173
|
-
await this.driver.actions({ async: true }).keyUp(Key.CONTROL).perform();
|
|
174
|
-
}
|
|
175
|
-
if (preserve && !isSelected) {
|
|
176
|
-
await this.driver.actions({ async: true }).keyDown(Key.CONTROL).perform();
|
|
177
|
-
await click(clickedElement, this.driver);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
await click(clickedElement, this.driver);
|
|
181
|
-
});
|
|
182
|
-
await safeWait(
|
|
183
|
-
async () => {
|
|
184
|
-
const classes = await this.getClasses();
|
|
185
|
-
return classes.includes(DX_SELECTION_CLASS);
|
|
186
|
-
},
|
|
187
|
-
this.driver,
|
|
188
|
-
"Cannot select row"
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
async isSelected() {
|
|
192
|
-
const result = await this.getAttribute("aria-selected");
|
|
193
|
-
return result === "true";
|
|
194
|
-
}
|
|
195
|
-
getIndex() {
|
|
196
|
-
return this.index;
|
|
197
|
-
}
|
|
198
|
-
async getCells() {
|
|
199
|
-
const cells = await this.driver.findElements(By3.css(`${this.getFullCssSelector()} td[role="gridcell"]`));
|
|
200
|
-
const result = [];
|
|
201
|
-
cells.forEach((_, index) => {
|
|
202
|
-
const newCell = this.getCellByIndex(index);
|
|
203
|
-
result.push(newCell);
|
|
204
|
-
});
|
|
205
|
-
return result;
|
|
206
|
-
}
|
|
207
|
-
async clickInlineButton(buttonClass) {
|
|
208
|
-
const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(
|
|
209
|
-
this.index
|
|
210
|
-
)}"] .${buttonClass}`;
|
|
211
|
-
const by = By3.css(`${this.parentCssSelector} ${this.fixedTableContentCssSelector} ${buttonCssSelector}`);
|
|
212
|
-
await staleElementAction(async () => {
|
|
213
|
-
const button = await fixElementStaleError(by, this.driver);
|
|
214
|
-
await click(button, this.driver);
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
async checkEditingMode(isEditing, msg) {
|
|
218
|
-
await safeWait(
|
|
219
|
-
async () => {
|
|
220
|
-
return (await this.getClasses()).includes(DX_ROW_EDIT_CLASS) === isEditing;
|
|
221
|
-
},
|
|
222
|
-
this.driver,
|
|
223
|
-
msg
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
async edit() {
|
|
227
|
-
await this.clickInlineButton("edit");
|
|
228
|
-
await this.checkEditingMode(true, "Row did not switch to edit mode");
|
|
229
|
-
}
|
|
230
|
-
async save() {
|
|
231
|
-
await this.clickInlineButton("save");
|
|
232
|
-
await this.checkEditingMode(false, "Row did not saved");
|
|
233
|
-
}
|
|
234
|
-
async cancel() {
|
|
235
|
-
await this.clickInlineButton("cancel");
|
|
236
|
-
await this.checkEditingMode(false, "Row did not switch to normal mode");
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
// src/pageObjects/elements/Table/elements/Column.ts
|
|
241
|
-
import { By as By4 } from "selenium-webdriver";
|
|
242
|
-
var Column = class extends AbstractElementWithParent {
|
|
243
|
-
_index;
|
|
244
|
-
_caption;
|
|
245
|
-
_name;
|
|
246
|
-
headerCssSelector;
|
|
247
|
-
constructor({ parentCssSelector, headerCssSelector, name, caption, index, driver }) {
|
|
248
|
-
super(parentCssSelector, "", driver);
|
|
249
|
-
this._name = name;
|
|
250
|
-
this.index = index;
|
|
251
|
-
this._caption = caption;
|
|
252
|
-
this.headerCssSelector = headerCssSelector;
|
|
253
|
-
}
|
|
254
|
-
set index(index) {
|
|
255
|
-
this._index = index;
|
|
256
|
-
this.elementCssSelector = getColumnByIndexCssSelector(index);
|
|
257
|
-
}
|
|
258
|
-
get index() {
|
|
259
|
-
return this._index;
|
|
260
|
-
}
|
|
261
|
-
async getElement() {
|
|
262
|
-
await this.getIndex();
|
|
263
|
-
return super.getElement();
|
|
264
|
-
}
|
|
265
|
-
async getColumnHeaderIndexBy(cssSelector) {
|
|
266
|
-
const column = await fixElementStaleError(By4.css(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`), this.driver);
|
|
267
|
-
return transformOutputIndex(await column.getAttribute("aria-colindex"));
|
|
268
|
-
}
|
|
269
|
-
async getIndexByCaption() {
|
|
270
|
-
return this.getColumnHeaderIndexBy(getColumnByCaptionCssSelector(this._caption));
|
|
271
|
-
}
|
|
272
|
-
async getIndexByName() {
|
|
273
|
-
return this.getColumnHeaderIndexBy(getColumnByNameCssSelector(this._name));
|
|
274
|
-
}
|
|
275
|
-
async caption() {
|
|
276
|
-
const el = await this.getElement();
|
|
277
|
-
return el.getText();
|
|
278
|
-
}
|
|
279
|
-
async getIndex() {
|
|
280
|
-
if (this.index != null) {
|
|
281
|
-
return this.index;
|
|
282
|
-
}
|
|
283
|
-
if (this._caption != null) {
|
|
284
|
-
this.index = await this.getIndexByCaption();
|
|
285
|
-
return this.index;
|
|
286
|
-
}
|
|
287
|
-
if (this._name != null) {
|
|
288
|
-
this.index = await this.getIndexByName();
|
|
289
|
-
return this.index;
|
|
290
|
-
}
|
|
291
|
-
throw new Error("Cant get the index in the column");
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// src/utils/typesUtil.ts
|
|
296
|
-
import { isObject } from "selenium-webdriver/lib/util";
|
|
297
|
-
var types = {
|
|
298
|
-
"[object Array]": "array",
|
|
299
|
-
"[object Date]": "date",
|
|
300
|
-
"[object Object]": "object",
|
|
301
|
-
"[object String]": "string",
|
|
302
|
-
"[object Null]": "null"
|
|
303
|
-
};
|
|
304
|
-
var type = function(object) {
|
|
305
|
-
const typeOfObject = Object.prototype.toString.call(object);
|
|
306
|
-
return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
|
|
307
|
-
};
|
|
308
|
-
var isArray = function(value) {
|
|
309
|
-
return type(value) === "array";
|
|
310
|
-
};
|
|
311
|
-
var isString = function(object) {
|
|
312
|
-
return typeof object === "string";
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
// src/pageObjects/elements/AbstractDropDownMenuList.ts
|
|
316
|
-
var AbstractDropDownMenuList = class extends AbstractElementWithParent {
|
|
317
|
-
buttonNotDisplayedError(name) {
|
|
318
|
-
return `Menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
|
|
319
|
-
}
|
|
320
|
-
async clickItemBy(errorMessage, by) {
|
|
321
|
-
await waitElementIsClickable_default({
|
|
322
|
-
errorMessage,
|
|
323
|
-
driver: this.driver,
|
|
324
|
-
by
|
|
325
|
-
});
|
|
326
|
-
const menuItemElement = await fixElementStaleError(by, this.driver);
|
|
327
|
-
await click(menuItemElement, this.driver);
|
|
328
|
-
}
|
|
329
|
-
async getElementByPath(path, getBy, returnLastElement = false) {
|
|
330
|
-
let pathList = isString(path) ? [path] : path;
|
|
331
|
-
let result = null;
|
|
332
|
-
let index = 1;
|
|
333
|
-
for (let text of pathList) {
|
|
334
|
-
if (!returnLastElement || index < pathList.length) {
|
|
335
|
-
await this.clickItemBy(this.buttonNotDisplayedError(text), getBy(text));
|
|
336
|
-
} else {
|
|
337
|
-
result = await fixElementStaleError(getBy(text), this.driver);
|
|
338
|
-
}
|
|
339
|
-
index++;
|
|
340
|
-
}
|
|
341
|
-
return result;
|
|
342
|
-
}
|
|
343
|
-
async clickButton(name) {
|
|
344
|
-
await this.getElementByPath(name, this.getButtonNameBy.bind(this));
|
|
345
|
-
}
|
|
346
|
-
async clickButtonByTitle(title) {
|
|
347
|
-
await this.getElementByPath(title, this.getButtonTitleBy.bind(this));
|
|
348
|
-
}
|
|
349
|
-
getMenuItemElementByTitle(title) {
|
|
350
|
-
return this.getElementByPath(title, this.getButtonTitleBy.bind(this), true);
|
|
351
|
-
}
|
|
352
|
-
getMenuItemElementByName(name) {
|
|
353
|
-
return this.getElementByPath(name, this.getButtonNameBy.bind(this), true);
|
|
354
|
-
}
|
|
355
|
-
isVisible() {
|
|
356
|
-
return Promise.resolve(true);
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
// src/pageObjects/elements/DXContextMenuList.ts
|
|
361
|
-
import { By as By5 } from "selenium-webdriver";
|
|
362
|
-
|
|
363
|
-
// src/utils/cssToXPath.ts
|
|
364
|
-
function cssClassesToXPath(classNames) {
|
|
365
|
-
const classNamesList = classNames.split(".").filter((className) => !!className);
|
|
366
|
-
const chained = classNamesList.map((className) => `contains(@class, "${className}")`).join(" and ");
|
|
367
|
-
return `[${chained}]`;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// src/pageObjects/elements/DXContextMenuList.ts
|
|
371
|
-
var CONTEXT_MENU_CLASS = "dx-context-menu";
|
|
372
|
-
var CONTEXT_MENU_ITEM_TEXT_CLASS = "dx-menu-item-text";
|
|
373
|
-
var DXContextMenuList = class extends AbstractDropDownMenuList {
|
|
374
|
-
/**
|
|
375
|
-
* @param parentCssSelector
|
|
376
|
-
* @param classNames - Список класів. Починається з крапки
|
|
377
|
-
* @param driver
|
|
378
|
-
*/
|
|
379
|
-
constructor(parentCssSelector, classNames, driver) {
|
|
380
|
-
super(parentCssSelector, `.${CONTEXT_MENU_CLASS}${classNames}`, driver);
|
|
381
|
-
}
|
|
382
|
-
getButtonTitleBy(title) {
|
|
383
|
-
const buttonByTextXpath = (text) => `//span[contains(@class, "${CONTEXT_MENU_ITEM_TEXT_CLASS}") and contains(text(), "${text}")]`;
|
|
384
|
-
const xpath = "//div" + cssClassesToXPath(this.elementCssSelector) + buttonByTextXpath(title);
|
|
385
|
-
return By5.xpath(xpath);
|
|
386
|
-
}
|
|
387
|
-
async isVisible() {
|
|
388
|
-
try {
|
|
389
|
-
await waitElementIsVisible_default({
|
|
390
|
-
element: await this.driver.findElement(By5.css(`.dx-overlay-wrapper .dx-context-menu`)),
|
|
391
|
-
driver: this.driver,
|
|
392
|
-
errorMessage: "Cannot find dropdown element"
|
|
393
|
-
});
|
|
394
|
-
} catch {
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
// src/pageObjects/elements/Table/elements/ContextMenu.ts
|
|
401
|
-
var ContextMenu = class extends DXContextMenuList {
|
|
402
|
-
_formName;
|
|
403
|
-
_initFn;
|
|
404
|
-
constructor(cssClass, formName, driver) {
|
|
405
|
-
super("", cssClass, driver);
|
|
406
|
-
this._formName = formName;
|
|
407
|
-
}
|
|
408
|
-
setInit(cb) {
|
|
409
|
-
this._initFn = cb;
|
|
410
|
-
return this;
|
|
411
|
-
}
|
|
412
|
-
getButtonNameBy(name) {
|
|
413
|
-
return byTestId(`cm-${this._formName}-${name}`);
|
|
414
|
-
}
|
|
415
|
-
async clickButtonByTitle(title) {
|
|
416
|
-
await this._initFn?.();
|
|
417
|
-
await super.clickButtonByTitle(title);
|
|
418
|
-
}
|
|
419
|
-
async clickButton(name) {
|
|
420
|
-
await this._initFn?.();
|
|
421
|
-
await super.clickButton(name);
|
|
422
|
-
}
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
// src/pageObjects/elements/Table/Table.ts
|
|
426
|
-
var Table = class extends AbstractElementWithParent {
|
|
427
|
-
formName;
|
|
428
|
-
headerCssSelector;
|
|
429
|
-
contextMenuCssSelector;
|
|
430
|
-
fixedTableContentCssSelector;
|
|
431
|
-
tableContentCssSelector;
|
|
432
|
-
constructor({
|
|
433
|
-
parentCssSelector,
|
|
434
|
-
contextMenuCssSelector,
|
|
435
|
-
tableContentCssSelector,
|
|
436
|
-
headerCssSelector,
|
|
437
|
-
fixedTableContentCssSelector,
|
|
438
|
-
formName,
|
|
439
|
-
driver
|
|
440
|
-
}) {
|
|
441
|
-
super(parentCssSelector, `#${createTableId(formName)}`, driver);
|
|
442
|
-
this.formName = formName;
|
|
443
|
-
this.headerCssSelector = headerCssSelector;
|
|
444
|
-
this.contextMenuCssSelector = contextMenuCssSelector;
|
|
445
|
-
this.fixedTableContentCssSelector = fixedTableContentCssSelector;
|
|
446
|
-
this.tableContentCssSelector = tableContentCssSelector;
|
|
447
|
-
}
|
|
448
|
-
getColumnBy = (args) => {
|
|
449
|
-
if (args.title) {
|
|
450
|
-
return this.getColumnByTitle(args.title);
|
|
451
|
-
}
|
|
452
|
-
return this.getColumnByName(args.name);
|
|
453
|
-
};
|
|
454
|
-
/**
|
|
455
|
-
* Отримати рядок по індексу.
|
|
456
|
-
* @param index починається з 0
|
|
457
|
-
*/
|
|
458
|
-
getRowByIndex(index) {
|
|
459
|
-
return new Row(this.getFullCssSelector(), this.fixedTableContentCssSelector, index, this.driver, this.getColumnBy);
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* @param index починається з 0
|
|
463
|
-
*/
|
|
464
|
-
getColumnByIndex(index) {
|
|
465
|
-
this.getRowByIndex(index);
|
|
466
|
-
return new Column({
|
|
467
|
-
parentCssSelector: this.getFullCssSelector(),
|
|
468
|
-
driver: this.driver,
|
|
469
|
-
index
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
getColumnByTitle = (title) => {
|
|
473
|
-
return new Column({
|
|
474
|
-
parentCssSelector: this.getFullCssSelector(),
|
|
475
|
-
headerCssSelector: this.headerCssSelector,
|
|
476
|
-
caption: title,
|
|
477
|
-
driver: this.driver
|
|
478
|
-
});
|
|
479
|
-
};
|
|
480
|
-
getColumnByName = (name) => {
|
|
481
|
-
return new Column({
|
|
482
|
-
parentCssSelector: this.getFullCssSelector(),
|
|
483
|
-
headerCssSelector: this.headerCssSelector,
|
|
484
|
-
name,
|
|
485
|
-
driver: this.driver
|
|
486
|
-
});
|
|
487
|
-
};
|
|
488
|
-
/**
|
|
489
|
-
* Вибрати рядок по індексу.
|
|
490
|
-
* @param index починається з 0
|
|
491
|
-
* @param preserve boolean який изначає, чи повинні раніше вибрані рядки залишатися вибраними
|
|
492
|
-
*/
|
|
493
|
-
selectRowByIndex(index, preserve = false) {
|
|
494
|
-
return this.getRowByIndex(index).select(preserve);
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Вибрати масив рядків по індексу.
|
|
498
|
-
* @param indexes починається з 0
|
|
499
|
-
*/
|
|
500
|
-
async selectRowsByIndexes(indexes) {
|
|
501
|
-
for (const index of indexes) {
|
|
502
|
-
await this.selectRowByIndex(index, true);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
getRowElements(timeout) {
|
|
506
|
-
const rowsFullCssSelector = `${this.getFullCssSelector()} ${this.tableContentCssSelector} .dx-row.dx-data-row`;
|
|
507
|
-
return withCustomTimeouts_default({
|
|
508
|
-
driver: this.driver,
|
|
509
|
-
timeout,
|
|
510
|
-
callback: () => {
|
|
511
|
-
return this.driver.findElements(By6.css(rowsFullCssSelector));
|
|
512
|
-
}
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
async getRows() {
|
|
516
|
-
const rows = await this.getRowElements();
|
|
517
|
-
const result = [];
|
|
518
|
-
rows.forEach((_, index) => {
|
|
519
|
-
const newRow = new Row(
|
|
520
|
-
this.getFullCssSelector(),
|
|
521
|
-
this.fixedTableContentCssSelector,
|
|
522
|
-
index,
|
|
523
|
-
this.driver,
|
|
524
|
-
this.getColumnBy
|
|
525
|
-
);
|
|
526
|
-
result.push(newRow);
|
|
527
|
-
});
|
|
528
|
-
return result;
|
|
529
|
-
}
|
|
530
|
-
async getColumns() {
|
|
531
|
-
const columns = await this.driver.findElements(
|
|
532
|
-
By6.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"] .header-template-text`)
|
|
533
|
-
);
|
|
534
|
-
const result = [];
|
|
535
|
-
columns.forEach((_, index) => {
|
|
536
|
-
const newCol = new Column({
|
|
537
|
-
parentCssSelector: this.getFullCssSelector(),
|
|
538
|
-
index,
|
|
539
|
-
driver: this.driver
|
|
540
|
-
});
|
|
541
|
-
result.push(newCol);
|
|
542
|
-
});
|
|
543
|
-
return result;
|
|
544
|
-
}
|
|
545
|
-
element() {
|
|
546
|
-
return this.getElement();
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Находит поле когда форма находится в состоянии редактирования
|
|
550
|
-
* @example
|
|
551
|
-
* const form = new MyForm();
|
|
552
|
-
* //...
|
|
553
|
-
* expect(await form.field('Name').getValue()).toBe('test value');
|
|
554
|
-
*/
|
|
555
|
-
field(name) {
|
|
556
|
-
return new FormField(this.getFullCssSelector(), this.formName, name, this.driver);
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* Возвращает список строк которые выделены
|
|
560
|
-
* @returns Row[]
|
|
561
|
-
* @example
|
|
562
|
-
* const form = new MyForm();
|
|
563
|
-
* //...
|
|
564
|
-
* await form.getSelectedRows();
|
|
565
|
-
*/
|
|
566
|
-
async getSelectedRows() {
|
|
567
|
-
const rows = await this.getRows();
|
|
568
|
-
let result = [];
|
|
569
|
-
for (const row of rows) {
|
|
570
|
-
if (await row.isSelected()) {
|
|
571
|
-
}
|
|
572
|
-
result.push(row);
|
|
573
|
-
}
|
|
574
|
-
return result;
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Вызывает контекстное меню в области с данными.
|
|
578
|
-
* @param fieldName - имя поля
|
|
579
|
-
* @param [rowIndex] - индекс строки. Если значение не передано, то по умолчанию контекстное меню будет вызвано на первой выделенной строке.
|
|
580
|
-
* @throws {Error} Если нет выделенных строк, то выбросит исключение.
|
|
581
|
-
* @example
|
|
582
|
-
* const form = new MyForm();
|
|
583
|
-
* //...
|
|
584
|
-
* await form.contextMenu('FieldName').clickButton('OpenFormButton');
|
|
585
|
-
* // or
|
|
586
|
-
* await form.contextMenu('FieldName', 3).clickButton(['Group', 'ButtonInGroup']);
|
|
587
|
-
*/
|
|
588
|
-
contextMenu(fieldName, rowIndex) {
|
|
589
|
-
return new ContextMenu(this.contextMenuCssSelector, this.formName, this.driver).setInit(async () => {
|
|
590
|
-
let row;
|
|
591
|
-
if (rowIndex != null) {
|
|
592
|
-
row = this.getRowByIndex(rowIndex);
|
|
593
|
-
} else {
|
|
594
|
-
[row] = await this.getSelectedRows();
|
|
595
|
-
}
|
|
596
|
-
if (!row)
|
|
597
|
-
throw new Error("No row available row for context menu");
|
|
598
|
-
const cellElement = await row.getCell(fieldName).getElement();
|
|
599
|
-
await contextMenu(cellElement, this.driver);
|
|
600
|
-
});
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Отримує значення комірки таблиці за ім'ям комірки та індексом рядка.
|
|
604
|
-
*
|
|
605
|
-
* @param {string} cellName - Ім'я комірки (поля) в таблиці
|
|
606
|
-
* @param {number} rowIndex - Індекс рядка (починається з 0)
|
|
607
|
-
* @throws {Error} Викидає помилку, якщо rowIndex не вказано
|
|
608
|
-
* @returns {Promise<string>} Повертає значення комірки
|
|
609
|
-
*
|
|
610
|
-
* @example
|
|
611
|
-
* const table = new Table(driver);
|
|
612
|
-
*
|
|
613
|
-
* // Отримання значення комірки 'Name' в першому рядку (індекс 0)
|
|
614
|
-
* const cellValue = await table.getCellValueByCellName('Name', 0);
|
|
615
|
-
* expect(cellValue).toBe('Очікуване значення');
|
|
616
|
-
*/
|
|
617
|
-
getCellValueByCellName(cellName, rowIndex) {
|
|
618
|
-
if (rowIndex == null) {
|
|
619
|
-
throw new Error("Error: getCellValue(): rowIndex is required");
|
|
620
|
-
}
|
|
621
|
-
const row = this.getRowByIndex(rowIndex);
|
|
622
|
-
return row.getCell(cellName).getValue();
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* Перевіряє, чи є таблиця порожньою (не містить жодного рядка з даними).
|
|
626
|
-
*
|
|
627
|
-
* @returns {Promise<boolean>} Повертає true, якщо таблиця порожня, false - якщо містить рядки
|
|
628
|
-
*
|
|
629
|
-
* @example
|
|
630
|
-
* const table = new Table(driver);
|
|
631
|
-
*
|
|
632
|
-
* // Перевірка чи порожня таблиця
|
|
633
|
-
* const empty = await table.isEmpty();
|
|
634
|
-
* expect(empty).toBe(true);
|
|
635
|
-
*/
|
|
636
|
-
async isEmpty() {
|
|
637
|
-
try {
|
|
638
|
-
await this.waitRowsCount(0);
|
|
639
|
-
return true;
|
|
640
|
-
} catch {
|
|
641
|
-
return false;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
* Очікує, поки кількість рядків у таблиці не стане рівною заданому значенню.
|
|
646
|
-
* Використовується для синхронізації тестів з динамічним завантаженням даних.
|
|
647
|
-
*
|
|
648
|
-
* @param {number} count - Очікувана кількість рядків у таблиці
|
|
649
|
-
* @returns {Promise<void>} Повертає Promise, який виконується, коли кількість рядків відповідає очікуваній
|
|
650
|
-
* @throws {Error} Викидає помилку, якщо очікування перевищує тайм-аут
|
|
651
|
-
*
|
|
652
|
-
* @example
|
|
653
|
-
* const table = new Table(driver);
|
|
654
|
-
*
|
|
655
|
-
* // Очікування, поки таблиця не стане порожньою
|
|
656
|
-
* await table.waitRowsCount(0);
|
|
657
|
-
*
|
|
658
|
-
* // Очікування, поки в таблиці не з'явиться 5 рядків
|
|
659
|
-
* await table.waitRowsCount(5);
|
|
660
|
-
* console.log('Таблиця містить 5 рядків');
|
|
661
|
-
*/
|
|
662
|
-
async waitRowsCount(count) {
|
|
663
|
-
await safeWait(async () => {
|
|
664
|
-
const rows = await this.getRowElements(1e3);
|
|
665
|
-
return rows.length === count;
|
|
666
|
-
}, this.driver, `Rows count not equal: ${count}`);
|
|
667
|
-
}
|
|
668
|
-
};
|
|
669
|
-
|
|
670
|
-
// src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
|
|
671
|
-
import { By as By8 } from "selenium-webdriver";
|
|
672
|
-
|
|
673
|
-
// src/pageObjects/elements/TableToolbar/ToolbarButton.ts
|
|
674
|
-
import { By as By7 } from "selenium-webdriver";
|
|
675
|
-
var TOOLBAR_BUTTON_CLASS = "toolbar-button";
|
|
676
|
-
var TOOLBAR_BUTTON_TEXT_CLASS = "dx-button-text";
|
|
677
|
-
var getToolbarButtonSelector = (name) => `#${TOOLBAR_BUTTON_CLASS}-${name}`;
|
|
678
|
-
var getToolbarButtonTextSelector = (name) => `${getToolbarButtonSelector(name)} .${TOOLBAR_BUTTON_TEXT_CLASS}`;
|
|
679
|
-
var getToolbarButtonTextByTestIdSelector = (testId) => `${byTestIdCssSelector(testId)} .${TOOLBAR_BUTTON_TEXT_CLASS}`;
|
|
680
|
-
var ToolbarButton = class extends AbstractButton {
|
|
681
|
-
name;
|
|
682
|
-
constructor(parentCssSelector, name, driver) {
|
|
683
|
-
super(parentCssSelector, getToolbarButtonSelector(name), driver);
|
|
684
|
-
this.name = name;
|
|
685
|
-
}
|
|
686
|
-
buttonNotDisplayedError() {
|
|
687
|
-
return `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
|
|
688
|
-
}
|
|
689
|
-
async getTitle() {
|
|
690
|
-
try {
|
|
691
|
-
const buttonTextContainer = await this.driver.findElement(By7.css(getToolbarButtonTextSelector(this.name)));
|
|
692
|
-
return await buttonTextContainer.getText();
|
|
693
|
-
} catch (_) {
|
|
694
|
-
return null;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
};
|
|
698
|
-
|
|
699
|
-
// src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
|
|
700
|
-
var ToolbarGroupButton = class extends AbstractButton {
|
|
701
|
-
name;
|
|
702
|
-
constructor(parentCssSelector, name, driver) {
|
|
703
|
-
super(parentCssSelector, ``, driver);
|
|
704
|
-
this.name = name;
|
|
705
|
-
}
|
|
706
|
-
buttonNotDisplayedError() {
|
|
707
|
-
return `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
|
|
708
|
-
}
|
|
709
|
-
async getTitle() {
|
|
710
|
-
try {
|
|
711
|
-
const buttonTestId = await this.getDataTestId();
|
|
712
|
-
const buttonTextContainer = await this.driver.findElement(By8.css(getToolbarButtonTextByTestIdSelector(buttonTestId)));
|
|
713
|
-
return await buttonTextContainer.getText();
|
|
714
|
-
} catch (_) {
|
|
715
|
-
return null;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
|
|
720
|
-
// src/pageObjects/elements/AbstractDropDownMenuButton.ts
|
|
721
|
-
var AbstractDropDownMenuButton = class extends AbstractElementWithParent {
|
|
722
|
-
_list;
|
|
723
|
-
constructor(parentCssSelector, elementCssSelector, list, driver) {
|
|
724
|
-
super(parentCssSelector, elementCssSelector, driver);
|
|
725
|
-
this._list = list;
|
|
726
|
-
}
|
|
727
|
-
async openDropdownMenu() {
|
|
728
|
-
const dropdown = await this.getElement();
|
|
729
|
-
await click(dropdown, this.driver);
|
|
730
|
-
await this._list.isVisible();
|
|
731
|
-
}
|
|
732
|
-
async clickButton(name) {
|
|
733
|
-
await this.openDropdownMenu();
|
|
734
|
-
await this._list.clickButton(name);
|
|
735
|
-
}
|
|
736
|
-
async clickButtonByTitle(title) {
|
|
737
|
-
await this.openDropdownMenu();
|
|
738
|
-
await this._list.clickButtonByTitle(title);
|
|
739
|
-
}
|
|
740
|
-
async getMenuItemElementByTitle(title) {
|
|
741
|
-
await this.openDropdownMenu();
|
|
742
|
-
return await this._list.getMenuItemElementByTitle(title);
|
|
743
|
-
}
|
|
744
|
-
async getMenuItemElementByName(name) {
|
|
745
|
-
await this.openDropdownMenu();
|
|
746
|
-
return await this._list.getMenuItemElementByName(name);
|
|
747
|
-
}
|
|
748
|
-
};
|
|
749
|
-
|
|
750
|
-
// src/pageObjects/elements/TableToolbar/ToolbarMenuItem.ts
|
|
751
|
-
var ToolbarMenuItem = class {
|
|
752
|
-
getMenuItem;
|
|
753
|
-
name;
|
|
754
|
-
constructor(getMenuItem, name) {
|
|
755
|
-
this.getMenuItem = getMenuItem;
|
|
756
|
-
this.name = name;
|
|
757
|
-
}
|
|
758
|
-
async click() {
|
|
759
|
-
const menuItemElement = await this.getMenuItem(this.name);
|
|
760
|
-
await menuItemElement.click();
|
|
761
|
-
}
|
|
762
|
-
async getTitle() {
|
|
763
|
-
try {
|
|
764
|
-
const menuItemElement = await this.getMenuItem(this.name);
|
|
765
|
-
return await menuItemElement.getText();
|
|
766
|
-
} catch (_) {
|
|
767
|
-
return null;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
async isDisabled() {
|
|
771
|
-
const menuItemElement = await this.getMenuItem(this.name);
|
|
772
|
-
return await menuItemElement.getCssValue("pointer-events") === "none";
|
|
773
|
-
}
|
|
774
|
-
async isDisplayed() {
|
|
775
|
-
try {
|
|
776
|
-
const menuItemElement = await this.getMenuItem(this.name);
|
|
777
|
-
return await menuItemElement.isDisplayed();
|
|
778
|
-
} catch (_) {
|
|
779
|
-
return false;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
// src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
|
|
785
|
-
var SPINDOWN_CLASS = ".dx-icon-spindown";
|
|
786
|
-
var buttonGroupItemSelector = (formName, name) => byTestIdCssSelector(`ftb-${formName}-${name}`);
|
|
787
|
-
var getFullCssSelector = (formName, name) => `${buttonGroupItemSelector(formName, name)} ${SPINDOWN_CLASS}`;
|
|
788
|
-
var ToolbarMenuList = class extends DXContextMenuList {
|
|
789
|
-
_formName;
|
|
790
|
-
constructor(parentCssSelector, elementCssSelector, formName, driver) {
|
|
791
|
-
super(parentCssSelector, elementCssSelector, driver);
|
|
792
|
-
this._formName = formName;
|
|
793
|
-
}
|
|
794
|
-
getButtonNameBy(name) {
|
|
795
|
-
return byTestId(`ftb-${this._formName}-${name}`);
|
|
796
|
-
}
|
|
797
|
-
};
|
|
798
|
-
var ToolbarMenu = class extends AbstractDropDownMenuButton {
|
|
799
|
-
constructor(parentCssSelector, formName, name, driver) {
|
|
800
|
-
const fullSelector = getFullCssSelector(formName, name);
|
|
801
|
-
const list = new ToolbarMenuList(parentCssSelector, ".toolbar-dropdown-context-menu", formName, driver);
|
|
802
|
-
super(parentCssSelector, fullSelector, list, driver);
|
|
803
|
-
}
|
|
804
|
-
checkNameValue(name) {
|
|
805
|
-
if (!isString(name) && !isArray(name))
|
|
806
|
-
throw new Error(`"name" must be a string or array of string`);
|
|
807
|
-
}
|
|
808
|
-
checkTitleValue(title) {
|
|
809
|
-
if (!isString(title) && !isArray(title))
|
|
810
|
-
throw new Error(`"title" must be a string or array of string`);
|
|
811
|
-
}
|
|
812
|
-
buttonByName(name) {
|
|
813
|
-
this.checkNameValue(name);
|
|
814
|
-
return new ToolbarMenuItem(this.getMenuItemElementByName.bind(this), name);
|
|
815
|
-
}
|
|
816
|
-
buttonByTitle(title) {
|
|
817
|
-
this.checkTitleValue(title);
|
|
818
|
-
return new ToolbarMenuItem(this.getMenuItemElementByTitle.bind(this), title);
|
|
819
|
-
}
|
|
820
|
-
async buttonIsDisplayed(name) {
|
|
821
|
-
const button = this.buttonByName(name);
|
|
822
|
-
return await button.isDisplayed();
|
|
823
|
-
}
|
|
824
|
-
async buttonByTitleIsDisplayed(title) {
|
|
825
|
-
const button = this.buttonByTitle(title);
|
|
826
|
-
return await button.isDisplayed();
|
|
827
|
-
}
|
|
828
|
-
async buttonTitle(name) {
|
|
829
|
-
const button = this.buttonByName(name);
|
|
830
|
-
return await button.getTitle();
|
|
831
|
-
}
|
|
832
|
-
async buttonIsDisabled(name) {
|
|
833
|
-
const button = this.buttonByName(name);
|
|
834
|
-
return await button.isDisabled();
|
|
835
|
-
}
|
|
836
|
-
async buttonByTitleIsDisabled(title) {
|
|
837
|
-
const button = this.buttonByTitle(title);
|
|
838
|
-
return await button.isDisabled();
|
|
839
|
-
}
|
|
840
|
-
async clickButton(name) {
|
|
841
|
-
const button = this.buttonByName(name);
|
|
842
|
-
await button.click();
|
|
843
|
-
}
|
|
844
|
-
async clickButtonByTitle(title) {
|
|
845
|
-
const button = this.buttonByTitle(title);
|
|
846
|
-
await button.click();
|
|
847
|
-
}
|
|
848
|
-
};
|
|
849
|
-
|
|
850
|
-
// src/pageObjects/elements/TableToolbar/ToolbarItem.ts
|
|
851
|
-
var GROUP_BUTTON_CLASS = "toolbar-group-button";
|
|
852
|
-
var toolbarItemSelector = (form, name) => byTestIdCssSelector(`ftb-${form}-${name}`);
|
|
853
|
-
var ToolbarItem = class extends AbstractElementWithParent {
|
|
854
|
-
_button;
|
|
855
|
-
_formName;
|
|
856
|
-
_itemName;
|
|
857
|
-
constructor(parentCssSelector, formName, itemName, driver) {
|
|
858
|
-
super(parentCssSelector, toolbarItemSelector(formName, itemName), driver);
|
|
859
|
-
this._itemName = itemName;
|
|
860
|
-
this._formName = formName;
|
|
861
|
-
}
|
|
862
|
-
async init() {
|
|
863
|
-
if (this._button) return this._button;
|
|
864
|
-
const classNames = await this.getClasses();
|
|
865
|
-
if (classNames.includes(GROUP_BUTTON_CLASS)) {
|
|
866
|
-
this._button = new ToolbarGroupButton(this.getFullCssSelector(), this._itemName, this.driver);
|
|
867
|
-
return;
|
|
868
|
-
}
|
|
869
|
-
this._button = new ToolbarButton(this.parentCssSelector, this._itemName, this.driver);
|
|
870
|
-
}
|
|
871
|
-
async click() {
|
|
872
|
-
await this.init();
|
|
873
|
-
await this._button.click();
|
|
874
|
-
}
|
|
875
|
-
async isDisabled() {
|
|
876
|
-
await this.init();
|
|
877
|
-
return await this._button.isDisabled();
|
|
878
|
-
}
|
|
879
|
-
async isDisplayed() {
|
|
880
|
-
try {
|
|
881
|
-
await this.init();
|
|
882
|
-
return this._button.isDisplayed();
|
|
883
|
-
} catch (error) {
|
|
884
|
-
return false;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
async isPressed() {
|
|
888
|
-
try {
|
|
889
|
-
await this.init();
|
|
890
|
-
return this._button.isPressed();
|
|
891
|
-
} catch (error) {
|
|
892
|
-
return false;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
async getTitle() {
|
|
896
|
-
await this.init();
|
|
897
|
-
return await this._button.getTitle();
|
|
898
|
-
}
|
|
899
|
-
get menu() {
|
|
900
|
-
return new ToolbarMenu(this.parentCssSelector, this._formName, this._itemName, this.driver);
|
|
901
|
-
}
|
|
902
|
-
};
|
|
903
|
-
|
|
904
|
-
// src/pageObjects/elements/TableToolbar/FormToolbar.ts
|
|
905
|
-
var TABLE_TOOLBAR_CLASS = "d5-table-toolbar";
|
|
906
|
-
var FormToolbar = class extends AbstractElementWithParent {
|
|
907
|
-
formName;
|
|
908
|
-
constructor(parentCssSelector, formName, driver) {
|
|
909
|
-
super(parentCssSelector, `#${TABLE_TOOLBAR_CLASS}-${formName}`, driver);
|
|
910
|
-
this.formName = formName;
|
|
911
|
-
}
|
|
912
|
-
button(name) {
|
|
913
|
-
return new ToolbarItem(this.getFullCssSelector(), this.formName, name, this.driver);
|
|
914
|
-
}
|
|
915
|
-
};
|
|
916
|
-
|
|
917
|
-
// src/pageObjects/elements/Filters/FilterOperation.ts
|
|
918
|
-
import { By as By9 } from "selenium-webdriver";
|
|
919
|
-
var FILTER_OPERATIONS = [
|
|
920
|
-
"=",
|
|
921
|
-
"<>",
|
|
922
|
-
"<",
|
|
923
|
-
">",
|
|
924
|
-
"<=",
|
|
925
|
-
">=",
|
|
926
|
-
"contains",
|
|
927
|
-
"between",
|
|
928
|
-
"isanyof",
|
|
929
|
-
"isnotanyof",
|
|
930
|
-
"isblank",
|
|
931
|
-
"isnotblank",
|
|
932
|
-
"startwith",
|
|
933
|
-
"bywords"
|
|
934
|
-
];
|
|
935
|
-
var BUTTON_OPERATION_WIDGET = "operation-widget";
|
|
936
|
-
var OPERATIONS_WIDGET_POPUP = "operation-type-widget-popup";
|
|
937
|
-
var getWidgetInPopupSelector = (operationName) => `.dx-list-item [data-operation="${operationName}"]`;
|
|
938
|
-
var FilterOperation = class extends AbstractElementWithParent {
|
|
939
|
-
_testId;
|
|
940
|
-
constructor({ parentCssSelector, filterTestID, driver }) {
|
|
941
|
-
super(parentCssSelector, `${byTestIdCssSelector(`${BUTTON_OPERATION_WIDGET}-${filterTestID}`)}`, driver);
|
|
942
|
-
this._testId = filterTestID;
|
|
943
|
-
}
|
|
944
|
-
async initOperationWidget() {
|
|
945
|
-
const widgetButtonEl = await this.getElement();
|
|
946
|
-
await waitElementIsClickable_default({
|
|
947
|
-
element: widgetButtonEl,
|
|
948
|
-
errorMessage: "Widget operation is not clickable",
|
|
949
|
-
driver: this.driver
|
|
950
|
-
});
|
|
951
|
-
const clickableElement = await widgetButtonEl.findElement(By9.className("dx-icon"));
|
|
952
|
-
await click(clickableElement, this.driver);
|
|
953
|
-
try {
|
|
954
|
-
const widgetPopupEl = await this.driver.findElement(By9.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
|
|
955
|
-
await waitElementIsVisible_default({
|
|
956
|
-
element: widgetPopupEl,
|
|
957
|
-
errorMessage: `Operation widget popup is not visible`,
|
|
958
|
-
driver: this.driver
|
|
959
|
-
});
|
|
960
|
-
} catch (_) {
|
|
961
|
-
throw `Operation widget popup is not visible`;
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
async setOperation(operationName) {
|
|
965
|
-
if (!FILTER_OPERATIONS.includes(operationName)) {
|
|
966
|
-
throw new Error(`Operation with name "${operationName}" is not correct.`);
|
|
967
|
-
}
|
|
968
|
-
await this.initOperationWidget();
|
|
969
|
-
const operationEl = await fixElementStaleError(By9.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
|
|
970
|
-
await click(operationEl, this.driver);
|
|
971
|
-
await safeWait(
|
|
972
|
-
async () => {
|
|
973
|
-
const currOperationName = await this.getAttribute("data-operation");
|
|
974
|
-
if (operationName === "isblank") return true;
|
|
975
|
-
return currOperationName === operationName;
|
|
976
|
-
},
|
|
977
|
-
this.driver,
|
|
978
|
-
"Operation is not changed"
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
async getOperation() {
|
|
982
|
-
const result = await this.getAttribute("data-operation");
|
|
983
|
-
if (!result) throw new Error("Operation not found");
|
|
984
|
-
return result;
|
|
985
|
-
}
|
|
986
|
-
async setIsBlank(value) {
|
|
987
|
-
const currValue = await this.getIsBlank();
|
|
988
|
-
if (currValue !== value) {
|
|
989
|
-
await this.setOperation("isblank");
|
|
990
|
-
await safeWait(
|
|
991
|
-
async () => {
|
|
992
|
-
const currIsBlank = await this.getIsBlank();
|
|
993
|
-
return currIsBlank === value;
|
|
994
|
-
},
|
|
995
|
-
this.driver,
|
|
996
|
-
"Operation is not changed"
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
async getIsBlank() {
|
|
1001
|
-
const result = await this.getAttribute("data-hasblank");
|
|
1002
|
-
return result === "true";
|
|
1003
|
-
}
|
|
1004
|
-
};
|
|
1005
|
-
|
|
1006
|
-
// src/pageObjects/elements/Filters/FormFilterField.ts
|
|
1007
|
-
var FormFilterField = class extends AbstractEditor {
|
|
1008
|
-
formName;
|
|
1009
|
-
name;
|
|
1010
|
-
constructor(parentCssSelector, formName, name, driver) {
|
|
1011
|
-
super(parentCssSelector, byTestIdCssSelector(createLayoutFilterTestId(formName, name)), driver);
|
|
1012
|
-
this.formName = formName;
|
|
1013
|
-
this.name = name;
|
|
1014
|
-
}
|
|
1015
|
-
/**
|
|
1016
|
-
* Возвращает значение в поле
|
|
1017
|
-
* @example
|
|
1018
|
-
* expect(await form.formFilter('NumberFld').getValue()).toBe(10);
|
|
1019
|
-
* expect(await form.formFilter('TextFld').getValue()).toBe('TestValue');
|
|
1020
|
-
*/
|
|
1021
|
-
async getValue() {
|
|
1022
|
-
return super.getValue();
|
|
1023
|
-
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Устанавливает значение в поле
|
|
1026
|
-
* @example
|
|
1027
|
-
* await form.formFilter('NumberFld').setValue(123);
|
|
1028
|
-
* await form.formFilter('TextFld').setValue('TestValue');
|
|
1029
|
-
* await form.formFilter('TextFld').setValue('TestValue', '=', true);
|
|
1030
|
-
*/
|
|
1031
|
-
async setValue(value, operation, isBlank) {
|
|
1032
|
-
if (typeof operation === "string") {
|
|
1033
|
-
await this.setOperation(operation);
|
|
1034
|
-
}
|
|
1035
|
-
if (typeof isBlank === "boolean") {
|
|
1036
|
-
await this.setIsBlank(isBlank);
|
|
1037
|
-
}
|
|
1038
|
-
return super.setValue(value);
|
|
1039
|
-
}
|
|
1040
|
-
/**
|
|
1041
|
-
* Очищает значение в поле
|
|
1042
|
-
* @example
|
|
1043
|
-
* await form.formFilter('NumberFld').clear();
|
|
1044
|
-
*/
|
|
1045
|
-
async clear() {
|
|
1046
|
-
return super.clear();
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* Удаляет тег по переданному тексту
|
|
1050
|
-
* @example
|
|
1051
|
-
* await form.formFilter('TagBox').remove('test');
|
|
1052
|
-
*/
|
|
1053
|
-
async remove(itemText) {
|
|
1054
|
-
return super.remove(itemText);
|
|
1055
|
-
}
|
|
1056
|
-
/**
|
|
1057
|
-
* Инициализация операции фильтра
|
|
1058
|
-
*/
|
|
1059
|
-
async initOperation() {
|
|
1060
|
-
return new FilterOperation({
|
|
1061
|
-
parentCssSelector: this.parentCssSelector,
|
|
1062
|
-
filterTestID: createLayoutFilterTestId(this.formName, this.name),
|
|
1063
|
-
driver: this.driver
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
/**
|
|
1067
|
-
* Устанавливает операцию для фильтра
|
|
1068
|
-
* @example
|
|
1069
|
-
* await form.formFilter('TagBox').setOperation("=");
|
|
1070
|
-
*/
|
|
1071
|
-
async setOperation(operationName) {
|
|
1072
|
-
const filterOperation = await this.initOperation();
|
|
1073
|
-
await filterOperation.setOperation(operationName);
|
|
1074
|
-
}
|
|
1075
|
-
/**
|
|
1076
|
-
* Возвращает операцию фильтра
|
|
1077
|
-
* @example
|
|
1078
|
-
* expect(await form.formFilter('NumberFld').getOperation()).toBe("=");
|
|
1079
|
-
*/
|
|
1080
|
-
async getOperation() {
|
|
1081
|
-
const filterOperation = await this.initOperation();
|
|
1082
|
-
return await filterOperation.getOperation();
|
|
1083
|
-
}
|
|
1084
|
-
/**
|
|
1085
|
-
* Устанавливает операцию 'isblank' для фильтра
|
|
1086
|
-
* @example
|
|
1087
|
-
* await form.formFilter('TagBox').setIsBlank(true);
|
|
1088
|
-
*/
|
|
1089
|
-
async setIsBlank(value) {
|
|
1090
|
-
const filterOperation = await this.initOperation();
|
|
1091
|
-
await filterOperation.setIsBlank(value);
|
|
1092
|
-
}
|
|
1093
|
-
/**
|
|
1094
|
-
* Возвращает true|false, если операция 'isblank' установлена для фильтра
|
|
1095
|
-
* @example
|
|
1096
|
-
* expect(await form.formFilter('NumberFld').getIsBlank()).toBe(false);
|
|
1097
|
-
*/
|
|
1098
|
-
async getIsBlank() {
|
|
1099
|
-
const filterOperation = await this.initOperation();
|
|
1100
|
-
return await filterOperation.getIsBlank();
|
|
1101
|
-
}
|
|
1102
|
-
async isReadonly() {
|
|
1103
|
-
return super.isReadonly();
|
|
1104
|
-
}
|
|
1105
|
-
async isDisabled() {
|
|
1106
|
-
return super.isDisabled();
|
|
1107
|
-
}
|
|
1108
|
-
};
|
|
1109
|
-
|
|
1110
|
-
// src/pageObjects/elements/Filters/FilterPanel.ts
|
|
1111
|
-
import { By as By10 } from "selenium-webdriver";
|
|
1112
|
-
|
|
1113
|
-
// src/pageObjects/elements/Filters/PanelFilterField.ts
|
|
1114
|
-
var PanelFilterField = class extends AbstractEditor {
|
|
1115
|
-
formName;
|
|
1116
|
-
name;
|
|
1117
|
-
constructor(parentCssSelector, formName, name, driver) {
|
|
1118
|
-
super(parentCssSelector, byTestIdCssSelector(createDocFilterTestId(formName, name)), driver);
|
|
1119
|
-
this.formName = formName;
|
|
1120
|
-
this.name = name;
|
|
1121
|
-
}
|
|
1122
|
-
/**
|
|
1123
|
-
* Возвращает значение в поле
|
|
1124
|
-
* @example
|
|
1125
|
-
* expect(await form.filterPanel.filterField('NumberFld').getValue()).toBe(10);
|
|
1126
|
-
* expect(await form.filterPanel.filterField('TextFld').getValue()).toBe('TestValue');
|
|
1127
|
-
*/
|
|
1128
|
-
async getValue() {
|
|
1129
|
-
return super.getValue();
|
|
1130
|
-
}
|
|
1131
|
-
/**
|
|
1132
|
-
* Устанавливает значение в поле
|
|
1133
|
-
* @example
|
|
1134
|
-
* await form.filterPanel.filterField('NumberFld').setValue(123);
|
|
1135
|
-
* await form.filterPanel.filterField('TextFld').setValue('TestValue');
|
|
1136
|
-
* await form.filterPanel.filterField('TextFld').setValue('TestValue', '=', true);
|
|
1137
|
-
*/
|
|
1138
|
-
async setValue(value, operation, isBlank) {
|
|
1139
|
-
if (typeof operation === "string") {
|
|
1140
|
-
await this.setOperation(operation);
|
|
1141
|
-
}
|
|
1142
|
-
if (typeof isBlank === "boolean") {
|
|
1143
|
-
await this.setIsBlank(isBlank);
|
|
1144
|
-
}
|
|
1145
|
-
return super.setValue(value);
|
|
1146
|
-
}
|
|
1147
|
-
/**
|
|
1148
|
-
* Очищает значение в поле
|
|
1149
|
-
* @example
|
|
1150
|
-
* await form.filterPanel.filterField('NumberFld').clear();
|
|
1151
|
-
*/
|
|
1152
|
-
async clear() {
|
|
1153
|
-
return super.clear();
|
|
1154
|
-
}
|
|
1155
|
-
/**
|
|
1156
|
-
* Удаляет тег по переданному тексту
|
|
1157
|
-
* @example
|
|
1158
|
-
* await form.filterPanel.filterField('TagBox').remove('test');
|
|
1159
|
-
*/
|
|
1160
|
-
async remove(itemText) {
|
|
1161
|
-
return super.remove(itemText);
|
|
1162
|
-
}
|
|
1163
|
-
/**
|
|
1164
|
-
* Инициализация операции фильтра
|
|
1165
|
-
*/
|
|
1166
|
-
async initOperation() {
|
|
1167
|
-
return new FilterOperation({
|
|
1168
|
-
parentCssSelector: this.parentCssSelector,
|
|
1169
|
-
filterTestID: createDocFilterTestId(this.formName, this.name),
|
|
1170
|
-
driver: this.driver
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
/**
|
|
1174
|
-
* Устанавливает операцию для фильтра
|
|
1175
|
-
* @example
|
|
1176
|
-
* await form.filterPanel.filterField('TagBox').setOperation("=");
|
|
1177
|
-
*/
|
|
1178
|
-
async setOperation(operationName) {
|
|
1179
|
-
const filterOperation = await this.initOperation();
|
|
1180
|
-
await filterOperation.setOperation(operationName);
|
|
1181
|
-
}
|
|
1182
|
-
/**
|
|
1183
|
-
* Возвращает операцию фильтра
|
|
1184
|
-
* @example
|
|
1185
|
-
* expect(await form.filterPanel.filterField('NumberFld').getOperation()).toBe("=");
|
|
1186
|
-
*/
|
|
1187
|
-
async getOperation() {
|
|
1188
|
-
const filterOperation = await this.initOperation();
|
|
1189
|
-
return await filterOperation.getOperation();
|
|
1190
|
-
}
|
|
1191
|
-
/**
|
|
1192
|
-
* Устанавливает операцию 'isblank' для фильтра
|
|
1193
|
-
* @example
|
|
1194
|
-
* await form.filterPanel.filterField('TagBox').setIsBlank(true);
|
|
1195
|
-
*/
|
|
1196
|
-
async setIsBlank(value) {
|
|
1197
|
-
const filterOperation = await this.initOperation();
|
|
1198
|
-
await filterOperation.setIsBlank(value);
|
|
1199
|
-
}
|
|
1200
|
-
/**
|
|
1201
|
-
* Возвращает true|false, если операция 'isblank' установлена для фильтра
|
|
1202
|
-
* @example
|
|
1203
|
-
* expect(await form.filterPanel.filterField('NumberFld').getIsBlank()).toBe(false);
|
|
1204
|
-
*/
|
|
1205
|
-
async getIsBlank() {
|
|
1206
|
-
const filterOperation = await this.initOperation();
|
|
1207
|
-
return await filterOperation.getIsBlank();
|
|
1208
|
-
}
|
|
1209
|
-
async isReadonly() {
|
|
1210
|
-
return super.isReadonly();
|
|
1211
|
-
}
|
|
1212
|
-
async isDisabled() {
|
|
1213
|
-
return super.isDisabled();
|
|
1214
|
-
}
|
|
1215
|
-
};
|
|
1216
|
-
|
|
1217
|
-
// src/pageObjects/elements/Filters/FilterPanel.ts
|
|
1218
|
-
var drawerSelector = (formName) => `.secondary-drawer-side-panel.form-${formName}`;
|
|
1219
|
-
var FILTER_PANEL_SELECTOR = ".filter-panel";
|
|
1220
|
-
var CLOSE_SELECTOR = ".button-close";
|
|
1221
|
-
var FilterPanel = class extends AbstractElement {
|
|
1222
|
-
_formName;
|
|
1223
|
-
get filterPanelSelector() {
|
|
1224
|
-
return `${this.elementCssSelector} ${FILTER_PANEL_SELECTOR}`;
|
|
1225
|
-
}
|
|
1226
|
-
async filterPanelButtons() {
|
|
1227
|
-
const selector = `${this.elementCssSelector} ${FILTER_PANEL_SELECTOR} .filter-panel__buttons-panel .dx-button-text`;
|
|
1228
|
-
const el = await this.getElement();
|
|
1229
|
-
return el.findElements(By10.css(selector));
|
|
1230
|
-
}
|
|
1231
|
-
constructor(formName, driver) {
|
|
1232
|
-
super(driver, drawerSelector(formName));
|
|
1233
|
-
this._formName = formName;
|
|
1234
|
-
}
|
|
1235
|
-
/**
|
|
1236
|
-
* Возвращает фильтр на панели фильтрации
|
|
1237
|
-
* @returns {PanelFilterField}
|
|
1238
|
-
* @example
|
|
1239
|
-
* await form.filterPanel.filterField('NumberFld');
|
|
1240
|
-
*/
|
|
1241
|
-
filterField(name) {
|
|
1242
|
-
return new PanelFilterField(this.filterPanelSelector, this._formName, name, this.driver);
|
|
1243
|
-
}
|
|
1244
|
-
async apply() {
|
|
1245
|
-
const btn = await this.findButtonByTitle("\u0417\u0430\u0441\u0442\u043E\u0441\u0443\u0432\u0430\u0442\u0438");
|
|
1246
|
-
await click(btn, this.driver);
|
|
1247
|
-
}
|
|
1248
|
-
async findButtonByTitle(title) {
|
|
1249
|
-
const buttons = await this.filterPanelButtons();
|
|
1250
|
-
for (const btn of buttons) {
|
|
1251
|
-
if (await btn.getText() === title) {
|
|
1252
|
-
return btn;
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
async clearAll() {
|
|
1257
|
-
const btn = await this.findButtonByTitle("\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438");
|
|
1258
|
-
await click(btn, this.driver);
|
|
1259
|
-
await this.driver.sleep(300);
|
|
1260
|
-
}
|
|
1261
|
-
async close() {
|
|
1262
|
-
const btn = await this.driver.findElement(By10.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
|
|
1263
|
-
await click(btn, this.driver);
|
|
1264
|
-
}
|
|
1265
|
-
};
|
|
1266
|
-
|
|
1267
|
-
// src/pageObjects/elements/Filters/ColumnFilter.ts
|
|
1268
|
-
import { By as By11 } from "selenium-webdriver";
|
|
1269
|
-
|
|
1270
|
-
// src/pageObjects/elements/Filters/HeaderFilterField.ts
|
|
1271
|
-
var HeaderFilterField = class extends AbstractEditor {
|
|
1272
|
-
constructor(parentCssSelector, formName, name, driver) {
|
|
1273
|
-
super(parentCssSelector, byTestIdCssSelector(createHeaderFilterTestId(formName, name)), driver);
|
|
1274
|
-
}
|
|
1275
|
-
async getValue() {
|
|
1276
|
-
return super.getValue();
|
|
1277
|
-
}
|
|
1278
|
-
async setValue(value) {
|
|
1279
|
-
return super.setValue(value);
|
|
1280
|
-
}
|
|
1281
|
-
async clear() {
|
|
1282
|
-
return super.clear();
|
|
1283
|
-
}
|
|
1284
|
-
async remove(itemText) {
|
|
1285
|
-
return super.remove(itemText);
|
|
1286
|
-
}
|
|
1287
|
-
async isReadonly() {
|
|
1288
|
-
return super.isReadonly();
|
|
1289
|
-
}
|
|
1290
|
-
async isDisabled() {
|
|
1291
|
-
return super.isDisabled();
|
|
1292
|
-
}
|
|
1293
|
-
};
|
|
1294
|
-
|
|
1295
|
-
// src/pageObjects/elements/Filters/ColumnFilter.ts
|
|
1296
|
-
var APPLY_SELECTOR = ".apply-button";
|
|
1297
|
-
var CANCEL_SELECTOR = ".cancel-button";
|
|
1298
|
-
var HEADER_FILTER_ICON = ".indicators-container .filter-icon";
|
|
1299
|
-
var HEADER_FILTER_CONTAINER = ".header-filter";
|
|
1300
|
-
var HEADER_FILTER_BUTTONS = ".header-filter-buttons";
|
|
1301
|
-
var ColumnFilter = class extends AbstractElement {
|
|
1302
|
-
_formName;
|
|
1303
|
-
_name;
|
|
1304
|
-
_column;
|
|
1305
|
-
constructor(formName, name, column, driver) {
|
|
1306
|
-
super(driver, HEADER_FILTER_CONTAINER);
|
|
1307
|
-
this._formName = formName;
|
|
1308
|
-
this._name = name;
|
|
1309
|
-
this._column = column;
|
|
1310
|
-
this.driver = driver;
|
|
1311
|
-
}
|
|
1312
|
-
async getApplyButton() {
|
|
1313
|
-
const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${APPLY_SELECTOR}`;
|
|
1314
|
-
return this.driver.findElement(By11.css(selector));
|
|
1315
|
-
}
|
|
1316
|
-
async getCancelButton() {
|
|
1317
|
-
const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${CANCEL_SELECTOR}`;
|
|
1318
|
-
return this.driver.findElement(By11.css(selector));
|
|
1319
|
-
}
|
|
1320
|
-
async apply() {
|
|
1321
|
-
const btn = await this.getApplyButton();
|
|
1322
|
-
await click(btn, this.driver);
|
|
1323
|
-
}
|
|
1324
|
-
async cancel() {
|
|
1325
|
-
const btn = await this.getCancelButton();
|
|
1326
|
-
await click(btn, this.driver);
|
|
1327
|
-
}
|
|
1328
|
-
async initFilter() {
|
|
1329
|
-
const columnEl = await this._column.getElement();
|
|
1330
|
-
const actions = this.driver.actions({ async: true });
|
|
1331
|
-
await actions.move({ origin: columnEl }).perform();
|
|
1332
|
-
const headerFilterIconBy = By11.css(HEADER_FILTER_ICON);
|
|
1333
|
-
let headerFilterIcon = await columnEl.findElement(headerFilterIconBy);
|
|
1334
|
-
await safeWait(
|
|
1335
|
-
() => {
|
|
1336
|
-
return headerFilterIcon.isDisplayed();
|
|
1337
|
-
},
|
|
1338
|
-
this.driver,
|
|
1339
|
-
`HeaderFilter "${this._name}" is not visible`
|
|
1340
|
-
);
|
|
1341
|
-
await click(headerFilterIcon, this.driver);
|
|
1342
|
-
const filter = new HeaderFilterField("", this._formName, this._name, this.driver);
|
|
1343
|
-
const filterEl = await filter.getElement();
|
|
1344
|
-
await waitElementIsVisible_default({
|
|
1345
|
-
element: filterEl,
|
|
1346
|
-
driver: this.driver,
|
|
1347
|
-
errorMessage: `Header filter is not visible`
|
|
1348
|
-
});
|
|
1349
|
-
return filter;
|
|
1350
|
-
}
|
|
1351
|
-
/**
|
|
1352
|
-
* Возвращает значение в поле
|
|
1353
|
-
* @example
|
|
1354
|
-
* expect(await form.columnFilter('NumberFld').getValue()).toBe(10);
|
|
1355
|
-
* expect(await form.columnFilter('TextFld').getValue()).toBe('TestValue');
|
|
1356
|
-
*/
|
|
1357
|
-
async getValue() {
|
|
1358
|
-
const filter = await this.initFilter();
|
|
1359
|
-
const result = await filter.getValue();
|
|
1360
|
-
await this.cancel();
|
|
1361
|
-
return result;
|
|
1362
|
-
}
|
|
1363
|
-
/**
|
|
1364
|
-
* Устанавливает значение в поле
|
|
1365
|
-
* @example
|
|
1366
|
-
* await form.columnFilter('NumberFld').setValue(123);
|
|
1367
|
-
* await form.columnFilter('TextFld').setValue('TestValue');
|
|
1368
|
-
* await form.columnFilter('TextFld').setValue('TestValue', '=', true);
|
|
1369
|
-
*/
|
|
1370
|
-
async setValue(value, operation, isBlank) {
|
|
1371
|
-
const filter = await this.initFilter();
|
|
1372
|
-
const filterOperation = new FilterOperation({
|
|
1373
|
-
parentCssSelector: HEADER_FILTER_CONTAINER,
|
|
1374
|
-
filterTestID: createHeaderFilterTestId(this._formName, this._name),
|
|
1375
|
-
driver: this.driver
|
|
1376
|
-
});
|
|
1377
|
-
const inputEl = await filter.getElement();
|
|
1378
|
-
if (typeof operation === "string") {
|
|
1379
|
-
await inputEl.click();
|
|
1380
|
-
await filterOperation.setOperation(operation);
|
|
1381
|
-
}
|
|
1382
|
-
if (typeof isBlank === "boolean") {
|
|
1383
|
-
await inputEl.click();
|
|
1384
|
-
await filterOperation.setIsBlank(isBlank);
|
|
1385
|
-
}
|
|
1386
|
-
await filter.setValue(value);
|
|
1387
|
-
return this.apply();
|
|
1388
|
-
}
|
|
1389
|
-
/**
|
|
1390
|
-
* Очищает значение в поле
|
|
1391
|
-
* @example
|
|
1392
|
-
* await form.columnFilter('NumberFld').clear();
|
|
1393
|
-
*/
|
|
1394
|
-
async clear() {
|
|
1395
|
-
const filter = await this.initFilter();
|
|
1396
|
-
await filter.clear();
|
|
1397
|
-
return this.apply();
|
|
1398
|
-
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Удаляет тег по переданному тексту
|
|
1401
|
-
* @example
|
|
1402
|
-
* await form.columnFilter('TagBox').remove('test');
|
|
1403
|
-
*/
|
|
1404
|
-
async remove(itemText) {
|
|
1405
|
-
const filter = await this.initFilter();
|
|
1406
|
-
await filter.remove(itemText);
|
|
1407
|
-
return this.apply();
|
|
1408
|
-
}
|
|
1409
|
-
/**
|
|
1410
|
-
* Инициализация операции фильтра
|
|
1411
|
-
*/
|
|
1412
|
-
async initOperation() {
|
|
1413
|
-
const filter = await this.initFilter();
|
|
1414
|
-
const inputEl = await filter.getElement();
|
|
1415
|
-
await inputEl.click();
|
|
1416
|
-
return new FilterOperation({
|
|
1417
|
-
parentCssSelector: HEADER_FILTER_CONTAINER,
|
|
1418
|
-
filterTestID: createHeaderFilterTestId(this._formName, this._name),
|
|
1419
|
-
driver: this.driver
|
|
1420
|
-
});
|
|
1421
|
-
}
|
|
1422
|
-
/**
|
|
1423
|
-
* Устанавливает операцию для фильтра
|
|
1424
|
-
* @example
|
|
1425
|
-
* await form.columnFilter('TagBox').setOperation("=");
|
|
1426
|
-
*/
|
|
1427
|
-
async setOperation(operationName) {
|
|
1428
|
-
const filterOperation = await this.initOperation();
|
|
1429
|
-
await filterOperation.setOperation(operationName);
|
|
1430
|
-
await this.apply();
|
|
1431
|
-
}
|
|
1432
|
-
/**
|
|
1433
|
-
* Возвращает операцию фильтра
|
|
1434
|
-
* @example
|
|
1435
|
-
* expect(await form.columnFilter('NumberFld').getOperation()).toBe("=");
|
|
1436
|
-
*/
|
|
1437
|
-
async getOperation() {
|
|
1438
|
-
const filterOperation = await this.initOperation();
|
|
1439
|
-
return await filterOperation.getOperation();
|
|
1440
|
-
}
|
|
1441
|
-
/**
|
|
1442
|
-
* Устанавливает операцию 'isblank' для фильтра
|
|
1443
|
-
* @example
|
|
1444
|
-
* await form.columnFilter('TagBox').setIsBlank(true);
|
|
1445
|
-
*/
|
|
1446
|
-
async setIsBlank(value) {
|
|
1447
|
-
const filterOperation = await this.initOperation();
|
|
1448
|
-
await filterOperation.setIsBlank(value);
|
|
1449
|
-
await this.apply();
|
|
1450
|
-
}
|
|
1451
|
-
/**
|
|
1452
|
-
* Возвращает true|false, если операция 'isblank' установлена для фильтра
|
|
1453
|
-
* @example
|
|
1454
|
-
* expect(await form.columnFilter('NumberFld').getIsBlank()).toBe(false);
|
|
1455
|
-
*/
|
|
1456
|
-
async getIsBlank() {
|
|
1457
|
-
const filterOperation = await this.initOperation();
|
|
1458
|
-
return await filterOperation.getIsBlank();
|
|
1459
|
-
}
|
|
1460
|
-
async isReadonly() {
|
|
1461
|
-
const filter = await this.initFilter();
|
|
1462
|
-
const result = await filter.isReadonly();
|
|
1463
|
-
await this.cancel();
|
|
1464
|
-
return result;
|
|
1465
|
-
}
|
|
1466
|
-
async isDisabled() {
|
|
1467
|
-
const filter = await this.initFilter();
|
|
1468
|
-
const result = await filter.isDisabled();
|
|
1469
|
-
await this.cancel();
|
|
1470
|
-
return result;
|
|
1471
|
-
}
|
|
1472
|
-
};
|
|
1473
|
-
|
|
1474
|
-
// src/pageObjects/elements/Forms/ListForm.ts
|
|
1475
|
-
var DATAGRID_HEADER_CSS_SELECTOR = ".dx-datagrid-headers .dx-datagrid-content .dx-datagrid-table.dx-datagrid-table-fixed";
|
|
1476
|
-
var DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-content .dx-datagrid-table.dx-datagrid-table-fixed";
|
|
1477
|
-
var FIXED_DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-sticky-columns .dx-datagrid-content .dx-datagrid-table.dx-datagrid-table-fixed";
|
|
1478
|
-
var CONTEXT_MENU_CSS_SELECTOR = ".dx-datagrid";
|
|
1479
|
-
var ListForm = class extends Form {
|
|
1480
|
-
headerCssSelector;
|
|
1481
|
-
fixedTableContentCssSelector;
|
|
1482
|
-
tableContentCssSelector;
|
|
1483
|
-
contextMenuCssSelector;
|
|
1484
|
-
constructor(driver) {
|
|
1485
|
-
super(driver);
|
|
1486
|
-
this.popupContainerCssSelector = `.popup.form-inline-${this.formName}`;
|
|
1487
|
-
this.headerCssSelector = DATAGRID_HEADER_CSS_SELECTOR;
|
|
1488
|
-
this.fixedTableContentCssSelector = FIXED_DATAGRID_CONTENT_CSS_SELECTOR;
|
|
1489
|
-
this.tableContentCssSelector = DATAGRID_CONTENT_CSS_SELECTOR;
|
|
1490
|
-
this.contextMenuCssSelector = CONTEXT_MENU_CSS_SELECTOR;
|
|
1491
|
-
}
|
|
1492
|
-
/**
|
|
1493
|
-
* Находит таблицу
|
|
1494
|
-
* @example
|
|
1495
|
-
* const listForm = new MyForm();
|
|
1496
|
-
* //...
|
|
1497
|
-
* expect(listForm.table());
|
|
1498
|
-
*/
|
|
1499
|
-
table() {
|
|
1500
|
-
return new Table(
|
|
1501
|
-
{
|
|
1502
|
-
parentCssSelector: this.containerCssSelector,
|
|
1503
|
-
headerCssSelector: this.headerCssSelector,
|
|
1504
|
-
fixedTableContentCssSelector: this.fixedTableContentCssSelector,
|
|
1505
|
-
formName: this.formName,
|
|
1506
|
-
driver: this.driver,
|
|
1507
|
-
contextMenuCssSelector: this.contextMenuCssSelector,
|
|
1508
|
-
tableContentCssSelector: this.tableContentCssSelector
|
|
1509
|
-
}
|
|
1510
|
-
);
|
|
1511
|
-
}
|
|
1512
|
-
/**
|
|
1513
|
-
* Находит таблицу
|
|
1514
|
-
* @example
|
|
1515
|
-
* const listForm = new MyForm();
|
|
1516
|
-
* //...
|
|
1517
|
-
* expect(listForm.toolbarButton());
|
|
1518
|
-
*/
|
|
1519
|
-
toolbarButton(name) {
|
|
1520
|
-
const toolbar = new FormToolbar(this.containerCssSelector, this.formName, this.driver);
|
|
1521
|
-
return toolbar.button(name);
|
|
1522
|
-
}
|
|
1523
|
-
/**
|
|
1524
|
-
* Фильтр который расположен на форме
|
|
1525
|
-
* @example
|
|
1526
|
-
* const listForm = new MyForm();
|
|
1527
|
-
* //...
|
|
1528
|
-
* expect(listForm.formFilter());
|
|
1529
|
-
*/
|
|
1530
|
-
formFilter(name) {
|
|
1531
|
-
return new FormFilterField(this.containerCssSelector, this.formName, name, this.driver);
|
|
1532
|
-
}
|
|
1533
|
-
columnFilter(name) {
|
|
1534
|
-
const column = this.table().getColumnByName(name);
|
|
1535
|
-
return new ColumnFilter(this.formName, name, column, this.driver);
|
|
1536
|
-
}
|
|
1537
|
-
/**
|
|
1538
|
-
* Модель панели фильтрации
|
|
1539
|
-
* @returns {FilterPanel}
|
|
1540
|
-
* @example
|
|
1541
|
-
* const listForm = new MyForm();
|
|
1542
|
-
* //...
|
|
1543
|
-
* expect(listForm.filterPanel());
|
|
1544
|
-
*/
|
|
1545
|
-
get filterPanel() {
|
|
1546
|
-
return new FilterPanel(this.formName, this.driver);
|
|
1547
|
-
}
|
|
1548
|
-
};
|
|
1549
|
-
|
|
1550
|
-
export {
|
|
1551
|
-
FormFilterField,
|
|
1552
|
-
PanelFilterField,
|
|
1553
|
-
FilterPanel,
|
|
1554
|
-
ListForm
|
|
1555
|
-
};
|