d5-testing-library 1.9.0-alpha.2 → 1.9.0-alpha.21

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.
@@ -512,6 +512,24 @@ var init_ClearButtonStrategy = __esm({
512
512
  }
513
513
  });
514
514
 
515
+ // src/utils/withCustomTimeouts.ts
516
+ async function withCustomTimeouts({ driver, timeout, callback }) {
517
+ const { implicit: defaultTimeout } = await driver.manage().getTimeouts();
518
+ try {
519
+ await driver.manage().setTimeouts({ implicit: timeout ?? defaultTimeout });
520
+ return await callback();
521
+ } finally {
522
+ await driver.manage().setTimeouts({ implicit: defaultTimeout });
523
+ }
524
+ }
525
+ var withCustomTimeouts_default;
526
+ var init_withCustomTimeouts = __esm({
527
+ "src/utils/withCustomTimeouts.ts"() {
528
+ "use strict";
529
+ withCustomTimeouts_default = withCustomTimeouts;
530
+ }
531
+ });
532
+
515
533
  // src/pageObjects/elements/Editors/SelectBoxEditor.ts
516
534
  var import_selenium_webdriver9, SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, combinedValueXpath, dropDownOptionClick, SelectBoxEditor;
517
535
  var init_SelectBoxEditor = __esm({
@@ -522,21 +540,22 @@ var init_SelectBoxEditor = __esm({
522
540
  init_xpathHelper();
523
541
  init_actions();
524
542
  init_ClearButtonStrategy();
543
+ init_withCustomTimeouts();
525
544
  SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS = "d5-multi-select-item";
526
545
  combinedValueXpath = (value) => `//body/div[@id="root"]/div[contains(@class, "dx-overlay-wrapper")]//${XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value)}`;
527
546
  dropDownOptionClick = async (optionValue, driver, delay = true) => {
528
- const { implicit } = await driver.manage().getTimeouts();
529
- let optElement = null;
530
- const timeout = delay ? implicit : 200;
531
547
  let err = null;
532
548
  try {
533
- await driver.manage().setTimeouts({ implicit: timeout });
534
- optElement = await driver.findElement(import_selenium_webdriver9.By.xpath(combinedValueXpath(optionValue)));
535
- await click(optElement, driver);
549
+ await withCustomTimeouts_default({
550
+ driver,
551
+ timeout: delay ? void 0 : 200,
552
+ callback: async () => {
553
+ let optElement = await driver.findElement(import_selenium_webdriver9.By.xpath(combinedValueXpath(optionValue)));
554
+ await click(optElement, driver);
555
+ }
556
+ });
536
557
  } catch (e) {
537
558
  err = new Error(`Item not found: "${optionValue}"`);
538
- } finally {
539
- await driver.manage().setTimeouts({ implicit });
540
559
  }
541
560
  if (err)
542
561
  throw err;
@@ -602,7 +621,7 @@ var init_SwitchEditor = __esm({
602
621
  });
603
622
 
604
623
  // src/pageObjects/elements/Editors/TagBox.ts
605
- var import_selenium_webdriver10, TAGS_SELECTOR, DX_TAG_CONTAINER, DX_TEXTEDITOR_EMPTY2, BTN_OK_SELECTOR, TAG_BOX_LIST_ITEM_SELECTOR, TagBox;
624
+ var import_selenium_webdriver10, TAGS_SELECTOR, DX_TAG_CONTAINER, DX_TEXTEDITOR_EMPTY2, BTN_OK_SELECTOR, getSelectedOptionXpath, TagBox;
606
625
  var init_TagBox = __esm({
607
626
  "src/pageObjects/elements/Editors/TagBox.ts"() {
608
627
  "use strict";
@@ -618,7 +637,7 @@ var init_TagBox = __esm({
618
637
  DX_TAG_CONTAINER = "dx-tag-container";
619
638
  DX_TEXTEDITOR_EMPTY2 = "dx-texteditor-empty";
620
639
  BTN_OK_SELECTOR = ".dx-tagbox-popup-wrapper .dx-popup-bottom .dx-button.dx-popup-done";
621
- TAG_BOX_LIST_ITEM_SELECTOR = '.dx-tagbox-popup-wrapper .dx-list-item[aria-selected="true"]';
640
+ getSelectedOptionXpath = (value) => `//body/div[@id="root"]/div[contains(@class, "dx-overlay-wrapper")]//div[contains(@class, 'dx-list-item') and @aria-selected="true"]//div[contains(., "${value}")]`;
622
641
  TagBox = class extends AbstractDXEditorWithInput {
623
642
  constructor(parentCssSelector, elementCssSelector, driver) {
624
643
  super(parentCssSelector, elementCssSelector, driver);
@@ -633,9 +652,15 @@ var init_TagBox = __esm({
633
652
  }
634
653
  await this.confirmSelection();
635
654
  }
636
- async waitOptionSelection() {
637
- const option = await fixElementStaleError(import_selenium_webdriver10.By.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
638
- await safeWait(() => option.isDisplayed(), this.driver);
655
+ async waitOptionSelection(value) {
656
+ await safeWait(
657
+ async () => {
658
+ const elements = await this.driver.findElements(import_selenium_webdriver10.By.xpath(getSelectedOptionXpath(value)));
659
+ if (elements.length === 0) return false;
660
+ return await elements[0].isDisplayed();
661
+ },
662
+ this.driver
663
+ );
639
664
  }
640
665
  async selectOption(inputEl, value, lastElement) {
641
666
  try {
@@ -644,7 +669,7 @@ var init_TagBox = __esm({
644
669
  await inputEl.sendKeys(value);
645
670
  await dropDownOptionClick(value, this.driver);
646
671
  }
647
- await this.waitOptionSelection();
672
+ await this.waitOptionSelection(value);
648
673
  if (value !== lastElement) {
649
674
  await inputEl.clear();
650
675
  }
@@ -756,19 +781,30 @@ var init_BooleanSelector = __esm({
756
781
  });
757
782
 
758
783
  // src/pageObjects/elements/Editors/Date/utils.ts
759
- var formatDMYDate;
784
+ var formatDMYDate, formatToDateTime;
760
785
  var init_utils = __esm({
761
786
  "src/pageObjects/elements/Editors/Date/utils.ts"() {
762
787
  "use strict";
763
- formatDMYDate = (date) => {
764
- const [year, month, day] = date.toJSON().split("T")[0].split("-");
765
- return `${day}${month}${year}`;
788
+ formatDMYDate = (date, isTimeAllowed = false) => {
789
+ const [year, month, day] = date.toISOString().split("T")[0].split("-");
790
+ if (!isTimeAllowed) {
791
+ return `${day}${month}${year}`;
792
+ }
793
+ const hours = String(date.getHours()).padStart(2, "0");
794
+ const minutes = String(date.getMinutes()).padStart(2, "0");
795
+ return `${day}${month}${year}${hours}${minutes}`;
796
+ };
797
+ formatToDateTime = (dateString) => {
798
+ const [datePart, timePart] = dateString.split("T");
799
+ const [year, month, day] = datePart.split("-").map(Number);
800
+ const [hours, minutes] = timePart.split(":").map(Number);
801
+ return new Date(year, month - 1, day, hours, minutes, 0, 0);
766
802
  };
767
803
  }
768
804
  });
769
805
 
770
806
  // src/pageObjects/elements/Editors/Date/BaseDateEditor.ts
771
- var import_selenium_webdriver12, BTN_CALENDAR_POPOVER_OPEN_SELECTOR, BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR, BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR, BTN_SAVE_SELECTOR, BaseDateEditor;
807
+ var import_selenium_webdriver12, BTN_CALENDAR_POPOVER_OPEN_SELECTOR, BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR, BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR, BTN_SAVE_SELECTOR, DATETIME_ALLOWED_SELECTOR, BaseDateEditor;
772
808
  var init_BaseDateEditor = __esm({
773
809
  "src/pageObjects/elements/Editors/Date/BaseDateEditor.ts"() {
774
810
  "use strict";
@@ -782,11 +818,17 @@ var init_BaseDateEditor = __esm({
782
818
  BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR = "DateRange__inputs-item--dateFrom";
783
819
  BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR = "DateRange__inputs-item--dateTo";
784
820
  BTN_SAVE_SELECTOR = "DateRange__button-save";
821
+ DATETIME_ALLOWED_SELECTOR = "dx-datebox-datetime";
785
822
  BaseDateEditor = class extends AbstractDXEditorWithInput {
786
823
  constructor(parentCssSelector, elementCssSelector, driver) {
787
824
  super(parentCssSelector, elementCssSelector, driver);
788
825
  this.setClearStrategy(new InputClearStrategy());
789
826
  }
827
+ async getIsAllowedTime() {
828
+ const dateField = await this.driver.findElement(import_selenium_webdriver12.By.css(`${this.getFullCssSelector()}`));
829
+ const classString = await dateField.getAttribute("class");
830
+ return classString.includes(DATETIME_ALLOWED_SELECTOR);
831
+ }
790
832
  async setArrayValue(value) {
791
833
  const dateField = await this.driver.findElement(import_selenium_webdriver12.By.css(`${this.getFullCssSelector()}`));
792
834
  const dateFieldDataTestID = await this.getDataTestId();
@@ -806,7 +848,8 @@ var init_BaseDateEditor = __esm({
806
848
  }
807
849
  async setSingleValue(value, inputEl) {
808
850
  const actions = this.driver.actions({ async: true });
809
- const formattedDate = formatDMYDate(value);
851
+ const isTimeAllowed = await this.getIsAllowedTime();
852
+ const formattedDate = formatDMYDate(value, isTimeAllowed);
810
853
  await click(inputEl, this.driver);
811
854
  await actions.move({ origin: inputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
812
855
  await actions.move({ origin: inputEl }).sendKeys(formattedDate, import_selenium_webdriver12.Key.ENTER).perform();
@@ -830,6 +873,7 @@ var init_SingleDateEditor = __esm({
830
873
  import_selenium_webdriver13 = require("selenium-webdriver");
831
874
  init_InputClearStrategy();
832
875
  init_BaseDateEditor();
876
+ init_utils();
833
877
  SingleDateEditor = class extends BaseDateEditor {
834
878
  constructor(parentCssSelector, elementCssSelector, driver) {
835
879
  super(parentCssSelector, elementCssSelector, driver);
@@ -844,6 +888,10 @@ var init_SingleDateEditor = __esm({
844
888
  }
845
889
  async getValue() {
846
890
  const value = await this.getDateValue();
891
+ const isTimeAllowed = await this.getIsAllowedTime();
892
+ if (isTimeAllowed) {
893
+ return value == "" ? null : formatToDateTime(value);
894
+ }
847
895
  return value == "" ? null : new Date(value);
848
896
  }
849
897
  setValue(value) {
@@ -941,7 +989,7 @@ var init_DateEditor = __esm({
941
989
  });
942
990
 
943
991
  // src/pageObjects/elements/Editors/HeaderFilterDictionary.ts
944
- var import_selenium_webdriver15, TAGS_SELECTOR2, DX_TAG_CONTAINER2, DX_TEXTEDITOR_EMPTY3, CUSTOM_OPTION_LIST_SELECTOR, SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2, TAG_BOX_LIST_ITEM_SELECTOR2, combinedOptionHeaderFilterDictValueXpath, dropDownHeaderFilterDictionaryOptionClick, HeaderFilterDictionary;
992
+ var import_selenium_webdriver15, TAGS_SELECTOR2, DX_TAG_CONTAINER2, DX_TEXTEDITOR_EMPTY3, CUSTOM_OPTION_LIST_SELECTOR, SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2, TAG_BOX_LIST_ITEM_SELECTOR, combinedOptionHeaderFilterDictValueXpath, dropDownHeaderFilterDictionaryOptionClick, HeaderFilterDictionary;
945
993
  var init_HeaderFilterDictionary = __esm({
946
994
  "src/pageObjects/elements/Editors/HeaderFilterDictionary.ts"() {
947
995
  "use strict";
@@ -951,29 +999,30 @@ var init_HeaderFilterDictionary = __esm({
951
999
  init_locators();
952
1000
  init_ClearButtonStrategy();
953
1001
  init_fixElementStaleError();
1002
+ init_withCustomTimeouts();
954
1003
  TAGS_SELECTOR2 = ".dx-tag .tag-text";
955
1004
  DX_TAG_CONTAINER2 = "dx-tag-container";
956
1005
  DX_TEXTEDITOR_EMPTY3 = "dx-texteditor-empty";
957
1006
  CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
958
1007
  SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
959
- TAG_BOX_LIST_ITEM_SELECTOR2 = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
1008
+ TAG_BOX_LIST_ITEM_SELECTOR = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
960
1009
  combinedOptionHeaderFilterDictValueXpath = (value) => `//div[contains(@class, '${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}') and contains(text(), '${value}')]`;
961
1010
  dropDownHeaderFilterDictionaryOptionClick = async (optionValue, driver, dataTEST = "", delay = true) => {
962
- const { implicit } = await driver.manage().getTimeouts();
963
- let optElement = null;
964
- const timeout = delay ? implicit : 600;
965
1011
  let err = null;
966
1012
  try {
967
1013
  const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
968
- await driver.manage().setTimeouts({ implicit: timeout });
969
- const calendarPopoverElement = await driver.findElement(import_selenium_webdriver15.By.css(calendarPopoverSelector));
970
- const customOptionList = calendarPopoverElement.findElement(import_selenium_webdriver15.By.css(`.${CUSTOM_OPTION_LIST_SELECTOR}`));
971
- optElement = await customOptionList.findElement(import_selenium_webdriver15.By.xpath(combinedOptionHeaderFilterDictValueXpath(optionValue)));
972
- await click(optElement, driver);
1014
+ await withCustomTimeouts_default({
1015
+ driver,
1016
+ timeout: delay ? void 0 : 600,
1017
+ callback: async () => {
1018
+ const calendarPopoverElement = await driver.findElement(import_selenium_webdriver15.By.css(calendarPopoverSelector));
1019
+ const customOptionList = calendarPopoverElement.findElement(import_selenium_webdriver15.By.css(`.${CUSTOM_OPTION_LIST_SELECTOR}`));
1020
+ const optElement = await customOptionList.findElement(import_selenium_webdriver15.By.xpath(combinedOptionHeaderFilterDictValueXpath(optionValue)));
1021
+ await click(optElement, driver);
1022
+ }
1023
+ });
973
1024
  } catch (e) {
974
1025
  err = new Error(`Item not found: "${optionValue}"`);
975
- } finally {
976
- await driver.manage().setTimeouts({ implicit });
977
1026
  }
978
1027
  if (err)
979
1028
  throw err;
@@ -992,7 +1041,7 @@ var init_HeaderFilterDictionary = __esm({
992
1041
  }
993
1042
  }
994
1043
  async waitOptionSelection() {
995
- await fixElementStaleError(import_selenium_webdriver15.By.css(TAG_BOX_LIST_ITEM_SELECTOR2), this.driver);
1044
+ await fixElementStaleError(import_selenium_webdriver15.By.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
996
1045
  }
997
1046
  async selectOption(inputEl, value, lastElement) {
998
1047
  try {
@@ -1136,13 +1185,14 @@ var init_createDataTestId = __esm({
1136
1185
  });
1137
1186
 
1138
1187
  // src/pageObjects/elements/AbstractButton.ts
1139
- var AbstractButton;
1188
+ var D5_BUTTON_IS_PRESSED, AbstractButton;
1140
1189
  var init_AbstractButton = __esm({
1141
1190
  "src/pageObjects/elements/AbstractButton.ts"() {
1142
1191
  "use strict";
1143
1192
  init_AbstractElementWithParent();
1144
1193
  init_actions();
1145
1194
  init_waitElementIsClickable();
1195
+ D5_BUTTON_IS_PRESSED = "d5-is-pressed";
1146
1196
  AbstractButton = class extends AbstractElementWithParent {
1147
1197
  constructor(parentCssSelector, elementCssSelector, driver) {
1148
1198
  super(parentCssSelector, elementCssSelector, driver);
@@ -1168,6 +1218,15 @@ var init_AbstractButton = __esm({
1168
1218
  return false;
1169
1219
  }
1170
1220
  }
1221
+ async isPressed() {
1222
+ try {
1223
+ const button = await this.getElement();
1224
+ const classAttribute = await button.getAttribute("class");
1225
+ return classAttribute.includes(D5_BUTTON_IS_PRESSED);
1226
+ } catch {
1227
+ return false;
1228
+ }
1229
+ }
1171
1230
  };
1172
1231
  }
1173
1232
  });
@@ -1467,6 +1526,7 @@ var init_AbstractForm = __esm({
1467
1526
  init_AbstractPage();
1468
1527
  init_FormButton();
1469
1528
  init_FormGroup();
1529
+ init_waitElementIsVisible();
1470
1530
  AbstractForm = class extends AbstractPage {
1471
1531
  containerCssSelector = "";
1472
1532
  _formName = "";
@@ -1491,7 +1551,15 @@ var init_AbstractForm = __esm({
1491
1551
  async exists() {
1492
1552
  try {
1493
1553
  let elements = await this.driver.findElements(this.containerBy);
1494
- return elements.length > 0;
1554
+ if (elements.length === 0) {
1555
+ return false;
1556
+ }
1557
+ await waitElementIsVisible_default({
1558
+ element: elements[0],
1559
+ errorMessage: "Element exists in DOM but is not visible",
1560
+ driver: this.driver
1561
+ });
1562
+ return true;
1495
1563
  } catch (error) {
1496
1564
  return false;
1497
1565
  }
@@ -1594,7 +1662,7 @@ var init_Cell = __esm({
1594
1662
  const [datePart, timePart] = value.split(", ");
1595
1663
  const [day, month, year] = datePart.split(".").map(Number);
1596
1664
  const [hours, minutes] = timePart.split(":").map(Number);
1597
- return new Date(Date.UTC(year, month - 1, day, hours, minutes));
1665
+ return new Date(year, month - 1, day, hours, minutes, 0, 0);
1598
1666
  } else {
1599
1667
  const [day, month, year] = value.split(".").map(Number);
1600
1668
  return new Date(Date.UTC(year, month - 1, day));
@@ -1678,9 +1746,18 @@ var init_Row = __esm({
1678
1746
  getCellByTitle(title) {
1679
1747
  return this._getCell({ title });
1680
1748
  }
1681
- async select() {
1749
+ async select(preserve = false) {
1682
1750
  await staleElementAction(async () => {
1683
1751
  const rowEl = await this.getElement();
1752
+ const isSelected = (await this.getClasses()).includes(DX_SELECTION_CLASS);
1753
+ if (isSelected && !preserve) {
1754
+ await this.driver.actions({ async: true }).keyUp(import_selenium_webdriver22.Key.CONTROL).perform();
1755
+ }
1756
+ if (preserve && !isSelected) {
1757
+ await this.driver.actions({ async: true }).keyDown(import_selenium_webdriver22.Key.CONTROL).perform();
1758
+ await click(rowEl, this.driver);
1759
+ return;
1760
+ }
1684
1761
  await click(rowEl, this.driver);
1685
1762
  });
1686
1763
  await safeWait(
@@ -2013,8 +2090,8 @@ var init_AbstractDropDownMenuList = __esm({
2013
2090
  const menuItemElement = await fixElementStaleError(by, this.driver);
2014
2091
  await click(menuItemElement, this.driver);
2015
2092
  }
2016
- async getElementByPath(path, getBy, returnLastElement = false) {
2017
- let pathList = isString(path) ? [path] : path;
2093
+ async getElementByPath(path2, getBy, returnLastElement = false) {
2094
+ let pathList = isString(path2) ? [path2] : path2;
2018
2095
  let result = null;
2019
2096
  let index = 1;
2020
2097
  for (let text of pathList) {
@@ -2086,7 +2163,7 @@ var init_DXContextMenuList = __esm({
2086
2163
  async isVisible() {
2087
2164
  try {
2088
2165
  await waitElementIsVisible_default({
2089
- element: await this.driver.findElement(import_selenium_webdriver24.By.css(`.dx-overlay-wrapper .dx-contextmenu`)),
2166
+ element: await this.driver.findElement(import_selenium_webdriver24.By.css(`.dx-overlay-wrapper .dx-context-menu`)),
2090
2167
  driver: this.driver,
2091
2168
  errorMessage: "Cannot find dropdown element"
2092
2169
  });
@@ -2144,6 +2221,8 @@ var init_Table = __esm({
2144
2221
  init_FormField();
2145
2222
  init_ContextMenu();
2146
2223
  init_actions();
2224
+ init_wait();
2225
+ init_withCustomTimeouts();
2147
2226
  Table = class extends AbstractElementWithParent {
2148
2227
  formName;
2149
2228
  headerCssSelector;
@@ -2209,13 +2288,32 @@ var init_Table = __esm({
2209
2288
  /**
2210
2289
  * Вибрати рядок по індексу.
2211
2290
  * @param index починається з 0
2291
+ * @param preserve boolean який изначає, чи повинні раніше вибрані рядки залишатися вибраними
2212
2292
  */
2213
- selectRowByIndex(index) {
2214
- return this.getRowByIndex(index).select();
2293
+ selectRowByIndex(index, preserve = false) {
2294
+ return this.getRowByIndex(index).select(preserve);
2215
2295
  }
2216
- async getRows() {
2296
+ /**
2297
+ * Вибрати масив рядків по індексу.
2298
+ * @param indexes починається з 0
2299
+ */
2300
+ async selectRowsByIndexes(indexes) {
2301
+ for (const index of indexes) {
2302
+ await this.selectRowByIndex(index, true);
2303
+ }
2304
+ }
2305
+ getRowElements(timeout) {
2217
2306
  const rowsFullCssSelector = `${this.getFullCssSelector()} ${this.tableContentCssSelector} .dx-row.dx-data-row`;
2218
- const rows = await this.driver.findElements(import_selenium_webdriver25.By.css(rowsFullCssSelector));
2307
+ return withCustomTimeouts_default({
2308
+ driver: this.driver,
2309
+ timeout,
2310
+ callback: () => {
2311
+ return this.driver.findElements(import_selenium_webdriver25.By.css(rowsFullCssSelector));
2312
+ }
2313
+ });
2314
+ }
2315
+ async getRows() {
2316
+ const rows = await this.getRowElements();
2219
2317
  const result = [];
2220
2318
  rows.forEach((_, index) => {
2221
2319
  const newRow = new Row(
@@ -2301,6 +2399,72 @@ var init_Table = __esm({
2301
2399
  await contextMenu(cellElement, this.driver);
2302
2400
  });
2303
2401
  }
2402
+ /**
2403
+ * Отримує значення комірки таблиці за ім'ям комірки та індексом рядка.
2404
+ *
2405
+ * @param {string} cellName - Ім'я комірки (поля) в таблиці
2406
+ * @param {number} rowIndex - Індекс рядка (починається з 0)
2407
+ * @throws {Error} Викидає помилку, якщо rowIndex не вказано
2408
+ * @returns {Promise<string>} Повертає значення комірки
2409
+ *
2410
+ * @example
2411
+ * const table = new Table(driver);
2412
+ *
2413
+ * // Отримання значення комірки 'Name' в першому рядку (індекс 0)
2414
+ * const cellValue = await table.getCellValueByCellName('Name', 0);
2415
+ * expect(cellValue).toBe('Очікуване значення');
2416
+ */
2417
+ getCellValueByCellName(cellName, rowIndex) {
2418
+ if (rowIndex == null) {
2419
+ throw new Error("Error: getCellValue(): rowIndex is required");
2420
+ }
2421
+ const row = this.getRowByIndex(rowIndex);
2422
+ return row.getCell(cellName).getValue();
2423
+ }
2424
+ /**
2425
+ * Перевіряє, чи є таблиця порожньою (не містить жодного рядка з даними).
2426
+ *
2427
+ * @returns {Promise<boolean>} Повертає true, якщо таблиця порожня, false - якщо містить рядки
2428
+ *
2429
+ * @example
2430
+ * const table = new Table(driver);
2431
+ *
2432
+ * // Перевірка чи порожня таблиця
2433
+ * const empty = await table.isEmpty();
2434
+ * expect(empty).toBe(true);
2435
+ */
2436
+ async isEmpty() {
2437
+ try {
2438
+ await this.waitRowsCount(0);
2439
+ return true;
2440
+ } catch {
2441
+ return false;
2442
+ }
2443
+ }
2444
+ /**
2445
+ * Очікує, поки кількість рядків у таблиці не стане рівною заданому значенню.
2446
+ * Використовується для синхронізації тестів з динамічним завантаженням даних.
2447
+ *
2448
+ * @param {number} count - Очікувана кількість рядків у таблиці
2449
+ * @returns {Promise<void>} Повертає Promise, який виконується, коли кількість рядків відповідає очікуваній
2450
+ * @throws {Error} Викидає помилку, якщо очікування перевищує тайм-аут
2451
+ *
2452
+ * @example
2453
+ * const table = new Table(driver);
2454
+ *
2455
+ * // Очікування, поки таблиця не стане порожньою
2456
+ * await table.waitRowsCount(0);
2457
+ *
2458
+ * // Очікування, поки в таблиці не з'явиться 5 рядків
2459
+ * await table.waitRowsCount(5);
2460
+ * console.log('Таблиця містить 5 рядків');
2461
+ */
2462
+ async waitRowsCount(count) {
2463
+ await safeWait(async () => {
2464
+ const rows = await this.getRowElements(1e3);
2465
+ return rows.length === count;
2466
+ }, this.driver, `Rows count not equal: ${count}`);
2467
+ }
2304
2468
  };
2305
2469
  }
2306
2470
  });
@@ -2567,6 +2731,14 @@ var init_ToolbarItem = __esm({
2567
2731
  return false;
2568
2732
  }
2569
2733
  }
2734
+ async isPressed() {
2735
+ try {
2736
+ await this.init();
2737
+ return this._button.isPressed();
2738
+ } catch (error) {
2739
+ return false;
2740
+ }
2741
+ }
2570
2742
  async getTitle() {
2571
2743
  await this.init();
2572
2744
  return await this._button.getTitle();
@@ -3020,7 +3192,7 @@ var init_ColumnFilter = __esm({
3020
3192
  init_wait();
3021
3193
  APPLY_SELECTOR = ".apply-button";
3022
3194
  CANCEL_SELECTOR = ".cancel-button";
3023
- HEADER_FILTER_ICON = ".dx-column-indicators .dx-header-filter";
3195
+ HEADER_FILTER_ICON = ".indicators-container .filter-icon";
3024
3196
  HEADER_FILTER_CONTAINER = ".header-filter";
3025
3197
  HEADER_FILTER_BUTTONS = ".header-filter-buttons";
3026
3198
  ColumnFilter = class extends AbstractElement {
@@ -3054,24 +3226,15 @@ var init_ColumnFilter = __esm({
3054
3226
  const columnEl = await this._column.getElement();
3055
3227
  const actions = this.driver.actions({ async: true });
3056
3228
  await actions.move({ origin: columnEl }).perform();
3057
- const elements = await columnEl.findElements(import_selenium_webdriver30.By.css(HEADER_FILTER_ICON));
3058
- let headerFilterIcon = null;
3229
+ const headerFilterIconBy = import_selenium_webdriver30.By.css(HEADER_FILTER_ICON);
3230
+ let headerFilterIcon = await columnEl.findElement(headerFilterIconBy);
3059
3231
  await safeWait(
3060
- async () => {
3061
- let result = false;
3062
- for (let element of elements) {
3063
- if (await element.isDisplayed()) {
3064
- headerFilterIcon = element;
3065
- result = true;
3066
- break;
3067
- }
3068
- }
3069
- return result;
3232
+ () => {
3233
+ return headerFilterIcon.isDisplayed();
3070
3234
  },
3071
3235
  this.driver,
3072
3236
  `HeaderFilter "${this._name}" is not visible`
3073
3237
  );
3074
- if (!headerFilterIcon) throw new Error(`HeaderFilter "${this._name}" is not visible`);
3075
3238
  await click(headerFilterIcon, this.driver);
3076
3239
  const filter = new HeaderFilterField("", this._formName, this._name, this.driver);
3077
3240
  const filterEl = await filter.getElement();
@@ -3210,9 +3373,9 @@ var init_ListForm = __esm({
3210
3373
  init_FormFilterField();
3211
3374
  init_FilterPanel();
3212
3375
  init_ColumnFilter();
3213
- DATAGRID_HEADER_CSS_SELECTOR = ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
3214
- DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-content:not(.dx-datagrid-content-fixed)";
3215
- FIXED_DATAGRID_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
3376
+ DATAGRID_HEADER_CSS_SELECTOR = ".dx-datagrid-headers .dx-datagrid-content .dx-datagrid-table.dx-datagrid-table-fixed";
3377
+ DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-content .dx-datagrid-table.dx-datagrid-table-fixed";
3378
+ FIXED_DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-sticky-columns .dx-datagrid-content .dx-datagrid-table.dx-datagrid-table-fixed";
3216
3379
  CONTEXT_MENU_CSS_SELECTOR = ".dx-datagrid";
3217
3380
  ListForm = class extends Form {
3218
3381
  headerCssSelector;
@@ -3297,9 +3460,9 @@ var init_TreeView = __esm({
3297
3460
  "src/pageObjects/elements/Forms/TreeView.ts"() {
3298
3461
  "use strict";
3299
3462
  init_ListForm();
3300
- TREELIST_HEADER_CSS_SELECTOR = ".dx-treelist-headers .dx-treelist-content:not(.dx-datagrid-content-fixed)";
3301
- TREELIST_CONTENT_CSS_SELECTOR = ".dx-treelist-content:not(.dx-datagrid-content-fixed)";
3302
- FIXED_TREELIST_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-treelist-content.dx-treelist-content-fixed";
3463
+ TREELIST_HEADER_CSS_SELECTOR = ".dx-treelist-headers .dx-treelist-content .dx-treelist-table.dx-treelist-table-fixed";
3464
+ TREELIST_CONTENT_CSS_SELECTOR = ".dx-treelist-content .dx-treelist-table.dx-treelist-table-fixed";
3465
+ FIXED_TREELIST_CONTENT_CSS_SELECTOR = ".dx-treelist-sticky-columns .dx-treelist-content .dx-treelist-table.dx-treelist-table-fixed";
3303
3466
  TreeView = class extends ListForm {
3304
3467
  constructor(driver) {
3305
3468
  super(driver);
@@ -3600,6 +3763,9 @@ init_locators();
3600
3763
 
3601
3764
  // src/utils/createDriver.ts
3602
3765
  var import_selenium_webdriver4 = require("selenium-webdriver");
3766
+ var import_node_path = __toESM(require("path"));
3767
+ var import_node_fs = __toESM(require("fs"));
3768
+ var import_node_os = __toESM(require("os"));
3603
3769
  init_config();
3604
3770
  var import_chrome = __toESM(require("selenium-webdriver/chrome"));
3605
3771
  var import_firefox = __toESM(require("selenium-webdriver/firefox"));
@@ -3607,7 +3773,15 @@ function chromeOptions(builder, options) {
3607
3773
  const ChromeOptions = new import_chrome.default.Options();
3608
3774
  if (options.headless) {
3609
3775
  ChromeOptions.addArguments(`--headless=new`);
3776
+ ChromeOptions.addArguments(`--disable-gpu`);
3777
+ ChromeOptions.addArguments(`--disable-dev-shm-usage`);
3778
+ ChromeOptions.addArguments(`--window-size=1920,1080`);
3610
3779
  }
3780
+ const userDataDir = import_node_path.default.join(import_node_os.default.tmpdir(), ".chrome-cache");
3781
+ if (!import_node_fs.default.existsSync(userDataDir)) {
3782
+ import_node_fs.default.mkdirSync(userDataDir, { recursive: true });
3783
+ }
3784
+ ChromeOptions.addArguments(`--user-data-dir=${userDataDir}`);
3611
3785
  return builder.setChromeOptions(ChromeOptions);
3612
3786
  }
3613
3787
  function firefoxOptions(builder, options) {
@@ -3635,7 +3809,9 @@ var createDriver = async (browser) => {
3635
3809
  const driver = await builder.build();
3636
3810
  const manage = driver.manage();
3637
3811
  await manage.setTimeouts({ implicit: config().timeout });
3638
- await manage.window().maximize();
3812
+ if (!headless) {
3813
+ await manage.window().maximize();
3814
+ }
3639
3815
  return driver;
3640
3816
  };
3641
3817