d5-testing-library 1.0.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/README.md +0 -0
- package/dist/cjs/d5-testing-library.cjs +354 -0
- package/dist/d5-testing-library.d.ts +140 -0
- package/dist/d5-testing-library.legacy-esm.js +314 -0
- package/dist/d5-testing-library.mjs +314 -0
- package/package.json +48 -0
package/README.md
ADDED
|
File without changes
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
AbstractPage: () => AbstractPage,
|
|
24
|
+
FormEdit: () => FormEdit,
|
|
25
|
+
FormField: () => FormField,
|
|
26
|
+
ListForm: () => ListForm,
|
|
27
|
+
LoginPage: () => LoginPage,
|
|
28
|
+
NumberEditor: () => NumberEditor,
|
|
29
|
+
SubsystemsPanel: () => SubsystemsPanel,
|
|
30
|
+
TextEditor: () => TextEditor,
|
|
31
|
+
byTestId: () => byTestId,
|
|
32
|
+
config: () => config,
|
|
33
|
+
createDriver: () => createDriver,
|
|
34
|
+
editorFactory: () => editorFactory,
|
|
35
|
+
elementIsNotPresent: () => elementIsNotPresent,
|
|
36
|
+
signIn: () => signIn
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(src_exports);
|
|
39
|
+
|
|
40
|
+
// src/config.ts
|
|
41
|
+
var Config = class _Config {
|
|
42
|
+
static instance;
|
|
43
|
+
appConfig;
|
|
44
|
+
static getInstance() {
|
|
45
|
+
if (!_Config.instance) {
|
|
46
|
+
_Config.instance = new _Config();
|
|
47
|
+
}
|
|
48
|
+
return _Config.instance;
|
|
49
|
+
}
|
|
50
|
+
config = (cfg) => {
|
|
51
|
+
if (!cfg)
|
|
52
|
+
return this.appConfig;
|
|
53
|
+
this.appConfig = cfg;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
var configInstance = Config.getInstance();
|
|
57
|
+
function config(cfg) {
|
|
58
|
+
return configInstance.config(cfg);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/pageObjects/AbstractElement.ts
|
|
62
|
+
var AbstractElement = class {
|
|
63
|
+
driver;
|
|
64
|
+
constructor(driver) {
|
|
65
|
+
this.driver = driver || config().driver;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/pageObjects/pages/AbstractPage.ts
|
|
70
|
+
var AbstractPage = class extends AbstractElement {
|
|
71
|
+
url;
|
|
72
|
+
host;
|
|
73
|
+
constructor(driver) {
|
|
74
|
+
super(driver);
|
|
75
|
+
this.host = config().auth.host;
|
|
76
|
+
this.url = this.host + this.prependHash(this.path);
|
|
77
|
+
}
|
|
78
|
+
prependHash(urlPath) {
|
|
79
|
+
if (!urlPath.startsWith("/#")) {
|
|
80
|
+
return `/#${urlPath}`;
|
|
81
|
+
}
|
|
82
|
+
return urlPath;
|
|
83
|
+
}
|
|
84
|
+
async goToUrl(url) {
|
|
85
|
+
await this.driver.get(url);
|
|
86
|
+
}
|
|
87
|
+
get path() {
|
|
88
|
+
return "/#";
|
|
89
|
+
}
|
|
90
|
+
async locate() {
|
|
91
|
+
await this.goToUrl(this.url);
|
|
92
|
+
}
|
|
93
|
+
async reloadPage() {
|
|
94
|
+
await this.driver.navigate().refresh();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/utils/locators.ts
|
|
99
|
+
var import_selenium_webdriver = require("selenium-webdriver");
|
|
100
|
+
var byTestId = (testId, element = "div") => {
|
|
101
|
+
return import_selenium_webdriver.By.css(`${element}[data-testid=${testId}]`);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// src/utils/createDriver.ts
|
|
105
|
+
var import_selenium_webdriver2 = require("selenium-webdriver");
|
|
106
|
+
var createDriver = async (browser) => {
|
|
107
|
+
const driver = await new import_selenium_webdriver2.Builder().forBrowser(browser ?? config().browser).build();
|
|
108
|
+
const manage = driver.manage();
|
|
109
|
+
await manage.setTimeouts({ implicit: config().timeout });
|
|
110
|
+
await manage.window().maximize();
|
|
111
|
+
return driver;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/utils/elementIsNotPresent.ts
|
|
115
|
+
var import_selenium_webdriver3 = require("selenium-webdriver");
|
|
116
|
+
var elementIsNotPresent = function elementIsNotPresent2(locator) {
|
|
117
|
+
return new import_selenium_webdriver3.Condition("for no element to be located " + locator, function(driver) {
|
|
118
|
+
return driver.findElements(locator).then(function(elements) {
|
|
119
|
+
return elements.length == 0;
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// src/pageObjects/AbstractElementWithParent.ts
|
|
125
|
+
var AbstractElementWithParent = class extends AbstractElement {
|
|
126
|
+
getParentElement;
|
|
127
|
+
elementBy;
|
|
128
|
+
constructor(getParentElement, driver) {
|
|
129
|
+
super(driver);
|
|
130
|
+
this.getParentElement = getParentElement;
|
|
131
|
+
}
|
|
132
|
+
async getElement() {
|
|
133
|
+
const parentEl = await this.getParentElement();
|
|
134
|
+
return parentEl.findElement(this.elementBy);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanelHeader.ts
|
|
139
|
+
var SubsystemsPanelHeader = class extends AbstractElementWithParent {
|
|
140
|
+
titleBy = byTestId("subsystems-panel-title", "span");
|
|
141
|
+
async title() {
|
|
142
|
+
const panel = await this.getParentElement();
|
|
143
|
+
return panel.findElement(this.titleBy);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanel.ts
|
|
148
|
+
var import_selenium_webdriver4 = require("selenium-webdriver");
|
|
149
|
+
var SubsystemsPanel = class extends AbstractElement {
|
|
150
|
+
panelBy = import_selenium_webdriver4.By.id("aside");
|
|
151
|
+
header;
|
|
152
|
+
constructor(driver) {
|
|
153
|
+
super(driver);
|
|
154
|
+
this.header = new SubsystemsPanelHeader(this.panelElement, this.driver);
|
|
155
|
+
}
|
|
156
|
+
panelElement = () => {
|
|
157
|
+
return this.driver.findElement(this.panelBy);
|
|
158
|
+
};
|
|
159
|
+
headerTitle() {
|
|
160
|
+
return this.header.title().then((el) => el.getText());
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/pageObjects/elements/Forms/AbstractForm.ts
|
|
165
|
+
var AbstractForm = class extends AbstractPage {
|
|
166
|
+
containerBy;
|
|
167
|
+
constructor(driver) {
|
|
168
|
+
super(driver);
|
|
169
|
+
this.containerBy = byTestId(`form-content-wrapper-${this.formName}`);
|
|
170
|
+
}
|
|
171
|
+
getContainerElement = () => {
|
|
172
|
+
return this.driver.findElement(this.containerBy);
|
|
173
|
+
};
|
|
174
|
+
get formName() {
|
|
175
|
+
return "";
|
|
176
|
+
}
|
|
177
|
+
async exists() {
|
|
178
|
+
try {
|
|
179
|
+
await this.driver.wait(elementIsNotPresent(this.containerBy), 1e3);
|
|
180
|
+
return false;
|
|
181
|
+
} catch {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
188
|
+
var import_selenium_webdriver6 = require("selenium-webdriver");
|
|
189
|
+
|
|
190
|
+
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
191
|
+
var import_selenium_webdriver5 = require("selenium-webdriver");
|
|
192
|
+
|
|
193
|
+
// src/pageObjects/AbstractFormElement.ts
|
|
194
|
+
var AbstractFormElement = class extends AbstractElementWithParent {
|
|
195
|
+
constructor(getParentElement, elementBy, driver) {
|
|
196
|
+
super(getParentElement, driver);
|
|
197
|
+
this.elementBy = elementBy;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
202
|
+
var AbstractDXEditorWithInput = class extends AbstractFormElement {
|
|
203
|
+
async getInputElement() {
|
|
204
|
+
const controlEl = await this.getElement();
|
|
205
|
+
return controlEl.findElement(import_selenium_webdriver5.By.className("dx-texteditor-input"));
|
|
206
|
+
}
|
|
207
|
+
async getInputValue() {
|
|
208
|
+
const inputEl = await this.getInputElement();
|
|
209
|
+
return inputEl.getAttribute("value");
|
|
210
|
+
}
|
|
211
|
+
async setInputValue(value) {
|
|
212
|
+
const inputEl = await this.getInputElement();
|
|
213
|
+
await inputEl.click();
|
|
214
|
+
await inputEl.sendKeys(value, import_selenium_webdriver5.Key.ENTER);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// src/pageObjects/elements/Editors/TextEditor.ts
|
|
219
|
+
var TextEditor = class extends AbstractDXEditorWithInput {
|
|
220
|
+
getValue() {
|
|
221
|
+
return this.getInputValue();
|
|
222
|
+
}
|
|
223
|
+
setValue(value) {
|
|
224
|
+
return this.setInputValue(value);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/pageObjects/elements/Editors/NumberEditor.ts
|
|
229
|
+
var NumberEditor = class extends AbstractDXEditorWithInput {
|
|
230
|
+
async getValue() {
|
|
231
|
+
const value = await super.getInputValue();
|
|
232
|
+
return value == "" ? null : Number.parseFloat(value);
|
|
233
|
+
}
|
|
234
|
+
setValue(value) {
|
|
235
|
+
return this.setInputValue(value);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
240
|
+
var editorFactory = async (getParentElement, elementBy, driver) => {
|
|
241
|
+
const elementInstance = new AbstractFormElement(getParentElement, elementBy, driver);
|
|
242
|
+
const element = await elementInstance.getElement();
|
|
243
|
+
const classSting = await element.getAttribute("class");
|
|
244
|
+
if (classSting.includes("text-control"))
|
|
245
|
+
return new TextEditor(getParentElement, elementBy, driver);
|
|
246
|
+
if (classSting.includes("number-control"))
|
|
247
|
+
return new NumberEditor(getParentElement, elementBy, driver);
|
|
248
|
+
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// src/utils/createDataTestId.ts
|
|
252
|
+
function createDataTestId(formName, itemType, itemName) {
|
|
253
|
+
return `${formName}-${itemType}-${itemName}`;
|
|
254
|
+
}
|
|
255
|
+
function createFieldTestId(formName, itemName) {
|
|
256
|
+
return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/pageObjects/elements/FormField.ts
|
|
260
|
+
var FormField = class extends AbstractElementWithParent {
|
|
261
|
+
editor;
|
|
262
|
+
constructor(getParentElement, formName, name, driver) {
|
|
263
|
+
super(getParentElement, driver);
|
|
264
|
+
this.elementBy = byTestId(createFieldTestId(formName, name));
|
|
265
|
+
}
|
|
266
|
+
async initEditor() {
|
|
267
|
+
if (!this.editor) {
|
|
268
|
+
this.editor = await editorFactory(this.getParentElement, this.elementBy, this.driver);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async getValue() {
|
|
272
|
+
await this.initEditor();
|
|
273
|
+
return this.editor.getValue();
|
|
274
|
+
}
|
|
275
|
+
async setValue(value) {
|
|
276
|
+
await this.initEditor();
|
|
277
|
+
return this.editor.setValue(value);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
282
|
+
var FormEdit = class extends AbstractForm {
|
|
283
|
+
saveButtonBy = import_selenium_webdriver6.By.id("button-save");
|
|
284
|
+
field(name) {
|
|
285
|
+
return new FormField(this.getContainerElement, this.formName, name, this.driver);
|
|
286
|
+
}
|
|
287
|
+
async saveButtonClick() {
|
|
288
|
+
await this.driver.findElement(this.saveButtonBy).click();
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/pageObjects/elements/Forms/ListForm.ts
|
|
293
|
+
var import_selenium_webdriver7 = require("selenium-webdriver");
|
|
294
|
+
var ListForm = class extends AbstractForm {
|
|
295
|
+
titleBy = import_selenium_webdriver7.By.className("form-toolbar-name-container");
|
|
296
|
+
getTitleText() {
|
|
297
|
+
return this.getContainerElement().then((el) => el.findElement(this.titleBy)).then((el) => el.getText());
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// src/utils/signIn.ts
|
|
302
|
+
async function signIn(driver) {
|
|
303
|
+
const webDriver = driver ?? await createDriver();
|
|
304
|
+
config().driver = webDriver;
|
|
305
|
+
const loginPage = new LoginPage(webDriver);
|
|
306
|
+
await loginPage.locate();
|
|
307
|
+
await loginPage.authorize();
|
|
308
|
+
return webDriver;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/pageObjects/pages/LoginPage.ts
|
|
312
|
+
var LOGIN_PATH = "/login";
|
|
313
|
+
var LoginPage = class extends AbstractPage {
|
|
314
|
+
usernameField = byTestId("loginField", "input");
|
|
315
|
+
passwordField = byTestId("passwordField", "input");
|
|
316
|
+
loginButton = byTestId("loginButton");
|
|
317
|
+
get path() {
|
|
318
|
+
return LOGIN_PATH;
|
|
319
|
+
}
|
|
320
|
+
async enterUsername(username) {
|
|
321
|
+
await this.driver.findElement(this.usernameField).sendKeys(username);
|
|
322
|
+
}
|
|
323
|
+
async enterPassword(password) {
|
|
324
|
+
await this.driver.findElement(this.passwordField).sendKeys(password);
|
|
325
|
+
}
|
|
326
|
+
async clickLoginButton() {
|
|
327
|
+
await this.driver.findElement(this.loginButton).click();
|
|
328
|
+
}
|
|
329
|
+
async loginWith(username, password) {
|
|
330
|
+
await this.enterUsername(username);
|
|
331
|
+
await this.enterPassword(password);
|
|
332
|
+
await this.clickLoginButton();
|
|
333
|
+
}
|
|
334
|
+
async authorize() {
|
|
335
|
+
await this.loginWith(config().auth.login, config().auth.password);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
339
|
+
0 && (module.exports = {
|
|
340
|
+
AbstractPage,
|
|
341
|
+
FormEdit,
|
|
342
|
+
FormField,
|
|
343
|
+
ListForm,
|
|
344
|
+
LoginPage,
|
|
345
|
+
NumberEditor,
|
|
346
|
+
SubsystemsPanel,
|
|
347
|
+
TextEditor,
|
|
348
|
+
byTestId,
|
|
349
|
+
config,
|
|
350
|
+
createDriver,
|
|
351
|
+
editorFactory,
|
|
352
|
+
elementIsNotPresent,
|
|
353
|
+
signIn
|
|
354
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as selenium_webdriver from 'selenium-webdriver';
|
|
2
|
+
import { WebDriver, Browser, By, Condition, WebElementPromise } from 'selenium-webdriver';
|
|
3
|
+
|
|
4
|
+
type DriverType = typeof Browser;
|
|
5
|
+
type BrowserList = DriverType[keyof DriverType];
|
|
6
|
+
type IConfig = {
|
|
7
|
+
auth: {
|
|
8
|
+
host: string;
|
|
9
|
+
login: string;
|
|
10
|
+
password: string;
|
|
11
|
+
};
|
|
12
|
+
timeout: number;
|
|
13
|
+
browser: BrowserList;
|
|
14
|
+
driver?: WebDriver;
|
|
15
|
+
};
|
|
16
|
+
declare function config(cfg?: IConfig): IConfig;
|
|
17
|
+
|
|
18
|
+
declare abstract class AbstractElement {
|
|
19
|
+
protected driver: WebDriver;
|
|
20
|
+
protected constructor(driver?: WebDriver);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare abstract class AbstractPage extends AbstractElement {
|
|
24
|
+
protected url: string;
|
|
25
|
+
protected host: string;
|
|
26
|
+
constructor(driver?: WebDriver);
|
|
27
|
+
private prependHash;
|
|
28
|
+
protected goToUrl(url: string): Promise<void>;
|
|
29
|
+
protected get path(): string;
|
|
30
|
+
locate(): Promise<void>;
|
|
31
|
+
reloadPage(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declare class LoginPage extends AbstractPage {
|
|
35
|
+
usernameField: selenium_webdriver.By;
|
|
36
|
+
passwordField: selenium_webdriver.By;
|
|
37
|
+
loginButton: selenium_webdriver.By;
|
|
38
|
+
get path(): string;
|
|
39
|
+
enterUsername(username: string): Promise<void>;
|
|
40
|
+
enterPassword(password: string): Promise<void>;
|
|
41
|
+
clickLoginButton(): Promise<void>;
|
|
42
|
+
loginWith(username: string, password: string): Promise<void>;
|
|
43
|
+
authorize(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns a By locator object that can be used to locate an element by its test ID.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} testId - The test ID of the element.
|
|
50
|
+
* @param {string} [element='div'] - The HTML tag name of the element (optional).
|
|
51
|
+
* @returns {By} - The By locator object.
|
|
52
|
+
*/
|
|
53
|
+
declare const byTestId: (testId: string, element?: string) => By;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a WebDriver instance for the specified browser.
|
|
57
|
+
* If no browser parameter is provided, it uses the default browser specified in the configuration.
|
|
58
|
+
* The default timeout is also set based on the configuration.
|
|
59
|
+
*
|
|
60
|
+
* @param {BrowserList} browser - The browser to create the WebDriver instance for.
|
|
61
|
+
* @returns {Promise<WebDriver>} A promise that resolves to the WebDriver instance.
|
|
62
|
+
*/
|
|
63
|
+
declare const createDriver: (browser?: BrowserList) => Promise<WebDriver>;
|
|
64
|
+
|
|
65
|
+
declare const elementIsNotPresent: (locator: By) => Condition<boolean>;
|
|
66
|
+
|
|
67
|
+
declare function signIn(driver?: WebDriver): Promise<WebDriver>;
|
|
68
|
+
|
|
69
|
+
declare class SubsystemsPanel extends AbstractElement {
|
|
70
|
+
private panelBy;
|
|
71
|
+
private header;
|
|
72
|
+
constructor(driver?: WebDriver);
|
|
73
|
+
private panelElement;
|
|
74
|
+
headerTitle(): Promise<string>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
declare abstract class AbstractForm extends AbstractPage {
|
|
78
|
+
protected containerBy: By;
|
|
79
|
+
constructor(driver?: WebDriver);
|
|
80
|
+
protected getContainerElement: () => selenium_webdriver.WebElementPromise;
|
|
81
|
+
protected get formName(): string;
|
|
82
|
+
exists(): Promise<boolean>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare abstract class AbstractElementWithParent extends AbstractElement {
|
|
86
|
+
protected getParentElement: () => WebElementPromise;
|
|
87
|
+
protected elementBy: By;
|
|
88
|
+
constructor(getParentElement: () => WebElementPromise, driver?: WebDriver);
|
|
89
|
+
getElement(): Promise<selenium_webdriver.WebElement>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface Editor {
|
|
93
|
+
setValue(value: any): Promise<void>;
|
|
94
|
+
getValue(): Promise<any>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
declare class AbstractFormElement extends AbstractElementWithParent {
|
|
98
|
+
constructor(getParentElement: () => WebElementPromise, elementBy: By, driver?: WebDriver);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
declare abstract class AbstractDXEditorWithInput extends AbstractFormElement implements Editor {
|
|
102
|
+
protected getInputElement(): Promise<selenium_webdriver.WebElement>;
|
|
103
|
+
protected getInputValue(): Promise<string>;
|
|
104
|
+
protected setInputValue(value: string): Promise<void>;
|
|
105
|
+
abstract setValue(value: any): Promise<void>;
|
|
106
|
+
abstract getValue(): Promise<any>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
declare class TextEditor extends AbstractDXEditorWithInput {
|
|
110
|
+
getValue(): Promise<string>;
|
|
111
|
+
setValue(value: string): Promise<void>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare class NumberEditor extends AbstractDXEditorWithInput {
|
|
115
|
+
getValue(): Promise<number | null>;
|
|
116
|
+
setValue(value: any): Promise<void>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
declare const editorFactory: (getParentElement: () => WebElementPromise, elementBy: By, driver?: WebDriver) => Promise<Editor>;
|
|
120
|
+
|
|
121
|
+
declare class FormField extends AbstractElementWithParent implements Editor {
|
|
122
|
+
editor: Editor;
|
|
123
|
+
constructor(getParentElement: () => WebElementPromise, formName: string, name: string, driver?: WebDriver);
|
|
124
|
+
private initEditor;
|
|
125
|
+
getValue(): Promise<any>;
|
|
126
|
+
setValue(value: any): Promise<void>;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
declare abstract class FormEdit extends AbstractForm {
|
|
130
|
+
saveButtonBy: By;
|
|
131
|
+
field(name: string): FormField;
|
|
132
|
+
saveButtonClick(): Promise<void>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
declare abstract class ListForm extends AbstractForm {
|
|
136
|
+
titleBy: By;
|
|
137
|
+
getTitleText(): Promise<string>;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export { AbstractPage, Editor, FormEdit, FormField, ListForm, LoginPage, NumberEditor, SubsystemsPanel, TextEditor, byTestId, config, createDriver, editorFactory, elementIsNotPresent, signIn };
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
var Config = class _Config {
|
|
3
|
+
static instance;
|
|
4
|
+
appConfig;
|
|
5
|
+
static getInstance() {
|
|
6
|
+
if (!_Config.instance) {
|
|
7
|
+
_Config.instance = new _Config();
|
|
8
|
+
}
|
|
9
|
+
return _Config.instance;
|
|
10
|
+
}
|
|
11
|
+
config = (cfg) => {
|
|
12
|
+
if (!cfg)
|
|
13
|
+
return this.appConfig;
|
|
14
|
+
this.appConfig = cfg;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
var configInstance = Config.getInstance();
|
|
18
|
+
function config(cfg) {
|
|
19
|
+
return configInstance.config(cfg);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/pageObjects/AbstractElement.ts
|
|
23
|
+
var AbstractElement = class {
|
|
24
|
+
driver;
|
|
25
|
+
constructor(driver) {
|
|
26
|
+
this.driver = driver || config().driver;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/pageObjects/pages/AbstractPage.ts
|
|
31
|
+
var AbstractPage = class extends AbstractElement {
|
|
32
|
+
url;
|
|
33
|
+
host;
|
|
34
|
+
constructor(driver) {
|
|
35
|
+
super(driver);
|
|
36
|
+
this.host = config().auth.host;
|
|
37
|
+
this.url = this.host + this.prependHash(this.path);
|
|
38
|
+
}
|
|
39
|
+
prependHash(urlPath) {
|
|
40
|
+
if (!urlPath.startsWith("/#")) {
|
|
41
|
+
return `/#${urlPath}`;
|
|
42
|
+
}
|
|
43
|
+
return urlPath;
|
|
44
|
+
}
|
|
45
|
+
async goToUrl(url) {
|
|
46
|
+
await this.driver.get(url);
|
|
47
|
+
}
|
|
48
|
+
get path() {
|
|
49
|
+
return "/#";
|
|
50
|
+
}
|
|
51
|
+
async locate() {
|
|
52
|
+
await this.goToUrl(this.url);
|
|
53
|
+
}
|
|
54
|
+
async reloadPage() {
|
|
55
|
+
await this.driver.navigate().refresh();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/utils/locators.ts
|
|
60
|
+
import { By } from "selenium-webdriver";
|
|
61
|
+
var byTestId = (testId, element = "div") => {
|
|
62
|
+
return By.css(`${element}[data-testid=${testId}]`);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// src/utils/createDriver.ts
|
|
66
|
+
import { Builder } from "selenium-webdriver";
|
|
67
|
+
var createDriver = async (browser) => {
|
|
68
|
+
const driver = await new Builder().forBrowser(browser ?? config().browser).build();
|
|
69
|
+
const manage = driver.manage();
|
|
70
|
+
await manage.setTimeouts({ implicit: config().timeout });
|
|
71
|
+
await manage.window().maximize();
|
|
72
|
+
return driver;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/utils/elementIsNotPresent.ts
|
|
76
|
+
import { Condition } from "selenium-webdriver";
|
|
77
|
+
var elementIsNotPresent = function elementIsNotPresent2(locator) {
|
|
78
|
+
return new Condition("for no element to be located " + locator, function(driver) {
|
|
79
|
+
return driver.findElements(locator).then(function(elements) {
|
|
80
|
+
return elements.length == 0;
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/pageObjects/AbstractElementWithParent.ts
|
|
86
|
+
var AbstractElementWithParent = class extends AbstractElement {
|
|
87
|
+
getParentElement;
|
|
88
|
+
elementBy;
|
|
89
|
+
constructor(getParentElement, driver) {
|
|
90
|
+
super(driver);
|
|
91
|
+
this.getParentElement = getParentElement;
|
|
92
|
+
}
|
|
93
|
+
async getElement() {
|
|
94
|
+
const parentEl = await this.getParentElement();
|
|
95
|
+
return parentEl.findElement(this.elementBy);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanelHeader.ts
|
|
100
|
+
var SubsystemsPanelHeader = class extends AbstractElementWithParent {
|
|
101
|
+
titleBy = byTestId("subsystems-panel-title", "span");
|
|
102
|
+
async title() {
|
|
103
|
+
const panel = await this.getParentElement();
|
|
104
|
+
return panel.findElement(this.titleBy);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanel.ts
|
|
109
|
+
import { By as By3 } from "selenium-webdriver";
|
|
110
|
+
var SubsystemsPanel = class extends AbstractElement {
|
|
111
|
+
panelBy = By3.id("aside");
|
|
112
|
+
header;
|
|
113
|
+
constructor(driver) {
|
|
114
|
+
super(driver);
|
|
115
|
+
this.header = new SubsystemsPanelHeader(this.panelElement, this.driver);
|
|
116
|
+
}
|
|
117
|
+
panelElement = () => {
|
|
118
|
+
return this.driver.findElement(this.panelBy);
|
|
119
|
+
};
|
|
120
|
+
headerTitle() {
|
|
121
|
+
return this.header.title().then((el) => el.getText());
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/pageObjects/elements/Forms/AbstractForm.ts
|
|
126
|
+
var AbstractForm = class extends AbstractPage {
|
|
127
|
+
containerBy;
|
|
128
|
+
constructor(driver) {
|
|
129
|
+
super(driver);
|
|
130
|
+
this.containerBy = byTestId(`form-content-wrapper-${this.formName}`);
|
|
131
|
+
}
|
|
132
|
+
getContainerElement = () => {
|
|
133
|
+
return this.driver.findElement(this.containerBy);
|
|
134
|
+
};
|
|
135
|
+
get formName() {
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
async exists() {
|
|
139
|
+
try {
|
|
140
|
+
await this.driver.wait(elementIsNotPresent(this.containerBy), 1e3);
|
|
141
|
+
return false;
|
|
142
|
+
} catch {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
149
|
+
import { By as By5 } from "selenium-webdriver";
|
|
150
|
+
|
|
151
|
+
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
152
|
+
import { By as By4, Key } from "selenium-webdriver";
|
|
153
|
+
|
|
154
|
+
// src/pageObjects/AbstractFormElement.ts
|
|
155
|
+
var AbstractFormElement = class extends AbstractElementWithParent {
|
|
156
|
+
constructor(getParentElement, elementBy, driver) {
|
|
157
|
+
super(getParentElement, driver);
|
|
158
|
+
this.elementBy = elementBy;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
163
|
+
var AbstractDXEditorWithInput = class extends AbstractFormElement {
|
|
164
|
+
async getInputElement() {
|
|
165
|
+
const controlEl = await this.getElement();
|
|
166
|
+
return controlEl.findElement(By4.className("dx-texteditor-input"));
|
|
167
|
+
}
|
|
168
|
+
async getInputValue() {
|
|
169
|
+
const inputEl = await this.getInputElement();
|
|
170
|
+
return inputEl.getAttribute("value");
|
|
171
|
+
}
|
|
172
|
+
async setInputValue(value) {
|
|
173
|
+
const inputEl = await this.getInputElement();
|
|
174
|
+
await inputEl.click();
|
|
175
|
+
await inputEl.sendKeys(value, Key.ENTER);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// src/pageObjects/elements/Editors/TextEditor.ts
|
|
180
|
+
var TextEditor = class extends AbstractDXEditorWithInput {
|
|
181
|
+
getValue() {
|
|
182
|
+
return this.getInputValue();
|
|
183
|
+
}
|
|
184
|
+
setValue(value) {
|
|
185
|
+
return this.setInputValue(value);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/pageObjects/elements/Editors/NumberEditor.ts
|
|
190
|
+
var NumberEditor = class extends AbstractDXEditorWithInput {
|
|
191
|
+
async getValue() {
|
|
192
|
+
const value = await super.getInputValue();
|
|
193
|
+
return value == "" ? null : Number.parseFloat(value);
|
|
194
|
+
}
|
|
195
|
+
setValue(value) {
|
|
196
|
+
return this.setInputValue(value);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
201
|
+
var editorFactory = async (getParentElement, elementBy, driver) => {
|
|
202
|
+
const elementInstance = new AbstractFormElement(getParentElement, elementBy, driver);
|
|
203
|
+
const element = await elementInstance.getElement();
|
|
204
|
+
const classSting = await element.getAttribute("class");
|
|
205
|
+
if (classSting.includes("text-control"))
|
|
206
|
+
return new TextEditor(getParentElement, elementBy, driver);
|
|
207
|
+
if (classSting.includes("number-control"))
|
|
208
|
+
return new NumberEditor(getParentElement, elementBy, driver);
|
|
209
|
+
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/utils/createDataTestId.ts
|
|
213
|
+
function createDataTestId(formName, itemType, itemName) {
|
|
214
|
+
return `${formName}-${itemType}-${itemName}`;
|
|
215
|
+
}
|
|
216
|
+
function createFieldTestId(formName, itemName) {
|
|
217
|
+
return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/pageObjects/elements/FormField.ts
|
|
221
|
+
var FormField = class extends AbstractElementWithParent {
|
|
222
|
+
editor;
|
|
223
|
+
constructor(getParentElement, formName, name, driver) {
|
|
224
|
+
super(getParentElement, driver);
|
|
225
|
+
this.elementBy = byTestId(createFieldTestId(formName, name));
|
|
226
|
+
}
|
|
227
|
+
async initEditor() {
|
|
228
|
+
if (!this.editor) {
|
|
229
|
+
this.editor = await editorFactory(this.getParentElement, this.elementBy, this.driver);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async getValue() {
|
|
233
|
+
await this.initEditor();
|
|
234
|
+
return this.editor.getValue();
|
|
235
|
+
}
|
|
236
|
+
async setValue(value) {
|
|
237
|
+
await this.initEditor();
|
|
238
|
+
return this.editor.setValue(value);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
243
|
+
var FormEdit = class extends AbstractForm {
|
|
244
|
+
saveButtonBy = By5.id("button-save");
|
|
245
|
+
field(name) {
|
|
246
|
+
return new FormField(this.getContainerElement, this.formName, name, this.driver);
|
|
247
|
+
}
|
|
248
|
+
async saveButtonClick() {
|
|
249
|
+
await this.driver.findElement(this.saveButtonBy).click();
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// src/pageObjects/elements/Forms/ListForm.ts
|
|
254
|
+
import { By as By6 } from "selenium-webdriver";
|
|
255
|
+
var ListForm = class extends AbstractForm {
|
|
256
|
+
titleBy = By6.className("form-toolbar-name-container");
|
|
257
|
+
getTitleText() {
|
|
258
|
+
return this.getContainerElement().then((el) => el.findElement(this.titleBy)).then((el) => el.getText());
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/utils/signIn.ts
|
|
263
|
+
async function signIn(driver) {
|
|
264
|
+
const webDriver = driver ?? await createDriver();
|
|
265
|
+
config().driver = webDriver;
|
|
266
|
+
const loginPage = new LoginPage(webDriver);
|
|
267
|
+
await loginPage.locate();
|
|
268
|
+
await loginPage.authorize();
|
|
269
|
+
return webDriver;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/pageObjects/pages/LoginPage.ts
|
|
273
|
+
var LOGIN_PATH = "/login";
|
|
274
|
+
var LoginPage = class extends AbstractPage {
|
|
275
|
+
usernameField = byTestId("loginField", "input");
|
|
276
|
+
passwordField = byTestId("passwordField", "input");
|
|
277
|
+
loginButton = byTestId("loginButton");
|
|
278
|
+
get path() {
|
|
279
|
+
return LOGIN_PATH;
|
|
280
|
+
}
|
|
281
|
+
async enterUsername(username) {
|
|
282
|
+
await this.driver.findElement(this.usernameField).sendKeys(username);
|
|
283
|
+
}
|
|
284
|
+
async enterPassword(password) {
|
|
285
|
+
await this.driver.findElement(this.passwordField).sendKeys(password);
|
|
286
|
+
}
|
|
287
|
+
async clickLoginButton() {
|
|
288
|
+
await this.driver.findElement(this.loginButton).click();
|
|
289
|
+
}
|
|
290
|
+
async loginWith(username, password) {
|
|
291
|
+
await this.enterUsername(username);
|
|
292
|
+
await this.enterPassword(password);
|
|
293
|
+
await this.clickLoginButton();
|
|
294
|
+
}
|
|
295
|
+
async authorize() {
|
|
296
|
+
await this.loginWith(config().auth.login, config().auth.password);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
export {
|
|
300
|
+
AbstractPage,
|
|
301
|
+
FormEdit,
|
|
302
|
+
FormField,
|
|
303
|
+
ListForm,
|
|
304
|
+
LoginPage,
|
|
305
|
+
NumberEditor,
|
|
306
|
+
SubsystemsPanel,
|
|
307
|
+
TextEditor,
|
|
308
|
+
byTestId,
|
|
309
|
+
config,
|
|
310
|
+
createDriver,
|
|
311
|
+
editorFactory,
|
|
312
|
+
elementIsNotPresent,
|
|
313
|
+
signIn
|
|
314
|
+
};
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
var Config = class _Config {
|
|
3
|
+
static instance;
|
|
4
|
+
appConfig;
|
|
5
|
+
static getInstance() {
|
|
6
|
+
if (!_Config.instance) {
|
|
7
|
+
_Config.instance = new _Config();
|
|
8
|
+
}
|
|
9
|
+
return _Config.instance;
|
|
10
|
+
}
|
|
11
|
+
config = (cfg) => {
|
|
12
|
+
if (!cfg)
|
|
13
|
+
return this.appConfig;
|
|
14
|
+
this.appConfig = cfg;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
var configInstance = Config.getInstance();
|
|
18
|
+
function config(cfg) {
|
|
19
|
+
return configInstance.config(cfg);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/pageObjects/AbstractElement.ts
|
|
23
|
+
var AbstractElement = class {
|
|
24
|
+
driver;
|
|
25
|
+
constructor(driver) {
|
|
26
|
+
this.driver = driver || config().driver;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/pageObjects/pages/AbstractPage.ts
|
|
31
|
+
var AbstractPage = class extends AbstractElement {
|
|
32
|
+
url;
|
|
33
|
+
host;
|
|
34
|
+
constructor(driver) {
|
|
35
|
+
super(driver);
|
|
36
|
+
this.host = config().auth.host;
|
|
37
|
+
this.url = this.host + this.prependHash(this.path);
|
|
38
|
+
}
|
|
39
|
+
prependHash(urlPath) {
|
|
40
|
+
if (!urlPath.startsWith("/#")) {
|
|
41
|
+
return `/#${urlPath}`;
|
|
42
|
+
}
|
|
43
|
+
return urlPath;
|
|
44
|
+
}
|
|
45
|
+
async goToUrl(url) {
|
|
46
|
+
await this.driver.get(url);
|
|
47
|
+
}
|
|
48
|
+
get path() {
|
|
49
|
+
return "/#";
|
|
50
|
+
}
|
|
51
|
+
async locate() {
|
|
52
|
+
await this.goToUrl(this.url);
|
|
53
|
+
}
|
|
54
|
+
async reloadPage() {
|
|
55
|
+
await this.driver.navigate().refresh();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/utils/locators.ts
|
|
60
|
+
import { By } from "selenium-webdriver";
|
|
61
|
+
var byTestId = (testId, element = "div") => {
|
|
62
|
+
return By.css(`${element}[data-testid=${testId}]`);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// src/utils/createDriver.ts
|
|
66
|
+
import { Builder } from "selenium-webdriver";
|
|
67
|
+
var createDriver = async (browser) => {
|
|
68
|
+
const driver = await new Builder().forBrowser(browser ?? config().browser).build();
|
|
69
|
+
const manage = driver.manage();
|
|
70
|
+
await manage.setTimeouts({ implicit: config().timeout });
|
|
71
|
+
await manage.window().maximize();
|
|
72
|
+
return driver;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/utils/elementIsNotPresent.ts
|
|
76
|
+
import { Condition } from "selenium-webdriver";
|
|
77
|
+
var elementIsNotPresent = function elementIsNotPresent2(locator) {
|
|
78
|
+
return new Condition("for no element to be located " + locator, function(driver) {
|
|
79
|
+
return driver.findElements(locator).then(function(elements) {
|
|
80
|
+
return elements.length == 0;
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/pageObjects/AbstractElementWithParent.ts
|
|
86
|
+
var AbstractElementWithParent = class extends AbstractElement {
|
|
87
|
+
getParentElement;
|
|
88
|
+
elementBy;
|
|
89
|
+
constructor(getParentElement, driver) {
|
|
90
|
+
super(driver);
|
|
91
|
+
this.getParentElement = getParentElement;
|
|
92
|
+
}
|
|
93
|
+
async getElement() {
|
|
94
|
+
const parentEl = await this.getParentElement();
|
|
95
|
+
return parentEl.findElement(this.elementBy);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanelHeader.ts
|
|
100
|
+
var SubsystemsPanelHeader = class extends AbstractElementWithParent {
|
|
101
|
+
titleBy = byTestId("subsystems-panel-title", "span");
|
|
102
|
+
async title() {
|
|
103
|
+
const panel = await this.getParentElement();
|
|
104
|
+
return panel.findElement(this.titleBy);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/pageObjects/elements/SubsystemsPanel/SubsystemsPanel.ts
|
|
109
|
+
import { By as By3 } from "selenium-webdriver";
|
|
110
|
+
var SubsystemsPanel = class extends AbstractElement {
|
|
111
|
+
panelBy = By3.id("aside");
|
|
112
|
+
header;
|
|
113
|
+
constructor(driver) {
|
|
114
|
+
super(driver);
|
|
115
|
+
this.header = new SubsystemsPanelHeader(this.panelElement, this.driver);
|
|
116
|
+
}
|
|
117
|
+
panelElement = () => {
|
|
118
|
+
return this.driver.findElement(this.panelBy);
|
|
119
|
+
};
|
|
120
|
+
headerTitle() {
|
|
121
|
+
return this.header.title().then((el) => el.getText());
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/pageObjects/elements/Forms/AbstractForm.ts
|
|
126
|
+
var AbstractForm = class extends AbstractPage {
|
|
127
|
+
containerBy;
|
|
128
|
+
constructor(driver) {
|
|
129
|
+
super(driver);
|
|
130
|
+
this.containerBy = byTestId(`form-content-wrapper-${this.formName}`);
|
|
131
|
+
}
|
|
132
|
+
getContainerElement = () => {
|
|
133
|
+
return this.driver.findElement(this.containerBy);
|
|
134
|
+
};
|
|
135
|
+
get formName() {
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
async exists() {
|
|
139
|
+
try {
|
|
140
|
+
await this.driver.wait(elementIsNotPresent(this.containerBy), 1e3);
|
|
141
|
+
return false;
|
|
142
|
+
} catch {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
149
|
+
import { By as By5 } from "selenium-webdriver";
|
|
150
|
+
|
|
151
|
+
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
152
|
+
import { By as By4, Key } from "selenium-webdriver";
|
|
153
|
+
|
|
154
|
+
// src/pageObjects/AbstractFormElement.ts
|
|
155
|
+
var AbstractFormElement = class extends AbstractElementWithParent {
|
|
156
|
+
constructor(getParentElement, elementBy, driver) {
|
|
157
|
+
super(getParentElement, driver);
|
|
158
|
+
this.elementBy = elementBy;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// src/pageObjects/elements/Editors/AbstractEditor.ts
|
|
163
|
+
var AbstractDXEditorWithInput = class extends AbstractFormElement {
|
|
164
|
+
async getInputElement() {
|
|
165
|
+
const controlEl = await this.getElement();
|
|
166
|
+
return controlEl.findElement(By4.className("dx-texteditor-input"));
|
|
167
|
+
}
|
|
168
|
+
async getInputValue() {
|
|
169
|
+
const inputEl = await this.getInputElement();
|
|
170
|
+
return inputEl.getAttribute("value");
|
|
171
|
+
}
|
|
172
|
+
async setInputValue(value) {
|
|
173
|
+
const inputEl = await this.getInputElement();
|
|
174
|
+
await inputEl.click();
|
|
175
|
+
await inputEl.sendKeys(value, Key.ENTER);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// src/pageObjects/elements/Editors/TextEditor.ts
|
|
180
|
+
var TextEditor = class extends AbstractDXEditorWithInput {
|
|
181
|
+
getValue() {
|
|
182
|
+
return this.getInputValue();
|
|
183
|
+
}
|
|
184
|
+
setValue(value) {
|
|
185
|
+
return this.setInputValue(value);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/pageObjects/elements/Editors/NumberEditor.ts
|
|
190
|
+
var NumberEditor = class extends AbstractDXEditorWithInput {
|
|
191
|
+
async getValue() {
|
|
192
|
+
const value = await super.getInputValue();
|
|
193
|
+
return value == "" ? null : Number.parseFloat(value);
|
|
194
|
+
}
|
|
195
|
+
setValue(value) {
|
|
196
|
+
return this.setInputValue(value);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// src/pageObjects/elements/Editors/editorFactory.ts
|
|
201
|
+
var editorFactory = async (getParentElement, elementBy, driver) => {
|
|
202
|
+
const elementInstance = new AbstractFormElement(getParentElement, elementBy, driver);
|
|
203
|
+
const element = await elementInstance.getElement();
|
|
204
|
+
const classSting = await element.getAttribute("class");
|
|
205
|
+
if (classSting.includes("text-control"))
|
|
206
|
+
return new TextEditor(getParentElement, elementBy, driver);
|
|
207
|
+
if (classSting.includes("number-control"))
|
|
208
|
+
return new NumberEditor(getParentElement, elementBy, driver);
|
|
209
|
+
throw new Error("Unknown type of editor. Please write ticket to the support");
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/utils/createDataTestId.ts
|
|
213
|
+
function createDataTestId(formName, itemType, itemName) {
|
|
214
|
+
return `${formName}-${itemType}-${itemName}`;
|
|
215
|
+
}
|
|
216
|
+
function createFieldTestId(formName, itemName) {
|
|
217
|
+
return createDataTestId(formName, "form_field" /* FORM_FIELD */, itemName);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/pageObjects/elements/FormField.ts
|
|
221
|
+
var FormField = class extends AbstractElementWithParent {
|
|
222
|
+
editor;
|
|
223
|
+
constructor(getParentElement, formName, name, driver) {
|
|
224
|
+
super(getParentElement, driver);
|
|
225
|
+
this.elementBy = byTestId(createFieldTestId(formName, name));
|
|
226
|
+
}
|
|
227
|
+
async initEditor() {
|
|
228
|
+
if (!this.editor) {
|
|
229
|
+
this.editor = await editorFactory(this.getParentElement, this.elementBy, this.driver);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async getValue() {
|
|
233
|
+
await this.initEditor();
|
|
234
|
+
return this.editor.getValue();
|
|
235
|
+
}
|
|
236
|
+
async setValue(value) {
|
|
237
|
+
await this.initEditor();
|
|
238
|
+
return this.editor.setValue(value);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// src/pageObjects/elements/Forms/FormEdit.ts
|
|
243
|
+
var FormEdit = class extends AbstractForm {
|
|
244
|
+
saveButtonBy = By5.id("button-save");
|
|
245
|
+
field(name) {
|
|
246
|
+
return new FormField(this.getContainerElement, this.formName, name, this.driver);
|
|
247
|
+
}
|
|
248
|
+
async saveButtonClick() {
|
|
249
|
+
await this.driver.findElement(this.saveButtonBy).click();
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// src/pageObjects/elements/Forms/ListForm.ts
|
|
254
|
+
import { By as By6 } from "selenium-webdriver";
|
|
255
|
+
var ListForm = class extends AbstractForm {
|
|
256
|
+
titleBy = By6.className("form-toolbar-name-container");
|
|
257
|
+
getTitleText() {
|
|
258
|
+
return this.getContainerElement().then((el) => el.findElement(this.titleBy)).then((el) => el.getText());
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/utils/signIn.ts
|
|
263
|
+
async function signIn(driver) {
|
|
264
|
+
const webDriver = driver ?? await createDriver();
|
|
265
|
+
config().driver = webDriver;
|
|
266
|
+
const loginPage = new LoginPage(webDriver);
|
|
267
|
+
await loginPage.locate();
|
|
268
|
+
await loginPage.authorize();
|
|
269
|
+
return webDriver;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/pageObjects/pages/LoginPage.ts
|
|
273
|
+
var LOGIN_PATH = "/login";
|
|
274
|
+
var LoginPage = class extends AbstractPage {
|
|
275
|
+
usernameField = byTestId("loginField", "input");
|
|
276
|
+
passwordField = byTestId("passwordField", "input");
|
|
277
|
+
loginButton = byTestId("loginButton");
|
|
278
|
+
get path() {
|
|
279
|
+
return LOGIN_PATH;
|
|
280
|
+
}
|
|
281
|
+
async enterUsername(username) {
|
|
282
|
+
await this.driver.findElement(this.usernameField).sendKeys(username);
|
|
283
|
+
}
|
|
284
|
+
async enterPassword(password) {
|
|
285
|
+
await this.driver.findElement(this.passwordField).sendKeys(password);
|
|
286
|
+
}
|
|
287
|
+
async clickLoginButton() {
|
|
288
|
+
await this.driver.findElement(this.loginButton).click();
|
|
289
|
+
}
|
|
290
|
+
async loginWith(username, password) {
|
|
291
|
+
await this.enterUsername(username);
|
|
292
|
+
await this.enterPassword(password);
|
|
293
|
+
await this.clickLoginButton();
|
|
294
|
+
}
|
|
295
|
+
async authorize() {
|
|
296
|
+
await this.loginWith(config().auth.login, config().auth.password);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
export {
|
|
300
|
+
AbstractPage,
|
|
301
|
+
FormEdit,
|
|
302
|
+
FormField,
|
|
303
|
+
ListForm,
|
|
304
|
+
LoginPage,
|
|
305
|
+
NumberEditor,
|
|
306
|
+
SubsystemsPanel,
|
|
307
|
+
TextEditor,
|
|
308
|
+
byTestId,
|
|
309
|
+
config,
|
|
310
|
+
createDriver,
|
|
311
|
+
editorFactory,
|
|
312
|
+
elementIsNotPresent,
|
|
313
|
+
signIn
|
|
314
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "d5-testing-library",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "e2e testing D5 projects",
|
|
5
|
+
"main": "dist/cjs/d5-testing-library.cjs",
|
|
6
|
+
"module": "dist/d5-testing-library.legacy-esm.js",
|
|
7
|
+
"types": "dist/d5-testing-library.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/d5-testing-library.d.ts",
|
|
12
|
+
"import": "./dist/d5-testing-library.mjs",
|
|
13
|
+
"default": "./dist/cjs/d5-testing-library.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"repository": "",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">18"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"clean": "rimraf dist",
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"changelog": "node ./scripts/releaseChangelog.mjs changelog -p v1.0.0",
|
|
24
|
+
"prepublishOnly": "yarn clean",
|
|
25
|
+
"prepack": "yarn build"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"author": "",
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"selenium-webdriver": "^4.17.0",
|
|
34
|
+
"typescript": "5.3.3"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@babel/core": "^7.23.9",
|
|
38
|
+
"@types/node": "^20.11.16",
|
|
39
|
+
"@types/selenium-webdriver": "^4.1.21",
|
|
40
|
+
"commander": "12.0.0",
|
|
41
|
+
"esbuild-extra": "^0.3.1",
|
|
42
|
+
"rimraf": "^5.0.5",
|
|
43
|
+
"tsup": "7.0.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"selenium-webdriver": "^4.17.0"
|
|
47
|
+
}
|
|
48
|
+
}
|