@cuppet/core 1.0.0 → 1.0.2
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 +144 -183
- package/features/app/appiumManager.js +58 -58
- package/features/app/browserManager.js +54 -54
- package/features/app/commonComponents/commonFields.js +18 -0
- package/features/app/commonComponents/commonPaths.js +17 -0
- package/features/app/hooks.js +95 -95
- package/features/app/multilingualStrings/multilingualStrings.js +20 -0
- package/features/app/stepDefinitions/accessibilitySteps.js +17 -17
- package/features/app/stepDefinitions/apiSteps.js +52 -52
- package/features/app/stepDefinitions/generalSteps.js +4 -2
- package/features/app/stepDefinitions/ifVisibleSteps.js +2 -1
- package/features/app/stepDefinitions/iframeSteps.js +10 -6
- package/features/app/stepDefinitions/lighthouseSteps.js +17 -17
- package/features/app/stepDefinitions/pageElements.js +31 -16
- package/features/app/stepDefinitions/visualRegressionSteps.js +26 -26
- package/features/app/world.js +12 -2
- package/features/tests/example.feature +17 -0
- package/index.js +43 -43
- package/package.json +72 -57
- package/src/accessibilityTesting.js +44 -44
- package/src/apiFunctions.js +290 -290
- package/src/appiumTesting.js +79 -79
- package/src/elementInteraction.js +29 -44
- package/src/helperFunctions.js +0 -17
- package/src/visualRegression.js +67 -67
- package/stepDefinitions.js +17 -17
package/src/appiumTesting.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module appiumTesting
|
|
3
|
-
*/
|
|
4
|
-
const config = require('config');
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
/**
|
|
8
|
-
* Handles UiSelector case as it requires special prefixing
|
|
9
|
-
* @param {string} selector
|
|
10
|
-
* @returns {string} - Either the original selector or a UiSelector formatted string
|
|
11
|
-
*/
|
|
12
|
-
prepareSelector: function (selector) {
|
|
13
|
-
if (selector.startsWith('.')) {
|
|
14
|
-
// If the selector starts with ., treat it as a UiSelector
|
|
15
|
-
// For example .text('Example Text') becomes android='new UiSelector().text("Example Text")'
|
|
16
|
-
return `android=new UiSelector()${selector}`;
|
|
17
|
-
} else {
|
|
18
|
-
return selector; // Otherwise, return the selector as is
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param {import('@wdio/globals').driver} driver - The WebDriverIO appium instance.
|
|
24
|
-
* @param {string} androidPackage - The name of the Android package.
|
|
25
|
-
* @param {string} activity - The name of the Android activity.
|
|
26
|
-
* @returns {Promise<void>} - Resolves when the session is reloaded successfully.
|
|
27
|
-
* @throws Will throw an error if the element is not found or not clickable.
|
|
28
|
-
*/
|
|
29
|
-
reloadSession: async function (driver, androidPackage, activity) {
|
|
30
|
-
const appiumCapabilities = config.get('appiumCapabilities');
|
|
31
|
-
const capabilities = {
|
|
32
|
-
...appiumCapabilities,
|
|
33
|
-
'appium:appPackage': androidPackage,
|
|
34
|
-
'appium:appActivity': activity,
|
|
35
|
-
};
|
|
36
|
-
// Reload the session with the updated capabilities
|
|
37
|
-
await driver.reloadSession(capabilities);
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {import('@wdio/globals')} driver - The WebDriverIO appium instance.
|
|
42
|
-
* @param {string} selector - The selector of the element to click.
|
|
43
|
-
* Possible values for selector: https://webdriver.io/docs/selectors/
|
|
44
|
-
* - A UiSelector string, e.g. '.text("Example Text")'
|
|
45
|
-
* - An ID selector (e.g. 'com.example:id/button1')
|
|
46
|
-
* - A class name selector (e.g. 'android.widget.Button')
|
|
47
|
-
* - An accessibility ID selector (e.g. '~button1')
|
|
48
|
-
* @returns {Promise<void>} - Resolves when the element is clicked successfully.
|
|
49
|
-
* @throws Will throw an error if the element is not found or not clickable.
|
|
50
|
-
*/
|
|
51
|
-
clickElement: async function (driver, selector) {
|
|
52
|
-
try {
|
|
53
|
-
// $ and $$ are not async functions, as Wdio uses lazy loading.
|
|
54
|
-
// The actual element is not fetched until an action is performed like .click(), .getText(), .isDisplayed(), etc.
|
|
55
|
-
const element = driver.$(selector);
|
|
56
|
-
await element.waitForDisplayed({ timeout: 5000 });
|
|
57
|
-
await element.click();
|
|
58
|
-
} catch (error) {
|
|
59
|
-
throw new Error(`Error clicking element with selector ${selector}: ${error}`);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @param {import('@wdio/globals').driver} driver - The WebDriverIO appium instance.
|
|
65
|
-
* @param {string} selector - The selector of the element.
|
|
66
|
-
* @returns {Promise<void>} - Resolves when the element is scrolled into view successfully.
|
|
67
|
-
* @throws Will throw an error if the element is not found.
|
|
68
|
-
*/
|
|
69
|
-
scrollToElement: async function (driver, selector) {
|
|
70
|
-
try {
|
|
71
|
-
await driver.findElement(
|
|
72
|
-
'-android uiautomator',
|
|
73
|
-
`new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().${selector})`
|
|
74
|
-
);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
throw new Error(`Cannot find element with selector ${selector}: ${error}`);
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* @module appiumTesting
|
|
3
|
+
*/
|
|
4
|
+
const config = require('config');
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
/**
|
|
8
|
+
* Handles UiSelector case as it requires special prefixing
|
|
9
|
+
* @param {string} selector
|
|
10
|
+
* @returns {string} - Either the original selector or a UiSelector formatted string
|
|
11
|
+
*/
|
|
12
|
+
prepareSelector: function (selector) {
|
|
13
|
+
if (selector.startsWith('.')) {
|
|
14
|
+
// If the selector starts with ., treat it as a UiSelector
|
|
15
|
+
// For example .text('Example Text') becomes android='new UiSelector().text("Example Text")'
|
|
16
|
+
return `android=new UiSelector()${selector}`;
|
|
17
|
+
} else {
|
|
18
|
+
return selector; // Otherwise, return the selector as is
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {import('@wdio/globals').driver} driver - The WebDriverIO appium instance.
|
|
24
|
+
* @param {string} androidPackage - The name of the Android package.
|
|
25
|
+
* @param {string} activity - The name of the Android activity.
|
|
26
|
+
* @returns {Promise<void>} - Resolves when the session is reloaded successfully.
|
|
27
|
+
* @throws Will throw an error if the element is not found or not clickable.
|
|
28
|
+
*/
|
|
29
|
+
reloadSession: async function (driver, androidPackage, activity) {
|
|
30
|
+
const appiumCapabilities = config.get('appiumCapabilities');
|
|
31
|
+
const capabilities = {
|
|
32
|
+
...appiumCapabilities,
|
|
33
|
+
'appium:appPackage': androidPackage,
|
|
34
|
+
'appium:appActivity': activity,
|
|
35
|
+
};
|
|
36
|
+
// Reload the session with the updated capabilities
|
|
37
|
+
await driver.reloadSession(capabilities);
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {import('@wdio/globals')} driver - The WebDriverIO appium instance.
|
|
42
|
+
* @param {string} selector - The selector of the element to click.
|
|
43
|
+
* Possible values for selector: https://webdriver.io/docs/selectors/
|
|
44
|
+
* - A UiSelector string, e.g. '.text("Example Text")'
|
|
45
|
+
* - An ID selector (e.g. 'com.example:id/button1')
|
|
46
|
+
* - A class name selector (e.g. 'android.widget.Button')
|
|
47
|
+
* - An accessibility ID selector (e.g. '~button1')
|
|
48
|
+
* @returns {Promise<void>} - Resolves when the element is clicked successfully.
|
|
49
|
+
* @throws Will throw an error if the element is not found or not clickable.
|
|
50
|
+
*/
|
|
51
|
+
clickElement: async function (driver, selector) {
|
|
52
|
+
try {
|
|
53
|
+
// $ and $$ are not async functions, as Wdio uses lazy loading.
|
|
54
|
+
// The actual element is not fetched until an action is performed like .click(), .getText(), .isDisplayed(), etc.
|
|
55
|
+
const element = driver.$(selector);
|
|
56
|
+
await element.waitForDisplayed({ timeout: 5000 });
|
|
57
|
+
await element.click();
|
|
58
|
+
} catch (error) {
|
|
59
|
+
throw new Error(`Error clicking element with selector ${selector}: ${error}`);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {import('@wdio/globals').driver} driver - The WebDriverIO appium instance.
|
|
65
|
+
* @param {string} selector - The selector of the element.
|
|
66
|
+
* @returns {Promise<void>} - Resolves when the element is scrolled into view successfully.
|
|
67
|
+
* @throws Will throw an error if the element is not found.
|
|
68
|
+
*/
|
|
69
|
+
scrollToElement: async function (driver, selector) {
|
|
70
|
+
try {
|
|
71
|
+
await driver.findElement(
|
|
72
|
+
'-android uiautomator',
|
|
73
|
+
`new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().${selector})`
|
|
74
|
+
);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new Error(`Cannot find element with selector ${selector}: ${error}`);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
@@ -169,15 +169,14 @@ module.exports = {
|
|
|
169
169
|
* Click on the text of a link and expect it to open in a new tab. target="_blank"
|
|
170
170
|
* @param {Browser} browser
|
|
171
171
|
* @param {Page} page
|
|
172
|
-
* @param value -
|
|
172
|
+
* @param value - text of link
|
|
173
173
|
* @param xpath - flag, whether to use xpath or not
|
|
174
174
|
* @returns {Promise<Object>}
|
|
175
175
|
*/
|
|
176
176
|
clickLinkOpenNewTab: async function (browser, page, value, xpath = true) {
|
|
177
177
|
let objectToClick;
|
|
178
178
|
if (xpath) {
|
|
179
|
-
|
|
180
|
-
objectToClick = await page.waitForSelector('xpath/' + `//body//*[text()[contains(.,'${result}')]]`);
|
|
179
|
+
objectToClick = await page.waitForSelector('xpath/' + `//body//*[text()[contains(.,'${value}')]]`);
|
|
181
180
|
} else {
|
|
182
181
|
objectToClick = await page.waitForSelector(value);
|
|
183
182
|
}
|
|
@@ -303,12 +302,11 @@ module.exports = {
|
|
|
303
302
|
* @returns {Promise<void>}
|
|
304
303
|
*/
|
|
305
304
|
validateValueOfElementAttributeByText: async function (page, text, attribute, value) {
|
|
306
|
-
const
|
|
307
|
-
const selector = 'xpath/' + `//body//*[text()[contains(.,'${result}')]]`;
|
|
305
|
+
const selector = 'xpath/' + `//body//*[text()[contains(.,'${text}')]]`;
|
|
308
306
|
await page.waitForSelector(selector);
|
|
309
307
|
const attrValue = await page.$eval(selector, (el, attribute) => el.getAttribute(attribute), attribute);
|
|
310
308
|
if (value !== attrValue) {
|
|
311
|
-
throw new Error(`The provided text "${
|
|
309
|
+
throw new Error(`The provided text "${text}" doesn't match element which attribute has value: ${value}.`);
|
|
312
310
|
}
|
|
313
311
|
},
|
|
314
312
|
|
|
@@ -359,7 +357,6 @@ module.exports = {
|
|
|
359
357
|
* @returns {Promise<void>}
|
|
360
358
|
*/
|
|
361
359
|
seeTextByXpath: async function (page, text, time = 6000) {
|
|
362
|
-
let result = await helper.getMultilingualString(text);
|
|
363
360
|
const options = {
|
|
364
361
|
visible: true, // Wait for the element to be visible (default: false)
|
|
365
362
|
timeout: time, // Maximum time to wait in milliseconds (default: 30000)
|
|
@@ -370,9 +367,9 @@ module.exports = {
|
|
|
370
367
|
});
|
|
371
368
|
}
|
|
372
369
|
try {
|
|
373
|
-
await page.waitForSelector('xpath/' + `//body//*[text()[contains(.,"${
|
|
370
|
+
await page.waitForSelector('xpath/' + `//body//*[text()[contains(.,"${text}")]]`, options);
|
|
374
371
|
} catch (error) {
|
|
375
|
-
throw new Error(`Could not find text : ${
|
|
372
|
+
throw new Error(`Could not find text : ${text}. The error thrown is: ${error}`);
|
|
376
373
|
}
|
|
377
374
|
},
|
|
378
375
|
|
|
@@ -385,14 +382,13 @@ module.exports = {
|
|
|
385
382
|
* @returns {Promise<void>}
|
|
386
383
|
*/
|
|
387
384
|
seeTextByElementHandle: async function (page, selector, text) {
|
|
388
|
-
const result = await helper.getMultilingualString(text);
|
|
389
385
|
await page.waitForSelector(selector);
|
|
390
386
|
let textContent = await page.$eval(selector, (element) => element.textContent.trim());
|
|
391
387
|
if (!textContent) {
|
|
392
388
|
textContent = await page.$eval(selector, (element) => element.value.trim());
|
|
393
389
|
}
|
|
394
|
-
if (textContent !==
|
|
395
|
-
throw new Error(`Expected ${
|
|
390
|
+
if (textContent !== text) {
|
|
391
|
+
throw new Error(`Expected ${text} text, but found ${textContent} instead.`);
|
|
396
392
|
}
|
|
397
393
|
},
|
|
398
394
|
|
|
@@ -406,13 +402,12 @@ module.exports = {
|
|
|
406
402
|
*/
|
|
407
403
|
seeTextInRegion: async function (page, text, region) {
|
|
408
404
|
const regionClass = await helper.getRegion(page, region);
|
|
409
|
-
const result = await helper.getMultilingualString(text);
|
|
410
405
|
try {
|
|
411
406
|
await page.waitForSelector(
|
|
412
|
-
'xpath/' + `//*[contains(@class,'${regionClass}') and .//text()[contains(.,"${
|
|
407
|
+
'xpath/' + `//*[contains(@class,'${regionClass}') and .//text()[contains(.,"${text}")]]`
|
|
413
408
|
);
|
|
414
409
|
} catch {
|
|
415
|
-
throw new Error(`Cannot find ${
|
|
410
|
+
throw new Error(`Cannot find ${text} in ${regionClass}!`);
|
|
416
411
|
}
|
|
417
412
|
},
|
|
418
413
|
|
|
@@ -425,8 +420,7 @@ module.exports = {
|
|
|
425
420
|
*/
|
|
426
421
|
hoverTextInRegion: async function (page, text, region) {
|
|
427
422
|
const regionClass = await helper.getRegion(page, region);
|
|
428
|
-
const
|
|
429
|
-
const selector = 'xpath/' + `//*[@class='${regionClass}']//*[text()='${result}']`;
|
|
423
|
+
const selector = 'xpath/' + `//*[@class='${regionClass}']//*[text()='${text}']`;
|
|
430
424
|
try {
|
|
431
425
|
const element = await page.waitForSelector(selector);
|
|
432
426
|
const parentElementHandle = await page.evaluateHandle((el) => el.parentElement, element);
|
|
@@ -443,8 +437,7 @@ module.exports = {
|
|
|
443
437
|
* @returns {Promise<void>}
|
|
444
438
|
*/
|
|
445
439
|
notSeeText: async function (page, text) {
|
|
446
|
-
|
|
447
|
-
const isTextInDom = await page.$('xpath/' + `//*[text()[contains(.,'${result}')]]`);
|
|
440
|
+
const isTextInDom = await page.$('xpath/' + `//*[text()[contains(.,'${text}')]]`);
|
|
448
441
|
// isVisible() is used for the cases where the text is in the DOM, but not visible
|
|
449
442
|
// If you need to NOT have it in the DOM - use notSeeElement() or extend this step with flag
|
|
450
443
|
const visibility = await isTextInDom?.isVisible();
|
|
@@ -461,7 +454,6 @@ module.exports = {
|
|
|
461
454
|
* @returns {Promise<void>}
|
|
462
455
|
*/
|
|
463
456
|
validateTextInField: async function (page, text, selector) {
|
|
464
|
-
let result = await helper.getMultilingualString(text);
|
|
465
457
|
let value = '';
|
|
466
458
|
await page.waitForSelector(selector);
|
|
467
459
|
try {
|
|
@@ -475,8 +467,8 @@ module.exports = {
|
|
|
475
467
|
} catch (error) {
|
|
476
468
|
throw new Error(error);
|
|
477
469
|
}
|
|
478
|
-
if (value !==
|
|
479
|
-
throw new Error(`Value of element ${value} does not match the text ${
|
|
470
|
+
if (value !== text) {
|
|
471
|
+
throw new Error(`Value of element ${value} does not match the text ${text}`);
|
|
480
472
|
}
|
|
481
473
|
},
|
|
482
474
|
|
|
@@ -489,7 +481,6 @@ module.exports = {
|
|
|
489
481
|
* @returns {Promise<void>}
|
|
490
482
|
*/
|
|
491
483
|
textVisibilityInAccordion: async function (page, cssSelector, text, isVisible) {
|
|
492
|
-
let result = await helper.getMultilingualString(text);
|
|
493
484
|
const el = await page.$(cssSelector);
|
|
494
485
|
if (el) {
|
|
495
486
|
const isShown = await (await page.evaluateHandle((el) => el.clientHeight, el)).jsonValue();
|
|
@@ -498,9 +489,9 @@ module.exports = {
|
|
|
498
489
|
}
|
|
499
490
|
if (isShown) {
|
|
500
491
|
const textValue = await (await page.evaluateHandle((el) => el.textContent.trim(), el)).jsonValue();
|
|
501
|
-
if (isVisible && textValue !==
|
|
502
|
-
throw new Error(`Element text: ${textValue} does not match the expected: ${
|
|
503
|
-
} else if (!isVisible && textValue ===
|
|
492
|
+
if (isVisible && textValue !== text) {
|
|
493
|
+
throw new Error(`Element text: ${textValue} does not match the expected: ${text}!`);
|
|
494
|
+
} else if (!isVisible && textValue === text) {
|
|
504
495
|
throw new Error(`Element text: ${textValue} is visible but it should not be!`);
|
|
505
496
|
}
|
|
506
497
|
}
|
|
@@ -518,14 +509,13 @@ module.exports = {
|
|
|
518
509
|
* @returns {Promise<void>}
|
|
519
510
|
*/
|
|
520
511
|
disappearText: async function (page, text, time) {
|
|
521
|
-
let result = await helper.getMultilingualString(text);
|
|
522
512
|
const options = {
|
|
523
513
|
visible: true, // Wait for the element to be visible (default: false)
|
|
524
514
|
timeout: 250, // 250ms and for that reason time is multiplied by 4 to add up to a full second.
|
|
525
515
|
};
|
|
526
516
|
for (let i = 0; i < time * 4; i++) {
|
|
527
517
|
try {
|
|
528
|
-
await page.waitForSelector('xpath/' + `//*[text()[contains(.,'${
|
|
518
|
+
await page.waitForSelector('xpath/' + `//*[text()[contains(.,'${text}')]]`, options);
|
|
529
519
|
} catch {
|
|
530
520
|
console.log(`Element disappeared in ${time * 4}.`);
|
|
531
521
|
break;
|
|
@@ -543,11 +533,10 @@ module.exports = {
|
|
|
543
533
|
*/
|
|
544
534
|
clickTextInRegion: async function (page, text, region) {
|
|
545
535
|
const regionClass = await helper.getRegion(page, region);
|
|
546
|
-
const result = await helper.getMultilingualString(text);
|
|
547
536
|
await page.waitForSelector('xpath/' + `//*[@class='${regionClass}']`);
|
|
548
537
|
const elements =
|
|
549
|
-
(await page.$$('xpath/' + `//*[@class='${regionClass}']//*[text()='${
|
|
550
|
-
(await page.$$('xpath/' + `//*[@class='${regionClass}']//*[contains(text(),'${
|
|
538
|
+
(await page.$$('xpath/' + `//*[@class='${regionClass}']//*[text()='${text}']`)) ||
|
|
539
|
+
(await page.$$('xpath/' + `//*[@class='${regionClass}']//*[contains(text(),'${text}')]`));
|
|
551
540
|
|
|
552
541
|
if (!elements?.[0]) {
|
|
553
542
|
throw new Error('Element not found!');
|
|
@@ -608,18 +597,17 @@ module.exports = {
|
|
|
608
597
|
* Put value in a field. It directly places the text like Ctrl+V(Paste) will do it.
|
|
609
598
|
* @param {Page} page
|
|
610
599
|
* @param selector
|
|
611
|
-
* @param
|
|
600
|
+
* @param text
|
|
612
601
|
* @param skip
|
|
613
602
|
* @returns {Promise<boolean>}
|
|
614
603
|
*/
|
|
615
|
-
fillField: async function (page, selector,
|
|
616
|
-
let result = await helper.getMultilingualString(data);
|
|
604
|
+
fillField: async function (page, selector, text, skip = false) {
|
|
617
605
|
const skipped = await this.customWaitForSkippableElement(page, selector, skip);
|
|
618
606
|
if (skipped) {
|
|
619
607
|
return true;
|
|
620
608
|
}
|
|
621
609
|
try {
|
|
622
|
-
await page.$eval(selector, (el, name) => (el.value = name),
|
|
610
|
+
await page.$eval(selector, (el, name) => (el.value = name), text);
|
|
623
611
|
await new Promise(function (resolve) {
|
|
624
612
|
setTimeout(resolve, 500);
|
|
625
613
|
});
|
|
@@ -637,7 +625,6 @@ module.exports = {
|
|
|
637
625
|
* @returns {Promise<boolean>}
|
|
638
626
|
*/
|
|
639
627
|
typeInField: async function (page, selector, text, skip = false) {
|
|
640
|
-
let result = await helper.getMultilingualString(text);
|
|
641
628
|
const skipped = await this.customWaitForSkippableElement(page, selector, skip);
|
|
642
629
|
if (skipped) {
|
|
643
630
|
return true;
|
|
@@ -650,7 +637,7 @@ module.exports = {
|
|
|
650
637
|
setTimeout(resolve, 150);
|
|
651
638
|
});
|
|
652
639
|
try {
|
|
653
|
-
await page.type(selector,
|
|
640
|
+
await page.type(selector, text, { delay: 250 });
|
|
654
641
|
} catch (error) {
|
|
655
642
|
throw new Error(`Cannot type into field due to ${error}`);
|
|
656
643
|
}
|
|
@@ -745,14 +732,13 @@ module.exports = {
|
|
|
745
732
|
* @returns {Promise<void>}
|
|
746
733
|
*/
|
|
747
734
|
selectOptionByText: async function (page, selector, text) {
|
|
748
|
-
let result = await helper.getMultilingualString(text);
|
|
749
735
|
await page.waitForSelector(selector);
|
|
750
|
-
const objectToSelect = await page.$('xpath/' + `//body//*[contains(text(), '${
|
|
736
|
+
const objectToSelect = await page.$('xpath/' + `//body//*[contains(text(), '${text}')]`);
|
|
751
737
|
if (objectToSelect) {
|
|
752
738
|
const value = await (await objectToSelect.getProperty('value')).jsonValue();
|
|
753
739
|
await page.select(selector, value);
|
|
754
740
|
} else {
|
|
755
|
-
throw new Error(`Could not find option with text: ${
|
|
741
|
+
throw new Error(`Could not find option with text: ${text}`);
|
|
756
742
|
}
|
|
757
743
|
},
|
|
758
744
|
|
|
@@ -894,18 +880,17 @@ module.exports = {
|
|
|
894
880
|
* Sets value into codemirror field
|
|
895
881
|
* @param {Page} page
|
|
896
882
|
* @param cssSelector
|
|
897
|
-
* @param
|
|
883
|
+
* @param text
|
|
898
884
|
* @returns {Promise<void>}
|
|
899
885
|
*/
|
|
900
|
-
setValueInCodeMirrorField: async function (page, cssSelector,
|
|
901
|
-
let result = await helper.getMultilingualString(value);
|
|
886
|
+
setValueInCodeMirrorField: async function (page, cssSelector, text) {
|
|
902
887
|
await page.waitForSelector(cssSelector);
|
|
903
888
|
try {
|
|
904
889
|
const jsCode = `
|
|
905
890
|
(function () {
|
|
906
891
|
const textArea = document.querySelector('${cssSelector}');
|
|
907
892
|
let editor = CodeMirror.fromTextArea(textArea);
|
|
908
|
-
editor.getDoc().setValue("${
|
|
893
|
+
editor.getDoc().setValue("${text}");
|
|
909
894
|
})();
|
|
910
895
|
`;
|
|
911
896
|
await page.evaluate(jsCode);
|
package/src/helperFunctions.js
CHANGED
|
@@ -43,23 +43,6 @@ module.exports = {
|
|
|
43
43
|
await page.waitForFunction(jsCode);
|
|
44
44
|
},
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* Returns the translated variant of the inputted text or the text itself if there isn't a translation.
|
|
48
|
-
* @param text
|
|
49
|
-
* @returns {Promise<string>}
|
|
50
|
-
*/
|
|
51
|
-
getMultilingualString: async function (text) {
|
|
52
|
-
const lang = config.has('language') ? config.get('language') : null;
|
|
53
|
-
let result;
|
|
54
|
-
if (lang) {
|
|
55
|
-
let string = strings.multilingualStrings(lang, text);
|
|
56
|
-
result = string ?? text;
|
|
57
|
-
} else {
|
|
58
|
-
result = text;
|
|
59
|
-
}
|
|
60
|
-
return result;
|
|
61
|
-
},
|
|
62
|
-
|
|
63
46
|
/**
|
|
64
47
|
* Retrieves the class name of an element based on a property in the config json.
|
|
65
48
|
* You can set directly the full class, partial or ID, but mind that it always resolves to
|
package/src/visualRegression.js
CHANGED
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
const config = require('config');
|
|
2
|
-
const backStop = require('backstopjs');
|
|
3
|
-
const backStopConfig = require('../backStopData/backStopConfig.json');
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
* @returns {Object} - the backstop configuration object
|
|
9
|
-
*/
|
|
10
|
-
backstopConfigPrepare: function () {
|
|
11
|
-
let newConfig = backStopConfig;
|
|
12
|
-
newConfig.id = process.env.NODE_CONFIG_ENV;
|
|
13
|
-
newConfig.viewports[0].width = Number(config.get('viewport.width'));
|
|
14
|
-
newConfig.viewports[0].height = Number(config.get('viewport.height'));
|
|
15
|
-
newConfig.engineOptions.args = config.get('args');
|
|
16
|
-
return newConfig;
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
* @param command
|
|
22
|
-
* @param configObject
|
|
23
|
-
* @returns {Promise<void>}
|
|
24
|
-
*/
|
|
25
|
-
runBackStop: async function (command, configObject) {
|
|
26
|
-
await backStop(command, { config: configObject })
|
|
27
|
-
.then(() => {
|
|
28
|
-
console.log(`${command} backstop run executed successfully!`);
|
|
29
|
-
// test successful
|
|
30
|
-
})
|
|
31
|
-
.catch((error) => {
|
|
32
|
-
throw new Error(error);
|
|
33
|
-
});
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
*
|
|
38
|
-
* @param scenarioName
|
|
39
|
-
* @param path
|
|
40
|
-
* @param testCommand
|
|
41
|
-
* @returns {Promise<void>}
|
|
42
|
-
*/
|
|
43
|
-
runBackStopSingleScenario: async function (scenarioName, path, testCommand) {
|
|
44
|
-
const newConfig = this.backstopConfigPrepare();
|
|
45
|
-
newConfig.scenarios[0].label = scenarioName;
|
|
46
|
-
newConfig.scenarios[0].url = path;
|
|
47
|
-
await this.runBackStop(testCommand, newConfig);
|
|
48
|
-
},
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* @param pages
|
|
52
|
-
* @param testCommand
|
|
53
|
-
* @returns {Promise<void>}
|
|
54
|
-
*/
|
|
55
|
-
runBackstopMultiplePages: async function (pages, testCommand) {
|
|
56
|
-
const newConfig = this.backstopConfigPrepare();
|
|
57
|
-
newConfig.scenarios = [];
|
|
58
|
-
pages.forEach((page) => {
|
|
59
|
-
newConfig.scenarios.push({
|
|
60
|
-
label: page.label,
|
|
61
|
-
url: page.url,
|
|
62
|
-
// Add other scenario properties as needed...
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
await this.runBackStop(testCommand, newConfig);
|
|
66
|
-
},
|
|
67
|
-
};
|
|
1
|
+
const config = require('config');
|
|
2
|
+
const backStop = require('backstopjs');
|
|
3
|
+
const backStopConfig = require('../backStopData/backStopConfig.json');
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @returns {Object} - the backstop configuration object
|
|
9
|
+
*/
|
|
10
|
+
backstopConfigPrepare: function () {
|
|
11
|
+
let newConfig = backStopConfig;
|
|
12
|
+
newConfig.id = process.env.NODE_CONFIG_ENV;
|
|
13
|
+
newConfig.viewports[0].width = Number(config.get('viewport.width'));
|
|
14
|
+
newConfig.viewports[0].height = Number(config.get('viewport.height'));
|
|
15
|
+
newConfig.engineOptions.args = config.get('args');
|
|
16
|
+
return newConfig;
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param command
|
|
22
|
+
* @param configObject
|
|
23
|
+
* @returns {Promise<void>}
|
|
24
|
+
*/
|
|
25
|
+
runBackStop: async function (command, configObject) {
|
|
26
|
+
await backStop(command, { config: configObject })
|
|
27
|
+
.then(() => {
|
|
28
|
+
console.log(`${command} backstop run executed successfully!`);
|
|
29
|
+
// test successful
|
|
30
|
+
})
|
|
31
|
+
.catch((error) => {
|
|
32
|
+
throw new Error(error);
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param scenarioName
|
|
39
|
+
* @param path
|
|
40
|
+
* @param testCommand
|
|
41
|
+
* @returns {Promise<void>}
|
|
42
|
+
*/
|
|
43
|
+
runBackStopSingleScenario: async function (scenarioName, path, testCommand) {
|
|
44
|
+
const newConfig = this.backstopConfigPrepare();
|
|
45
|
+
newConfig.scenarios[0].label = scenarioName;
|
|
46
|
+
newConfig.scenarios[0].url = path;
|
|
47
|
+
await this.runBackStop(testCommand, newConfig);
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @param pages
|
|
52
|
+
* @param testCommand
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
runBackstopMultiplePages: async function (pages, testCommand) {
|
|
56
|
+
const newConfig = this.backstopConfigPrepare();
|
|
57
|
+
newConfig.scenarios = [];
|
|
58
|
+
pages.forEach((page) => {
|
|
59
|
+
newConfig.scenarios.push({
|
|
60
|
+
label: page.label,
|
|
61
|
+
url: page.url,
|
|
62
|
+
// Add other scenario properties as needed...
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
await this.runBackStop(testCommand, newConfig);
|
|
66
|
+
},
|
|
67
|
+
};
|
package/stepDefinitions.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
// Cuppet Core Step Definitions
|
|
2
|
-
// This file exports all step definitions for use in consuming projects
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
accessibilitySteps: require('./features/app/stepDefinitions/accessibilitySteps'),
|
|
6
|
-
apiSteps: require('./features/app/stepDefinitions/apiSteps'),
|
|
7
|
-
appiumSteps: require('./features/app/stepDefinitions/appiumSteps'),
|
|
8
|
-
generalSteps: require('./features/app/stepDefinitions/generalSteps'),
|
|
9
|
-
helperSteps: require('./features/app/stepDefinitions/helperSteps'),
|
|
10
|
-
iframeSteps: require('./features/app/stepDefinitions/iframeSteps'),
|
|
11
|
-
ifVisibleSteps: require('./features/app/stepDefinitions/ifVisibleSteps'),
|
|
12
|
-
lighthouseSteps: require('./features/app/stepDefinitions/lighthouseSteps'),
|
|
13
|
-
pageElements: require('./features/app/stepDefinitions/pageElements'),
|
|
14
|
-
pageElementsConfig: require('./features/app/stepDefinitions/pageElementsConfig'),
|
|
15
|
-
pageElementsJson: require('./features/app/stepDefinitions/pageElementsJson'),
|
|
16
|
-
visualRegressionSteps: require('./features/app/stepDefinitions/visualRegressionSteps')
|
|
17
|
-
};
|
|
1
|
+
// Cuppet Core Step Definitions
|
|
2
|
+
// This file exports all step definitions for use in consuming projects
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
accessibilitySteps: require('./features/app/stepDefinitions/accessibilitySteps'),
|
|
6
|
+
apiSteps: require('./features/app/stepDefinitions/apiSteps'),
|
|
7
|
+
appiumSteps: require('./features/app/stepDefinitions/appiumSteps'),
|
|
8
|
+
generalSteps: require('./features/app/stepDefinitions/generalSteps'),
|
|
9
|
+
helperSteps: require('./features/app/stepDefinitions/helperSteps'),
|
|
10
|
+
iframeSteps: require('./features/app/stepDefinitions/iframeSteps'),
|
|
11
|
+
ifVisibleSteps: require('./features/app/stepDefinitions/ifVisibleSteps'),
|
|
12
|
+
lighthouseSteps: require('./features/app/stepDefinitions/lighthouseSteps'),
|
|
13
|
+
pageElements: require('./features/app/stepDefinitions/pageElements'),
|
|
14
|
+
pageElementsConfig: require('./features/app/stepDefinitions/pageElementsConfig'),
|
|
15
|
+
pageElementsJson: require('./features/app/stepDefinitions/pageElementsJson'),
|
|
16
|
+
visualRegressionSteps: require('./features/app/stepDefinitions/visualRegressionSteps'),
|
|
17
|
+
};
|