@actionlogementservices/wdio-test-context 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/.editorconfig +20 -0
- package/.jsdoc.json +35 -0
- package/.prettierrc +11 -0
- package/README.md +116 -0
- package/doc/images/badges/modifier-abstract.png +0 -0
- package/doc/images/badges/modifier-abstract.svg +10 -0
- package/doc/images/badges/modifier-default.png +0 -0
- package/doc/images/badges/modifier-default.svg +10 -0
- package/doc/images/badges/modifier-private.png +0 -0
- package/doc/images/badges/modifier-private.svg +10 -0
- package/doc/images/badges/modifier-protected.png +0 -0
- package/doc/images/badges/modifier-protected.svg +10 -0
- package/doc/images/badges/modifier-public.png +0 -0
- package/doc/images/badges/modifier-public.svg +10 -0
- package/doc/images/badges/modifier-readonly.png +0 -0
- package/doc/images/badges/modifier-readonly.svg +10 -0
- package/doc/images/badges/modifier-static.png +0 -0
- package/doc/images/badges/modifier-static.svg +10 -0
- package/doc/src-page-objects_guerrillamail.page.md +69 -0
- package/doc/src-page-objects_maildrop.page.md +57 -0
- package/doc/src-page-objects_page.md +484 -0
- package/doc/src-page-objects_yopmail.page.md +57 -0
- package/doc/src-wdio_ado-reporter.md +93 -0
- package/doc/src-wdio_test-context-worker-service.md +48 -0
- package/doc/src_ado-client.md +55 -0
- package/doc/src_logger.md +183 -0
- package/doc/src_mail-service.md +54 -0
- package/doc/src_pdf-generator.md +35 -0
- package/doc/src_test-context.md +173 -0
- package/doc/toc.md +22 -0
- package/eslint.config.js +100 -0
- package/jsconfig.json +14 -0
- package/package.json +58 -0
- package/src/ado-client.js +96 -0
- package/src/index.js +8 -0
- package/src/logger.js +125 -0
- package/src/mail-service.js +81 -0
- package/src/page-objects/guerrillamail.page.js +144 -0
- package/src/page-objects/index.js +3 -0
- package/src/page-objects/maildrop.page.js +97 -0
- package/src/page-objects/page.js +463 -0
- package/src/page-objects/yopmail.page.js +102 -0
- package/src/pdf-generator.js +61 -0
- package/src/test-context.js +248 -0
- package/src/types.d.ts +60 -0
- package/src/wdio/ado-reporter.js +111 -0
- package/src/wdio/test-context-worker-service.js +88 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base page object for WDIO page objects.
|
|
3
|
+
* @module
|
|
4
|
+
* @category public
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* global browser,$,$$ */
|
|
8
|
+
|
|
9
|
+
import { logger } from '../logger.js';
|
|
10
|
+
|
|
11
|
+
export const TIMEOUT = process.env.DEBUG ? 60 * 60 * 1000 : 20_000;
|
|
12
|
+
export const EXTRA_LARGE_TIMEOUT = 120_000;
|
|
13
|
+
|
|
14
|
+
const tabs = new Map();
|
|
15
|
+
|
|
16
|
+
export default class Page {
|
|
17
|
+
/**
|
|
18
|
+
* **Sets the browser url** for the specified **tab name**.
|
|
19
|
+
* @param {string} tabName tab name
|
|
20
|
+
* @param {string} url url to navigate to
|
|
21
|
+
* @param {boolean} [maximize] maximize window
|
|
22
|
+
* @returns {Promise<void>}
|
|
23
|
+
*/
|
|
24
|
+
async setUrl(tabName, url, maximize = true) {
|
|
25
|
+
await browser.url(url);
|
|
26
|
+
if (maximize) await browser.maximizeWindow();
|
|
27
|
+
const handle = await browser.getWindowHandle();
|
|
28
|
+
tabs.set(tabName, handle);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* **Opens** the specified **tab name** with the specified **url**.
|
|
33
|
+
* @param {string} tabName nom de l'onglet du navigateur
|
|
34
|
+
* @param {string} url url à atteindre
|
|
35
|
+
* @returns {Promise<void>}
|
|
36
|
+
*/
|
|
37
|
+
async openNewTab(tabName, url) {
|
|
38
|
+
if (tabs.has(tabName)) {
|
|
39
|
+
const handle = tabs.get(tabName);
|
|
40
|
+
await browser.switchToWindow(handle);
|
|
41
|
+
await browser.url(url);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
await browser.newWindow(url);
|
|
45
|
+
await browser.maximizeWindow();
|
|
46
|
+
const handle = await browser.getWindowHandle();
|
|
47
|
+
tabs.set(tabName, handle);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* **Switches to** the specified **tab name**.
|
|
52
|
+
* @param {string} tabName nom de l'onglet du navigateur
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
async switchToTab(tabName) {
|
|
56
|
+
const handle = tabs.get(tabName);
|
|
57
|
+
await browser.switchToWindow(handle);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* **Switches to** the **last opened tab**.
|
|
62
|
+
* @returns {Promise<void>}
|
|
63
|
+
*/
|
|
64
|
+
async switchToLastOpenedTab() {
|
|
65
|
+
const handles = await browser.getWindowHandles();
|
|
66
|
+
return browser.switchToWindow(handles.at(-1));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Dumps tabs information.
|
|
71
|
+
*/
|
|
72
|
+
async debugTabs() {
|
|
73
|
+
for (const tab of tabs) {
|
|
74
|
+
const [name, handle] = tab;
|
|
75
|
+
if (handle) {
|
|
76
|
+
await browser.switchToWindow(handle);
|
|
77
|
+
const url = await browser.getUrl();
|
|
78
|
+
logger.debug(`Tab ${name}: ${url}`);
|
|
79
|
+
} else {
|
|
80
|
+
logger.error(`Tab ${name} not set!`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Switches to the frame specified by the css selector.
|
|
87
|
+
* @param {string} [css] css selector of top level frame if not specified
|
|
88
|
+
* @returns {Promise<void | string>}
|
|
89
|
+
*/
|
|
90
|
+
async switchToFrame(css) {
|
|
91
|
+
if (!css) {
|
|
92
|
+
// eslint-disable-next-line unicorn/no-null
|
|
93
|
+
return browser.switchFrame(null);
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
return browser.switchFrame($(css));
|
|
97
|
+
} catch (error) {
|
|
98
|
+
logger.detailError(error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* **Retrieves the text** corresponding to the specified css selector.
|
|
104
|
+
* Waits during the specified (or default) timeout **before throwing error**.
|
|
105
|
+
* @param {string} css css selector
|
|
106
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
107
|
+
* @returns {Promise<string>} the corresponding text
|
|
108
|
+
*/
|
|
109
|
+
async getText(css, timeout = TIMEOUT) {
|
|
110
|
+
await browser.waitUntil($(css).isDisplayed, { timeout });
|
|
111
|
+
return $(css).getText();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* **Retrieves the value** corresponding to the specified css selector.
|
|
116
|
+
* Waits during the specified (or default) timeout **before throwing error**.
|
|
117
|
+
* @param {string} css css selector
|
|
118
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
119
|
+
* @returns {Promise<string>} the corresponding value
|
|
120
|
+
*/
|
|
121
|
+
async getValue(css, timeout = TIMEOUT) {
|
|
122
|
+
await browser.waitUntil($(css).isDisplayed, { timeout });
|
|
123
|
+
return $(css).getValue();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* **Retrieves the inner html** corresponding to the specified css selector.
|
|
128
|
+
* Waits during the specified (or default) timeout **before throwing error**.
|
|
129
|
+
* @param {string} css css selector
|
|
130
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
131
|
+
* @returns {Promise<string>} the corresponding inner html
|
|
132
|
+
*/
|
|
133
|
+
async getHtml(css, timeout = TIMEOUT) {
|
|
134
|
+
await browser.waitUntil($(css).isDisplayed, { timeout });
|
|
135
|
+
return $(css).getHTML({ includeSelectorTag: false });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* **Retrieves the list of values** of the specified **select** css selector.
|
|
140
|
+
* Waits during the specified (or default) timeout **before throwing error**.
|
|
141
|
+
* @param {string} css css selector of the select
|
|
142
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
143
|
+
* @returns {Promise<string[]>} the corresponding values
|
|
144
|
+
*/
|
|
145
|
+
async getOptions(css, timeout = TIMEOUT) {
|
|
146
|
+
await this.waitElementHasChildren(css, timeout);
|
|
147
|
+
const options = await $$(`${css} option`).getElements();
|
|
148
|
+
// le tableau des options
|
|
149
|
+
const items = [];
|
|
150
|
+
for (const o of options) {
|
|
151
|
+
const item = await o.getValue();
|
|
152
|
+
items.push(item);
|
|
153
|
+
}
|
|
154
|
+
return items;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* **Retrieves the selected text** of the specified **select** css selector.
|
|
159
|
+
* Waits during the specified (or default) timeout **before throwing error**.
|
|
160
|
+
* @param {string} css css selector of the select
|
|
161
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
162
|
+
* @returns {Promise<string>} the corresponding text
|
|
163
|
+
*/
|
|
164
|
+
async getSelectedText(css, timeout = TIMEOUT) {
|
|
165
|
+
await this.waitElementHasChildren(css, timeout);
|
|
166
|
+
return $(`${css} option:checked`).getText();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* **Retrieves the selected value** of the specified **select** css selector.
|
|
171
|
+
* Waits during the specified (or default) timeout **before throwing error**.
|
|
172
|
+
* @param {string} css css selector of the select
|
|
173
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
174
|
+
* @returns {Promise<string>} the corresponding text
|
|
175
|
+
*/
|
|
176
|
+
async getSelectedValue(css, timeout = TIMEOUT) {
|
|
177
|
+
await this.waitElementHasChildren(css, timeout);
|
|
178
|
+
return $(`${css} option:checked`).getValue();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* **Verifies if the element** specified by the css selector **exists**.
|
|
183
|
+
* Will only verify for the **specified amount of seconds**.
|
|
184
|
+
* **Does not throw error**.
|
|
185
|
+
* @param {string} css css selector
|
|
186
|
+
* @param {Number} periodInSecond period of time to wait (in s)
|
|
187
|
+
* @returns {Promise<boolean>} true if element exists, false otherwise
|
|
188
|
+
*/
|
|
189
|
+
async verifyElementExistsDuring(css, periodInSecond) {
|
|
190
|
+
const totalTime = Math.trunc(periodInSecond);
|
|
191
|
+
let elementExists = false;
|
|
192
|
+
let elapsedTime = 0;
|
|
193
|
+
while (!elementExists || elapsedTime <= totalTime) {
|
|
194
|
+
elementExists = await $(css).isExisting();
|
|
195
|
+
if (elementExists || elapsedTime === totalTime) break;
|
|
196
|
+
await browser.pause(1000);
|
|
197
|
+
elapsedTime++;
|
|
198
|
+
}
|
|
199
|
+
return elementExists;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* **Verifies if the element** specified by the css selector **exists**.
|
|
204
|
+
* **Does not throw error**.
|
|
205
|
+
* @param {string} css css selector
|
|
206
|
+
* @returns {Promise<boolean>} true if element exists, false otherwise
|
|
207
|
+
*/
|
|
208
|
+
async verifyElementExists(css) {
|
|
209
|
+
return $(css).isExisting();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* **Waits until the element** specified by the css selector **exists**.
|
|
214
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
215
|
+
* @param {string} css css selector
|
|
216
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
217
|
+
* @returns {ChainablePromiseElement} the element if it exists
|
|
218
|
+
*/
|
|
219
|
+
async waitElementExists(css, timeout = TIMEOUT) {
|
|
220
|
+
await $(css).waitForExist();
|
|
221
|
+
await browser.waitUntil(async () => await $(css).isExisting(), { timeout });
|
|
222
|
+
return $(css);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* **Waits until the element** specified by the css selector **has no more** the specified **text**.
|
|
227
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
228
|
+
* @param {string} css css selector
|
|
229
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
230
|
+
* @param {string} oldText text that is supposed to disapear
|
|
231
|
+
* @returns {Promise<string>} the new text if it exists
|
|
232
|
+
*/
|
|
233
|
+
async waitTextChanged(css, oldText, timeout = TIMEOUT) {
|
|
234
|
+
await browser.waitUntil(
|
|
235
|
+
async () => {
|
|
236
|
+
const existingText = await $(css).getText();
|
|
237
|
+
return !existingText.includes(oldText);
|
|
238
|
+
},
|
|
239
|
+
{ timeout }
|
|
240
|
+
);
|
|
241
|
+
return $(css).getText();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* **Waits until the element** specified by the css selector **has** the specified **text**.
|
|
246
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
247
|
+
* @param {string} css css selector
|
|
248
|
+
* @param {string} text text to wait for
|
|
249
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
250
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
251
|
+
*/
|
|
252
|
+
async waitElementHasText(css, text, timeout = TIMEOUT) {
|
|
253
|
+
return browser.waitUntil(
|
|
254
|
+
async () => {
|
|
255
|
+
const existingText = await $(css).getText();
|
|
256
|
+
return existingText.includes(text);
|
|
257
|
+
},
|
|
258
|
+
{ timeout }
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* **Waits until the element** specified by the css selector **has the specified value**.
|
|
264
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
265
|
+
* @param {string} css css selector
|
|
266
|
+
* @param {string | number | boolean} value value to wait for
|
|
267
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
268
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
269
|
+
*/
|
|
270
|
+
async waitElementHasValue(css, value, timeout = TIMEOUT) {
|
|
271
|
+
// eslint-disable-next-line eqeqeq
|
|
272
|
+
return await browser.waitUntil(async () => (await $(css).getValue()) == value, { timeout });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* **Waits until the element** specified by the css selector is **removed from the DOM**.
|
|
277
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
278
|
+
* @param {string} css css selector
|
|
279
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
280
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
281
|
+
*/
|
|
282
|
+
async waitElementRemoved(css, timeout = TIMEOUT) {
|
|
283
|
+
return browser.waitUntil(async () => !(await $(css).isExisting()), { timeout });
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* **Waits until the element** specified by the css selector is **clickable**.
|
|
288
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
289
|
+
* @param {string} css css selector
|
|
290
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
291
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
292
|
+
*/
|
|
293
|
+
async waitElementClickable(css, timeout = TIMEOUT) {
|
|
294
|
+
return browser.waitUntil(() => $(css).isClickable(), { timeout });
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* **Waits until the element** specified by the css selector is **displayed**.
|
|
299
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
300
|
+
* @param {string} css css selector
|
|
301
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
302
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
303
|
+
*/
|
|
304
|
+
async waitElementDisplayed(css, timeout = TIMEOUT) {
|
|
305
|
+
return browser.waitUntil(() => $(css).isDisplayed(), { timeout });
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* **Waits until the element** specified by the css selector is **hidden**.
|
|
310
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
311
|
+
* @param {string} css css selector
|
|
312
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
313
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
314
|
+
*/
|
|
315
|
+
async waitElementHidden(css, timeout = TIMEOUT) {
|
|
316
|
+
return browser.waitUntil(async () => !(await $(css).isDisplayed()), { timeout });
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* **Waits until the element** specified by the css selector **has children**.
|
|
321
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
322
|
+
* @param {string} css css selector
|
|
323
|
+
* @param {number} [childrenCount] optional count of children to wait for (default 1)
|
|
324
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
325
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
326
|
+
*/
|
|
327
|
+
async waitElementHasChildren(css, childrenCount = 1, timeout = TIMEOUT) {
|
|
328
|
+
return browser.waitUntil(async () => (await $$(css).length) >= childrenCount, { timeout });
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* **Waits until the browser url ends with** the specified **text**.
|
|
333
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
334
|
+
* @param {string} text ending text
|
|
335
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
336
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
337
|
+
*/
|
|
338
|
+
async waitUrlEndsWith(text, timeout = TIMEOUT) {
|
|
339
|
+
return browser.waitUntil(
|
|
340
|
+
async () => {
|
|
341
|
+
const existingUrl = await browser.getUrl();
|
|
342
|
+
return existingUrl.endsWith(text);
|
|
343
|
+
},
|
|
344
|
+
{ timeout }
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* **Waits until the browser url contains** the specified **text**.
|
|
350
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
351
|
+
* @param {string} text ending text
|
|
352
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
353
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
354
|
+
*/
|
|
355
|
+
async waitUrlContains(text, timeout = TIMEOUT) {
|
|
356
|
+
return browser.waitUntil(
|
|
357
|
+
async () => {
|
|
358
|
+
const existingUrl = await browser.getUrl();
|
|
359
|
+
return existingUrl.includes(text);
|
|
360
|
+
},
|
|
361
|
+
{ timeout }
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* **Waits until the browser url is not more** the specified **text**.
|
|
367
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
368
|
+
* @param {string} text ending text
|
|
369
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
370
|
+
* @returns {Promise<boolean>} true if condition is fullfilled
|
|
371
|
+
*/
|
|
372
|
+
async waitUrlIsNoMore(text, timeout = TIMEOUT) {
|
|
373
|
+
return browser.waitUntil(async () => (await browser.getUrl()) !== text, { timeout });
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* **Clicks the element** specified by the css selector.
|
|
378
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
379
|
+
* @param {string} css css selector
|
|
380
|
+
* @param {string} [cssParent] optional css selector of the parent
|
|
381
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
382
|
+
* @returns {Promise<void>}
|
|
383
|
+
*/
|
|
384
|
+
async click(css, cssParent, timeout = TIMEOUT) {
|
|
385
|
+
const element = cssParent ? $(cssParent).$(css) : $(css);
|
|
386
|
+
await browser.waitUntil(() => element.isClickable(), { timeout });
|
|
387
|
+
return element.click();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* **Checks the checkbox or radio button** specified by the css selector.
|
|
392
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
393
|
+
* @param {string} css css selector of checkbox or radio button
|
|
394
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
395
|
+
* @returns {Promise<void>}
|
|
396
|
+
*/
|
|
397
|
+
async check(css, timeout = TIMEOUT) {
|
|
398
|
+
const element = $(css);
|
|
399
|
+
await browser.waitUntil(() => element.isClickable(), { timeout });
|
|
400
|
+
return element.click();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* **Checks the checkbox or radio button** specified by the label text and css selector.
|
|
405
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
406
|
+
* @param {string} text label text
|
|
407
|
+
* @param {string} css css selector of the label
|
|
408
|
+
* @param {string} [cssParent] optional css selector for the parent
|
|
409
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
410
|
+
* @returns {Promise<void>}
|
|
411
|
+
*/
|
|
412
|
+
async checkByText(text, css, cssParent, timeout = TIMEOUT) {
|
|
413
|
+
return this.click(`${css}=${text}`, cssParent, timeout);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* **Fills the input** specified by the css selector with the specified **text**.
|
|
418
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
419
|
+
* @param {string} css css selector of the input
|
|
420
|
+
* @param {string | number} text text to fill in
|
|
421
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
422
|
+
* @returns {Promise<void>}
|
|
423
|
+
*/
|
|
424
|
+
async fillInput(css, text, timeout = TIMEOUT) {
|
|
425
|
+
await browser.waitUntil(() => $(css).isEnabled(), { timeout });
|
|
426
|
+
await $(css).setValue(text);
|
|
427
|
+
return browser.keys('Tab');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* **Selects the option** specified by the **select** css selector with the specified **text**.
|
|
432
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
433
|
+
* @param {string} css css selector of the select
|
|
434
|
+
* @param {string} text text of the option
|
|
435
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
436
|
+
* @returns {Promise<void>}
|
|
437
|
+
*/
|
|
438
|
+
async selectItem(css, text, timeout = TIMEOUT) {
|
|
439
|
+
await browser.waitUntil(
|
|
440
|
+
async () => {
|
|
441
|
+
const nbOptions = await $$(`${css} option`).length;
|
|
442
|
+
return nbOptions > 1;
|
|
443
|
+
},
|
|
444
|
+
{ timeout }
|
|
445
|
+
);
|
|
446
|
+
await this.click(css);
|
|
447
|
+
await $(css).selectByVisibleText(text);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* **Selects the option** specified by the wdio element with the specified **text**.
|
|
452
|
+
* **Throws an error** after the specified (or default) timeout has expired.
|
|
453
|
+
* @param {WebdriverIO.Element} element select element
|
|
454
|
+
* @param {string} text text of the option
|
|
455
|
+
* @param {number} [timeout] optional timeout before throwing error
|
|
456
|
+
* @returns {Promise<void>}
|
|
457
|
+
*/
|
|
458
|
+
async selectObjectItem(element, text, timeout = TIMEOUT) {
|
|
459
|
+
await browser.waitUntil(() => element.isClickable(), { timeout });
|
|
460
|
+
await element.click();
|
|
461
|
+
return element.selectByVisibleText(text);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page-object on top of YOPmail.
|
|
3
|
+
* @module
|
|
4
|
+
* @category internal
|
|
5
|
+
*/
|
|
6
|
+
/* global browser,$,$$ */
|
|
7
|
+
|
|
8
|
+
import Page from './page.js';
|
|
9
|
+
import { logger } from '../logger.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Implements a page-object on top of YOPmail.
|
|
13
|
+
*/
|
|
14
|
+
class YopmailPage extends Page {
|
|
15
|
+
/** name of the provider */ name = 'YOPmail!';
|
|
16
|
+
|
|
17
|
+
/** domains exposed of the provider */ domains = ['yopmail.com'];
|
|
18
|
+
|
|
19
|
+
css = {
|
|
20
|
+
text: {
|
|
21
|
+
inbox: '#content div.mailbox table tbody'
|
|
22
|
+
},
|
|
23
|
+
button: {
|
|
24
|
+
refresh: '#refresh',
|
|
25
|
+
accepterpopup: 'button[aria-label=Autoriser]'
|
|
26
|
+
},
|
|
27
|
+
div: {
|
|
28
|
+
messages: 'div.m',
|
|
29
|
+
from: 'div.lmfd span.lmf',
|
|
30
|
+
subject: 'div.lms',
|
|
31
|
+
content: '#mail',
|
|
32
|
+
popup: 'div.fc-consent-root'
|
|
33
|
+
},
|
|
34
|
+
iframe: {
|
|
35
|
+
inbox: 'iframe[name=ifinbox]',
|
|
36
|
+
message: 'iframe[name=ifmail]'
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* WDIO logic to open the mailbox.
|
|
42
|
+
* @param {string} email disposable email
|
|
43
|
+
*/
|
|
44
|
+
async openInbox(email) {
|
|
45
|
+
await this.openNewTab('inbox', `https://yopmail.com?${email}`);
|
|
46
|
+
const popup = await this.verifyElementExistsDuring(this.css.div.popup, 2);
|
|
47
|
+
if (popup) {
|
|
48
|
+
await this.click(this.css.button.accepterpopup);
|
|
49
|
+
logger.debug('Yopmail popup detected');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* WDIO logic to get emails.
|
|
55
|
+
* @return {Promise<{ from: string, subject: string}[]>}
|
|
56
|
+
*/
|
|
57
|
+
async getMessages() {
|
|
58
|
+
let noMessage = true;
|
|
59
|
+
// on attent que l'iframe inbox soit présent
|
|
60
|
+
do {
|
|
61
|
+
// on attend 1,5s avant de cliquer sur refresh
|
|
62
|
+
await browser.pause(1500);
|
|
63
|
+
// on bascule sur la fenêtre principale car le bouton refresh est dedans
|
|
64
|
+
await this.switchToFrame();
|
|
65
|
+
await this.click(this.css.button.refresh);
|
|
66
|
+
await browser.pause(500);
|
|
67
|
+
// on retourne sur l'iframe inbox pour contrôler les messages
|
|
68
|
+
await this.switchToFrame(this.css.iframe.inbox);
|
|
69
|
+
// on regarde s'il y a au moins un message (= un div.m)
|
|
70
|
+
noMessage = !(await this.verifyElementExists(this.css.div.messages));
|
|
71
|
+
} while (noMessage);
|
|
72
|
+
// on récupère la liste de tous les messages
|
|
73
|
+
const messages = await $$(this.css.div.messages).getElements();
|
|
74
|
+
const froms = [];
|
|
75
|
+
for (const message of messages) {
|
|
76
|
+
const from = await message.$(this.css.div.from).getText();
|
|
77
|
+
const subject = await message.$(this.css.div.subject).getText();
|
|
78
|
+
froms.push({ from, subject });
|
|
79
|
+
}
|
|
80
|
+
return froms;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* WDIO logic to get the specified message content.
|
|
85
|
+
* @param {number} index
|
|
86
|
+
* @returns {Promise<string>}
|
|
87
|
+
*/
|
|
88
|
+
async getMessageContent(index) {
|
|
89
|
+
// on clique sur le message correspondant à l'index demandé
|
|
90
|
+
const messages = await $$(this.css.div.messages);
|
|
91
|
+
await messages[index].click();
|
|
92
|
+
// on bascule sur la fenêtre principale car l'iframe message est dedans
|
|
93
|
+
await this.switchToFrame();
|
|
94
|
+
// on bascule sur l'iframe message pour lire le contenu du message
|
|
95
|
+
await this.switchToFrame(this.css.iframe.message);
|
|
96
|
+
return this.getHtml(this.css.div.content);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const page = new YopmailPage();
|
|
101
|
+
|
|
102
|
+
export default page;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **Pdf file generator**.
|
|
3
|
+
* @module
|
|
4
|
+
* @category public
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
|
|
10
|
+
import { jsPDF } from 'jspdf';
|
|
11
|
+
import moment from 'moment';
|
|
12
|
+
|
|
13
|
+
import { logger } from './logger.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generates a pdf file with specified name and context data.
|
|
17
|
+
* @param {string} filename file name
|
|
18
|
+
* @param {import('./test-context.js').TestContext} context test context
|
|
19
|
+
* @returns {Promise<string>} the file path
|
|
20
|
+
*/
|
|
21
|
+
async function generatePdf(filename, context) {
|
|
22
|
+
const folder = path.join(process.cwd(), 'data', 'files');
|
|
23
|
+
await fs.mkdir(folder, { recursive: true });
|
|
24
|
+
const filepath = path.join(folder, `${filename}.pdf`);
|
|
25
|
+
logger.debug(`Generating '${filepath}'...`);
|
|
26
|
+
const timestamp = moment().format('[Le] DD/MM/YYYY [à] HH:mm:ss');
|
|
27
|
+
const {
|
|
28
|
+
user: { firstname, lastname, gender, email }
|
|
29
|
+
} = context;
|
|
30
|
+
const lines = [
|
|
31
|
+
filename.toUpperCase(),
|
|
32
|
+
timestamp,
|
|
33
|
+
`${gender} ${firstname} ${lastname}`,
|
|
34
|
+
`Adresse e-mail : ${email}`
|
|
35
|
+
];
|
|
36
|
+
try {
|
|
37
|
+
const pdf = new jsPDF();
|
|
38
|
+
pdf.setFontSize(12);
|
|
39
|
+
pdf.text(lines, 10, 10);
|
|
40
|
+
const fileContent = Buffer.from(pdf.output('arraybuffer'));
|
|
41
|
+
await fs.writeFile(filepath, fileContent, { encoding: 'utf8' });
|
|
42
|
+
return filepath;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
logger.detailError(error);
|
|
45
|
+
throw new Error(`Unable to create pdf file '${filepath}': ${error.message}!`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Deletes the specified file.
|
|
51
|
+
* @param {string} filepath pdf file path
|
|
52
|
+
*/
|
|
53
|
+
async function deletePdf(filepath) {
|
|
54
|
+
try {
|
|
55
|
+
await fs.rm(filepath);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
logger.detailError(error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default { deletePdf, generatePdf };
|