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