@auxcode/auxta 0.1.10 → 0.2.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 +7 -3
- package/package.json +1 -1
- package/src/AuxTA.ts +4 -12
- package/src/auxta/configs/config.ts +5 -1
- package/src/auxta/hooks/report.hook.ts +1 -1
- package/src/auxta/services/report.service.ts +1 -1
- package/src/macros/helpers/code.helper.ts +36 -16
- package/src/puppeteer/puppeteer.ts +30 -11
package/README.md
CHANGED
|
@@ -36,9 +36,13 @@ npm i
|
|
|
36
36
|
# Default 1000
|
|
37
37
|
"timeout": 1000,
|
|
38
38
|
# The credentials of the user that uploads the tests to the site
|
|
39
|
-
"email": "",
|
|
40
|
-
"password": "",
|
|
41
|
-
"token": ""
|
|
39
|
+
"email": "string",
|
|
40
|
+
"password": "string",
|
|
41
|
+
"token": "string"
|
|
42
|
+
# Screen width and height used in the testing
|
|
43
|
+
# Allows testing from mobile devices screens
|
|
44
|
+
"screenWidth": 1920,
|
|
45
|
+
"screenHeight": 1080,
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
```
|
package/package.json
CHANGED
package/src/AuxTA.ts
CHANGED
|
@@ -20,27 +20,19 @@ class AuxTA extends FunctionHelper {
|
|
|
20
20
|
super();
|
|
21
21
|
let file;
|
|
22
22
|
try {
|
|
23
|
-
//todo find a better way to load the file
|
|
24
23
|
let currentDir = ""
|
|
25
24
|
while (true) {
|
|
26
25
|
file = path.join(__dirname, currentDir, "auxta.json");
|
|
27
|
-
|
|
28
|
-
fs.accessSync(file, fs.constants.R_OK | fs.constants.W_OK)
|
|
29
|
-
break;
|
|
30
|
-
} catch {
|
|
31
|
-
console.log("Current dir: ", file)
|
|
32
|
-
console.log("Files: ")
|
|
33
|
-
const files = fs.readdirSync(path.join(__dirname, currentDir));
|
|
34
|
-
files.forEach(file => {
|
|
35
|
-
console.log("- " + file);
|
|
36
|
-
});
|
|
26
|
+
if (!fs.existsSync(file)) {
|
|
37
27
|
currentDir += "../"
|
|
38
|
-
if (currentDir.length >=
|
|
28
|
+
if (currentDir.length >= 30) {
|
|
39
29
|
console.log("auxta.json file not found!")
|
|
40
30
|
process.exit(1);
|
|
41
31
|
return;
|
|
42
32
|
}
|
|
33
|
+
continue;
|
|
43
34
|
}
|
|
35
|
+
break;
|
|
44
36
|
}
|
|
45
37
|
const jsonConfig = JSON.parse(fs.readFileSync(file).toString());
|
|
46
38
|
try {
|
|
@@ -16,6 +16,8 @@ export function setupConfig(jsonConfig: any) {
|
|
|
16
16
|
if (!jsonConfig.suitesList) throw new Error("suitesList");
|
|
17
17
|
config.suitesList = jsonConfig.suitesList;
|
|
18
18
|
if (jsonConfig.timeout) config.timeout = jsonConfig.timeout;
|
|
19
|
+
if (jsonConfig.screenWidth) config.screenWidth = jsonConfig.screenWidth;
|
|
20
|
+
if (jsonConfig.screenHeight) config.screenHeight = jsonConfig.screenHeight;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export let config = {
|
|
@@ -26,7 +28,9 @@ export let config = {
|
|
|
26
28
|
netlifyPath: "",
|
|
27
29
|
digitalProduct: "",
|
|
28
30
|
token: "",
|
|
29
|
-
|
|
31
|
+
screenWidth: 1920,
|
|
32
|
+
screenHeight: 1080,
|
|
33
|
+
timeout: 10000,
|
|
30
34
|
suitesList: [],
|
|
31
35
|
auxtaCredentials: {
|
|
32
36
|
email: "",
|
|
@@ -12,7 +12,7 @@ import { startSuite } from '../utilities/start-suite.helper';
|
|
|
12
12
|
import { StepStatusEnum } from "../enums/step-status.enum";
|
|
13
13
|
import { UploadModel } from "../models/upload.model";
|
|
14
14
|
|
|
15
|
-
export async function
|
|
15
|
+
export async function onTestEnd(body: any, featureName: string, scenarioName: string, statusCode: number, screenshotBuffer: Buffer, errMessage?: object) {
|
|
16
16
|
let isFinal: boolean = false;
|
|
17
17
|
if (process.env.ENVIRONMENT == "LIVE") {
|
|
18
18
|
console.log('asc ' + errMessage);
|
|
@@ -66,7 +66,7 @@ export async function createEmptyReport(body: any): Promise<string> {
|
|
|
66
66
|
)).data.reportId;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export async function uploadScenario(stepLog: Step[], scenarioName: string, screenshot?: Buffer, errMessage?:
|
|
69
|
+
export async function uploadScenario(stepLog: Step[], scenarioName: string, screenshot?: Buffer, errMessage?: object) {
|
|
70
70
|
let scenarios = [];
|
|
71
71
|
let token = await auth();
|
|
72
72
|
let lastStep = stepLog[stepLog.length - 1];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import log from "../../auxta/services/log.service";
|
|
2
2
|
import puppeteer from "../../puppeteer/puppeteer";
|
|
3
3
|
import { StepStatusEnum } from "../../auxta/enums/step-status.enum";
|
|
4
|
+
import { config } from "../../auxta/configs/config";
|
|
4
5
|
|
|
5
6
|
export class FunctionHelper {
|
|
6
|
-
public readonly defaultTimeout: number =
|
|
7
|
+
public readonly defaultTimeout: number = config.timeout;
|
|
7
8
|
|
|
8
9
|
public log(keyword: string, name: string, status: StepStatusEnum){
|
|
9
10
|
log.push(keyword, name, status)
|
|
@@ -22,39 +23,49 @@ export class FunctionHelper {
|
|
|
22
23
|
await page.waitForTimeout(this.defaultTimeout);
|
|
23
24
|
const [linkHandlers] = await page.$x(`//${selector}[. = ${this.getEscapedText(text)}]`);
|
|
24
25
|
|
|
26
|
+
const message = `I click on the ${text} ${selector}`;
|
|
25
27
|
if (linkHandlers) {
|
|
26
|
-
log.push('
|
|
28
|
+
log.push('Then', message, StepStatusEnum.PASSED);
|
|
27
29
|
await linkHandlers.click();
|
|
28
30
|
} else {
|
|
29
|
-
log.push('
|
|
31
|
+
log.push('Then', message, StepStatusEnum.FAILED);
|
|
30
32
|
throw new Error(`Link not found: ${text}`);
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
public async waitForSelectorWithText(selector: string, text: string) {
|
|
35
37
|
const linkHandlers = await puppeteer.defaultPage.$x(`//${selector}[. = ${this.getEscapedText(text)}]`);
|
|
38
|
+
const message = `I check for ${text}`;
|
|
36
39
|
if (linkHandlers.length > 0) {
|
|
37
|
-
log.push('And',
|
|
40
|
+
log.push('And', message, StepStatusEnum.PASSED);
|
|
38
41
|
return true;
|
|
39
42
|
} else {
|
|
40
|
-
log.push('And',
|
|
43
|
+
log.push('And', message, StepStatusEnum.FAILED);
|
|
41
44
|
throw new Error(`Link not found: ${text}`);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
public async goto(page: string) {
|
|
46
49
|
await puppeteer.defaultPage.goto(page);
|
|
47
|
-
log.push('
|
|
50
|
+
log.push('Then', `I go to the ${page} page`, StepStatusEnum.PASSED);
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
public async type(field: string, value: string) {
|
|
51
54
|
await puppeteer.defaultPage.type(field, value);
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
let elementName = await puppeteer.defaultPage.$eval(field, (e) => e.textContent);
|
|
56
|
+
if (!elementName || elementName === ' ') elementName = field;
|
|
57
|
+
log.push('Then', `I type '${value}' into the ${elementName} field`, StepStatusEnum.PASSED);
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
public async waitForNetwork() {
|
|
57
|
-
|
|
61
|
+
let message = 'I wait for the page to load'
|
|
62
|
+
try{
|
|
63
|
+
await puppeteer.defaultPage.waitForNetworkIdle();
|
|
64
|
+
log.push('Then', message, StepStatusEnum.PASSED);
|
|
65
|
+
} catch (e){
|
|
66
|
+
log.push('Then', message, StepStatusEnum.FAILED);
|
|
67
|
+
throw new Error(message)
|
|
68
|
+
}
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
public async timeout(timeout = this.defaultTimeout) {
|
|
@@ -72,26 +83,35 @@ export class FunctionHelper {
|
|
|
72
83
|
*/
|
|
73
84
|
|
|
74
85
|
public async waitForSelector(option: string, selector: string, time: number = this.defaultTimeout, page = puppeteer.defaultPage) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
const message = `I check for the ${selector} element to be ${option}`;
|
|
87
|
+
try{
|
|
88
|
+
await page.waitForSelector(selector, {
|
|
89
|
+
[option]: true,
|
|
90
|
+
timeout: time
|
|
91
|
+
});
|
|
92
|
+
} catch (e){
|
|
93
|
+
log.push('And', message, StepStatusEnum.FAILED);
|
|
94
|
+
throw new Error(message)
|
|
95
|
+
}
|
|
96
|
+
log.push('And', message, StepStatusEnum.PASSED);
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
public async click(className: string, page = puppeteer.defaultPage) {
|
|
82
100
|
await page.waitForTimeout(this.defaultTimeout);
|
|
83
|
-
|
|
101
|
+
let elementName = await puppeteer.defaultPage.$eval(className, (e) => e.textContent);
|
|
102
|
+
if (!elementName || elementName === ' ') elementName = className;
|
|
84
103
|
await page.click(className);
|
|
85
104
|
log.push('Then', `I click on ${elementName}`, StepStatusEnum.PASSED);
|
|
86
105
|
}
|
|
87
106
|
|
|
88
107
|
public async urlContains(selector: string) {
|
|
89
108
|
const url = puppeteer.defaultPage.url();
|
|
109
|
+
let message = `I am on the ${selector} page`
|
|
90
110
|
if (!url.includes(selector)) {
|
|
91
|
-
log.push('And',
|
|
111
|
+
log.push('And', message, StepStatusEnum.FAILED);
|
|
92
112
|
throw new Error(`I am not at the ${selector} page`)
|
|
93
113
|
}
|
|
94
|
-
log.push('And',
|
|
114
|
+
log.push('And', message, StepStatusEnum.PASSED);
|
|
95
115
|
}
|
|
96
116
|
|
|
97
117
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chromium from 'chrome-aws-lambda';
|
|
2
2
|
import log from "../auxta/services/log.service";
|
|
3
3
|
import { captureScreenshot } from "../auxta/utilities/screenshot.helper";
|
|
4
|
-
import {
|
|
4
|
+
import { onTestEnd } from "../auxta/hooks/report.hook";
|
|
5
5
|
import auxta from "../AuxTA";
|
|
6
6
|
import { StepStatusEnum } from "../auxta/enums/step-status.enum";
|
|
7
7
|
import { UploadModel } from "../auxta/models/upload.model";
|
|
@@ -14,17 +14,23 @@ export class Puppeteer {
|
|
|
14
14
|
private browser!: puppeteer_core.Browser;
|
|
15
15
|
|
|
16
16
|
public async startBrowser() {
|
|
17
|
+
let args = [
|
|
18
|
+
'--start-maximized',
|
|
19
|
+
'--no-sandbox',
|
|
20
|
+
'--disable-setuid-sandbox',
|
|
21
|
+
'--disable-dev-shm-usage',
|
|
22
|
+
'--single-process'
|
|
23
|
+
];
|
|
24
|
+
if (process.env.ENVIRONMENT != 'LOCAL')
|
|
25
|
+
args.push(`--window-size=${config.screenWidth},${config.screenHeight}`)
|
|
17
26
|
this.browser = await chromium.puppeteer.launch({
|
|
18
27
|
executablePath: process.env.NODE_ENV !== 'production' ? undefined : await chromium.executablePath,
|
|
19
|
-
args
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
],
|
|
26
|
-
defaultViewport: null,
|
|
27
|
-
// Return back to headless for commit
|
|
28
|
+
args,
|
|
29
|
+
defaultViewport: process.env.ENVIRONMENT == 'LOCAL' ? null : {
|
|
30
|
+
width: config.screenWidth,
|
|
31
|
+
height: config.screenHeight
|
|
32
|
+
},
|
|
33
|
+
// Return back to headless for netlify
|
|
28
34
|
headless: process.env.ENVIRONMENT == 'LOCAL' ? false : chromium.headless
|
|
29
35
|
});
|
|
30
36
|
this.defaultPage = (await this.browser.pages())[0];
|
|
@@ -47,9 +53,17 @@ export class Puppeteer {
|
|
|
47
53
|
let errMessage: string | undefined;
|
|
48
54
|
let statusCode: number = 200;
|
|
49
55
|
|
|
56
|
+
let consoleStack = [];
|
|
50
57
|
try {
|
|
51
58
|
await log.push('When', `Starting puppeteer process`, StepStatusEnum.PASSED);
|
|
52
59
|
await this.startBrowser()
|
|
60
|
+
await this.defaultPage.on('console', message =>
|
|
61
|
+
consoleStack.push(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
|
|
62
|
+
.on('pageerror', ({ message }) => consoleStack.push(message))
|
|
63
|
+
.on('response', response =>
|
|
64
|
+
consoleStack.push(`${response.status()} ${response.url()}`))
|
|
65
|
+
.on('requestfailed', request =>
|
|
66
|
+
consoleStack.push(`${request.failure().errorText} ${request.url()}`))
|
|
53
67
|
await callback(event)
|
|
54
68
|
screenshotBuffer = await captureScreenshot();
|
|
55
69
|
await log.push('When', `Finished puppeteer process`, StepStatusEnum.PASSED);
|
|
@@ -60,9 +74,14 @@ export class Puppeteer {
|
|
|
60
74
|
screenshotBuffer = await captureScreenshot();
|
|
61
75
|
await log.push('When', `Finished puppeteer process`, StepStatusEnum.FAILED);
|
|
62
76
|
}
|
|
77
|
+
let url = this.defaultPage.url();
|
|
63
78
|
if (close) await this.close();
|
|
79
|
+
log.clear();
|
|
64
80
|
|
|
65
|
-
await
|
|
81
|
+
await onTestEnd(uploadModel, featureName, scenarioName, statusCode, screenshotBuffer, !errMessage ? undefined : {
|
|
82
|
+
currentPageUrl: url,
|
|
83
|
+
error: errMessage
|
|
84
|
+
});
|
|
66
85
|
}
|
|
67
86
|
|
|
68
87
|
private static setupHeader(event: any, uploadModel: UploadModel) {
|