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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,29 +34,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
34
34
  function config(cfg) {
35
35
  return configInstance.config(cfg);
36
36
  }
37
- var process, driversMap, createConfigProxy, Config, configInstance;
37
+ var Config, configInstance;
38
38
  var init_config = __esm({
39
39
  "src/config.ts"() {
40
40
  "use strict";
41
- process = __toESM(require("process"));
42
- driversMap = /* @__PURE__ */ new Map();
43
- createConfigProxy = (config2) => {
44
- return new Proxy(config2, {
45
- get(_target, prop) {
46
- if (prop === "driver") {
47
- return driversMap.get(process.pid);
48
- }
49
- return Reflect.get(...arguments);
50
- },
51
- set(_target, prop, value) {
52
- if (prop === "driver") {
53
- driversMap.set(process.pid, value);
54
- return true;
55
- }
56
- return Reflect.set(...arguments);
57
- }
58
- });
59
- };
60
41
  Config = class _Config {
61
42
  static instance;
62
43
  appConfig;
@@ -67,8 +48,7 @@ var init_config = __esm({
67
48
  return _Config.instance;
68
49
  }
69
50
  config = (cfg) => {
70
- if (!cfg)
71
- return createConfigProxy(this.appConfig);
51
+ if (!cfg) return this.appConfig;
72
52
  this.appConfig = cfg;
73
53
  };
74
54
  };
@@ -80,23 +60,38 @@ var init_config = __esm({
80
60
  function fixElementStaleError(by, driver) {
81
61
  const maxCount = 3;
82
62
  let err;
83
- const call = async (times = 0) => {
84
- if (times > maxCount)
85
- throw err;
63
+ const call = async (times) => {
64
+ if (times > maxCount) throw err;
86
65
  try {
87
66
  let el = await driver.findElement(by);
88
67
  await el.getAttribute("class");
89
68
  return el;
90
69
  } catch (e) {
91
70
  err = e;
92
- if (e instanceof Error && e.name === "StaleElementReferenceError") {
93
- return call(++times);
71
+ if (e instanceof Error && e.message.toLowerCase().includes("stale element")) {
72
+ return call(times + 1);
73
+ }
74
+ }
75
+ if (err) throw err;
76
+ };
77
+ return call(0);
78
+ }
79
+ async function staleElementAction(action) {
80
+ const maxCount = 3;
81
+ let err;
82
+ const call = async (times) => {
83
+ if (times > maxCount) throw err;
84
+ try {
85
+ await action();
86
+ } catch (e) {
87
+ err = e;
88
+ if (e instanceof Error && e.message.toLowerCase().includes("stale element")) {
89
+ await call(times + 1);
94
90
  }
95
91
  }
96
- if (err)
97
- throw err;
92
+ if (err) throw err;
98
93
  };
99
- return call();
94
+ await call(0);
100
95
  }
101
96
  var init_fixElementStaleError = __esm({
102
97
  "src/utils/fixElementStaleError.ts"() {
@@ -110,13 +105,12 @@ var init_AbstractElement = __esm({
110
105
  "src/pageObjects/AbstractElement.ts"() {
111
106
  "use strict";
112
107
  import_selenium_webdriver = require("selenium-webdriver");
113
- init_config();
114
108
  init_fixElementStaleError();
115
109
  AbstractElement = class {
116
110
  driver;
117
111
  elementCssSelector;
118
112
  constructor(driver, elementCssSelector) {
119
- this.driver = driver || config().driver;
113
+ this.driver = driver;
120
114
  this.elementCssSelector = elementCssSelector;
121
115
  }
122
116
  getFullCssSelector() {
@@ -181,9 +175,17 @@ var init_AbstractPage = __esm({
181
175
 
182
176
  // src/utils/wait.ts
183
177
  async function wait(condition, driver, errorMessage, timeout) {
184
- driver = driver ?? config().driver;
185
178
  await driver.wait(condition, timeout ?? config().timeout, errorMessage);
186
179
  }
180
+ function safeWait(condition, driver, errorMessage, timeout) {
181
+ return wait(async () => {
182
+ try {
183
+ return await condition(driver);
184
+ } catch {
185
+ return false;
186
+ }
187
+ }, driver, errorMessage, timeout);
188
+ }
187
189
  var init_wait = __esm({
188
190
  "src/utils/wait.ts"() {
189
191
  "use strict";
@@ -193,58 +195,89 @@ var init_wait = __esm({
193
195
 
194
196
  // src/utils/waitElementIsVisible.ts
195
197
  async function waitElementIsVisible({
196
- element,
197
198
  timeout,
198
199
  errorMessage,
199
- driver
200
+ driver,
201
+ ...rest
200
202
  }) {
201
- driver = driver ?? config().driver;
202
- const condition = import_selenium_webdriver2.until.elementIsVisible(element);
203
- await wait(condition.fn, driver, errorMessage ?? condition.description(), timeout ?? config().timeout);
203
+ await safeWait(async () => {
204
+ const searchedElement = "by" in rest ? await fixElementStaleError(rest.by, driver) : rest.element;
205
+ return await searchedElement.isDisplayed();
206
+ }, driver, errorMessage ?? "Element is not visible", timeout ?? config().timeout);
204
207
  }
205
- var import_selenium_webdriver2;
208
+ var waitElementIsVisible_default;
206
209
  var init_waitElementIsVisible = __esm({
207
210
  "src/utils/waitElementIsVisible.ts"() {
208
211
  "use strict";
209
- import_selenium_webdriver2 = require("selenium-webdriver");
210
212
  init_config();
211
213
  init_wait();
214
+ init_fixElementStaleError();
215
+ waitElementIsVisible_default = waitElementIsVisible;
212
216
  }
213
217
  });
214
218
 
215
219
  // src/utils/actions.ts
216
- var click;
220
+ var click, contextMenu;
217
221
  var init_actions = __esm({
218
222
  "src/utils/actions.ts"() {
219
223
  "use strict";
220
- init_config();
221
224
  click = async (webElement, driver) => {
222
- driver = driver ?? config().driver;
223
225
  if (!await webElement.isDisplayed()) {
224
226
  await driver.executeScript("arguments[0].scrollIntoView(true);", webElement);
225
227
  }
226
228
  const actions = driver.actions({ async: true });
227
229
  await actions.move({ origin: webElement }).click().perform();
228
230
  };
231
+ contextMenu = async (webElement, driver) => {
232
+ if (!await webElement.isDisplayed()) {
233
+ await driver.executeScript("arguments[0].scrollIntoView(true);", webElement);
234
+ }
235
+ const actions = driver.actions({ async: true });
236
+ await actions.move({ origin: webElement }).contextClick().perform();
237
+ };
229
238
  }
230
239
  });
231
240
 
232
241
  // src/utils/locators.ts
233
- var import_selenium_webdriver3, byTestIdCssSelector, byTestId, readonlyLocator;
242
+ var import_selenium_webdriver2, byTestIdCssSelector, byTestId, readonlyLocator;
234
243
  var init_locators = __esm({
235
244
  "src/utils/locators.ts"() {
236
245
  "use strict";
237
- import_selenium_webdriver3 = require("selenium-webdriver");
246
+ import_selenium_webdriver2 = require("selenium-webdriver");
238
247
  byTestIdCssSelector = (testId, element = "div") => {
239
248
  return `${element}[data-testid="${testId}"]`;
240
249
  };
241
250
  byTestId = (testId, element = "div") => {
242
- return import_selenium_webdriver3.By.css(byTestIdCssSelector(testId, element));
251
+ return import_selenium_webdriver2.By.css(byTestIdCssSelector(testId, element));
243
252
  };
244
253
  readonlyLocator = "readonly";
245
254
  }
246
255
  });
247
256
 
257
+ // src/utils/waitElementIsClickable.ts
258
+ async function waitElementIsClickable({
259
+ timeout,
260
+ errorMessage,
261
+ driver,
262
+ ...rest
263
+ }) {
264
+ await safeWait(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);
@@ -417,10 +451,8 @@ var init_CheckBox = __esm({
417
451
  CheckBox = class extends AbstractElementWithParent {
418
452
  async getValue() {
419
453
  const result = await this.getAttribute("aria-checked");
420
- if (result === "true")
421
- return 1;
422
- if (result === "false")
423
- return 0;
454
+ if (result === "true") return 1;
455
+ if (result === "false") return 0;
424
456
  return null;
425
457
  }
426
458
  async setValue(value) {
@@ -546,10 +578,8 @@ var init_SwitchEditor = __esm({
546
578
  SwitchEditor = class extends AbstractElementWithParent {
547
579
  async getValue() {
548
580
  const result = await this.getAttribute("aria-label");
549
- if (result === "ON")
550
- return 1;
551
- if (result === "OFF")
552
- return 0;
581
+ if (result === "ON") return 1;
582
+ if (result === "OFF") return 0;
553
583
  return null;
554
584
  }
555
585
  async setValue(value) {
@@ -562,7 +592,7 @@ var init_SwitchEditor = __esm({
562
592
  return;
563
593
  }
564
594
  await click(inputEl, this.driver);
565
- await wait(async () => {
595
+ await safeWait(async () => {
566
596
  const updatedValue = await this.getValue();
567
597
  return updatedValue !== currentValue;
568
598
  }, this.driver);
@@ -583,6 +613,7 @@ var init_TagBox = __esm({
583
613
  init_SelectBoxEditor();
584
614
  init_ClearButtonStrategy();
585
615
  init_fixElementStaleError();
616
+ init_wait();
586
617
  TAGS_SELECTOR = ".dx-tag .tag-text";
587
618
  DX_TAG_CONTAINER = "dx-tag-container";
588
619
  DX_TEXTEDITOR_EMPTY2 = "dx-texteditor-empty";
@@ -603,7 +634,8 @@ var init_TagBox = __esm({
603
634
  await this.confirmSelection();
604
635
  }
605
636
  async waitOptionSelection() {
606
- await fixElementStaleError(import_selenium_webdriver10.By.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
637
+ const option = await fixElementStaleError(import_selenium_webdriver10.By.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
638
+ await safeWait(() => option.isDisplayed(), this.driver);
607
639
  }
608
640
  async selectOption(inputEl, value, lastElement) {
609
641
  try {
@@ -695,8 +727,7 @@ var init_ButtonGroup = __esm({
695
727
  break;
696
728
  }
697
729
  }
698
- if (!buttonEl)
699
- throw new Error(`Cannot find item in button group with text: ${value}`);
730
+ if (!buttonEl) throw new Error(`Cannot find item in button group with text: ${value}`);
700
731
  await click(buttonEl, this.driver);
701
732
  }
702
733
  };
@@ -756,33 +787,35 @@ var init_BaseDateEditor = __esm({
756
787
  super(parentCssSelector, elementCssSelector, driver);
757
788
  this.setClearStrategy(new InputClearStrategy());
758
789
  }
759
- async setDateValue(value) {
760
- const actions = this.driver.actions({ async: true });
790
+ async setArrayValue(value) {
761
791
  const dateField = await this.driver.findElement(import_selenium_webdriver12.By.css(`${this.getFullCssSelector()}`));
762
792
  const dateFieldDataTestID = await this.getDataTestId();
763
- const calendarPopoverSelector = byTestIdCssSelector(`${dateFieldDataTestID}-calendar-popover`);
764
- const dateInputEl = await this.getInputElement();
765
- await dateInputEl.clear();
793
+ const button = await dateField.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
794
+ await click(button, this.driver);
795
+ const calendarPopoverElement = await this.driver.findElement(import_selenium_webdriver12.By.css(byTestIdCssSelector(`${dateFieldDataTestID}-calendar-popover`)));
796
+ const dateFromInput = await calendarPopoverElement.findElement(
797
+ import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`)
798
+ );
799
+ const dateToInput = await calendarPopoverElement.findElement(
800
+ import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`)
801
+ );
802
+ await this.setSingleValue(value[0], dateFromInput);
803
+ await this.setSingleValue(value[1], dateToInput);
804
+ const btnOk = await this.driver.findElement(import_selenium_webdriver12.By.css(`.${BTN_SAVE_SELECTOR}`));
805
+ await click(btnOk, this.driver);
806
+ }
807
+ async setSingleValue(value, inputEl) {
808
+ const actions = this.driver.actions({ async: true });
809
+ const formattedDate = formatDMYDate(value);
810
+ await click(inputEl, this.driver);
811
+ await actions.move({ origin: inputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
812
+ await actions.move({ origin: inputEl }).sendKeys(formattedDate, import_selenium_webdriver12.Key.ENTER).perform();
813
+ }
814
+ async setDateValue(value) {
766
815
  if (Array.isArray(value)) {
767
- const formattedDates = value.map(formatDMYDate);
768
- const button = await dateField.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
769
- await button.click();
770
- const calendarPopoverElement = await this.driver.findElement(import_selenium_webdriver12.By.css(calendarPopoverSelector));
771
- const dateFromInput = await calendarPopoverElement.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`));
772
- const dateToInput = await calendarPopoverElement.findElement(import_selenium_webdriver12.By.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`));
773
- await dateFromInput.click();
774
- await dateFromInput.sendKeys(formattedDates[0]);
775
- await dateToInput.click();
776
- await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
777
- await dateToInput.sendKeys(formattedDates[1]);
778
- await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.ENTER).perform();
779
- const btnOk = await this.driver.findElement(import_selenium_webdriver12.By.css(`.${BTN_SAVE_SELECTOR}`));
780
- await btnOk.click();
816
+ await this.setArrayValue(value);
781
817
  } else {
782
- const formattedDate = formatDMYDate(value);
783
- await click(dateInputEl, this.driver);
784
- await actions.move({ origin: dateInputEl }).sendKeys(import_selenium_webdriver12.Key.HOME).perform();
785
- await actions.move({ origin: dateInputEl }).sendKeys(formattedDate, import_selenium_webdriver12.Key.ENTER).perform();
818
+ await this.setSingleValue(value, await this.getInputElement());
786
819
  }
787
820
  }
788
821
  };
@@ -873,15 +906,14 @@ var init_DateEditor = __esm({
873
906
  init_types();
874
907
  DateEditor = class extends AbstractDXEditorWithInput {
875
908
  editorInstance = null;
876
- initPromise;
877
- constructor(parentCssSelector, elementCssSelector, driver) {
878
- super(parentCssSelector, elementCssSelector, driver);
879
- this.initPromise = this.init(parentCssSelector, elementCssSelector, driver);
880
- }
881
- async init(parentCssSelector, elementCssSelector, driver) {
882
- await this.updateEditorInstance(parentCssSelector, elementCssSelector, driver);
909
+ async init() {
910
+ if (this.editorInstance) {
911
+ return this.editorInstance;
912
+ }
913
+ await this.setEditorInstance();
883
914
  }
884
- async updateEditorInstance(parentCssSelector, elementCssSelector, driver) {
915
+ async setEditorInstance() {
916
+ const { parentCssSelector, elementCssSelector, driver } = this;
885
917
  const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
886
918
  const classString = await elementInstance.getClasses();
887
919
  switch (true) {
@@ -895,25 +927,14 @@ var init_DateEditor = __esm({
895
927
  this.editorInstance = new SingleDateEditor(parentCssSelector, elementCssSelector, driver);
896
928
  }
897
929
  }
898
- async ensureInitialized() {
899
- if (!this.editorInstance) {
900
- await this.initPromise;
901
- }
902
- }
903
930
  async setValue(value) {
904
- await this.ensureInitialized();
905
- if (this.editorInstance) {
906
- await this.editorInstance.setValue(value);
907
- return await this.updateEditorInstance(this.parentCssSelector, this.elementCssSelector, this.driver);
908
- }
909
- throw new Error("Editor instance is not initialized.");
931
+ await this.init();
932
+ await this.editorInstance.setValue(value);
933
+ await this.setEditorInstance();
910
934
  }
911
935
  async getValue() {
912
- await this.ensureInitialized();
913
- if (this.editorInstance) {
914
- return this.editorInstance.getValue();
915
- }
916
- throw new Error("Editor instance is not initialized.");
936
+ await this.init();
937
+ return this.editorInstance.getValue();
917
938
  }
918
939
  };
919
940
  }
@@ -1043,16 +1064,12 @@ var init_editorFactory = __esm({
1043
1064
  const classSting = await elementInstance.getClasses();
1044
1065
  if ((classSting.includes("text-control" /* Text */) || classSting.includes("text-area-control" /* TextArea */)) && !classSting.includes("single-date-range-control" /* SingleDateRange */))
1045
1066
  return new TextEditor(parentCssSelector, elementCssSelector, driver);
1046
- if (classSting.includes("number-control" /* Number */))
1047
- return new NumberEditor(parentCssSelector, elementCssSelector, driver);
1048
- if (classSting.includes("check-box" /* CheckBox */))
1049
- return new CheckBox(parentCssSelector, elementCssSelector, driver);
1050
- if (classSting.includes("multi-select-control" /* Multiselect */))
1051
- return new TagBox(parentCssSelector, elementCssSelector, driver);
1067
+ if (classSting.includes("number-control" /* Number */)) return new NumberEditor(parentCssSelector, elementCssSelector, driver);
1068
+ if (classSting.includes("check-box" /* CheckBox */)) return new CheckBox(parentCssSelector, elementCssSelector, driver);
1069
+ if (classSting.includes("multi-select-control" /* Multiselect */)) return new TagBox(parentCssSelector, elementCssSelector, driver);
1052
1070
  if (classSting.includes("select-control" /* Select */))
1053
1071
  return new SelectBoxEditor(parentCssSelector, elementCssSelector, driver);
1054
- if (classSting.includes("switch-control" /* Switch */))
1055
- return new SwitchEditor(parentCssSelector, elementCssSelector, driver);
1072
+ if (classSting.includes("switch-control" /* Switch */)) return new SwitchEditor(parentCssSelector, elementCssSelector, driver);
1056
1073
  if (classSting.includes("date-control" /* Date */) || classSting.includes("single-date-range-control" /* SingleDateRange */)) {
1057
1074
  return new DateEditor(parentCssSelector, elementCssSelector, driver);
1058
1075
  }
@@ -1118,42 +1135,21 @@ var init_createDataTestId = __esm({
1118
1135
  }
1119
1136
  });
1120
1137
 
1121
- // src/utils/waitElementIsClickable.ts
1122
- async function waitElementIsClickable({
1123
- element,
1124
- timeout,
1125
- errorMessage,
1126
- driver
1127
- }) {
1128
- driver = driver ?? config().driver;
1129
- await wait(async () => {
1130
- const isDisabled = await element.getCssValue("pointer-events") === "none";
1131
- return await element.isDisplayed() && !isDisabled;
1132
- }, driver, errorMessage, timeout ?? config().timeout);
1133
- }
1134
- var init_waitElementIsClickable = __esm({
1135
- "src/utils/waitElementIsClickable.ts"() {
1136
- "use strict";
1137
- init_config();
1138
- init_wait();
1139
- }
1140
- });
1141
-
1142
- // src/pageObjects/elements/TableToolbar/AbstractButton.ts
1138
+ // src/pageObjects/elements/AbstractButton.ts
1143
1139
  var AbstractButton;
1144
1140
  var init_AbstractButton = __esm({
1145
- "src/pageObjects/elements/TableToolbar/AbstractButton.ts"() {
1141
+ "src/pageObjects/elements/AbstractButton.ts"() {
1146
1142
  "use strict";
1143
+ init_AbstractElementWithParent();
1147
1144
  init_actions();
1148
1145
  init_waitElementIsClickable();
1149
- init_AbstractElementWithParent();
1150
1146
  AbstractButton = class extends AbstractElementWithParent {
1151
1147
  constructor(parentCssSelector, elementCssSelector, driver) {
1152
1148
  super(parentCssSelector, elementCssSelector, driver);
1153
1149
  }
1154
1150
  async click() {
1155
1151
  const button = await this.getElement();
1156
- await waitElementIsClickable({
1152
+ await waitElementIsClickable_default({
1157
1153
  element: button,
1158
1154
  errorMessage: this.buttonNotDisplayedError(),
1159
1155
  driver: this.driver
@@ -1165,8 +1161,12 @@ var init_AbstractButton = __esm({
1165
1161
  return await button.getCssValue("pointer-events") === "none";
1166
1162
  }
1167
1163
  async isDisplayed() {
1168
- const button = await this.getElement();
1169
- return await button.isDisplayed();
1164
+ try {
1165
+ const button = await this.getElement();
1166
+ return await button.isDisplayed();
1167
+ } catch {
1168
+ return false;
1169
+ }
1170
1170
  }
1171
1171
  };
1172
1172
  }
@@ -1210,6 +1210,9 @@ var init_FormButton = __esm({
1210
1210
  buttonNotDisplayedError() {
1211
1211
  return `Form Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
1212
1212
  }
1213
+ async getTitle() {
1214
+ return await this.getText();
1215
+ }
1213
1216
  };
1214
1217
  }
1215
1218
  });
@@ -1353,16 +1356,11 @@ var init_groupFactory = __esm({
1353
1356
  groupFactory = async (parentCssSelector, elementCssSelector, driver) => {
1354
1357
  const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
1355
1358
  const classSting = await elementInstance.getClasses();
1356
- if (classSting.includes("tab-panel-group"))
1357
- return new TabPanel(parentCssSelector, elementCssSelector, driver);
1358
- if (classSting.includes("tab-panel-item"))
1359
- return new TabPanelItem(parentCssSelector, elementCssSelector, driver);
1360
- if (classSting.includes("panel-group"))
1361
- return new Panel(parentCssSelector, elementCssSelector, driver);
1362
- if (classSting.includes("accordion-group"))
1363
- return new Accordion(parentCssSelector, elementCssSelector, driver);
1364
- if (classSting.includes("d5-accordion-item"))
1365
- return new AccordionItem(parentCssSelector, elementCssSelector, driver);
1359
+ if (classSting.includes("tab-panel-group")) return new TabPanel(parentCssSelector, elementCssSelector, driver);
1360
+ if (classSting.includes("tab-panel-item")) return new TabPanelItem(parentCssSelector, elementCssSelector, driver);
1361
+ if (classSting.includes("panel-group")) return new Panel(parentCssSelector, elementCssSelector, driver);
1362
+ if (classSting.includes("accordion-group")) return new Accordion(parentCssSelector, elementCssSelector, driver);
1363
+ if (classSting.includes("d5-accordion-item")) return new AccordionItem(parentCssSelector, elementCssSelector, driver);
1366
1364
  throw new Error("Unknown type of group. Please write ticket to the support");
1367
1365
  };
1368
1366
  }
@@ -1561,7 +1559,7 @@ var init_Cell = __esm({
1561
1559
  Cell = class extends AbstractElementWithParent {
1562
1560
  _index;
1563
1561
  getCellIndex;
1564
- constructor(parentCssSelector, getCellIndex, index, driver) {
1562
+ constructor(parentCssSelector, getCellIndex, driver, index) {
1565
1563
  super(parentCssSelector, getCssCellByIndexSelector(index), driver);
1566
1564
  this.getCellIndex = getCellIndex;
1567
1565
  this._index = index;
@@ -1581,7 +1579,30 @@ var init_Cell = __esm({
1581
1579
  for (const tag of tags) {
1582
1580
  values.push(await tag.getAttribute("textContent"));
1583
1581
  }
1584
- return values;
1582
+ return values.length ? values : null;
1583
+ }
1584
+ async getNumberValue(cellEl) {
1585
+ const value = (await cellEl.getText()).trim();
1586
+ return value == "" ? null : Number.parseFloat(value);
1587
+ }
1588
+ async getDateValue(cellEl, cellElClass) {
1589
+ const value = (await cellEl.getText()).trim();
1590
+ if (value === "") return null;
1591
+ const isWithTime = cellElClass.includes("with-time");
1592
+ try {
1593
+ if (isWithTime) {
1594
+ const [datePart, timePart] = value.split(", ");
1595
+ const [day, month, year] = datePart.split(".").map(Number);
1596
+ const [hours, minutes] = timePart.split(":").map(Number);
1597
+ return new Date(Date.UTC(year, month - 1, day, hours, minutes));
1598
+ } else {
1599
+ const [day, month, year] = value.split(".").map(Number);
1600
+ return new Date(Date.UTC(year, month - 1, day));
1601
+ }
1602
+ } catch (error) {
1603
+ console.error(`Error parsing date value "${value}":`, error);
1604
+ return null;
1605
+ }
1585
1606
  }
1586
1607
  async getElement() {
1587
1608
  if (this._index == null) {
@@ -1592,11 +1613,12 @@ var init_Cell = __esm({
1592
1613
  async getValue() {
1593
1614
  const cellEl = await this.getElement();
1594
1615
  const cellElClass = await cellEl.getAttribute("class");
1595
- if (cellElClass.includes("boolean-column" /* Boolean */))
1596
- return this.getBooleanValue(cellEl);
1597
- if (cellElClass.includes("tags-column" /* Tags */))
1598
- return this.getTagsValue(cellEl);
1599
- return cellEl.getText();
1616
+ if (cellElClass.includes("boolean-column" /* Boolean */)) return this.getBooleanValue(cellEl);
1617
+ if (cellElClass.includes("tags-column" /* Tags */)) return this.getTagsValue(cellEl);
1618
+ if (cellElClass.includes("number-column" /* Number */)) return this.getNumberValue(cellEl);
1619
+ if (cellElClass.includes("date-column" /* Date */)) return this.getDateValue(cellEl, cellElClass);
1620
+ const cellText = await cellEl.getText();
1621
+ return cellText == "" ? null : cellText;
1600
1622
  }
1601
1623
  getIndex() {
1602
1624
  return this._index;
@@ -1624,6 +1646,13 @@ var init_Row = __esm({
1624
1646
  index;
1625
1647
  getColumnBy;
1626
1648
  fixedTableContentCssSelector;
1649
+ /**
1650
+ * @param parentCssSelector
1651
+ * @param fixedTableContentCssSelector
1652
+ * @param index починається з 0 (в getCssRowByIndexSelector додається +1)
1653
+ * @param driver
1654
+ * @param getColumnBy
1655
+ */
1627
1656
  constructor(parentCssSelector, fixedTableContentCssSelector, index, driver, getColumnBy) {
1628
1657
  super(parentCssSelector, getCssRowByIndexSelector(index), driver);
1629
1658
  this.index = index;
@@ -1636,8 +1665,8 @@ var init_Row = __esm({
1636
1665
  () => {
1637
1666
  return this.getColumnBy({ title, name }).getIndex();
1638
1667
  },
1639
- index,
1640
- this.driver
1668
+ this.driver,
1669
+ index
1641
1670
  );
1642
1671
  }
1643
1672
  getCellByIndex(index) {
@@ -1650,9 +1679,11 @@ var init_Row = __esm({
1650
1679
  return this._getCell({ title });
1651
1680
  }
1652
1681
  async select() {
1653
- const rowEl = await this.getElement();
1654
- await click(rowEl, this.driver);
1655
- await wait(
1682
+ await staleElementAction(async () => {
1683
+ const rowEl = await this.getElement();
1684
+ await click(rowEl, this.driver);
1685
+ });
1686
+ await safeWait(
1656
1687
  async () => {
1657
1688
  const classes = await this.getClasses();
1658
1689
  return classes.includes(DX_SELECTION_CLASS);
@@ -1681,14 +1712,14 @@ var init_Row = __esm({
1681
1712
  const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(
1682
1713
  this.index
1683
1714
  )}"] .${buttonClass}`;
1684
- const button = await fixElementStaleError(
1685
- import_selenium_webdriver22.By.css(`${this.parentCssSelector} ${this.fixedTableContentCssSelector} ${buttonCssSelector}`),
1686
- this.driver
1687
- );
1688
- return click(button, this.driver);
1715
+ const by = import_selenium_webdriver22.By.css(`${this.parentCssSelector} ${this.fixedTableContentCssSelector} ${buttonCssSelector}`);
1716
+ await staleElementAction(async () => {
1717
+ const button = await fixElementStaleError(by, this.driver);
1718
+ await click(button, this.driver);
1719
+ });
1689
1720
  }
1690
1721
  async checkEditingMode(isEditing, msg) {
1691
- await wait(
1722
+ await safeWait(
1692
1723
  async () => {
1693
1724
  return (await this.getClasses()).includes(DX_ROW_EDIT_CLASS) === isEditing;
1694
1725
  },
@@ -1797,7 +1828,7 @@ var init_EditorButton = __esm({
1797
1828
  }
1798
1829
  async click() {
1799
1830
  const button = await this.getElement();
1800
- await waitElementIsClickable({
1831
+ await waitElementIsClickable_default({
1801
1832
  element: button,
1802
1833
  errorMessage: this.buttonNotDisplayedError(),
1803
1834
  driver: this.driver
@@ -1888,6 +1919,21 @@ var init_AbstractEditor2 = __esm({
1888
1919
  await this.initEditor();
1889
1920
  return this.editor.isReadonly();
1890
1921
  }
1922
+ /**
1923
+ * Возвращает значение true|false в зависимости isDisplayed поле или нет
1924
+ * @example
1925
+ * expect(await formEdit.field('NumberFld').isDisplayed()).toBe(true);
1926
+ * expect(await formEdit.field('TextFld').isDisplayed()).toBe(false);
1927
+ */
1928
+ async isDisplayed() {
1929
+ try {
1930
+ await this.initEditor();
1931
+ const element = await this.getElement();
1932
+ return await element.isDisplayed();
1933
+ } catch {
1934
+ return false;
1935
+ }
1936
+ }
1891
1937
  /**
1892
1938
  * Находит кнопку на поле по имени
1893
1939
  * @example
@@ -1918,26 +1964,207 @@ var init_FormField = __esm({
1918
1964
  }
1919
1965
  });
1920
1966
 
1967
+ // src/utils/typesUtil.ts
1968
+ var import_util, types, type, isArray, isString;
1969
+ var init_typesUtil = __esm({
1970
+ "src/utils/typesUtil.ts"() {
1971
+ "use strict";
1972
+ import_util = require("selenium-webdriver/lib/util");
1973
+ types = {
1974
+ "[object Array]": "array",
1975
+ "[object Date]": "date",
1976
+ "[object Object]": "object",
1977
+ "[object String]": "string",
1978
+ "[object Null]": "null"
1979
+ };
1980
+ type = function(object) {
1981
+ const typeOfObject = Object.prototype.toString.call(object);
1982
+ return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
1983
+ };
1984
+ isArray = function(value) {
1985
+ return type(value) === "array";
1986
+ };
1987
+ isString = function(object) {
1988
+ return typeof object === "string";
1989
+ };
1990
+ }
1991
+ });
1992
+
1993
+ // src/pageObjects/elements/AbstractDropDownMenuList.ts
1994
+ var AbstractDropDownMenuList;
1995
+ var init_AbstractDropDownMenuList = __esm({
1996
+ "src/pageObjects/elements/AbstractDropDownMenuList.ts"() {
1997
+ "use strict";
1998
+ init_AbstractElementWithParent();
1999
+ init_actions();
2000
+ init_waitElementIsClickable();
2001
+ init_fixElementStaleError();
2002
+ init_typesUtil();
2003
+ AbstractDropDownMenuList = class extends AbstractElementWithParent {
2004
+ buttonNotDisplayedError(name) {
2005
+ return `Menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
2006
+ }
2007
+ async clickItemBy(errorMessage, by) {
2008
+ await waitElementIsClickable_default({
2009
+ errorMessage,
2010
+ driver: this.driver,
2011
+ by
2012
+ });
2013
+ const menuItemElement = await fixElementStaleError(by, this.driver);
2014
+ await click(menuItemElement, this.driver);
2015
+ }
2016
+ async getElementByPath(path, getBy, returnLastElement = false) {
2017
+ let pathList = isString(path) ? [path] : path;
2018
+ let result = null;
2019
+ let index = 1;
2020
+ for (let text of pathList) {
2021
+ if (!returnLastElement || index < pathList.length) {
2022
+ await this.clickItemBy(this.buttonNotDisplayedError(text), getBy(text));
2023
+ } else {
2024
+ result = await fixElementStaleError(getBy(text), this.driver);
2025
+ }
2026
+ index++;
2027
+ }
2028
+ return result;
2029
+ }
2030
+ async clickButton(name) {
2031
+ await this.getElementByPath(name, this.getButtonNameBy.bind(this));
2032
+ }
2033
+ async clickButtonByTitle(title) {
2034
+ await this.getElementByPath(title, this.getButtonTitleBy.bind(this));
2035
+ }
2036
+ getMenuItemElementByTitle(title) {
2037
+ return this.getElementByPath(title, this.getButtonTitleBy.bind(this), true);
2038
+ }
2039
+ getMenuItemElementByName(name) {
2040
+ return this.getElementByPath(name, this.getButtonNameBy.bind(this), true);
2041
+ }
2042
+ isVisible() {
2043
+ return Promise.resolve(true);
2044
+ }
2045
+ };
2046
+ }
2047
+ });
2048
+
2049
+ // src/utils/cssToXPath.ts
2050
+ function cssClassesToXPath(classNames) {
2051
+ const classNamesList = classNames.split(".").filter((className) => !!className);
2052
+ const chained = classNamesList.map((className) => `contains(@class, "${className}")`).join(" and ");
2053
+ return `[${chained}]`;
2054
+ }
2055
+ var init_cssToXPath = __esm({
2056
+ "src/utils/cssToXPath.ts"() {
2057
+ "use strict";
2058
+ }
2059
+ });
2060
+
2061
+ // src/pageObjects/elements/DXContextMenuList.ts
2062
+ var import_selenium_webdriver24, CONTEXT_MENU_CLASS, CONTEXT_MENU_ITEM_TEXT_CLASS, DXContextMenuList;
2063
+ var init_DXContextMenuList = __esm({
2064
+ "src/pageObjects/elements/DXContextMenuList.ts"() {
2065
+ "use strict";
2066
+ init_AbstractDropDownMenuList();
2067
+ import_selenium_webdriver24 = require("selenium-webdriver");
2068
+ init_cssToXPath();
2069
+ init_waitElementIsVisible();
2070
+ CONTEXT_MENU_CLASS = "dx-context-menu";
2071
+ CONTEXT_MENU_ITEM_TEXT_CLASS = "dx-menu-item-text";
2072
+ DXContextMenuList = class extends AbstractDropDownMenuList {
2073
+ /**
2074
+ * @param parentCssSelector
2075
+ * @param classNames - Список класів. Починається з крапки
2076
+ * @param driver
2077
+ */
2078
+ constructor(parentCssSelector, classNames, driver) {
2079
+ super(parentCssSelector, `.${CONTEXT_MENU_CLASS}${classNames}`, driver);
2080
+ }
2081
+ getButtonTitleBy(title) {
2082
+ const buttonByTextXpath2 = (text) => `//span[contains(@class, "${CONTEXT_MENU_ITEM_TEXT_CLASS}") and contains(text(), "${text}")]`;
2083
+ const xpath = "//div" + cssClassesToXPath(this.elementCssSelector) + buttonByTextXpath2(title);
2084
+ return import_selenium_webdriver24.By.xpath(xpath);
2085
+ }
2086
+ async isVisible() {
2087
+ try {
2088
+ await waitElementIsVisible_default({
2089
+ element: await this.driver.findElement(import_selenium_webdriver24.By.css(`.dx-overlay-wrapper .dx-contextmenu`)),
2090
+ driver: this.driver,
2091
+ errorMessage: "Cannot find dropdown element"
2092
+ });
2093
+ } catch {
2094
+ return false;
2095
+ }
2096
+ }
2097
+ };
2098
+ }
2099
+ });
2100
+
2101
+ // src/pageObjects/elements/Table/elements/ContextMenu.ts
2102
+ var ContextMenu;
2103
+ var init_ContextMenu = __esm({
2104
+ "src/pageObjects/elements/Table/elements/ContextMenu.ts"() {
2105
+ "use strict";
2106
+ init_DXContextMenuList();
2107
+ init_locators();
2108
+ ContextMenu = class extends DXContextMenuList {
2109
+ _formName;
2110
+ _initFn;
2111
+ constructor(cssClass, formName, driver) {
2112
+ super("", cssClass, driver);
2113
+ this._formName = formName;
2114
+ }
2115
+ setInit(cb) {
2116
+ this._initFn = cb;
2117
+ return this;
2118
+ }
2119
+ getButtonNameBy(name) {
2120
+ return byTestId(`cm-${this._formName}-${name}`);
2121
+ }
2122
+ async clickButtonByTitle(title) {
2123
+ await this._initFn?.();
2124
+ await super.clickButtonByTitle(title);
2125
+ }
2126
+ async clickButton(name) {
2127
+ await this._initFn?.();
2128
+ await super.clickButton(name);
2129
+ }
2130
+ };
2131
+ }
2132
+ });
2133
+
1921
2134
  // src/pageObjects/elements/Table/Table.ts
1922
- var import_selenium_webdriver24, Table;
2135
+ var import_selenium_webdriver25, Table;
1923
2136
  var init_Table = __esm({
1924
2137
  "src/pageObjects/elements/Table/Table.ts"() {
1925
2138
  "use strict";
1926
- import_selenium_webdriver24 = require("selenium-webdriver");
2139
+ import_selenium_webdriver25 = require("selenium-webdriver");
1927
2140
  init_createDataTestId();
1928
2141
  init_AbstractElementWithParent();
1929
2142
  init_Row();
1930
2143
  init_Column();
1931
2144
  init_FormField();
2145
+ init_ContextMenu();
2146
+ init_actions();
1932
2147
  Table = class extends AbstractElementWithParent {
1933
2148
  formName;
1934
2149
  headerCssSelector;
2150
+ contextMenuCssSelector;
1935
2151
  fixedTableContentCssSelector;
1936
- constructor(parentCssSelector, headerCssSelector, fixedTableContentCssSelector, formName, driver) {
2152
+ tableContentCssSelector;
2153
+ constructor({
2154
+ parentCssSelector,
2155
+ contextMenuCssSelector,
2156
+ tableContentCssSelector,
2157
+ headerCssSelector,
2158
+ fixedTableContentCssSelector,
2159
+ formName,
2160
+ driver
2161
+ }) {
1937
2162
  super(parentCssSelector, `#${createTableId(formName)}`, driver);
1938
2163
  this.formName = formName;
1939
2164
  this.headerCssSelector = headerCssSelector;
2165
+ this.contextMenuCssSelector = contextMenuCssSelector;
1940
2166
  this.fixedTableContentCssSelector = fixedTableContentCssSelector;
2167
+ this.tableContentCssSelector = tableContentCssSelector;
1941
2168
  }
1942
2169
  getColumnBy = (args) => {
1943
2170
  if (args.title) {
@@ -1945,10 +2172,18 @@ var init_Table = __esm({
1945
2172
  }
1946
2173
  return this.getColumnByName(args.name);
1947
2174
  };
2175
+ /**
2176
+ * Отримати рядок по індексу.
2177
+ * @param index починається з 0
2178
+ */
1948
2179
  getRowByIndex(index) {
1949
2180
  return new Row(this.getFullCssSelector(), this.fixedTableContentCssSelector, index, this.driver, this.getColumnBy);
1950
2181
  }
2182
+ /**
2183
+ * @param index починається з 0
2184
+ */
1951
2185
  getColumnByIndex(index) {
2186
+ this.getRowByIndex(index);
1952
2187
  return new Column({
1953
2188
  parentCssSelector: this.getFullCssSelector(),
1954
2189
  driver: this.driver,
@@ -1971,11 +2206,16 @@ var init_Table = __esm({
1971
2206
  driver: this.driver
1972
2207
  });
1973
2208
  };
2209
+ /**
2210
+ * Вибрати рядок по індексу.
2211
+ * @param index починається з 0
2212
+ */
1974
2213
  selectRowByIndex(index) {
1975
2214
  return this.getRowByIndex(index).select();
1976
2215
  }
1977
2216
  async getRows() {
1978
- const rows = await this.driver.findElements(import_selenium_webdriver24.By.css(`${this.getFullCssSelector()} .dx-row.dx-data-row`));
2217
+ const rowsFullCssSelector = `${this.getFullCssSelector()} ${this.tableContentCssSelector} .dx-row.dx-data-row`;
2218
+ const rows = await this.driver.findElements(import_selenium_webdriver25.By.css(rowsFullCssSelector));
1979
2219
  const result = [];
1980
2220
  rows.forEach((_, index) => {
1981
2221
  const newRow = new Row(
@@ -1991,7 +2231,7 @@ var init_Table = __esm({
1991
2231
  }
1992
2232
  async getColumns() {
1993
2233
  const columns = await this.driver.findElements(
1994
- import_selenium_webdriver24.By.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"]`)
2234
+ import_selenium_webdriver25.By.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"] .header-template-text`)
1995
2235
  );
1996
2236
  const result = [];
1997
2237
  columns.forEach((_, index) => {
@@ -2017,132 +2257,265 @@ var init_Table = __esm({
2017
2257
  field(name) {
2018
2258
  return new FormField(this.getFullCssSelector(), this.formName, name, this.driver);
2019
2259
  }
2260
+ /**
2261
+ * Возвращает список строк которые выделены
2262
+ * @returns Row[]
2263
+ * @example
2264
+ * const form = new MyForm();
2265
+ * //...
2266
+ * await form.getSelectedRows();
2267
+ */
2268
+ async getSelectedRows() {
2269
+ const rows = await this.getRows();
2270
+ let result = [];
2271
+ for (const row of rows) {
2272
+ if (await row.isSelected()) {
2273
+ }
2274
+ result.push(row);
2275
+ }
2276
+ return result;
2277
+ }
2278
+ /**
2279
+ * Вызывает контекстное меню в области с данными.
2280
+ * @param fieldName - имя поля
2281
+ * @param [rowIndex] - индекс строки. Если значение не передано, то по умолчанию контекстное меню будет вызвано на первой выделенной строке.
2282
+ * @throws {Error} Если нет выделенных строк, то выбросит исключение.
2283
+ * @example
2284
+ * const form = new MyForm();
2285
+ * //...
2286
+ * await form.contextMenu('FieldName').clickButton('OpenFormButton');
2287
+ * // or
2288
+ * await form.contextMenu('FieldName', 3).clickButton(['Group', 'ButtonInGroup']);
2289
+ */
2290
+ contextMenu(fieldName, rowIndex) {
2291
+ return new ContextMenu(this.contextMenuCssSelector, this.formName, this.driver).setInit(async () => {
2292
+ let row;
2293
+ if (rowIndex != null) {
2294
+ row = this.getRowByIndex(rowIndex);
2295
+ } else {
2296
+ [row] = await this.getSelectedRows();
2297
+ }
2298
+ if (!row)
2299
+ throw new Error("No row available row for context menu");
2300
+ const cellElement = await row.getCell(fieldName).getElement();
2301
+ await contextMenu(cellElement, this.driver);
2302
+ });
2303
+ }
2020
2304
  };
2021
2305
  }
2022
2306
  });
2023
2307
 
2024
- // src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
2025
- var ToolbarGroupButton;
2026
- var init_ToolbarGroupButton = __esm({
2027
- "src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts"() {
2308
+ // src/pageObjects/elements/TableToolbar/ToolbarButton.ts
2309
+ var import_selenium_webdriver26, TOOLBAR_BUTTON_CLASS, TOOLBAR_BUTTON_TEXT_CLASS, getToolbarButtonSelector, getToolbarButtonTextSelector, ToolbarButton;
2310
+ var init_ToolbarButton = __esm({
2311
+ "src/pageObjects/elements/TableToolbar/ToolbarButton.ts"() {
2028
2312
  "use strict";
2313
+ import_selenium_webdriver26 = require("selenium-webdriver");
2029
2314
  init_AbstractButton();
2030
- ToolbarGroupButton = class extends AbstractButton {
2315
+ TOOLBAR_BUTTON_CLASS = "toolbar-button";
2316
+ TOOLBAR_BUTTON_TEXT_CLASS = "dx-button-text";
2317
+ getToolbarButtonSelector = (name) => `#${TOOLBAR_BUTTON_CLASS}-${name}`;
2318
+ getToolbarButtonTextSelector = (name) => `${getToolbarButtonSelector(name)} .${TOOLBAR_BUTTON_TEXT_CLASS}`;
2319
+ ToolbarButton = class extends AbstractButton {
2031
2320
  name;
2032
2321
  constructor(parentCssSelector, name, driver) {
2033
- super(parentCssSelector, ``, driver);
2322
+ super(parentCssSelector, getToolbarButtonSelector(name), driver);
2034
2323
  this.name = name;
2035
2324
  }
2036
2325
  buttonNotDisplayedError() {
2037
2326
  return `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
2038
2327
  }
2328
+ async getTitle() {
2329
+ try {
2330
+ const buttonTextContainer = await this.driver.findElement(import_selenium_webdriver26.By.css(getToolbarButtonTextSelector(this.name)));
2331
+ return await buttonTextContainer.getText();
2332
+ } catch (_) {
2333
+ return null;
2334
+ }
2335
+ }
2039
2336
  };
2040
2337
  }
2041
2338
  });
2042
2339
 
2043
- // src/pageObjects/elements/TableToolbar/ToolbarButton.ts
2044
- var TOOLBAR_BUTTON_CLASS, ToolbarButton;
2045
- var init_ToolbarButton = __esm({
2046
- "src/pageObjects/elements/TableToolbar/ToolbarButton.ts"() {
2340
+ // src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
2341
+ var import_selenium_webdriver27, ToolbarGroupButton;
2342
+ var init_ToolbarGroupButton = __esm({
2343
+ "src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts"() {
2047
2344
  "use strict";
2048
2345
  init_AbstractButton();
2049
- TOOLBAR_BUTTON_CLASS = "toolbar-button";
2050
- ToolbarButton = class extends AbstractButton {
2346
+ import_selenium_webdriver27 = require("selenium-webdriver");
2347
+ init_ToolbarButton();
2348
+ ToolbarGroupButton = class extends AbstractButton {
2051
2349
  name;
2052
2350
  constructor(parentCssSelector, name, driver) {
2053
- super(parentCssSelector, `#${TOOLBAR_BUTTON_CLASS}-${name}`, driver);
2351
+ super(parentCssSelector, ``, driver);
2054
2352
  this.name = name;
2055
2353
  }
2056
2354
  buttonNotDisplayedError() {
2057
2355
  return `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
2058
2356
  }
2357
+ async getTitle() {
2358
+ try {
2359
+ const buttonTextContainer = await this.driver.findElement(import_selenium_webdriver27.By.css(getToolbarButtonTextSelector(this.name)));
2360
+ return await buttonTextContainer.getText();
2361
+ } catch (_) {
2362
+ return null;
2363
+ }
2364
+ }
2059
2365
  };
2060
2366
  }
2061
2367
  });
2062
2368
 
2063
- // src/utils/typesUtil.ts
2064
- var types, type, isArray, isString;
2065
- var init_typesUtil = __esm({
2066
- "src/utils/typesUtil.ts"() {
2369
+ // src/pageObjects/elements/AbstractDropDownMenuButton.ts
2370
+ var AbstractDropDownMenuButton;
2371
+ var init_AbstractDropDownMenuButton = __esm({
2372
+ "src/pageObjects/elements/AbstractDropDownMenuButton.ts"() {
2067
2373
  "use strict";
2068
- types = {
2069
- "[object Array]": "array",
2070
- "[object Date]": "date",
2071
- "[object Object]": "object",
2072
- "[object String]": "string",
2073
- "[object Null]": "null"
2074
- };
2075
- type = function(object) {
2076
- const typeOfObject = Object.prototype.toString.call(object);
2077
- return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
2078
- };
2079
- isArray = function(value) {
2080
- return type(value) === "array";
2374
+ init_AbstractElementWithParent();
2375
+ init_actions();
2376
+ AbstractDropDownMenuButton = class extends AbstractElementWithParent {
2377
+ _list;
2378
+ constructor(parentCssSelector, elementCssSelector, list, driver) {
2379
+ super(parentCssSelector, elementCssSelector, driver);
2380
+ this._list = list;
2381
+ }
2382
+ async openDropdownMenu() {
2383
+ const dropdown = await this.getElement();
2384
+ await click(dropdown, this.driver);
2385
+ await this._list.isVisible();
2386
+ }
2387
+ async clickButton(name) {
2388
+ await this.openDropdownMenu();
2389
+ await this._list.clickButton(name);
2390
+ }
2391
+ async clickButtonByTitle(title) {
2392
+ await this.openDropdownMenu();
2393
+ await this._list.clickButtonByTitle(title);
2394
+ }
2395
+ async getMenuItemElementByTitle(title) {
2396
+ await this.openDropdownMenu();
2397
+ return await this._list.getMenuItemElementByTitle(title);
2398
+ }
2399
+ async getMenuItemElementByName(name) {
2400
+ await this.openDropdownMenu();
2401
+ return await this._list.getMenuItemElementByName(name);
2402
+ }
2081
2403
  };
2082
- isString = function(object) {
2083
- return typeof object === "string";
2404
+ }
2405
+ });
2406
+
2407
+ // src/pageObjects/elements/TableToolbar/ToolbarMenuItem.ts
2408
+ var ToolbarMenuItem;
2409
+ var init_ToolbarMenuItem = __esm({
2410
+ "src/pageObjects/elements/TableToolbar/ToolbarMenuItem.ts"() {
2411
+ "use strict";
2412
+ ToolbarMenuItem = class {
2413
+ getMenuItem;
2414
+ name;
2415
+ constructor(getMenuItem, name) {
2416
+ this.getMenuItem = getMenuItem;
2417
+ this.name = name;
2418
+ }
2419
+ async click() {
2420
+ const menuItemElement = await this.getMenuItem(this.name);
2421
+ await menuItemElement.click();
2422
+ }
2423
+ async getTitle() {
2424
+ try {
2425
+ const menuItemElement = await this.getMenuItem(this.name);
2426
+ return await menuItemElement.getText();
2427
+ } catch (_) {
2428
+ return null;
2429
+ }
2430
+ }
2431
+ async isDisabled() {
2432
+ const menuItemElement = await this.getMenuItem(this.name);
2433
+ return await menuItemElement.getCssValue("pointer-events") === "none";
2434
+ }
2435
+ async isDisplayed() {
2436
+ try {
2437
+ const menuItemElement = await this.getMenuItem(this.name);
2438
+ return await menuItemElement.isDisplayed();
2439
+ } catch (_) {
2440
+ return false;
2441
+ }
2442
+ }
2084
2443
  };
2085
2444
  }
2086
2445
  });
2087
2446
 
2088
2447
  // src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
2089
- var import_selenium_webdriver25, SPINDOWN_CLASS, buttonGroupItemSelector, getFullCssSelector, buttonByTextXpath, ToolbarMenu;
2448
+ var SPINDOWN_CLASS, buttonGroupItemSelector, getFullCssSelector, ToolbarMenuList, ToolbarMenu;
2090
2449
  var init_ToolbarMenu = __esm({
2091
2450
  "src/pageObjects/elements/TableToolbar/ToolbarMenu.ts"() {
2092
2451
  "use strict";
2093
- import_selenium_webdriver25 = require("selenium-webdriver");
2094
2452
  init_typesUtil();
2095
- init_AbstractElementWithParent();
2096
2453
  init_locators();
2097
- init_actions();
2098
- init_waitElementIsClickable();
2099
- init_fixElementStaleError();
2454
+ init_AbstractDropDownMenuButton();
2455
+ init_DXContextMenuList();
2456
+ init_ToolbarMenuItem();
2100
2457
  SPINDOWN_CLASS = ".dx-icon-spindown";
2101
2458
  buttonGroupItemSelector = (formName, name) => byTestIdCssSelector(`ftb-${formName}-${name}`);
2102
2459
  getFullCssSelector = (formName, name) => `${buttonGroupItemSelector(formName, name)} ${SPINDOWN_CLASS}`;
2103
- buttonByTextXpath = (text) => `.//span[contains(@class, "dx-menu-item-text") and contains(text(), "${text}")]`;
2104
- ToolbarMenu = class extends AbstractElementWithParent {
2460
+ ToolbarMenuList = class extends DXContextMenuList {
2105
2461
  _formName;
2106
- constructor(parentCssSelector, formName, name, driver) {
2107
- super(parentCssSelector, getFullCssSelector(formName, name), driver);
2462
+ constructor(parentCssSelector, elementCssSelector, formName, driver) {
2463
+ super(parentCssSelector, elementCssSelector, driver);
2108
2464
  this._formName = formName;
2109
2465
  }
2110
- async openDropdownMenu() {
2111
- const dropdown = await this.getElement();
2112
- await click(dropdown, this.driver);
2113
- }
2114
- getCssSelectorToButton(name) {
2466
+ getButtonNameBy(name) {
2115
2467
  return byTestId(`ftb-${this._formName}-${name}`);
2116
2468
  }
2117
- buttonNotDisplayedError(name) {
2118
- return `Toolbar menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
2119
- }
2120
- async goToButton(name, by) {
2121
- const toolbarMenuItem = await fixElementStaleError(by, this.driver);
2122
- await waitElementIsClickable({
2123
- element: toolbarMenuItem,
2124
- errorMessage: this.buttonNotDisplayedError(name),
2125
- driver: this.driver
2126
- });
2127
- await click(toolbarMenuItem, this.driver);
2469
+ };
2470
+ ToolbarMenu = class extends AbstractDropDownMenuButton {
2471
+ constructor(parentCssSelector, formName, name, driver) {
2472
+ const fullSelector = getFullCssSelector(formName, name);
2473
+ const list = new ToolbarMenuList(parentCssSelector, ".toolbar-dropdown-context-menu", formName, driver);
2474
+ super(parentCssSelector, fullSelector, list, driver);
2128
2475
  }
2129
- async clickButton(name) {
2130
- await this.openDropdownMenu();
2476
+ checkNameValue(name) {
2131
2477
  if (!isString(name) && !isArray(name))
2132
2478
  throw new Error(`"name" must be a string or array of string`);
2133
- let lName = isString(name) ? [name] : name;
2134
- for (let n of lName) {
2135
- await this.goToButton(n, this.getCssSelectorToButton(n));
2136
- }
2137
2479
  }
2138
- async clickButtonByTitle(title) {
2139
- await this.openDropdownMenu();
2480
+ checkTitleValue(title) {
2140
2481
  if (!isString(title) && !isArray(title))
2141
2482
  throw new Error(`"title" must be a string or array of string`);
2142
- let lTitle = isString(title) ? [title] : title;
2143
- for (let t of lTitle) {
2144
- await this.goToButton(t, import_selenium_webdriver25.By.xpath(buttonByTextXpath(t)));
2145
- }
2483
+ }
2484
+ buttonByName(name) {
2485
+ this.checkNameValue(name);
2486
+ return new ToolbarMenuItem(this.getMenuItemElementByName.bind(this), name);
2487
+ }
2488
+ buttonByTitle(title) {
2489
+ this.checkTitleValue(title);
2490
+ return new ToolbarMenuItem(this.getMenuItemElementByTitle.bind(this), title);
2491
+ }
2492
+ async buttonIsDisplayed(name) {
2493
+ const button = this.buttonByName(name);
2494
+ return await button.isDisplayed();
2495
+ }
2496
+ async buttonByTitleIsDisplayed(title) {
2497
+ const button = this.buttonByTitle(title);
2498
+ return await button.isDisplayed();
2499
+ }
2500
+ async buttonTitle(name) {
2501
+ const button = this.buttonByName(name);
2502
+ return await button.getTitle();
2503
+ }
2504
+ async buttonIsDisabled(name) {
2505
+ const button = this.buttonByName(name);
2506
+ return await button.isDisabled();
2507
+ }
2508
+ async buttonByTitleIsDisabled(title) {
2509
+ const button = this.buttonByTitle(title);
2510
+ return await button.isDisabled();
2511
+ }
2512
+ async clickButton(name) {
2513
+ const button = this.buttonByName(name);
2514
+ await button.click();
2515
+ }
2516
+ async clickButtonByTitle(title) {
2517
+ const button = this.buttonByTitle(title);
2518
+ await button.click();
2146
2519
  }
2147
2520
  };
2148
2521
  }
@@ -2170,8 +2543,7 @@ var init_ToolbarItem = __esm({
2170
2543
  this._formName = formName;
2171
2544
  }
2172
2545
  async init() {
2173
- if (this._button)
2174
- return this._button;
2546
+ if (this._button) return this._button;
2175
2547
  const classNames = await this.getClasses();
2176
2548
  if (classNames.includes(GROUP_BUTTON_CLASS)) {
2177
2549
  this._button = new ToolbarGroupButton(this.getFullCssSelector(), this._itemName, this.driver);
@@ -2195,6 +2567,10 @@ var init_ToolbarItem = __esm({
2195
2567
  return false;
2196
2568
  }
2197
2569
  }
2570
+ async getTitle() {
2571
+ await this.init();
2572
+ return await this._button.getTitle();
2573
+ }
2198
2574
  get menu() {
2199
2575
  return new ToolbarMenu(this.parentCssSelector, this._formName, this._itemName, this.driver);
2200
2576
  }
@@ -2224,11 +2600,11 @@ var init_FormToolbar = __esm({
2224
2600
  });
2225
2601
 
2226
2602
  // src/pageObjects/elements/Filters/FilterOperation.ts
2227
- var import_selenium_webdriver26, FILTER_OPERATIONS, BUTTON_OPERATION_WIDGET, OPERATIONS_WIDGET_POPUP, getWidgetInPopupSelector, FilterOperation;
2603
+ var import_selenium_webdriver28, FILTER_OPERATIONS, BUTTON_OPERATION_WIDGET, OPERATIONS_WIDGET_POPUP, getWidgetInPopupSelector, FilterOperation;
2228
2604
  var init_FilterOperation = __esm({
2229
2605
  "src/pageObjects/elements/Filters/FilterOperation.ts"() {
2230
2606
  "use strict";
2231
- import_selenium_webdriver26 = require("selenium-webdriver");
2607
+ import_selenium_webdriver28 = require("selenium-webdriver");
2232
2608
  init_fixElementStaleError();
2233
2609
  init_AbstractElementWithParent();
2234
2610
  init_locators();
@@ -2263,16 +2639,16 @@ var init_FilterOperation = __esm({
2263
2639
  }
2264
2640
  async initOperationWidget() {
2265
2641
  const widgetButtonEl = await this.getElement();
2266
- await waitElementIsClickable({
2642
+ await waitElementIsClickable_default({
2267
2643
  element: widgetButtonEl,
2268
2644
  errorMessage: "Widget operation is not clickable",
2269
2645
  driver: this.driver
2270
2646
  });
2271
- const clickableElement = await widgetButtonEl.findElement(import_selenium_webdriver26.By.className("dx-icon"));
2647
+ const clickableElement = await widgetButtonEl.findElement(import_selenium_webdriver28.By.className("dx-icon"));
2272
2648
  await click(clickableElement, this.driver);
2273
2649
  try {
2274
- const widgetPopupEl = await this.driver.findElement(import_selenium_webdriver26.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
2275
- await waitElementIsVisible({
2650
+ const widgetPopupEl = await this.driver.findElement(import_selenium_webdriver28.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)}`));
2651
+ await waitElementIsVisible_default({
2276
2652
  element: widgetPopupEl,
2277
2653
  errorMessage: `Operation widget popup is not visible`,
2278
2654
  driver: this.driver
@@ -2286,13 +2662,12 @@ var init_FilterOperation = __esm({
2286
2662
  throw new Error(`Operation with name "${operationName}" is not correct.`);
2287
2663
  }
2288
2664
  await this.initOperationWidget();
2289
- const operationEl = await fixElementStaleError(import_selenium_webdriver26.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
2665
+ const operationEl = await fixElementStaleError(import_selenium_webdriver28.By.css(`${byTestIdCssSelector(`${OPERATIONS_WIDGET_POPUP}-${this._testId}`)} ${getWidgetInPopupSelector(operationName)}`), this.driver);
2290
2666
  await click(operationEl, this.driver);
2291
- await wait(
2667
+ await safeWait(
2292
2668
  async () => {
2293
2669
  const currOperationName = await this.getAttribute("data-operation");
2294
- if (operationName === "isblank")
2295
- return true;
2670
+ if (operationName === "isblank") return true;
2296
2671
  return currOperationName === operationName;
2297
2672
  },
2298
2673
  this.driver,
@@ -2301,15 +2676,14 @@ var init_FilterOperation = __esm({
2301
2676
  }
2302
2677
  async getOperation() {
2303
2678
  const result = await this.getAttribute("data-operation");
2304
- if (!result)
2305
- throw new Error("Operation not found");
2679
+ if (!result) throw new Error("Operation not found");
2306
2680
  return result;
2307
2681
  }
2308
2682
  async setIsBlank(value) {
2309
2683
  const currValue = await this.getIsBlank();
2310
2684
  if (currValue !== value) {
2311
2685
  await this.setOperation("isblank");
2312
- await wait(
2686
+ await safeWait(
2313
2687
  async () => {
2314
2688
  const currIsBlank = await this.getIsBlank();
2315
2689
  return currIsBlank === value;
@@ -2391,7 +2765,8 @@ var init_FormFilterField = __esm({
2391
2765
  async initOperation() {
2392
2766
  return new FilterOperation({
2393
2767
  parentCssSelector: this.parentCssSelector,
2394
- filterTestID: createLayoutFilterTestId(this.formName, this.name)
2768
+ filterTestID: createLayoutFilterTestId(this.formName, this.name),
2769
+ driver: this.driver
2395
2770
  });
2396
2771
  }
2397
2772
  /**
@@ -2498,7 +2873,8 @@ var init_PanelFilterField = __esm({
2498
2873
  async initOperation() {
2499
2874
  return new FilterOperation({
2500
2875
  parentCssSelector: this.parentCssSelector,
2501
- filterTestID: createDocFilterTestId(this.formName, this.name)
2876
+ filterTestID: createDocFilterTestId(this.formName, this.name),
2877
+ driver: this.driver
2502
2878
  });
2503
2879
  }
2504
2880
  /**
@@ -2542,11 +2918,11 @@ var init_PanelFilterField = __esm({
2542
2918
  });
2543
2919
 
2544
2920
  // src/pageObjects/elements/Filters/FilterPanel.ts
2545
- var import_selenium_webdriver27, drawerSelector, FILTER_PANEL_SELECTOR, CLOSE_SELECTOR, FilterPanel;
2921
+ var import_selenium_webdriver29, drawerSelector, FILTER_PANEL_SELECTOR, CLOSE_SELECTOR, FilterPanel;
2546
2922
  var init_FilterPanel = __esm({
2547
2923
  "src/pageObjects/elements/Filters/FilterPanel.ts"() {
2548
2924
  "use strict";
2549
- import_selenium_webdriver27 = require("selenium-webdriver");
2925
+ import_selenium_webdriver29 = require("selenium-webdriver");
2550
2926
  init_AbstractElement();
2551
2927
  init_PanelFilterField();
2552
2928
  init_actions();
@@ -2561,7 +2937,7 @@ var init_FilterPanel = __esm({
2561
2937
  async filterPanelButtons() {
2562
2938
  const selector = `${this.elementCssSelector} ${FILTER_PANEL_SELECTOR} .filter-panel__buttons-panel .dx-button-text`;
2563
2939
  const el = await this.getElement();
2564
- return el.findElements(import_selenium_webdriver27.By.css(selector));
2940
+ return el.findElements(import_selenium_webdriver29.By.css(selector));
2565
2941
  }
2566
2942
  constructor(formName, driver) {
2567
2943
  super(driver, drawerSelector(formName));
@@ -2594,7 +2970,7 @@ var init_FilterPanel = __esm({
2594
2970
  await this.driver.sleep(300);
2595
2971
  }
2596
2972
  async close() {
2597
- const btn = await this.driver.findElement(import_selenium_webdriver27.By.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
2973
+ const btn = await this.driver.findElement(import_selenium_webdriver29.By.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
2598
2974
  await click(btn, this.driver);
2599
2975
  }
2600
2976
  };
@@ -2630,12 +3006,12 @@ var init_HeaderFilterField = __esm({
2630
3006
  });
2631
3007
 
2632
3008
  // src/pageObjects/elements/Filters/ColumnFilter.ts
2633
- var import_selenium_webdriver28, APPLY_SELECTOR, CANCEL_SELECTOR, HEADER_FILTER_ICON, HEADER_FILTER_CONTAINER, HEADER_FILTER_BUTTONS, ColumnFilter;
3009
+ var import_selenium_webdriver30, APPLY_SELECTOR, CANCEL_SELECTOR, HEADER_FILTER_ICON, HEADER_FILTER_CONTAINER, HEADER_FILTER_BUTTONS, ColumnFilter;
2634
3010
  var init_ColumnFilter = __esm({
2635
3011
  "src/pageObjects/elements/Filters/ColumnFilter.ts"() {
2636
3012
  "use strict";
2637
3013
  init_actions();
2638
- import_selenium_webdriver28 = require("selenium-webdriver");
3014
+ import_selenium_webdriver30 = require("selenium-webdriver");
2639
3015
  init_HeaderFilterField();
2640
3016
  init_waitElementIsVisible();
2641
3017
  init_AbstractElement();
@@ -2660,11 +3036,11 @@ var init_ColumnFilter = __esm({
2660
3036
  }
2661
3037
  async getApplyButton() {
2662
3038
  const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${APPLY_SELECTOR}`;
2663
- return this.driver.findElement(import_selenium_webdriver28.By.css(selector));
3039
+ return this.driver.findElement(import_selenium_webdriver30.By.css(selector));
2664
3040
  }
2665
3041
  async getCancelButton() {
2666
3042
  const selector = `${HEADER_FILTER_CONTAINER} ${HEADER_FILTER_BUTTONS} ${CANCEL_SELECTOR}`;
2667
- return this.driver.findElement(import_selenium_webdriver28.By.css(selector));
3043
+ return this.driver.findElement(import_selenium_webdriver30.By.css(selector));
2668
3044
  }
2669
3045
  async apply() {
2670
3046
  const btn = await this.getApplyButton();
@@ -2678,9 +3054,9 @@ var init_ColumnFilter = __esm({
2678
3054
  const columnEl = await this._column.getElement();
2679
3055
  const actions = this.driver.actions({ async: true });
2680
3056
  await actions.move({ origin: columnEl }).perform();
2681
- const elements = await columnEl.findElements(import_selenium_webdriver28.By.css(HEADER_FILTER_ICON));
3057
+ const elements = await columnEl.findElements(import_selenium_webdriver30.By.css(HEADER_FILTER_ICON));
2682
3058
  let headerFilterIcon = null;
2683
- await wait(
3059
+ await safeWait(
2684
3060
  async () => {
2685
3061
  let result = false;
2686
3062
  for (let element of elements) {
@@ -2695,12 +3071,11 @@ var init_ColumnFilter = __esm({
2695
3071
  this.driver,
2696
3072
  `HeaderFilter "${this._name}" is not visible`
2697
3073
  );
2698
- if (!headerFilterIcon)
2699
- throw new Error(`HeaderFilter "${this._name}" is not visible`);
2700
- await headerFilterIcon.click();
3074
+ if (!headerFilterIcon) throw new Error(`HeaderFilter "${this._name}" is not visible`);
3075
+ await click(headerFilterIcon, this.driver);
2701
3076
  const filter = new HeaderFilterField("", this._formName, this._name, this.driver);
2702
3077
  const filterEl = await filter.getElement();
2703
- await waitElementIsVisible({
3078
+ await waitElementIsVisible_default({
2704
3079
  element: filterEl,
2705
3080
  driver: this.driver,
2706
3081
  errorMessage: `Header filter is not visible`
@@ -2728,16 +3103,18 @@ var init_ColumnFilter = __esm({
2728
3103
  */
2729
3104
  async setValue(value, operation, isBlank) {
2730
3105
  const filter = await this.initFilter();
2731
- const inputEl = await filter.getElement();
2732
- await inputEl.click();
2733
3106
  const filterOperation = new FilterOperation({
2734
3107
  parentCssSelector: HEADER_FILTER_CONTAINER,
2735
- filterTestID: createHeaderFilterTestId(this._formName, this._name)
3108
+ filterTestID: createHeaderFilterTestId(this._formName, this._name),
3109
+ driver: this.driver
2736
3110
  });
3111
+ const inputEl = await filter.getElement();
2737
3112
  if (typeof operation === "string") {
3113
+ await inputEl.click();
2738
3114
  await filterOperation.setOperation(operation);
2739
3115
  }
2740
3116
  if (typeof isBlank === "boolean") {
3117
+ await inputEl.click();
2741
3118
  await filterOperation.setIsBlank(isBlank);
2742
3119
  }
2743
3120
  await filter.setValue(value);
@@ -2772,7 +3149,8 @@ var init_ColumnFilter = __esm({
2772
3149
  await inputEl.click();
2773
3150
  return new FilterOperation({
2774
3151
  parentCssSelector: HEADER_FILTER_CONTAINER,
2775
- filterTestID: createHeaderFilterTestId(this._formName, this._name)
3152
+ filterTestID: createHeaderFilterTestId(this._formName, this._name),
3153
+ driver: this.driver
2776
3154
  });
2777
3155
  }
2778
3156
  /**
@@ -2822,7 +3200,7 @@ var ListForm_exports = {};
2822
3200
  __export(ListForm_exports, {
2823
3201
  default: () => ListForm
2824
3202
  });
2825
- var DATAGRID_HEADER_CSS_SELECTOR, FIXED_DATAGRID_CONTENT_CSS_SELECTOR, ListForm;
3203
+ var DATAGRID_HEADER_CSS_SELECTOR, DATAGRID_CONTENT_CSS_SELECTOR, FIXED_DATAGRID_CONTENT_CSS_SELECTOR, CONTEXT_MENU_CSS_SELECTOR, ListForm;
2826
3204
  var init_ListForm = __esm({
2827
3205
  "src/pageObjects/elements/Forms/ListForm.ts"() {
2828
3206
  "use strict";
@@ -2833,15 +3211,21 @@ var init_ListForm = __esm({
2833
3211
  init_FilterPanel();
2834
3212
  init_ColumnFilter();
2835
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)";
2836
3215
  FIXED_DATAGRID_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
3216
+ CONTEXT_MENU_CSS_SELECTOR = ".dx-datagrid";
2837
3217
  ListForm = class extends Form {
2838
3218
  headerCssSelector;
2839
3219
  fixedTableContentCssSelector;
3220
+ tableContentCssSelector;
3221
+ contextMenuCssSelector;
2840
3222
  constructor(driver) {
2841
3223
  super(driver);
2842
3224
  this.popupContainerCssSelector = `.popup.form-inline-${this.formName}`;
2843
3225
  this.headerCssSelector = DATAGRID_HEADER_CSS_SELECTOR;
2844
3226
  this.fixedTableContentCssSelector = FIXED_DATAGRID_CONTENT_CSS_SELECTOR;
3227
+ this.tableContentCssSelector = DATAGRID_CONTENT_CSS_SELECTOR;
3228
+ this.contextMenuCssSelector = CONTEXT_MENU_CSS_SELECTOR;
2845
3229
  }
2846
3230
  /**
2847
3231
  * Находит таблицу
@@ -2852,11 +3236,15 @@ var init_ListForm = __esm({
2852
3236
  */
2853
3237
  table() {
2854
3238
  return new Table(
2855
- this.containerCssSelector,
2856
- this.headerCssSelector,
2857
- this.fixedTableContentCssSelector,
2858
- this.formName,
2859
- this.driver
3239
+ {
3240
+ parentCssSelector: this.containerCssSelector,
3241
+ headerCssSelector: this.headerCssSelector,
3242
+ fixedTableContentCssSelector: this.fixedTableContentCssSelector,
3243
+ formName: this.formName,
3244
+ driver: this.driver,
3245
+ contextMenuCssSelector: this.contextMenuCssSelector,
3246
+ tableContentCssSelector: this.tableContentCssSelector
3247
+ }
2860
3248
  );
2861
3249
  }
2862
3250
  /**
@@ -2904,27 +3292,34 @@ var TreeView_exports = {};
2904
3292
  __export(TreeView_exports, {
2905
3293
  default: () => TreeView
2906
3294
  });
2907
- var TREELIST_HEADER_CSS_SELECTOR, FIXED_TREELIST_CONTENT_CSS_SELECTOR, TreeView;
3295
+ var TREELIST_HEADER_CSS_SELECTOR, TREELIST_CONTENT_CSS_SELECTOR, FIXED_TREELIST_CONTENT_CSS_SELECTOR, TreeView;
2908
3296
  var init_TreeView = __esm({
2909
3297
  "src/pageObjects/elements/Forms/TreeView.ts"() {
2910
3298
  "use strict";
2911
3299
  init_ListForm();
2912
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)";
2913
3302
  FIXED_TREELIST_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-treelist-content.dx-treelist-content-fixed";
2914
3303
  TreeView = class extends ListForm {
2915
3304
  constructor(driver) {
2916
3305
  super(driver);
2917
- this.popupContainerCssSelector = `.popup.wrapper-tree-view-${this.formName}`;
3306
+ this.popupContainerCssSelector = `.popup.tree-view-${this.formName}`;
2918
3307
  this.headerCssSelector = TREELIST_HEADER_CSS_SELECTOR;
2919
3308
  this.fixedTableContentCssSelector = FIXED_TREELIST_CONTENT_CSS_SELECTOR;
3309
+ this.contextMenuCssSelector = ".dx-treelist-container";
3310
+ this.tableContentCssSelector = TREELIST_CONTENT_CSS_SELECTOR;
2920
3311
  }
2921
3312
  };
2922
3313
  }
2923
3314
  });
2924
3315
 
2925
3316
  // src/pageObjects/elements/Forms/createSubFormInstance.ts
2926
- function subformCssSelector(parentCssSelector, testId) {
2927
- return `${parentCssSelector} ${byTestIdCssSelector(testId)}`;
3317
+ function subformCssSelector(parentCssSelector, testId, isDockPanel = false) {
3318
+ if (isDockPanel) {
3319
+ return `${SECONDARY_DRAWER_LAYOUT_CONTENT} ${byTestIdCssSelector(testId)}`;
3320
+ } else {
3321
+ return `${parentCssSelector} ${byTestIdCssSelector(testId)}`;
3322
+ }
2928
3323
  }
2929
3324
  async function classDependencyInjector(formType) {
2930
3325
  let SubFormFactoryClass;
@@ -2945,23 +3340,24 @@ async function classDependencyInjector(formType) {
2945
3340
  }
2946
3341
  return SubFormFactoryClass;
2947
3342
  }
2948
- var subFormTestId;
3343
+ var SECONDARY_DRAWER_LAYOUT_CONTENT, subFormTestId;
2949
3344
  var init_createSubFormInstance = __esm({
2950
3345
  "src/pageObjects/elements/Forms/createSubFormInstance.ts"() {
2951
3346
  "use strict";
2952
3347
  init_locators();
2953
3348
  init_types2();
3349
+ SECONDARY_DRAWER_LAYOUT_CONTENT = ".secondary-drawer-layout-content";
2954
3350
  subFormTestId = (name) => `subform-${name}`;
2955
3351
  }
2956
3352
  });
2957
3353
 
2958
3354
  // src/pageObjects/elements/Forms/Form.ts
2959
- var import_selenium_webdriver29, formTestId, Form;
3355
+ var import_selenium_webdriver31, formTestId, Form;
2960
3356
  var init_Form = __esm({
2961
3357
  "src/pageObjects/elements/Forms/Form.ts"() {
2962
3358
  "use strict";
2963
3359
  init_locators();
2964
- import_selenium_webdriver29 = require("selenium-webdriver");
3360
+ import_selenium_webdriver31 = require("selenium-webdriver");
2965
3361
  init_AbstractForm();
2966
3362
  init_waitElementIsVisible();
2967
3363
  init_createSubFormInstance();
@@ -2986,10 +3382,15 @@ var init_Form = __esm({
2986
3382
  */
2987
3383
  async getTitleText() {
2988
3384
  if (await this.isModal()) {
2989
- const titleEl2 = await this.driver.findElement(import_selenium_webdriver29.By.css(`${this.popupContainerCssSelector} .popup-title`));
3385
+ const titleEl2 = await this.driver.findElement(import_selenium_webdriver31.By.css(`${this.popupContainerCssSelector} .popup-title`));
3386
+ await waitElementIsVisible_default({
3387
+ element: titleEl2,
3388
+ driver: this.driver,
3389
+ errorMessage: `Form title element is not visible`
3390
+ });
2990
3391
  return titleEl2.getText();
2991
3392
  }
2992
- let titleEl = await this.driver.findElement(import_selenium_webdriver29.By.className("main-toolbar-form-title"));
3393
+ let titleEl = await this.driver.findElement(import_selenium_webdriver31.By.className("main-toolbar-form-title"));
2993
3394
  return titleEl.getText();
2994
3395
  }
2995
3396
  setSubFormMode() {
@@ -3005,11 +3406,12 @@ var init_Form = __esm({
3005
3406
  * //...
3006
3407
  * expect(await form.subForm(name));
3007
3408
  */
3008
- async subForm(name) {
3009
- const cssSelector = subformCssSelector(this.containerCssSelector, subFormTestId(name));
3010
- const byCssSelector = import_selenium_webdriver29.By.css(cssSelector);
3409
+ async subForm(name, options = {}) {
3410
+ const { isDockPanel = false } = options;
3411
+ const cssSelector = subformCssSelector(this.containerCssSelector, subFormTestId(name), isDockPanel);
3412
+ const byCssSelector = import_selenium_webdriver31.By.css(cssSelector);
3011
3413
  const subFormEl = await this.driver.findElement(byCssSelector);
3012
- await waitElementIsVisible({
3414
+ await waitElementIsVisible_default({
3013
3415
  element: subFormEl,
3014
3416
  driver: this.driver,
3015
3417
  errorMessage: `Subform "${name}" is not visible`
@@ -3037,12 +3439,12 @@ var FormEdit_exports = {};
3037
3439
  __export(FormEdit_exports, {
3038
3440
  default: () => FormEdit
3039
3441
  });
3040
- var import_selenium_webdriver30, FormEdit;
3442
+ var import_selenium_webdriver32, FormEdit;
3041
3443
  var init_FormEdit = __esm({
3042
3444
  "src/pageObjects/elements/Forms/FormEdit.ts"() {
3043
3445
  "use strict";
3044
3446
  init_Form();
3045
- import_selenium_webdriver30 = require("selenium-webdriver");
3447
+ import_selenium_webdriver32 = require("selenium-webdriver");
3046
3448
  init_FormField();
3047
3449
  init_actions();
3048
3450
  init_wait();
@@ -3078,7 +3480,7 @@ var init_FormEdit = __esm({
3078
3480
  */
3079
3481
  async isSaveButtonDisabled() {
3080
3482
  const saveButtonCssSelector = await this.getButtonCssSelector(this.saveButtonId);
3081
- const saveButton = await this.driver.findElement(import_selenium_webdriver30.By.css(saveButtonCssSelector));
3483
+ const saveButton = await this.driver.findElement(import_selenium_webdriver32.By.css(saveButtonCssSelector));
3082
3484
  const result = await saveButton.getAttribute("aria-disabled");
3083
3485
  return result === "true";
3084
3486
  }
@@ -3091,8 +3493,8 @@ var init_FormEdit = __esm({
3091
3493
  */
3092
3494
  async saveButtonClick() {
3093
3495
  const saveButtonCssSelector = await this.getButtonCssSelector(this.saveButtonId);
3094
- const saveButton = await this.driver.findElement(import_selenium_webdriver30.By.css(saveButtonCssSelector));
3095
- await wait(async () => !await this.isSaveButtonDisabled(), this.driver, "Button is disabled");
3496
+ const saveButton = await this.driver.findElement(import_selenium_webdriver32.By.css(saveButtonCssSelector));
3497
+ await safeWait(async () => !await this.isSaveButtonDisabled(), this.driver, "Button is disabled");
3096
3498
  await click(saveButton, this.driver);
3097
3499
  }
3098
3500
  /**
@@ -3104,7 +3506,7 @@ var init_FormEdit = __esm({
3104
3506
  */
3105
3507
  async closeButtonClick() {
3106
3508
  const closeButtonCssSelector = await this.getButtonCssSelector(this.closeButtonId);
3107
- const closeButton = await this.driver.findElement(import_selenium_webdriver30.By.css(closeButtonCssSelector));
3509
+ const closeButton = await this.driver.findElement(import_selenium_webdriver32.By.css(closeButtonCssSelector));
3108
3510
  await click(closeButton, this.driver);
3109
3511
  }
3110
3512
  };
@@ -3133,13 +3535,15 @@ __export(src_exports, {
3133
3535
  byTestIdCssSelector: () => byTestIdCssSelector,
3134
3536
  click: () => click,
3135
3537
  config: () => config,
3538
+ contextMenu: () => contextMenu,
3136
3539
  createDriver: () => createDriver,
3137
3540
  editorFactory: () => editorFactory,
3138
3541
  elementIsNotPresent: () => elementIsNotPresent,
3139
3542
  readonlyLocator: () => readonlyLocator,
3140
3543
  signIn: () => signIn,
3141
- wait: () => wait,
3142
- waitElementIsVisible: () => waitElementIsVisible
3544
+ wait: () => safeWait,
3545
+ waitElementIsClickable: () => waitElementIsClickable_default,
3546
+ waitElementIsVisible: () => waitElementIsVisible_default
3143
3547
  });
3144
3548
  module.exports = __toCommonJS(src_exports);
3145
3549
  init_config();
@@ -3150,6 +3554,7 @@ init_config();
3150
3554
  init_waitElementIsVisible();
3151
3555
  init_actions();
3152
3556
  init_locators();
3557
+ var import_selenium_webdriver3 = require("selenium-webdriver");
3153
3558
  var LOGIN_PATH = "/login";
3154
3559
  var LoginPage = class extends AbstractPage {
3155
3560
  usernameField = byTestId("loginField", "input");
@@ -3158,7 +3563,7 @@ var LoginPage = class extends AbstractPage {
3158
3563
  async locate() {
3159
3564
  await super.locate();
3160
3565
  const login = await this.driver.findElement(this.usernameField);
3161
- await waitElementIsVisible({
3566
+ await waitElementIsVisible_default({
3162
3567
  element: login,
3163
3568
  driver: this.driver
3164
3569
  });
@@ -3174,6 +3579,11 @@ var LoginPage = class extends AbstractPage {
3174
3579
  }
3175
3580
  async clickLoginButton() {
3176
3581
  await click(await this.driver.findElement(this.loginButton), this.driver);
3582
+ await waitElementIsVisible_default({
3583
+ driver: this.driver,
3584
+ by: import_selenium_webdriver3.By.id("section"),
3585
+ errorMessage: "Sing in not successful"
3586
+ });
3177
3587
  }
3178
3588
  async loginWith(username, password) {
3179
3589
  await this.enterUsername(username);
@@ -3191,8 +3601,38 @@ init_locators();
3191
3601
  // src/utils/createDriver.ts
3192
3602
  var import_selenium_webdriver4 = require("selenium-webdriver");
3193
3603
  init_config();
3604
+ var import_chrome = __toESM(require("selenium-webdriver/chrome"));
3605
+ var import_firefox = __toESM(require("selenium-webdriver/firefox"));
3606
+ function chromeOptions(builder, options) {
3607
+ const ChromeOptions = new import_chrome.default.Options();
3608
+ if (options.headless) {
3609
+ ChromeOptions.addArguments(`--headless=new`);
3610
+ }
3611
+ return builder.setChromeOptions(ChromeOptions);
3612
+ }
3613
+ function firefoxOptions(builder, options) {
3614
+ const FirefoxOptions = new import_firefox.default.Options();
3615
+ if (options.headless) {
3616
+ FirefoxOptions.addArguments(`--headless`);
3617
+ }
3618
+ return builder.setFirefoxOptions(FirefoxOptions);
3619
+ }
3620
+ function setOptions(builder, browser, options) {
3621
+ switch (browser) {
3622
+ case "chrome":
3623
+ return chromeOptions(builder, options);
3624
+ case "firefox":
3625
+ return firefoxOptions(builder, options);
3626
+ default:
3627
+ return builder;
3628
+ }
3629
+ }
3194
3630
  var createDriver = async (browser) => {
3195
- const driver = await new import_selenium_webdriver4.Builder().forBrowser(browser ?? config().browser).build();
3631
+ const _browser = browser ?? config().browser;
3632
+ const headless = config().headless === "true";
3633
+ let builder = new import_selenium_webdriver4.Builder().forBrowser(_browser);
3634
+ builder = setOptions(builder, _browser, { headless });
3635
+ const driver = await builder.build();
3196
3636
  const manage = driver.manage();
3197
3637
  await manage.setTimeouts({ implicit: config().timeout });
3198
3638
  await manage.window().maximize();
@@ -3210,13 +3650,12 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
3210
3650
 
3211
3651
  // src/index.ts
3212
3652
  init_waitElementIsVisible();
3653
+ init_waitElementIsClickable();
3213
3654
  init_wait();
3214
3655
 
3215
3656
  // src/utils/signIn.ts
3216
- init_config();
3217
3657
  async function signIn(driver) {
3218
3658
  const webDriver = driver ?? await createDriver();
3219
- config().driver = webDriver;
3220
3659
  const loginPage = new LoginPage(webDriver);
3221
3660
  await loginPage.locate();
3222
3661
  await loginPage.authorize();
@@ -3248,6 +3687,8 @@ init_Editors();
3248
3687
  // src/pageObjects/elements/SubsystemsPanel/SubsystemItem.ts
3249
3688
  init_actions();
3250
3689
  init_fixElementStaleError();
3690
+ init_waitElementIsVisible();
3691
+ init_waitElementIsClickable();
3251
3692
  var SubsystemItem = class {
3252
3693
  bySelector;
3253
3694
  driver;
@@ -3259,10 +3700,22 @@ var SubsystemItem = class {
3259
3700
  return fixElementStaleError(this.bySelector, this.driver);
3260
3701
  }
3261
3702
  async getTitle() {
3703
+ await waitElementIsVisible_default(
3704
+ {
3705
+ by: this.bySelector,
3706
+ driver: this.driver
3707
+ }
3708
+ );
3262
3709
  const el = await this.getElement();
3263
3710
  return await el.getAttribute("data-title");
3264
3711
  }
3265
3712
  async click() {
3713
+ await waitElementIsClickable_default(
3714
+ {
3715
+ by: this.bySelector,
3716
+ driver: this.driver
3717
+ }
3718
+ );
3266
3719
  const el = await this.getElement();
3267
3720
  await click(el, this.driver);
3268
3721
  }
@@ -3273,6 +3726,7 @@ init_createDataTestId();
3273
3726
  init_actions();
3274
3727
  init_ClearButtonStrategy();
3275
3728
  init_waitElementIsVisible();
3729
+ init_fixElementStaleError();
3276
3730
  var SEARCH_ITEM_SELECTOR = "search-item";
3277
3731
  var BACK_BUTTON_SELECTOR = "subsystem-back-item";
3278
3732
  var SEARCH_INPUT_SELECTOR = "search-subsystem-input";
@@ -3287,11 +3741,11 @@ var SubsystemsPanel = class extends AbstractElement {
3287
3741
  }
3288
3742
  async headerTitle() {
3289
3743
  const title = await this.header.title();
3290
- await wait(async () => await title.getText() != "", this.driver);
3744
+ await safeWait(async () => await title.getText() != "", this.driver);
3291
3745
  return title.getText();
3292
3746
  }
3293
3747
  getSearchComponent() {
3294
- return new TextEditor("#aside", byTestIdCssSelector(SEARCH_INPUT_SELECTOR));
3748
+ return new TextEditor("#aside", byTestIdCssSelector(SEARCH_INPUT_SELECTOR), this.driver);
3295
3749
  }
3296
3750
  /**
3297
3751
  * Находит сабсистему по заголовку
@@ -3302,8 +3756,9 @@ var SubsystemsPanel = class extends AbstractElement {
3302
3756
  */
3303
3757
  async search(title) {
3304
3758
  const searchComponent = this.getSearchComponent();
3759
+ await this.searchClear();
3305
3760
  await searchComponent.setValue(title);
3306
- await wait(
3761
+ await safeWait(
3307
3762
  async () => {
3308
3763
  const findElement = await this.itemByTitle(title).getElement();
3309
3764
  const classes = await findElement.getAttribute("class");
@@ -3322,7 +3777,7 @@ var SubsystemsPanel = class extends AbstractElement {
3322
3777
  */
3323
3778
  async searchClear() {
3324
3779
  const clearBtnSelector = `#aside ${byTestIdCssSelector(SEARCH_INPUT_SELECTOR)} .${DX_CLEAR_BUTTON_AREA}`;
3325
- const clearBtn = await this.driver.findElement(import_selenium_webdriver16.By.css(clearBtnSelector));
3780
+ const clearBtn = await fixElementStaleError(import_selenium_webdriver16.By.css(clearBtnSelector), this.driver);
3326
3781
  if (await clearBtn.isDisplayed()) {
3327
3782
  await click(clearBtn, this.driver);
3328
3783
  }
@@ -3356,14 +3811,14 @@ var SubsystemsPanel = class extends AbstractElement {
3356
3811
  * wait subsystemsPanel.back();
3357
3812
  */
3358
3813
  async back() {
3359
- const backButton = this.driver.findElement(import_selenium_webdriver16.By.css(`#aside .${BACK_BUTTON_SELECTOR}`));
3360
- await waitElementIsVisible(
3814
+ const by = import_selenium_webdriver16.By.css(`#aside .${BACK_BUTTON_SELECTOR}`);
3815
+ await waitElementIsVisible_default(
3361
3816
  {
3362
- element: backButton,
3817
+ by,
3363
3818
  driver: this.driver
3364
3819
  }
3365
3820
  );
3366
- await click(backButton, this.driver);
3821
+ await click(await fixElementStaleError(by, this.driver), this.driver);
3367
3822
  }
3368
3823
  };
3369
3824
 
@@ -3401,13 +3856,13 @@ init_FilterPanel();
3401
3856
 
3402
3857
  // src/pageObjects/elements/Dialog.ts
3403
3858
  init_AbstractElement();
3404
- var import_selenium_webdriver31 = require("selenium-webdriver");
3859
+ var import_selenium_webdriver33 = require("selenium-webdriver");
3405
3860
  init_AbstractButton();
3406
3861
  var DIALOG_CLASS = ".d5-dialog";
3407
3862
  var DIALOG_TITLE_CLASS = ".dialog__title";
3408
3863
  var DIALOG_TEXT_CLASS = ".dialog__text";
3409
3864
  var DIALOG_BUTTONS_PANEL_CLASS = ".dialog__buttons-panel";
3410
- var buttonByTextXpath2 = (text) => `.//span[contains(@class, "dx-button-text") and contains(text(), "${text}")]`;
3865
+ var buttonByTextXpath = (text) => `.//span[contains(@class, "dx-button-text") and contains(text(), "${text}")]`;
3411
3866
  var DialogButton = class extends AbstractButton {
3412
3867
  text;
3413
3868
  constructor(parentCssSelector, text, driver) {
@@ -3416,11 +3871,14 @@ var DialogButton = class extends AbstractButton {
3416
3871
  }
3417
3872
  async getElement() {
3418
3873
  const panel = await super.getElement();
3419
- return panel.findElement(import_selenium_webdriver31.By.xpath(buttonByTextXpath2(this.text)));
3874
+ return panel.findElement(import_selenium_webdriver33.By.xpath(buttonByTextXpath(this.text)));
3420
3875
  }
3421
3876
  buttonNotDisplayedError() {
3422
3877
  return `Dialog button ${this.text} cannot be clicked. It is not displayed or it is disabled`;
3423
3878
  }
3879
+ getTitle() {
3880
+ throw new Error(`Method "getTitle()" is not working.`);
3881
+ }
3424
3882
  };
3425
3883
  var Dialog = class extends AbstractElement {
3426
3884
  constructor(driver) {
@@ -3436,11 +3894,11 @@ var Dialog = class extends AbstractElement {
3436
3894
  return this.joinRelativeCssSelectors([DIALOG_CLASS, DIALOG_BUTTONS_PANEL_CLASS]);
3437
3895
  }
3438
3896
  async title() {
3439
- const el = await this.driver.findElement(import_selenium_webdriver31.By.css(this.titleSelector));
3897
+ const el = await this.driver.findElement(import_selenium_webdriver33.By.css(this.titleSelector));
3440
3898
  return await el.getText();
3441
3899
  }
3442
3900
  async text() {
3443
- const el = await this.driver.findElement(import_selenium_webdriver31.By.css(this.textSelector));
3901
+ const el = await this.driver.findElement(import_selenium_webdriver33.By.css(this.textSelector));
3444
3902
  return await el.getText();
3445
3903
  }
3446
3904
  button(text) {
@@ -3468,11 +3926,13 @@ var Dialog = class extends AbstractElement {
3468
3926
  byTestIdCssSelector,
3469
3927
  click,
3470
3928
  config,
3929
+ contextMenu,
3471
3930
  createDriver,
3472
3931
  editorFactory,
3473
3932
  elementIsNotPresent,
3474
3933
  readonlyLocator,
3475
3934
  signIn,
3476
3935
  wait,
3936
+ waitElementIsClickable,
3477
3937
  waitElementIsVisible
3478
3938
  });