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