d5-testing-library 1.8.0-alpha.9 → 1.8.0

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.
@@ -8,18 +8,20 @@ import {
8
8
  byTestId,
9
9
  byTestIdCssSelector,
10
10
  click,
11
+ contextMenu,
11
12
  createDocFilterTestId,
12
13
  createHeaderFilterTestId,
13
14
  createLayoutFilterTestId,
14
15
  createTableId,
15
16
  fixElementStaleError,
16
- wait,
17
- waitElementIsClickable,
18
- waitElementIsVisible
19
- } from "./chunk-R3BWDLN3.mjs";
17
+ safeWait,
18
+ staleElementAction,
19
+ waitElementIsClickable_default,
20
+ waitElementIsVisible_default
21
+ } from "./chunk-32KSAOFJ.mjs";
20
22
 
21
23
  // src/pageObjects/elements/Table/Table.ts
22
- import { By as By5 } from "selenium-webdriver";
24
+ import { By as By6 } from "selenium-webdriver";
23
25
 
24
26
  // src/pageObjects/elements/Table/elements/Row.ts
25
27
  import { By as By3 } from "selenium-webdriver";
@@ -45,7 +47,7 @@ var transformOutputIndex = (index) => +index - 1;
45
47
  var Cell = class extends AbstractElementWithParent {
46
48
  _index;
47
49
  getCellIndex;
48
- constructor(parentCssSelector, getCellIndex, index, driver) {
50
+ constructor(parentCssSelector, getCellIndex, driver, index) {
49
51
  super(parentCssSelector, getCssCellByIndexSelector(index), driver);
50
52
  this.getCellIndex = getCellIndex;
51
53
  this._index = index;
@@ -65,7 +67,30 @@ var Cell = class extends AbstractElementWithParent {
65
67
  for (const tag of tags) {
66
68
  values.push(await tag.getAttribute("textContent"));
67
69
  }
68
- return values;
70
+ return values.length ? values : null;
71
+ }
72
+ async getNumberValue(cellEl) {
73
+ const value = (await cellEl.getText()).trim();
74
+ return value == "" ? null : Number.parseFloat(value);
75
+ }
76
+ async getDateValue(cellEl, cellElClass) {
77
+ const value = (await cellEl.getText()).trim();
78
+ if (value === "") return null;
79
+ const isWithTime = cellElClass.includes("with-time");
80
+ try {
81
+ if (isWithTime) {
82
+ const [datePart, timePart] = value.split(", ");
83
+ const [day, month, year] = datePart.split(".").map(Number);
84
+ const [hours, minutes] = timePart.split(":").map(Number);
85
+ return new Date(Date.UTC(year, month - 1, day, hours, minutes));
86
+ } else {
87
+ const [day, month, year] = value.split(".").map(Number);
88
+ return new Date(Date.UTC(year, month - 1, day));
89
+ }
90
+ } catch (error) {
91
+ console.error(`Error parsing date value "${value}":`, error);
92
+ return null;
93
+ }
69
94
  }
70
95
  async getElement() {
71
96
  if (this._index == null) {
@@ -76,11 +101,12 @@ var Cell = class extends AbstractElementWithParent {
76
101
  async getValue() {
77
102
  const cellEl = await this.getElement();
78
103
  const cellElClass = await cellEl.getAttribute("class");
79
- if (cellElClass.includes("boolean-column" /* Boolean */))
80
- return this.getBooleanValue(cellEl);
81
- if (cellElClass.includes("tags-column" /* Tags */))
82
- return this.getTagsValue(cellEl);
83
- return cellEl.getText();
104
+ if (cellElClass.includes("boolean-column" /* Boolean */)) return this.getBooleanValue(cellEl);
105
+ if (cellElClass.includes("tags-column" /* Tags */)) return this.getTagsValue(cellEl);
106
+ if (cellElClass.includes("number-column" /* Number */)) return this.getNumberValue(cellEl);
107
+ if (cellElClass.includes("date-column" /* Date */)) return this.getDateValue(cellEl, cellElClass);
108
+ const cellText = await cellEl.getText();
109
+ return cellText == "" ? null : cellText;
84
110
  }
85
111
  getIndex() {
86
112
  return this._index;
@@ -95,6 +121,13 @@ var Row = class extends AbstractElementWithParent {
95
121
  index;
96
122
  getColumnBy;
97
123
  fixedTableContentCssSelector;
124
+ /**
125
+ * @param parentCssSelector
126
+ * @param fixedTableContentCssSelector
127
+ * @param index починається з 0 (в getCssRowByIndexSelector додається +1)
128
+ * @param driver
129
+ * @param getColumnBy
130
+ */
98
131
  constructor(parentCssSelector, fixedTableContentCssSelector, index, driver, getColumnBy) {
99
132
  super(parentCssSelector, getCssRowByIndexSelector(index), driver);
100
133
  this.index = index;
@@ -107,8 +140,8 @@ var Row = class extends AbstractElementWithParent {
107
140
  () => {
108
141
  return this.getColumnBy({ title, name }).getIndex();
109
142
  },
110
- index,
111
- this.driver
143
+ this.driver,
144
+ index
112
145
  );
113
146
  }
114
147
  getCellByIndex(index) {
@@ -121,9 +154,11 @@ var Row = class extends AbstractElementWithParent {
121
154
  return this._getCell({ title });
122
155
  }
123
156
  async select() {
124
- const rowEl = await this.getElement();
125
- await click(rowEl, this.driver);
126
- await wait(
157
+ await staleElementAction(async () => {
158
+ const rowEl = await this.getElement();
159
+ await click(rowEl, this.driver);
160
+ });
161
+ await safeWait(
127
162
  async () => {
128
163
  const classes = await this.getClasses();
129
164
  return classes.includes(DX_SELECTION_CLASS);
@@ -152,14 +187,14 @@ var Row = class extends AbstractElementWithParent {
152
187
  const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(
153
188
  this.index
154
189
  )}"] .${buttonClass}`;
155
- const button = await fixElementStaleError(
156
- By3.css(`${this.parentCssSelector} ${this.fixedTableContentCssSelector} ${buttonCssSelector}`),
157
- this.driver
158
- );
159
- return click(button, this.driver);
190
+ const by = By3.css(`${this.parentCssSelector} ${this.fixedTableContentCssSelector} ${buttonCssSelector}`);
191
+ await staleElementAction(async () => {
192
+ const button = await fixElementStaleError(by, this.driver);
193
+ await click(button, this.driver);
194
+ });
160
195
  }
161
196
  async checkEditingMode(isEditing, msg) {
162
- await wait(
197
+ await safeWait(
163
198
  async () => {
164
199
  return (await this.getClasses()).includes(DX_ROW_EDIT_CLASS) === isEditing;
165
200
  },
@@ -236,16 +271,156 @@ var Column = class extends AbstractElementWithParent {
236
271
  }
237
272
  };
238
273
 
274
+ // src/utils/typesUtil.ts
275
+ import { isObject } from "selenium-webdriver/lib/util";
276
+ var types = {
277
+ "[object Array]": "array",
278
+ "[object Date]": "date",
279
+ "[object Object]": "object",
280
+ "[object String]": "string",
281
+ "[object Null]": "null"
282
+ };
283
+ var type = function(object) {
284
+ const typeOfObject = Object.prototype.toString.call(object);
285
+ return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
286
+ };
287
+ var isArray = function(value) {
288
+ return type(value) === "array";
289
+ };
290
+ var isString = function(object) {
291
+ return typeof object === "string";
292
+ };
293
+
294
+ // src/pageObjects/elements/AbstractDropDownMenuList.ts
295
+ var AbstractDropDownMenuList = class extends AbstractElementWithParent {
296
+ buttonNotDisplayedError(name) {
297
+ return `Menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
298
+ }
299
+ async clickItemBy(errorMessage, by) {
300
+ await waitElementIsClickable_default({
301
+ errorMessage,
302
+ driver: this.driver,
303
+ by
304
+ });
305
+ const menuItemElement = await fixElementStaleError(by, this.driver);
306
+ await click(menuItemElement, this.driver);
307
+ }
308
+ async getElementByPath(path, getBy, returnLastElement = false) {
309
+ let pathList = isString(path) ? [path] : path;
310
+ let result = null;
311
+ let index = 1;
312
+ for (let text of pathList) {
313
+ if (!returnLastElement || index < pathList.length) {
314
+ await this.clickItemBy(this.buttonNotDisplayedError(text), getBy(text));
315
+ } else {
316
+ result = await fixElementStaleError(getBy(text), this.driver);
317
+ }
318
+ index++;
319
+ }
320
+ return result;
321
+ }
322
+ async clickButton(name) {
323
+ await this.getElementByPath(name, this.getButtonNameBy.bind(this));
324
+ }
325
+ async clickButtonByTitle(title) {
326
+ await this.getElementByPath(title, this.getButtonTitleBy.bind(this));
327
+ }
328
+ getMenuItemElementByTitle(title) {
329
+ return this.getElementByPath(title, this.getButtonTitleBy.bind(this), true);
330
+ }
331
+ getMenuItemElementByName(name) {
332
+ return this.getElementByPath(name, this.getButtonNameBy.bind(this), true);
333
+ }
334
+ isVisible() {
335
+ return Promise.resolve(true);
336
+ }
337
+ };
338
+
339
+ // src/pageObjects/elements/DXContextMenuList.ts
340
+ import { By as By5 } from "selenium-webdriver";
341
+
342
+ // src/utils/cssToXPath.ts
343
+ function cssClassesToXPath(classNames) {
344
+ const classNamesList = classNames.split(".").filter((className) => !!className);
345
+ const chained = classNamesList.map((className) => `contains(@class, "${className}")`).join(" and ");
346
+ return `[${chained}]`;
347
+ }
348
+
349
+ // src/pageObjects/elements/DXContextMenuList.ts
350
+ var CONTEXT_MENU_CLASS = "dx-context-menu";
351
+ var CONTEXT_MENU_ITEM_TEXT_CLASS = "dx-menu-item-text";
352
+ var DXContextMenuList = class extends AbstractDropDownMenuList {
353
+ /**
354
+ * @param parentCssSelector
355
+ * @param classNames - Список класів. Починається з крапки
356
+ * @param driver
357
+ */
358
+ constructor(parentCssSelector, classNames, driver) {
359
+ super(parentCssSelector, `.${CONTEXT_MENU_CLASS}${classNames}`, driver);
360
+ }
361
+ getButtonTitleBy(title) {
362
+ const buttonByTextXpath = (text) => `//span[contains(@class, "${CONTEXT_MENU_ITEM_TEXT_CLASS}") and contains(text(), "${text}")]`;
363
+ const xpath = "//div" + cssClassesToXPath(this.elementCssSelector) + buttonByTextXpath(title);
364
+ return By5.xpath(xpath);
365
+ }
366
+ async isVisible() {
367
+ try {
368
+ await waitElementIsVisible_default({
369
+ element: await this.driver.findElement(By5.css(`.dx-overlay-wrapper .dx-contextmenu`)),
370
+ driver: this.driver,
371
+ errorMessage: "Cannot find dropdown element"
372
+ });
373
+ } catch {
374
+ return false;
375
+ }
376
+ }
377
+ };
378
+
379
+ // src/pageObjects/elements/Table/elements/ContextMenu.ts
380
+ var ContextMenu = class extends DXContextMenuList {
381
+ _formName;
382
+ _initFn;
383
+ constructor(cssClass, formName, driver) {
384
+ super("", cssClass, driver);
385
+ this._formName = formName;
386
+ }
387
+ setInit(cb) {
388
+ this._initFn = cb;
389
+ return this;
390
+ }
391
+ getButtonNameBy(name) {
392
+ return byTestId(`cm-${this._formName}-${name}`);
393
+ }
394
+ async clickButtonByTitle(title) {
395
+ await this._initFn?.();
396
+ await super.clickButtonByTitle(title);
397
+ }
398
+ async clickButton(name) {
399
+ await this._initFn?.();
400
+ await super.clickButton(name);
401
+ }
402
+ };
403
+
239
404
  // src/pageObjects/elements/Table/Table.ts
240
405
  var Table = class extends AbstractElementWithParent {
241
406
  formName;
242
407
  headerCssSelector;
408
+ contextMenuCssSelector;
243
409
  fixedTableContentCssSelector;
244
410
  tableContentCssSelector;
245
- constructor(parentCssSelector, headerCssSelector, tableContentCssSelector, fixedTableContentCssSelector, formName, driver) {
411
+ constructor({
412
+ parentCssSelector,
413
+ contextMenuCssSelector,
414
+ tableContentCssSelector,
415
+ headerCssSelector,
416
+ fixedTableContentCssSelector,
417
+ formName,
418
+ driver
419
+ }) {
246
420
  super(parentCssSelector, `#${createTableId(formName)}`, driver);
247
421
  this.formName = formName;
248
422
  this.headerCssSelector = headerCssSelector;
423
+ this.contextMenuCssSelector = contextMenuCssSelector;
249
424
  this.fixedTableContentCssSelector = fixedTableContentCssSelector;
250
425
  this.tableContentCssSelector = tableContentCssSelector;
251
426
  }
@@ -255,10 +430,18 @@ var Table = class extends AbstractElementWithParent {
255
430
  }
256
431
  return this.getColumnByName(args.name);
257
432
  };
433
+ /**
434
+ * Отримати рядок по індексу.
435
+ * @param index починається з 0
436
+ */
258
437
  getRowByIndex(index) {
259
438
  return new Row(this.getFullCssSelector(), this.fixedTableContentCssSelector, index, this.driver, this.getColumnBy);
260
439
  }
440
+ /**
441
+ * @param index починається з 0
442
+ */
261
443
  getColumnByIndex(index) {
444
+ this.getRowByIndex(index);
262
445
  return new Column({
263
446
  parentCssSelector: this.getFullCssSelector(),
264
447
  driver: this.driver,
@@ -281,12 +464,16 @@ var Table = class extends AbstractElementWithParent {
281
464
  driver: this.driver
282
465
  });
283
466
  };
467
+ /**
468
+ * Вибрати рядок по індексу.
469
+ * @param index починається з 0
470
+ */
284
471
  selectRowByIndex(index) {
285
472
  return this.getRowByIndex(index).select();
286
473
  }
287
474
  async getRows() {
288
475
  const rowsFullCssSelector = `${this.getFullCssSelector()} ${this.tableContentCssSelector} .dx-row.dx-data-row`;
289
- const rows = await this.driver.findElements(By5.css(rowsFullCssSelector));
476
+ const rows = await this.driver.findElements(By6.css(rowsFullCssSelector));
290
477
  const result = [];
291
478
  rows.forEach((_, index) => {
292
479
  const newRow = new Row(
@@ -302,7 +489,7 @@ var Table = class extends AbstractElementWithParent {
302
489
  }
303
490
  async getColumns() {
304
491
  const columns = await this.driver.findElements(
305
- By5.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"]`)
492
+ By6.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"] .header-template-text`)
306
493
  );
307
494
  const result = [];
308
495
  columns.forEach((_, index) => {
@@ -328,102 +515,227 @@ var Table = class extends AbstractElementWithParent {
328
515
  field(name) {
329
516
  return new FormField(this.getFullCssSelector(), this.formName, name, this.driver);
330
517
  }
518
+ /**
519
+ * Возвращает список строк которые выделены
520
+ * @returns Row[]
521
+ * @example
522
+ * const form = new MyForm();
523
+ * //...
524
+ * await form.getSelectedRows();
525
+ */
526
+ async getSelectedRows() {
527
+ const rows = await this.getRows();
528
+ let result = [];
529
+ for (const row of rows) {
530
+ if (await row.isSelected()) {
531
+ }
532
+ result.push(row);
533
+ }
534
+ return result;
535
+ }
536
+ /**
537
+ * Вызывает контекстное меню в области с данными.
538
+ * @param fieldName - имя поля
539
+ * @param [rowIndex] - индекс строки. Если значение не передано, то по умолчанию контекстное меню будет вызвано на первой выделенной строке.
540
+ * @throws {Error} Если нет выделенных строк, то выбросит исключение.
541
+ * @example
542
+ * const form = new MyForm();
543
+ * //...
544
+ * await form.contextMenu('FieldName').clickButton('OpenFormButton');
545
+ * // or
546
+ * await form.contextMenu('FieldName', 3).clickButton(['Group', 'ButtonInGroup']);
547
+ */
548
+ contextMenu(fieldName, rowIndex) {
549
+ return new ContextMenu(this.contextMenuCssSelector, this.formName, this.driver).setInit(async () => {
550
+ let row;
551
+ if (rowIndex != null) {
552
+ row = this.getRowByIndex(rowIndex);
553
+ } else {
554
+ [row] = await this.getSelectedRows();
555
+ }
556
+ if (!row)
557
+ throw new Error("No row available row for context menu");
558
+ const cellElement = await row.getCell(fieldName).getElement();
559
+ await contextMenu(cellElement, this.driver);
560
+ });
561
+ }
331
562
  };
332
563
 
333
564
  // src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
334
- var ToolbarGroupButton = class extends AbstractButton {
565
+ import { By as By8 } from "selenium-webdriver";
566
+
567
+ // src/pageObjects/elements/TableToolbar/ToolbarButton.ts
568
+ import { By as By7 } from "selenium-webdriver";
569
+ var TOOLBAR_BUTTON_CLASS = "toolbar-button";
570
+ var TOOLBAR_BUTTON_TEXT_CLASS = "dx-button-text";
571
+ var getToolbarButtonSelector = (name) => `#${TOOLBAR_BUTTON_CLASS}-${name}`;
572
+ var getToolbarButtonTextSelector = (name) => `${getToolbarButtonSelector(name)} .${TOOLBAR_BUTTON_TEXT_CLASS}`;
573
+ var ToolbarButton = class extends AbstractButton {
335
574
  name;
336
575
  constructor(parentCssSelector, name, driver) {
337
- super(parentCssSelector, ``, driver);
576
+ super(parentCssSelector, getToolbarButtonSelector(name), driver);
338
577
  this.name = name;
339
578
  }
340
579
  buttonNotDisplayedError() {
341
580
  return `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
342
581
  }
582
+ async getTitle() {
583
+ try {
584
+ const buttonTextContainer = await this.driver.findElement(By7.css(getToolbarButtonTextSelector(this.name)));
585
+ return await buttonTextContainer.getText();
586
+ } catch (_) {
587
+ return null;
588
+ }
589
+ }
343
590
  };
344
591
 
345
- // src/pageObjects/elements/TableToolbar/ToolbarButton.ts
346
- var TOOLBAR_BUTTON_CLASS = "toolbar-button";
347
- var ToolbarButton = class extends AbstractButton {
592
+ // src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
593
+ var ToolbarGroupButton = class extends AbstractButton {
348
594
  name;
349
595
  constructor(parentCssSelector, name, driver) {
350
- super(parentCssSelector, `#${TOOLBAR_BUTTON_CLASS}-${name}`, driver);
596
+ super(parentCssSelector, ``, driver);
351
597
  this.name = name;
352
598
  }
353
599
  buttonNotDisplayedError() {
354
600
  return `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
355
601
  }
602
+ async getTitle() {
603
+ try {
604
+ const buttonTextContainer = await this.driver.findElement(By8.css(getToolbarButtonTextSelector(this.name)));
605
+ return await buttonTextContainer.getText();
606
+ } catch (_) {
607
+ return null;
608
+ }
609
+ }
356
610
  };
357
611
 
358
- // src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
359
- import { By as By6 } from "selenium-webdriver";
360
-
361
- // src/utils/typesUtil.ts
362
- var types = {
363
- "[object Array]": "array",
364
- "[object Date]": "date",
365
- "[object Object]": "object",
366
- "[object String]": "string",
367
- "[object Null]": "null"
368
- };
369
- var type = function(object) {
370
- const typeOfObject = Object.prototype.toString.call(object);
371
- return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
372
- };
373
- var isArray = function(value) {
374
- return type(value) === "array";
612
+ // src/pageObjects/elements/AbstractDropDownMenuButton.ts
613
+ var AbstractDropDownMenuButton = class extends AbstractElementWithParent {
614
+ _list;
615
+ constructor(parentCssSelector, elementCssSelector, list, driver) {
616
+ super(parentCssSelector, elementCssSelector, driver);
617
+ this._list = list;
618
+ }
619
+ async openDropdownMenu() {
620
+ const dropdown = await this.getElement();
621
+ await click(dropdown, this.driver);
622
+ await this._list.isVisible();
623
+ }
624
+ async clickButton(name) {
625
+ await this.openDropdownMenu();
626
+ await this._list.clickButton(name);
627
+ }
628
+ async clickButtonByTitle(title) {
629
+ await this.openDropdownMenu();
630
+ await this._list.clickButtonByTitle(title);
631
+ }
632
+ async getMenuItemElementByTitle(title) {
633
+ await this.openDropdownMenu();
634
+ return await this._list.getMenuItemElementByTitle(title);
635
+ }
636
+ async getMenuItemElementByName(name) {
637
+ await this.openDropdownMenu();
638
+ return await this._list.getMenuItemElementByName(name);
639
+ }
375
640
  };
376
- var isString = function(object) {
377
- return typeof object === "string";
641
+
642
+ // src/pageObjects/elements/TableToolbar/ToolbarMenuItem.ts
643
+ var ToolbarMenuItem = class {
644
+ getMenuItem;
645
+ name;
646
+ constructor(getMenuItem, name) {
647
+ this.getMenuItem = getMenuItem;
648
+ this.name = name;
649
+ }
650
+ async click() {
651
+ const menuItemElement = await this.getMenuItem(this.name);
652
+ await menuItemElement.click();
653
+ }
654
+ async getTitle() {
655
+ try {
656
+ const menuItemElement = await this.getMenuItem(this.name);
657
+ return await menuItemElement.getText();
658
+ } catch (_) {
659
+ return null;
660
+ }
661
+ }
662
+ async isDisabled() {
663
+ const menuItemElement = await this.getMenuItem(this.name);
664
+ return await menuItemElement.getCssValue("pointer-events") === "none";
665
+ }
666
+ async isDisplayed() {
667
+ try {
668
+ const menuItemElement = await this.getMenuItem(this.name);
669
+ return await menuItemElement.isDisplayed();
670
+ } catch (_) {
671
+ return false;
672
+ }
673
+ }
378
674
  };
379
675
 
380
676
  // src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
381
677
  var SPINDOWN_CLASS = ".dx-icon-spindown";
382
678
  var buttonGroupItemSelector = (formName, name) => byTestIdCssSelector(`ftb-${formName}-${name}`);
383
679
  var getFullCssSelector = (formName, name) => `${buttonGroupItemSelector(formName, name)} ${SPINDOWN_CLASS}`;
384
- var buttonByTextXpath = (text) => `.//span[contains(@class, "dx-menu-item-text") and contains(text(), "${text}")]`;
385
- var ToolbarMenu = class extends AbstractElementWithParent {
680
+ var ToolbarMenuList = class extends DXContextMenuList {
386
681
  _formName;
387
- constructor(parentCssSelector, formName, name, driver) {
388
- super(parentCssSelector, getFullCssSelector(formName, name), driver);
682
+ constructor(parentCssSelector, elementCssSelector, formName, driver) {
683
+ super(parentCssSelector, elementCssSelector, driver);
389
684
  this._formName = formName;
390
685
  }
391
- async openDropdownMenu() {
392
- const dropdown = await this.getElement();
393
- await click(dropdown, this.driver);
394
- }
395
- getCssSelectorToButton(name) {
686
+ getButtonNameBy(name) {
396
687
  return byTestId(`ftb-${this._formName}-${name}`);
397
688
  }
398
- buttonNotDisplayedError(name) {
399
- return `Toolbar menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
400
- }
401
- async goToButton(name, by) {
402
- const toolbarMenuItem = await fixElementStaleError(by, this.driver);
403
- await waitElementIsClickable({
404
- element: toolbarMenuItem,
405
- errorMessage: this.buttonNotDisplayedError(name),
406
- driver: this.driver
407
- });
408
- await click(toolbarMenuItem, this.driver);
689
+ };
690
+ var ToolbarMenu = class extends AbstractDropDownMenuButton {
691
+ constructor(parentCssSelector, formName, name, driver) {
692
+ const fullSelector = getFullCssSelector(formName, name);
693
+ const list = new ToolbarMenuList(parentCssSelector, ".toolbar-dropdown-context-menu", formName, driver);
694
+ super(parentCssSelector, fullSelector, list, driver);
409
695
  }
410
- async clickButton(name) {
411
- await this.openDropdownMenu();
696
+ checkNameValue(name) {
412
697
  if (!isString(name) && !isArray(name))
413
698
  throw new Error(`"name" must be a string or array of string`);
414
- let lName = isString(name) ? [name] : name;
415
- for (let n of lName) {
416
- await this.goToButton(n, this.getCssSelectorToButton(n));
417
- }
418
699
  }
419
- async clickButtonByTitle(title) {
420
- await this.openDropdownMenu();
700
+ checkTitleValue(title) {
421
701
  if (!isString(title) && !isArray(title))
422
702
  throw new Error(`"title" must be a string or array of string`);
423
- let lTitle = isString(title) ? [title] : title;
424
- for (let t of lTitle) {
425
- await this.goToButton(t, By6.xpath(buttonByTextXpath(t)));
426
- }
703
+ }
704
+ buttonByName(name) {
705
+ this.checkNameValue(name);
706
+ return new ToolbarMenuItem(this.getMenuItemElementByName.bind(this), name);
707
+ }
708
+ buttonByTitle(title) {
709
+ this.checkTitleValue(title);
710
+ return new ToolbarMenuItem(this.getMenuItemElementByTitle.bind(this), title);
711
+ }
712
+ async buttonIsDisplayed(name) {
713
+ const button = this.buttonByName(name);
714
+ return await button.isDisplayed();
715
+ }
716
+ async buttonByTitleIsDisplayed(title) {
717
+ const button = this.buttonByTitle(title);
718
+ return await button.isDisplayed();
719
+ }
720
+ async buttonTitle(name) {
721
+ const button = this.buttonByName(name);
722
+ return await button.getTitle();
723
+ }
724
+ async buttonIsDisabled(name) {
725
+ const button = this.buttonByName(name);
726
+ return await button.isDisabled();
727
+ }
728
+ async buttonByTitleIsDisabled(title) {
729
+ const button = this.buttonByTitle(title);
730
+ return await button.isDisabled();
731
+ }
732
+ async clickButton(name) {
733
+ const button = this.buttonByName(name);
734
+ await button.click();
735
+ }
736
+ async clickButtonByTitle(title) {
737
+ const button = this.buttonByTitle(title);
738
+ await button.click();
427
739
  }
428
740
  };
429
741
 
@@ -440,8 +752,7 @@ var ToolbarItem = class extends AbstractElementWithParent {
440
752
  this._formName = formName;
441
753
  }
442
754
  async init() {
443
- if (this._button)
444
- return this._button;
755
+ if (this._button) return this._button;
445
756
  const classNames = await this.getClasses();
446
757
  if (classNames.includes(GROUP_BUTTON_CLASS)) {
447
758
  this._button = new ToolbarGroupButton(this.getFullCssSelector(), this._itemName, this.driver);
@@ -465,6 +776,10 @@ var ToolbarItem = class extends AbstractElementWithParent {
465
776
  return false;
466
777
  }
467
778
  }
779
+ async getTitle() {
780
+ await this.init();
781
+ return await this._button.getTitle();
782
+ }
468
783
  get menu() {
469
784
  return new ToolbarMenu(this.parentCssSelector, this._formName, this._itemName, this.driver);
470
785
  }
@@ -484,7 +799,7 @@ var FormToolbar = class extends AbstractElementWithParent {
484
799
  };
485
800
 
486
801
  // src/pageObjects/elements/Filters/FilterOperation.ts
487
- import { By as By7 } from "selenium-webdriver";
802
+ import { By as By9 } from "selenium-webdriver";
488
803
  var FILTER_OPERATIONS = [
489
804
  "=",
490
805
  "<>",
@@ -512,16 +827,16 @@ var FilterOperation = class extends AbstractElementWithParent {
512
827
  }
513
828
  async initOperationWidget() {
514
829
  const widgetButtonEl = await this.getElement();
515
- await waitElementIsClickable({
830
+ await waitElementIsClickable_default({
516
831
  element: widgetButtonEl,
517
832
  errorMessage: "Widget operation is not clickable",
518
833
  driver: this.driver
519
834
  });
520
- const clickableElement = await widgetButtonEl.findElement(By7.className("dx-icon"));
835
+ const clickableElement = await widgetButtonEl.findElement(By9.className("dx-icon"));
521
836
  await click(clickableElement, this.driver);
522
837
  try {
523
- const widgetPopupEl = await this.driver.findElement(By7.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
524
- await waitElementIsVisible({
838
+ const widgetPopupEl = await this.driver.findElement(By9.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
839
+ await waitElementIsVisible_default({
525
840
  element: widgetPopupEl,
526
841
  errorMessage: `Operation widget popup is not visible`,
527
842
  driver: this.driver
@@ -535,13 +850,12 @@ var FilterOperation = class extends AbstractElementWithParent {
535
850
  throw new Error(`Operation with name "${operationName}" is not correct.`);
536
851
  }
537
852
  await this.initOperationWidget();
538
- const operationEl = await fixElementStaleError(By7.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
853
+ const operationEl = await fixElementStaleError(By9.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
539
854
  await click(operationEl, this.driver);
540
- await wait(
855
+ await safeWait(
541
856
  async () => {
542
857
  const currOperationName = await this.getAttribute("data-operation");
543
- if (operationName === "isblank")
544
- return true;
858
+ if (operationName === "isblank") return true;
545
859
  return currOperationName === operationName;
546
860
  },
547
861
  this.driver,
@@ -550,15 +864,14 @@ var FilterOperation = class extends AbstractElementWithParent {
550
864
  }
551
865
  async getOperation() {
552
866
  const result = await this.getAttribute("data-operation");
553
- if (!result)
554
- throw new Error("Operation not found");
867
+ if (!result) throw new Error("Operation not found");
555
868
  return result;
556
869
  }
557
870
  async setIsBlank(value) {
558
871
  const currValue = await this.getIsBlank();
559
872
  if (currValue !== value) {
560
873
  await this.setOperation("isblank");
561
- await wait(
874
+ await safeWait(
562
875
  async () => {
563
876
  const currIsBlank = await this.getIsBlank();
564
877
  return currIsBlank === value;
@@ -630,7 +943,8 @@ var FormFilterField = class extends AbstractEditor {
630
943
  async initOperation() {
631
944
  return new FilterOperation({
632
945
  parentCssSelector: this.parentCssSelector,
633
- filterTestID: createLayoutFilterTestId(this.formName, this.name)
946
+ filterTestID: createLayoutFilterTestId(this.formName, this.name),
947
+ driver: this.driver
634
948
  });
635
949
  }
636
950
  /**
@@ -672,7 +986,7 @@ var FormFilterField = class extends AbstractEditor {
672
986
  };
673
987
 
674
988
  // src/pageObjects/elements/Filters/FilterPanel.ts
675
- import { By as By8 } from "selenium-webdriver";
989
+ import { By as By10 } from "selenium-webdriver";
676
990
 
677
991
  // src/pageObjects/elements/Filters/PanelFilterField.ts
678
992
  var PanelFilterField = class extends AbstractEditor {
@@ -730,7 +1044,8 @@ var PanelFilterField = class extends AbstractEditor {
730
1044
  async initOperation() {
731
1045
  return new FilterOperation({
732
1046
  parentCssSelector: this.parentCssSelector,
733
- filterTestID: createDocFilterTestId(this.formName, this.name)
1047
+ filterTestID: createDocFilterTestId(this.formName, this.name),
1048
+ driver: this.driver
734
1049
  });
735
1050
  }
736
1051
  /**
@@ -783,7 +1098,7 @@ var FilterPanel = class extends AbstractElement {
783
1098
  async filterPanelButtons() {
784
1099
  const selector = `${this.elementCssSelector} ${FILTER_PANEL_SELECTOR} .filter-panel__buttons-panel .dx-button-text`;
785
1100
  const el = await this.getElement();
786
- return el.findElements(By8.css(selector));
1101
+ return el.findElements(By10.css(selector));
787
1102
  }
788
1103
  constructor(formName, driver) {
789
1104
  super(driver, drawerSelector(formName));
@@ -816,13 +1131,13 @@ var FilterPanel = class extends AbstractElement {
816
1131
  await this.driver.sleep(300);
817
1132
  }
818
1133
  async close() {
819
- const btn = await this.driver.findElement(By8.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
1134
+ const btn = await this.driver.findElement(By10.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
820
1135
  await click(btn, this.driver);
821
1136
  }
822
1137
  };
823
1138
 
824
1139
  // src/pageObjects/elements/Filters/ColumnFilter.ts
825
- import { By as By9 } from "selenium-webdriver";
1140
+ import { By as By11 } from "selenium-webdriver";
826
1141
 
827
1142
  // src/pageObjects/elements/Filters/HeaderFilterField.ts
828
1143
  var HeaderFilterField = class extends AbstractEditor {
@@ -862,11 +1177,11 @@ var ColumnFilter = class extends AbstractElement {
862
1177
  }
863
1178
  async getApplyButton() {
864
1179
  const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${APPLY_SELECTOR}`;
865
- return this.driver.findElement(By9.css(selector));
1180
+ return this.driver.findElement(By11.css(selector));
866
1181
  }
867
1182
  async getCancelButton() {
868
1183
  const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${CANCEL_SELECTOR}`;
869
- return this.driver.findElement(By9.css(selector));
1184
+ return this.driver.findElement(By11.css(selector));
870
1185
  }
871
1186
  async apply() {
872
1187
  const btn = await this.getApplyButton();
@@ -880,9 +1195,9 @@ var ColumnFilter = class extends AbstractElement {
880
1195
  const columnEl = await this._column.getElement();
881
1196
  const actions = this.driver.actions({ async: true });
882
1197
  await actions.move({ origin: columnEl }).perform();
883
- const elements = await columnEl.findElements(By9.css(HEADER_FILTER_ICON));
1198
+ const elements = await columnEl.findElements(By11.css(HEADER_FILTER_ICON));
884
1199
  let headerFilterIcon = null;
885
- await wait(
1200
+ await safeWait(
886
1201
  async () => {
887
1202
  let result = false;
888
1203
  for (let element of elements) {
@@ -897,12 +1212,11 @@ var ColumnFilter = class extends AbstractElement {
897
1212
  this.driver,
898
1213
  `HeaderFilter "${this._name}" is not visible`
899
1214
  );
900
- if (!headerFilterIcon)
901
- throw new Error(`HeaderFilter "${this._name}" is not visible`);
902
- await headerFilterIcon.click();
1215
+ if (!headerFilterIcon) throw new Error(`HeaderFilter "${this._name}" is not visible`);
1216
+ await click(headerFilterIcon, this.driver);
903
1217
  const filter = new HeaderFilterField("", this._formName, this._name, this.driver);
904
1218
  const filterEl = await filter.getElement();
905
- await waitElementIsVisible({
1219
+ await waitElementIsVisible_default({
906
1220
  element: filterEl,
907
1221
  driver: this.driver,
908
1222
  errorMessage: `Header filter is not visible`
@@ -930,16 +1244,18 @@ var ColumnFilter = class extends AbstractElement {
930
1244
  */
931
1245
  async setValue(value, operation, isBlank) {
932
1246
  const filter = await this.initFilter();
933
- const inputEl = await filter.getElement();
934
- await inputEl.click();
935
1247
  const filterOperation = new FilterOperation({
936
1248
  parentCssSelector: HEADER_FILTER_CONTAINER,
937
- filterTestID: createHeaderFilterTestId(this._formName, this._name)
1249
+ filterTestID: createHeaderFilterTestId(this._formName, this._name),
1250
+ driver: this.driver
938
1251
  });
1252
+ const inputEl = await filter.getElement();
939
1253
  if (typeof operation === "string") {
1254
+ await inputEl.click();
940
1255
  await filterOperation.setOperation(operation);
941
1256
  }
942
1257
  if (typeof isBlank === "boolean") {
1258
+ await inputEl.click();
943
1259
  await filterOperation.setIsBlank(isBlank);
944
1260
  }
945
1261
  await filter.setValue(value);
@@ -974,7 +1290,8 @@ var ColumnFilter = class extends AbstractElement {
974
1290
  await inputEl.click();
975
1291
  return new FilterOperation({
976
1292
  parentCssSelector: HEADER_FILTER_CONTAINER,
977
- filterTestID: createHeaderFilterTestId(this._formName, this._name)
1293
+ filterTestID: createHeaderFilterTestId(this._formName, this._name),
1294
+ driver: this.driver
978
1295
  });
979
1296
  }
980
1297
  /**
@@ -1021,16 +1338,19 @@ var ColumnFilter = class extends AbstractElement {
1021
1338
  var DATAGRID_HEADER_CSS_SELECTOR = ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
1022
1339
  var DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-content:not(.dx-datagrid-content-fixed)";
1023
1340
  var FIXED_DATAGRID_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
1341
+ var CONTEXT_MENU_CSS_SELECTOR = ".dx-datagrid";
1024
1342
  var ListForm = class extends Form {
1025
1343
  headerCssSelector;
1026
1344
  fixedTableContentCssSelector;
1027
1345
  tableContentCssSelector;
1346
+ contextMenuCssSelector;
1028
1347
  constructor(driver) {
1029
1348
  super(driver);
1030
1349
  this.popupContainerCssSelector = `.popup.form-inline-${this.formName}`;
1031
1350
  this.headerCssSelector = DATAGRID_HEADER_CSS_SELECTOR;
1032
1351
  this.fixedTableContentCssSelector = FIXED_DATAGRID_CONTENT_CSS_SELECTOR;
1033
1352
  this.tableContentCssSelector = DATAGRID_CONTENT_CSS_SELECTOR;
1353
+ this.contextMenuCssSelector = CONTEXT_MENU_CSS_SELECTOR;
1034
1354
  }
1035
1355
  /**
1036
1356
  * Находит таблицу
@@ -1041,12 +1361,15 @@ var ListForm = class extends Form {
1041
1361
  */
1042
1362
  table() {
1043
1363
  return new Table(
1044
- this.containerCssSelector,
1045
- this.headerCssSelector,
1046
- this.tableContentCssSelector,
1047
- this.fixedTableContentCssSelector,
1048
- this.formName,
1049
- this.driver
1364
+ {
1365
+ parentCssSelector: this.containerCssSelector,
1366
+ headerCssSelector: this.headerCssSelector,
1367
+ fixedTableContentCssSelector: this.fixedTableContentCssSelector,
1368
+ formName: this.formName,
1369
+ driver: this.driver,
1370
+ contextMenuCssSelector: this.contextMenuCssSelector,
1371
+ tableContentCssSelector: this.tableContentCssSelector
1372
+ }
1050
1373
  );
1051
1374
  }
1052
1375
  /**