d5-testing-library 1.8.0-alpha.8 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FormEdit-QNZOB7PA.mjs +7 -0
- package/dist/ListForm-MXGUBMWS.mjs +7 -0
- package/dist/TreeView-VZBOZCFW.mjs +8 -0
- package/dist/{chunk-K6JEWF3Y.mjs → chunk-32KSAOFJ.mjs} +171 -147
- package/dist/{chunk-S6ZF7DZF.mjs → chunk-75FRHQCI.mjs} +5 -2
- package/dist/{chunk-7TTKFTZM.mjs → chunk-S62QEWWA.mjs} +450 -120
- package/dist/{chunk-43FE34WA.mjs → chunk-XGIXXZD6.mjs} +3 -3
- package/dist/cjs/d5-testing-library.cjs +785 -325
- package/dist/{d5-testing-library.d.ts → d5-testing-library.d.mts} +196 -72
- package/dist/d5-testing-library.legacy-esm.js +83 -28
- package/dist/d5-testing-library.mjs +83 -28
- package/package.json +23 -11
- package/dist/FormEdit-5JMOGDF5.mjs +0 -7
- package/dist/ListForm-RYJQQ7PK.mjs +0 -7
- package/dist/TreeView-YRHW5YVA.mjs +0 -8
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
// src/config.ts
|
|
2
|
-
import * as process from "node:process";
|
|
3
|
-
var driversMap = /* @__PURE__ */ new Map();
|
|
4
|
-
var createConfigProxy = (config2) => {
|
|
5
|
-
return new Proxy(config2, {
|
|
6
|
-
get(_target, prop) {
|
|
7
|
-
if (prop === "driver") {
|
|
8
|
-
return driversMap.get(process.pid);
|
|
9
|
-
}
|
|
10
|
-
return Reflect.get(...arguments);
|
|
11
|
-
},
|
|
12
|
-
set(_target, prop, value) {
|
|
13
|
-
if (prop === "driver") {
|
|
14
|
-
driversMap.set(process.pid, value);
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
return Reflect.set(...arguments);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
2
|
var Config = class _Config {
|
|
22
3
|
static instance;
|
|
23
4
|
appConfig;
|
|
@@ -28,8 +9,7 @@ var Config = class _Config {
|
|
|
28
9
|
return _Config.instance;
|
|
29
10
|
}
|
|
30
11
|
config = (cfg) => {
|
|
31
|
-
if (!cfg)
|
|
32
|
-
return createConfigProxy(this.appConfig);
|
|
12
|
+
if (!cfg) return this.appConfig;
|
|
33
13
|
this.appConfig = cfg;
|
|
34
14
|
};
|
|
35
15
|
};
|
|
@@ -45,23 +25,38 @@ import { By } from "selenium-webdriver";
|
|
|
45
25
|
function fixElementStaleError(by, driver) {
|
|
46
26
|
const maxCount = 3;
|
|
47
27
|
let err;
|
|
48
|
-
const call = async (times
|
|
49
|
-
if (times > maxCount)
|
|
50
|
-
throw err;
|
|
28
|
+
const call = async (times) => {
|
|
29
|
+
if (times > maxCount) throw err;
|
|
51
30
|
try {
|
|
52
31
|
let el = await driver.findElement(by);
|
|
53
32
|
await el.getAttribute("class");
|
|
54
33
|
return el;
|
|
55
34
|
} catch (e) {
|
|
56
35
|
err = e;
|
|
57
|
-
if (e instanceof Error && e.
|
|
58
|
-
return call(
|
|
36
|
+
if (e instanceof Error && e.message.toLowerCase().includes("stale element")) {
|
|
37
|
+
return call(times + 1);
|
|
59
38
|
}
|
|
60
39
|
}
|
|
61
|
-
if (err)
|
|
62
|
-
throw err;
|
|
40
|
+
if (err) throw err;
|
|
63
41
|
};
|
|
64
|
-
return call();
|
|
42
|
+
return call(0);
|
|
43
|
+
}
|
|
44
|
+
async function staleElementAction(action) {
|
|
45
|
+
const maxCount = 3;
|
|
46
|
+
let err;
|
|
47
|
+
const call = async (times) => {
|
|
48
|
+
if (times > maxCount) throw err;
|
|
49
|
+
try {
|
|
50
|
+
await action();
|
|
51
|
+
} catch (e) {
|
|
52
|
+
err = e;
|
|
53
|
+
if (e instanceof Error && e.message.toLowerCase().includes("stale element")) {
|
|
54
|
+
await call(times + 1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (err) throw err;
|
|
58
|
+
};
|
|
59
|
+
await call(0);
|
|
65
60
|
}
|
|
66
61
|
|
|
67
62
|
// src/pageObjects/AbstractElement.ts
|
|
@@ -69,7 +64,7 @@ var AbstractElement = class {
|
|
|
69
64
|
driver;
|
|
70
65
|
elementCssSelector;
|
|
71
66
|
constructor(driver, elementCssSelector) {
|
|
72
|
-
this.driver = driver
|
|
67
|
+
this.driver = driver;
|
|
73
68
|
this.elementCssSelector = elementCssSelector;
|
|
74
69
|
}
|
|
75
70
|
getFullCssSelector() {
|
|
@@ -124,32 +119,47 @@ var AbstractPage = class extends AbstractElement {
|
|
|
124
119
|
|
|
125
120
|
// src/utils/wait.ts
|
|
126
121
|
async function wait(condition, driver, errorMessage, timeout) {
|
|
127
|
-
driver = driver ?? config().driver;
|
|
128
122
|
await driver.wait(condition, timeout ?? config().timeout, errorMessage);
|
|
129
123
|
}
|
|
124
|
+
function safeWait(condition, driver, errorMessage, timeout) {
|
|
125
|
+
return wait(async () => {
|
|
126
|
+
try {
|
|
127
|
+
return await condition(driver);
|
|
128
|
+
} catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}, driver, errorMessage, timeout);
|
|
132
|
+
}
|
|
130
133
|
|
|
131
134
|
// src/utils/waitElementIsVisible.ts
|
|
132
|
-
import { until } from "selenium-webdriver";
|
|
133
135
|
async function waitElementIsVisible({
|
|
134
|
-
element,
|
|
135
136
|
timeout,
|
|
136
137
|
errorMessage,
|
|
137
|
-
driver
|
|
138
|
+
driver,
|
|
139
|
+
...rest
|
|
138
140
|
}) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
await safeWait(async () => {
|
|
142
|
+
const searchedElement = "by" in rest ? await fixElementStaleError(rest.by, driver) : rest.element;
|
|
143
|
+
return await searchedElement.isDisplayed();
|
|
144
|
+
}, driver, errorMessage ?? "Element is not visible", timeout ?? config().timeout);
|
|
142
145
|
}
|
|
146
|
+
var waitElementIsVisible_default = waitElementIsVisible;
|
|
143
147
|
|
|
144
148
|
// src/utils/actions.ts
|
|
145
149
|
var click = async (webElement, driver) => {
|
|
146
|
-
driver = driver ?? config().driver;
|
|
147
150
|
if (!await webElement.isDisplayed()) {
|
|
148
151
|
await driver.executeScript("arguments[0].scrollIntoView(true);", webElement);
|
|
149
152
|
}
|
|
150
153
|
const actions = driver.actions({ async: true });
|
|
151
154
|
await actions.move({ origin: webElement }).click().perform();
|
|
152
155
|
};
|
|
156
|
+
var contextMenu = async (webElement, driver) => {
|
|
157
|
+
if (!await webElement.isDisplayed()) {
|
|
158
|
+
await driver.executeScript("arguments[0].scrollIntoView(true);", webElement);
|
|
159
|
+
}
|
|
160
|
+
const actions = driver.actions({ async: true });
|
|
161
|
+
await actions.move({ origin: webElement }).contextClick().perform();
|
|
162
|
+
};
|
|
153
163
|
|
|
154
164
|
// src/utils/locators.ts
|
|
155
165
|
import { By as By2 } from "selenium-webdriver";
|
|
@@ -161,6 +171,21 @@ var byTestId = (testId, element = "div") => {
|
|
|
161
171
|
};
|
|
162
172
|
var readonlyLocator = "readonly";
|
|
163
173
|
|
|
174
|
+
// src/utils/waitElementIsClickable.ts
|
|
175
|
+
async function waitElementIsClickable({
|
|
176
|
+
timeout,
|
|
177
|
+
errorMessage,
|
|
178
|
+
driver,
|
|
179
|
+
...rest
|
|
180
|
+
}) {
|
|
181
|
+
await safeWait(async () => {
|
|
182
|
+
const searchedElement = "by" in rest ? await fixElementStaleError(rest.by, driver) : rest.element;
|
|
183
|
+
const isDisabled = await searchedElement.getCssValue("pointer-events") === "none";
|
|
184
|
+
return await searchedElement.isDisplayed() && !isDisabled;
|
|
185
|
+
}, driver, errorMessage, timeout ?? config().timeout);
|
|
186
|
+
}
|
|
187
|
+
var waitElementIsClickable_default = waitElementIsClickable;
|
|
188
|
+
|
|
164
189
|
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
165
190
|
import { By as By3, Key } from "selenium-webdriver";
|
|
166
191
|
|
|
@@ -226,8 +251,9 @@ var TextEditor = class extends AbstractDXEditorWithInput {
|
|
|
226
251
|
super(parentCssSelector, elementCssSelector, driver);
|
|
227
252
|
this.setClearStrategy(new InputClearStrategy());
|
|
228
253
|
}
|
|
229
|
-
getValue() {
|
|
230
|
-
|
|
254
|
+
async getValue() {
|
|
255
|
+
const value = await super.getInputValue();
|
|
256
|
+
return value == "" ? null : value;
|
|
231
257
|
}
|
|
232
258
|
setValue(value) {
|
|
233
259
|
return this.setInputValue(value);
|
|
@@ -277,10 +303,8 @@ var AbstractFormElement = class extends AbstractElementWithParent {
|
|
|
277
303
|
var CheckBox = class extends AbstractElementWithParent {
|
|
278
304
|
async getValue() {
|
|
279
305
|
const result = await this.getAttribute("aria-checked");
|
|
280
|
-
if (result === "true")
|
|
281
|
-
|
|
282
|
-
if (result === "false")
|
|
283
|
-
return 0;
|
|
306
|
+
if (result === "true") return 1;
|
|
307
|
+
if (result === "false") return 0;
|
|
284
308
|
return null;
|
|
285
309
|
}
|
|
286
310
|
async setValue(value) {
|
|
@@ -376,10 +400,8 @@ var SelectBoxEditor = class extends AbstractDXEditorWithInput {
|
|
|
376
400
|
var SwitchEditor = class extends AbstractElementWithParent {
|
|
377
401
|
async getValue() {
|
|
378
402
|
const result = await this.getAttribute("aria-label");
|
|
379
|
-
if (result === "ON")
|
|
380
|
-
|
|
381
|
-
if (result === "OFF")
|
|
382
|
-
return 0;
|
|
403
|
+
if (result === "ON") return 1;
|
|
404
|
+
if (result === "OFF") return 0;
|
|
383
405
|
return null;
|
|
384
406
|
}
|
|
385
407
|
async setValue(value) {
|
|
@@ -392,7 +414,7 @@ var SwitchEditor = class extends AbstractElementWithParent {
|
|
|
392
414
|
return;
|
|
393
415
|
}
|
|
394
416
|
await click(inputEl, this.driver);
|
|
395
|
-
await
|
|
417
|
+
await safeWait(async () => {
|
|
396
418
|
const updatedValue = await this.getValue();
|
|
397
419
|
return updatedValue !== currentValue;
|
|
398
420
|
}, this.driver);
|
|
@@ -421,7 +443,8 @@ var TagBox = class extends AbstractDXEditorWithInput {
|
|
|
421
443
|
await this.confirmSelection();
|
|
422
444
|
}
|
|
423
445
|
async waitOptionSelection() {
|
|
424
|
-
await fixElementStaleError(By6.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
|
|
446
|
+
const option = await fixElementStaleError(By6.css(TAG_BOX_LIST_ITEM_SELECTOR), this.driver);
|
|
447
|
+
await safeWait(() => option.isDisplayed(), this.driver);
|
|
425
448
|
}
|
|
426
449
|
async selectOption(inputEl, value, lastElement) {
|
|
427
450
|
try {
|
|
@@ -505,8 +528,7 @@ var ButtonGroup = class extends AbstractElementWithParent {
|
|
|
505
528
|
break;
|
|
506
529
|
}
|
|
507
530
|
}
|
|
508
|
-
if (!buttonEl)
|
|
509
|
-
throw new Error(`Cannot find item in button group with text: ${value}`);
|
|
531
|
+
if (!buttonEl) throw new Error(`Cannot find item in button group with text: ${value}`);
|
|
510
532
|
await click(buttonEl, this.driver);
|
|
511
533
|
}
|
|
512
534
|
};
|
|
@@ -547,33 +569,35 @@ var BaseDateEditor = class extends AbstractDXEditorWithInput {
|
|
|
547
569
|
super(parentCssSelector, elementCssSelector, driver);
|
|
548
570
|
this.setClearStrategy(new InputClearStrategy());
|
|
549
571
|
}
|
|
550
|
-
async
|
|
551
|
-
const actions = this.driver.actions({ async: true });
|
|
572
|
+
async setArrayValue(value) {
|
|
552
573
|
const dateField = await this.driver.findElement(By8.css(`${this.getFullCssSelector()}`));
|
|
553
574
|
const dateFieldDataTestID = await this.getDataTestId();
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
await
|
|
575
|
+
const button = await dateField.findElement(By8.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
|
|
576
|
+
await click(button, this.driver);
|
|
577
|
+
const calendarPopoverElement = await this.driver.findElement(By8.css(byTestIdCssSelector(`${dateFieldDataTestID}-calendar-popover`)));
|
|
578
|
+
const dateFromInput = await calendarPopoverElement.findElement(
|
|
579
|
+
By8.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`)
|
|
580
|
+
);
|
|
581
|
+
const dateToInput = await calendarPopoverElement.findElement(
|
|
582
|
+
By8.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`)
|
|
583
|
+
);
|
|
584
|
+
await this.setSingleValue(value[0], dateFromInput);
|
|
585
|
+
await this.setSingleValue(value[1], dateToInput);
|
|
586
|
+
const btnOk = await this.driver.findElement(By8.css(`.${BTN_SAVE_SELECTOR}`));
|
|
587
|
+
await click(btnOk, this.driver);
|
|
588
|
+
}
|
|
589
|
+
async setSingleValue(value, inputEl) {
|
|
590
|
+
const actions = this.driver.actions({ async: true });
|
|
591
|
+
const formattedDate = formatDMYDate(value);
|
|
592
|
+
await click(inputEl, this.driver);
|
|
593
|
+
await actions.move({ origin: inputEl }).sendKeys(Key3.HOME).perform();
|
|
594
|
+
await actions.move({ origin: inputEl }).sendKeys(formattedDate, Key3.ENTER).perform();
|
|
595
|
+
}
|
|
596
|
+
async setDateValue(value) {
|
|
557
597
|
if (Array.isArray(value)) {
|
|
558
|
-
|
|
559
|
-
const button = await dateField.findElement(By8.css(`.${BTN_CALENDAR_POPOVER_OPEN_SELECTOR}`));
|
|
560
|
-
await button.click();
|
|
561
|
-
const calendarPopoverElement = await this.driver.findElement(By8.css(calendarPopoverSelector));
|
|
562
|
-
const dateFromInput = await calendarPopoverElement.findElement(By8.css(`.${BTN_CALENDAR_POPOVER_DATE_FROM_INPUT_SELECTOR} .dx-texteditor-input`));
|
|
563
|
-
const dateToInput = await calendarPopoverElement.findElement(By8.css(`.${BTN_CALENDAR_POPOVER_DATE_TO_INPUT_SELECTOR} .dx-texteditor-input`));
|
|
564
|
-
await dateFromInput.click();
|
|
565
|
-
await dateFromInput.sendKeys(formattedDates[0]);
|
|
566
|
-
await dateToInput.click();
|
|
567
|
-
await actions.move({ origin: dateInputEl }).sendKeys(Key3.HOME).perform();
|
|
568
|
-
await dateToInput.sendKeys(formattedDates[1]);
|
|
569
|
-
await actions.move({ origin: dateInputEl }).sendKeys(Key3.ENTER).perform();
|
|
570
|
-
const btnOk = await this.driver.findElement(By8.css(`.${BTN_SAVE_SELECTOR}`));
|
|
571
|
-
await btnOk.click();
|
|
598
|
+
await this.setArrayValue(value);
|
|
572
599
|
} else {
|
|
573
|
-
|
|
574
|
-
await click(dateInputEl, this.driver);
|
|
575
|
-
await actions.move({ origin: dateInputEl }).sendKeys(Key3.HOME).perform();
|
|
576
|
-
await actions.move({ origin: dateInputEl }).sendKeys(formattedDate, Key3.ENTER).perform();
|
|
600
|
+
await this.setSingleValue(value, await this.getInputElement());
|
|
577
601
|
}
|
|
578
602
|
}
|
|
579
603
|
};
|
|
@@ -636,15 +660,14 @@ var DateRangeEditor = class extends BaseDateEditor {
|
|
|
636
660
|
// src/pageObjects/elements/Editors/Date/DateEditor.ts
|
|
637
661
|
var DateEditor = class extends AbstractDXEditorWithInput {
|
|
638
662
|
editorInstance = null;
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
async init(parentCssSelector, elementCssSelector, driver) {
|
|
645
|
-
await this.updateEditorInstance(parentCssSelector, elementCssSelector, driver);
|
|
663
|
+
async init() {
|
|
664
|
+
if (this.editorInstance) {
|
|
665
|
+
return this.editorInstance;
|
|
666
|
+
}
|
|
667
|
+
await this.setEditorInstance();
|
|
646
668
|
}
|
|
647
|
-
async
|
|
669
|
+
async setEditorInstance() {
|
|
670
|
+
const { parentCssSelector, elementCssSelector, driver } = this;
|
|
648
671
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
|
|
649
672
|
const classString = await elementInstance.getClasses();
|
|
650
673
|
switch (true) {
|
|
@@ -658,25 +681,14 @@ var DateEditor = class extends AbstractDXEditorWithInput {
|
|
|
658
681
|
this.editorInstance = new SingleDateEditor(parentCssSelector, elementCssSelector, driver);
|
|
659
682
|
}
|
|
660
683
|
}
|
|
661
|
-
async ensureInitialized() {
|
|
662
|
-
if (!this.editorInstance) {
|
|
663
|
-
await this.initPromise;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
684
|
async setValue(value) {
|
|
667
|
-
await this.
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
return await this.updateEditorInstance(this.parentCssSelector, this.elementCssSelector, this.driver);
|
|
671
|
-
}
|
|
672
|
-
throw new Error("Editor instance is not initialized.");
|
|
685
|
+
await this.init();
|
|
686
|
+
await this.editorInstance.setValue(value);
|
|
687
|
+
await this.setEditorInstance();
|
|
673
688
|
}
|
|
674
689
|
async getValue() {
|
|
675
|
-
await this.
|
|
676
|
-
|
|
677
|
-
return this.editorInstance.getValue();
|
|
678
|
-
}
|
|
679
|
-
throw new Error("Editor instance is not initialized.");
|
|
690
|
+
await this.init();
|
|
691
|
+
return this.editorInstance.getValue();
|
|
680
692
|
}
|
|
681
693
|
};
|
|
682
694
|
|
|
@@ -777,16 +789,12 @@ var editorFactory = async (parentCssSelector, elementCssSelector, driver) => {
|
|
|
777
789
|
const classSting = await elementInstance.getClasses();
|
|
778
790
|
if ((classSting.includes("text-control" /* Text */) || classSting.includes("text-area-control" /* TextArea */)) && !classSting.includes("single-date-range-control" /* SingleDateRange */))
|
|
779
791
|
return new TextEditor(parentCssSelector, elementCssSelector, driver);
|
|
780
|
-
if (classSting.includes("number-control" /* Number */))
|
|
781
|
-
|
|
782
|
-
if (classSting.includes("
|
|
783
|
-
return new CheckBox(parentCssSelector, elementCssSelector, driver);
|
|
784
|
-
if (classSting.includes("multi-select-control" /* Multiselect */))
|
|
785
|
-
return new TagBox(parentCssSelector, elementCssSelector, driver);
|
|
792
|
+
if (classSting.includes("number-control" /* Number */)) return new NumberEditor(parentCssSelector, elementCssSelector, driver);
|
|
793
|
+
if (classSting.includes("check-box" /* CheckBox */)) return new CheckBox(parentCssSelector, elementCssSelector, driver);
|
|
794
|
+
if (classSting.includes("multi-select-control" /* Multiselect */)) return new TagBox(parentCssSelector, elementCssSelector, driver);
|
|
786
795
|
if (classSting.includes("select-control" /* Select */))
|
|
787
796
|
return new SelectBoxEditor(parentCssSelector, elementCssSelector, driver);
|
|
788
|
-
if (classSting.includes("switch-control" /* Switch */))
|
|
789
|
-
return new SwitchEditor(parentCssSelector, elementCssSelector, driver);
|
|
797
|
+
if (classSting.includes("switch-control" /* Switch */)) return new SwitchEditor(parentCssSelector, elementCssSelector, driver);
|
|
790
798
|
if (classSting.includes("date-control" /* Date */) || classSting.includes("single-date-range-control" /* SingleDateRange */)) {
|
|
791
799
|
return new DateEditor(parentCssSelector, elementCssSelector, driver);
|
|
792
800
|
}
|
|
@@ -834,20 +842,6 @@ function createEditorButtonTestId(itemName) {
|
|
|
834
842
|
return `${"editor-button" /* EDITOR_BUTTON */}-${itemName}`;
|
|
835
843
|
}
|
|
836
844
|
|
|
837
|
-
// src/utils/waitElementIsClickable.ts
|
|
838
|
-
async function waitElementIsClickable({
|
|
839
|
-
element,
|
|
840
|
-
timeout,
|
|
841
|
-
errorMessage,
|
|
842
|
-
driver
|
|
843
|
-
}) {
|
|
844
|
-
driver = driver ?? config().driver;
|
|
845
|
-
await wait(async () => {
|
|
846
|
-
const isDisabled = await element.getCssValue("pointer-events") === "none";
|
|
847
|
-
return await element.isDisplayed() && !isDisabled;
|
|
848
|
-
}, driver, errorMessage, timeout ?? config().timeout);
|
|
849
|
-
}
|
|
850
|
-
|
|
851
845
|
// src/pageObjects/elements/EditorButton.ts
|
|
852
846
|
var EditorButton = class extends AbstractElementWithParent {
|
|
853
847
|
name;
|
|
@@ -860,7 +854,7 @@ var EditorButton = class extends AbstractElementWithParent {
|
|
|
860
854
|
}
|
|
861
855
|
async click() {
|
|
862
856
|
const button = await this.getElement();
|
|
863
|
-
await
|
|
857
|
+
await waitElementIsClickable_default({
|
|
864
858
|
element: button,
|
|
865
859
|
errorMessage: this.buttonNotDisplayedError(),
|
|
866
860
|
driver: this.driver
|
|
@@ -942,6 +936,21 @@ var AbstractEditor = class extends AbstractElementWithParent {
|
|
|
942
936
|
await this.initEditor();
|
|
943
937
|
return this.editor.isReadonly();
|
|
944
938
|
}
|
|
939
|
+
/**
|
|
940
|
+
* Возвращает значение true|false в зависимости isDisplayed поле или нет
|
|
941
|
+
* @example
|
|
942
|
+
* expect(await formEdit.field('NumberFld').isDisplayed()).toBe(true);
|
|
943
|
+
* expect(await formEdit.field('TextFld').isDisplayed()).toBe(false);
|
|
944
|
+
*/
|
|
945
|
+
async isDisplayed() {
|
|
946
|
+
try {
|
|
947
|
+
await this.initEditor();
|
|
948
|
+
const element = await this.getElement();
|
|
949
|
+
return await element.isDisplayed();
|
|
950
|
+
} catch {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
945
954
|
/**
|
|
946
955
|
* Находит кнопку на поле по имени
|
|
947
956
|
* @example
|
|
@@ -964,14 +973,14 @@ var FormField = class extends AbstractEditor {
|
|
|
964
973
|
// src/pageObjects/elements/Forms/Form.ts
|
|
965
974
|
import { By as By15 } from "selenium-webdriver";
|
|
966
975
|
|
|
967
|
-
// src/pageObjects/elements/
|
|
976
|
+
// src/pageObjects/elements/AbstractButton.ts
|
|
968
977
|
var AbstractButton = class extends AbstractElementWithParent {
|
|
969
978
|
constructor(parentCssSelector, elementCssSelector, driver) {
|
|
970
979
|
super(parentCssSelector, elementCssSelector, driver);
|
|
971
980
|
}
|
|
972
981
|
async click() {
|
|
973
982
|
const button = await this.getElement();
|
|
974
|
-
await
|
|
983
|
+
await waitElementIsClickable_default({
|
|
975
984
|
element: button,
|
|
976
985
|
errorMessage: this.buttonNotDisplayedError(),
|
|
977
986
|
driver: this.driver
|
|
@@ -983,8 +992,12 @@ var AbstractButton = class extends AbstractElementWithParent {
|
|
|
983
992
|
return await button.getCssValue("pointer-events") === "none";
|
|
984
993
|
}
|
|
985
994
|
async isDisplayed() {
|
|
986
|
-
|
|
987
|
-
|
|
995
|
+
try {
|
|
996
|
+
const button = await this.getElement();
|
|
997
|
+
return await button.isDisplayed();
|
|
998
|
+
} catch {
|
|
999
|
+
return false;
|
|
1000
|
+
}
|
|
988
1001
|
}
|
|
989
1002
|
};
|
|
990
1003
|
|
|
@@ -1012,6 +1025,9 @@ var FormButton = class extends DXButton {
|
|
|
1012
1025
|
buttonNotDisplayedError() {
|
|
1013
1026
|
return `Form Button ${this.name} cannot be clicked. It is not displayed or it is disabled`;
|
|
1014
1027
|
}
|
|
1028
|
+
async getTitle() {
|
|
1029
|
+
return await this.getText();
|
|
1030
|
+
}
|
|
1015
1031
|
};
|
|
1016
1032
|
|
|
1017
1033
|
// src/pageObjects/elements/Groups/AbstractGroup.ts
|
|
@@ -1106,16 +1122,11 @@ var Accordion = class extends AbstractGroup {
|
|
|
1106
1122
|
var groupFactory = async (parentCssSelector, elementCssSelector, driver) => {
|
|
1107
1123
|
const elementInstance = new AbstractFormElement(parentCssSelector, elementCssSelector, driver);
|
|
1108
1124
|
const classSting = await elementInstance.getClasses();
|
|
1109
|
-
if (classSting.includes("tab-panel-group"))
|
|
1110
|
-
|
|
1111
|
-
if (classSting.includes("
|
|
1112
|
-
|
|
1113
|
-
if (classSting.includes("
|
|
1114
|
-
return new Panel(parentCssSelector, elementCssSelector, driver);
|
|
1115
|
-
if (classSting.includes("accordion-group"))
|
|
1116
|
-
return new Accordion(parentCssSelector, elementCssSelector, driver);
|
|
1117
|
-
if (classSting.includes("d5-accordion-item"))
|
|
1118
|
-
return new AccordionItem(parentCssSelector, elementCssSelector, driver);
|
|
1125
|
+
if (classSting.includes("tab-panel-group")) return new TabPanel(parentCssSelector, elementCssSelector, driver);
|
|
1126
|
+
if (classSting.includes("tab-panel-item")) return new TabPanelItem(parentCssSelector, elementCssSelector, driver);
|
|
1127
|
+
if (classSting.includes("panel-group")) return new Panel(parentCssSelector, elementCssSelector, driver);
|
|
1128
|
+
if (classSting.includes("accordion-group")) return new Accordion(parentCssSelector, elementCssSelector, driver);
|
|
1129
|
+
if (classSting.includes("d5-accordion-item")) return new AccordionItem(parentCssSelector, elementCssSelector, driver);
|
|
1119
1130
|
throw new Error("Unknown type of group. Please write ticket to the support");
|
|
1120
1131
|
};
|
|
1121
1132
|
|
|
@@ -1246,23 +1257,28 @@ var AbstractForm = class extends AbstractPage {
|
|
|
1246
1257
|
};
|
|
1247
1258
|
|
|
1248
1259
|
// src/pageObjects/elements/Forms/createSubFormInstance.ts
|
|
1260
|
+
var SECONDARY_DRAWER_LAYOUT_CONTENT = ".secondary-drawer-layout-content";
|
|
1249
1261
|
var subFormTestId = (name) => `subform-${name}`;
|
|
1250
|
-
function subformCssSelector(parentCssSelector, testId) {
|
|
1251
|
-
|
|
1262
|
+
function subformCssSelector(parentCssSelector, testId, isDockPanel = false) {
|
|
1263
|
+
if (isDockPanel) {
|
|
1264
|
+
return `${SECONDARY_DRAWER_LAYOUT_CONTENT} ${byTestIdCssSelector(testId)}`;
|
|
1265
|
+
} else {
|
|
1266
|
+
return `${parentCssSelector} ${byTestIdCssSelector(testId)}`;
|
|
1267
|
+
}
|
|
1252
1268
|
}
|
|
1253
1269
|
async function classDependencyInjector(formType) {
|
|
1254
1270
|
let SubFormFactoryClass;
|
|
1255
1271
|
switch (formType) {
|
|
1256
1272
|
case "1" /* LIST */:
|
|
1257
|
-
SubFormFactoryClass = (await import("./ListForm-
|
|
1273
|
+
SubFormFactoryClass = (await import("./ListForm-MXGUBMWS.mjs")).default;
|
|
1258
1274
|
break;
|
|
1259
1275
|
case "3" /* TREE */:
|
|
1260
|
-
SubFormFactoryClass = (await import("./TreeView-
|
|
1276
|
+
SubFormFactoryClass = (await import("./TreeView-VZBOZCFW.mjs")).default;
|
|
1261
1277
|
break;
|
|
1262
1278
|
case "2" /* EDIT */:
|
|
1263
1279
|
case "99" /* FREE_FORM */:
|
|
1264
1280
|
case "4" /* REPORT */:
|
|
1265
|
-
SubFormFactoryClass = (await import("./FormEdit-
|
|
1281
|
+
SubFormFactoryClass = (await import("./FormEdit-QNZOB7PA.mjs")).default;
|
|
1266
1282
|
break;
|
|
1267
1283
|
default:
|
|
1268
1284
|
throw new Error(`Unsupported form type ${formType}`);
|
|
@@ -1293,6 +1309,11 @@ var Form = class extends AbstractForm {
|
|
|
1293
1309
|
async getTitleText() {
|
|
1294
1310
|
if (await this.isModal()) {
|
|
1295
1311
|
const titleEl2 = await this.driver.findElement(By15.css(`${this.popupContainerCssSelector} .popup-title`));
|
|
1312
|
+
await waitElementIsVisible_default({
|
|
1313
|
+
element: titleEl2,
|
|
1314
|
+
driver: this.driver,
|
|
1315
|
+
errorMessage: `Form title element is not visible`
|
|
1316
|
+
});
|
|
1296
1317
|
return titleEl2.getText();
|
|
1297
1318
|
}
|
|
1298
1319
|
let titleEl = await this.driver.findElement(By15.className("main-toolbar-form-title"));
|
|
@@ -1311,11 +1332,12 @@ var Form = class extends AbstractForm {
|
|
|
1311
1332
|
* //...
|
|
1312
1333
|
* expect(await form.subForm(name));
|
|
1313
1334
|
*/
|
|
1314
|
-
async subForm(name) {
|
|
1315
|
-
const
|
|
1335
|
+
async subForm(name, options = {}) {
|
|
1336
|
+
const { isDockPanel = false } = options;
|
|
1337
|
+
const cssSelector = subformCssSelector(this.containerCssSelector, subFormTestId(name), isDockPanel);
|
|
1316
1338
|
const byCssSelector = By15.css(cssSelector);
|
|
1317
1339
|
const subFormEl = await this.driver.findElement(byCssSelector);
|
|
1318
|
-
await
|
|
1340
|
+
await waitElementIsVisible_default({
|
|
1319
1341
|
element: subFormEl,
|
|
1320
1342
|
driver: this.driver,
|
|
1321
1343
|
errorMessage: `Subform "${name}" is not visible`
|
|
@@ -1339,14 +1361,17 @@ var Form = class extends AbstractForm {
|
|
|
1339
1361
|
export {
|
|
1340
1362
|
config,
|
|
1341
1363
|
fixElementStaleError,
|
|
1364
|
+
staleElementAction,
|
|
1342
1365
|
AbstractElement,
|
|
1343
1366
|
AbstractPage,
|
|
1344
|
-
|
|
1345
|
-
|
|
1367
|
+
safeWait,
|
|
1368
|
+
waitElementIsVisible_default,
|
|
1346
1369
|
click,
|
|
1370
|
+
contextMenu,
|
|
1347
1371
|
byTestIdCssSelector,
|
|
1348
1372
|
byTestId,
|
|
1349
1373
|
readonlyLocator,
|
|
1374
|
+
waitElementIsClickable_default,
|
|
1350
1375
|
AbstractElementWithParent,
|
|
1351
1376
|
TextEditor,
|
|
1352
1377
|
NumberEditor,
|
|
@@ -1358,7 +1383,6 @@ export {
|
|
|
1358
1383
|
createLayoutFilterTestId,
|
|
1359
1384
|
createTableId,
|
|
1360
1385
|
createSubSystemTestId,
|
|
1361
|
-
waitElementIsClickable,
|
|
1362
1386
|
AbstractButton,
|
|
1363
1387
|
AbstractEditor,
|
|
1364
1388
|
FormField,
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ListForm
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-S62QEWWA.mjs";
|
|
4
4
|
|
|
5
5
|
// src/pageObjects/elements/Forms/TreeView.ts
|
|
6
6
|
var TREELIST_HEADER_CSS_SELECTOR = ".dx-treelist-headers .dx-treelist-content:not(.dx-datagrid-content-fixed)";
|
|
7
|
+
var TREELIST_CONTENT_CSS_SELECTOR = ".dx-treelist-content:not(.dx-datagrid-content-fixed)";
|
|
7
8
|
var FIXED_TREELIST_CONTENT_CSS_SELECTOR = ".dx-fixed-columns .dx-treelist-content.dx-treelist-content-fixed";
|
|
8
9
|
var TreeView = class extends ListForm {
|
|
9
10
|
constructor(driver) {
|
|
10
11
|
super(driver);
|
|
11
|
-
this.popupContainerCssSelector = `.popup.
|
|
12
|
+
this.popupContainerCssSelector = `.popup.tree-view-${this.formName}`;
|
|
12
13
|
this.headerCssSelector = TREELIST_HEADER_CSS_SELECTOR;
|
|
13
14
|
this.fixedTableContentCssSelector = FIXED_TREELIST_CONTENT_CSS_SELECTOR;
|
|
15
|
+
this.contextMenuCssSelector = ".dx-treelist-container";
|
|
16
|
+
this.tableContentCssSelector = TREELIST_CONTENT_CSS_SELECTOR;
|
|
14
17
|
}
|
|
15
18
|
};
|
|
16
19
|
|