d5-testing-library 1.3.0 → 1.4.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.
- package/dist/cjs/d5-testing-library.cjs +558 -134
- package/dist/d5-testing-library.d.ts +102 -14
- package/dist/d5-testing-library.legacy-esm.js +553 -133
- package/dist/d5-testing-library.mjs +553 -133
- package/package.json +1 -1
|
@@ -73,6 +73,9 @@ var AbstractElement = class {
|
|
|
73
73
|
getFullCssSelector() {
|
|
74
74
|
return this.elementCssSelector;
|
|
75
75
|
}
|
|
76
|
+
joinRelativeCssSelectors(selectors) {
|
|
77
|
+
return selectors.join(" ");
|
|
78
|
+
}
|
|
76
79
|
async getElement() {
|
|
77
80
|
return this.driver.findElement(By.css(this.getFullCssSelector()));
|
|
78
81
|
}
|
|
@@ -125,6 +128,9 @@ var AbstractPage = class extends AbstractElement {
|
|
|
125
128
|
// src/utils/actions.ts
|
|
126
129
|
var click = async (webElement, driver) => {
|
|
127
130
|
driver = driver ?? config().driver;
|
|
131
|
+
if (!await webElement.isDisplayed()) {
|
|
132
|
+
await driver.executeScript("arguments[0].scrollIntoView(true);", webElement);
|
|
133
|
+
}
|
|
128
134
|
const actions = driver.actions({ async: true });
|
|
129
135
|
await actions.move({ origin: webElement }).click().perform();
|
|
130
136
|
};
|
|
@@ -137,6 +143,7 @@ var byTestIdCssSelector = (testId, element = "div") => {
|
|
|
137
143
|
var byTestId = (testId, element = "div") => {
|
|
138
144
|
return By2.css(byTestIdCssSelector(testId, element));
|
|
139
145
|
};
|
|
146
|
+
var readonlyLocator = "readonly";
|
|
140
147
|
|
|
141
148
|
// src/pageObjects/pages/LoginPage.ts
|
|
142
149
|
var LOGIN_PATH = "/login";
|
|
@@ -219,6 +226,11 @@ var AbstractElementWithParent = class extends AbstractElement {
|
|
|
219
226
|
}
|
|
220
227
|
return `${this.parentCssSelector} ${this.elementCssSelector}`;
|
|
221
228
|
}
|
|
229
|
+
async isReadonly() {
|
|
230
|
+
const fieldEl = await this.getElement();
|
|
231
|
+
const classSting = await fieldEl.getAttribute("class");
|
|
232
|
+
return classSting.includes(readonlyLocator);
|
|
233
|
+
}
|
|
222
234
|
};
|
|
223
235
|
|
|
224
236
|
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanelHeader.ts
|
|
@@ -244,7 +256,95 @@ var SubsystemsPanel = class extends AbstractElement {
|
|
|
244
256
|
};
|
|
245
257
|
|
|
246
258
|
// src/pageObjects/elements/Forms/AbstractForm.ts
|
|
259
|
+
import { By as By6 } from "selenium-webdriver";
|
|
260
|
+
|
|
261
|
+
// src/utils/createDataTestId.ts
|
|
262
|
+
function createDataTestId(formName, itemType, itemName) {
|
|
263
|
+
return `${formName}-${itemType}-${itemName}`;
|
|
264
|
+
}
|
|
265
|
+
function createFieldTestId(formName, itemName) {
|
|
266
|
+
return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
|
|
267
|
+
}
|
|
268
|
+
function createGroupTestId(formName, itemName) {
|
|
269
|
+
return createDataTestId(formName, "group" /* GROUP */, itemName);
|
|
270
|
+
}
|
|
271
|
+
function createFilterTestId(formName, itemName, layout) {
|
|
272
|
+
return createDataTestId(formName, "filter" /* FILTER */, itemName) + `-${layout}`;
|
|
273
|
+
}
|
|
274
|
+
function createDocFilterTestId(formName, itemName) {
|
|
275
|
+
return createFilterTestId(formName, itemName, "dock-panel-filter" /* DOCK_PANEL */);
|
|
276
|
+
}
|
|
277
|
+
function createLayoutFilterTestId(formName, itemName) {
|
|
278
|
+
return createFilterTestId(formName, itemName, "layout-filter" /* LAYOUT */);
|
|
279
|
+
}
|
|
280
|
+
function createTableId(formName) {
|
|
281
|
+
return `${"table" /* TABLE */}-${formName}`;
|
|
282
|
+
}
|
|
283
|
+
function createFormButtonTestId(formName, itemName) {
|
|
284
|
+
return createDataTestId(formName, "button" /* BUTTON */, itemName);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// src/utils/waitElementIsClickable.ts
|
|
288
|
+
async function waitElementIsClickable({
|
|
289
|
+
element,
|
|
290
|
+
timeout,
|
|
291
|
+
errorMessage,
|
|
292
|
+
driver
|
|
293
|
+
}) {
|
|
294
|
+
driver = driver ?? config().driver;
|
|
295
|
+
await wait(async () => {
|
|
296
|
+
const isDisabled = await element.getCssValue("pointer-events") === "none";
|
|
297
|
+
return await element.isDisplayed() && !isDisabled;
|
|
298
|
+
}, driver, errorMessage, timeout ?? config().timeout);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// src/pageObjects/elements/TableToolbar/AbstractButton.ts
|
|
302
|
+
var AbstractButton = class extends AbstractElementWithParent {
|
|
303
|
+
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
304
|
+
super(parentCssSelector, elementCssSelector, driver);
|
|
305
|
+
}
|
|
306
|
+
async click() {
|
|
307
|
+
const button = await this.getElement();
|
|
308
|
+
await waitElementIsClickable({
|
|
309
|
+
element: button,
|
|
310
|
+
errorMessage: this.buttonNotDisplayedError(),
|
|
311
|
+
driver: this.driver
|
|
312
|
+
});
|
|
313
|
+
await click(button, this.driver);
|
|
314
|
+
}
|
|
315
|
+
async isDisabled() {
|
|
316
|
+
const button = await this.getElement();
|
|
317
|
+
return await button.getCssValue("pointer-events") === "none";
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// src/pageObjects/elements/DXComponents/DXButton.ts
|
|
247
322
|
import { By as By5 } from "selenium-webdriver";
|
|
323
|
+
var DXButton = class extends AbstractButton {
|
|
324
|
+
async getText() {
|
|
325
|
+
const classes = await this.getClasses();
|
|
326
|
+
if (!classes.includes("dx-button-has-text")) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const el = await this.getElement();
|
|
330
|
+
const textEl = el.findElement(By5.className("dx-button-text"));
|
|
331
|
+
return await textEl.getText();
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
// src/pageObjects/elements/FormButton.ts
|
|
336
|
+
var FormButton = class extends DXButton {
|
|
337
|
+
name;
|
|
338
|
+
constructor(parentCssSelector, formName, name, driver) {
|
|
339
|
+
super(parentCssSelector, byTestIdCssSelector(createFormButtonTestId(formName, name)), driver);
|
|
340
|
+
this.name = name;
|
|
341
|
+
}
|
|
342
|
+
buttonNotDisplayedError() {
|
|
343
|
+
return `Form Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/pageObjects/elements/Forms/AbstractForm.ts
|
|
248
348
|
var AbstractForm = class extends AbstractPage {
|
|
249
349
|
containerCssSelector = "";
|
|
250
350
|
containerBy;
|
|
@@ -291,42 +391,22 @@ var AbstractForm = class extends AbstractPage {
|
|
|
291
391
|
*/
|
|
292
392
|
async getTitleText() {
|
|
293
393
|
if (await this.isModal()) {
|
|
294
|
-
const titleEl2 = await this.driver.findElement(
|
|
394
|
+
const titleEl2 = await this.driver.findElement(By6.css(`${this.popupContainerCssSelector} .popup-title`));
|
|
295
395
|
return titleEl2.getText();
|
|
296
396
|
}
|
|
297
|
-
let titleEl = await this.driver.findElement(
|
|
397
|
+
let titleEl = await this.driver.findElement(By6.className("main-toolbar-form-title"));
|
|
298
398
|
return titleEl.getText();
|
|
299
399
|
}
|
|
400
|
+
button(name) {
|
|
401
|
+
return new FormButton(this.containerCssSelector, this.formName, name, this.driver);
|
|
402
|
+
}
|
|
300
403
|
};
|
|
301
404
|
|
|
302
405
|
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
303
|
-
import { By as
|
|
304
|
-
|
|
305
|
-
// src/utils/createDataTestId.ts
|
|
306
|
-
function createDataTestId(formName, itemType, itemName) {
|
|
307
|
-
return `${formName}-${itemType}-${itemName}`;
|
|
308
|
-
}
|
|
309
|
-
function createFieldTestId(formName, itemName) {
|
|
310
|
-
return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
|
|
311
|
-
}
|
|
312
|
-
function createGroupTestId(formName, itemName) {
|
|
313
|
-
return createDataTestId(formName, "group" /* GROUP */, itemName);
|
|
314
|
-
}
|
|
315
|
-
function createFilterTestId(formName, itemName, layout) {
|
|
316
|
-
return createDataTestId(formName, "filter" /* FILTER */, itemName) + `-${layout}`;
|
|
317
|
-
}
|
|
318
|
-
function createDocFilterTestId(formName, itemName) {
|
|
319
|
-
return createFilterTestId(formName, itemName, "dock-panel-filter" /* DOCK_PANEL */);
|
|
320
|
-
}
|
|
321
|
-
function createLayoutFilterTestId(formName, itemName) {
|
|
322
|
-
return createFilterTestId(formName, itemName, "layout-filter" /* LAYOUT */);
|
|
323
|
-
}
|
|
324
|
-
function createTableId(formName) {
|
|
325
|
-
return `${"table" /* TABLE */}-${formName}`;
|
|
326
|
-
}
|
|
406
|
+
import { By as By15 } from "selenium-webdriver";
|
|
327
407
|
|
|
328
408
|
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
329
|
-
import { By as
|
|
409
|
+
import { By as By7, Key } from "selenium-webdriver";
|
|
330
410
|
|
|
331
411
|
// src/pageObjects/elements/Editors/ClearStrategy/InputClearStrategy.ts
|
|
332
412
|
var InputClearStrategy = class {
|
|
@@ -346,7 +426,7 @@ var AbstractDXEditorWithInput = class extends AbstractElementWithParent {
|
|
|
346
426
|
return `${this.getFullCssSelector()} .dx-texteditor-input`;
|
|
347
427
|
}
|
|
348
428
|
async getInputElement() {
|
|
349
|
-
return this.driver.findElement(
|
|
429
|
+
return this.driver.findElement(By7.css(this.getInputCssSelector()));
|
|
350
430
|
}
|
|
351
431
|
async getInputValue() {
|
|
352
432
|
const inputEl = await this.getInputElement();
|
|
@@ -391,6 +471,22 @@ var NumberEditor = class extends AbstractDXEditorWithInput {
|
|
|
391
471
|
}
|
|
392
472
|
};
|
|
393
473
|
|
|
474
|
+
// src/pageObjects/elements/Editors/types.ts
|
|
475
|
+
var ControlClass = /* @__PURE__ */ ((ControlClass2) => {
|
|
476
|
+
ControlClass2["Text"] = "text-control";
|
|
477
|
+
ControlClass2["TextArea"] = "text-area-control";
|
|
478
|
+
ControlClass2["Number"] = "number-control";
|
|
479
|
+
ControlClass2["CheckBox"] = "check-box";
|
|
480
|
+
ControlClass2["Multiselect"] = "multi-select-control";
|
|
481
|
+
ControlClass2["Select"] = "select-control";
|
|
482
|
+
ControlClass2["Switch"] = "switch-control";
|
|
483
|
+
ControlClass2["Date"] = "date-control";
|
|
484
|
+
ControlClass2["SingleDateRange"] = "single-date-range-control";
|
|
485
|
+
ControlClass2["BooleanSelector"] = "buttons-group";
|
|
486
|
+
ControlClass2["ButtonGroup"] = "button-group-field";
|
|
487
|
+
return ControlClass2;
|
|
488
|
+
})(ControlClass || {});
|
|
489
|
+
|
|
394
490
|
// src/pageObjects/AbstractFormElement.ts
|
|
395
491
|
var AbstractFormElement = class extends AbstractElementWithParent {
|
|
396
492
|
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
@@ -418,20 +514,17 @@ var CheckBox = class extends AbstractElementWithParent {
|
|
|
418
514
|
};
|
|
419
515
|
|
|
420
516
|
// src/pageObjects/elements/Editors/SelectBoxEditor.ts
|
|
421
|
-
import { By as
|
|
517
|
+
import { By as By9, Key as Key2 } from "selenium-webdriver";
|
|
422
518
|
|
|
423
519
|
// src/utils/xpathHelper.ts
|
|
424
520
|
var XPathHelper = class {
|
|
425
|
-
static getRoleXpath(role) {
|
|
426
|
-
return `//div[@role='${role}']`;
|
|
427
|
-
}
|
|
428
521
|
static getClassAndValueXpath(cssClass, value) {
|
|
429
|
-
return
|
|
522
|
+
return `div[contains(@class, '${cssClass}') and contains(.,'${value}')]`;
|
|
430
523
|
}
|
|
431
524
|
};
|
|
432
525
|
|
|
433
526
|
// src/pageObjects/elements/Editors/ClearStrategy/ClearButtonStrategy.ts
|
|
434
|
-
import { By as
|
|
527
|
+
import { By as By8 } from "selenium-webdriver";
|
|
435
528
|
var DX_TEXTEDITOR_EMPTY = "dx-texteditor-empty";
|
|
436
529
|
var DX_CLEAR_BUTTON_AREA = "dx-clear-button-area";
|
|
437
530
|
var ClearButtonStrategy = class {
|
|
@@ -442,7 +535,7 @@ var ClearButtonStrategy = class {
|
|
|
442
535
|
this._driver = driver;
|
|
443
536
|
}
|
|
444
537
|
async isEmptyEditorField() {
|
|
445
|
-
const editorContainer = await this._driver.findElement(
|
|
538
|
+
const editorContainer = await this._driver.findElement(By8.css(this.editorContainerClass));
|
|
446
539
|
const classAttribute = await editorContainer.getAttribute("class");
|
|
447
540
|
return classAttribute.includes(DX_TEXTEDITOR_EMPTY);
|
|
448
541
|
}
|
|
@@ -451,18 +544,31 @@ var ClearButtonStrategy = class {
|
|
|
451
544
|
throw new Error("This field is already empty");
|
|
452
545
|
}
|
|
453
546
|
const clearBtnSelector = `${this.editorContainerClass} .${DX_CLEAR_BUTTON_AREA}`;
|
|
454
|
-
const clearBtn = await this._driver.findElement(
|
|
547
|
+
const clearBtn = await this._driver.findElement(By8.css(clearBtnSelector));
|
|
455
548
|
await click(clearBtn, this._driver);
|
|
456
549
|
}
|
|
457
550
|
};
|
|
458
551
|
|
|
459
552
|
// src/pageObjects/elements/Editors/SelectBoxEditor.ts
|
|
460
553
|
var SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS = "d5-multi-select-item";
|
|
461
|
-
var
|
|
462
|
-
var
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
554
|
+
var combinedValueXpath = (value) => `//body/div[@id="root"]/div[contains(@class, "dx-overlay-wrapper")]//${XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value)}`;
|
|
555
|
+
var dropDownOptionClick = async (optionValue, driver, delay = true) => {
|
|
556
|
+
const { implicit } = await driver.manage().getTimeouts();
|
|
557
|
+
let optElement = null;
|
|
558
|
+
const timeout = delay ? implicit : 200;
|
|
559
|
+
let err = null;
|
|
560
|
+
try {
|
|
561
|
+
await driver.manage().setTimeouts({ implicit: timeout });
|
|
562
|
+
optElement = await driver.findElement(By9.xpath(combinedValueXpath(optionValue)));
|
|
563
|
+
await click(optElement, driver);
|
|
564
|
+
} catch (e) {
|
|
565
|
+
err = new Error(`Item not found: "${optionValue}"`);
|
|
566
|
+
} finally {
|
|
567
|
+
await driver.manage().setTimeouts({ implicit });
|
|
568
|
+
}
|
|
569
|
+
if (err)
|
|
570
|
+
throw err;
|
|
571
|
+
};
|
|
466
572
|
var SelectBoxEditor = class extends AbstractDXEditorWithInput {
|
|
467
573
|
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
468
574
|
super(parentCssSelector, elementCssSelector, driver);
|
|
@@ -471,9 +577,12 @@ var SelectBoxEditor = class extends AbstractDXEditorWithInput {
|
|
|
471
577
|
async setSelectInputValue(value) {
|
|
472
578
|
const inputEl = await this.getInputElement();
|
|
473
579
|
await click(inputEl, this.driver);
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
580
|
+
try {
|
|
581
|
+
await dropDownOptionClick(value, this.driver, false);
|
|
582
|
+
} catch {
|
|
583
|
+
await inputEl.sendKeys(value, Key2.ENTER);
|
|
584
|
+
await dropDownOptionClick(value, this.driver);
|
|
585
|
+
}
|
|
477
586
|
}
|
|
478
587
|
async getValue() {
|
|
479
588
|
const value = await super.getInputValue();
|
|
@@ -512,7 +621,7 @@ var SwitchEditor = class extends AbstractElementWithParent {
|
|
|
512
621
|
};
|
|
513
622
|
|
|
514
623
|
// src/pageObjects/elements/Editors/TagBox.ts
|
|
515
|
-
import { By as
|
|
624
|
+
import { By as By10 } from "selenium-webdriver";
|
|
516
625
|
var TAGS_SELECTOR = ".dx-tag .tag-text";
|
|
517
626
|
var DX_TAG_CONTAINER = "dx-tag-container";
|
|
518
627
|
var DX_TEXTEDITOR_EMPTY2 = "dx-texteditor-empty";
|
|
@@ -533,31 +642,35 @@ var TagBox = class extends AbstractDXEditorWithInput {
|
|
|
533
642
|
await this.confirmSelection();
|
|
534
643
|
}
|
|
535
644
|
async waitOptionSelection() {
|
|
536
|
-
const option = await this.driver.findElement(
|
|
645
|
+
const option = await this.driver.findElement(By10.css(TAG_BOX_LIST_ITEM_SELECTOR));
|
|
537
646
|
await wait(() => option.isDisplayed(), this.driver);
|
|
538
647
|
}
|
|
539
648
|
async selectOption(inputEl, value, lastElement) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
649
|
+
try {
|
|
650
|
+
await dropDownOptionClick(value, this.driver, false);
|
|
651
|
+
} catch {
|
|
652
|
+
await inputEl.sendKeys(value);
|
|
653
|
+
await dropDownOptionClick(value, this.driver);
|
|
654
|
+
}
|
|
543
655
|
await this.waitOptionSelection();
|
|
544
656
|
if (value !== lastElement) {
|
|
545
657
|
await inputEl.clear();
|
|
546
658
|
}
|
|
547
659
|
}
|
|
548
660
|
async confirmSelection() {
|
|
549
|
-
const btnOk = await this.driver.findElement(
|
|
661
|
+
const btnOk = await this.driver.findElement(By10.css(BTN_OK_SELECTOR));
|
|
550
662
|
await click(btnOk, this.driver);
|
|
551
663
|
}
|
|
552
664
|
async getTagBoxInputValue() {
|
|
553
665
|
if (await this.isTagBoxEmpty()) {
|
|
554
666
|
return [];
|
|
555
667
|
}
|
|
556
|
-
const tags = await this.driver.findElements(
|
|
668
|
+
const tags = await this.driver.findElements(
|
|
669
|
+
By10.css(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER} ${TAGS_SELECTOR}`)
|
|
670
|
+
);
|
|
557
671
|
const values = [];
|
|
558
672
|
for (const tag of tags) {
|
|
559
|
-
|
|
560
|
-
values.push(text);
|
|
673
|
+
values.push(await tag.getAttribute("textContent"));
|
|
561
674
|
}
|
|
562
675
|
return values;
|
|
563
676
|
}
|
|
@@ -582,24 +695,26 @@ var TagBox = class extends AbstractDXEditorWithInput {
|
|
|
582
695
|
throw new Error(`The tag with the text: ${itemText} was not found`);
|
|
583
696
|
}
|
|
584
697
|
const clearBtnTestId = byTestIdCssSelector(`clear-button-${itemText}`);
|
|
585
|
-
const clearBtn = await this.driver.findElement(
|
|
698
|
+
const clearBtn = await this.driver.findElement(
|
|
699
|
+
By10.css(`${this.getFullCssSelector()} .${DX_TAG_CONTAINER} ${clearBtnTestId}`)
|
|
700
|
+
);
|
|
586
701
|
await click(clearBtn, this.driver);
|
|
587
702
|
}
|
|
588
703
|
};
|
|
589
704
|
|
|
590
705
|
// src/pageObjects/elements/Editors/ButtonGroup.ts
|
|
591
|
-
import { By as
|
|
706
|
+
import { By as By11 } from "selenium-webdriver";
|
|
592
707
|
var ITEM_CLASS = "dx-buttongroup-item";
|
|
593
708
|
var SELECTED_CLASS = "dx-state-selected";
|
|
594
709
|
var ButtonGroup = class extends AbstractElementWithParent {
|
|
595
710
|
getItems() {
|
|
596
|
-
return this.driver.findElements(
|
|
711
|
+
return this.driver.findElements(By11.css(`${this.getFullCssSelector()} .${ITEM_CLASS}`));
|
|
597
712
|
}
|
|
598
713
|
getDataValue(el) {
|
|
599
714
|
return el.getAttribute("data-value");
|
|
600
715
|
}
|
|
601
716
|
async getValue() {
|
|
602
|
-
const selectedEl = await this.driver.findElement(
|
|
717
|
+
const selectedEl = await this.driver.findElement(By11.css(`${this.getFullCssSelector()} .${ITEM_CLASS}.${SELECTED_CLASS}`));
|
|
603
718
|
return this.getDataValue(selectedEl);
|
|
604
719
|
}
|
|
605
720
|
async setValue(value) {
|
|
@@ -632,26 +747,67 @@ var BooleanSelector = class extends ButtonGroup {
|
|
|
632
747
|
}
|
|
633
748
|
};
|
|
634
749
|
|
|
635
|
-
// src/pageObjects/elements/Editors/
|
|
636
|
-
import { By as
|
|
637
|
-
|
|
750
|
+
// src/pageObjects/elements/Editors/Date/SingleDateEditor.ts
|
|
751
|
+
import { By as By13 } from "selenium-webdriver";
|
|
752
|
+
|
|
753
|
+
// src/pageObjects/elements/Editors/Date/BaseDateEditor.ts
|
|
754
|
+
import { By as By12, Key as Key3 } from "selenium-webdriver";
|
|
755
|
+
|
|
756
|
+
// src/pageObjects/elements/Editors/Date/utils.ts
|
|
757
|
+
var formatDMYDate = (date) => {
|
|
758
|
+
const [year, month, day] = date.toJSON().split("T")[0].split("-");
|
|
759
|
+
return `${day}${month}${year}`;
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
// src/pageObjects/elements/Editors/Date/BaseDateEditor.ts
|
|
763
|
+
var BTN_CALENDAR_POPOVER_OPEN_SELECTOR = "calendar-popover-open-button";
|
|
764
|
+
var BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR = "DateRange__inputs-item--dateFrom";
|
|
765
|
+
var BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR = "DateRange__inputs-item--dateTo";
|
|
766
|
+
var BTN_SAVE_SELECTOR = "DateRange__button-save";
|
|
767
|
+
var BaseDateEditor = class extends AbstractDXEditorWithInput {
|
|
638
768
|
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
639
769
|
super(parentCssSelector, elementCssSelector, driver);
|
|
640
770
|
this.setClearStrategy(new InputClearStrategy());
|
|
641
771
|
}
|
|
642
|
-
async getDateElement() {
|
|
643
|
-
return this.driver.findElement(By11.css(this.getFullCssSelector() + " .dx-dropdowneditor-input-wrapper input[type=hidden]"));
|
|
644
|
-
}
|
|
645
772
|
async setDateValue(value) {
|
|
646
|
-
const dateEl = await this.getInputElement();
|
|
647
|
-
const stringDate = value.toJSON().split("T")[0];
|
|
648
|
-
const dateArr = stringDate.split("-");
|
|
649
|
-
const [year, month, day] = dateArr;
|
|
650
|
-
const keys = day + month + year;
|
|
651
|
-
await click(dateEl, this.driver);
|
|
652
773
|
const actions = this.driver.actions({ async: true });
|
|
653
|
-
|
|
654
|
-
|
|
774
|
+
const dateField = await this.driver.findElement(By12.css(`${this.getFullCssSelector()}`));
|
|
775
|
+
const dateFieldDataTestID = await this.getDataTestId();
|
|
776
|
+
const calendarPopoverSelector = byTestIdCssSelector(`${dateFieldDataTestID}-calendar-popover`);
|
|
777
|
+
const dateInputEl = await this.getInputElement();
|
|
778
|
+
await dateInputEl.clear();
|
|
779
|
+
if (Array.isArray(value)) {
|
|
780
|
+
const formattedDates = value.map(formatDMYDate);
|
|
781
|
+
const button = await dateField.findElement(By12.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
|
|
782
|
+
await button.click();
|
|
783
|
+
const calendarPopoverElement = await this.driver.findElement(By12.css(calendarPopoverSelector));
|
|
784
|
+
const dateFromInput = await calendarPopoverElement.findElement(By12.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`));
|
|
785
|
+
const dateToInput = await calendarPopoverElement.findElement(By12.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`));
|
|
786
|
+
await dateFromInput.click();
|
|
787
|
+
await dateFromInput.sendKeys(formattedDates[0]);
|
|
788
|
+
await dateToInput.click();
|
|
789
|
+
await actions.move({ origin: dateInputEl }).sendKeys(Key3.HOME).perform();
|
|
790
|
+
await dateToInput.sendKeys(formattedDates[1]);
|
|
791
|
+
await actions.move({ origin: dateInputEl }).sendKeys(Key3.ENTER).perform();
|
|
792
|
+
const btnOk = await this.driver.findElement(By12.css(`.${BTN_SAVE_SELECTOR}`));
|
|
793
|
+
await btnOk.click();
|
|
794
|
+
} else {
|
|
795
|
+
const formattedDate = formatDMYDate(value);
|
|
796
|
+
await click(dateInputEl, this.driver);
|
|
797
|
+
await actions.move({ origin: dateInputEl }).sendKeys(Key3.HOME).perform();
|
|
798
|
+
await actions.move({ origin: dateInputEl }).sendKeys(formattedDate, Key3.ENTER).perform();
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
// src/pageObjects/elements/Editors/Date/SingleDateEditor.ts
|
|
804
|
+
var SingleDateEditor = class extends BaseDateEditor {
|
|
805
|
+
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
806
|
+
super(parentCssSelector, elementCssSelector, driver);
|
|
807
|
+
this.setClearStrategy(new InputClearStrategy());
|
|
808
|
+
}
|
|
809
|
+
async getDateElement() {
|
|
810
|
+
return this.driver.findElement(By13.css(this.getFullCssSelector() + " .dx-dropdowneditor-input-wrapper input[type=hidden]"));
|
|
655
811
|
}
|
|
656
812
|
async getDateValue() {
|
|
657
813
|
const inputEl = await this.getDateElement();
|
|
@@ -669,27 +825,105 @@ var DateEditor = class extends AbstractDXEditorWithInput {
|
|
|
669
825
|
}
|
|
670
826
|
};
|
|
671
827
|
|
|
828
|
+
// src/pageObjects/elements/Editors/Date/DateRangeEditor.ts
|
|
829
|
+
import { By as By14 } from "selenium-webdriver";
|
|
830
|
+
var DateRangeEditor = class extends BaseDateEditor {
|
|
831
|
+
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
832
|
+
super(parentCssSelector, elementCssSelector, driver);
|
|
833
|
+
this.setClearStrategy(new InputClearStrategy());
|
|
834
|
+
}
|
|
835
|
+
async getDateElement() {
|
|
836
|
+
return this.driver.findElement(By14.css(this.getFullCssSelector() + " .dx-texteditor-input"));
|
|
837
|
+
}
|
|
838
|
+
async getDateValue() {
|
|
839
|
+
const inputEl = await this.getDateElement();
|
|
840
|
+
const dateFromStr = await inputEl.getAttribute("datefrom");
|
|
841
|
+
const dateToStr = await inputEl.getAttribute("dateto");
|
|
842
|
+
const dateFrom = new Date(dateFromStr);
|
|
843
|
+
const dateTo = new Date(dateToStr);
|
|
844
|
+
return [dateFrom, dateTo];
|
|
845
|
+
}
|
|
846
|
+
async getValue() {
|
|
847
|
+
const values = await this.getDateValue();
|
|
848
|
+
return !values.length ? null : values;
|
|
849
|
+
}
|
|
850
|
+
setValue(value) {
|
|
851
|
+
if (typeof value === "object") {
|
|
852
|
+
return this.setDateValue(value);
|
|
853
|
+
}
|
|
854
|
+
throw new Error(`Value is incorrect. It should be Object`);
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
// src/pageObjects/elements/Editors/Date/DateEditor.ts
|
|
859
|
+
var DateEditor = class extends AbstractDXEditorWithInput {
|
|
860
|
+
editorInstance = null;
|
|
861
|
+
initPromise;
|
|
862
|
+
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
863
|
+
super(parentCssSelector, elementCssSelector, driver);
|
|
864
|
+
this.initPromise = this.init(parentCssSelector, elementCssSelector, driver);
|
|
865
|
+
}
|
|
866
|
+
async init(parentCssSelector, elementCssSelector, driver) {
|
|
867
|
+
await this.updateEditorInstance(parentCssSelector, elementCssSelector, driver);
|
|
868
|
+
}
|
|
869
|
+
async updateEditorInstance(parentCssSelector, elementCssSelector, driver) {
|
|
870
|
+
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
|
|
871
|
+
const classString = await elementInstance.getClasses();
|
|
872
|
+
switch (true) {
|
|
873
|
+
case classString.includes("date-control" /* Date */):
|
|
874
|
+
this.editorInstance = new SingleDateEditor(parentCssSelector, elementCssSelector, driver);
|
|
875
|
+
break;
|
|
876
|
+
case classString.includes("single-date-range-control" /* SingleDateRange */):
|
|
877
|
+
this.editorInstance = new DateRangeEditor(parentCssSelector, elementCssSelector, driver);
|
|
878
|
+
break;
|
|
879
|
+
default:
|
|
880
|
+
this.editorInstance = new SingleDateEditor(parentCssSelector, elementCssSelector, driver);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
async ensureInitialized() {
|
|
884
|
+
if (!this.editorInstance) {
|
|
885
|
+
await this.initPromise;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
async setValue(value) {
|
|
889
|
+
await this.ensureInitialized();
|
|
890
|
+
if (this.editorInstance) {
|
|
891
|
+
await this.editorInstance.setValue(value);
|
|
892
|
+
return await this.updateEditorInstance(this.parentCssSelector, this.elementCssSelector, this.driver);
|
|
893
|
+
}
|
|
894
|
+
throw new Error("Editor instance is not initialized.");
|
|
895
|
+
}
|
|
896
|
+
async getValue() {
|
|
897
|
+
await this.ensureInitialized();
|
|
898
|
+
if (this.editorInstance) {
|
|
899
|
+
return this.editorInstance.getValue();
|
|
900
|
+
}
|
|
901
|
+
throw new Error("Editor instance is not initialized.");
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
|
|
672
905
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
673
906
|
var editorFactory = async (parentCssSelector, elementCssSelector, driver) => {
|
|
674
907
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
|
|
675
908
|
const classSting = await elementInstance.getClasses();
|
|
676
|
-
if (classSting.includes("text-control"))
|
|
909
|
+
if ((classSting.includes("text-control" /* Text */) || classSting.includes("text-area-control" /* TextArea */)) && !classSting.includes("single-date-range-control" /* SingleDateRange */))
|
|
677
910
|
return new TextEditor(parentCssSelector, elementCssSelector, driver);
|
|
678
|
-
if (classSting.includes("number-control"))
|
|
911
|
+
if (classSting.includes("number-control" /* Number */))
|
|
679
912
|
return new NumberEditor(parentCssSelector, elementCssSelector, driver);
|
|
680
|
-
if (classSting.includes("check-box"))
|
|
913
|
+
if (classSting.includes("check-box" /* CheckBox */))
|
|
681
914
|
return new CheckBox(parentCssSelector, elementCssSelector, driver);
|
|
682
|
-
if (classSting.includes("multi-select-control"))
|
|
915
|
+
if (classSting.includes("multi-select-control" /* Multiselect */))
|
|
683
916
|
return new TagBox(parentCssSelector, elementCssSelector, driver);
|
|
684
|
-
if (classSting.includes("select-control"))
|
|
917
|
+
if (classSting.includes("select-control" /* Select */))
|
|
685
918
|
return new SelectBoxEditor(parentCssSelector, elementCssSelector, driver);
|
|
686
|
-
if (classSting.includes("switch-control"))
|
|
919
|
+
if (classSting.includes("switch-control" /* Switch */))
|
|
687
920
|
return new SwitchEditor(parentCssSelector, elementCssSelector, driver);
|
|
688
|
-
if (classSting.includes("date-control"))
|
|
921
|
+
if (classSting.includes("date-control" /* Date */) || classSting.includes("single-date-range-control" /* SingleDateRange */)) {
|
|
689
922
|
return new DateEditor(parentCssSelector, elementCssSelector, driver);
|
|
690
|
-
|
|
923
|
+
}
|
|
924
|
+
if (classSting.includes("buttons-group" /* BooleanSelector */))
|
|
691
925
|
return new BooleanSelector(parentCssSelector, elementCssSelector, driver);
|
|
692
|
-
if (classSting.includes("button-group-field"))
|
|
926
|
+
if (classSting.includes("button-group-field" /* ButtonGroup */))
|
|
693
927
|
return new ButtonGroup(parentCssSelector, elementCssSelector, driver);
|
|
694
928
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
695
929
|
};
|
|
@@ -749,6 +983,16 @@ var AbstractEditor = class extends AbstractElementWithParent {
|
|
|
749
983
|
}
|
|
750
984
|
return this.editor.remove(itemText);
|
|
751
985
|
}
|
|
986
|
+
/**
|
|
987
|
+
* Возвращает значение true|false в зависимости readOnly поле или нет
|
|
988
|
+
* @example
|
|
989
|
+
* expect(await formEdit.field('NumberFld').isReadonly()).toBe(true);
|
|
990
|
+
* expect(await formEdit.field('TextFld').isReadonly()).toBe(false);
|
|
991
|
+
*/
|
|
992
|
+
async isReadonly() {
|
|
993
|
+
await this.initEditor();
|
|
994
|
+
return this.editor.isReadonly();
|
|
995
|
+
}
|
|
752
996
|
};
|
|
753
997
|
|
|
754
998
|
// src/pageObjects/elements/FormField.ts
|
|
@@ -807,7 +1051,8 @@ var FormGroup = class extends AbstractElementWithParent {
|
|
|
807
1051
|
|
|
808
1052
|
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
809
1053
|
var FormEdit = class extends AbstractForm {
|
|
810
|
-
saveButtonBy =
|
|
1054
|
+
saveButtonBy = By15.id("button-save");
|
|
1055
|
+
closeButtonBy = By15.id("button-cancel");
|
|
811
1056
|
constructor(driver) {
|
|
812
1057
|
super(driver);
|
|
813
1058
|
this.popupContainerCssSelector = `.popup .form-edit-${this.formName}`;
|
|
@@ -856,19 +1101,30 @@ var FormEdit = class extends AbstractForm {
|
|
|
856
1101
|
await wait(async () => !await this.isSaveButtonDisabled(), this.driver, "Button is disabled");
|
|
857
1102
|
await click(saveButton, this.driver);
|
|
858
1103
|
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Нажатие на кнопку Закрить
|
|
1106
|
+
* @example
|
|
1107
|
+
* const formEdit = new MyForm();
|
|
1108
|
+
* //...
|
|
1109
|
+
* await formEdit.closeButtonClick();
|
|
1110
|
+
*/
|
|
1111
|
+
async closeButtonClick() {
|
|
1112
|
+
const closeButton = await this.driver.findElement(this.closeButtonBy);
|
|
1113
|
+
await click(closeButton, this.driver);
|
|
1114
|
+
}
|
|
859
1115
|
};
|
|
860
1116
|
|
|
861
1117
|
// src/pageObjects/elements/Table/Table.ts
|
|
862
|
-
import { By as
|
|
1118
|
+
import { By as By20 } from "selenium-webdriver";
|
|
863
1119
|
|
|
864
1120
|
// src/pageObjects/elements/Table/elements/Row.ts
|
|
865
|
-
import { By as
|
|
1121
|
+
import { By as By18 } from "selenium-webdriver";
|
|
866
1122
|
|
|
867
1123
|
// src/pageObjects/elements/Table/elements/Cell.ts
|
|
868
|
-
import { By as
|
|
1124
|
+
import { By as By17 } from "selenium-webdriver";
|
|
869
1125
|
|
|
870
1126
|
// src/pageObjects/elements/Table/utils.ts
|
|
871
|
-
import { By as
|
|
1127
|
+
import { By as By16 } from "selenium-webdriver";
|
|
872
1128
|
function getCssRowByIndexSelector(index) {
|
|
873
1129
|
return `tr[aria-rowindex="${transformInputIndex(index)}"]`;
|
|
874
1130
|
}
|
|
@@ -895,9 +1151,18 @@ var Cell = class extends AbstractElementWithParent {
|
|
|
895
1151
|
this.elementCssSelector = getCssCellByIndexSelector(index);
|
|
896
1152
|
}
|
|
897
1153
|
async getBooleanValue(cellEl) {
|
|
898
|
-
const booleanEl = await cellEl.findElement(
|
|
1154
|
+
const booleanEl = await cellEl.findElement(By17.className("boolean-widget"));
|
|
899
1155
|
return await booleanEl.getAttribute("aria-checked") === "true" ? 1 : 0;
|
|
900
1156
|
}
|
|
1157
|
+
async getTagsValue(cellEl) {
|
|
1158
|
+
const tagsCssSelector = ".multiselect-container .multiselect-cell";
|
|
1159
|
+
const tags = await cellEl.findElements(By17.css(tagsCssSelector));
|
|
1160
|
+
const values = [];
|
|
1161
|
+
for (const tag of tags) {
|
|
1162
|
+
values.push(await tag.getAttribute("textContent"));
|
|
1163
|
+
}
|
|
1164
|
+
return values;
|
|
1165
|
+
}
|
|
901
1166
|
async getElement() {
|
|
902
1167
|
if (this._index == null) {
|
|
903
1168
|
this.index = await this.getCellIndex();
|
|
@@ -907,9 +1172,10 @@ var Cell = class extends AbstractElementWithParent {
|
|
|
907
1172
|
async getValue() {
|
|
908
1173
|
const cellEl = await this.getElement();
|
|
909
1174
|
const cellElClass = await cellEl.getAttribute("class");
|
|
910
|
-
if (cellElClass.includes("boolean-column"))
|
|
1175
|
+
if (cellElClass.includes("boolean-column" /* Boolean */))
|
|
911
1176
|
return this.getBooleanValue(cellEl);
|
|
912
|
-
|
|
1177
|
+
if (cellElClass.includes("tags-column" /* Tags */))
|
|
1178
|
+
return this.getTagsValue(cellEl);
|
|
913
1179
|
return cellEl.getText();
|
|
914
1180
|
}
|
|
915
1181
|
getIndex() {
|
|
@@ -930,9 +1196,14 @@ var Row = class extends AbstractElementWithParent {
|
|
|
930
1196
|
this.getColumnBy = getColumnBy;
|
|
931
1197
|
}
|
|
932
1198
|
_getCell({ index, name, title }) {
|
|
933
|
-
return new Cell(
|
|
934
|
-
|
|
935
|
-
|
|
1199
|
+
return new Cell(
|
|
1200
|
+
this.getFullCssSelector(),
|
|
1201
|
+
() => {
|
|
1202
|
+
return this.getColumnBy({ title, name }).getIndex();
|
|
1203
|
+
},
|
|
1204
|
+
index,
|
|
1205
|
+
this.driver
|
|
1206
|
+
);
|
|
936
1207
|
}
|
|
937
1208
|
getCellByIndex(index) {
|
|
938
1209
|
return this._getCell({ index });
|
|
@@ -946,10 +1217,14 @@ var Row = class extends AbstractElementWithParent {
|
|
|
946
1217
|
async select() {
|
|
947
1218
|
const rowEl = await this.getElement();
|
|
948
1219
|
await click(rowEl, this.driver);
|
|
949
|
-
await wait(
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1220
|
+
await wait(
|
|
1221
|
+
async () => {
|
|
1222
|
+
const classes = await this.getClasses();
|
|
1223
|
+
return classes.includes(DX_SELECTION_CLASS);
|
|
1224
|
+
},
|
|
1225
|
+
this.driver,
|
|
1226
|
+
"Cannot select row"
|
|
1227
|
+
);
|
|
953
1228
|
}
|
|
954
1229
|
async isSelected() {
|
|
955
1230
|
const result = await this.getAttribute("aria-selected");
|
|
@@ -959,7 +1234,7 @@ var Row = class extends AbstractElementWithParent {
|
|
|
959
1234
|
return this.index;
|
|
960
1235
|
}
|
|
961
1236
|
async getCells() {
|
|
962
|
-
const cells = await this.driver.findElements(
|
|
1237
|
+
const cells = await this.driver.findElements(By18.css(`${this.getFullCssSelector()} td[role="gridcell"]`));
|
|
963
1238
|
const result = [];
|
|
964
1239
|
cells.forEach((_, index) => {
|
|
965
1240
|
const newCell = this.getCellByIndex(index);
|
|
@@ -969,14 +1244,22 @@ var Row = class extends AbstractElementWithParent {
|
|
|
969
1244
|
}
|
|
970
1245
|
async clickInlineButton(buttonClass) {
|
|
971
1246
|
const FIXED_TABLE_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
|
|
972
|
-
const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(
|
|
973
|
-
|
|
1247
|
+
const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(
|
|
1248
|
+
this.index
|
|
1249
|
+
)}"] .${buttonClass}`;
|
|
1250
|
+
const button = await this.driver.findElement(
|
|
1251
|
+
By18.css(`${this.parentCssSelector} ${FIXED_TABLE_CSS_SELECTOR} ${buttonCssSelector}`)
|
|
1252
|
+
);
|
|
974
1253
|
return click(button, this.driver);
|
|
975
1254
|
}
|
|
976
1255
|
async checkEditingMode(isEditing, msg) {
|
|
977
|
-
await wait(
|
|
978
|
-
|
|
979
|
-
|
|
1256
|
+
await wait(
|
|
1257
|
+
async () => {
|
|
1258
|
+
return (await this.getClasses()).includes(DX_ROW_EDIT_CLASS) === isEditing;
|
|
1259
|
+
},
|
|
1260
|
+
this.driver,
|
|
1261
|
+
msg
|
|
1262
|
+
);
|
|
980
1263
|
}
|
|
981
1264
|
async edit() {
|
|
982
1265
|
await this.clickInlineButton("edit");
|
|
@@ -993,19 +1276,18 @@ var Row = class extends AbstractElementWithParent {
|
|
|
993
1276
|
};
|
|
994
1277
|
|
|
995
1278
|
// src/pageObjects/elements/Table/elements/Column.ts
|
|
996
|
-
import { By as
|
|
997
|
-
var getHeaderCssSelector = () => {
|
|
998
|
-
return ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
|
|
999
|
-
};
|
|
1279
|
+
import { By as By19 } from "selenium-webdriver";
|
|
1000
1280
|
var Column = class extends AbstractElementWithParent {
|
|
1001
1281
|
_index;
|
|
1002
1282
|
_caption;
|
|
1003
1283
|
_name;
|
|
1004
|
-
|
|
1284
|
+
headerCssSelector;
|
|
1285
|
+
constructor({ parentCssSelector, headerCssSelector, name, caption, index, driver }) {
|
|
1005
1286
|
super(parentCssSelector, "", driver);
|
|
1006
1287
|
this._name = name;
|
|
1007
1288
|
this.index = index;
|
|
1008
1289
|
this._caption = caption;
|
|
1290
|
+
this.headerCssSelector = headerCssSelector;
|
|
1009
1291
|
}
|
|
1010
1292
|
set index(index) {
|
|
1011
1293
|
this._index = index;
|
|
@@ -1019,7 +1301,9 @@ var Column = class extends AbstractElementWithParent {
|
|
|
1019
1301
|
return super.getElement();
|
|
1020
1302
|
}
|
|
1021
1303
|
async getColumnHeaderIndexBy(cssSelector) {
|
|
1022
|
-
const column = await this.driver.findElement(
|
|
1304
|
+
const column = await this.driver.findElement(
|
|
1305
|
+
By19.css(`${this.parentCssSelector} ${this.headerCssSelector} ${cssSelector}`)
|
|
1306
|
+
);
|
|
1023
1307
|
return transformOutputIndex(await column.getAttribute("aria-colindex"));
|
|
1024
1308
|
}
|
|
1025
1309
|
async getIndexByCaption() {
|
|
@@ -1051,9 +1335,11 @@ var Column = class extends AbstractElementWithParent {
|
|
|
1051
1335
|
// src/pageObjects/elements/Table/Table.ts
|
|
1052
1336
|
var Table = class extends AbstractElementWithParent {
|
|
1053
1337
|
formName;
|
|
1054
|
-
|
|
1338
|
+
headerCssSelector;
|
|
1339
|
+
constructor(parentCssSelector, headerCssSelector, formName, driver) {
|
|
1055
1340
|
super(parentCssSelector, `#${createTableId(formName)}`, driver);
|
|
1056
1341
|
this.formName = formName;
|
|
1342
|
+
this.headerCssSelector = headerCssSelector;
|
|
1057
1343
|
}
|
|
1058
1344
|
getColumnBy = (args) => {
|
|
1059
1345
|
if (args.title) {
|
|
@@ -1074,6 +1360,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
1074
1360
|
getColumnByTitle = (title) => {
|
|
1075
1361
|
return new Column({
|
|
1076
1362
|
parentCssSelector: this.getFullCssSelector(),
|
|
1363
|
+
headerCssSelector: this.headerCssSelector,
|
|
1077
1364
|
caption: title,
|
|
1078
1365
|
driver: this.driver
|
|
1079
1366
|
});
|
|
@@ -1081,6 +1368,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
1081
1368
|
getColumnByName = (name) => {
|
|
1082
1369
|
return new Column({
|
|
1083
1370
|
parentCssSelector: this.getFullCssSelector(),
|
|
1371
|
+
headerCssSelector: this.headerCssSelector,
|
|
1084
1372
|
name,
|
|
1085
1373
|
driver: this.driver
|
|
1086
1374
|
});
|
|
@@ -1089,7 +1377,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
1089
1377
|
return this.getRowByIndex(index).select();
|
|
1090
1378
|
}
|
|
1091
1379
|
async getRows() {
|
|
1092
|
-
const rows = await this.driver.findElements(
|
|
1380
|
+
const rows = await this.driver.findElements(By20.css(`${this.getFullCssSelector()} .dx-row.dx-data-row`));
|
|
1093
1381
|
const result = [];
|
|
1094
1382
|
rows.forEach((_, index) => {
|
|
1095
1383
|
const newRow = new Row(this.getFullCssSelector(), index, this.driver, this.getColumnBy);
|
|
@@ -1098,7 +1386,9 @@ var Table = class extends AbstractElementWithParent {
|
|
|
1098
1386
|
return result;
|
|
1099
1387
|
}
|
|
1100
1388
|
async getColumns() {
|
|
1101
|
-
const columns = await this.driver.findElements(
|
|
1389
|
+
const columns = await this.driver.findElements(
|
|
1390
|
+
By20.css(`${this.getFullCssSelector()} ${this.headerCssSelector} td[role="columnheader"]`)
|
|
1391
|
+
);
|
|
1102
1392
|
const result = [];
|
|
1103
1393
|
columns.forEach((_, index) => {
|
|
1104
1394
|
const newCol = new Column({
|
|
@@ -1125,24 +1415,6 @@ var Table = class extends AbstractElementWithParent {
|
|
|
1125
1415
|
}
|
|
1126
1416
|
};
|
|
1127
1417
|
|
|
1128
|
-
// src/pageObjects/elements/TableToolbar/AbstractButton.ts
|
|
1129
|
-
var AbstractButton = class extends AbstractElementWithParent {
|
|
1130
|
-
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
1131
|
-
super(parentCssSelector, elementCssSelector, driver);
|
|
1132
|
-
}
|
|
1133
|
-
async click() {
|
|
1134
|
-
const button = await this.getElement();
|
|
1135
|
-
await wait(async () => {
|
|
1136
|
-
return await button.isDisplayed() && !await this.isDisabled();
|
|
1137
|
-
}, this.driver, this.buttonNotDisplayedError());
|
|
1138
|
-
await click(button, this.driver);
|
|
1139
|
-
}
|
|
1140
|
-
async isDisabled() {
|
|
1141
|
-
const button = await this.getElement();
|
|
1142
|
-
return await button.getCssValue("pointer-events") === "none";
|
|
1143
|
-
}
|
|
1144
|
-
};
|
|
1145
|
-
|
|
1146
1418
|
// src/pageObjects/elements/TableToolbar/ToolbarGroupButton.ts
|
|
1147
1419
|
var ToolbarGroupButton = class extends AbstractButton {
|
|
1148
1420
|
name;
|
|
@@ -1168,16 +1440,97 @@ var ToolbarButton = class extends AbstractButton {
|
|
|
1168
1440
|
}
|
|
1169
1441
|
};
|
|
1170
1442
|
|
|
1443
|
+
// src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
|
|
1444
|
+
import { By as By21 } from "selenium-webdriver";
|
|
1445
|
+
|
|
1446
|
+
// src/utils/typesUtil.ts
|
|
1447
|
+
var types = {
|
|
1448
|
+
"[object Array]": "array",
|
|
1449
|
+
"[object Date]": "date",
|
|
1450
|
+
"[object Object]": "object",
|
|
1451
|
+
"[object String]": "string",
|
|
1452
|
+
"[object Null]": "null"
|
|
1453
|
+
};
|
|
1454
|
+
var type = function(object) {
|
|
1455
|
+
const typeOfObject = Object.prototype.toString.call(object);
|
|
1456
|
+
return typeof object === "object" ? types[typeOfObject] || "object" : typeof object;
|
|
1457
|
+
};
|
|
1458
|
+
var isArray = function(value) {
|
|
1459
|
+
return type(value) === "array";
|
|
1460
|
+
};
|
|
1461
|
+
var isString = function(object) {
|
|
1462
|
+
return typeof object === "string";
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
// src/pageObjects/elements/TableToolbar/ToolbarMenu.ts
|
|
1466
|
+
var SPINDOWN_CLASS = ".dx-icon-spindown";
|
|
1467
|
+
var buttonGroupItemSelector = (formName, name) => byTestIdCssSelector(`ftb-${formName}-${name}`);
|
|
1468
|
+
var getFullCssSelector = (formName, name) => `${buttonGroupItemSelector(formName, name)} ${SPINDOWN_CLASS}`;
|
|
1469
|
+
var buttonByTextXpath = (text) => `.//span[contains(@class, "dx-menu-item-text") and contains(text(), "${text}")]`;
|
|
1470
|
+
var ToolbarMenu = class extends AbstractElementWithParent {
|
|
1471
|
+
_formName;
|
|
1472
|
+
constructor(parentCssSelector, formName, name, driver) {
|
|
1473
|
+
super(parentCssSelector, getFullCssSelector(formName, name), driver);
|
|
1474
|
+
this._formName = formName;
|
|
1475
|
+
}
|
|
1476
|
+
async toggle() {
|
|
1477
|
+
const dropdown = await this.getElement();
|
|
1478
|
+
await click(dropdown, this.driver);
|
|
1479
|
+
}
|
|
1480
|
+
getCssSelectorToButton(name) {
|
|
1481
|
+
return byTestId(`ftb-${this._formName}-${name}`);
|
|
1482
|
+
}
|
|
1483
|
+
buttonNotDisplayedError(name) {
|
|
1484
|
+
return `Toolbar menu button ${name} cannot be clicked. It is not displayed or it is disabled`;
|
|
1485
|
+
}
|
|
1486
|
+
async goToButton(name, selector) {
|
|
1487
|
+
const toolbarMenuItem = this.driver.findElement(selector);
|
|
1488
|
+
await waitElementIsClickable({
|
|
1489
|
+
element: toolbarMenuItem,
|
|
1490
|
+
errorMessage: this.buttonNotDisplayedError(name),
|
|
1491
|
+
driver: this.driver
|
|
1492
|
+
});
|
|
1493
|
+
await click(toolbarMenuItem, this.driver);
|
|
1494
|
+
}
|
|
1495
|
+
async clickButton(name) {
|
|
1496
|
+
await this.toggle();
|
|
1497
|
+
if (isString(name)) {
|
|
1498
|
+
const selector = this.getCssSelectorToButton(name);
|
|
1499
|
+
await this.goToButton(name, selector);
|
|
1500
|
+
}
|
|
1501
|
+
if (isArray(name)) {
|
|
1502
|
+
for (let n of name) {
|
|
1503
|
+
const selector = this.getCssSelectorToButton(n);
|
|
1504
|
+
await this.goToButton(n, selector);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
async clickButtonByTitle(title) {
|
|
1509
|
+
await this.toggle();
|
|
1510
|
+
if (isString(title)) {
|
|
1511
|
+
const selector = By21.xpath(buttonByTextXpath(title));
|
|
1512
|
+
await this.goToButton(title, selector);
|
|
1513
|
+
}
|
|
1514
|
+
if (isArray(title)) {
|
|
1515
|
+
for (let t of title) {
|
|
1516
|
+
const selector = By21.xpath(buttonByTextXpath(t));
|
|
1517
|
+
await this.goToButton(t, selector);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
};
|
|
1522
|
+
|
|
1171
1523
|
// src/pageObjects/elements/TableToolbar/ToolbarItem.ts
|
|
1172
1524
|
var GROUP_BUTTON_CLASS = "toolbar-group-button";
|
|
1173
1525
|
var toolbarItemSelector = (form, name) => byTestIdCssSelector(`ftb-${form}-${name}`);
|
|
1174
1526
|
var ToolbarItem = class extends AbstractElementWithParent {
|
|
1175
1527
|
_button;
|
|
1176
|
-
|
|
1528
|
+
_formName;
|
|
1177
1529
|
_itemName;
|
|
1178
1530
|
constructor(parentCssSelector, formName, itemName, driver) {
|
|
1179
1531
|
super(parentCssSelector, toolbarItemSelector(formName, itemName), driver);
|
|
1180
1532
|
this._itemName = itemName;
|
|
1533
|
+
this._formName = formName;
|
|
1181
1534
|
}
|
|
1182
1535
|
async init() {
|
|
1183
1536
|
if (this._button)
|
|
@@ -1197,6 +1550,9 @@ var ToolbarItem = class extends AbstractElementWithParent {
|
|
|
1197
1550
|
await this.init();
|
|
1198
1551
|
return await this._button.isDisabled();
|
|
1199
1552
|
}
|
|
1553
|
+
get menu() {
|
|
1554
|
+
return new ToolbarMenu(this.parentCssSelector, this._formName, this._itemName, this.driver);
|
|
1555
|
+
}
|
|
1200
1556
|
};
|
|
1201
1557
|
|
|
1202
1558
|
// src/pageObjects/elements/TableToolbar/FormToolbar.ts
|
|
@@ -1254,7 +1610,7 @@ var FormFilterField = class extends AbstractEditor {
|
|
|
1254
1610
|
};
|
|
1255
1611
|
|
|
1256
1612
|
// src/pageObjects/elements/Filters/FilterPanel.ts
|
|
1257
|
-
import { By as
|
|
1613
|
+
import { By as By22 } from "selenium-webdriver";
|
|
1258
1614
|
|
|
1259
1615
|
// src/pageObjects/elements/Filters/PanelFilterField.ts
|
|
1260
1616
|
var PanelFilterField = class extends AbstractEditor {
|
|
@@ -1309,7 +1665,7 @@ var FilterPanel = class extends AbstractElement {
|
|
|
1309
1665
|
async filterPanelButtons() {
|
|
1310
1666
|
const selector = `${this.elementCssSelector} ${FILTER_PANEL_SELECTOR} .filter-panel__buttons-panel .dx-button-text`;
|
|
1311
1667
|
const el = await this.getElement();
|
|
1312
|
-
return el.findElements(
|
|
1668
|
+
return el.findElements(By22.css(selector));
|
|
1313
1669
|
}
|
|
1314
1670
|
constructor(formName, driver) {
|
|
1315
1671
|
super(driver, drawerSelector(formName));
|
|
@@ -1342,16 +1698,19 @@ var FilterPanel = class extends AbstractElement {
|
|
|
1342
1698
|
await this.driver.sleep(300);
|
|
1343
1699
|
}
|
|
1344
1700
|
async close() {
|
|
1345
|
-
const btn = await this.driver.findElement(
|
|
1701
|
+
const btn = await this.driver.findElement(By22.css(`${this.elementCssSelector} ${CLOSE_SELECTOR}`));
|
|
1346
1702
|
await click(btn, this.driver);
|
|
1347
1703
|
}
|
|
1348
1704
|
};
|
|
1349
1705
|
|
|
1350
1706
|
// src/pageObjects/elements/Forms/ListForm.ts
|
|
1707
|
+
var DATAGRID_HEADER_CSS_SELECTOR = ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
|
|
1351
1708
|
var ListForm = class extends AbstractForm {
|
|
1709
|
+
headerCssSelector;
|
|
1352
1710
|
constructor(driver) {
|
|
1353
1711
|
super(driver);
|
|
1354
1712
|
this.popupContainerCssSelector = `.popup .form-inline-${this.formName}`;
|
|
1713
|
+
this.headerCssSelector = DATAGRID_HEADER_CSS_SELECTOR;
|
|
1355
1714
|
}
|
|
1356
1715
|
/**
|
|
1357
1716
|
* Находит таблицу
|
|
@@ -1361,7 +1720,7 @@ var ListForm = class extends AbstractForm {
|
|
|
1361
1720
|
* expect(listForm.table());
|
|
1362
1721
|
*/
|
|
1363
1722
|
table() {
|
|
1364
|
-
return new Table(this.containerCssSelector, this.formName, this.driver);
|
|
1723
|
+
return new Table(this.containerCssSelector, this.headerCssSelector, this.formName, this.driver);
|
|
1365
1724
|
}
|
|
1366
1725
|
/**
|
|
1367
1726
|
* Находит группу на лист форме по имени
|
|
@@ -1406,8 +1765,67 @@ var ListForm = class extends AbstractForm {
|
|
|
1406
1765
|
return new FilterPanel(this.formName, this.driver);
|
|
1407
1766
|
}
|
|
1408
1767
|
};
|
|
1768
|
+
|
|
1769
|
+
// src/pageObjects/elements/Forms/TreeView.ts
|
|
1770
|
+
var TREELIST_HEADER_CSS_SELECTOR = ".dx-treelist-headers .dx-treelist-content:not(.dx-datagrid-content-fixed)";
|
|
1771
|
+
var TreeView = class extends ListForm {
|
|
1772
|
+
constructor(driver) {
|
|
1773
|
+
super(driver);
|
|
1774
|
+
this.popupContainerCssSelector = `.popup .wrapper-tree-view-${this.formName}`;
|
|
1775
|
+
this.headerCssSelector = TREELIST_HEADER_CSS_SELECTOR;
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1778
|
+
|
|
1779
|
+
// src/pageObjects/elements/Dialog.ts
|
|
1780
|
+
import { By as By23 } from "selenium-webdriver";
|
|
1781
|
+
var DIALOG_CLASS = ".d5-dialog";
|
|
1782
|
+
var DIALOG_TITLE_CLASS = ".dialog__title";
|
|
1783
|
+
var DIALOG_TEXT_CLASS = ".dialog__text";
|
|
1784
|
+
var DIALOG_BUTTONS_PANEL_CLASS = ".dialog__buttons-panel";
|
|
1785
|
+
var buttonByTextXpath2 = (text) => `.//span[contains(@class, "dx-button-text") and contains(text(), "${text}")]`;
|
|
1786
|
+
var DialogButton = class extends AbstractButton {
|
|
1787
|
+
text;
|
|
1788
|
+
constructor(parentCssSelector, text, driver) {
|
|
1789
|
+
super(parentCssSelector, "", driver);
|
|
1790
|
+
this.text = text;
|
|
1791
|
+
}
|
|
1792
|
+
async getElement() {
|
|
1793
|
+
const panel = await super.getElement();
|
|
1794
|
+
return panel.findElement(By23.xpath(buttonByTextXpath2(this.text)));
|
|
1795
|
+
}
|
|
1796
|
+
buttonNotDisplayedError() {
|
|
1797
|
+
return `Dialog button ${this.text} cannot be clicked. It is not displayed or it is disabled`;
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
var Dialog = class extends AbstractElement {
|
|
1801
|
+
constructor(driver) {
|
|
1802
|
+
super(driver, DIALOG_CLASS);
|
|
1803
|
+
}
|
|
1804
|
+
get titleSelector() {
|
|
1805
|
+
return this.joinRelativeCssSelectors([DIALOG_CLASS, DIALOG_TITLE_CLASS]);
|
|
1806
|
+
}
|
|
1807
|
+
get textSelector() {
|
|
1808
|
+
return this.joinRelativeCssSelectors([DIALOG_CLASS, DIALOG_TEXT_CLASS]);
|
|
1809
|
+
}
|
|
1810
|
+
get buttonsSelector() {
|
|
1811
|
+
return this.joinRelativeCssSelectors([DIALOG_CLASS, DIALOG_BUTTONS_PANEL_CLASS]);
|
|
1812
|
+
}
|
|
1813
|
+
async title() {
|
|
1814
|
+
const el = await this.driver.findElement(By23.css(this.titleSelector));
|
|
1815
|
+
return await el.getText();
|
|
1816
|
+
}
|
|
1817
|
+
async text() {
|
|
1818
|
+
const el = await this.driver.findElement(By23.css(this.textSelector));
|
|
1819
|
+
return await el.getText();
|
|
1820
|
+
}
|
|
1821
|
+
button(text) {
|
|
1822
|
+
return new DialogButton(this.buttonsSelector, text, this.driver);
|
|
1823
|
+
}
|
|
1824
|
+
};
|
|
1409
1825
|
export {
|
|
1410
1826
|
AbstractPage,
|
|
1827
|
+
ControlClass,
|
|
1828
|
+
Dialog,
|
|
1411
1829
|
FilterPanel,
|
|
1412
1830
|
FormEdit,
|
|
1413
1831
|
FormField,
|
|
@@ -1418,6 +1836,7 @@ export {
|
|
|
1418
1836
|
PanelFilterField,
|
|
1419
1837
|
SubsystemsPanel,
|
|
1420
1838
|
TextEditor,
|
|
1839
|
+
TreeView,
|
|
1421
1840
|
byTestId,
|
|
1422
1841
|
byTestIdCssSelector,
|
|
1423
1842
|
click,
|
|
@@ -1425,6 +1844,7 @@ export {
|
|
|
1425
1844
|
createDriver,
|
|
1426
1845
|
editorFactory,
|
|
1427
1846
|
elementIsNotPresent,
|
|
1847
|
+
readonlyLocator,
|
|
1428
1848
|
signIn,
|
|
1429
1849
|
wait,
|
|
1430
1850
|
waitElementIsVisible
|