@cuppet/core 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.
@@ -0,0 +1,290 @@
1
+ /**
2
+ * @module dataStorage
3
+ * @typedef {import('puppeteer').Page} Page
4
+ */
5
+ const config = require('config');
6
+ const fs = require('fs');
7
+ const helper = require('./helperFunctions');
8
+ const moment = require('moment');
9
+ const jsonFilePath = config.get('jsonFilePath').toString();
10
+
11
+ module.exports = {
12
+ /**
13
+ * Create the JSON file in which test data will be stored
14
+ * @returns {Promise<void>}
15
+ */
16
+ createFile: async function () {
17
+ if (jsonFilePath && !fs.existsSync(jsonFilePath)) {
18
+ fs.writeFile(jsonFilePath, '', { flag: 'w+' }, (err) => {
19
+ if (err) {
20
+ console.error('File is not created, please check if the folder exists!');
21
+ } else {
22
+ console.log('File Created');
23
+ }
24
+ });
25
+ }
26
+ },
27
+
28
+ /**
29
+ * Clear the JSON file
30
+ * @returns {void}
31
+ */
32
+ clearJsonFile: function () {
33
+ if (jsonFilePath) {
34
+ fs.truncate(jsonFilePath, 0, () => {
35
+ console.log('JSON File Cleared successfully!');
36
+ });
37
+ }
38
+ },
39
+
40
+ /**
41
+ * Generate pa11y,lighthouse etc. html reports
42
+ * @param fileName - string with the name of the file
43
+ * @param data - HtmlReporter formatted result
44
+ * @returns {Promise<void>}
45
+ */
46
+ createHtmlReport: async function (fileName, data) {
47
+ const profile = process.env.NODE_CONFIG_ENV;
48
+ fs.writeFile(`reports/${profile}/${fileName}.html`, data, (err) => {
49
+ if (err) throw err;
50
+ console.log(`Html report: ${fileName}.html is generated!`);
51
+ });
52
+ },
53
+
54
+ /**
55
+ * Load the JSON file
56
+ * @param file
57
+ * @returns {any|{}}
58
+ */
59
+ getJsonFile: function (file = '') {
60
+ file = file || jsonFilePath;
61
+ const result = fs.readFileSync(file, 'utf-8');
62
+ return result ? JSON.parse(result) : {};
63
+ },
64
+
65
+ /**
66
+ * Save variable to JSON file. Example: {
67
+ * "varName":"Value"
68
+ * }
69
+ * @param data - the value of the variable
70
+ * @param variable - the variable name
71
+ * @returns {Promise<void>}
72
+ */
73
+ iStoreVariableWithValueToTheJsonFile: async function (data, variable) {
74
+ const tempJson = this.getJsonFile();
75
+ tempJson[variable] = data;
76
+ fs.writeFileSync(jsonFilePath, JSON.stringify(tempJson), { flag: 'w+' });
77
+ },
78
+
79
+ /**
80
+ * Get specific variable and throw error if missing
81
+ * @param variable
82
+ * @param {boolean} stringify - flag to be used when getting values which are object themselves
83
+ * @returns {*}
84
+ */
85
+ getVariable: function (variable, stringify = false) {
86
+ const tempJson = this.getJsonFile();
87
+ if (!tempJson[variable]) {
88
+ throw new Error(`Variable with name ${variable} not found in the json file!`);
89
+ }
90
+ if (stringify) {
91
+ return JSON.stringify(tempJson[variable]);
92
+ }
93
+ return tempJson[variable];
94
+ },
95
+
96
+ /**
97
+ * Check for variable existence or return the inputted value.
98
+ * To be used in steps which can work both with JSON vars and direct user input
99
+ * @param variable
100
+ * @returns {*}
101
+ */
102
+ checkForVariable: function (variable) {
103
+ const tempJson = this.getJsonFile();
104
+ return tempJson[variable] ?? variable;
105
+ },
106
+
107
+ /**
108
+ * Replace single occurrence of %% pattern in a string with a stored variable.
109
+ * Example - I go to "/node/%myStoredPage%" -> "/node/test-page-alias"
110
+ * @param data
111
+ * @returns {Promise<*>}
112
+ */
113
+ checkForSavedVariable: async function (data) {
114
+ return data.replace(/%([a-zA-Z_-]+)%/g, (match, p1) => {
115
+ return this.checkForVariable(p1);
116
+ });
117
+ },
118
+
119
+ /**
120
+ * Similar to checkForSavedVariable but it extracts multiple variable names from the following pattern:
121
+ * Example - "Here are %var1% and %var2%" and replace
122
+ * them with their values - "Here are valueOfVar1 and valueOfVar2"
123
+ * @param text
124
+ * @returns {Promise<*>}
125
+ */
126
+ checkForMultipleVariables: async function (text) {
127
+ const regex = /%([^%]+)%/g;
128
+ const allVariables = this.getJsonFile();
129
+ // The convention dictates if function argument is not used, it can be replaced by "_".
130
+ const result = text.replace(regex, (_, group) => {
131
+ return allVariables[group];
132
+ });
133
+ return result || text;
134
+ },
135
+
136
+ /**
137
+ * Re-save the JSON file with all it's values in lowercase.
138
+ * @returns {Promise<void>}
139
+ */
140
+ lowercaseAllVariables: async function () {
141
+ const allVariables = this.getJsonFile();
142
+ const lowercaseJson = Object.fromEntries(
143
+ Object.entries(allVariables).map(([key, value]) => [
144
+ key,
145
+ typeof value === 'string' ? value.toLowerCase() : value,
146
+ ])
147
+ );
148
+ fs.writeFileSync(jsonFilePath, JSON.stringify(lowercaseJson), { flag: 'w+' });
149
+ },
150
+
151
+ /**
152
+ * Cut the value of a variable on special char occurrence. The regex can be changed via the config json.
153
+ * Example - valueOf@Variable -> valueOf.
154
+ * @param variable
155
+ * @returns {Promise<void>}
156
+ */
157
+ trimVariableOnFirstSpecialChar: async function (variable) {
158
+ let regex = /[?&@$#:,;]/;
159
+ if (config.has('trimRegex')) {
160
+ const configRegex = config.get('trimRegex');
161
+ regex = new RegExp(configRegex.toString());
162
+ }
163
+ const value = this.getVariable(variable);
164
+ let splitArr = value.split(regex);
165
+ const result = splitArr[0].trim();
166
+ await this.iStoreVariableWithValueToTheJsonFile(result, variable);
167
+ },
168
+
169
+ /**
170
+ * Save current page url in both relative and absolute url variants. Predefined json
171
+ * property names are used for easier usage.
172
+ * @param {Page} page - current tab in puppeteer
173
+ * @returns {Promise<void>}
174
+ */
175
+ saveCurrentPath: async function (page) {
176
+ // Get the current URL
177
+ const url = new URL(page.url());
178
+ const absolutePath = url.href;
179
+ // Get the relative path
180
+ const relativePath = url.pathname;
181
+ // Store paths
182
+ await this.iStoreVariableWithValueToTheJsonFile(absolutePath, 'path');
183
+ await this.iStoreVariableWithValueToTheJsonFile(relativePath, 'relativePath');
184
+ },
185
+
186
+ /**
187
+ * Store ID (in case of Drupal) or the sequence of numbers in url path alias.
188
+ * Example /node/123/edit -> 123 will be extracted and saved
189
+ * @param {Page} page
190
+ * @param variable
191
+ * @returns {Promise<void>}
192
+ */
193
+ iStoreEntityId: async function (page, variable) {
194
+ const currentUrl = new URL(page.url());
195
+ const alias = currentUrl.pathname;
196
+ const matches = /[1-9]\d*/.exec(alias);
197
+ if (!matches) {
198
+ throw new Error(`The url path doesn't contain an ID:${alias}`);
199
+ }
200
+ await this.iStoreVariableWithValueToTheJsonFile(matches[0], variable);
201
+ },
202
+
203
+ /**
204
+ * Saves the href from a link <a>.
205
+ * TO DO: Can be done with more generic method to save specific attribute of element, instead of the hardcoded href.
206
+ * @param {Page} page
207
+ * @param selector
208
+ * @param variable
209
+ * @returns {Promise<void>}
210
+ */
211
+ storeHrefOfElement: async function (page, selector, variable) {
212
+ await page.waitForSelector(selector);
213
+ let href = await page.$eval(selector, (el) => el.getAttribute('href'));
214
+ href = encodeURI(href);
215
+ await this.iStoreVariableWithValueToTheJsonFile(href, variable);
216
+ },
217
+
218
+ /**
219
+ * Save the text from a page element matching specific pattern.
220
+ * Example: "This is your code for password reset: 123456"
221
+ * You can create a regex to find the 123456 number and extract it from that text.
222
+ * @param {Page} page - current puppeteer tab
223
+ * @param pattern - regex
224
+ * @param text - text in which this pattern needs to be searched for
225
+ * @returns {Promise<void>}
226
+ */
227
+ storeTextFromPattern: async function (page, pattern, text) {
228
+ const element = await page.$('xpath/' + `//body//*[text()[contains(.,'${text}')]]`);
229
+ let textValue = await (await page.evaluateHandle((el) => el.textContent, element)).jsonValue();
230
+ const regex = new RegExp(pattern);
231
+ const matches = regex.exec(textValue);
232
+ if (!matches) {
233
+ throw new Error(`There isn't a string matching the pattern:${regex}`);
234
+ }
235
+ await this.iStoreVariableWithValueToTheJsonFile(matches[0], 'storedString');
236
+ },
237
+
238
+ /**
239
+ * Store the value of the element (input, button, option, li etc.)
240
+ * @param {Page} page
241
+ * @param cssSelector
242
+ * @param variable
243
+ * @returns {Promise<void>}
244
+ */
245
+ storeValueOfElement: async function (page, cssSelector, variable) {
246
+ await page.waitForSelector(cssSelector);
247
+ const value = await page.$eval(cssSelector, (el) => el.value);
248
+ if (!value) {
249
+ throw new Error(`Element with selector ${cssSelector} doesn't have value!`);
250
+ }
251
+ await this.iStoreVariableWithValueToTheJsonFile(value, variable);
252
+ },
253
+
254
+ /**
255
+ * Generate mail extension with specific length.
256
+ * Example test@example.com -> test+zy62a@example.com
257
+ * @param number
258
+ * @param emailVariable
259
+ * @param varName
260
+ * @returns {Promise<void>}
261
+ */
262
+ generateExtensionAndStoreVar: async function (number, emailVariable, varName) {
263
+ let email = emailVariable;
264
+ if (config.has(emailVariable)) {
265
+ email = config.get(emailVariable);
266
+ }
267
+ let splitVar = email.split('@');
268
+ if (splitVar.length === 0) {
269
+ throw new Error(`The provided string: ${email} is not an email!`);
270
+ }
271
+ let randomStr = helper.generateRandomString(number);
272
+ const value = splitVar[0] + '+' + randomStr + '@' + splitVar[1];
273
+ await this.iStoreVariableWithValueToTheJsonFile(value, varName);
274
+ },
275
+
276
+ /**
277
+ *
278
+ * @param format
279
+ * @param variable
280
+ * @param days
281
+ * @returns {Promise<void>}
282
+ */
283
+ generateAndSaveDateWithCustomFormat: async function (format, variable, days = 0) {
284
+ let date = moment()
285
+ .add(days >= 0 ? days : -days, 'days')
286
+ .format(format);
287
+
288
+ await this.iStoreVariableWithValueToTheJsonFile(date, variable);
289
+ },
290
+ };