d5-testing-library 1.8.0-alpha.2 → 1.8.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.
@@ -213,7 +213,7 @@ var init_waitElementIsVisible = __esm({
213
213
  });
214
214
 
215
215
  // src/utils/actions.ts
216
- var click;
216
+ var click, contextMenu;
217
217
  var init_actions = __esm({
218
218
  "src/utils/actions.ts"() {
219
219
  "use strict";
@@ -226,6 +226,14 @@ var init_actions = __esm({
226
226
  const actions = driver.actions({ async: true });
227
227
  await actions.move({ origin: webElement }).click().perform();
228
228
  };
229
+ contextMenu = async (webElement, driver) => {
230
+ driver = driver ?? config().driver;
231
+ if (!await webElement.isDisplayed()) {
232
+ await driver.executeScript("arguments[0].scrollIntoView(true);", webElement);
233
+ }
234
+ const actions = driver.actions({ async: true });
235
+ await actions.move({ origin: webElement }).contextClick().perform();
236
+ };
229
237
  }
230
238
  });
231
239
 
@@ -245,6 +253,31 @@ var init_locators = __esm({
245
253
  }
246
254
  });
247
255
 
256
+ // src/utils/waitElementIsClickable.ts
257
+ async function waitElementIsClickable({
258
+ timeout,
259
+ errorMessage,
260
+ driver,
261
+ ...rest
262
+ }) {
263
+ driver = driver ?? config().driver;
264
+ await wait(async () => {
265
+ const searchedElement = "by" in rest ? await fixElementStaleError(rest.by, driver) : rest.element;
266
+ const isDisabled = await searchedElement.getCssValue("pointer-events") === "none";
267
+ return await searchedElement.isDisplayed() && !isDisabled;
268
+ }, driver, errorMessage, timeout ?? config().timeout);
269
+ }
270
+ var waitElementIsClickable_default;
271
+ var init_waitElementIsClickable = __esm({
272
+ "src/utils/waitElementIsClickable.ts"() {
273
+ "use strict";
274
+ init_config();
275
+ init_wait();
276
+ init_fixElementStaleError();
277
+ waitElementIsClickable_default = waitElementIsClickable;
278
+ }
279
+ });
280
+
248
281
  // src/pageObjects/AbstractElementWithParent.ts
249
282
  var AbstractElementWithParent;
250
283
  var init_AbstractElementWithParent = __esm({
@@ -337,8 +370,9 @@ var init_TextEditor = __esm({
337
370
  super(parentCssSelector, elementCssSelector, driver);
338
371
  this.setClearStrategy(new InputClearStrategy());
339
372
  }
340
- getValue() {
341
- return this.getInputValue();
373
+ async getValue() {
374
+ const value = await super.getInputValue();
375
+ return value == "" ? null : value;
342
376
  }
343
377
  setValue(value) {
344
378
  return this.setInputValue(value);
@@ -387,6 +421,7 @@ var init_types = __esm({
387
421
  ControlClass2["SingleDateRange"] = "single-date-range-control";
388
422
  ControlClass2["BooleanSelector"] = "buttons-group";
389
423
  ControlClass2["ButtonGroup"] = "button-group-field";
424
+ ControlClass2["HeaderFilterDictionary"] = "header-filter-dictionary";
390
425
  return ControlClass2;
391
426
  })(ControlClass || {});
392
427
  }
@@ -582,6 +617,7 @@ var init_TagBox = __esm({
582
617
  init_SelectBoxEditor();
583
618
  init_ClearButtonStrategy();
584
619
  init_fixElementStaleError();
620
+ init_wait();
585
621
  TAGS_SELECTOR = ".dx-tag .tag-text";
586
622
  DX_TAG_CONTAINER = "dx-tag-container";
587
623
  DX_TEXTEDITOR_EMPTY2 = "dx-texteditor-empty";
@@ -602,7 +638,8 @@ var init_TagBox = __esm({
602
638
  await this.confirmSelection();
603
639
  }
604
640
  async waitOptionSelection() {
605
- await fixElementStaleError(import_selenium_webdriver10.By.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
641
+ const option = await fixElementStaleError(import_selenium_webdriver10.By.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
642
+ await wait(() => option.isDisplayed(), this.driver);
606
643
  }
607
644
  async selectOption(inputEl, value, lastElement) {
608
645
  try {
@@ -755,33 +792,44 @@ var init_BaseDateEditor = __esm({
755
792
  super(parentCssSelector, elementCssSelector, driver);
756
793
  this.setClearStrategy(new InputClearStrategy());
757
794
  }
758
- async setDateValue(value) {
795
+ async setArrayValue(value) {
759
796
  const actions = this.driver.actions({ async: true });
760
797
  const dateField = await this.driver.findElement(import_selenium_webdriver12.By.css(`${this.getFullCssSelector()}`));
798
+ const dateInputEl = await this.getInputElement();
761
799
  const dateFieldDataTestID = await this.getDataTestId();
762
- const calendarPopoverSelector = byTestIdCssSelector(`${dateFieldDataTestID}-calendar-popover`);
800
+ const formattedDates = value.map(formatDMYDate);
801
+ const button = await dateField.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
802
+ await click(button, this.driver);
803
+ const calendarPopoverElement = await this.driver.findElement(import_selenium_webdriver12.By.css(byTestIdCssSelector(`${dateFieldDataTestID}-calendar-popover`)));
804
+ const dateFromInput = await calendarPopoverElement.findElement(
805
+ import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`)
806
+ );
807
+ const dateToInput = await calendarPopoverElement.findElement(
808
+ import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`)
809
+ );
810
+ await click(dateFromInput, this.driver);
811
+ await dateFromInput.sendKeys(formattedDates[0]);
812
+ await click(dateToInput, this.driver);
813
+ await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
814
+ await dateToInput.sendKeys(formattedDates[1]);
815
+ await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.ENTER).perform();
816
+ const btnOk = await this.driver.findElement(import_selenium_webdriver12.By.css(`.${BTN_SAVE_SELECTOR}`));
817
+ await click(btnOk, this.driver);
818
+ }
819
+ async setSingleValue(value) {
820
+ const actions = this.driver.actions({ async: true });
821
+ const formattedDate = formatDMYDate(value);
763
822
  const dateInputEl = await this.getInputElement();
764
- await dateInputEl.clear();
823
+ await click(dateInputEl, this.driver);
824
+ await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
825
+ await actions.move({ origin: dateInputEl }).sendKeys(formattedDate, import_selenium_webdriver12.Key.ENTER).perform();
826
+ }
827
+ async setDateValue(value) {
828
+ await this.clear();
765
829
  if (Array.isArray(value)) {
766
- const formattedDates = value.map(formatDMYDate);
767
- const button = await dateField.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
768
- await button.click();
769
- const calendarPopoverElement = await this.driver.findElement(import_selenium_webdriver12.By.css(calendarPopoverSelector));
770
- const dateFromInput = await calendarPopoverElement.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`));
771
- const dateToInput = await calendarPopoverElement.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`));
772
- await dateFromInput.click();
773
- await dateFromInput.sendKeys(formattedDates[0]);
774
- await dateToInput.click();
775
- await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
776
- await dateToInput.sendKeys(formattedDates[1]);
777
- await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.ENTER).perform();
778
- const btnOk = await this.driver.findElement(import_selenium_webdriver12.By.css(`.${BTN_SAVE_SELECTOR}`));
779
- await btnOk.click();
830
+ await this.setArrayValue(value);
780
831
  } else {
781
- const formattedDate = formatDMYDate(value);
782
- await click(dateInputEl, this.driver);
783
- await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
784
- await actions.move({ origin: dateInputEl }).sendKeys(formattedDate, import_selenium_webdriver12.Key.ENTER).perform();
832
+ await this.setSingleValue(value);
785
833
  }
786
834
  }
787
835
  };
@@ -872,15 +920,14 @@ var init_DateEditor = __esm({
872
920
  init_types();
873
921
  DateEditor = class extends AbstractDXEditorWithInput {
874
922
  editorInstance = null;
875
- initPromise;
876
- constructor(parentCssSelector, elementCssSelector, driver) {
877
- super(parentCssSelector, elementCssSelector, driver);
878
- this.initPromise = this.init(parentCssSelector, elementCssSelector, driver);
879
- }
880
- async init(parentCssSelector, elementCssSelector, driver) {
881
- await this.updateEditorInstance(parentCssSelector, elementCssSelector, driver);
923
+ async init() {
924
+ if (this.editorInstance) {
925
+ return this.editorInstance;
926
+ }
927
+ await this.setEditorInstance();
882
928
  }
883
- async updateEditorInstance(parentCssSelector, elementCssSelector, driver) {
929
+ async setEditorInstance() {
930
+ const { parentCssSelector, elementCssSelector, driver } = this;
884
931
  const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
885
932
  const classString = await elementInstance.getClasses();
886
933
  switch (true) {
@@ -894,25 +941,116 @@ var init_DateEditor = __esm({
894
941
  this.editorInstance = new SingleDateEditor(parentCssSelector, elementCssSelector, driver);
895
942
  }
896
943
  }
897
- async ensureInitialized() {
898
- if (!this.editorInstance) {
899
- await this.initPromise;
944
+ async setValue(value) {
945
+ await this.init();
946
+ await this.editorInstance.setValue(value);
947
+ await this.setEditorInstance();
948
+ }
949
+ async getValue() {
950
+ await this.init();
951
+ return this.editorInstance.getValue();
952
+ }
953
+ };
954
+ }
955
+ });
956
+
957
+ // src/pageObjects/elements/Editors/HeaderFilterDictionary.ts
958
+ 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;
959
+ var init_HeaderFilterDictionary = __esm({
960
+ "src/pageObjects/elements/Editors/HeaderFilterDictionary.ts"() {
961
+ "use strict";
962
+ init_AbstractEditor();
963
+ import_selenium_webdriver15 = require("selenium-webdriver");
964
+ init_actions();
965
+ init_locators();
966
+ init_ClearButtonStrategy();
967
+ init_fixElementStaleError();
968
+ TAGS_SELECTOR2 = ".dx-tag .tag-text";
969
+ DX_TAG_CONTAINER2 = "dx-tag-container";
970
+ DX_TEXTEDITOR_EMPTY3 = "dx-texteditor-empty";
971
+ CUSTOM_OPTION_LIST_SELECTOR = "custom-list";
972
+ SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2 = "d5-multi-select-item";
973
+ TAG_BOX_LIST_ITEM_SELECTOR2 = '.dx-overlay-wrapper .dx-list-item[aria-selected="true"]';
974
+ combinedOptionHeaderFilterDictValueXpath = (value) => `//div[contains(@class, '${SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS2}') and contains(text(), '${value}')]`;
975
+ dropDownHeaderFilterDictionaryOptionClick = async (optionValue, driver, dataTEST = "", delay = true) => {
976
+ const { implicit } = await driver.manage().getTimeouts();
977
+ let optElement = null;
978
+ const timeout = delay ? implicit : 600;
979
+ let err = null;
980
+ try {
981
+ const calendarPopoverSelector = byTestIdCssSelector(`${dataTEST}`);
982
+ await driver.manage().setTimeouts({ implicit: timeout });
983
+ const calendarPopoverElement = await driver.findElement(import_selenium_webdriver15.By.css(calendarPopoverSelector));
984
+ const customOptionList = calendarPopoverElement.findElement(import_selenium_webdriver15.By.css(`.${CUSTOM_OPTION_LIST_SELECTOR}`));
985
+ optElement = await customOptionList.findElement(import_selenium_webdriver15.By.xpath(combinedOptionHeaderFilterDictValueXpath(optionValue)));
986
+ await click(optElement, driver);
987
+ } catch (e) {
988
+ err = new Error(`Item not found: "${optionValue}"`);
989
+ } finally {
990
+ await driver.manage().setTimeouts({ implicit });
991
+ }
992
+ if (err)
993
+ throw err;
994
+ };
995
+ HeaderFilterDictionary = class extends AbstractDXEditorWithInput {
996
+ constructor(parentCssSelector, elementCssSelector, driver) {
997
+ super(parentCssSelector, elementCssSelector, driver);
998
+ this.setClearStrategy(new ClearButtonStrategy(this.getFullCssSelector(), this.driver));
999
+ }
1000
+ async setTagBoxInputValue(values) {
1001
+ const lastElement = values[values.length - 1];
1002
+ const inputEl = await this.getInputElement();
1003
+ await inputEl.click();
1004
+ for (const value of values) {
1005
+ await this.selectOption(inputEl, value, lastElement);
900
1006
  }
901
1007
  }
902
- async setValue(value) {
903
- await this.ensureInitialized();
904
- if (this.editorInstance) {
905
- await this.editorInstance.setValue(value);
906
- return await this.updateEditorInstance(this.parentCssSelector, this.elementCssSelector, this.driver);
1008
+ async waitOptionSelection() {
1009
+ await fixElementStaleError(import_selenium_webdriver15.By.css(TAG_BOX_LIST_ITEM_SELECTOR2), this.driver);
1010
+ }
1011
+ async selectOption(inputEl, value, lastElement) {
1012
+ try {
1013
+ await inputEl.sendKeys(value);
1014
+ const dataTEST = await this.getDataTestId();
1015
+ await dropDownHeaderFilterDictionaryOptionClick(value, this.driver, dataTEST);
1016
+ const textLength = await inputEl.getAttribute("value").then((value2) => value2.length);
1017
+ for (let i = 0; i < textLength; i++) {
1018
+ await inputEl.sendKeys(import_selenium_webdriver15.Key.BACK_SPACE);
1019
+ }
1020
+ } catch (error) {
1021
+ throw error;
1022
+ }
1023
+ await this.waitOptionSelection();
1024
+ if (value !== lastElement) {
1025
+ await inputEl.clear();
907
1026
  }
908
- throw new Error("Editor instance is not initialized.");
1027
+ }
1028
+ async getHeaderFilterDictionaryInputValue() {
1029
+ if (await this.isHeaderFilterDictionaryEmpty()) {
1030
+ return [];
1031
+ }
1032
+ const tags = await this.driver.findElements(
1033
+ import_selenium_webdriver15.By.css(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER2} ${TAGS_SELECTOR2}`)
1034
+ );
1035
+ const values = [];
1036
+ for (const tag of tags) {
1037
+ values.push(await tag.getAttribute("textContent"));
1038
+ }
1039
+ return values;
1040
+ }
1041
+ async isHeaderFilterDictionaryEmpty() {
1042
+ const classAttribute = await this.getClasses();
1043
+ return classAttribute.includes(DX_TEXTEDITOR_EMPTY3);
909
1044
  }
910
1045
  async getValue() {
911
- await this.ensureInitialized();
912
- if (this.editorInstance) {
913
- return this.editorInstance.getValue();
1046
+ const value = await this.getHeaderFilterDictionaryInputValue();
1047
+ return value.length ? value : null;
1048
+ }
1049
+ async setValue(values) {
1050
+ if (!Array.isArray(values)) {
1051
+ values = [values];
914
1052
  }
915
- throw new Error("Editor instance is not initialized.");
1053
+ await this.setTagBoxInputValue(values);
916
1054
  }
917
1055
  };
918
1056
  }
@@ -934,6 +1072,7 @@ var init_editorFactory = __esm({
934
1072
  init_BooleanSelector();
935
1073
  init_ButtonGroup();
936
1074
  init_DateEditor();
1075
+ init_HeaderFilterDictionary();
937
1076
  editorFactory = async (parentCssSelector, elementCssSelector, driver) => {
938
1077
  const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
939
1078
  const classSting = await elementInstance.getClasses();
@@ -956,6 +1095,8 @@ var init_editorFactory = __esm({
956
1095
  return new BooleanSelector(parentCssSelector, elementCssSelector, driver);
957
1096
  if (classSting.includes("button-group-field" /* ButtonGroup */))
958
1097
  return new ButtonGroup(parentCssSelector, elementCssSelector, driver);
1098
+ if (classSting.includes("header-filter-dictionary" /* HeaderFilterDictionary */))
1099
+ return new HeaderFilterDictionary(parentCssSelector, elementCssSelector, driver);
959
1100
  throw new Error("Unknown type of editor. Please write ticket to the support");
960
1101
  };
961
1102
  }
@@ -1003,37 +1144,19 @@ function createFormButtonTestId(formName, itemName) {
1003
1144
  function createSubSystemTestId(itemName) {
1004
1145
  return `${"subsystem-item" /* SUBSYSTEM_ITEM */}-${itemName}`;
1005
1146
  }
1147
+ function createEditorButtonTestId(itemName) {
1148
+ return `${"editor-button" /* EDITOR_BUTTON */}-${itemName}`;
1149
+ }
1006
1150
  var init_createDataTestId = __esm({
1007
1151
  "src/utils/createDataTestId.ts"() {
1008
1152
  "use strict";
1009
1153
  }
1010
1154
  });
1011
1155
 
1012
- // src/utils/waitElementIsClickable.ts
1013
- async function waitElementIsClickable({
1014
- element,
1015
- timeout,
1016
- errorMessage,
1017
- driver
1018
- }) {
1019
- driver = driver ?? config().driver;
1020
- await wait(async () => {
1021
- const isDisabled = await element.getCssValue("pointer-events") === "none";
1022
- return await element.isDisplayed() && !isDisabled;
1023
- }, driver, errorMessage, timeout ?? config().timeout);
1024
- }
1025
- var init_waitElementIsClickable = __esm({
1026
- "src/utils/waitElementIsClickable.ts"() {
1027
- "use strict";
1028
- init_config();
1029
- init_wait();
1030
- }
1031
- });
1032
-
1033
- // src/pageObjects/elements/TableToolbar/AbstractButton.ts
1156
+ // src/pageObjects/elements/AbstractButton.ts
1034
1157
  var AbstractButton;
1035
1158
  var init_AbstractButton = __esm({
1036
- "src/pageObjects/elements/TableToolbar/AbstractButton.ts"() {
1159
+ "src/pageObjects/elements/AbstractButton.ts"() {
1037
1160
  "use strict";
1038
1161
  init_AbstractElementWithParent();
1039
1162
  init_actions();
@@ -1044,7 +1167,7 @@ var init_AbstractButton = __esm({
1044
1167
  }
1045
1168
  async click() {
1046
1169
  const button = await this.getElement();
1047
- await waitElementIsClickable({
1170
+ await waitElementIsClickable_default({
1048
1171
  element: button,
1049
1172
  errorMessage: this.buttonNotDisplayedError(),
1050
1173
  driver: this.driver
@@ -1055,17 +1178,25 @@ var init_AbstractButton = __esm({
1055
1178
  const button = await this.getElement();
1056
1179
  return await button.getCssValue("pointer-events") === "none";
1057
1180
  }
1181
+ async isDisplayed() {
1182
+ try {
1183
+ const button = await this.getElement();
1184
+ return await button.isDisplayed();
1185
+ } catch {
1186
+ return false;
1187
+ }
1188
+ }
1058
1189
  };
1059
1190
  }
1060
1191
  });
1061
1192
 
1062
1193
  // src/pageObjects/elements/DXComponents/DXButton.ts
1063
- var import_selenium_webdriver16, DXButton;
1194
+ var import_selenium_webdriver17, DXButton;
1064
1195
  var init_DXButton = __esm({
1065
1196
  "src/pageObjects/elements/DXComponents/DXButton.ts"() {
1066
1197
  "use strict";
1067
1198
  init_AbstractButton();
1068
- import_selenium_webdriver16 = require("selenium-webdriver");
1199
+ import_selenium_webdriver17 = require("selenium-webdriver");
1069
1200
  DXButton = class extends AbstractButton {
1070
1201
  async getText() {
1071
1202
  const classes = await this.getClasses();
@@ -1073,7 +1204,7 @@ var init_DXButton = __esm({
1073
1204
  return null;
1074
1205
  }
1075
1206
  const el = await this.getElement();
1076
- const textEl = el.findElement(import_selenium_webdriver16.By.className("dx-button-text"));
1207
+ const textEl = el.findElement(import_selenium_webdriver17.By.className("dx-button-text"));
1077
1208
  return await textEl.getText();
1078
1209
  }
1079
1210
  };
@@ -1128,12 +1259,12 @@ var init_Panel = __esm({
1128
1259
  });
1129
1260
 
1130
1261
  // src/pageObjects/elements/Groups/TabPanel.ts
1131
- var import_selenium_webdriver17, TabPanelItem, TabPanel;
1262
+ var import_selenium_webdriver18, TabPanelItem, TabPanel;
1132
1263
  var init_TabPanel = __esm({
1133
1264
  "src/pageObjects/elements/Groups/TabPanel.ts"() {
1134
1265
  "use strict";
1135
1266
  init_AbstractGroup();
1136
- import_selenium_webdriver17 = require("selenium-webdriver");
1267
+ import_selenium_webdriver18 = require("selenium-webdriver");
1137
1268
  init_actions();
1138
1269
  TabPanelItem = class extends AbstractGroup {
1139
1270
  constructor(parentCssSelector, elementCssSelector, driver) {
@@ -1144,7 +1275,7 @@ var init_TabPanel = __esm({
1144
1275
  }
1145
1276
  async isActive() {
1146
1277
  const tabPanelItemElement = await this.getElement();
1147
- const grandparentTab = await tabPanelItemElement.findElement(import_selenium_webdriver17.By.xpath('ancestor::div[@role="tab"][1]'));
1278
+ const grandparentTab = await tabPanelItemElement.findElement(import_selenium_webdriver18.By.xpath('ancestor::div[@role="tab"][1]'));
1148
1279
  return await grandparentTab.getAttribute("aria-selected") === "true";
1149
1280
  }
1150
1281
  async getTitle() {
@@ -1163,12 +1294,12 @@ var init_TabPanel = __esm({
1163
1294
  });
1164
1295
 
1165
1296
  // src/pageObjects/elements/Groups/Accordion/AccordionItem.ts
1166
- var import_selenium_webdriver18, ACCORDION_TITLE_CONTAINER, AccordionItem;
1297
+ var import_selenium_webdriver19, ACCORDION_TITLE_CONTAINER, AccordionItem;
1167
1298
  var init_AccordionItem = __esm({
1168
1299
  "src/pageObjects/elements/Groups/Accordion/AccordionItem.ts"() {
1169
1300
  "use strict";
1170
1301
  init_AbstractGroup();
1171
- import_selenium_webdriver18 = require("selenium-webdriver");
1302
+ import_selenium_webdriver19 = require("selenium-webdriver");
1172
1303
  init_actions();
1173
1304
  ACCORDION_TITLE_CONTAINER = "accordion-title-container";
1174
1305
  AccordionItem = class extends AbstractGroup {
@@ -1181,7 +1312,7 @@ var init_AccordionItem = __esm({
1181
1312
  }
1182
1313
  async clickAccordionItemTitle() {
1183
1314
  const accordionElement = await this.getElement();
1184
- const accordTitleElement = await accordionElement.findElement(import_selenium_webdriver18.By.className(ACCORDION_TITLE_CONTAINER));
1315
+ const accordTitleElement = await accordionElement.findElement(import_selenium_webdriver19.By.className(ACCORDION_TITLE_CONTAINER));
1185
1316
  await accordTitleElement.click();
1186
1317
  }
1187
1318
  async click() {
@@ -1416,11 +1547,11 @@ function getCssRowByIndexSelector(index) {
1416
1547
  function getCssCellByIndexSelector(index) {
1417
1548
  return `td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`;
1418
1549
  }
1419
- var import_selenium_webdriver19, getColumnByIndexCssSelector, getColumnByCaptionCssSelector, getColumnByNameCssSelector, transformInputIndex, transformOutputIndex;
1550
+ var import_selenium_webdriver20, getColumnByIndexCssSelector, getColumnByCaptionCssSelector, getColumnByNameCssSelector, transformInputIndex, transformOutputIndex;
1420
1551
  var init_utils2 = __esm({
1421
1552
  "src/pageObjects/elements/Table/utils.ts"() {
1422
1553
  "use strict";
1423
- import_selenium_webdriver19 = require("selenium-webdriver");
1554
+ import_selenium_webdriver20 = require("selenium-webdriver");
1424
1555
  getColumnByIndexCssSelector = (columnIndex) => `td[aria-colindex="${transformInputIndex(columnIndex)}"]`;
1425
1556
  getColumnByCaptionCssSelector = (caption) => `td[role="columnheader"][aria-label="Column ${caption}"]`;
1426
1557
  getColumnByNameCssSelector = (name) => `td[role="columnheader"][data-fieldname="${name}"]`;
@@ -1437,11 +1568,11 @@ var init_types3 = __esm({
1437
1568
  });
1438
1569
 
1439
1570
  // src/pageObjects/elements/Table/elements/Cell.ts
1440
- var import_selenium_webdriver20, Cell;
1571
+ var import_selenium_webdriver21, Cell;
1441
1572
  var init_Cell = __esm({
1442
1573
  "src/pageObjects/elements/Table/elements/Cell.ts"() {
1443
1574
  "use strict";
1444
- import_selenium_webdriver20 = require("selenium-webdriver");
1575
+ import_selenium_webdriver21 = require("selenium-webdriver");
1445
1576
  init_AbstractElementWithParent();
1446
1577
  init_utils2();
1447
1578
  init_types3();
@@ -1458,17 +1589,41 @@ var init_Cell = __esm({
1458
1589
  this.elementCssSelector = getCssCellByIndexSelector(index);
1459
1590
  }
1460
1591
  async getBooleanValue(cellEl) {
1461
- const booleanEl = await cellEl.findElement(import_selenium_webdriver20.By.className("boolean-widget"));
1592
+ const booleanEl = await cellEl.findElement(import_selenium_webdriver21.By.className("boolean-widget"));
1462
1593
  return await booleanEl.getAttribute("aria-checked") === "true" ? 1 : 0;
1463
1594
  }
1464
1595
  async getTagsValue(cellEl) {
1465
1596
  const tagsCssSelector = ".multiselect-container .multiselect-cell";
1466
- const tags = await cellEl.findElements(import_selenium_webdriver20.By.css(tagsCssSelector));
1597
+ const tags = await cellEl.findElements(import_selenium_webdriver21.By.css(tagsCssSelector));
1467
1598
  const values = [];
1468
1599
  for (const tag of tags) {
1469
1600
  values.push(await tag.getAttribute("textContent"));
1470
1601
  }
1471
- return values;
1602
+ return values.length ? values : null;
1603
+ }
1604
+ async getNumberValue(cellEl) {
1605
+ const value = (await cellEl.getText()).trim();
1606
+ return value == "" ? null : Number.parseFloat(value);
1607
+ }
1608
+ async getDateValue(cellEl, cellElClass) {
1609
+ const value = (await cellEl.getText()).trim();
1610
+ if (value === "")
1611
+ return null;
1612
+ const isWithTime = cellElClass.includes("with-time");
1613
+ try {
1614
+ if (isWithTime) {
1615
+ const [datePart, timePart] = value.split(", ");
1616
+ const [day, month, year] = datePart.split(".").map(Number);
1617
+ const [hours, minutes] = timePart.split(":").map(Number);
1618
+ return new Date(Date.UTC(year, month - 1, day, hours, minutes));
1619
+ } else {
1620
+ const [day, month, year] = value.split(".").map(Number);
1621
+ return new Date(Date.UTC(year, month - 1, day));
1622
+ }
1623
+ } catch (error) {
1624
+ console.error(`Error parsing date value "${value}":`, error);
1625
+ return null;
1626
+ }
1472
1627
  }
1473
1628
  async getElement() {
1474
1629
  if (this._index == null) {
@@ -1483,7 +1638,12 @@ var init_Cell = __esm({
1483
1638
  return this.getBooleanValue(cellEl);
1484
1639
  if (cellElClass.includes("tags-column" /* Tags */))
1485
1640
  return this.getTagsValue(cellEl);
1486
- return cellEl.getText();
1641
+ if (cellElClass.includes("number-column" /* Number */))
1642
+ return this.getNumberValue(cellEl);
1643
+ if (cellElClass.includes("date-column" /* Date */))
1644
+ return this.getDateValue(cellEl, cellElClass);
1645
+ const cellText = await cellEl.getText();
1646
+ return cellText == "" ? null : cellText;
1487
1647
  }
1488
1648
  getIndex() {
1489
1649
  return this._index;
@@ -1493,11 +1653,11 @@ var init_Cell = __esm({
1493
1653
  });
1494
1654
 
1495
1655
  // src/pageObjects/elements/Table/elements/Row.ts
1496
- var import_selenium_webdriver21, DX_SELECTION_CLASS, DX_ROW_EDIT_CLASS, DX_DATA_ROW_CLASS, Row;
1656
+ var import_selenium_webdriver22, DX_SELECTION_CLASS, DX_ROW_EDIT_CLASS, DX_DATA_ROW_CLASS, Row;
1497
1657
  var init_Row = __esm({
1498
1658
  "src/pageObjects/elements/Table/elements/Row.ts"() {
1499
1659
  "use strict";
1500
- import_selenium_webdriver21 = require("selenium-webdriver");
1660
+ import_selenium_webdriver22 = require("selenium-webdriver");
1501
1661
  init_Cell();
1502
1662
  init_utils2();
1503
1663
  init_AbstractElementWithParent();
@@ -1510,10 +1670,19 @@ var init_Row = __esm({
1510
1670
  Row = class extends AbstractElementWithParent {
1511
1671
  index;
1512
1672
  getColumnBy;
1513
- constructor(parentCssSelector, index, driver, getColumnBy) {
1673
+ fixedTableContentCssSelector;
1674
+ /**
1675
+ * @param parentCssSelector
1676
+ * @param fixedTableContentCssSelector
1677
+ * @param index починається з 0 (в getCssRowByIndexSelector додається +1)
1678
+ * @param driver
1679
+ * @param getColumnBy
1680
+ */
1681
+ constructor(parentCssSelector, fixedTableContentCssSelector, index, driver, getColumnBy) {
1514
1682
  super(parentCssSelector, getCssRowByIndexSelector(index), driver);
1515
1683
  this.index = index;
1516
1684
  this.getColumnBy = getColumnBy;
1685
+ this.fixedTableContentCssSelector = fixedTableContentCssSelector;
1517
1686
  }
1518
1687
  _getCell({ index, name, title }) {
1519
1688
  return new Cell(
@@ -1554,7 +1723,7 @@ var init_Row = __esm({
1554
1723
  return this.index;
1555
1724
  }
1556
1725
  async getCells() {
1557
- const cells = await this.driver.findElements(import_selenium_webdriver21.By.css(`${this.getFullCssSelector()} td[role="gridcell"]`));
1726
+ const cells = await this.driver.findElements(import_selenium_webdriver22.By.css(`${this.getFullCssSelector()} td[role="gridcell"]`));
1558
1727
  const result = [];
1559
1728
  cells.forEach((_, index) => {
1560
1729
  const newCell = this.getCellByIndex(index);
@@ -1563,12 +1732,11 @@ var init_Row = __esm({
1563
1732
  return result;
1564
1733
  }
1565
1734
  async clickInlineButton(buttonClass) {
1566
- const FIXED_TABLE_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
1567
1735
  const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(
1568
1736
  this.index
1569
1737
  )}"] .${buttonClass}`;
1570
1738
  const button = await fixElementStaleError(
1571
- import_selenium_webdriver21.By.css(`${this.parentCssSelector} ${FIXED_TABLE_CSS_SELECTOR} ${buttonCssSelector}`),
1739
+ import_selenium_webdriver22.By.css(`${this.parentCssSelector} ${this.fixedTableContentCssSelector} ${buttonCssSelector}`),
1572
1740
  this.driver
1573
1741
  );
1574
1742
  return click(button, this.driver);
@@ -1599,11 +1767,11 @@ var init_Row = __esm({
1599
1767
  });
1600
1768
 
1601
1769
  // src/pageObjects/elements/Table/elements/Column.ts
1602
- var import_selenium_webdriver22, Column;
1770
+ var import_selenium_webdriver23, Column;
1603
1771
  var init_Column = __esm({
1604
1772
  "src/pageObjects/elements/Table/elements/Column.ts"() {
1605
1773
  "use strict";
1606
- import_selenium_webdriver22 = require("selenium-webdriver");
1774
+ import_selenium_webdriver23 = require("selenium-webdriver");
1607
1775
  init_utils2();
1608
1776
  init_AbstractElementWithParent();
1609
1777
  init_fixElementStaleError();
@@ -1631,7 +1799,7 @@ var init_Column = __esm({
1631
1799
  return super.getElement();
1632
1800
  }
1633
1801
  async getColumnHeaderIndexBy(cssSelector) {
1634
- const column = await fixElementStaleError(import_selenium_webdriver22.By.css(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`), this.driver);
1802
+ const column = await fixElementStaleError(import_selenium_webdriver23.By.css(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`), this.driver);
1635
1803
  return transformOutputIndex(await column.getAttribute("aria-colindex"));
1636
1804
  }
1637
1805
  async getIndexByCaption() {
@@ -1662,6 +1830,46 @@ var init_Column = __esm({
1662
1830
  }
1663
1831
  });
1664
1832
 
1833
+ // src/pageObjects/elements/EditorButton.ts
1834
+ var EditorButton;
1835
+ var init_EditorButton = __esm({
1836
+ "src/pageObjects/elements/EditorButton.ts"() {
1837
+ "use strict";
1838
+ init_locators();
1839
+ init_createDataTestId();
1840
+ init_AbstractElementWithParent();
1841
+ init_waitElementIsClickable();
1842
+ init_actions();
1843
+ EditorButton = class extends AbstractElementWithParent {
1844
+ name;
1845
+ constructor(parentCssSelector, name, driver) {
1846
+ super(parentCssSelector, byTestIdCssSelector(createEditorButtonTestId(name)), driver);
1847
+ this.name = name;
1848
+ }
1849
+ buttonNotDisplayedError() {
1850
+ return `Editor Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
1851
+ }
1852
+ async click() {
1853
+ const button = await this.getElement();
1854
+ await waitElementIsClickable_default({
1855
+ element: button,
1856
+ errorMessage: this.buttonNotDisplayedError(),
1857
+ driver: this.driver
1858
+ });
1859
+ await click(button, this.driver);
1860
+ }
1861
+ async isDisplayed() {
1862
+ try {
1863
+ const button = await this.getElement();
1864
+ return await button.isDisplayed();
1865
+ } catch (error) {
1866
+ return false;
1867
+ }
1868
+ }
1869
+ };
1870
+ }
1871
+ });
1872
+
1665
1873
  // src/pageObjects/elements/AbstractEditor.ts
1666
1874
  var AbstractEditor;
1667
1875
  var init_AbstractEditor2 = __esm({
@@ -1669,6 +1877,7 @@ var init_AbstractEditor2 = __esm({
1669
1877
  "use strict";
1670
1878
  init_AbstractElementWithParent();
1671
1879
  init_Editors();
1880
+ init_EditorButton();
1672
1881
  AbstractEditor = class extends AbstractElementWithParent {
1673
1882
  editor;
1674
1883
  constructor(parentCssSelector, elementCssSelector, driver) {
@@ -1733,6 +1942,31 @@ var init_AbstractEditor2 = __esm({
1733
1942
  await this.initEditor();
1734
1943
  return this.editor.isReadonly();
1735
1944
  }
1945
+ /**
1946
+ * Возвращает значение true|false в зависимости isDisplayed поле или нет
1947
+ * @example
1948
+ * expect(await formEdit.field('NumberFld').isDisplayed()).toBe(true);
1949
+ * expect(await formEdit.field('TextFld').isDisplayed()).toBe(false);
1950
+ */
1951
+ async isDisplayed() {
1952
+ try {
1953
+ await this.initEditor();
1954
+ const element = await this.getElement();
1955
+ return await element.isDisplayed();
1956
+ } catch {
1957
+ return false;
1958
+ }
1959
+ }
1960
+ /**
1961
+ * Находит кнопку на поле по имени
1962
+ * @example
1963
+ * const form= new MyForm();
1964
+ * //...
1965
+ * await form.field('Name').button('editorButton).click()
1966
+ */
1967
+ button(name) {
1968
+ return new EditorButton(this.getFullCssSelector(), name, this.driver);
1969
+ }
1736
1970
  };
1737
1971
  }
1738
1972
  });
@@ -1753,24 +1987,193 @@ var init_FormField = __esm({
1753
1987
  }
1754
1988
  });
1755
1989
 
1990
+ // src/utils/typesUtil.ts
1991
+ var import_util, types, type, isArray, isString;
1992
+ var init_typesUtil = __esm({
1993
+ "src/utils/typesUtil.ts"() {
1994
+ "use strict";
1995
+ import_util = require("selenium-webdriver/lib/util");
1996
+ types = {
1997
+ "[object Array]": "array",
1998
+ "[object Date]": "date",
1999
+ "[object Object]": "object",
2000
+ "[object String]": "string",
2001
+ "[object Null]": "null"
2002
+ };
2003
+ type = function(object) {
2004
+ const typeOfObject = Object.prototype.toString.call(object);
2005
+ return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
2006
+ };
2007
+ isArray = function(value) {
2008
+ return type(value) === "array";
2009
+ };
2010
+ isString = function(object) {
2011
+ return typeof object === "string";
2012
+ };
2013
+ }
2014
+ });
2015
+
2016
+ // src/pageObjects/elements/AbstractDropDownMenuList.ts
2017
+ var AbstractDropDownMenuList;
2018
+ var init_AbstractDropDownMenuList = __esm({
2019
+ "src/pageObjects/elements/AbstractDropDownMenuList.ts"() {
2020
+ "use strict";
2021
+ init_AbstractElementWithParent();
2022
+ init_actions();
2023
+ init_waitElementIsClickable();
2024
+ init_fixElementStaleError();
2025
+ init_typesUtil();
2026
+ AbstractDropDownMenuList = class extends AbstractElementWithParent {
2027
+ buttonNotDisplayedError(name) {
2028
+ return `Menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
2029
+ }
2030
+ async clickItemBy(errorMessage, by) {
2031
+ await waitElementIsClickable_default({
2032
+ errorMessage,
2033
+ driver: this.driver,
2034
+ by
2035
+ });
2036
+ const menuItemElement = await fixElementStaleError(by, this.driver);
2037
+ await click(menuItemElement, this.driver);
2038
+ }
2039
+ async clickItemByPath(path, getBy) {
2040
+ let pathList = isString(path) ? [path] : path;
2041
+ for (let text of pathList) {
2042
+ await this.clickItemBy(this.buttonNotDisplayedError(text), getBy(text));
2043
+ }
2044
+ }
2045
+ clickButton(name) {
2046
+ return this.clickItemByPath(name, this.getButtonNameBy.bind(this));
2047
+ }
2048
+ clickButtonByTitle(title) {
2049
+ return this.clickItemByPath(title, this.getButtonTitleBy.bind(this));
2050
+ }
2051
+ isVisible() {
2052
+ return Promise.resolve(true);
2053
+ }
2054
+ };
2055
+ }
2056
+ });
2057
+
2058
+ // src/utils/cssToXPath.ts
2059
+ function cssClassesToXPath(classNames) {
2060
+ const classNamesList = classNames.split(".").filter((className) => !!className);
2061
+ const chained = classNamesList.map((className) => `contains(@class, "${className}")`).join(" and ");
2062
+ return `[${chained}]`;
2063
+ }
2064
+ var init_cssToXPath = __esm({
2065
+ "src/utils/cssToXPath.ts"() {
2066
+ "use strict";
2067
+ }
2068
+ });
2069
+
2070
+ // src/pageObjects/elements/DXContextMenuList.ts
2071
+ var import_selenium_webdriver24, CONTEXT_MENU_CLASS, CONTEXT_MENU_ITEM_TEXT_CLASS, DXContextMenuList;
2072
+ var init_DXContextMenuList = __esm({
2073
+ "src/pageObjects/elements/DXContextMenuList.ts"() {
2074
+ "use strict";
2075
+ init_AbstractDropDownMenuList();
2076
+ import_selenium_webdriver24 = require("selenium-webdriver");
2077
+ init_cssToXPath();
2078
+ init_waitElementIsVisible();
2079
+ CONTEXT_MENU_CLASS = "dx-context-menu";
2080
+ CONTEXT_MENU_ITEM_TEXT_CLASS = "dx-menu-item-text";
2081
+ DXContextMenuList = class extends AbstractDropDownMenuList {
2082
+ /**
2083
+ * @param parentCssSelector
2084
+ * @param classNames - Список класів. Починається з крапки
2085
+ * @param driver
2086
+ */
2087
+ constructor(parentCssSelector, classNames, driver) {
2088
+ super(parentCssSelector, `.${CONTEXT_MENU_CLASS}${classNames}`, driver);
2089
+ }
2090
+ getButtonTitleBy(title) {
2091
+ const buttonByTextXpath2 = (text) => `//span[contains(@class, "${CONTEXT_MENU_ITEM_TEXT_CLASS}") and contains(text(), "${text}")]`;
2092
+ const xpath = "//div" + cssClassesToXPath(this.elementCssSelector) + buttonByTextXpath2(title);
2093
+ return import_selenium_webdriver24.By.xpath(xpath);
2094
+ }
2095
+ async isVisible() {
2096
+ try {
2097
+ await waitElementIsVisible({
2098
+ element: await this.driver.findElement(import_selenium_webdriver24.By.css(`.dx-overlay-wrapper .dx-contextmenu`)),
2099
+ driver: this.driver,
2100
+ errorMessage: "Cannot find dropdown element"
2101
+ });
2102
+ } catch {
2103
+ return false;
2104
+ }
2105
+ }
2106
+ };
2107
+ }
2108
+ });
2109
+
2110
+ // src/pageObjects/elements/Table/elements/ContextMenu.ts
2111
+ var ContextMenu;
2112
+ var init_ContextMenu = __esm({
2113
+ "src/pageObjects/elements/Table/elements/ContextMenu.ts"() {
2114
+ "use strict";
2115
+ init_DXContextMenuList();
2116
+ init_locators();
2117
+ ContextMenu = class extends DXContextMenuList {
2118
+ _formName;
2119
+ _initFn;
2120
+ constructor(cssClass, formName, driver) {
2121
+ super("", cssClass, driver);
2122
+ this._formName = formName;
2123
+ }
2124
+ setInit(cb) {
2125
+ this._initFn = cb;
2126
+ return this;
2127
+ }
2128
+ getButtonNameBy(name) {
2129
+ return byTestId(`cm-${this._formName}-${name}`);
2130
+ }
2131
+ async clickButtonByTitle(title) {
2132
+ await this._initFn?.();
2133
+ await super.clickButtonByTitle(title);
2134
+ }
2135
+ async clickButton(name) {
2136
+ await this._initFn?.();
2137
+ await super.clickButton(name);
2138
+ }
2139
+ };
2140
+ }
2141
+ });
2142
+
1756
2143
  // src/pageObjects/elements/Table/Table.ts
1757
- var import_selenium_webdriver23, Table;
2144
+ var import_selenium_webdriver25, Table;
1758
2145
  var init_Table = __esm({
1759
2146
  "src/pageObjects/elements/Table/Table.ts"() {
1760
2147
  "use strict";
1761
- import_selenium_webdriver23 = require("selenium-webdriver");
2148
+ import_selenium_webdriver25 = require("selenium-webdriver");
1762
2149
  init_createDataTestId();
1763
2150
  init_AbstractElementWithParent();
1764
2151
  init_Row();
1765
2152
  init_Column();
1766
2153
  init_FormField();
2154
+ init_ContextMenu();
2155
+ init_actions();
1767
2156
  Table = class extends AbstractElementWithParent {
1768
2157
  formName;
1769
2158
  headerCssSelector;
1770
- constructor(parentCssSelector, headerCssSelector, formName, driver) {
2159
+ contextMenuCssSelector;
2160
+ fixedTableContentCssSelector;
2161
+ tableContentCssSelector;
2162
+ constructor({
2163
+ parentCssSelector,
2164
+ contextMenuCssSelector,
2165
+ tableContentCssSelector,
2166
+ headerCssSelector,
2167
+ fixedTableContentCssSelector,
2168
+ formName,
2169
+ driver
2170
+ }) {
1771
2171
  super(parentCssSelector, `#${createTableId(formName)}`, driver);
1772
2172
  this.formName = formName;
1773
2173
  this.headerCssSelector = headerCssSelector;
2174
+ this.contextMenuCssSelector = contextMenuCssSelector;
2175
+ this.fixedTableContentCssSelector = fixedTableContentCssSelector;
2176
+ this.tableContentCssSelector = tableContentCssSelector;
1774
2177
  }
1775
2178
  getColumnBy = (args) => {
1776
2179
  if (args.title) {
@@ -1778,10 +2181,18 @@ var init_Table = __esm({
1778
2181
  }
1779
2182
  return this.getColumnByName(args.name);
1780
2183
  };
2184
+ /**
2185
+ * Отримати рядок по індексу.
2186
+ * @param index починається з 0
2187
+ */
1781
2188
  getRowByIndex(index) {
1782
- return new Row(this.getFullCssSelector(), index, this.driver, this.getColumnBy);
2189
+ return new Row(this.getFullCssSelector(), this.fixedTableContentCssSelector, index, this.driver, this.getColumnBy);
1783
2190
  }
2191
+ /**
2192
+ * @param index починається з 0
2193
+ */
1784
2194
  getColumnByIndex(index) {
2195
+ this.getRowByIndex(index);
1785
2196
  return new Column({
1786
2197
  parentCssSelector: this.getFullCssSelector(),
1787
2198
  driver: this.driver,
@@ -1804,21 +2215,32 @@ var init_Table = __esm({
1804
2215
  driver: this.driver
1805
2216
  });
1806
2217
  };
2218
+ /**
2219
+ * Вибрати рядок по індексу.
2220
+ * @param index починається з 0
2221
+ */
1807
2222
  selectRowByIndex(index) {
1808
2223
  return this.getRowByIndex(index).select();
1809
2224
  }
1810
2225
  async getRows() {
1811
- const rows = await this.driver.findElements(import_selenium_webdriver23.By.css(`${this.getFullCssSelector()} .dx-row.dx-data-row`));
2226
+ const rowsFullCssSelector = `${this.getFullCssSelector()} ${this.tableContentCssSelector} .dx-row.dx-data-row`;
2227
+ const rows = await this.driver.findElements(import_selenium_webdriver25.By.css(rowsFullCssSelector));
1812
2228
  const result = [];
1813
2229
  rows.forEach((_, index) => {
1814
- const newRow = new Row(this.getFullCssSelector(), index, this.driver, this.getColumnBy);
2230
+ const newRow = new Row(
2231
+ this.getFullCssSelector(),
2232
+ this.fixedTableContentCssSelector,
2233
+ index,
2234
+ this.driver,
2235
+ this.getColumnBy
2236
+ );
1815
2237
  result.push(newRow);
1816
2238
  });
1817
2239
  return result;
1818
2240
  }
1819
2241
  async getColumns() {
1820
2242
  const columns = await this.driver.findElements(
1821
- import_selenium_webdriver23.By.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"]`)
2243
+ import_selenium_webdriver25.By.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"] .header-template-text`)
1822
2244
  );
1823
2245
  const result = [];
1824
2246
  columns.forEach((_, index) => {
@@ -1844,6 +2266,50 @@ var init_Table = __esm({
1844
2266
  field(name) {
1845
2267
  return new FormField(this.getFullCssSelector(), this.formName, name, this.driver);
1846
2268
  }
2269
+ /**
2270
+ * Возвращает список строк которые выделены
2271
+ * @returns Row[]
2272
+ * @example
2273
+ * const form = new MyForm();
2274
+ * //...
2275
+ * await form.getSelectedRows();
2276
+ */
2277
+ async getSelectedRows() {
2278
+ const rows = await this.getRows();
2279
+ let result = [];
2280
+ for (const row of rows) {
2281
+ if (await row.isSelected()) {
2282
+ }
2283
+ result.push(row);
2284
+ }
2285
+ return result;
2286
+ }
2287
+ /**
2288
+ * Вызывает контекстное меню в области с данными.
2289
+ * @param fieldName - имя поля
2290
+ * @param [rowIndex] - индекс строки. Если значение не передано, то по умолчанию контекстное меню будет вызвано на первой выделенной строке.
2291
+ * @throws {Error} Если нет выделенных строк, то выбросит исключение.
2292
+ * @example
2293
+ * const form = new MyForm();
2294
+ * //...
2295
+ * await form.contextMenu('FieldName').clickButton('OpenFormButton');
2296
+ * // or
2297
+ * await form.contextMenu('FieldName', 3).clickButton(['Group', 'ButtonInGroup']);
2298
+ */
2299
+ contextMenu(fieldName, rowIndex) {
2300
+ return new ContextMenu(this.contextMenuCssSelector, this.formName, this.driver).setInit(async () => {
2301
+ let row;
2302
+ if (rowIndex != null) {
2303
+ row = this.getRowByIndex(rowIndex);
2304
+ } else {
2305
+ [row] = await this.getSelectedRows();
2306
+ }
2307
+ if (!row)
2308
+ throw new Error("No row available row for context menu");
2309
+ const cellElement = await row.getCell(fieldName).getElement();
2310
+ await contextMenu(cellElement, this.driver);
2311
+ });
2312
+ }
1847
2313
  };
1848
2314
  }
1849
2315
  });
@@ -1887,89 +2353,73 @@ var init_ToolbarButton = __esm({
1887
2353
  }
1888
2354
  });
1889
2355
 
1890
- // src/utils/typesUtil.ts
1891
- var types, type, isArray, isString;
1892
- var init_typesUtil = __esm({
1893
- "src/utils/typesUtil.ts"() {
2356
+ // src/pageObjects/elements/AbstractDropDownMenuButton.ts
2357
+ var AbstractDropDownMenuButton;
2358
+ var init_AbstractDropDownMenuButton = __esm({
2359
+ "src/pageObjects/elements/AbstractDropDownMenuButton.ts"() {
1894
2360
  "use strict";
1895
- types = {
1896
- "[object Array]": "array",
1897
- "[object Date]": "date",
1898
- "[object Object]": "object",
1899
- "[object String]": "string",
1900
- "[object Null]": "null"
1901
- };
1902
- type = function(object) {
1903
- const typeOfObject = Object.prototype.toString.call(object);
1904
- return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
1905
- };
1906
- isArray = function(value) {
1907
- return type(value) === "array";
1908
- };
1909
- isString = function(object) {
1910
- return typeof object === "string";
2361
+ init_AbstractElementWithParent();
2362
+ init_actions();
2363
+ AbstractDropDownMenuButton = class extends AbstractElementWithParent {
2364
+ _list;
2365
+ constructor(parentCssSelector, elementCssSelector, list, driver) {
2366
+ super(parentCssSelector, elementCssSelector, driver);
2367
+ this._list = list;
2368
+ }
2369
+ async openDropdownMenu() {
2370
+ const dropdown = await this.getElement();
2371
+ await click(dropdown, this.driver);
2372
+ await this._list.isVisible();
2373
+ }
2374
+ async clickButton(name) {
2375
+ await this.openDropdownMenu();
2376
+ await this._list.clickButton(name);
2377
+ }
2378
+ async clickButtonByTitle(title) {
2379
+ await this.openDropdownMenu();
2380
+ await this._list.clickButtonByTitle(title);
2381
+ }
1911
2382
  };
1912
2383
  }
1913
2384
  });
1914
2385
 
1915
2386
  // src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
1916
- var import_selenium_webdriver24, SPINDOWN_CLASS, buttonGroupItemSelector, getFullCssSelector, buttonByTextXpath, ToolbarMenu;
2387
+ var SPINDOWN_CLASS, buttonGroupItemSelector, getFullCssSelector, ToolbarMenuList, ToolbarMenu;
1917
2388
  var init_ToolbarMenu = __esm({
1918
2389
  "src/pageObjects/elements/TableToolbar/ToolbarMenu.ts"() {
1919
2390
  "use strict";
1920
- import_selenium_webdriver24 = require("selenium-webdriver");
1921
2391
  init_typesUtil();
1922
- init_AbstractElementWithParent();
1923
2392
  init_locators();
1924
- init_actions();
1925
- init_waitElementIsClickable();
1926
- init_fixElementStaleError();
2393
+ init_AbstractDropDownMenuButton();
2394
+ init_DXContextMenuList();
1927
2395
  SPINDOWN_CLASS = ".dx-icon-spindown";
1928
2396
  buttonGroupItemSelector = (formName, name) => byTestIdCssSelector(`ftb-${formName}-${name}`);
1929
2397
  getFullCssSelector = (formName, name) => `${buttonGroupItemSelector(formName, name)} ${SPINDOWN_CLASS}`;
1930
- buttonByTextXpath = (text) => `.//span[contains(@class, "dx-menu-item-text") and contains(text(), "${text}")]`;
1931
- ToolbarMenu = class extends AbstractElementWithParent {
2398
+ ToolbarMenuList = class extends DXContextMenuList {
1932
2399
  _formName;
1933
- constructor(parentCssSelector, formName, name, driver) {
1934
- super(parentCssSelector, getFullCssSelector(formName, name), driver);
2400
+ constructor(parentCssSelector, elementCssSelector, formName, driver) {
2401
+ super(parentCssSelector, elementCssSelector, driver);
1935
2402
  this._formName = formName;
1936
2403
  }
1937
- async openDropdownMenu() {
1938
- const dropdown = await this.getElement();
1939
- await click(dropdown, this.driver);
1940
- }
1941
- getCssSelectorToButton(name) {
2404
+ getButtonNameBy(name) {
1942
2405
  return byTestId(`ftb-${this._formName}-${name}`);
1943
2406
  }
1944
- buttonNotDisplayedError(name) {
1945
- return `Toolbar menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
1946
- }
1947
- async goToButton(name, by) {
1948
- const toolbarMenuItem = await fixElementStaleError(by, this.driver);
1949
- await waitElementIsClickable({
1950
- element: toolbarMenuItem,
1951
- errorMessage: this.buttonNotDisplayedError(name),
1952
- driver: this.driver
1953
- });
1954
- await click(toolbarMenuItem, this.driver);
2407
+ };
2408
+ ToolbarMenu = class extends AbstractDropDownMenuButton {
2409
+ constructor(parentCssSelector, formName, name, driver) {
2410
+ const fullSelector = getFullCssSelector(formName, name);
2411
+ const list = new ToolbarMenuList(parentCssSelector, ".toolbar-dropdown-context-menu", formName, driver);
2412
+ super(parentCssSelector, fullSelector, list, driver);
1955
2413
  }
1956
2414
  async clickButton(name) {
1957
- await this.openDropdownMenu();
1958
2415
  if (!isString(name) && !isArray(name))
1959
2416
  throw new Error(`"name" must be a string or array of string`);
1960
- let lName = isString(name) ? [name] : name;
1961
- for (let n of lName) {
1962
- await this.goToButton(n, this.getCssSelectorToButton(n));
1963
- }
2417
+ await super.clickButton(name);
1964
2418
  }
1965
2419
  async clickButtonByTitle(title) {
1966
- await this.openDropdownMenu();
1967
2420
  if (!isString(title) && !isArray(title))
1968
2421
  throw new Error(`"title" must be a string or array of string`);
1969
- let lTitle = isString(title) ? [title] : title;
1970
- for (let t of lTitle) {
1971
- await this.goToButton(t, import_selenium_webdriver24.By.xpath(buttonByTextXpath(t)));
1972
- }
2422
+ await super.clickButtonByTitle(title);
1973
2423
  }
1974
2424
  };
1975
2425
  }
@@ -2014,6 +2464,14 @@ var init_ToolbarItem = __esm({
2014
2464
  await this.init();
2015
2465
  return await this._button.isDisabled();
2016
2466
  }
2467
+ async isDisplayed() {
2468
+ try {
2469
+ await this.init();
2470
+ return this._button.isDisplayed();
2471
+ } catch (error) {
2472
+ return false;
2473
+ }
2474
+ }
2017
2475
  get menu() {
2018
2476
  return new ToolbarMenu(this.parentCssSelector, this._formName, this._itemName, this.driver);
2019
2477
  }
@@ -2043,11 +2501,11 @@ var init_FormToolbar = __esm({
2043
2501
  });
2044
2502
 
2045
2503
  // src/pageObjects/elements/Filters/FilterOperation.ts
2046
- var import_selenium_webdriver25, FILTER_OPERATIONS, BUTTON_OPERATION_WIDGET, OPERATIONS_WIDGET_POPUP, getWidgetInPopupSelector, FilterOperation;
2504
+ var import_selenium_webdriver26, FILTER_OPERATIONS, BUTTON_OPERATION_WIDGET, OPERATIONS_WIDGET_POPUP, getWidgetInPopupSelector, FilterOperation;
2047
2505
  var init_FilterOperation = __esm({
2048
2506
  "src/pageObjects/elements/Filters/FilterOperation.ts"() {
2049
2507
  "use strict";
2050
- import_selenium_webdriver25 = require("selenium-webdriver");
2508
+ import_selenium_webdriver26 = require("selenium-webdriver");
2051
2509
  init_fixElementStaleError();
2052
2510
  init_AbstractElementWithParent();
2053
2511
  init_locators();
@@ -2082,15 +2540,15 @@ var init_FilterOperation = __esm({
2082
2540
  }
2083
2541
  async initOperationWidget() {
2084
2542
  const widgetButtonEl = await this.getElement();
2085
- await waitElementIsClickable({
2543
+ await waitElementIsClickable_default({
2086
2544
  element: widgetButtonEl,
2087
2545
  errorMessage: "Widget operation is not clickable",
2088
2546
  driver: this.driver
2089
2547
  });
2090
- const clickableElement = await widgetButtonEl.findElement(import_selenium_webdriver25.By.className("dx-icon"));
2548
+ const clickableElement = await widgetButtonEl.findElement(import_selenium_webdriver26.By.className("dx-icon"));
2091
2549
  await click(clickableElement, this.driver);
2092
2550
  try {
2093
- const widgetPopupEl = await this.driver.findElement(import_selenium_webdriver25.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
2551
+ const widgetPopupEl = await this.driver.findElement(import_selenium_webdriver26.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
2094
2552
  await waitElementIsVisible({
2095
2553
  element: widgetPopupEl,
2096
2554
  errorMessage: `Operation widget popup is not visible`,
@@ -2105,7 +2563,7 @@ var init_FilterOperation = __esm({
2105
2563
  throw new Error(`Operation with name "${operationName}" is not correct.`);
2106
2564
  }
2107
2565
  await this.initOperationWidget();
2108
- const operationEl = await fixElementStaleError(import_selenium_webdriver25.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
2566
+ const operationEl = await fixElementStaleError(import_selenium_webdriver26.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
2109
2567
  await click(operationEl, this.driver);
2110
2568
  await wait(
2111
2569
  async () => {
@@ -2177,8 +2635,15 @@ var init_FormFilterField = __esm({
2177
2635
  * @example
2178
2636
  * await form.formFilter('NumberFld').setValue(123);
2179
2637
  * await form.formFilter('TextFld').setValue('TestValue');
2638
+ * await form.formFilter('TextFld').setValue('TestValue', '=', true);
2180
2639
  */
2181
- async setValue(value) {
2640
+ async setValue(value, operation, isBlank) {
2641
+ if (typeof operation === "string") {
2642
+ await this.setOperation(operation);
2643
+ }
2644
+ if (typeof isBlank === "boolean") {
2645
+ await this.setIsBlank(isBlank);
2646
+ }
2182
2647
  return super.setValue(value);
2183
2648
  }
2184
2649
  /**
@@ -2277,8 +2742,15 @@ var init_PanelFilterField = __esm({
2277
2742
  * @example
2278
2743
  * await form.filterPanel.filterField('NumberFld').setValue(123);
2279
2744
  * await form.filterPanel.filterField('TextFld').setValue('TestValue');
2745
+ * await form.filterPanel.filterField('TextFld').setValue('TestValue', '=', true);
2280
2746
  */
2281
- async setValue(value) {
2747
+ async setValue(value, operation, isBlank) {
2748
+ if (typeof operation === "string") {
2749
+ await this.setOperation(operation);
2750
+ }
2751
+ if (typeof isBlank === "boolean") {
2752
+ await this.setIsBlank(isBlank);
2753
+ }
2282
2754
  return super.setValue(value);
2283
2755
  }
2284
2756
  /**
@@ -2347,11 +2819,11 @@ var init_PanelFilterField = __esm({
2347
2819
  });
2348
2820
 
2349
2821
  // src/pageObjects/elements/Filters/FilterPanel.ts
2350
- var import_selenium_webdriver26, drawerSelector, FILTER_PANEL_SELECTOR, CLOSE_SELECTOR, FilterPanel;
2822
+ var import_selenium_webdriver27, drawerSelector, FILTER_PANEL_SELECTOR, CLOSE_SELECTOR, FilterPanel;
2351
2823
  var init_FilterPanel = __esm({
2352
2824
  "src/pageObjects/elements/Filters/FilterPanel.ts"() {
2353
2825
  "use strict";
2354
- import_selenium_webdriver26 = require("selenium-webdriver");
2826
+ import_selenium_webdriver27 = require("selenium-webdriver");
2355
2827
  init_AbstractElement();
2356
2828
  init_PanelFilterField();
2357
2829
  init_actions();
@@ -2366,7 +2838,7 @@ var init_FilterPanel = __esm({
2366
2838
  async filterPanelButtons() {
2367
2839
  const selector = `${this.elementCssSelector} ${FILTER_PANEL_SELECTOR} .filter-panel__buttons-panel .dx-button-text`;
2368
2840
  const el = await this.getElement();
2369
- return el.findElements(import_selenium_webdriver26.By.css(selector));
2841
+ return el.findElements(import_selenium_webdriver27.By.css(selector));
2370
2842
  }
2371
2843
  constructor(formName, driver) {
2372
2844
  super(driver, drawerSelector(formName));
@@ -2399,7 +2871,7 @@ var init_FilterPanel = __esm({
2399
2871
  await this.driver.sleep(300);
2400
2872
  }
2401
2873
  async close() {
2402
- const btn = await this.driver.findElement(import_selenium_webdriver26.By.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
2874
+ const btn = await this.driver.findElement(import_selenium_webdriver27.By.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
2403
2875
  await click(btn, this.driver);
2404
2876
  }
2405
2877
  };
@@ -2435,12 +2907,12 @@ var init_HeaderFilterField = __esm({
2435
2907
  });
2436
2908
 
2437
2909
  // src/pageObjects/elements/Filters/ColumnFilter.ts
2438
- var import_selenium_webdriver27, APPLY_SELECTOR, CANCEL_SELECTOR, HEADER_FILTER_ICON, HEADER_FILTER_CONTAINER, HEADER_FILTER_BUTTONS, ColumnFilter;
2910
+ var import_selenium_webdriver28, APPLY_SELECTOR, CANCEL_SELECTOR, HEADER_FILTER_ICON, HEADER_FILTER_CONTAINER, HEADER_FILTER_BUTTONS, ColumnFilter;
2439
2911
  var init_ColumnFilter = __esm({
2440
2912
  "src/pageObjects/elements/Filters/ColumnFilter.ts"() {
2441
2913
  "use strict";
2442
2914
  init_actions();
2443
- import_selenium_webdriver27 = require("selenium-webdriver");
2915
+ import_selenium_webdriver28 = require("selenium-webdriver");
2444
2916
  init_HeaderFilterField();
2445
2917
  init_waitElementIsVisible();
2446
2918
  init_AbstractElement();
@@ -2465,11 +2937,11 @@ var init_ColumnFilter = __esm({
2465
2937
  }
2466
2938
  async getApplyButton() {
2467
2939
  const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${APPLY_SELECTOR}`;
2468
- return this.driver.findElement(import_selenium_webdriver27.By.css(selector));
2940
+ return this.driver.findElement(import_selenium_webdriver28.By.css(selector));
2469
2941
  }
2470
2942
  async getCancelButton() {
2471
2943
  const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${CANCEL_SELECTOR}`;
2472
- return this.driver.findElement(import_selenium_webdriver27.By.css(selector));
2944
+ return this.driver.findElement(import_selenium_webdriver28.By.css(selector));
2473
2945
  }
2474
2946
  async apply() {
2475
2947
  const btn = await this.getApplyButton();
@@ -2483,7 +2955,7 @@ var init_ColumnFilter = __esm({
2483
2955
  const columnEl = await this._column.getElement();
2484
2956
  const actions = this.driver.actions({ async: true });
2485
2957
  await actions.move({ origin: columnEl }).perform();
2486
- const elements = await columnEl.findElements(import_selenium_webdriver27.By.css(HEADER_FILTER_ICON));
2958
+ const elements = await columnEl.findElements(import_selenium_webdriver28.By.css(HEADER_FILTER_ICON));
2487
2959
  let headerFilterIcon = null;
2488
2960
  await wait(
2489
2961
  async () => {
@@ -2529,9 +3001,23 @@ var init_ColumnFilter = __esm({
2529
3001
  * @example
2530
3002
  * await form.columnFilter('NumberFld').setValue(123);
2531
3003
  * await form.columnFilter('TextFld').setValue('TestValue');
3004
+ * await form.columnFilter('TextFld').setValue('TestValue', '=', true);
2532
3005
  */
2533
- async setValue(value) {
3006
+ async setValue(value, operation, isBlank) {
2534
3007
  const filter = await this.initFilter();
3008
+ const filterOperation = new FilterOperation({
3009
+ parentCssSelector: HEADER_FILTER_CONTAINER,
3010
+ filterTestID: createHeaderFilterTestId(this._formName, this._name)
3011
+ });
3012
+ const inputEl = await filter.getElement();
3013
+ if (typeof operation === "string") {
3014
+ await inputEl.click();
3015
+ await filterOperation.setOperation(operation);
3016
+ }
3017
+ if (typeof isBlank === "boolean") {
3018
+ await inputEl.click();
3019
+ await filterOperation.setIsBlank(isBlank);
3020
+ }
2535
3021
  await filter.setValue(value);
2536
3022
  return this.apply();
2537
3023
  }
@@ -2555,32 +3041,52 @@ var init_ColumnFilter = __esm({
2555
3041
  await filter.remove(itemText);
2556
3042
  return this.apply();
2557
3043
  }
2558
- // ToDo: Треба доробити після того, як буде реалізована логіка з editor buttons
3044
+ /**
3045
+ * Инициализация операции фильтра
3046
+ */
2559
3047
  async initOperation() {
2560
- await this.initFilter();
3048
+ const filter = await this.initFilter();
3049
+ const inputEl = await filter.getElement();
3050
+ await inputEl.click();
2561
3051
  return new FilterOperation({
2562
3052
  parentCssSelector: HEADER_FILTER_CONTAINER,
2563
3053
  filterTestID: createHeaderFilterTestId(this._formName, this._name)
2564
3054
  });
2565
3055
  }
2566
- // ToDo: Треба доробити після того, як буде реалізована логіка з editor buttons
3056
+ /**
3057
+ * Устанавливает операцию для фильтра
3058
+ * @example
3059
+ * await form.columnFilter('TagBox').setOperation("=");
3060
+ */
2567
3061
  async setOperation(operationName) {
2568
3062
  const filterOperation = await this.initOperation();
2569
3063
  await filterOperation.setOperation(operationName);
2570
3064
  await this.apply();
2571
3065
  }
2572
- // ToDo: Треба доробити після того, як буде реалізована логіка з editor buttons
3066
+ /**
3067
+ * Возвращает операцию фильтра
3068
+ * @example
3069
+ * expect(await form.columnFilter('NumberFld').getOperation()).toBe("=");
3070
+ */
2573
3071
  async getOperation() {
2574
3072
  const filterOperation = await this.initOperation();
2575
3073
  return await filterOperation.getOperation();
2576
3074
  }
2577
- // ToDo: Треба доробити після того, як буде реалізована логіка з editor buttons
3075
+ /**
3076
+ * Устанавливает операцию 'isblank' для фильтра
3077
+ * @example
3078
+ * await form.columnFilter('TagBox').setIsBlank(true);
3079
+ */
2578
3080
  async setIsBlank(value) {
2579
3081
  const filterOperation = await this.initOperation();
2580
3082
  await filterOperation.setIsBlank(value);
2581
3083
  await this.apply();
2582
3084
  }
2583
- // ToDo: Треба доробити після того, як буде реалізована логіка з editor buttons
3085
+ /**
3086
+ * Возвращает true|false, если операция 'isblank' установлена для фильтра
3087
+ * @example
3088
+ * expect(await form.columnFilter('NumberFld').getIsBlank()).toBe(false);
3089
+ */
2584
3090
  async getIsBlank() {
2585
3091
  const filterOperation = await this.initOperation();
2586
3092
  return await filterOperation.getIsBlank();
@@ -2594,7 +3100,7 @@ var ListForm_exports = {};
2594
3100
  __export(ListForm_exports, {
2595
3101
  default: () => ListForm
2596
3102
  });
2597
- var DATAGRID_HEADER_CSS_SELECTOR, ListForm;
3103
+ var DATAGRID_HEADER_CSS_SELECTOR, DATAGRID_CONTENT_CSS_SELECTOR, FIXED_DATAGRID_CONTENT_CSS_SELECTOR, CONTEXT_MENU_CSS_SELECTOR, ListForm;
2598
3104
  var init_ListForm = __esm({
2599
3105
  "src/pageObjects/elements/Forms/ListForm.ts"() {
2600
3106
  "use strict";
@@ -2605,12 +3111,21 @@ var init_ListForm = __esm({
2605
3111
  init_FilterPanel();
2606
3112
  init_ColumnFilter();
2607
3113
  DATAGRID_HEADER_CSS_SELECTOR = ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
3114
+ DATAGRID_CONTENT_CSS_SELECTOR = ".dx-datagrid-content:not(.dx-datagrid-content-fixed)";
3115
+ FIXED_DATAGRID_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
3116
+ CONTEXT_MENU_CSS_SELECTOR = ".dx-datagrid";
2608
3117
  ListForm = class extends Form {
2609
3118
  headerCssSelector;
3119
+ fixedTableContentCssSelector;
3120
+ tableContentCssSelector;
3121
+ contextMenuCssSelector;
2610
3122
  constructor(driver) {
2611
3123
  super(driver);
2612
- this.popupContainerCssSelector = `.popup .form-inline-${this.formName}`;
3124
+ this.popupContainerCssSelector = `.popup.form-inline-${this.formName}`;
2613
3125
  this.headerCssSelector = DATAGRID_HEADER_CSS_SELECTOR;
3126
+ this.fixedTableContentCssSelector = FIXED_DATAGRID_CONTENT_CSS_SELECTOR;
3127
+ this.tableContentCssSelector = DATAGRID_CONTENT_CSS_SELECTOR;
3128
+ this.contextMenuCssSelector = CONTEXT_MENU_CSS_SELECTOR;
2614
3129
  }
2615
3130
  /**
2616
3131
  * Находит таблицу
@@ -2620,7 +3135,17 @@ var init_ListForm = __esm({
2620
3135
  * expect(listForm.table());
2621
3136
  */
2622
3137
  table() {
2623
- return new Table(this.containerCssSelector, this.headerCssSelector, this.formName, this.driver);
3138
+ return new Table(
3139
+ {
3140
+ parentCssSelector: this.containerCssSelector,
3141
+ headerCssSelector: this.headerCssSelector,
3142
+ fixedTableContentCssSelector: this.fixedTableContentCssSelector,
3143
+ formName: this.formName,
3144
+ driver: this.driver,
3145
+ contextMenuCssSelector: this.contextMenuCssSelector,
3146
+ tableContentCssSelector: this.tableContentCssSelector
3147
+ }
3148
+ );
2624
3149
  }
2625
3150
  /**
2626
3151
  * Находит таблицу
@@ -2667,25 +3192,34 @@ var TreeView_exports = {};
2667
3192
  __export(TreeView_exports, {
2668
3193
  default: () => TreeView
2669
3194
  });
2670
- var TREELIST_HEADER_CSS_SELECTOR, TreeView;
3195
+ var TREELIST_HEADER_CSS_SELECTOR, TREELIST_CONTENT_CSS_SELECTOR, FIXED_TREELIST_CONTENT_CSS_SELECTOR, TreeView;
2671
3196
  var init_TreeView = __esm({
2672
3197
  "src/pageObjects/elements/Forms/TreeView.ts"() {
2673
3198
  "use strict";
2674
3199
  init_ListForm();
2675
3200
  TREELIST_HEADER_CSS_SELECTOR = ".dx-treelist-headers .dx-treelist-content:not(.dx-datagrid-content-fixed)";
3201
+ TREELIST_CONTENT_CSS_SELECTOR = ".dx-treelist-content:not(.dx-datagrid-content-fixed)";
3202
+ FIXED_TREELIST_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-treelist-content.dx-treelist-content-fixed";
2676
3203
  TreeView = class extends ListForm {
2677
3204
  constructor(driver) {
2678
3205
  super(driver);
2679
- this.popupContainerCssSelector = `.popup .wrapper-tree-view-${this.formName}`;
3206
+ this.popupContainerCssSelector = `.popup.tree-view-${this.formName}`;
2680
3207
  this.headerCssSelector = TREELIST_HEADER_CSS_SELECTOR;
3208
+ this.fixedTableContentCssSelector = FIXED_TREELIST_CONTENT_CSS_SELECTOR;
3209
+ this.contextMenuCssSelector = ".dx-treelist-container";
3210
+ this.tableContentCssSelector = TREELIST_CONTENT_CSS_SELECTOR;
2681
3211
  }
2682
3212
  };
2683
3213
  }
2684
3214
  });
2685
3215
 
2686
3216
  // src/pageObjects/elements/Forms/createSubFormInstance.ts
2687
- function subformCssSelector(parentCssSelector, testId) {
2688
- return `${parentCssSelector} ${byTestIdCssSelector(testId)}`;
3217
+ function subformCssSelector(parentCssSelector, testId, isDockPanel = false) {
3218
+ if (isDockPanel) {
3219
+ return `${SECONDARY_DRAWER_LAYOUT_CONTENT} ${byTestIdCssSelector(testId)}`;
3220
+ } else {
3221
+ return `${parentCssSelector} ${byTestIdCssSelector(testId)}`;
3222
+ }
2689
3223
  }
2690
3224
  async function classDependencyInjector(formType) {
2691
3225
  let SubFormFactoryClass;
@@ -2706,23 +3240,24 @@ async function classDependencyInjector(formType) {
2706
3240
  }
2707
3241
  return SubFormFactoryClass;
2708
3242
  }
2709
- var subFormTestId;
3243
+ var SECONDARY_DRAWER_LAYOUT_CONTENT, subFormTestId;
2710
3244
  var init_createSubFormInstance = __esm({
2711
3245
  "src/pageObjects/elements/Forms/createSubFormInstance.ts"() {
2712
3246
  "use strict";
2713
3247
  init_locators();
2714
3248
  init_types2();
3249
+ SECONDARY_DRAWER_LAYOUT_CONTENT = ".secondary-drawer-layout-content";
2715
3250
  subFormTestId = (name) => `subform-${name}`;
2716
3251
  }
2717
3252
  });
2718
3253
 
2719
3254
  // src/pageObjects/elements/Forms/Form.ts
2720
- var import_selenium_webdriver28, formTestId, Form;
3255
+ var import_selenium_webdriver29, formTestId, Form;
2721
3256
  var init_Form = __esm({
2722
3257
  "src/pageObjects/elements/Forms/Form.ts"() {
2723
3258
  "use strict";
2724
3259
  init_locators();
2725
- import_selenium_webdriver28 = require("selenium-webdriver");
3260
+ import_selenium_webdriver29 = require("selenium-webdriver");
2726
3261
  init_AbstractForm();
2727
3262
  init_waitElementIsVisible();
2728
3263
  init_createSubFormInstance();
@@ -2747,10 +3282,15 @@ var init_Form = __esm({
2747
3282
  */
2748
3283
  async getTitleText() {
2749
3284
  if (await this.isModal()) {
2750
- const titleEl2 = await this.driver.findElement(import_selenium_webdriver28.By.css(`${this.popupContainerCssSelector} .popup-title`));
3285
+ const titleEl2 = await this.driver.findElement(import_selenium_webdriver29.By.css(`${this.popupContainerCssSelector} .popup-title`));
3286
+ await waitElementIsVisible({
3287
+ element: titleEl2,
3288
+ driver: this.driver,
3289
+ errorMessage: `Form title element is not visible`
3290
+ });
2751
3291
  return titleEl2.getText();
2752
3292
  }
2753
- let titleEl = await this.driver.findElement(import_selenium_webdriver28.By.className("main-toolbar-form-title"));
3293
+ let titleEl = await this.driver.findElement(import_selenium_webdriver29.By.className("main-toolbar-form-title"));
2754
3294
  return titleEl.getText();
2755
3295
  }
2756
3296
  setSubFormMode() {
@@ -2766,9 +3306,10 @@ var init_Form = __esm({
2766
3306
  * //...
2767
3307
  * expect(await form.subForm(name));
2768
3308
  */
2769
- async subForm(name) {
2770
- const cssSelector = subformCssSelector(this.containerCssSelector, subFormTestId(name));
2771
- const byCssSelector = import_selenium_webdriver28.By.css(cssSelector);
3309
+ async subForm(name, options = {}) {
3310
+ const { isDockPanel = false } = options;
3311
+ const cssSelector = subformCssSelector(this.containerCssSelector, subFormTestId(name), isDockPanel);
3312
+ const byCssSelector = import_selenium_webdriver29.By.css(cssSelector);
2772
3313
  const subFormEl = await this.driver.findElement(byCssSelector);
2773
3314
  await waitElementIsVisible({
2774
3315
  element: subFormEl,
@@ -2798,21 +3339,27 @@ var FormEdit_exports = {};
2798
3339
  __export(FormEdit_exports, {
2799
3340
  default: () => FormEdit
2800
3341
  });
2801
- var import_selenium_webdriver29, FormEdit;
3342
+ var import_selenium_webdriver30, FormEdit;
2802
3343
  var init_FormEdit = __esm({
2803
3344
  "src/pageObjects/elements/Forms/FormEdit.ts"() {
2804
3345
  "use strict";
2805
3346
  init_Form();
2806
- import_selenium_webdriver29 = require("selenium-webdriver");
3347
+ import_selenium_webdriver30 = require("selenium-webdriver");
2807
3348
  init_FormField();
2808
3349
  init_actions();
2809
3350
  init_wait();
2810
3351
  FormEdit = class extends Form {
2811
- saveButtonBy = import_selenium_webdriver29.By.id("button-save");
2812
- closeButtonBy = import_selenium_webdriver29.By.id("button-cancel");
3352
+ saveButtonId = "#button-save";
3353
+ closeButtonId = "#button-cancel";
2813
3354
  constructor(driver) {
2814
3355
  super(driver);
2815
- this.popupContainerCssSelector = `.popup .form-edit-${this.formName}`;
3356
+ this.popupContainerCssSelector = `.popup.form-edit-${this.formName}`;
3357
+ }
3358
+ async getButtonCssSelector(buttonId) {
3359
+ if (await this.isModal()) {
3360
+ return `${this.popupContainerCssSelector} ${buttonId}`;
3361
+ }
3362
+ return buttonId;
2816
3363
  }
2817
3364
  /**
2818
3365
  * Находит поле формы редактирования по имени
@@ -2832,7 +3379,8 @@ var init_FormEdit = __esm({
2832
3379
  * await formEdit.isSaveButtonDisabled();
2833
3380
  */
2834
3381
  async isSaveButtonDisabled() {
2835
- const saveButton = await this.driver.findElement(this.saveButtonBy);
3382
+ const saveButtonCssSelector = await this.getButtonCssSelector(this.saveButtonId);
3383
+ const saveButton = await this.driver.findElement(import_selenium_webdriver30.By.css(saveButtonCssSelector));
2836
3384
  const result = await saveButton.getAttribute("aria-disabled");
2837
3385
  return result === "true";
2838
3386
  }
@@ -2844,7 +3392,8 @@ var init_FormEdit = __esm({
2844
3392
  * await formEdit.saveButtonClick();
2845
3393
  */
2846
3394
  async saveButtonClick() {
2847
- const saveButton = await this.driver.findElement(this.saveButtonBy);
3395
+ const saveButtonCssSelector = await this.getButtonCssSelector(this.saveButtonId);
3396
+ const saveButton = await this.driver.findElement(import_selenium_webdriver30.By.css(saveButtonCssSelector));
2848
3397
  await wait(async () => !await this.isSaveButtonDisabled(), this.driver, "Button is disabled");
2849
3398
  await click(saveButton, this.driver);
2850
3399
  }
@@ -2856,7 +3405,8 @@ var init_FormEdit = __esm({
2856
3405
  * await formEdit.closeButtonClick();
2857
3406
  */
2858
3407
  async closeButtonClick() {
2859
- const closeButton = await this.driver.findElement(this.closeButtonBy);
3408
+ const closeButtonCssSelector = await this.getButtonCssSelector(this.closeButtonId);
3409
+ const closeButton = await this.driver.findElement(import_selenium_webdriver30.By.css(closeButtonCssSelector));
2860
3410
  await click(closeButton, this.driver);
2861
3411
  }
2862
3412
  };
@@ -2885,12 +3435,14 @@ __export(src_exports, {
2885
3435
  byTestIdCssSelector: () => byTestIdCssSelector,
2886
3436
  click: () => click,
2887
3437
  config: () => config,
3438
+ contextMenu: () => contextMenu,
2888
3439
  createDriver: () => createDriver,
2889
3440
  editorFactory: () => editorFactory,
2890
3441
  elementIsNotPresent: () => elementIsNotPresent,
2891
3442
  readonlyLocator: () => readonlyLocator,
2892
3443
  signIn: () => signIn,
2893
3444
  wait: () => wait,
3445
+ waitElementIsClickable: () => waitElementIsClickable_default,
2894
3446
  waitElementIsVisible: () => waitElementIsVisible
2895
3447
  });
2896
3448
  module.exports = __toCommonJS(src_exports);
@@ -2962,6 +3514,7 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
2962
3514
 
2963
3515
  // src/index.ts
2964
3516
  init_waitElementIsVisible();
3517
+ init_waitElementIsClickable();
2965
3518
  init_wait();
2966
3519
 
2967
3520
  // src/utils/signIn.ts
@@ -2992,7 +3545,7 @@ var SubsystemsPanelHeader = class extends AbstractElementWithParent {
2992
3545
  };
2993
3546
 
2994
3547
  // src/pageObjects/elements/SubsystemsPanel/SubsystemsPanel.ts
2995
- var import_selenium_webdriver15 = require("selenium-webdriver");
3548
+ var import_selenium_webdriver16 = require("selenium-webdriver");
2996
3549
  init_wait();
2997
3550
  init_locators();
2998
3551
  init_Editors();
@@ -3000,6 +3553,8 @@ init_Editors();
3000
3553
  // src/pageObjects/elements/SubsystemsPanel/SubsystemItem.ts
3001
3554
  init_actions();
3002
3555
  init_fixElementStaleError();
3556
+ init_waitElementIsVisible();
3557
+ init_waitElementIsClickable();
3003
3558
  var SubsystemItem = class {
3004
3559
  bySelector;
3005
3560
  driver;
@@ -3012,10 +3567,22 @@ var SubsystemItem = class {
3012
3567
  }
3013
3568
  async getTitle() {
3014
3569
  const el = await this.getElement();
3570
+ await waitElementIsVisible(
3571
+ {
3572
+ element: el,
3573
+ driver: this.driver
3574
+ }
3575
+ );
3015
3576
  return await el.getAttribute("data-title");
3016
3577
  }
3017
3578
  async click() {
3018
3579
  const el = await this.getElement();
3580
+ await waitElementIsClickable_default(
3581
+ {
3582
+ element: el,
3583
+ driver: this.driver
3584
+ }
3585
+ );
3019
3586
  await click(el, this.driver);
3020
3587
  }
3021
3588
  };
@@ -3025,6 +3592,7 @@ init_createDataTestId();
3025
3592
  init_actions();
3026
3593
  init_ClearButtonStrategy();
3027
3594
  init_waitElementIsVisible();
3595
+ init_fixElementStaleError();
3028
3596
  var SEARCH_ITEM_SELECTOR = "search-item";
3029
3597
  var BACK_BUTTON_SELECTOR = "subsystem-back-item";
3030
3598
  var SEARCH_INPUT_SELECTOR = "search-subsystem-input";
@@ -3054,6 +3622,7 @@ var SubsystemsPanel = class extends AbstractElement {
3054
3622
  */
3055
3623
  async search(title) {
3056
3624
  const searchComponent = this.getSearchComponent();
3625
+ await this.searchClear();
3057
3626
  await searchComponent.setValue(title);
3058
3627
  await wait(
3059
3628
  async () => {
@@ -3074,7 +3643,7 @@ var SubsystemsPanel = class extends AbstractElement {
3074
3643
  */
3075
3644
  async searchClear() {
3076
3645
  const clearBtnSelector = `#aside ${byTestIdCssSelector(SEARCH_INPUT_SELECTOR)} .${DX_CLEAR_BUTTON_AREA}`;
3077
- const clearBtn = await this.driver.findElement(import_selenium_webdriver15.By.css(clearBtnSelector));
3646
+ const clearBtn = await fixElementStaleError(import_selenium_webdriver16.By.css(clearBtnSelector), this.driver);
3078
3647
  if (await clearBtn.isDisplayed()) {
3079
3648
  await click(clearBtn, this.driver);
3080
3649
  }
@@ -3088,7 +3657,7 @@ var SubsystemsPanel = class extends AbstractElement {
3088
3657
  */
3089
3658
  item(name) {
3090
3659
  const elementCSS = createSubSystemTestId(name);
3091
- return new SubsystemItem({ driver: this.driver, bySelector: import_selenium_webdriver15.By.css(`${byTestIdCssSelector(elementCSS, "span")}`) });
3660
+ return new SubsystemItem({ driver: this.driver, bySelector: import_selenium_webdriver16.By.css(`${byTestIdCssSelector(elementCSS, "span")}`) });
3092
3661
  }
3093
3662
  /**
3094
3663
  * Возвращает сабсистему по заголовку
@@ -3098,7 +3667,7 @@ var SubsystemsPanel = class extends AbstractElement {
3098
3667
  * const subsystem = subsystemsPanel.itemByTitle('SubSystemTitle');
3099
3668
  */
3100
3669
  itemByTitle(title) {
3101
- return new SubsystemItem({ driver: this.driver, bySelector: import_selenium_webdriver15.By.css(byTitleCssSelector(title)) });
3670
+ return new SubsystemItem({ driver: this.driver, bySelector: import_selenium_webdriver16.By.css(byTitleCssSelector(title)) });
3102
3671
  }
3103
3672
  /**
3104
3673
  * Возвращается на уровень выше по сабсистемам
@@ -3108,7 +3677,7 @@ var SubsystemsPanel = class extends AbstractElement {
3108
3677
  * wait subsystemsPanel.back();
3109
3678
  */
3110
3679
  async back() {
3111
- const backButton = this.driver.findElement(import_selenium_webdriver15.By.css(`#aside .${BACK_BUTTON_SELECTOR}`));
3680
+ const backButton = await fixElementStaleError(import_selenium_webdriver16.By.css(`#aside .${BACK_BUTTON_SELECTOR}`), this.driver);
3112
3681
  await waitElementIsVisible(
3113
3682
  {
3114
3683
  element: backButton,
@@ -3125,13 +3694,12 @@ init_ListForm();
3125
3694
  init_TreeView();
3126
3695
 
3127
3696
  // src/pageObjects/elements/Forms/ReportForm.ts
3128
- var import_selenium_webdriver30 = require("selenium-webdriver");
3129
3697
  init_FormEdit();
3130
3698
  var ReportForm = class extends FormEdit {
3131
3699
  constructor(driver) {
3132
3700
  super(driver);
3133
- this.popupContainerCssSelector = `.popup .form-report-${this.formName}`;
3134
- this.saveButtonBy = import_selenium_webdriver30.By.id("button-apply");
3701
+ this.popupContainerCssSelector = `.popup.form-report-${this.formName}`;
3702
+ this.saveButtonId = "#button-apply";
3135
3703
  }
3136
3704
  /**
3137
3705
  * Знаходить поле/фільтр у формі репорту за ім'ям
@@ -3160,7 +3728,7 @@ var DIALOG_CLASS = ".d5-dialog";
3160
3728
  var DIALOG_TITLE_CLASS = ".dialog__title";
3161
3729
  var DIALOG_TEXT_CLASS = ".dialog__text";
3162
3730
  var DIALOG_BUTTONS_PANEL_CLASS = ".dialog__buttons-panel";
3163
- var buttonByTextXpath2 = (text) => `.//span[contains(@class, "dx-button-text") and contains(text(), "${text}")]`;
3731
+ var buttonByTextXpath = (text) => `.//span[contains(@class, "dx-button-text") and contains(text(), "${text}")]`;
3164
3732
  var DialogButton = class extends AbstractButton {
3165
3733
  text;
3166
3734
  constructor(parentCssSelector, text, driver) {
@@ -3169,7 +3737,7 @@ var DialogButton = class extends AbstractButton {
3169
3737
  }
3170
3738
  async getElement() {
3171
3739
  const panel = await super.getElement();
3172
- return panel.findElement(import_selenium_webdriver31.By.xpath(buttonByTextXpath2(this.text)));
3740
+ return panel.findElement(import_selenium_webdriver31.By.xpath(buttonByTextXpath(this.text)));
3173
3741
  }
3174
3742
  buttonNotDisplayedError() {
3175
3743
  return `Dialog button ${this.text} cannot be clicked. It is not displayed or it is disabled`;
@@ -3221,11 +3789,13 @@ var Dialog = class extends AbstractElement {
3221
3789
  byTestIdCssSelector,
3222
3790
  click,
3223
3791
  config,
3792
+ contextMenu,
3224
3793
  createDriver,
3225
3794
  editorFactory,
3226
3795
  elementIsNotPresent,
3227
3796
  readonlyLocator,
3228
3797
  signIn,
3229
3798
  wait,
3799
+ waitElementIsClickable,
3230
3800
  waitElementIsVisible
3231
3801
  });