d5-testing-library 1.0.4 → 1.0.5

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.
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -29,6 +39,7 @@ __export(src_exports, {
29
39
  SubsystemsPanel: () => SubsystemsPanel,
30
40
  TextEditor: () => TextEditor,
31
41
  byTestId: () => byTestId,
42
+ click: () => click,
32
43
  config: () => config,
33
44
  createDriver: () => createDriver,
34
45
  editorFactory: () => editorFactory,
@@ -38,6 +49,25 @@ __export(src_exports, {
38
49
  module.exports = __toCommonJS(src_exports);
39
50
 
40
51
  // src/config.ts
52
+ var process = __toESM(require("process"));
53
+ var driversMap = /* @__PURE__ */ new Map();
54
+ var createConfigProxy = (config2) => {
55
+ return new Proxy(config2, {
56
+ get(_target, prop) {
57
+ if (prop === "driver") {
58
+ return driversMap.get(process.pid);
59
+ }
60
+ return Reflect.get(...arguments);
61
+ },
62
+ set(_target, prop, value) {
63
+ if (prop === "driver") {
64
+ driversMap.set(process.pid, value);
65
+ return true;
66
+ }
67
+ return Reflect.set(...arguments);
68
+ }
69
+ });
70
+ };
41
71
  var Config = class _Config {
42
72
  static instance;
43
73
  appConfig;
@@ -49,7 +79,7 @@ var Config = class _Config {
49
79
  }
50
80
  config = (cfg) => {
51
81
  if (!cfg)
52
- return this.appConfig;
82
+ return createConfigProxy(this.appConfig);
53
83
  this.appConfig = cfg;
54
84
  };
55
85
  };
@@ -120,6 +150,9 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
120
150
  });
121
151
  };
122
152
 
153
+ // src/utils/waitElementIsVisible.ts
154
+ var import_selenium_webdriver4 = require("selenium-webdriver");
155
+
123
156
  // src/pageObjects/AbstractElementWithParent.ts
124
157
  var AbstractElementWithParent = class extends AbstractElement {
125
158
  getParentElement;
@@ -144,9 +177,9 @@ var SubsystemsPanelHeader = class extends AbstractElementWithParent {
144
177
  };
145
178
 
146
179
  // src/pageObjects/elements/SubsystemsPanel/SubsystemsPanel.ts
147
- var import_selenium_webdriver4 = require("selenium-webdriver");
180
+ var import_selenium_webdriver5 = require("selenium-webdriver");
148
181
  var SubsystemsPanel = class extends AbstractElement {
149
- panelBy = import_selenium_webdriver4.By.id("aside");
182
+ panelBy = import_selenium_webdriver5.By.id("aside");
150
183
  header;
151
184
  constructor(driver) {
152
185
  super(driver);
@@ -161,7 +194,7 @@ var SubsystemsPanel = class extends AbstractElement {
161
194
  };
162
195
 
163
196
  // src/pageObjects/elements/Forms/AbstractForm.ts
164
- var import_selenium_webdriver5 = require("selenium-webdriver");
197
+ var import_selenium_webdriver6 = require("selenium-webdriver");
165
198
  var AbstractForm = class extends AbstractPage {
166
199
  containerBy;
167
200
  popupContainerBy;
@@ -206,20 +239,20 @@ var AbstractForm = class extends AbstractPage {
206
239
  async getTitleText() {
207
240
  if (await this.isModal()) {
208
241
  const popupEl = await this.driver.findElement(this.popupContainerBy);
209
- const titleEl2 = await popupEl.findElement(import_selenium_webdriver5.By.className("popup-title"));
242
+ const titleEl2 = await popupEl.findElement(import_selenium_webdriver6.By.className("popup-title"));
210
243
  return titleEl2.getText();
211
244
  }
212
245
  let container = await this.getContainerElement();
213
- let titleEl = await container.findElement(import_selenium_webdriver5.By.className("form-toolbar-name-container"));
246
+ let titleEl = await container.findElement(import_selenium_webdriver6.By.className("form-toolbar-name-container"));
214
247
  return titleEl.getText();
215
248
  }
216
249
  };
217
250
 
218
251
  // src/pageObjects/elements/Forms/FormEdit.ts
219
- var import_selenium_webdriver8 = require("selenium-webdriver");
252
+ var import_selenium_webdriver9 = require("selenium-webdriver");
220
253
 
221
254
  // src/pageObjects/elements/Editors/AbstractEditor.ts
222
- var import_selenium_webdriver6 = require("selenium-webdriver");
255
+ var import_selenium_webdriver7 = require("selenium-webdriver");
223
256
 
224
257
  // src/pageObjects/AbstractFormElement.ts
225
258
  var AbstractFormElement = class extends AbstractElementWithParent {
@@ -233,7 +266,7 @@ var AbstractFormElement = class extends AbstractElementWithParent {
233
266
  var AbstractDXEditorWithInput = class extends AbstractFormElement {
234
267
  async getInputElement() {
235
268
  const controlEl = await this.getElement();
236
- return controlEl.findElement(import_selenium_webdriver6.By.className("dx-texteditor-input"));
269
+ return controlEl.findElement(import_selenium_webdriver7.By.className("dx-texteditor-input"));
237
270
  }
238
271
  async getInputValue() {
239
272
  const inputEl = await this.getInputElement();
@@ -241,8 +274,8 @@ var AbstractDXEditorWithInput = class extends AbstractFormElement {
241
274
  }
242
275
  async setInputValue(value) {
243
276
  const inputEl = await this.getInputElement();
244
- await inputEl.click();
245
- await inputEl.sendKeys(value, import_selenium_webdriver6.Key.ENTER);
277
+ await click(inputEl, this.driver);
278
+ await inputEl.sendKeys(value, import_selenium_webdriver7.Key.ENTER);
246
279
  }
247
280
  };
248
281
 
@@ -282,13 +315,13 @@ var CheckBox = class extends AbstractFormElement {
282
315
  const inputEl = await this.getElement();
283
316
  const currentValue = await this.getValue();
284
317
  if (currentValue !== value) {
285
- await inputEl.click();
318
+ await click(inputEl, this.driver);
286
319
  }
287
320
  }
288
321
  };
289
322
 
290
323
  // src/pageObjects/elements/Editors/SelectBoxEditor.ts
291
- var import_selenium_webdriver7 = require("selenium-webdriver");
324
+ var import_selenium_webdriver8 = require("selenium-webdriver");
292
325
 
293
326
  // src/utils/xpathHelper.ts
294
327
  var XPathHelper = class {
@@ -306,13 +339,13 @@ var SELECT_BOX_ELEMENT_ROLE = "option";
306
339
  var SelectBoxEditor = class extends AbstractDXEditorWithInput {
307
340
  async setSelectInputValue(value) {
308
341
  const inputEl = await this.getInputElement();
309
- await inputEl.click();
310
- await inputEl.sendKeys(value, import_selenium_webdriver7.Key.ENTER);
342
+ await click(inputEl, this.driver);
343
+ await inputEl.sendKeys(value, import_selenium_webdriver8.Key.ENTER);
311
344
  const combinedValueXpath = XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE) + XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value);
312
345
  await this.driver.wait(async () => {
313
346
  try {
314
- const optElement = await inputEl.findElement(import_selenium_webdriver7.By.xpath(combinedValueXpath));
315
- await optElement.click();
347
+ const optElement = await inputEl.findElement(import_selenium_webdriver8.By.xpath(combinedValueXpath));
348
+ await click(optElement, this.driver);
316
349
  return true;
317
350
  } catch (e) {
318
351
  return false;
@@ -346,7 +379,7 @@ var SwitchEditor = class extends AbstractFormElement {
346
379
  const inputEl = await this.getElement();
347
380
  const currentValue = await this.getValue();
348
381
  if (currentValue !== value) {
349
- await inputEl.click();
382
+ await click(inputEl, this.driver);
350
383
  await this.driver.wait(async () => {
351
384
  const updatedValue = await this.getValue();
352
385
  return updatedValue !== currentValue;
@@ -420,10 +453,10 @@ var FormField = class extends AbstractElementWithParent {
420
453
 
421
454
  // src/pageObjects/elements/Forms/FormEdit.ts
422
455
  var FormEdit = class extends AbstractForm {
423
- saveButtonBy = import_selenium_webdriver8.By.id("button-save");
456
+ saveButtonBy = import_selenium_webdriver9.By.id("button-save");
424
457
  constructor(driver) {
425
458
  super(driver);
426
- this.popupContainerBy = import_selenium_webdriver8.By.className(`popup form-edit-${this.formName}`);
459
+ this.popupContainerBy = import_selenium_webdriver9.By.className(`popup form-edit-${this.formName}`);
427
460
  }
428
461
  /**
429
462
  * Находит поле формы редактирования по имени
@@ -443,41 +476,41 @@ var FormEdit = class extends AbstractForm {
443
476
  * await formEdit.saveButtonClick();
444
477
  */
445
478
  async saveButtonClick() {
446
- await this.driver.findElement(this.saveButtonBy).click();
479
+ await click(await this.driver.findElement(this.saveButtonBy), this.driver);
447
480
  }
448
481
  };
449
482
 
450
483
  // src/pageObjects/elements/Forms/ListForm.ts
451
- var import_selenium_webdriver14 = require("selenium-webdriver");
484
+ var import_selenium_webdriver15 = require("selenium-webdriver");
452
485
 
453
486
  // src/pageObjects/elements/Table/Table.ts
454
- var import_selenium_webdriver11 = require("selenium-webdriver");
487
+ var import_selenium_webdriver12 = require("selenium-webdriver");
455
488
 
456
489
  // src/pageObjects/elements/Table/utils.ts
457
- var import_selenium_webdriver9 = require("selenium-webdriver");
490
+ var import_selenium_webdriver10 = require("selenium-webdriver");
458
491
  var getRowPathByIndex = (index) => {
459
- return import_selenium_webdriver9.By.xpath(`//tr[@aria-rowindex="${transformInputIndex(index)}"]`);
492
+ return import_selenium_webdriver10.By.css(`tr[aria-rowindex="${transformInputIndex(index)}"]`);
460
493
  };
461
494
  var getColumnPathByIndex = (index) => {
462
- return import_selenium_webdriver9.By.xpath(`//td[@aria-colindex="${transformInputIndex(index)}"]`);
495
+ return import_selenium_webdriver10.By.css(`td[aria-colindex="${transformInputIndex(index)}"]`);
463
496
  };
464
497
  var getColumnPathByCaption = (caption) => {
465
- return import_selenium_webdriver9.By.xpath(`//td[@role="columnheader"][@aria-label="Column ${caption}"]`);
498
+ return import_selenium_webdriver10.By.css(`td[role="columnheader"][aria-label="Column ${caption}"]`);
466
499
  };
467
500
  var getCellPathByIndex = (index) => {
468
- return import_selenium_webdriver9.By.xpath(`//td[@role="gridcell"][@aria-colindex="${transformInputIndex(index)}"]`);
501
+ return import_selenium_webdriver10.By.css(`td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`);
469
502
  };
470
503
  var transformInputIndex = (index) => index + 1;
471
504
  var transformOutputIndex = (index) => +index - 1;
472
505
 
473
506
  // src/pageObjects/elements/Table/elements/Row.ts
474
- var import_selenium_webdriver10 = require("selenium-webdriver");
507
+ var import_selenium_webdriver11 = require("selenium-webdriver");
475
508
 
476
509
  // src/pageObjects/elements/Table/elements/Cell.ts
477
510
  var Cell = class extends AbstractElementWithParent {
478
511
  index;
479
- constructor(getParentElement, index, driver) {
480
- super(getParentElement, driver);
512
+ constructor(rowEl, index, driver) {
513
+ super(() => Promise.resolve(rowEl), driver);
481
514
  this.index = index;
482
515
  this.elementBy = getCellPathByIndex(index);
483
516
  }
@@ -491,6 +524,8 @@ var Cell = class extends AbstractElementWithParent {
491
524
  };
492
525
 
493
526
  // src/pageObjects/elements/Table/elements/Row.ts
527
+ var DX_SELECTION_CLASS = "dx-selection";
528
+ var DX_ROW_EDIT_CLASS = "dx-edit-row";
494
529
  var Row = class extends AbstractElementWithParent {
495
530
  index;
496
531
  getColumnByCaption;
@@ -500,14 +535,11 @@ var Row = class extends AbstractElementWithParent {
500
535
  this.elementBy = getRowPathByIndex(index);
501
536
  this.getColumnByCaption = getColumnByCaption;
502
537
  }
503
- getRowElement = () => {
504
- return this.driver.findElement(this.elementBy);
505
- };
506
538
  async getCellByIndex(index) {
507
539
  const rowEl = await this.getElement();
508
540
  const cell = rowEl.findElement(getCellPathByIndex(index));
509
541
  if (cell) {
510
- return new Cell(this.getRowElement, index, this.driver);
542
+ return new Cell(rowEl, index, this.driver);
511
543
  }
512
544
  throw new Error(`Cannot find cell by index: ${index}`);
513
545
  }
@@ -521,7 +553,13 @@ var Row = class extends AbstractElementWithParent {
521
553
  }
522
554
  async select() {
523
555
  const rowEl = await this.getElement();
524
- await rowEl.click();
556
+ await click(rowEl, this.driver);
557
+ await this.driver.wait(async () => {
558
+ const classes = await rowEl.getAttribute("class");
559
+ if (!classes.includes(DX_SELECTION_CLASS))
560
+ throw new Error("Cannot select row");
561
+ return true;
562
+ }, 500);
525
563
  }
526
564
  async isSelected() {
527
565
  const rowEl = await this.getElement();
@@ -533,34 +571,34 @@ var Row = class extends AbstractElementWithParent {
533
571
  }
534
572
  async getCells() {
535
573
  const rowEl = await this.getElement();
536
- const cells = await rowEl.findElements(import_selenium_webdriver10.By.css(`td[role="gridcell"]`));
574
+ const cells = await rowEl.findElements(import_selenium_webdriver11.By.css(`td[role="gridcell"]`));
537
575
  const result = [];
538
576
  cells.forEach((_, index) => {
539
- const newCell = new Cell(this.getRowElement, index, this.driver);
577
+ const newCell = new Cell(rowEl, index, this.driver);
540
578
  result.push(newCell);
541
579
  });
542
580
  return result;
543
581
  }
544
582
  async clickInlineButton(rowClass, buttonClass) {
545
- const fixedTable = await this.getParentElement().findElement(
546
- import_selenium_webdriver10.By.css(".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed")
583
+ const fixedTable = (await this.getParentElement()).findElement(
584
+ import_selenium_webdriver11.By.css(".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed")
547
585
  );
548
- const rowEl = await fixedTable.findElement(import_selenium_webdriver10.By.className(rowClass));
549
- const button = await rowEl.findElement(import_selenium_webdriver10.By.className(buttonClass));
586
+ const rowEl = await fixedTable.findElement(import_selenium_webdriver11.By.className(rowClass));
587
+ const button = await rowEl.findElement(import_selenium_webdriver11.By.className(buttonClass));
550
588
  if (button) {
551
- return button.click();
589
+ return click(button, this.driver);
552
590
  }
553
591
  throw new Error(`Cannot find ${buttonClass} button`);
554
592
  }
555
593
  async edit() {
556
594
  await this.select();
557
- return this.clickInlineButton("dx-selection", "edit");
595
+ return this.clickInlineButton(DX_SELECTION_CLASS, "edit");
558
596
  }
559
597
  async save() {
560
- return this.clickInlineButton("dx-edit-row", "save");
598
+ return this.clickInlineButton(DX_ROW_EDIT_CLASS, "save");
561
599
  }
562
600
  async cancel() {
563
- return this.clickInlineButton("dx-edit-row", "cancel");
601
+ return this.clickInlineButton(DX_ROW_EDIT_CLASS, "cancel");
564
602
  }
565
603
  };
566
604
 
@@ -583,17 +621,19 @@ var Column = class extends AbstractElementWithParent {
583
621
 
584
622
  // src/pageObjects/elements/Table/Table.ts
585
623
  var Table = class extends AbstractElementWithParent {
624
+ formName;
586
625
  constructor(getParentElement, formName, driver) {
587
626
  super(getParentElement, driver);
588
- this.elementBy = import_selenium_webdriver11.By.id(createTableId(formName));
627
+ this.elementBy = import_selenium_webdriver12.By.id(createTableId(formName));
628
+ this.formName = formName;
589
629
  }
590
630
  async getHeaderElement() {
591
631
  const parentEl = await this.getElement();
592
- return parentEl.findElement(import_selenium_webdriver11.By.className("dx-header-row"));
632
+ return parentEl.findElement(import_selenium_webdriver12.By.className("dx-header-row"));
593
633
  }
594
634
  async getDataGrid() {
595
635
  const parentEl = await this.getElement();
596
- return parentEl.findElement(import_selenium_webdriver11.By.css(`div[role="grid"]`));
636
+ return parentEl.findElement(import_selenium_webdriver12.By.css(`div[role="grid"]`));
597
637
  }
598
638
  getTableElement = () => {
599
639
  return this.driver.findElement(this.elementBy);
@@ -633,7 +673,7 @@ var Table = class extends AbstractElementWithParent {
633
673
  }
634
674
  async getRows() {
635
675
  const gridContainer = await this.getDataGrid();
636
- const rows = await gridContainer.findElements(import_selenium_webdriver11.By.className("dx-row dx-data-row"));
676
+ const rows = await gridContainer.findElements(import_selenium_webdriver12.By.className("dx-row dx-data-row"));
637
677
  const result = [];
638
678
  rows.forEach((_, index) => {
639
679
  const newRow = new Row(this.getTableElement, index, this.driver, this.getColumnByCaption.bind(this));
@@ -643,7 +683,7 @@ var Table = class extends AbstractElementWithParent {
643
683
  }
644
684
  async getColumns() {
645
685
  const headerContainer = await this.getHeaderElement();
646
- const columns = await headerContainer.findElements(import_selenium_webdriver11.By.css(`td[role="columnheader"]`));
686
+ const columns = await headerContainer.findElements(import_selenium_webdriver12.By.css(`td[role="columnheader"]`));
647
687
  const result = [];
648
688
  columns.forEach((_, index) => {
649
689
  const newCol = new Column(this.getTableElement, index, this.driver);
@@ -651,25 +691,35 @@ var Table = class extends AbstractElementWithParent {
651
691
  });
652
692
  return result;
653
693
  }
654
- async element() {
694
+ element() {
655
695
  return this.getElement();
656
696
  }
697
+ /**
698
+ * Находит поле когда форма находится в состоянии редактирования
699
+ * @example
700
+ * const form = new MyForm();
701
+ * //...
702
+ * expect(await form.field('Name').getValue()).toBe('test value');
703
+ */
704
+ field(name) {
705
+ return new FormField(this.getElement, this.formName, name, this.driver);
706
+ }
657
707
  };
658
708
 
659
709
  // src/pageObjects/elements/TableToolbar/TableToolbar.ts
660
- var import_selenium_webdriver13 = require("selenium-webdriver");
710
+ var import_selenium_webdriver14 = require("selenium-webdriver");
661
711
 
662
712
  // src/pageObjects/elements/TableToolbar/TableToolbarButton.ts
663
- var import_selenium_webdriver12 = require("selenium-webdriver");
713
+ var import_selenium_webdriver13 = require("selenium-webdriver");
664
714
  var TOOLBAR_BUTTON_CLASS = "toolbar-button";
665
715
  var TableToolbarButton = class extends AbstractElementWithParent {
666
716
  constructor(getParentElement, name, driver) {
667
717
  super(getParentElement, driver);
668
- this.elementBy = import_selenium_webdriver12.By.id(`${TOOLBAR_BUTTON_CLASS}-${name}`);
718
+ this.elementBy = import_selenium_webdriver13.By.id(`${TOOLBAR_BUTTON_CLASS}-${name}`);
669
719
  }
670
720
  async click() {
671
721
  const button = await this.getElement();
672
- return button.click();
722
+ return click(button, this.driver);
673
723
  }
674
724
  async isDisabled() {
675
725
  const button = await this.getElement();
@@ -683,14 +733,14 @@ var TABLE_TOOLBAR_CLASS = "d5-table-toolbar";
683
733
  var TableToolbar = class extends AbstractElementWithParent {
684
734
  constructor(getParentElement, formName, driver) {
685
735
  super(getParentElement, driver);
686
- this.elementBy = import_selenium_webdriver13.By.id(`${TABLE_TOOLBAR_CLASS}-${formName}`);
736
+ this.elementBy = import_selenium_webdriver14.By.id(`${TABLE_TOOLBAR_CLASS}-${formName}`);
687
737
  }
688
738
  getTableToolbarElement = () => {
689
739
  return this.driver.findElement(this.elementBy);
690
740
  };
691
741
  async button(name) {
692
742
  const toolbar = await this.getTableToolbarElement();
693
- const button = await toolbar.findElement(import_selenium_webdriver13.By.id(`${TOOLBAR_BUTTON_CLASS}-${name}`));
743
+ const button = await toolbar.findElement(import_selenium_webdriver14.By.id(`${TOOLBAR_BUTTON_CLASS}-${name}`));
694
744
  if (button) {
695
745
  return new TableToolbarButton(this.getTableToolbarElement, name, this.driver);
696
746
  }
@@ -702,7 +752,7 @@ var TableToolbar = class extends AbstractElementWithParent {
702
752
  var ListForm = class extends AbstractForm {
703
753
  constructor(driver) {
704
754
  super(driver);
705
- this.popupContainerBy = import_selenium_webdriver14.By.className(`popup form-inline-${this.formName}`);
755
+ this.popupContainerBy = import_selenium_webdriver15.By.className(`popup form-inline-${this.formName}`);
706
756
  }
707
757
  /**
708
758
  * Находит таблицу
@@ -737,6 +787,13 @@ async function signIn(driver) {
737
787
  return webDriver;
738
788
  }
739
789
 
790
+ // src/utils/actions.ts
791
+ var click = async (webElement, driver) => {
792
+ driver = driver ?? config().driver;
793
+ const actions = driver.actions({ async: true });
794
+ await actions.move({ origin: webElement }).click().perform();
795
+ };
796
+
740
797
  // src/pageObjects/pages/LoginPage.ts
741
798
  var LOGIN_PATH = "/login";
742
799
  var LoginPage = class extends AbstractPage {
@@ -753,7 +810,7 @@ var LoginPage = class extends AbstractPage {
753
810
  await this.driver.findElement(this.passwordField).sendKeys(password);
754
811
  }
755
812
  async clickLoginButton() {
756
- await this.driver.findElement(this.loginButton).click();
813
+ await click(await this.driver.findElement(this.loginButton), this.driver);
757
814
  }
758
815
  async loginWith(username, password) {
759
816
  await this.enterUsername(username);
@@ -775,6 +832,7 @@ var LoginPage = class extends AbstractPage {
775
832
  SubsystemsPanel,
776
833
  TextEditor,
777
834
  byTestId,
835
+ click,
778
836
  config,
779
837
  createDriver,
780
838
  editorFactory,
@@ -1,5 +1,5 @@
1
1
  import * as selenium_webdriver from 'selenium-webdriver';
2
- import { WebDriver, Browser, By, Condition, WebElementPromise } from 'selenium-webdriver';
2
+ import { WebDriver, Browser, By, Condition, WebElement, WebElementPromise } from 'selenium-webdriver';
3
3
 
4
4
  type DriverType = typeof Browser;
5
5
  type BrowserList = DriverType[keyof DriverType];
@@ -66,6 +66,15 @@ declare const elementIsNotPresent: (locator: By) => Condition<boolean>;
66
66
 
67
67
  declare function signIn(driver?: WebDriver): Promise<WebDriver>;
68
68
 
69
+ /**
70
+ * Clicks on a specified web element.
71
+ *
72
+ * @param {WebElement} webElement - The web element to click on.
73
+ * @param {WebDriver} [driver] - The web driver instance to use. If not provided, the default driver from the configuration is used.
74
+ * @returns {Promise<void>} A promise that resolves when the click action is complete.
75
+ */
76
+ declare const click: (webElement: WebElement, driver?: WebDriver) => Promise<void>;
77
+
69
78
  declare class SubsystemsPanel extends AbstractElement {
70
79
  private panelBy;
71
80
  private header;
@@ -101,10 +110,10 @@ declare abstract class AbstractForm extends AbstractPage {
101
110
  }
102
111
 
103
112
  declare abstract class AbstractElementWithParent extends AbstractElement {
104
- protected getParentElement: () => WebElementPromise;
113
+ protected getParentElement: () => Promise<WebElement>;
105
114
  protected elementBy: By;
106
- constructor(getParentElement: () => WebElementPromise, driver?: WebDriver);
107
- getElement(): Promise<selenium_webdriver.WebElement>;
115
+ constructor(getParentElement: () => Promise<WebElement>, driver?: WebDriver);
116
+ getElement(): Promise<WebElement>;
108
117
  }
109
118
 
110
119
  interface Editor {
@@ -113,7 +122,7 @@ interface Editor {
113
122
  }
114
123
 
115
124
  declare class AbstractFormElement extends AbstractElementWithParent {
116
- constructor(getParentElement: () => WebElementPromise, elementBy: By, driver?: WebDriver);
125
+ constructor(getParentElement: () => Promise<WebElement>, elementBy: By, driver?: WebDriver);
117
126
  }
118
127
 
119
128
  declare abstract class AbstractDXEditorWithInput extends AbstractFormElement implements Editor {
@@ -134,11 +143,11 @@ declare class NumberEditor extends AbstractDXEditorWithInput {
134
143
  setValue(value: any): Promise<void>;
135
144
  }
136
145
 
137
- declare const editorFactory: (getParentElement: () => WebElementPromise, elementBy: By, driver?: WebDriver) => Promise<Editor>;
146
+ declare const editorFactory: (getParentElement: () => Promise<WebElement>, elementBy: By, driver?: WebDriver) => Promise<Editor>;
138
147
 
139
148
  declare class FormField extends AbstractElementWithParent implements Editor {
140
149
  editor: Editor;
141
- constructor(getParentElement: () => WebElementPromise, formName: string, name: string, driver?: WebDriver);
150
+ constructor(getParentElement: () => Promise<WebElement>, formName: string, name: string, driver?: WebDriver);
142
151
  private initEditor;
143
152
  /**
144
153
  * Возвращает значение в поле
@@ -185,7 +194,7 @@ declare class TableToolbarButton extends AbstractElementWithParent {
185
194
 
186
195
  declare class Cell extends AbstractElementWithParent {
187
196
  index: number;
188
- constructor(getParentElement: () => WebElementPromise, index: number, driver?: WebDriver);
197
+ constructor(rowEl: WebElement, index: number, driver?: WebDriver);
189
198
  getValue(): Promise<string>;
190
199
  getIndex(): number;
191
200
  }
@@ -201,7 +210,6 @@ declare class Row extends AbstractElementWithParent {
201
210
  index: number;
202
211
  protected getColumnByCaption: (caption: string) => Promise<Column>;
203
212
  constructor(getParentElement: () => WebElementPromise, index: number, driver?: WebDriver, getColumnByCaption?: (caption: string) => Promise<Column>);
204
- protected getRowElement: () => WebElementPromise;
205
213
  getCellByIndex(index: number): Promise<Cell>;
206
214
  getCell(caption: string): Promise<Cell>;
207
215
  select(): Promise<void>;
@@ -215,6 +223,7 @@ declare class Row extends AbstractElementWithParent {
215
223
  }
216
224
 
217
225
  declare class Table extends AbstractElementWithParent {
226
+ protected formName: string;
218
227
  constructor(getParentElement: () => WebElementPromise, formName: string, driver?: WebDriver);
219
228
  protected getHeaderElement(): Promise<selenium_webdriver.WebElement>;
220
229
  protected getDataGrid(): Promise<selenium_webdriver.WebElement>;
@@ -226,6 +235,14 @@ declare class Table extends AbstractElementWithParent {
226
235
  getRows(): Promise<Row[]>;
227
236
  getColumns(): Promise<Column[]>;
228
237
  element(): Promise<selenium_webdriver.WebElement>;
238
+ /**
239
+ * Находит поле когда форма находится в состоянии редактирования
240
+ * @example
241
+ * const form = new MyForm();
242
+ * //...
243
+ * expect(await form.field('Name').getValue()).toBe('test value');
244
+ */
245
+ field(name: string): FormField;
229
246
  }
230
247
 
231
248
  declare abstract class ListForm extends AbstractForm {
@@ -248,4 +265,4 @@ declare abstract class ListForm extends AbstractForm {
248
265
  toolbarButton(name: string): Promise<TableToolbarButton>;
249
266
  }
250
267
 
251
- export { AbstractPage, Editor, FormEdit, FormField, ListForm, LoginPage, NumberEditor, SubsystemsPanel, TextEditor, byTestId, config, createDriver, editorFactory, elementIsNotPresent, signIn };
268
+ export { AbstractPage, Editor, FormEdit, FormField, ListForm, LoginPage, NumberEditor, SubsystemsPanel, TextEditor, byTestId, click, config, createDriver, editorFactory, elementIsNotPresent, signIn };
@@ -1,4 +1,23 @@
1
1
  // src/config.ts
2
+ import * as process from "node:process";
3
+ var driversMap = /* @__PURE__ */ new Map();
4
+ var createConfigProxy = (config2) => {
5
+ return new Proxy(config2, {
6
+ get(_target, prop) {
7
+ if (prop === "driver") {
8
+ return driversMap.get(process.pid);
9
+ }
10
+ return Reflect.get(...arguments);
11
+ },
12
+ set(_target, prop, value) {
13
+ if (prop === "driver") {
14
+ driversMap.set(process.pid, value);
15
+ return true;
16
+ }
17
+ return Reflect.set(...arguments);
18
+ }
19
+ });
20
+ };
2
21
  var Config = class _Config {
3
22
  static instance;
4
23
  appConfig;
@@ -10,7 +29,7 @@ var Config = class _Config {
10
29
  }
11
30
  config = (cfg) => {
12
31
  if (!cfg)
13
- return this.appConfig;
32
+ return createConfigProxy(this.appConfig);
14
33
  this.appConfig = cfg;
15
34
  };
16
35
  };
@@ -81,6 +100,9 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
81
100
  });
82
101
  };
83
102
 
103
+ // src/utils/waitElementIsVisible.ts
104
+ import { until } from "selenium-webdriver";
105
+
84
106
  // src/pageObjects/AbstractElementWithParent.ts
85
107
  var AbstractElementWithParent = class extends AbstractElement {
86
108
  getParentElement;
@@ -202,7 +224,7 @@ var AbstractDXEditorWithInput = class extends AbstractFormElement {
202
224
  }
203
225
  async setInputValue(value) {
204
226
  const inputEl = await this.getInputElement();
205
- await inputEl.click();
227
+ await click(inputEl, this.driver);
206
228
  await inputEl.sendKeys(value, Key.ENTER);
207
229
  }
208
230
  };
@@ -243,7 +265,7 @@ var CheckBox = class extends AbstractFormElement {
243
265
  const inputEl = await this.getElement();
244
266
  const currentValue = await this.getValue();
245
267
  if (currentValue !== value) {
246
- await inputEl.click();
268
+ await click(inputEl, this.driver);
247
269
  }
248
270
  }
249
271
  };
@@ -267,13 +289,13 @@ var SELECT_BOX_ELEMENT_ROLE = "option";
267
289
  var SelectBoxEditor = class extends AbstractDXEditorWithInput {
268
290
  async setSelectInputValue(value) {
269
291
  const inputEl = await this.getInputElement();
270
- await inputEl.click();
292
+ await click(inputEl, this.driver);
271
293
  await inputEl.sendKeys(value, Key2.ENTER);
272
294
  const combinedValueXpath = XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE) + XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value);
273
295
  await this.driver.wait(async () => {
274
296
  try {
275
297
  const optElement = await inputEl.findElement(By6.xpath(combinedValueXpath));
276
- await optElement.click();
298
+ await click(optElement, this.driver);
277
299
  return true;
278
300
  } catch (e) {
279
301
  return false;
@@ -307,7 +329,7 @@ var SwitchEditor = class extends AbstractFormElement {
307
329
  const inputEl = await this.getElement();
308
330
  const currentValue = await this.getValue();
309
331
  if (currentValue !== value) {
310
- await inputEl.click();
332
+ await click(inputEl, this.driver);
311
333
  await this.driver.wait(async () => {
312
334
  const updatedValue = await this.getValue();
313
335
  return updatedValue !== currentValue;
@@ -404,7 +426,7 @@ var FormEdit = class extends AbstractForm {
404
426
  * await formEdit.saveButtonClick();
405
427
  */
406
428
  async saveButtonClick() {
407
- await this.driver.findElement(this.saveButtonBy).click();
429
+ await click(await this.driver.findElement(this.saveButtonBy), this.driver);
408
430
  }
409
431
  };
410
432
 
@@ -417,16 +439,16 @@ import { By as By10 } from "selenium-webdriver";
417
439
  // src/pageObjects/elements/Table/utils.ts
418
440
  import { By as By8 } from "selenium-webdriver";
419
441
  var getRowPathByIndex = (index) => {
420
- return By8.xpath(`//tr[@aria-rowindex="${transformInputIndex(index)}"]`);
442
+ return By8.css(`tr[aria-rowindex="${transformInputIndex(index)}"]`);
421
443
  };
422
444
  var getColumnPathByIndex = (index) => {
423
- return By8.xpath(`//td[@aria-colindex="${transformInputIndex(index)}"]`);
445
+ return By8.css(`td[aria-colindex="${transformInputIndex(index)}"]`);
424
446
  };
425
447
  var getColumnPathByCaption = (caption) => {
426
- return By8.xpath(`//td[@role="columnheader"][@aria-label="Column ${caption}"]`);
448
+ return By8.css(`td[role="columnheader"][aria-label="Column ${caption}"]`);
427
449
  };
428
450
  var getCellPathByIndex = (index) => {
429
- return By8.xpath(`//td[@role="gridcell"][@aria-colindex="${transformInputIndex(index)}"]`);
451
+ return By8.css(`td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`);
430
452
  };
431
453
  var transformInputIndex = (index) => index + 1;
432
454
  var transformOutputIndex = (index) => +index - 1;
@@ -437,8 +459,8 @@ import { By as By9 } from "selenium-webdriver";
437
459
  // src/pageObjects/elements/Table/elements/Cell.ts
438
460
  var Cell = class extends AbstractElementWithParent {
439
461
  index;
440
- constructor(getParentElement, index, driver) {
441
- super(getParentElement, driver);
462
+ constructor(rowEl, index, driver) {
463
+ super(() => Promise.resolve(rowEl), driver);
442
464
  this.index = index;
443
465
  this.elementBy = getCellPathByIndex(index);
444
466
  }
@@ -452,6 +474,8 @@ var Cell = class extends AbstractElementWithParent {
452
474
  };
453
475
 
454
476
  // src/pageObjects/elements/Table/elements/Row.ts
477
+ var DX_SELECTION_CLASS = "dx-selection";
478
+ var DX_ROW_EDIT_CLASS = "dx-edit-row";
455
479
  var Row = class extends AbstractElementWithParent {
456
480
  index;
457
481
  getColumnByCaption;
@@ -461,14 +485,11 @@ var Row = class extends AbstractElementWithParent {
461
485
  this.elementBy = getRowPathByIndex(index);
462
486
  this.getColumnByCaption = getColumnByCaption;
463
487
  }
464
- getRowElement = () => {
465
- return this.driver.findElement(this.elementBy);
466
- };
467
488
  async getCellByIndex(index) {
468
489
  const rowEl = await this.getElement();
469
490
  const cell = rowEl.findElement(getCellPathByIndex(index));
470
491
  if (cell) {
471
- return new Cell(this.getRowElement, index, this.driver);
492
+ return new Cell(rowEl, index, this.driver);
472
493
  }
473
494
  throw new Error(`Cannot find cell by index: ${index}`);
474
495
  }
@@ -482,7 +503,13 @@ var Row = class extends AbstractElementWithParent {
482
503
  }
483
504
  async select() {
484
505
  const rowEl = await this.getElement();
485
- await rowEl.click();
506
+ await click(rowEl, this.driver);
507
+ await this.driver.wait(async () => {
508
+ const classes = await rowEl.getAttribute("class");
509
+ if (!classes.includes(DX_SELECTION_CLASS))
510
+ throw new Error("Cannot select row");
511
+ return true;
512
+ }, 500);
486
513
  }
487
514
  async isSelected() {
488
515
  const rowEl = await this.getElement();
@@ -497,31 +524,31 @@ var Row = class extends AbstractElementWithParent {
497
524
  const cells = await rowEl.findElements(By9.css(`td[role="gridcell"]`));
498
525
  const result = [];
499
526
  cells.forEach((_, index) => {
500
- const newCell = new Cell(this.getRowElement, index, this.driver);
527
+ const newCell = new Cell(rowEl, index, this.driver);
501
528
  result.push(newCell);
502
529
  });
503
530
  return result;
504
531
  }
505
532
  async clickInlineButton(rowClass, buttonClass) {
506
- const fixedTable = await this.getParentElement().findElement(
533
+ const fixedTable = (await this.getParentElement()).findElement(
507
534
  By9.css(".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed")
508
535
  );
509
536
  const rowEl = await fixedTable.findElement(By9.className(rowClass));
510
537
  const button = await rowEl.findElement(By9.className(buttonClass));
511
538
  if (button) {
512
- return button.click();
539
+ return click(button, this.driver);
513
540
  }
514
541
  throw new Error(`Cannot find ${buttonClass} button`);
515
542
  }
516
543
  async edit() {
517
544
  await this.select();
518
- return this.clickInlineButton("dx-selection", "edit");
545
+ return this.clickInlineButton(DX_SELECTION_CLASS, "edit");
519
546
  }
520
547
  async save() {
521
- return this.clickInlineButton("dx-edit-row", "save");
548
+ return this.clickInlineButton(DX_ROW_EDIT_CLASS, "save");
522
549
  }
523
550
  async cancel() {
524
- return this.clickInlineButton("dx-edit-row", "cancel");
551
+ return this.clickInlineButton(DX_ROW_EDIT_CLASS, "cancel");
525
552
  }
526
553
  };
527
554
 
@@ -544,9 +571,11 @@ var Column = class extends AbstractElementWithParent {
544
571
 
545
572
  // src/pageObjects/elements/Table/Table.ts
546
573
  var Table = class extends AbstractElementWithParent {
574
+ formName;
547
575
  constructor(getParentElement, formName, driver) {
548
576
  super(getParentElement, driver);
549
577
  this.elementBy = By10.id(createTableId(formName));
578
+ this.formName = formName;
550
579
  }
551
580
  async getHeaderElement() {
552
581
  const parentEl = await this.getElement();
@@ -612,9 +641,19 @@ var Table = class extends AbstractElementWithParent {
612
641
  });
613
642
  return result;
614
643
  }
615
- async element() {
644
+ element() {
616
645
  return this.getElement();
617
646
  }
647
+ /**
648
+ * Находит поле когда форма находится в состоянии редактирования
649
+ * @example
650
+ * const form = new MyForm();
651
+ * //...
652
+ * expect(await form.field('Name').getValue()).toBe('test value');
653
+ */
654
+ field(name) {
655
+ return new FormField(this.getElement, this.formName, name, this.driver);
656
+ }
618
657
  };
619
658
 
620
659
  // src/pageObjects/elements/TableToolbar/TableToolbar.ts
@@ -630,7 +669,7 @@ var TableToolbarButton = class extends AbstractElementWithParent {
630
669
  }
631
670
  async click() {
632
671
  const button = await this.getElement();
633
- return button.click();
672
+ return click(button, this.driver);
634
673
  }
635
674
  async isDisabled() {
636
675
  const button = await this.getElement();
@@ -698,6 +737,13 @@ async function signIn(driver) {
698
737
  return webDriver;
699
738
  }
700
739
 
740
+ // src/utils/actions.ts
741
+ var click = async (webElement, driver) => {
742
+ driver = driver ?? config().driver;
743
+ const actions = driver.actions({ async: true });
744
+ await actions.move({ origin: webElement }).click().perform();
745
+ };
746
+
701
747
  // src/pageObjects/pages/LoginPage.ts
702
748
  var LOGIN_PATH = "/login";
703
749
  var LoginPage = class extends AbstractPage {
@@ -714,7 +760,7 @@ var LoginPage = class extends AbstractPage {
714
760
  await this.driver.findElement(this.passwordField).sendKeys(password);
715
761
  }
716
762
  async clickLoginButton() {
717
- await this.driver.findElement(this.loginButton).click();
763
+ await click(await this.driver.findElement(this.loginButton), this.driver);
718
764
  }
719
765
  async loginWith(username, password) {
720
766
  await this.enterUsername(username);
@@ -735,6 +781,7 @@ export {
735
781
  SubsystemsPanel,
736
782
  TextEditor,
737
783
  byTestId,
784
+ click,
738
785
  config,
739
786
  createDriver,
740
787
  editorFactory,
@@ -1,4 +1,23 @@
1
1
  // src/config.ts
2
+ import * as process from "node:process";
3
+ var driversMap = /* @__PURE__ */ new Map();
4
+ var createConfigProxy = (config2) => {
5
+ return new Proxy(config2, {
6
+ get(_target, prop) {
7
+ if (prop === "driver") {
8
+ return driversMap.get(process.pid);
9
+ }
10
+ return Reflect.get(...arguments);
11
+ },
12
+ set(_target, prop, value) {
13
+ if (prop === "driver") {
14
+ driversMap.set(process.pid, value);
15
+ return true;
16
+ }
17
+ return Reflect.set(...arguments);
18
+ }
19
+ });
20
+ };
2
21
  var Config = class _Config {
3
22
  static instance;
4
23
  appConfig;
@@ -10,7 +29,7 @@ var Config = class _Config {
10
29
  }
11
30
  config = (cfg) => {
12
31
  if (!cfg)
13
- return this.appConfig;
32
+ return createConfigProxy(this.appConfig);
14
33
  this.appConfig = cfg;
15
34
  };
16
35
  };
@@ -81,6 +100,9 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
81
100
  });
82
101
  };
83
102
 
103
+ // src/utils/waitElementIsVisible.ts
104
+ import { until } from "selenium-webdriver";
105
+
84
106
  // src/pageObjects/AbstractElementWithParent.ts
85
107
  var AbstractElementWithParent = class extends AbstractElement {
86
108
  getParentElement;
@@ -202,7 +224,7 @@ var AbstractDXEditorWithInput = class extends AbstractFormElement {
202
224
  }
203
225
  async setInputValue(value) {
204
226
  const inputEl = await this.getInputElement();
205
- await inputEl.click();
227
+ await click(inputEl, this.driver);
206
228
  await inputEl.sendKeys(value, Key.ENTER);
207
229
  }
208
230
  };
@@ -243,7 +265,7 @@ var CheckBox = class extends AbstractFormElement {
243
265
  const inputEl = await this.getElement();
244
266
  const currentValue = await this.getValue();
245
267
  if (currentValue !== value) {
246
- await inputEl.click();
268
+ await click(inputEl, this.driver);
247
269
  }
248
270
  }
249
271
  };
@@ -267,13 +289,13 @@ var SELECT_BOX_ELEMENT_ROLE = "option";
267
289
  var SelectBoxEditor = class extends AbstractDXEditorWithInput {
268
290
  async setSelectInputValue(value) {
269
291
  const inputEl = await this.getInputElement();
270
- await inputEl.click();
292
+ await click(inputEl, this.driver);
271
293
  await inputEl.sendKeys(value, Key2.ENTER);
272
294
  const combinedValueXpath = XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE) + XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value);
273
295
  await this.driver.wait(async () => {
274
296
  try {
275
297
  const optElement = await inputEl.findElement(By6.xpath(combinedValueXpath));
276
- await optElement.click();
298
+ await click(optElement, this.driver);
277
299
  return true;
278
300
  } catch (e) {
279
301
  return false;
@@ -307,7 +329,7 @@ var SwitchEditor = class extends AbstractFormElement {
307
329
  const inputEl = await this.getElement();
308
330
  const currentValue = await this.getValue();
309
331
  if (currentValue !== value) {
310
- await inputEl.click();
332
+ await click(inputEl, this.driver);
311
333
  await this.driver.wait(async () => {
312
334
  const updatedValue = await this.getValue();
313
335
  return updatedValue !== currentValue;
@@ -404,7 +426,7 @@ var FormEdit = class extends AbstractForm {
404
426
  * await formEdit.saveButtonClick();
405
427
  */
406
428
  async saveButtonClick() {
407
- await this.driver.findElement(this.saveButtonBy).click();
429
+ await click(await this.driver.findElement(this.saveButtonBy), this.driver);
408
430
  }
409
431
  };
410
432
 
@@ -417,16 +439,16 @@ import { By as By10 } from "selenium-webdriver";
417
439
  // src/pageObjects/elements/Table/utils.ts
418
440
  import { By as By8 } from "selenium-webdriver";
419
441
  var getRowPathByIndex = (index) => {
420
- return By8.xpath(`//tr[@aria-rowindex="${transformInputIndex(index)}"]`);
442
+ return By8.css(`tr[aria-rowindex="${transformInputIndex(index)}"]`);
421
443
  };
422
444
  var getColumnPathByIndex = (index) => {
423
- return By8.xpath(`//td[@aria-colindex="${transformInputIndex(index)}"]`);
445
+ return By8.css(`td[aria-colindex="${transformInputIndex(index)}"]`);
424
446
  };
425
447
  var getColumnPathByCaption = (caption) => {
426
- return By8.xpath(`//td[@role="columnheader"][@aria-label="Column ${caption}"]`);
448
+ return By8.css(`td[role="columnheader"][aria-label="Column ${caption}"]`);
427
449
  };
428
450
  var getCellPathByIndex = (index) => {
429
- return By8.xpath(`//td[@role="gridcell"][@aria-colindex="${transformInputIndex(index)}"]`);
451
+ return By8.css(`td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`);
430
452
  };
431
453
  var transformInputIndex = (index) => index + 1;
432
454
  var transformOutputIndex = (index) => +index - 1;
@@ -437,8 +459,8 @@ import { By as By9 } from "selenium-webdriver";
437
459
  // src/pageObjects/elements/Table/elements/Cell.ts
438
460
  var Cell = class extends AbstractElementWithParent {
439
461
  index;
440
- constructor(getParentElement, index, driver) {
441
- super(getParentElement, driver);
462
+ constructor(rowEl, index, driver) {
463
+ super(() => Promise.resolve(rowEl), driver);
442
464
  this.index = index;
443
465
  this.elementBy = getCellPathByIndex(index);
444
466
  }
@@ -452,6 +474,8 @@ var Cell = class extends AbstractElementWithParent {
452
474
  };
453
475
 
454
476
  // src/pageObjects/elements/Table/elements/Row.ts
477
+ var DX_SELECTION_CLASS = "dx-selection";
478
+ var DX_ROW_EDIT_CLASS = "dx-edit-row";
455
479
  var Row = class extends AbstractElementWithParent {
456
480
  index;
457
481
  getColumnByCaption;
@@ -461,14 +485,11 @@ var Row = class extends AbstractElementWithParent {
461
485
  this.elementBy = getRowPathByIndex(index);
462
486
  this.getColumnByCaption = getColumnByCaption;
463
487
  }
464
- getRowElement = () => {
465
- return this.driver.findElement(this.elementBy);
466
- };
467
488
  async getCellByIndex(index) {
468
489
  const rowEl = await this.getElement();
469
490
  const cell = rowEl.findElement(getCellPathByIndex(index));
470
491
  if (cell) {
471
- return new Cell(this.getRowElement, index, this.driver);
492
+ return new Cell(rowEl, index, this.driver);
472
493
  }
473
494
  throw new Error(`Cannot find cell by index: ${index}`);
474
495
  }
@@ -482,7 +503,13 @@ var Row = class extends AbstractElementWithParent {
482
503
  }
483
504
  async select() {
484
505
  const rowEl = await this.getElement();
485
- await rowEl.click();
506
+ await click(rowEl, this.driver);
507
+ await this.driver.wait(async () => {
508
+ const classes = await rowEl.getAttribute("class");
509
+ if (!classes.includes(DX_SELECTION_CLASS))
510
+ throw new Error("Cannot select row");
511
+ return true;
512
+ }, 500);
486
513
  }
487
514
  async isSelected() {
488
515
  const rowEl = await this.getElement();
@@ -497,31 +524,31 @@ var Row = class extends AbstractElementWithParent {
497
524
  const cells = await rowEl.findElements(By9.css(`td[role="gridcell"]`));
498
525
  const result = [];
499
526
  cells.forEach((_, index) => {
500
- const newCell = new Cell(this.getRowElement, index, this.driver);
527
+ const newCell = new Cell(rowEl, index, this.driver);
501
528
  result.push(newCell);
502
529
  });
503
530
  return result;
504
531
  }
505
532
  async clickInlineButton(rowClass, buttonClass) {
506
- const fixedTable = await this.getParentElement().findElement(
533
+ const fixedTable = (await this.getParentElement()).findElement(
507
534
  By9.css(".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed")
508
535
  );
509
536
  const rowEl = await fixedTable.findElement(By9.className(rowClass));
510
537
  const button = await rowEl.findElement(By9.className(buttonClass));
511
538
  if (button) {
512
- return button.click();
539
+ return click(button, this.driver);
513
540
  }
514
541
  throw new Error(`Cannot find ${buttonClass} button`);
515
542
  }
516
543
  async edit() {
517
544
  await this.select();
518
- return this.clickInlineButton("dx-selection", "edit");
545
+ return this.clickInlineButton(DX_SELECTION_CLASS, "edit");
519
546
  }
520
547
  async save() {
521
- return this.clickInlineButton("dx-edit-row", "save");
548
+ return this.clickInlineButton(DX_ROW_EDIT_CLASS, "save");
522
549
  }
523
550
  async cancel() {
524
- return this.clickInlineButton("dx-edit-row", "cancel");
551
+ return this.clickInlineButton(DX_ROW_EDIT_CLASS, "cancel");
525
552
  }
526
553
  };
527
554
 
@@ -544,9 +571,11 @@ var Column = class extends AbstractElementWithParent {
544
571
 
545
572
  // src/pageObjects/elements/Table/Table.ts
546
573
  var Table = class extends AbstractElementWithParent {
574
+ formName;
547
575
  constructor(getParentElement, formName, driver) {
548
576
  super(getParentElement, driver);
549
577
  this.elementBy = By10.id(createTableId(formName));
578
+ this.formName = formName;
550
579
  }
551
580
  async getHeaderElement() {
552
581
  const parentEl = await this.getElement();
@@ -612,9 +641,19 @@ var Table = class extends AbstractElementWithParent {
612
641
  });
613
642
  return result;
614
643
  }
615
- async element() {
644
+ element() {
616
645
  return this.getElement();
617
646
  }
647
+ /**
648
+ * Находит поле когда форма находится в состоянии редактирования
649
+ * @example
650
+ * const form = new MyForm();
651
+ * //...
652
+ * expect(await form.field('Name').getValue()).toBe('test value');
653
+ */
654
+ field(name) {
655
+ return new FormField(this.getElement, this.formName, name, this.driver);
656
+ }
618
657
  };
619
658
 
620
659
  // src/pageObjects/elements/TableToolbar/TableToolbar.ts
@@ -630,7 +669,7 @@ var TableToolbarButton = class extends AbstractElementWithParent {
630
669
  }
631
670
  async click() {
632
671
  const button = await this.getElement();
633
- return button.click();
672
+ return click(button, this.driver);
634
673
  }
635
674
  async isDisabled() {
636
675
  const button = await this.getElement();
@@ -698,6 +737,13 @@ async function signIn(driver) {
698
737
  return webDriver;
699
738
  }
700
739
 
740
+ // src/utils/actions.ts
741
+ var click = async (webElement, driver) => {
742
+ driver = driver ?? config().driver;
743
+ const actions = driver.actions({ async: true });
744
+ await actions.move({ origin: webElement }).click().perform();
745
+ };
746
+
701
747
  // src/pageObjects/pages/LoginPage.ts
702
748
  var LOGIN_PATH = "/login";
703
749
  var LoginPage = class extends AbstractPage {
@@ -714,7 +760,7 @@ var LoginPage = class extends AbstractPage {
714
760
  await this.driver.findElement(this.passwordField).sendKeys(password);
715
761
  }
716
762
  async clickLoginButton() {
717
- await this.driver.findElement(this.loginButton).click();
763
+ await click(await this.driver.findElement(this.loginButton), this.driver);
718
764
  }
719
765
  async loginWith(username, password) {
720
766
  await this.enterUsername(username);
@@ -735,6 +781,7 @@ export {
735
781
  SubsystemsPanel,
736
782
  TextEditor,
737
783
  byTestId,
784
+ click,
738
785
  config,
739
786
  createDriver,
740
787
  editorFactory,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "d5-testing-library",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "e2e testing D5 projects",
5
5
  "main": "dist/cjs/d5-testing-library.cjs",
6
6
  "module": "dist/d5-testing-library.legacy-esm.js",