d5-testing-library 1.0.5 → 1.2.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.
@@ -39,12 +39,15 @@ __export(src_exports, {
39
39
  SubsystemsPanel: () => SubsystemsPanel,
40
40
  TextEditor: () => TextEditor,
41
41
  byTestId: () => byTestId,
42
+ byTestIdCssSelector: () => byTestIdCssSelector,
42
43
  click: () => click,
43
44
  config: () => config,
44
45
  createDriver: () => createDriver,
45
46
  editorFactory: () => editorFactory,
46
47
  elementIsNotPresent: () => elementIsNotPresent,
47
- signIn: () => signIn
48
+ signIn: () => signIn,
49
+ wait: () => wait,
50
+ waitElementIsVisible: () => waitElementIsVisible
48
51
  });
49
52
  module.exports = __toCommonJS(src_exports);
50
53
 
@@ -127,8 +130,11 @@ var AbstractPage = class extends AbstractElement {
127
130
 
128
131
  // src/utils/locators.ts
129
132
  var import_selenium_webdriver = require("selenium-webdriver");
133
+ var byTestIdCssSelector = (testId, element = "div") => {
134
+ return `${element}[data-testid="${testId}"]`;
135
+ };
130
136
  var byTestId = (testId, element = "div") => {
131
- return import_selenium_webdriver.By.css(`${element}[data-testid=${testId}]`);
137
+ return import_selenium_webdriver.By.css(byTestIdCssSelector(testId, element));
132
138
  };
133
139
 
134
140
  // src/utils/createDriver.ts
@@ -153,54 +159,91 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
153
159
  // src/utils/waitElementIsVisible.ts
154
160
  var import_selenium_webdriver4 = require("selenium-webdriver");
155
161
 
162
+ // src/utils/wait.ts
163
+ async function wait(condition, driver, errorMessage, timeout) {
164
+ driver = driver ?? config().driver;
165
+ await driver.wait(condition, timeout ?? config().timeout, errorMessage);
166
+ }
167
+
168
+ // src/utils/waitElementIsVisible.ts
169
+ async function waitElementIsVisible({
170
+ element,
171
+ timeout,
172
+ errorMessage,
173
+ driver
174
+ }) {
175
+ driver = driver ?? config().driver;
176
+ const condition = import_selenium_webdriver4.until.elementIsVisible(element);
177
+ await wait(condition.fn, driver, errorMessage ?? condition.description(), timeout ?? config().timeout);
178
+ }
179
+
156
180
  // src/pageObjects/AbstractElementWithParent.ts
181
+ var import_selenium_webdriver5 = require("selenium-webdriver");
157
182
  var AbstractElementWithParent = class extends AbstractElement {
158
- getParentElement;
159
- elementBy;
160
- constructor(getParentElement, driver) {
183
+ elementCssSelector;
184
+ parentCssSelector;
185
+ constructor(parentCssSelector, elementCssSelector, driver) {
161
186
  super(driver);
162
- this.getParentElement = getParentElement;
187
+ this.parentCssSelector = parentCssSelector;
188
+ this.elementCssSelector = elementCssSelector;
189
+ }
190
+ getFullCssSelector() {
191
+ if (!this.elementCssSelector) {
192
+ return this.parentCssSelector;
193
+ }
194
+ if (!this.parentCssSelector) {
195
+ return this.elementCssSelector;
196
+ }
197
+ return `${this.parentCssSelector} ${this.elementCssSelector}`;
163
198
  }
164
199
  async getElement() {
165
- const parentEl = await this.getParentElement();
166
- return parentEl.findElement(this.elementBy);
200
+ return this.driver.findElement(import_selenium_webdriver5.By.css(this.getFullCssSelector()));
201
+ }
202
+ async getAttribute(attr) {
203
+ const element = await this.getElement();
204
+ await waitElementIsVisible({
205
+ element,
206
+ driver: this.driver,
207
+ errorMessage: `Element not found: ${this.getFullCssSelector()}`
208
+ });
209
+ return await element.getAttribute(attr);
210
+ }
211
+ async getClasses() {
212
+ return await this.getAttribute("class");
167
213
  }
168
214
  };
169
215
 
170
216
  // src/pageObjects/elements/SubsystemsPanel/SubsystemsPanelHeader.ts
217
+ var import_selenium_webdriver6 = require("selenium-webdriver");
171
218
  var SubsystemsPanelHeader = class extends AbstractElementWithParent {
172
- titleBy = byTestId("subsystems-panel-title", "span");
173
219
  async title() {
174
- const panel = await this.getParentElement();
175
- return panel.findElement(this.titleBy);
220
+ return this.driver.findElement(import_selenium_webdriver6.By.css(this.getFullCssSelector()));
176
221
  }
177
222
  };
178
223
 
179
224
  // src/pageObjects/elements/SubsystemsPanel/SubsystemsPanel.ts
180
- var import_selenium_webdriver5 = require("selenium-webdriver");
181
225
  var SubsystemsPanel = class extends AbstractElement {
182
- panelBy = import_selenium_webdriver5.By.id("aside");
183
226
  header;
184
227
  constructor(driver) {
185
228
  super(driver);
186
- this.header = new SubsystemsPanelHeader(this.panelElement, this.driver);
229
+ this.header = new SubsystemsPanelHeader("#aside", byTestIdCssSelector("subsystems-panel-title", "span"), this.driver);
187
230
  }
188
- panelElement = () => {
189
- return this.driver.findElement(this.panelBy);
190
- };
191
231
  headerTitle() {
192
232
  return this.header.title().then((el) => el.getText());
193
233
  }
194
234
  };
195
235
 
196
236
  // src/pageObjects/elements/Forms/AbstractForm.ts
197
- var import_selenium_webdriver6 = require("selenium-webdriver");
237
+ var import_selenium_webdriver7 = require("selenium-webdriver");
198
238
  var AbstractForm = class extends AbstractPage {
239
+ containerCssSelector = "";
199
240
  containerBy;
200
- popupContainerBy;
241
+ popupContainerCssSelector;
201
242
  constructor(driver) {
202
243
  super(driver);
203
- this.containerBy = byTestId(`form-content-wrapper-${this.formName}`);
244
+ const testId = `form-content-wrapper-${this.formName}`;
245
+ this.containerBy = byTestId(testId);
246
+ this.containerCssSelector = byTestIdCssSelector(testId);
204
247
  }
205
248
  async isModal() {
206
249
  const el = await this.getContainerElement();
@@ -223,7 +266,7 @@ var AbstractForm = class extends AbstractPage {
223
266
  */
224
267
  async exists() {
225
268
  try {
226
- await this.driver.wait(elementIsNotPresent(this.containerBy), 1e3);
269
+ await wait(elementIsNotPresent(this.containerBy), this.driver);
227
270
  return false;
228
271
  } catch {
229
272
  return true;
@@ -238,35 +281,39 @@ var AbstractForm = class extends AbstractPage {
238
281
  */
239
282
  async getTitleText() {
240
283
  if (await this.isModal()) {
241
- const popupEl = await this.driver.findElement(this.popupContainerBy);
242
- const titleEl2 = await popupEl.findElement(import_selenium_webdriver6.By.className("popup-title"));
284
+ const titleEl2 = await this.driver.findElement(import_selenium_webdriver7.By.css(`${this.popupContainerCssSelector} .popup-title`));
243
285
  return titleEl2.getText();
244
286
  }
245
- let container = await this.getContainerElement();
246
- let titleEl = await container.findElement(import_selenium_webdriver6.By.className("form-toolbar-name-container"));
287
+ let titleEl = await this.driver.findElement(import_selenium_webdriver7.By.css(`${this.containerCssSelector} .form-toolbar-name-container`));
247
288
  return titleEl.getText();
248
289
  }
249
290
  };
250
291
 
251
292
  // src/pageObjects/elements/Forms/FormEdit.ts
252
- var import_selenium_webdriver9 = require("selenium-webdriver");
293
+ var import_selenium_webdriver14 = require("selenium-webdriver");
253
294
 
254
295
  // src/pageObjects/elements/Editors/AbstractEditor.ts
255
- var import_selenium_webdriver7 = require("selenium-webdriver");
296
+ var import_selenium_webdriver8 = require("selenium-webdriver");
256
297
 
257
- // src/pageObjects/AbstractFormElement.ts
258
- var AbstractFormElement = class extends AbstractElementWithParent {
259
- constructor(getParentElement, elementBy, driver) {
260
- super(getParentElement, driver);
261
- this.elementBy = elementBy;
298
+ // src/pageObjects/elements/Editors/ClearStrategy/InputClearStrategy.ts
299
+ var InputClearStrategy = class {
300
+ async clear(editor) {
301
+ const inputEl = await editor.getInputElement();
302
+ await inputEl.clear();
262
303
  }
263
304
  };
264
305
 
265
306
  // src/pageObjects/elements/Editors/AbstractEditor.ts
266
- var AbstractDXEditorWithInput = class extends AbstractFormElement {
307
+ var AbstractDXEditorWithInput = class extends AbstractElementWithParent {
308
+ clearStrategy = new InputClearStrategy();
309
+ setClearStrategy(strategy) {
310
+ this.clearStrategy = strategy;
311
+ }
312
+ getInputCssSelector() {
313
+ return `${this.getFullCssSelector()} .dx-texteditor-input`;
314
+ }
267
315
  async getInputElement() {
268
- const controlEl = await this.getElement();
269
- return controlEl.findElement(import_selenium_webdriver7.By.className("dx-texteditor-input"));
316
+ return this.driver.findElement(import_selenium_webdriver8.By.css(this.getInputCssSelector()));
270
317
  }
271
318
  async getInputValue() {
272
319
  const inputEl = await this.getInputElement();
@@ -275,12 +322,19 @@ var AbstractDXEditorWithInput = class extends AbstractFormElement {
275
322
  async setInputValue(value) {
276
323
  const inputEl = await this.getInputElement();
277
324
  await click(inputEl, this.driver);
278
- await inputEl.sendKeys(value, import_selenium_webdriver7.Key.ENTER);
325
+ await inputEl.sendKeys(value, import_selenium_webdriver8.Key.ENTER);
326
+ }
327
+ async clear() {
328
+ await this.clearStrategy.clear(this);
279
329
  }
280
330
  };
281
331
 
282
332
  // src/pageObjects/elements/Editors/TextEditor.ts
283
333
  var TextEditor = class extends AbstractDXEditorWithInput {
334
+ constructor(parentCssSelector, elementCssSelector, driver) {
335
+ super(parentCssSelector, elementCssSelector, driver);
336
+ this.setClearStrategy(new InputClearStrategy());
337
+ }
284
338
  getValue() {
285
339
  return this.getInputValue();
286
340
  }
@@ -291,6 +345,10 @@ var TextEditor = class extends AbstractDXEditorWithInput {
291
345
 
292
346
  // src/pageObjects/elements/Editors/NumberEditor.ts
293
347
  var NumberEditor = class extends AbstractDXEditorWithInput {
348
+ constructor(parentCssSelector, elementCssSelector, driver) {
349
+ super(parentCssSelector, elementCssSelector, driver);
350
+ this.setClearStrategy(new InputClearStrategy());
351
+ }
294
352
  async getValue() {
295
353
  const value = await super.getInputValue();
296
354
  return value == "" ? null : Number.parseFloat(value);
@@ -300,16 +358,22 @@ var NumberEditor = class extends AbstractDXEditorWithInput {
300
358
  }
301
359
  };
302
360
 
361
+ // src/pageObjects/AbstractFormElement.ts
362
+ var AbstractFormElement = class extends AbstractElementWithParent {
363
+ constructor(parentCssSelector, elementCssSelector, driver) {
364
+ super(parentCssSelector, elementCssSelector, driver);
365
+ }
366
+ };
367
+
303
368
  // src/pageObjects/elements/Editors/CheckBox.ts
304
- var CheckBox = class extends AbstractFormElement {
369
+ var CheckBox = class extends AbstractElementWithParent {
305
370
  async getValue() {
306
- const inputEl = await this.getElement();
307
- const result = await inputEl.getAttribute("aria-checked");
371
+ const result = await this.getAttribute("aria-checked");
308
372
  if (result === "true")
309
- return true;
373
+ return 1;
310
374
  if (result === "false")
311
- return false;
312
- return void 0;
375
+ return 0;
376
+ return null;
313
377
  }
314
378
  async setValue(value) {
315
379
  const inputEl = await this.getElement();
@@ -321,7 +385,7 @@ var CheckBox = class extends AbstractFormElement {
321
385
  };
322
386
 
323
387
  // src/pageObjects/elements/Editors/SelectBoxEditor.ts
324
- var import_selenium_webdriver8 = require("selenium-webdriver");
388
+ var import_selenium_webdriver10 = require("selenium-webdriver");
325
389
 
326
390
  // src/utils/xpathHelper.ts
327
391
  var XPathHelper = class {
@@ -333,24 +397,50 @@ var XPathHelper = class {
333
397
  }
334
398
  };
335
399
 
400
+ // src/pageObjects/elements/Editors/ClearStrategy/ClearButtonStrategy.ts
401
+ var import_selenium_webdriver9 = require("selenium-webdriver");
402
+ var DX_TEXTEDITOR_EMPTY = "dx-texteditor-empty";
403
+ var DX_CLEAR_BUTTON_AREA = "dx-clear-button-area";
404
+ var ClearButtonStrategy = class {
405
+ editorContainerClass;
406
+ _driver;
407
+ constructor(editorContainerClass, driver) {
408
+ this.editorContainerClass = editorContainerClass;
409
+ this._driver = driver;
410
+ }
411
+ async isEmptyEditorField() {
412
+ const editorContainer = await this._driver.findElement(import_selenium_webdriver9.By.css(this.editorContainerClass));
413
+ const classAttribute = await editorContainer.getAttribute("class");
414
+ return classAttribute.includes(DX_TEXTEDITOR_EMPTY);
415
+ }
416
+ async clear() {
417
+ if (await this.isEmptyEditorField()) {
418
+ throw new Error("This field is already empty");
419
+ }
420
+ const clearBtnSelector = `${this.editorContainerClass} .${DX_CLEAR_BUTTON_AREA}`;
421
+ const clearBtn = await this._driver.findElement(import_selenium_webdriver9.By.css(clearBtnSelector));
422
+ await click(clearBtn, this._driver);
423
+ }
424
+ };
425
+
336
426
  // src/pageObjects/elements/Editors/SelectBoxEditor.ts
337
427
  var SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS = "d5-multi-select-item";
338
428
  var SELECT_BOX_ELEMENT_ROLE = "option";
429
+ var combinedValueXpath = (value) => `${XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE)}${XPathHelper.getClassAndValueXpath(
430
+ SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS,
431
+ value
432
+ )}`;
339
433
  var SelectBoxEditor = class extends AbstractDXEditorWithInput {
434
+ constructor(parentCssSelector, elementCssSelector, driver) {
435
+ super(parentCssSelector, elementCssSelector, driver);
436
+ this.setClearStrategy(new ClearButtonStrategy(this.getFullCssSelector(), this.driver));
437
+ }
340
438
  async setSelectInputValue(value) {
341
439
  const inputEl = await this.getInputElement();
342
440
  await click(inputEl, this.driver);
343
- await inputEl.sendKeys(value, import_selenium_webdriver8.Key.ENTER);
344
- const combinedValueXpath = XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE) + XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value);
345
- await this.driver.wait(async () => {
346
- try {
347
- const optElement = await inputEl.findElement(import_selenium_webdriver8.By.xpath(combinedValueXpath));
348
- await click(optElement, this.driver);
349
- return true;
350
- } catch (e) {
351
- return false;
352
- }
353
- }, 2e3);
441
+ await inputEl.sendKeys(value, import_selenium_webdriver10.Key.ENTER);
442
+ const optElement = await inputEl.findElement(import_selenium_webdriver10.By.xpath(combinedValueXpath(value)));
443
+ await click(optElement, this.driver);
354
444
  }
355
445
  async getValue() {
356
446
  const value = await super.getInputValue();
@@ -362,15 +452,14 @@ var SelectBoxEditor = class extends AbstractDXEditorWithInput {
362
452
  };
363
453
 
364
454
  // src/pageObjects/elements/Editors/SwitchEditor.ts
365
- var SwitchEditor = class extends AbstractFormElement {
455
+ var SwitchEditor = class extends AbstractElementWithParent {
366
456
  async getValue() {
367
- const inputEl = await this.getElement();
368
- const result = await inputEl.getAttribute("aria-label");
457
+ const result = await this.getAttribute("aria-label");
369
458
  if (result === "ON")
370
459
  return 1;
371
460
  if (result === "OFF")
372
461
  return 0;
373
- return void 0;
462
+ return null;
374
463
  }
375
464
  async setValue(value) {
376
465
  if (value !== 0 && value !== 1) {
@@ -378,31 +467,196 @@ var SwitchEditor = class extends AbstractFormElement {
378
467
  }
379
468
  const inputEl = await this.getElement();
380
469
  const currentValue = await this.getValue();
381
- if (currentValue !== value) {
382
- await click(inputEl, this.driver);
383
- await this.driver.wait(async () => {
384
- const updatedValue = await this.getValue();
385
- return updatedValue !== currentValue;
386
- });
470
+ if (currentValue === value) {
471
+ return;
472
+ }
473
+ await click(inputEl, this.driver);
474
+ await wait(async () => {
475
+ const updatedValue = await this.getValue();
476
+ return updatedValue !== currentValue;
477
+ }, this.driver);
478
+ }
479
+ };
480
+
481
+ // src/pageObjects/elements/Editors/TagBox.ts
482
+ var import_selenium_webdriver11 = require("selenium-webdriver");
483
+ var TAGS_SELECTOR = ".dx-tag .tag-text";
484
+ var DX_TAG_CONTAINER = "dx-tag-container";
485
+ var DX_TEXTEDITOR_EMPTY2 = "dx-texteditor-empty";
486
+ var BTN_OK_SELECTOR = ".dx-tagbox-popup-wrapper .dx-popup-bottom .dx-button.dx-popup-done";
487
+ var TagBox = class extends AbstractDXEditorWithInput {
488
+ constructor(parentCssSelector, elementCssSelector, driver) {
489
+ super(parentCssSelector, elementCssSelector, driver);
490
+ this.setClearStrategy(new ClearButtonStrategy(this.getFullCssSelector(), this.driver));
491
+ }
492
+ async setTagBoxInputValue(values) {
493
+ const lastElement = values[values.length - 1];
494
+ const inputEl = await this.getInputElement();
495
+ await inputEl.click();
496
+ for (const value of values) {
497
+ await this.selectOption(inputEl, value, lastElement);
498
+ }
499
+ await this.confirmSelection();
500
+ }
501
+ async selectOption(inputEl, value, lastElement) {
502
+ await inputEl.sendKeys(value);
503
+ const optElement = await inputEl.findElement(import_selenium_webdriver11.By.xpath(combinedValueXpath(value)));
504
+ await click(optElement, this.driver);
505
+ if (value !== lastElement) {
506
+ await inputEl.clear();
507
+ }
508
+ }
509
+ async confirmSelection() {
510
+ const inputEl = await this.getInputElement();
511
+ const option = await inputEl.findElement(import_selenium_webdriver11.By.xpath(XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE)));
512
+ const btnOk = await this.driver.findElement(import_selenium_webdriver11.By.css(BTN_OK_SELECTOR));
513
+ await wait(async () => {
514
+ return await option.getAttribute("aria-selected") === "true";
515
+ }, this.driver);
516
+ await click(btnOk, this.driver);
517
+ }
518
+ async getTagBoxInputValue() {
519
+ if (await this.isTagBoxEmpty()) {
520
+ return [];
521
+ }
522
+ const tags = await this.driver.findElements(import_selenium_webdriver11.By.css(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER} ${TAGS_SELECTOR}`));
523
+ const values = [];
524
+ for (const tag of tags) {
525
+ const text = await tag.getText();
526
+ values.push(text);
527
+ }
528
+ return values;
529
+ }
530
+ async isTagBoxEmpty() {
531
+ const classAttribute = await this.getClasses();
532
+ return classAttribute.includes(DX_TEXTEDITOR_EMPTY2);
533
+ }
534
+ async getValue() {
535
+ const value = await this.getTagBoxInputValue();
536
+ return value.length ? value : null;
537
+ }
538
+ async setValue(values) {
539
+ if (!Array.isArray(values)) {
540
+ throw new Error("The provided value is not an array");
541
+ }
542
+ await this.setTagBoxInputValue(values);
543
+ }
544
+ async remove(itemText) {
545
+ const tagValues = await this.getValue();
546
+ const tagExists = tagValues.includes(itemText);
547
+ if (!tagExists) {
548
+ throw new Error(`The tag with the text: ${itemText} was not found`);
549
+ }
550
+ const clearBtnTestId = byTestIdCssSelector(`clear-button-${itemText}`);
551
+ const clearBtn = await this.driver.findElement(import_selenium_webdriver11.By.css(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER} ${clearBtnTestId}`));
552
+ await click(clearBtn, this.driver);
553
+ }
554
+ };
555
+
556
+ // src/pageObjects/elements/Editors/ButtonGroup.ts
557
+ var import_selenium_webdriver12 = require("selenium-webdriver");
558
+ var ITEM_CLASS = "dx-buttongroup-item";
559
+ var SELECTED_CLASS = "dx-state-selected";
560
+ var ButtonGroup = class extends AbstractElementWithParent {
561
+ getItems() {
562
+ return this.driver.findElements(import_selenium_webdriver12.By.css(`${this.getFullCssSelector()} .${ITEM_CLASS}`));
563
+ }
564
+ getDataValue(el) {
565
+ return el.getAttribute("data-value");
566
+ }
567
+ async getValue() {
568
+ const selectedEl = await this.driver.findElement(import_selenium_webdriver12.By.css(`${this.getFullCssSelector()} .${ITEM_CLASS}.${SELECTED_CLASS}`));
569
+ return this.getDataValue(selectedEl);
570
+ }
571
+ async setValue(value) {
572
+ const items = await this.getItems();
573
+ let buttonEl = void 0;
574
+ for (const item of items) {
575
+ const text = await this.getDataValue(item);
576
+ if (text == value) {
577
+ buttonEl = item;
578
+ break;
579
+ }
387
580
  }
581
+ if (!buttonEl)
582
+ throw new Error(`Cannot find item in button group with text: ${value}`);
583
+ await click(buttonEl, this.driver);
584
+ }
585
+ };
586
+
587
+ // src/pageObjects/elements/Editors/BooleanSelector.ts
588
+ var BooleanSelector = class extends ButtonGroup {
589
+ // @ts-ignore
590
+ async getValue() {
591
+ const value = await super.getValue();
592
+ return value === "null" ? null : value === "1" ? 1 : 0;
593
+ }
594
+ // @ts-ignore
595
+ async setValue(value) {
596
+ const val = value == null ? "null" : value ? "1" : "0";
597
+ await super.setValue(val);
598
+ }
599
+ };
600
+
601
+ // src/pageObjects/elements/Editors/DateEditor.ts
602
+ var import_selenium_webdriver13 = require("selenium-webdriver");
603
+ var DateEditor = class extends AbstractDXEditorWithInput {
604
+ constructor(parentCssSelector, elementCssSelector, driver) {
605
+ super(parentCssSelector, elementCssSelector, driver);
606
+ this.setClearStrategy(new InputClearStrategy());
607
+ }
608
+ async getDateElement() {
609
+ return this.driver.findElement(import_selenium_webdriver13.By.css(this.getFullCssSelector() + " .dx-dropdowneditor-input-wrapper input[type=hidden]"));
610
+ }
611
+ async setDateValue(value) {
612
+ const dateEl = await this.getInputElement();
613
+ const stringDate = value.toJSON().split("T")[0];
614
+ const dateArr = stringDate.split("-");
615
+ const [year, month, day] = dateArr;
616
+ const keys = day + month + year;
617
+ await click(dateEl, this.driver);
618
+ const actions = this.driver.actions({ async: true });
619
+ await actions.move({ origin: dateEl }).sendKeys(import_selenium_webdriver13.Key.HOME).perform();
620
+ await actions.move({ origin: dateEl }).sendKeys(keys, import_selenium_webdriver13.Key.ENTER).perform();
621
+ }
622
+ async getDateValue() {
623
+ const inputEl = await this.getDateElement();
624
+ return inputEl.getAttribute("value");
625
+ }
626
+ async getValue() {
627
+ const value = await this.getDateValue();
628
+ return value == "" ? null : new Date(value);
629
+ }
630
+ setValue(value) {
631
+ if (typeof value === "object") {
632
+ return this.setDateValue(value);
633
+ }
634
+ throw new Error(`Value is incorrect. It should be Object`);
388
635
  }
389
636
  };
390
637
 
391
638
  // src/pageObjects/elements/Editors/editorFactory.ts
392
- var editorFactory = async (getParentElement, elementBy, driver) => {
393
- const elementInstance = new AbstractFormElement(getParentElement, elementBy, driver);
394
- const element = await elementInstance.getElement();
395
- const classSting = await element.getAttribute("class");
639
+ var editorFactory = async (parentCssSelector, elementCssSelector, driver) => {
640
+ const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
641
+ const classSting = await elementInstance.getClasses();
396
642
  if (classSting.includes("text-control"))
397
- return new TextEditor(getParentElement, elementBy, driver);
643
+ return new TextEditor(parentCssSelector, elementCssSelector, driver);
398
644
  if (classSting.includes("number-control"))
399
- return new NumberEditor(getParentElement, elementBy, driver);
645
+ return new NumberEditor(parentCssSelector, elementCssSelector, driver);
400
646
  if (classSting.includes("check-box"))
401
- return new CheckBox(getParentElement, elementBy, driver);
647
+ return new CheckBox(parentCssSelector, elementCssSelector, driver);
648
+ if (classSting.includes("multi-select-control"))
649
+ return new TagBox(parentCssSelector, elementCssSelector, driver);
402
650
  if (classSting.includes("select-control"))
403
- return new SelectBoxEditor(getParentElement, elementBy, driver);
651
+ return new SelectBoxEditor(parentCssSelector, elementCssSelector, driver);
404
652
  if (classSting.includes("switch-control"))
405
- return new SwitchEditor(getParentElement, elementBy, driver);
653
+ return new SwitchEditor(parentCssSelector, elementCssSelector, driver);
654
+ if (classSting.includes("date-control"))
655
+ return new DateEditor(parentCssSelector, elementCssSelector, driver);
656
+ if (classSting.includes("buttons-group"))
657
+ return new BooleanSelector(parentCssSelector, elementCssSelector, driver);
658
+ if (classSting.includes("button-group-field"))
659
+ return new ButtonGroup(parentCssSelector, elementCssSelector, driver);
406
660
  throw new Error("Unknown type of editor. Please write ticket to the support");
407
661
  };
408
662
 
@@ -413,6 +667,9 @@ function createDataTestId(formName, itemType, itemName) {
413
667
  function createFieldTestId(formName, itemName) {
414
668
  return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
415
669
  }
670
+ function createGroupTestId(formName, itemName) {
671
+ return createDataTestId(formName, "group" /* GROUP */, itemName);
672
+ }
416
673
  function createTableId(formName) {
417
674
  return `${"table" /* TABLE */}-${formName}`;
418
675
  }
@@ -420,13 +677,12 @@ function createTableId(formName) {
420
677
  // src/pageObjects/elements/FormField.ts
421
678
  var FormField = class extends AbstractElementWithParent {
422
679
  editor;
423
- constructor(getParentElement, formName, name, driver) {
424
- super(getParentElement, driver);
425
- this.elementBy = byTestId(createFieldTestId(formName, name));
680
+ constructor(parentCssSelector, formName, name, driver) {
681
+ super(parentCssSelector, byTestIdCssSelector(createFieldTestId(formName, name)), driver);
426
682
  }
427
683
  async initEditor() {
428
684
  if (!this.editor) {
429
- this.editor = await editorFactory(this.getParentElement, this.elementBy, this.driver);
685
+ this.editor = await editorFactory(this.parentCssSelector, this.elementCssSelector, this.driver);
430
686
  }
431
687
  }
432
688
  /**
@@ -449,14 +705,85 @@ var FormField = class extends AbstractElementWithParent {
449
705
  await this.initEditor();
450
706
  return this.editor.setValue(value);
451
707
  }
708
+ /**
709
+ * Очищает значение в поле
710
+ * @example
711
+ * await formEdit.field('NumberFld').clear();
712
+ */
713
+ async clear() {
714
+ await this.initEditor();
715
+ if (!this.editor.clear) {
716
+ throw new Error("The clear method is not available for this field type.");
717
+ }
718
+ return this.editor.clear();
719
+ }
720
+ /**
721
+ * Удаляет тег по переданному тексту
722
+ * @example
723
+ * await formEdit.field('TagBox').remove('test');
724
+ */
725
+ async remove(itemText) {
726
+ await this.initEditor();
727
+ if (!this.editor.remove) {
728
+ throw new Error("This method is only available for the TagBox field.");
729
+ }
730
+ return this.editor.remove(itemText);
731
+ }
732
+ };
733
+
734
+ // src/pageObjects/elements/Groups/AbstractGroup.ts
735
+ var AbstractGroup = class extends AbstractElementWithParent {
736
+ async isDisplayed() {
737
+ const groupElement = await this.getElement();
738
+ return await groupElement.isDisplayed();
739
+ }
740
+ };
741
+
742
+ // src/pageObjects/elements/Groups/Panel.ts
743
+ var Panel = class extends AbstractGroup {
744
+ };
745
+
746
+ // src/pageObjects/elements/Groups/groupFactory.ts
747
+ var groupFactory = async (parentCssSelector, elementCssSelector, driver) => {
748
+ const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
749
+ const classSting = await elementInstance.getClasses();
750
+ if (classSting.includes("panel-group"))
751
+ return new Panel(parentCssSelector, elementCssSelector, driver);
752
+ throw new Error("Unknown type of group. Please write ticket to the support");
753
+ };
754
+
755
+ // src/pageObjects/elements/FormGroup.ts
756
+ var FormGroup = class extends AbstractElementWithParent {
757
+ editor;
758
+ constructor(parentCssSelector, formName, name, driver) {
759
+ super(parentCssSelector, byTestIdCssSelector(createGroupTestId(formName, name)), driver);
760
+ }
761
+ async initEditor() {
762
+ if (!this.editor) {
763
+ this.editor = await groupFactory(this.parentCssSelector, this.elementCssSelector, this.driver);
764
+ }
765
+ }
766
+ /**
767
+ * Возвращает булевое значение доступна ли группа
768
+ * @example
769
+ * expect(await tableList.group('MainSuperPanel').isDisplayed();
770
+ */
771
+ async isDisplayed() {
772
+ try {
773
+ await this.initEditor();
774
+ return this.editor.isDisplayed();
775
+ } catch {
776
+ return false;
777
+ }
778
+ }
452
779
  };
453
780
 
454
781
  // src/pageObjects/elements/Forms/FormEdit.ts
455
782
  var FormEdit = class extends AbstractForm {
456
- saveButtonBy = import_selenium_webdriver9.By.id("button-save");
783
+ saveButtonBy = import_selenium_webdriver14.By.id("button-save");
457
784
  constructor(driver) {
458
785
  super(driver);
459
- this.popupContainerBy = import_selenium_webdriver9.By.className(`popup form-edit-${this.formName}`);
786
+ this.popupContainerCssSelector = `.popup .form-edit-${this.formName}`;
460
787
  }
461
788
  /**
462
789
  * Находит поле формы редактирования по имени
@@ -466,7 +793,29 @@ var FormEdit = class extends AbstractForm {
466
793
  * expect(await formEdit.field('Name').getValue()).toBe('test value');
467
794
  */
468
795
  field(name) {
469
- return new FormField(this.getContainerElement, this.formName, name, this.driver);
796
+ return new FormField(this.containerCssSelector, this.formName, name, this.driver);
797
+ }
798
+ /**
799
+ * Проверяет не отключена ли кнопка Сохранить
800
+ * @example
801
+ * const formEdit = new MyForm();
802
+ * //...
803
+ * await formEdit.isSaveButtonDisabled();
804
+ */
805
+ async isSaveButtonDisabled() {
806
+ const saveButton = await this.driver.findElement(this.saveButtonBy);
807
+ const result = await saveButton.getAttribute("aria-disabled");
808
+ return result === "true";
809
+ }
810
+ /**
811
+ * Находит группу формы редактирования по имени
812
+ * @example
813
+ * const formEdit = new MyForm();
814
+ * //...
815
+ * expect(await formEdit.group('Name');
816
+ */
817
+ group(name) {
818
+ return new FormGroup(this.containerCssSelector, this.formName, name, this.driver);
470
819
  }
471
820
  /**
472
821
  * Нажатие на кнопку Сохранить
@@ -476,145 +825,167 @@ var FormEdit = class extends AbstractForm {
476
825
  * await formEdit.saveButtonClick();
477
826
  */
478
827
  async saveButtonClick() {
479
- await click(await this.driver.findElement(this.saveButtonBy), this.driver);
828
+ const saveButton = await this.driver.findElement(this.saveButtonBy);
829
+ await wait(async () => !await this.isSaveButtonDisabled(), this.driver, "Button is disabled");
830
+ await click(saveButton, this.driver);
480
831
  }
481
832
  };
482
833
 
483
- // src/pageObjects/elements/Forms/ListForm.ts
484
- var import_selenium_webdriver15 = require("selenium-webdriver");
485
-
486
834
  // src/pageObjects/elements/Table/Table.ts
487
- var import_selenium_webdriver12 = require("selenium-webdriver");
835
+ var import_selenium_webdriver18 = require("selenium-webdriver");
836
+
837
+ // src/pageObjects/elements/Table/elements/Row.ts
838
+ var import_selenium_webdriver16 = require("selenium-webdriver");
488
839
 
489
840
  // src/pageObjects/elements/Table/utils.ts
490
- var import_selenium_webdriver10 = require("selenium-webdriver");
491
- var getRowPathByIndex = (index) => {
492
- return import_selenium_webdriver10.By.css(`tr[aria-rowindex="${transformInputIndex(index)}"]`);
493
- };
494
- var getColumnPathByIndex = (index) => {
495
- return import_selenium_webdriver10.By.css(`td[aria-colindex="${transformInputIndex(index)}"]`);
496
- };
497
- var getColumnPathByCaption = (caption) => {
498
- return import_selenium_webdriver10.By.css(`td[role="columnheader"][aria-label="Column ${caption}"]`);
499
- };
500
- var getCellPathByIndex = (index) => {
501
- return import_selenium_webdriver10.By.css(`td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`);
502
- };
841
+ var import_selenium_webdriver15 = require("selenium-webdriver");
842
+ function getCssRowByIndexSelector(index) {
843
+ return `tr[aria-rowindex="${transformInputIndex(index)}"]`;
844
+ }
845
+ var getColumnByIndexCssSelector = (columnIndex) => `td[aria-colindex="${transformInputIndex(columnIndex)}"]`;
846
+ var getColumnByCaptionCssSelector = (caption) => `td[role="columnheader"][aria-label="Column ${caption}"]`;
847
+ function getCssCellByIndexSelector(index) {
848
+ return `td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`;
849
+ }
503
850
  var transformInputIndex = (index) => index + 1;
504
851
  var transformOutputIndex = (index) => +index - 1;
505
852
 
506
- // src/pageObjects/elements/Table/elements/Row.ts
507
- var import_selenium_webdriver11 = require("selenium-webdriver");
508
-
509
853
  // src/pageObjects/elements/Table/elements/Cell.ts
510
854
  var Cell = class extends AbstractElementWithParent {
511
- index;
512
- constructor(rowEl, index, driver) {
513
- super(() => Promise.resolve(rowEl), driver);
514
- this.index = index;
515
- this.elementBy = getCellPathByIndex(index);
855
+ _index;
856
+ getCellIndex;
857
+ constructor(parentCssSelector, getCellIndex, index, driver) {
858
+ super(parentCssSelector, getCssCellByIndexSelector(index), driver);
859
+ this.getCellIndex = getCellIndex;
860
+ this._index = index;
861
+ }
862
+ set index(index) {
863
+ this._index = index;
864
+ this.elementCssSelector = getCssCellByIndexSelector(index);
865
+ }
866
+ async getElement() {
867
+ if (this._index == null) {
868
+ this.index = await this.getCellIndex();
869
+ }
870
+ return super.getElement();
516
871
  }
517
872
  async getValue() {
518
873
  const cellEl = await this.getElement();
519
874
  return cellEl.getText();
520
875
  }
521
876
  getIndex() {
522
- return this.index;
877
+ return this._index;
523
878
  }
524
879
  };
525
880
 
526
881
  // src/pageObjects/elements/Table/elements/Row.ts
527
882
  var DX_SELECTION_CLASS = "dx-selection";
528
883
  var DX_ROW_EDIT_CLASS = "dx-edit-row";
884
+ var DX_DATA_ROW_CLASS = "dx-data-row";
529
885
  var Row = class extends AbstractElementWithParent {
530
886
  index;
531
887
  getColumnByCaption;
532
- constructor(getParentElement, index, driver, getColumnByCaption) {
533
- super(getParentElement, driver);
888
+ constructor(parentCssSelector, index, driver, getColumnByCaption) {
889
+ super(parentCssSelector, getCssRowByIndexSelector(index), driver);
534
890
  this.index = index;
535
- this.elementBy = getRowPathByIndex(index);
536
891
  this.getColumnByCaption = getColumnByCaption;
537
892
  }
538
- async getCellByIndex(index) {
539
- const rowEl = await this.getElement();
540
- const cell = rowEl.findElement(getCellPathByIndex(index));
541
- if (cell) {
542
- return new Cell(rowEl, index, this.driver);
543
- }
544
- throw new Error(`Cannot find cell by index: ${index}`);
893
+ _getCell(index, caption) {
894
+ return new Cell(this.getFullCssSelector(), () => {
895
+ return this.getColumnByCaption(caption).getIndex();
896
+ }, index, this.driver);
545
897
  }
546
- async getCell(caption) {
547
- const column = await this.getColumnByCaption(caption);
548
- if (column) {
549
- const index = column.getIndex();
550
- return this.getCellByIndex(index);
551
- }
552
- throw new Error("Unknown caption of cell");
898
+ getCellByIndex(index) {
899
+ return this._getCell(index);
900
+ }
901
+ getCell(caption) {
902
+ return this._getCell(void 0, caption);
553
903
  }
554
904
  async select() {
555
905
  const rowEl = await this.getElement();
556
906
  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);
907
+ await wait(async () => {
908
+ const classes = await this.getClasses();
909
+ return classes.includes(DX_SELECTION_CLASS);
910
+ }, this.driver, "Cannot select row");
563
911
  }
564
912
  async isSelected() {
565
- const rowEl = await this.getElement();
566
- const result = await rowEl.getAttribute("aria-selected");
913
+ const result = await this.getAttribute("aria-selected");
567
914
  return result === "true";
568
915
  }
569
916
  getIndex() {
570
917
  return this.index;
571
918
  }
572
919
  async getCells() {
573
- const rowEl = await this.getElement();
574
- const cells = await rowEl.findElements(import_selenium_webdriver11.By.css(`td[role="gridcell"]`));
920
+ const cells = await this.driver.findElements(import_selenium_webdriver16.By.css(`${this.getFullCssSelector()} td[role="gridcell"]`));
575
921
  const result = [];
576
922
  cells.forEach((_, index) => {
577
- const newCell = new Cell(rowEl, index, this.driver);
923
+ const newCell = this.getCellByIndex(index);
578
924
  result.push(newCell);
579
925
  });
580
926
  return result;
581
927
  }
582
- async clickInlineButton(rowClass, buttonClass) {
583
- const fixedTable = (await this.getParentElement()).findElement(
584
- import_selenium_webdriver11.By.css(".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed")
585
- );
586
- const rowEl = await fixedTable.findElement(import_selenium_webdriver11.By.className(rowClass));
587
- const button = await rowEl.findElement(import_selenium_webdriver11.By.className(buttonClass));
588
- if (button) {
589
- return click(button, this.driver);
590
- }
591
- throw new Error(`Cannot find ${buttonClass} button`);
928
+ async clickInlineButton(buttonClass) {
929
+ const FIXED_TABLE_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
930
+ const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(this.index)}"] .${buttonClass}`;
931
+ const button = await this.driver.findElement(import_selenium_webdriver16.By.css(`${this.parentCssSelector} ${FIXED_TABLE_CSS_SELECTOR} ${buttonCssSelector}`));
932
+ return click(button, this.driver);
933
+ }
934
+ async checkEditingMode(isEditing, msg) {
935
+ await wait(async () => {
936
+ return (await this.getClasses()).includes(DX_ROW_EDIT_CLASS) === isEditing;
937
+ }, this.driver, msg);
592
938
  }
593
939
  async edit() {
594
- await this.select();
595
- return this.clickInlineButton(DX_SELECTION_CLASS, "edit");
940
+ await this.clickInlineButton("edit");
941
+ await this.checkEditingMode(true, "Row did not switch to edit mode");
596
942
  }
597
943
  async save() {
598
- return this.clickInlineButton(DX_ROW_EDIT_CLASS, "save");
944
+ await this.clickInlineButton("save");
945
+ await this.checkEditingMode(false, "Row did not saved");
599
946
  }
600
947
  async cancel() {
601
- return this.clickInlineButton(DX_ROW_EDIT_CLASS, "cancel");
948
+ await this.clickInlineButton("cancel");
949
+ await this.checkEditingMode(false, "Row did not switch to normal mode");
602
950
  }
603
951
  };
604
952
 
605
953
  // src/pageObjects/elements/Table/elements/Column.ts
954
+ var import_selenium_webdriver17 = require("selenium-webdriver");
955
+ var getHeaderCssSelector = () => {
956
+ return ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
957
+ };
606
958
  var Column = class extends AbstractElementWithParent {
607
- index;
608
- constructor(getParentElement, index, driver) {
609
- super(getParentElement, driver);
959
+ _index;
960
+ _caption;
961
+ constructor(parentCssSelector, caption, index, driver) {
962
+ super(parentCssSelector, "", driver);
610
963
  this.index = index;
611
- this.elementBy = getColumnPathByIndex(index);
964
+ this._caption = caption;
965
+ }
966
+ set index(index) {
967
+ this._index = index;
968
+ this.elementCssSelector = getColumnByIndexCssSelector(index);
969
+ }
970
+ get index() {
971
+ return this._index;
972
+ }
973
+ async getElement() {
974
+ await this.getIndex();
975
+ return super.getElement();
976
+ }
977
+ async getIndexByCaption() {
978
+ const column = await this.driver.findElement(import_selenium_webdriver17.By.css(`${this.parentCssSelector} ${getHeaderCssSelector()} ${getColumnByCaptionCssSelector(this._caption)}`));
979
+ return transformOutputIndex(await column.getAttribute("aria-colindex"));
612
980
  }
613
981
  async caption() {
614
982
  const el = await this.getElement();
615
983
  return el.getText();
616
984
  }
617
- getIndex() {
985
+ async getIndex() {
986
+ if (this.index == null) {
987
+ this.index = await this.getIndexByCaption();
988
+ }
618
989
  return this.index;
619
990
  }
620
991
  };
@@ -622,71 +993,36 @@ var Column = class extends AbstractElementWithParent {
622
993
  // src/pageObjects/elements/Table/Table.ts
623
994
  var Table = class extends AbstractElementWithParent {
624
995
  formName;
625
- constructor(getParentElement, formName, driver) {
626
- super(getParentElement, driver);
627
- this.elementBy = import_selenium_webdriver12.By.id(createTableId(formName));
996
+ constructor(parentCssSelector, formName, driver) {
997
+ super(parentCssSelector, `#${createTableId(formName)}`, driver);
628
998
  this.formName = formName;
629
999
  }
630
- async getHeaderElement() {
631
- const parentEl = await this.getElement();
632
- return parentEl.findElement(import_selenium_webdriver12.By.className("dx-header-row"));
1000
+ getRowByIndex(index) {
1001
+ return new Row(this.getFullCssSelector(), index, this.driver, this.getColumnByCaption.bind(this));
633
1002
  }
634
- async getDataGrid() {
635
- const parentEl = await this.getElement();
636
- return parentEl.findElement(import_selenium_webdriver12.By.css(`div[role="grid"]`));
1003
+ getColumnByIndex(index) {
1004
+ return new Column(this.getFullCssSelector(), void 0, index, this.driver);
637
1005
  }
638
- getTableElement = () => {
639
- return this.driver.findElement(this.elementBy);
1006
+ getColumnByCaption = (caption) => {
1007
+ return new Column(this.getFullCssSelector(), caption, void 0, this.driver);
640
1008
  };
641
- async getRowByIndex(index) {
642
- const gridContainer = await this.getDataGrid();
643
- const row = await gridContainer.findElement(getRowPathByIndex(index));
644
- if (row) {
645
- return new Row(this.getTableElement, index, this.driver, this.getColumnByCaption.bind(this));
646
- }
647
- throw new Error(`Cannot find row by index: ${index}`);
648
- }
649
- async getColumnByIndex(index) {
650
- const headerContainer = await this.getHeaderElement();
651
- const column = await headerContainer.findElement(getColumnPathByIndex(index));
652
- if (column) {
653
- return new Column(this.getTableElement, index, this.driver);
654
- }
655
- throw new Error(`Cannot find column by index: ${index}`);
656
- }
657
- async getColumnByCaption(caption) {
658
- const headerContainer = await this.getHeaderElement();
659
- const column = await headerContainer.findElement(getColumnPathByCaption(caption));
660
- if (column) {
661
- const index = await column.getAttribute("aria-colindex");
662
- return new Column(this.getTableElement, transformOutputIndex(index), this.driver);
663
- }
664
- throw new Error(`Cannot find column by caption: ${caption}`);
665
- }
666
- async selectRowByIndex(index) {
667
- const row = await this.getRowByIndex(index);
668
- if (row) {
669
- await row.select();
670
- } else {
671
- throw new Error(`Cannot find row by index: ${index}`);
672
- }
1009
+ selectRowByIndex(index) {
1010
+ return this.getRowByIndex(index).select();
673
1011
  }
674
1012
  async getRows() {
675
- const gridContainer = await this.getDataGrid();
676
- const rows = await gridContainer.findElements(import_selenium_webdriver12.By.className("dx-row dx-data-row"));
1013
+ const rows = await this.driver.findElements(import_selenium_webdriver18.By.css(`${this.getFullCssSelector()} .dx-row.dx-data-row`));
677
1014
  const result = [];
678
1015
  rows.forEach((_, index) => {
679
- const newRow = new Row(this.getTableElement, index, this.driver, this.getColumnByCaption.bind(this));
1016
+ const newRow = new Row(this.getFullCssSelector(), index, this.driver, this.getColumnByCaption);
680
1017
  result.push(newRow);
681
1018
  });
682
1019
  return result;
683
1020
  }
684
1021
  async getColumns() {
685
- const headerContainer = await this.getHeaderElement();
686
- const columns = await headerContainer.findElements(import_selenium_webdriver12.By.css(`td[role="columnheader"]`));
1022
+ const columns = await this.driver.findElements(import_selenium_webdriver18.By.css(`${this.getFullCssSelector()} ${getHeaderCssSelector()} td[role="columnheader"]`));
687
1023
  const result = [];
688
1024
  columns.forEach((_, index) => {
689
- const newCol = new Column(this.getTableElement, index, this.driver);
1025
+ const newCol = new Column(this.getFullCssSelector(), void 0, index, this.driver);
690
1026
  result.push(newCol);
691
1027
  });
692
1028
  return result;
@@ -702,49 +1038,39 @@ var Table = class extends AbstractElementWithParent {
702
1038
  * expect(await form.field('Name').getValue()).toBe('test value');
703
1039
  */
704
1040
  field(name) {
705
- return new FormField(this.getElement, this.formName, name, this.driver);
1041
+ return new FormField(this.getFullCssSelector(), this.formName, name, this.driver);
706
1042
  }
707
1043
  };
708
1044
 
709
- // src/pageObjects/elements/TableToolbar/TableToolbar.ts
710
- var import_selenium_webdriver14 = require("selenium-webdriver");
711
-
712
1045
  // src/pageObjects/elements/TableToolbar/TableToolbarButton.ts
713
- var import_selenium_webdriver13 = require("selenium-webdriver");
714
1046
  var TOOLBAR_BUTTON_CLASS = "toolbar-button";
715
1047
  var TableToolbarButton = class extends AbstractElementWithParent {
716
- constructor(getParentElement, name, driver) {
717
- super(getParentElement, driver);
718
- this.elementBy = import_selenium_webdriver13.By.id(`${TOOLBAR_BUTTON_CLASS}-${name}`);
1048
+ name;
1049
+ constructor(parentCssSelector, name, driver) {
1050
+ super(parentCssSelector, `#${TOOLBAR_BUTTON_CLASS}-${name}`, driver);
1051
+ this.name = name;
719
1052
  }
720
1053
  async click() {
721
1054
  const button = await this.getElement();
722
- return click(button, this.driver);
1055
+ await wait(async () => {
1056
+ return await button.isDisplayed() && !await this.isDisabled();
1057
+ }, this.driver, `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`);
1058
+ await click(button, this.driver);
723
1059
  }
724
1060
  async isDisabled() {
725
1061
  const button = await this.getElement();
726
- const result = await button.getAttribute("aria-disabled");
727
- return result === "true";
1062
+ return await button.getCssValue("pointer-events") === "none";
728
1063
  }
729
1064
  };
730
1065
 
731
1066
  // src/pageObjects/elements/TableToolbar/TableToolbar.ts
732
1067
  var TABLE_TOOLBAR_CLASS = "d5-table-toolbar";
733
1068
  var TableToolbar = class extends AbstractElementWithParent {
734
- constructor(getParentElement, formName, driver) {
735
- super(getParentElement, driver);
736
- this.elementBy = import_selenium_webdriver14.By.id(`${TABLE_TOOLBAR_CLASS}-${formName}`);
1069
+ constructor(parentCssSelector, formName, driver) {
1070
+ super(parentCssSelector, `#${TABLE_TOOLBAR_CLASS}-${formName}`, driver);
737
1071
  }
738
- getTableToolbarElement = () => {
739
- return this.driver.findElement(this.elementBy);
740
- };
741
- async button(name) {
742
- const toolbar = await this.getTableToolbarElement();
743
- const button = await toolbar.findElement(import_selenium_webdriver14.By.id(`${TOOLBAR_BUTTON_CLASS}-${name}`));
744
- if (button) {
745
- return new TableToolbarButton(this.getTableToolbarElement, name, this.driver);
746
- }
747
- throw new Error(`Cannot find button by name: ${name}`);
1072
+ button(name) {
1073
+ return new TableToolbarButton(this.getFullCssSelector(), name, this.driver);
748
1074
  }
749
1075
  };
750
1076
 
@@ -752,7 +1078,7 @@ var TableToolbar = class extends AbstractElementWithParent {
752
1078
  var ListForm = class extends AbstractForm {
753
1079
  constructor(driver) {
754
1080
  super(driver);
755
- this.popupContainerBy = import_selenium_webdriver15.By.className(`popup form-inline-${this.formName}`);
1081
+ this.popupContainerCssSelector = `.popup .form-inline-${this.formName}`;
756
1082
  }
757
1083
  /**
758
1084
  * Находит таблицу
@@ -762,7 +1088,17 @@ var ListForm = class extends AbstractForm {
762
1088
  * expect(listForm.table());
763
1089
  */
764
1090
  table() {
765
- return new Table(this.getContainerElement, this.formName, this.driver);
1091
+ return new Table(this.containerCssSelector, this.formName, this.driver);
1092
+ }
1093
+ /**
1094
+ * Находит группу на лист форме по имени
1095
+ * @example
1096
+ * const formEdit = new MyForm();
1097
+ * //...
1098
+ * expect(await formEdit.group('Name');
1099
+ */
1100
+ group(name) {
1101
+ return new FormGroup(this.containerCssSelector, this.formName, name, this.driver);
766
1102
  }
767
1103
  /**
768
1104
  * Находит таблицу
@@ -772,7 +1108,7 @@ var ListForm = class extends AbstractForm {
772
1108
  * expect(listForm.toolbarButton());
773
1109
  */
774
1110
  toolbarButton(name) {
775
- const toolbar = new TableToolbar(this.getContainerElement, this.formName, this.driver);
1111
+ const toolbar = new TableToolbar(this.containerCssSelector, this.formName, this.driver);
776
1112
  return toolbar.button(name);
777
1113
  }
778
1114
  };
@@ -800,6 +1136,14 @@ var LoginPage = class extends AbstractPage {
800
1136
  usernameField = byTestId("loginField", "input");
801
1137
  passwordField = byTestId("passwordField", "input");
802
1138
  loginButton = byTestId("loginButton");
1139
+ async locate() {
1140
+ await super.locate();
1141
+ const login = await this.driver.findElement(this.usernameField);
1142
+ await waitElementIsVisible({
1143
+ element: login,
1144
+ driver: this.driver
1145
+ });
1146
+ }
803
1147
  get path() {
804
1148
  return LOGIN_PATH;
805
1149
  }
@@ -832,10 +1176,13 @@ var LoginPage = class extends AbstractPage {
832
1176
  SubsystemsPanel,
833
1177
  TextEditor,
834
1178
  byTestId,
1179
+ byTestIdCssSelector,
835
1180
  click,
836
1181
  config,
837
1182
  createDriver,
838
1183
  editorFactory,
839
1184
  elementIsNotPresent,
840
- signIn
1185
+ signIn,
1186
+ wait,
1187
+ waitElementIsVisible
841
1188
  });