@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.
Files changed (47) hide show
  1. package/.editorconfig +20 -0
  2. package/.jsdoc.json +35 -0
  3. package/.prettierrc +11 -0
  4. package/README.md +116 -0
  5. package/doc/images/badges/modifier-abstract.png +0 -0
  6. package/doc/images/badges/modifier-abstract.svg +10 -0
  7. package/doc/images/badges/modifier-default.png +0 -0
  8. package/doc/images/badges/modifier-default.svg +10 -0
  9. package/doc/images/badges/modifier-private.png +0 -0
  10. package/doc/images/badges/modifier-private.svg +10 -0
  11. package/doc/images/badges/modifier-protected.png +0 -0
  12. package/doc/images/badges/modifier-protected.svg +10 -0
  13. package/doc/images/badges/modifier-public.png +0 -0
  14. package/doc/images/badges/modifier-public.svg +10 -0
  15. package/doc/images/badges/modifier-readonly.png +0 -0
  16. package/doc/images/badges/modifier-readonly.svg +10 -0
  17. package/doc/images/badges/modifier-static.png +0 -0
  18. package/doc/images/badges/modifier-static.svg +10 -0
  19. package/doc/src-page-objects_guerrillamail.page.md +69 -0
  20. package/doc/src-page-objects_maildrop.page.md +57 -0
  21. package/doc/src-page-objects_page.md +484 -0
  22. package/doc/src-page-objects_yopmail.page.md +57 -0
  23. package/doc/src-wdio_ado-reporter.md +93 -0
  24. package/doc/src-wdio_test-context-worker-service.md +48 -0
  25. package/doc/src_ado-client.md +55 -0
  26. package/doc/src_logger.md +183 -0
  27. package/doc/src_mail-service.md +54 -0
  28. package/doc/src_pdf-generator.md +35 -0
  29. package/doc/src_test-context.md +173 -0
  30. package/doc/toc.md +22 -0
  31. package/eslint.config.js +100 -0
  32. package/jsconfig.json +14 -0
  33. package/package.json +58 -0
  34. package/src/ado-client.js +96 -0
  35. package/src/index.js +8 -0
  36. package/src/logger.js +125 -0
  37. package/src/mail-service.js +81 -0
  38. package/src/page-objects/guerrillamail.page.js +144 -0
  39. package/src/page-objects/index.js +3 -0
  40. package/src/page-objects/maildrop.page.js +97 -0
  41. package/src/page-objects/page.js +463 -0
  42. package/src/page-objects/yopmail.page.js +102 -0
  43. package/src/pdf-generator.js +61 -0
  44. package/src/test-context.js +248 -0
  45. package/src/types.d.ts +60 -0
  46. package/src/wdio/ado-reporter.js +111 -0
  47. 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 };