d5-testing-library 1.0.4 → 1.1.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 +524 -86
- package/dist/d5-testing-library.d.ts +122 -19
- package/dist/d5-testing-library.legacy-esm.js +502 -76
- package/dist/d5-testing-library.mjs +502 -76
- package/package.json +1 -1
|
@@ -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
|
};
|
|
@@ -59,7 +78,7 @@ var AbstractPage = class extends AbstractElement {
|
|
|
59
78
|
// src/utils/locators.ts
|
|
60
79
|
import { By } from "selenium-webdriver";
|
|
61
80
|
var byTestId = (testId, element = "div") => {
|
|
62
|
-
return By.css(`${element}[data-testid
|
|
81
|
+
return By.css(`${element}[data-testid="${testId}"]`);
|
|
63
82
|
};
|
|
64
83
|
|
|
65
84
|
// src/utils/createDriver.ts
|
|
@@ -81,6 +100,14 @@ var elementIsNotPresent = function elementIsNotPresent2(locator) {
|
|
|
81
100
|
});
|
|
82
101
|
};
|
|
83
102
|
|
|
103
|
+
// src/utils/waitElementIsVisible.ts
|
|
104
|
+
import { until } from "selenium-webdriver";
|
|
105
|
+
async function waitElementIsVisible({ element, timeout, errorMessage, driver }) {
|
|
106
|
+
driver = driver ?? config().driver;
|
|
107
|
+
const condition = until.elementIsVisible(element);
|
|
108
|
+
await driver.wait(condition.fn, timeout ?? 1e4, errorMessage ?? condition.description());
|
|
109
|
+
}
|
|
110
|
+
|
|
84
111
|
// src/pageObjects/AbstractElementWithParent.ts
|
|
85
112
|
var AbstractElementWithParent = class extends AbstractElement {
|
|
86
113
|
getParentElement;
|
|
@@ -91,7 +118,23 @@ var AbstractElementWithParent = class extends AbstractElement {
|
|
|
91
118
|
}
|
|
92
119
|
async getElement() {
|
|
93
120
|
const parentEl = await this.getParentElement();
|
|
94
|
-
|
|
121
|
+
await waitElementIsVisible({
|
|
122
|
+
element: parentEl,
|
|
123
|
+
driver: this.driver
|
|
124
|
+
});
|
|
125
|
+
const el = await parentEl.findElement(this.elementBy);
|
|
126
|
+
await waitElementIsVisible({
|
|
127
|
+
element: el,
|
|
128
|
+
driver: this.driver
|
|
129
|
+
});
|
|
130
|
+
return el;
|
|
131
|
+
}
|
|
132
|
+
async getAttribute(attr) {
|
|
133
|
+
const el = await this.getElement();
|
|
134
|
+
return await el.getAttribute(attr);
|
|
135
|
+
}
|
|
136
|
+
async getClasses() {
|
|
137
|
+
return await this.getAttribute("class");
|
|
95
138
|
}
|
|
96
139
|
};
|
|
97
140
|
|
|
@@ -177,7 +220,7 @@ var AbstractForm = class extends AbstractPage {
|
|
|
177
220
|
};
|
|
178
221
|
|
|
179
222
|
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
180
|
-
import { By as
|
|
223
|
+
import { By as By11 } from "selenium-webdriver";
|
|
181
224
|
|
|
182
225
|
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
183
226
|
import { By as By5, Key } from "selenium-webdriver";
|
|
@@ -190,8 +233,20 @@ var AbstractFormElement = class extends AbstractElementWithParent {
|
|
|
190
233
|
}
|
|
191
234
|
};
|
|
192
235
|
|
|
236
|
+
// src/pageObjects/elements/Editors/ClearStrategy/InputClearStrategy.ts
|
|
237
|
+
var InputClearStrategy = class {
|
|
238
|
+
async clear(editor) {
|
|
239
|
+
const inputEl = await editor.getInputElement();
|
|
240
|
+
await inputEl.clear();
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
193
244
|
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
194
245
|
var AbstractDXEditorWithInput = class extends AbstractFormElement {
|
|
246
|
+
clearStrategy = new InputClearStrategy();
|
|
247
|
+
setClearStrategy(strategy) {
|
|
248
|
+
this.clearStrategy = strategy;
|
|
249
|
+
}
|
|
195
250
|
async getInputElement() {
|
|
196
251
|
const controlEl = await this.getElement();
|
|
197
252
|
return controlEl.findElement(By5.className("dx-texteditor-input"));
|
|
@@ -202,13 +257,20 @@ var AbstractDXEditorWithInput = class extends AbstractFormElement {
|
|
|
202
257
|
}
|
|
203
258
|
async setInputValue(value) {
|
|
204
259
|
const inputEl = await this.getInputElement();
|
|
205
|
-
await inputEl.
|
|
260
|
+
await click(inputEl, this.driver);
|
|
206
261
|
await inputEl.sendKeys(value, Key.ENTER);
|
|
207
262
|
}
|
|
263
|
+
async clear() {
|
|
264
|
+
await this.clearStrategy.clear(this);
|
|
265
|
+
}
|
|
208
266
|
};
|
|
209
267
|
|
|
210
268
|
// src/pageObjects/elements/Editors/TextEditor.ts
|
|
211
269
|
var TextEditor = class extends AbstractDXEditorWithInput {
|
|
270
|
+
constructor(getParentElement, elementBy, driver) {
|
|
271
|
+
super(getParentElement, elementBy, driver);
|
|
272
|
+
this.setClearStrategy(new InputClearStrategy());
|
|
273
|
+
}
|
|
212
274
|
getValue() {
|
|
213
275
|
return this.getInputValue();
|
|
214
276
|
}
|
|
@@ -219,6 +281,10 @@ var TextEditor = class extends AbstractDXEditorWithInput {
|
|
|
219
281
|
|
|
220
282
|
// src/pageObjects/elements/Editors/NumberEditor.ts
|
|
221
283
|
var NumberEditor = class extends AbstractDXEditorWithInput {
|
|
284
|
+
constructor(getParentElement, elementBy, driver) {
|
|
285
|
+
super(getParentElement, elementBy, driver);
|
|
286
|
+
this.setClearStrategy(new InputClearStrategy());
|
|
287
|
+
}
|
|
222
288
|
async getValue() {
|
|
223
289
|
const value = await super.getInputValue();
|
|
224
290
|
return value == "" ? null : Number.parseFloat(value);
|
|
@@ -234,22 +300,22 @@ var CheckBox = class extends AbstractFormElement {
|
|
|
234
300
|
const inputEl = await this.getElement();
|
|
235
301
|
const result = await inputEl.getAttribute("aria-checked");
|
|
236
302
|
if (result === "true")
|
|
237
|
-
return
|
|
303
|
+
return 1;
|
|
238
304
|
if (result === "false")
|
|
239
|
-
return
|
|
240
|
-
return
|
|
305
|
+
return 0;
|
|
306
|
+
return null;
|
|
241
307
|
}
|
|
242
308
|
async setValue(value) {
|
|
243
309
|
const inputEl = await this.getElement();
|
|
244
310
|
const currentValue = await this.getValue();
|
|
245
311
|
if (currentValue !== value) {
|
|
246
|
-
await inputEl.
|
|
312
|
+
await click(inputEl, this.driver);
|
|
247
313
|
}
|
|
248
314
|
}
|
|
249
315
|
};
|
|
250
316
|
|
|
251
317
|
// src/pageObjects/elements/Editors/SelectBoxEditor.ts
|
|
252
|
-
import { By as
|
|
318
|
+
import { By as By7, Key as Key2 } from "selenium-webdriver";
|
|
253
319
|
|
|
254
320
|
// src/utils/xpathHelper.ts
|
|
255
321
|
var XPathHelper = class {
|
|
@@ -261,19 +327,53 @@ var XPathHelper = class {
|
|
|
261
327
|
}
|
|
262
328
|
};
|
|
263
329
|
|
|
330
|
+
// src/pageObjects/elements/Editors/ClearStrategy/ClearButtonStrategy.ts
|
|
331
|
+
import { By as By6 } from "selenium-webdriver";
|
|
332
|
+
var DX_TEXTEDITOR_EMPTY = "dx-texteditor-empty";
|
|
333
|
+
var DX_CLEAR_BUTTON_AREA = "dx-clear-button-area";
|
|
334
|
+
var ClearButtonStrategy = class {
|
|
335
|
+
editorContainerClass;
|
|
336
|
+
constructor(editorContainerClass) {
|
|
337
|
+
this.editorContainerClass = editorContainerClass;
|
|
338
|
+
}
|
|
339
|
+
async isEmptyEditorField(editor) {
|
|
340
|
+
const parentEl = await editor.getParentElement();
|
|
341
|
+
const editorContainer = await parentEl.findElement(By6.className(this.editorContainerClass));
|
|
342
|
+
const classAttribute = await editorContainer.getAttribute("class");
|
|
343
|
+
return classAttribute.includes(DX_TEXTEDITOR_EMPTY);
|
|
344
|
+
}
|
|
345
|
+
async clear(editor) {
|
|
346
|
+
if (await this.isEmptyEditorField(editor)) {
|
|
347
|
+
throw new Error("This field is already empty");
|
|
348
|
+
}
|
|
349
|
+
const clearBtnSelector = `.${this.editorContainerClass} .${DX_CLEAR_BUTTON_AREA}`;
|
|
350
|
+
const parentEl = await editor.getParentElement();
|
|
351
|
+
const clearBtn = await parentEl.findElement(By6.css(clearBtnSelector));
|
|
352
|
+
await click(clearBtn, editor.driver);
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
264
356
|
// src/pageObjects/elements/Editors/SelectBoxEditor.ts
|
|
265
357
|
var SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS = "d5-multi-select-item";
|
|
266
358
|
var SELECT_BOX_ELEMENT_ROLE = "option";
|
|
359
|
+
var combinedValueXpath = (value) => `${XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE)}${XPathHelper.getClassAndValueXpath(
|
|
360
|
+
SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS,
|
|
361
|
+
value
|
|
362
|
+
)}`;
|
|
363
|
+
var DX_SELECTBOX = "dx-selectbox";
|
|
267
364
|
var SelectBoxEditor = class extends AbstractDXEditorWithInput {
|
|
365
|
+
constructor(getParentElement, elementBy, driver) {
|
|
366
|
+
super(getParentElement, elementBy, driver);
|
|
367
|
+
this.setClearStrategy(new ClearButtonStrategy(DX_SELECTBOX));
|
|
368
|
+
}
|
|
268
369
|
async setSelectInputValue(value) {
|
|
269
370
|
const inputEl = await this.getInputElement();
|
|
270
|
-
await inputEl.
|
|
371
|
+
await click(inputEl, this.driver);
|
|
271
372
|
await inputEl.sendKeys(value, Key2.ENTER);
|
|
272
|
-
const combinedValueXpath = XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE) + XPathHelper.getClassAndValueXpath(SELECT_BOX_OPTION_TEXT_CONTAINER_CLASS, value);
|
|
273
373
|
await this.driver.wait(async () => {
|
|
274
374
|
try {
|
|
275
|
-
const optElement = await inputEl.findElement(
|
|
276
|
-
await optElement.
|
|
375
|
+
const optElement = await inputEl.findElement(By7.xpath(combinedValueXpath(value)));
|
|
376
|
+
await click(optElement, this.driver);
|
|
277
377
|
return true;
|
|
278
378
|
} catch (e) {
|
|
279
379
|
return false;
|
|
@@ -298,7 +398,7 @@ var SwitchEditor = class extends AbstractFormElement {
|
|
|
298
398
|
return 1;
|
|
299
399
|
if (result === "OFF")
|
|
300
400
|
return 0;
|
|
301
|
-
return
|
|
401
|
+
return null;
|
|
302
402
|
}
|
|
303
403
|
async setValue(value) {
|
|
304
404
|
if (value !== 0 && value !== 1) {
|
|
@@ -307,7 +407,7 @@ var SwitchEditor = class extends AbstractFormElement {
|
|
|
307
407
|
const inputEl = await this.getElement();
|
|
308
408
|
const currentValue = await this.getValue();
|
|
309
409
|
if (currentValue !== value) {
|
|
310
|
-
await inputEl.
|
|
410
|
+
await click(inputEl, this.driver);
|
|
311
411
|
await this.driver.wait(async () => {
|
|
312
412
|
const updatedValue = await this.getValue();
|
|
313
413
|
return updatedValue !== currentValue;
|
|
@@ -316,21 +416,205 @@ var SwitchEditor = class extends AbstractFormElement {
|
|
|
316
416
|
}
|
|
317
417
|
};
|
|
318
418
|
|
|
419
|
+
// src/pageObjects/elements/Editors/TagBox.ts
|
|
420
|
+
import { By as By8 } from "selenium-webdriver";
|
|
421
|
+
var TAGS_SELECTOR = ".dx-tag .tag-text";
|
|
422
|
+
var DX_TAG_CONTAINER = "dx-tag-container";
|
|
423
|
+
var DX_TAGBOX = "dx-tagbox";
|
|
424
|
+
var DX_TEXTEDITOR_EMPTY2 = "dx-texteditor-empty";
|
|
425
|
+
var BTN_OK_SELECTOR = ".dx-tagbox-popup-wrapper .dx-popup-bottom .dx-button.dx-popup-done";
|
|
426
|
+
var TagBox = class extends AbstractDXEditorWithInput {
|
|
427
|
+
constructor(getParentElement, elementBy, driver) {
|
|
428
|
+
super(getParentElement, elementBy, driver);
|
|
429
|
+
this.setClearStrategy(new ClearButtonStrategy(DX_TAGBOX));
|
|
430
|
+
}
|
|
431
|
+
async setTagBoxInputValue(values) {
|
|
432
|
+
const lastElement = values[values.length - 1];
|
|
433
|
+
const inputEl = await this.getInputElement();
|
|
434
|
+
await inputEl.click();
|
|
435
|
+
for (const value of values) {
|
|
436
|
+
await this.selectOption(inputEl, value, lastElement);
|
|
437
|
+
}
|
|
438
|
+
await this.confirmSelection();
|
|
439
|
+
}
|
|
440
|
+
async selectOption(inputEl, value, lastElement) {
|
|
441
|
+
await inputEl.sendKeys(value);
|
|
442
|
+
await this.driver.wait(async () => {
|
|
443
|
+
try {
|
|
444
|
+
const optElement = await inputEl.findElement(By8.xpath(combinedValueXpath(value)));
|
|
445
|
+
await click(optElement, this.driver);
|
|
446
|
+
return true;
|
|
447
|
+
} catch (e) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
if (value !== lastElement) {
|
|
452
|
+
await inputEl.clear();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
async confirmSelection() {
|
|
456
|
+
const inputEl = await this.getInputElement();
|
|
457
|
+
const option = await inputEl.findElement(By8.xpath(XPathHelper.getRoleXpath(SELECT_BOX_ELEMENT_ROLE)));
|
|
458
|
+
const btnOk = await this.driver.findElement(By8.css(BTN_OK_SELECTOR));
|
|
459
|
+
await this.driver.wait(async () => {
|
|
460
|
+
return await option.getAttribute("aria-selected") === "true";
|
|
461
|
+
});
|
|
462
|
+
await click(btnOk, this.driver);
|
|
463
|
+
}
|
|
464
|
+
async getTagBoxInputValue() {
|
|
465
|
+
if (await this.isTagBoxEmpty()) {
|
|
466
|
+
return [];
|
|
467
|
+
}
|
|
468
|
+
const parentEl = await this.getParentElement();
|
|
469
|
+
const inputEl = await parentEl.findElement(By8.className(DX_TAG_CONTAINER));
|
|
470
|
+
const tags = await inputEl.findElements(By8.css(TAGS_SELECTOR));
|
|
471
|
+
const values = [];
|
|
472
|
+
for (const tag of tags) {
|
|
473
|
+
const text = await tag.getText();
|
|
474
|
+
values.push(text);
|
|
475
|
+
}
|
|
476
|
+
return values;
|
|
477
|
+
}
|
|
478
|
+
async isTagBoxEmpty() {
|
|
479
|
+
const parentEl = await this.getParentElement();
|
|
480
|
+
const tagboxContainer = await parentEl.findElement(By8.className(DX_TAGBOX));
|
|
481
|
+
const classAttribute = await tagboxContainer.getAttribute("class");
|
|
482
|
+
return classAttribute.includes(DX_TEXTEDITOR_EMPTY2);
|
|
483
|
+
}
|
|
484
|
+
async getValue() {
|
|
485
|
+
const value = await this.getTagBoxInputValue();
|
|
486
|
+
return value.length ? value : null;
|
|
487
|
+
}
|
|
488
|
+
async setValue(values) {
|
|
489
|
+
if (!Array.isArray(values)) {
|
|
490
|
+
throw new Error("The provided value is not an array");
|
|
491
|
+
}
|
|
492
|
+
await this.setTagBoxInputValue(values);
|
|
493
|
+
}
|
|
494
|
+
async remove(itemText) {
|
|
495
|
+
const tagValues = await this.getValue();
|
|
496
|
+
const tagExists = tagValues.includes(itemText);
|
|
497
|
+
if (!tagExists) {
|
|
498
|
+
throw new Error(`The tag with the text: ${itemText} was not found`);
|
|
499
|
+
}
|
|
500
|
+
const parentEl = await this.getParentElement();
|
|
501
|
+
const inputEl = await parentEl.findElement(By8.className(DX_TAG_CONTAINER));
|
|
502
|
+
const clearBtnTestId = byTestId(`clear-button-${itemText}`);
|
|
503
|
+
const clearBtn = await inputEl.findElement(clearBtnTestId);
|
|
504
|
+
await click(clearBtn, this.driver);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
// src/pageObjects/elements/Editors/ButtonGroup.ts
|
|
509
|
+
import { By as By9 } from "selenium-webdriver";
|
|
510
|
+
var ITEM_CLASS = "dx-buttongroup-item";
|
|
511
|
+
var SELECTED_CLASS = "dx-state-selected";
|
|
512
|
+
var ButtonGroup = class extends AbstractFormElement {
|
|
513
|
+
async getItems() {
|
|
514
|
+
return (await this.getElement()).findElements(By9.className(ITEM_CLASS));
|
|
515
|
+
}
|
|
516
|
+
getDataValue(el) {
|
|
517
|
+
return el.getAttribute("data-value");
|
|
518
|
+
}
|
|
519
|
+
async getValue() {
|
|
520
|
+
const inputEl = await this.getElement();
|
|
521
|
+
const selectedEl = await inputEl.findElement(By9.className(`${ITEM_CLASS} ${SELECTED_CLASS}`));
|
|
522
|
+
return this.getDataValue(selectedEl);
|
|
523
|
+
}
|
|
524
|
+
async setValue(value) {
|
|
525
|
+
const items = await this.getItems();
|
|
526
|
+
let buttonEl = void 0;
|
|
527
|
+
for (const item of items) {
|
|
528
|
+
const text = await this.getDataValue(item);
|
|
529
|
+
if (text == value) {
|
|
530
|
+
buttonEl = item;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (!buttonEl)
|
|
535
|
+
throw new Error(`Cannot find item in button group with text: ${value}`);
|
|
536
|
+
await click(buttonEl, this.driver);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// src/pageObjects/elements/Editors/BooleanSelector.ts
|
|
541
|
+
var BooleanSelector = class extends ButtonGroup {
|
|
542
|
+
// @ts-ignore
|
|
543
|
+
async getValue() {
|
|
544
|
+
const value = await super.getValue();
|
|
545
|
+
return value === "null" ? null : value === "1" ? 1 : 0;
|
|
546
|
+
}
|
|
547
|
+
// @ts-ignore
|
|
548
|
+
async setValue(value) {
|
|
549
|
+
const val = value == null ? "null" : value ? "1" : "0";
|
|
550
|
+
await super.setValue(val);
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
// src/pageObjects/elements/Editors/DateEditor.ts
|
|
555
|
+
import { By as By10, Key as Key3 } from "selenium-webdriver";
|
|
556
|
+
var DateEditor = class extends AbstractDXEditorWithInput {
|
|
557
|
+
constructor(getParentElement, elementBy, driver) {
|
|
558
|
+
super(getParentElement, elementBy, driver);
|
|
559
|
+
this.setClearStrategy(new InputClearStrategy());
|
|
560
|
+
}
|
|
561
|
+
async getControlElement() {
|
|
562
|
+
const controlEl = await this.getElement();
|
|
563
|
+
return controlEl.findElement(By10.className("dx-dropdowneditor-input-wrapper"));
|
|
564
|
+
}
|
|
565
|
+
async getDateElement() {
|
|
566
|
+
const controlEl = await this.getControlElement();
|
|
567
|
+
return controlEl.findElement(By10.css("input[type=hidden]"));
|
|
568
|
+
}
|
|
569
|
+
async setDateValue(value) {
|
|
570
|
+
const dateEl = await this.getInputElement();
|
|
571
|
+
const stringDate = value.toJSON().split("T")[0];
|
|
572
|
+
const dateArr = stringDate.split("-");
|
|
573
|
+
const [year, month, day] = dateArr;
|
|
574
|
+
const keys = day + month + year;
|
|
575
|
+
await click(dateEl, this.driver);
|
|
576
|
+
const actions = this.driver.actions({ async: true });
|
|
577
|
+
await actions.move({ origin: dateEl }).sendKeys(Key3.HOME).perform();
|
|
578
|
+
await actions.move({ origin: dateEl }).sendKeys(keys, Key3.ENTER).perform();
|
|
579
|
+
}
|
|
580
|
+
async getDateValue() {
|
|
581
|
+
const inputEl = await this.getDateElement();
|
|
582
|
+
return inputEl.getAttribute("value");
|
|
583
|
+
}
|
|
584
|
+
async getValue() {
|
|
585
|
+
const value = await this.getDateValue();
|
|
586
|
+
return value == "" ? null : new Date(value);
|
|
587
|
+
}
|
|
588
|
+
setValue(value) {
|
|
589
|
+
if (typeof value === "object") {
|
|
590
|
+
return this.setDateValue(value);
|
|
591
|
+
}
|
|
592
|
+
throw new Error(`Value is incorrect. It should be Object`);
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
319
596
|
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
320
597
|
var editorFactory = async (getParentElement, elementBy, driver) => {
|
|
321
598
|
const elementInstance = new AbstractFormElement(getParentElement, elementBy, driver);
|
|
322
|
-
const
|
|
323
|
-
const classSting = await element.getAttribute("class");
|
|
599
|
+
const classSting = await elementInstance.getClasses();
|
|
324
600
|
if (classSting.includes("text-control"))
|
|
325
601
|
return new TextEditor(getParentElement, elementBy, driver);
|
|
326
602
|
if (classSting.includes("number-control"))
|
|
327
603
|
return new NumberEditor(getParentElement, elementBy, driver);
|
|
328
604
|
if (classSting.includes("check-box"))
|
|
329
605
|
return new CheckBox(getParentElement, elementBy, driver);
|
|
606
|
+
if (classSting.includes("multi-select-control"))
|
|
607
|
+
return new TagBox(getParentElement, elementBy, driver);
|
|
330
608
|
if (classSting.includes("select-control"))
|
|
331
609
|
return new SelectBoxEditor(getParentElement, elementBy, driver);
|
|
332
610
|
if (classSting.includes("switch-control"))
|
|
333
611
|
return new SwitchEditor(getParentElement, elementBy, driver);
|
|
612
|
+
if (classSting.includes("date-control"))
|
|
613
|
+
return new DateEditor(getParentElement, elementBy, driver);
|
|
614
|
+
if (classSting.includes("buttons-group"))
|
|
615
|
+
return new BooleanSelector(getParentElement, elementBy, driver);
|
|
616
|
+
if (classSting.includes("button-group-field"))
|
|
617
|
+
return new ButtonGroup(getParentElement, elementBy, driver);
|
|
334
618
|
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
335
619
|
};
|
|
336
620
|
|
|
@@ -341,6 +625,9 @@ function createDataTestId(formName, itemType, itemName) {
|
|
|
341
625
|
function createFieldTestId(formName, itemName) {
|
|
342
626
|
return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
|
|
343
627
|
}
|
|
628
|
+
function createGroupTestId(formName, itemName) {
|
|
629
|
+
return createDataTestId(formName, "group" /* GROUP */, itemName);
|
|
630
|
+
}
|
|
344
631
|
function createTableId(formName) {
|
|
345
632
|
return `${"table" /* TABLE */}-${formName}`;
|
|
346
633
|
}
|
|
@@ -377,14 +664,82 @@ var FormField = class extends AbstractElementWithParent {
|
|
|
377
664
|
await this.initEditor();
|
|
378
665
|
return this.editor.setValue(value);
|
|
379
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
* Очищает значение в поле
|
|
669
|
+
* @example
|
|
670
|
+
* await formEdit.field('NumberFld').clear();
|
|
671
|
+
*/
|
|
672
|
+
async clear() {
|
|
673
|
+
await this.initEditor();
|
|
674
|
+
if (!this.editor.clear) {
|
|
675
|
+
throw new Error("The clear method is not available for this field type.");
|
|
676
|
+
}
|
|
677
|
+
return this.editor.clear();
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Удаляет тег по переданному тексту
|
|
681
|
+
* @example
|
|
682
|
+
* await formEdit.field('TagBox').remove('test');
|
|
683
|
+
*/
|
|
684
|
+
async remove(itemText) {
|
|
685
|
+
await this.initEditor();
|
|
686
|
+
if (!this.editor.remove) {
|
|
687
|
+
throw new Error("This method is only available for the TagBox field.");
|
|
688
|
+
}
|
|
689
|
+
return this.editor.remove(itemText);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// src/pageObjects/elements/Groups/AbstractGroup.ts
|
|
694
|
+
var AbstractDXGroup = class extends AbstractFormElement {
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
// src/pageObjects/elements/Groups/Panel.ts
|
|
698
|
+
var Panel = class extends AbstractDXGroup {
|
|
699
|
+
async isDisplayed() {
|
|
700
|
+
const groupElement = await this.getElement();
|
|
701
|
+
return await groupElement.isDisplayed();
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
// src/pageObjects/elements/Groups/groupFactory.ts
|
|
706
|
+
var groupFactory = async (getParentElement, elementBy, driver) => {
|
|
707
|
+
const elementInstance = new AbstractFormElement(getParentElement, elementBy, driver);
|
|
708
|
+
const classSting = await elementInstance.getClasses();
|
|
709
|
+
if (classSting.includes("panel-group"))
|
|
710
|
+
return new Panel(getParentElement, elementBy, driver);
|
|
711
|
+
throw new Error("Unknown type of group. Please write ticket to the support");
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
// src/pageObjects/elements/FormGroup.ts
|
|
715
|
+
var FormGroup = class extends AbstractElementWithParent {
|
|
716
|
+
editor;
|
|
717
|
+
constructor(getParentElement, formName, name, driver) {
|
|
718
|
+
super(getParentElement, driver);
|
|
719
|
+
this.elementBy = byTestId(createGroupTestId(formName, name));
|
|
720
|
+
}
|
|
721
|
+
async initEditor() {
|
|
722
|
+
if (!this.editor) {
|
|
723
|
+
this.editor = await groupFactory(this.getParentElement, this.elementBy, this.driver);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Возвращает булевое значение доступна ли группа
|
|
728
|
+
* @example
|
|
729
|
+
* expect(await tableList.group('MainSuperPanel').isDisplayed();
|
|
730
|
+
*/
|
|
731
|
+
async isDisplayed() {
|
|
732
|
+
await this.initEditor();
|
|
733
|
+
return this.editor.isDisplayed();
|
|
734
|
+
}
|
|
380
735
|
};
|
|
381
736
|
|
|
382
737
|
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
383
738
|
var FormEdit = class extends AbstractForm {
|
|
384
|
-
saveButtonBy =
|
|
739
|
+
saveButtonBy = By11.id("button-save");
|
|
385
740
|
constructor(driver) {
|
|
386
741
|
super(driver);
|
|
387
|
-
this.popupContainerBy =
|
|
742
|
+
this.popupContainerBy = By11.className(`popup form-edit-${this.formName}`);
|
|
388
743
|
}
|
|
389
744
|
/**
|
|
390
745
|
* Находит поле формы редактирования по имени
|
|
@@ -396,6 +751,28 @@ var FormEdit = class extends AbstractForm {
|
|
|
396
751
|
field(name) {
|
|
397
752
|
return new FormField(this.getContainerElement, this.formName, name, this.driver);
|
|
398
753
|
}
|
|
754
|
+
/**
|
|
755
|
+
* Проверяет не отключена ли кнопка Сохранить
|
|
756
|
+
* @example
|
|
757
|
+
* const formEdit = new MyForm();
|
|
758
|
+
* //...
|
|
759
|
+
* await formEdit.isSaveButtonDisabled();
|
|
760
|
+
*/
|
|
761
|
+
async isSaveButtonDisabled() {
|
|
762
|
+
const saveButton = await this.driver.findElement(this.saveButtonBy);
|
|
763
|
+
const result = await saveButton.getAttribute("aria-disabled");
|
|
764
|
+
return result === "true";
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Находит группу формы редактирования по имени
|
|
768
|
+
* @example
|
|
769
|
+
* const formEdit = new MyForm();
|
|
770
|
+
* //...
|
|
771
|
+
* expect(await formEdit.group('Name');
|
|
772
|
+
*/
|
|
773
|
+
group(name) {
|
|
774
|
+
return new FormGroup(this.getContainerElement, this.formName, name, this.driver);
|
|
775
|
+
}
|
|
399
776
|
/**
|
|
400
777
|
* Нажатие на кнопку Сохранить
|
|
401
778
|
* @example
|
|
@@ -404,41 +781,42 @@ var FormEdit = class extends AbstractForm {
|
|
|
404
781
|
* await formEdit.saveButtonClick();
|
|
405
782
|
*/
|
|
406
783
|
async saveButtonClick() {
|
|
407
|
-
await this.driver.findElement(this.saveButtonBy)
|
|
784
|
+
const saveButton = await this.driver.findElement(this.saveButtonBy);
|
|
785
|
+
await this.driver.wait(async () => !await this.isSaveButtonDisabled(), void 0, "Button is disabled");
|
|
786
|
+
await click(saveButton, this.driver);
|
|
408
787
|
}
|
|
409
788
|
};
|
|
410
789
|
|
|
411
790
|
// src/pageObjects/elements/Forms/ListForm.ts
|
|
412
|
-
import { By as
|
|
791
|
+
import { By as By17 } from "selenium-webdriver";
|
|
413
792
|
|
|
414
793
|
// src/pageObjects/elements/Table/Table.ts
|
|
415
|
-
import { By as
|
|
794
|
+
import { By as By14 } from "selenium-webdriver";
|
|
416
795
|
|
|
417
796
|
// src/pageObjects/elements/Table/utils.ts
|
|
418
|
-
import { By as
|
|
797
|
+
import { By as By12 } from "selenium-webdriver";
|
|
419
798
|
var getRowPathByIndex = (index) => {
|
|
420
|
-
return
|
|
799
|
+
return By12.css(`tr[aria-rowindex="${transformInputIndex(index)}"]`);
|
|
421
800
|
};
|
|
801
|
+
var getColumnByIndexCssSelector = (columnIndex) => `td[aria-colindex="${transformInputIndex(columnIndex)}"]`;
|
|
422
802
|
var getColumnPathByIndex = (index) => {
|
|
423
|
-
return
|
|
424
|
-
};
|
|
425
|
-
var getColumnPathByCaption = (caption) => {
|
|
426
|
-
return By8.xpath(`//td[@role="columnheader"][@aria-label="Column ${caption}"]`);
|
|
803
|
+
return By12.css(getColumnByIndexCssSelector(index));
|
|
427
804
|
};
|
|
805
|
+
var getColumnByCaptionCssSelector = (caption) => `td[role="columnheader"][aria-label="Column ${caption}"]`;
|
|
428
806
|
var getCellPathByIndex = (index) => {
|
|
429
|
-
return
|
|
807
|
+
return By12.css(`td[role="gridcell"][aria-colindex="${transformInputIndex(index)}"]`);
|
|
430
808
|
};
|
|
431
809
|
var transformInputIndex = (index) => index + 1;
|
|
432
810
|
var transformOutputIndex = (index) => +index - 1;
|
|
433
811
|
|
|
434
812
|
// src/pageObjects/elements/Table/elements/Row.ts
|
|
435
|
-
import { By as
|
|
813
|
+
import { By as By13 } from "selenium-webdriver";
|
|
436
814
|
|
|
437
815
|
// src/pageObjects/elements/Table/elements/Cell.ts
|
|
438
816
|
var Cell = class extends AbstractElementWithParent {
|
|
439
817
|
index;
|
|
440
|
-
constructor(
|
|
441
|
-
super(
|
|
818
|
+
constructor(rowEl, index, driver) {
|
|
819
|
+
super(() => Promise.resolve(rowEl), driver);
|
|
442
820
|
this.index = index;
|
|
443
821
|
this.elementBy = getCellPathByIndex(index);
|
|
444
822
|
}
|
|
@@ -452,6 +830,9 @@ var Cell = class extends AbstractElementWithParent {
|
|
|
452
830
|
};
|
|
453
831
|
|
|
454
832
|
// src/pageObjects/elements/Table/elements/Row.ts
|
|
833
|
+
var DX_SELECTION_CLASS = "dx-selection";
|
|
834
|
+
var DX_ROW_EDIT_CLASS = "dx-edit-row";
|
|
835
|
+
var DX_DATA_ROW_CLASS = "dx-data-row";
|
|
455
836
|
var Row = class extends AbstractElementWithParent {
|
|
456
837
|
index;
|
|
457
838
|
getColumnByCaption;
|
|
@@ -461,14 +842,11 @@ var Row = class extends AbstractElementWithParent {
|
|
|
461
842
|
this.elementBy = getRowPathByIndex(index);
|
|
462
843
|
this.getColumnByCaption = getColumnByCaption;
|
|
463
844
|
}
|
|
464
|
-
getRowElement = () => {
|
|
465
|
-
return this.driver.findElement(this.elementBy);
|
|
466
|
-
};
|
|
467
845
|
async getCellByIndex(index) {
|
|
468
846
|
const rowEl = await this.getElement();
|
|
469
847
|
const cell = rowEl.findElement(getCellPathByIndex(index));
|
|
470
848
|
if (cell) {
|
|
471
|
-
return new Cell(
|
|
849
|
+
return new Cell(rowEl, index, this.driver);
|
|
472
850
|
}
|
|
473
851
|
throw new Error(`Cannot find cell by index: ${index}`);
|
|
474
852
|
}
|
|
@@ -482,7 +860,11 @@ var Row = class extends AbstractElementWithParent {
|
|
|
482
860
|
}
|
|
483
861
|
async select() {
|
|
484
862
|
const rowEl = await this.getElement();
|
|
485
|
-
await rowEl.
|
|
863
|
+
await click(rowEl, this.driver);
|
|
864
|
+
await this.driver.wait(async () => {
|
|
865
|
+
const classes = await rowEl.getAttribute("class");
|
|
866
|
+
return classes.includes(DX_SELECTION_CLASS);
|
|
867
|
+
}, 500, "Cannot select row");
|
|
486
868
|
}
|
|
487
869
|
async isSelected() {
|
|
488
870
|
const rowEl = await this.getElement();
|
|
@@ -494,34 +876,38 @@ var Row = class extends AbstractElementWithParent {
|
|
|
494
876
|
}
|
|
495
877
|
async getCells() {
|
|
496
878
|
const rowEl = await this.getElement();
|
|
497
|
-
const cells = await rowEl.findElements(
|
|
879
|
+
const cells = await rowEl.findElements(By13.css(`td[role="gridcell"]`));
|
|
498
880
|
const result = [];
|
|
499
881
|
cells.forEach((_, index) => {
|
|
500
|
-
const newCell = new Cell(
|
|
882
|
+
const newCell = new Cell(rowEl, index, this.driver);
|
|
501
883
|
result.push(newCell);
|
|
502
884
|
});
|
|
503
885
|
return result;
|
|
504
886
|
}
|
|
505
|
-
async clickInlineButton(
|
|
506
|
-
const
|
|
507
|
-
|
|
887
|
+
async clickInlineButton(buttonClass) {
|
|
888
|
+
const FIXED_TABLE_CSS_SELECTOR = ".dx-fixed-columns .dx-datagrid-content.dx-datagrid-content-fixed";
|
|
889
|
+
const buttonCssSelector = `.${DX_DATA_ROW_CLASS}[aria-rowindex="${transformInputIndex(this.index)}"] .${buttonClass}`;
|
|
890
|
+
const button = (await this.getParentElement()).findElement(
|
|
891
|
+
By13.css(`${FIXED_TABLE_CSS_SELECTOR} ${buttonCssSelector}`)
|
|
508
892
|
);
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
893
|
+
return click(button, this.driver);
|
|
894
|
+
}
|
|
895
|
+
async checkEditingMode(isEditing, msg) {
|
|
896
|
+
await this.driver.wait(async () => {
|
|
897
|
+
return (await this.getClasses()).includes(DX_ROW_EDIT_CLASS) === isEditing;
|
|
898
|
+
}, 2e3, msg);
|
|
515
899
|
}
|
|
516
900
|
async edit() {
|
|
517
|
-
await this.
|
|
518
|
-
|
|
901
|
+
await this.clickInlineButton("edit");
|
|
902
|
+
await this.checkEditingMode(true, "Row did not switch to edit mode");
|
|
519
903
|
}
|
|
520
904
|
async save() {
|
|
521
|
-
|
|
905
|
+
await this.clickInlineButton("save");
|
|
906
|
+
await this.checkEditingMode(false, "Row did not saved");
|
|
522
907
|
}
|
|
523
908
|
async cancel() {
|
|
524
|
-
|
|
909
|
+
await this.clickInlineButton("cancel");
|
|
910
|
+
await this.checkEditingMode(false, "Row did not switch to normal mode");
|
|
525
911
|
}
|
|
526
912
|
};
|
|
527
913
|
|
|
@@ -544,20 +930,21 @@ var Column = class extends AbstractElementWithParent {
|
|
|
544
930
|
|
|
545
931
|
// src/pageObjects/elements/Table/Table.ts
|
|
546
932
|
var Table = class extends AbstractElementWithParent {
|
|
933
|
+
formName;
|
|
547
934
|
constructor(getParentElement, formName, driver) {
|
|
548
935
|
super(getParentElement, driver);
|
|
549
|
-
this.elementBy =
|
|
936
|
+
this.elementBy = By14.id(createTableId(formName));
|
|
937
|
+
this.formName = formName;
|
|
550
938
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
return parentEl.findElement(By10.className("dx-header-row"));
|
|
939
|
+
getHeaderCssSelector() {
|
|
940
|
+
return ".dx-datagrid-headers .dx-datagrid-content:not(.dx-datagrid-content-fixed)";
|
|
554
941
|
}
|
|
555
942
|
async getDataGrid() {
|
|
556
943
|
const parentEl = await this.getElement();
|
|
557
|
-
return parentEl.findElement(
|
|
944
|
+
return parentEl.findElement(By14.css(`div[role="grid"]`));
|
|
558
945
|
}
|
|
559
946
|
getTableElement = () => {
|
|
560
|
-
return this.
|
|
947
|
+
return this.getElement();
|
|
561
948
|
};
|
|
562
949
|
async getRowByIndex(index) {
|
|
563
950
|
const gridContainer = await this.getDataGrid();
|
|
@@ -568,16 +955,14 @@ var Table = class extends AbstractElementWithParent {
|
|
|
568
955
|
throw new Error(`Cannot find row by index: ${index}`);
|
|
569
956
|
}
|
|
570
957
|
async getColumnByIndex(index) {
|
|
571
|
-
const
|
|
572
|
-
const column = await headerContainer.findElement(getColumnPathByIndex(index));
|
|
958
|
+
const column = await (await this.getElement()).findElement(By14.css(`${this.getHeaderCssSelector()} ${getColumnByIndexCssSelector(index)}`));
|
|
573
959
|
if (column) {
|
|
574
960
|
return new Column(this.getTableElement, index, this.driver);
|
|
575
961
|
}
|
|
576
962
|
throw new Error(`Cannot find column by index: ${index}`);
|
|
577
963
|
}
|
|
578
964
|
async getColumnByCaption(caption) {
|
|
579
|
-
const
|
|
580
|
-
const column = await headerContainer.findElement(getColumnPathByCaption(caption));
|
|
965
|
+
const column = await (await this.getElement()).findElement(By14.css(`${this.getHeaderCssSelector()} ${getColumnByCaptionCssSelector(caption)}`));
|
|
581
966
|
if (column) {
|
|
582
967
|
const index = await column.getAttribute("aria-colindex");
|
|
583
968
|
return new Column(this.getTableElement, transformOutputIndex(index), this.driver);
|
|
@@ -594,7 +979,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
594
979
|
}
|
|
595
980
|
async getRows() {
|
|
596
981
|
const gridContainer = await this.getDataGrid();
|
|
597
|
-
const rows = await gridContainer.findElements(
|
|
982
|
+
const rows = await gridContainer.findElements(By14.className("dx-row dx-data-row"));
|
|
598
983
|
const result = [];
|
|
599
984
|
rows.forEach((_, index) => {
|
|
600
985
|
const newRow = new Row(this.getTableElement, index, this.driver, this.getColumnByCaption.bind(this));
|
|
@@ -603,8 +988,7 @@ var Table = class extends AbstractElementWithParent {
|
|
|
603
988
|
return result;
|
|
604
989
|
}
|
|
605
990
|
async getColumns() {
|
|
606
|
-
const
|
|
607
|
-
const columns = await headerContainer.findElements(By10.css(`td[role="columnheader"]`));
|
|
991
|
+
const columns = await (await this.getElement()).findElements(By14.css(`${this.getHeaderCssSelector()} td[role="columnheader"]`));
|
|
608
992
|
const result = [];
|
|
609
993
|
columns.forEach((_, index) => {
|
|
610
994
|
const newCol = new Column(this.getTableElement, index, this.driver);
|
|
@@ -612,25 +996,40 @@ var Table = class extends AbstractElementWithParent {
|
|
|
612
996
|
});
|
|
613
997
|
return result;
|
|
614
998
|
}
|
|
615
|
-
|
|
999
|
+
element() {
|
|
616
1000
|
return this.getElement();
|
|
617
1001
|
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Находит поле когда форма находится в состоянии редактирования
|
|
1004
|
+
* @example
|
|
1005
|
+
* const form = new MyForm();
|
|
1006
|
+
* //...
|
|
1007
|
+
* expect(await form.field('Name').getValue()).toBe('test value');
|
|
1008
|
+
*/
|
|
1009
|
+
field(name) {
|
|
1010
|
+
return new FormField(this.getTableElement, this.formName, name, this.driver);
|
|
1011
|
+
}
|
|
618
1012
|
};
|
|
619
1013
|
|
|
620
1014
|
// src/pageObjects/elements/TableToolbar/TableToolbar.ts
|
|
621
|
-
import { By as
|
|
1015
|
+
import { By as By16 } from "selenium-webdriver";
|
|
622
1016
|
|
|
623
1017
|
// src/pageObjects/elements/TableToolbar/TableToolbarButton.ts
|
|
624
|
-
import { By as
|
|
1018
|
+
import { By as By15 } from "selenium-webdriver";
|
|
625
1019
|
var TOOLBAR_BUTTON_CLASS = "toolbar-button";
|
|
626
1020
|
var TableToolbarButton = class extends AbstractElementWithParent {
|
|
1021
|
+
name;
|
|
627
1022
|
constructor(getParentElement, name, driver) {
|
|
628
1023
|
super(getParentElement, driver);
|
|
629
|
-
this.
|
|
1024
|
+
this.name = name;
|
|
1025
|
+
this.elementBy = By15.id(`${TOOLBAR_BUTTON_CLASS}-${name}`);
|
|
630
1026
|
}
|
|
631
1027
|
async click() {
|
|
632
1028
|
const button = await this.getElement();
|
|
633
|
-
|
|
1029
|
+
await this.driver.wait(async () => {
|
|
1030
|
+
return await button.isDisplayed() && !await this.isDisabled();
|
|
1031
|
+
}, 1e3, `Button ${this.name} cannot be clicked. It is not displayed or it is disabled`);
|
|
1032
|
+
return click(button, this.driver);
|
|
634
1033
|
}
|
|
635
1034
|
async isDisabled() {
|
|
636
1035
|
const button = await this.getElement();
|
|
@@ -644,14 +1043,14 @@ var TABLE_TOOLBAR_CLASS = "d5-table-toolbar";
|
|
|
644
1043
|
var TableToolbar = class extends AbstractElementWithParent {
|
|
645
1044
|
constructor(getParentElement, formName, driver) {
|
|
646
1045
|
super(getParentElement, driver);
|
|
647
|
-
this.elementBy =
|
|
1046
|
+
this.elementBy = By16.id(`${TABLE_TOOLBAR_CLASS}-${formName}`);
|
|
648
1047
|
}
|
|
649
1048
|
getTableToolbarElement = () => {
|
|
650
1049
|
return this.driver.findElement(this.elementBy);
|
|
651
1050
|
};
|
|
652
1051
|
async button(name) {
|
|
653
1052
|
const toolbar = await this.getTableToolbarElement();
|
|
654
|
-
const button = await toolbar.findElement(
|
|
1053
|
+
const button = await toolbar.findElement(By16.id(`${TOOLBAR_BUTTON_CLASS}-${name}`));
|
|
655
1054
|
if (button) {
|
|
656
1055
|
return new TableToolbarButton(this.getTableToolbarElement, name, this.driver);
|
|
657
1056
|
}
|
|
@@ -663,7 +1062,7 @@ var TableToolbar = class extends AbstractElementWithParent {
|
|
|
663
1062
|
var ListForm = class extends AbstractForm {
|
|
664
1063
|
constructor(driver) {
|
|
665
1064
|
super(driver);
|
|
666
|
-
this.popupContainerBy =
|
|
1065
|
+
this.popupContainerBy = By17.className(`popup form-inline-${this.formName}`);
|
|
667
1066
|
}
|
|
668
1067
|
/**
|
|
669
1068
|
* Находит таблицу
|
|
@@ -675,6 +1074,16 @@ var ListForm = class extends AbstractForm {
|
|
|
675
1074
|
table() {
|
|
676
1075
|
return new Table(this.getContainerElement, this.formName, this.driver);
|
|
677
1076
|
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Находит группу на лист форме по имени
|
|
1079
|
+
* @example
|
|
1080
|
+
* const formEdit = new MyForm();
|
|
1081
|
+
* //...
|
|
1082
|
+
* expect(await formEdit.group('Name');
|
|
1083
|
+
*/
|
|
1084
|
+
group(name) {
|
|
1085
|
+
return new FormGroup(this.getContainerElement, this.formName, name, this.driver);
|
|
1086
|
+
}
|
|
678
1087
|
/**
|
|
679
1088
|
* Находит таблицу
|
|
680
1089
|
* @example
|
|
@@ -698,12 +1107,27 @@ async function signIn(driver) {
|
|
|
698
1107
|
return webDriver;
|
|
699
1108
|
}
|
|
700
1109
|
|
|
1110
|
+
// src/utils/actions.ts
|
|
1111
|
+
var click = async (webElement, driver) => {
|
|
1112
|
+
driver = driver ?? config().driver;
|
|
1113
|
+
const actions = driver.actions({ async: true });
|
|
1114
|
+
await actions.move({ origin: webElement }).click().perform();
|
|
1115
|
+
};
|
|
1116
|
+
|
|
701
1117
|
// src/pageObjects/pages/LoginPage.ts
|
|
702
1118
|
var LOGIN_PATH = "/login";
|
|
703
1119
|
var LoginPage = class extends AbstractPage {
|
|
704
1120
|
usernameField = byTestId("loginField", "input");
|
|
705
1121
|
passwordField = byTestId("passwordField", "input");
|
|
706
1122
|
loginButton = byTestId("loginButton");
|
|
1123
|
+
async locate() {
|
|
1124
|
+
await super.locate();
|
|
1125
|
+
const login = await this.driver.findElement(this.usernameField);
|
|
1126
|
+
await waitElementIsVisible({
|
|
1127
|
+
element: login,
|
|
1128
|
+
driver: this.driver
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
707
1131
|
get path() {
|
|
708
1132
|
return LOGIN_PATH;
|
|
709
1133
|
}
|
|
@@ -714,7 +1138,7 @@ var LoginPage = class extends AbstractPage {
|
|
|
714
1138
|
await this.driver.findElement(this.passwordField).sendKeys(password);
|
|
715
1139
|
}
|
|
716
1140
|
async clickLoginButton() {
|
|
717
|
-
await this.driver.findElement(this.loginButton).
|
|
1141
|
+
await click(await this.driver.findElement(this.loginButton), this.driver);
|
|
718
1142
|
}
|
|
719
1143
|
async loginWith(username, password) {
|
|
720
1144
|
await this.enterUsername(username);
|
|
@@ -735,9 +1159,11 @@ export {
|
|
|
735
1159
|
SubsystemsPanel,
|
|
736
1160
|
TextEditor,
|
|
737
1161
|
byTestId,
|
|
1162
|
+
click,
|
|
738
1163
|
config,
|
|
739
1164
|
createDriver,
|
|
740
1165
|
editorFactory,
|
|
741
1166
|
elementIsNotPresent,
|
|
742
|
-
signIn
|
|
1167
|
+
signIn,
|
|
1168
|
+
waitElementIsVisible
|
|
743
1169
|
};
|