@auxcode/auxta 0.5.5 → 0.5.9
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/build/AuxTA.js +38 -23
- package/build/auxta/helpers/start.helper.js +12 -3
- package/build/auxta/hooks/report.hook.js +50 -37
- package/build/auxta/services/report.service.js +126 -105
- package/build/auxta/utilities/screenshot.helper.js +27 -16
- package/build/auxta/utilities/start-suite.helper.js +22 -11
- package/build/cjs/AuxTA.d.ts +43 -0
- package/build/cjs/AuxTA.js +137 -0
- package/build/cjs/auxta/configs/config.d.ts +51 -0
- package/build/cjs/auxta/configs/config.js +66 -0
- package/build/cjs/auxta/enums/status-of.step.d.ts +7 -0
- package/build/cjs/auxta/enums/status-of.step.js +11 -0
- package/build/cjs/auxta/helpers/response.helper.d.ts +10 -0
- package/build/cjs/auxta/helpers/response.helper.js +15 -0
- package/build/cjs/auxta/helpers/start.helper.d.ts +1 -0
- package/build/cjs/auxta/helpers/start.helper.js +26 -0
- package/build/cjs/auxta/hooks/report.hook.d.ts +4 -0
- package/build/cjs/auxta/hooks/report.hook.js +66 -0
- package/build/cjs/auxta/models/upload.model.d.ts +20 -0
- package/build/cjs/auxta/models/upload.model.js +47 -0
- package/build/cjs/auxta/services/log.service.d.ts +26 -0
- package/build/cjs/auxta/services/log.service.js +47 -0
- package/build/cjs/auxta/services/report.service.d.ts +36 -0
- package/build/cjs/auxta/services/report.service.js +162 -0
- package/build/cjs/auxta/services/runtime.service.d.ts +16 -0
- package/build/cjs/auxta/services/runtime.service.js +41 -0
- package/build/cjs/auxta/utilities/runtime.helper.d.ts +15 -0
- package/build/cjs/auxta/utilities/runtime.helper.js +19 -0
- package/build/cjs/auxta/utilities/screenshot.helper.d.ts +2 -0
- package/build/cjs/auxta/utilities/screenshot.helper.js +36 -0
- package/build/cjs/auxta/utilities/start-suite.helper.d.ts +1 -0
- package/build/cjs/auxta/utilities/start-suite.helper.js +32 -0
- package/build/cjs/macros/helpers/code.helper.d.ts +22 -0
- package/build/cjs/macros/helpers/code.helper.js +200 -0
- package/build/cjs/puppeteer/puppeteer.d.ts +13 -0
- package/build/cjs/puppeteer/puppeteer.js +160 -0
- package/build/esm/AuxTA.d.ts +43 -0
- package/build/esm/AuxTA.js +97 -0
- package/build/esm/auxta/configs/config.d.ts +51 -0
- package/build/esm/auxta/configs/config.js +61 -0
- package/build/esm/auxta/enums/status-of.step.d.ts +7 -0
- package/build/esm/auxta/enums/status-of.step.js +8 -0
- package/build/esm/auxta/helpers/response.helper.d.ts +10 -0
- package/build/esm/auxta/helpers/response.helper.js +11 -0
- package/build/esm/auxta/helpers/start.helper.d.ts +1 -0
- package/build/esm/auxta/helpers/start.helper.js +15 -0
- package/build/esm/auxta/hooks/report.hook.d.ts +4 -0
- package/build/esm/auxta/hooks/report.hook.js +45 -0
- package/build/esm/auxta/models/upload.model.d.ts +20 -0
- package/build/esm/auxta/models/upload.model.js +43 -0
- package/build/esm/auxta/services/log.service.d.ts +26 -0
- package/build/esm/auxta/services/log.service.js +43 -0
- package/build/esm/auxta/services/report.service.d.ts +36 -0
- package/build/esm/auxta/services/report.service.js +127 -0
- package/build/esm/auxta/services/runtime.service.d.ts +16 -0
- package/build/esm/auxta/services/runtime.service.js +37 -0
- package/build/esm/auxta/utilities/runtime.helper.d.ts +15 -0
- package/build/esm/auxta/utilities/runtime.helper.js +15 -0
- package/build/esm/auxta/utilities/screenshot.helper.d.ts +2 -0
- package/build/esm/auxta/utilities/screenshot.helper.js +18 -0
- package/build/esm/auxta/utilities/start-suite.helper.d.ts +1 -0
- package/build/esm/auxta/utilities/start-suite.helper.js +14 -0
- package/build/esm/macros/helpers/code.helper.d.ts +22 -0
- package/build/esm/macros/helpers/code.helper.js +158 -0
- package/build/esm/puppeteer/puppeteer.d.ts +13 -0
- package/build/esm/puppeteer/puppeteer.js +136 -0
- package/build/macros/helpers/code.helper.js +164 -129
- package/build/puppeteer/puppeteer.js +117 -100
- package/build/tsconfig-cjs.tsbuildinfo +1 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Step } from "./log.service";
|
|
3
|
+
import { UploadModel } from "../models/upload.model";
|
|
4
|
+
export interface Feature {
|
|
5
|
+
featureId: string;
|
|
6
|
+
featureName: string;
|
|
7
|
+
featureUri: string;
|
|
8
|
+
status: string;
|
|
9
|
+
scenariosCount: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Scenario {
|
|
12
|
+
featureId: string;
|
|
13
|
+
featureName: string;
|
|
14
|
+
featureUri: string;
|
|
15
|
+
status: string;
|
|
16
|
+
scenariosCount: number;
|
|
17
|
+
}
|
|
18
|
+
export interface Steps {
|
|
19
|
+
failedSteps: number;
|
|
20
|
+
passedSteps: number;
|
|
21
|
+
skippedSteps: number;
|
|
22
|
+
suggestedSteps: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function createEmptyReport(body: any): Promise<string>;
|
|
25
|
+
export declare function uploadScenario(stepLog: Step[], scenarioName: string, screenshot?: Buffer, errMessage?: object): Promise<{
|
|
26
|
+
scenarioRef: any;
|
|
27
|
+
name: any;
|
|
28
|
+
status: any;
|
|
29
|
+
stepsCount: any;
|
|
30
|
+
}[]>;
|
|
31
|
+
export declare function uploadFeature(scenarioId: any[], scenarioName: string, uri: string, hasFailed: boolean): Promise<any>;
|
|
32
|
+
export declare function updateReport(reportId: string, feature: Feature, steps: Steps, isFinal: boolean): Promise<void>;
|
|
33
|
+
export declare function getReport(reportId: string): Promise<any>;
|
|
34
|
+
export declare function getLastDayResults(): Promise<any>;
|
|
35
|
+
export declare function postNotifications(body: UploadModel): Promise<void>;
|
|
36
|
+
export declare function postNotificationsOnFail(body: UploadModel): Promise<void>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { config } from "../configs/config";
|
|
3
|
+
function headers(token) {
|
|
4
|
+
return {
|
|
5
|
+
headers: {
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
'cookie': `authToken=${token}`
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
async function auth() {
|
|
12
|
+
return axios.post(config.auxtaURL + 'login', config.auxtaCredentials, {
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
.then(({ data }) => {
|
|
18
|
+
return data.token;
|
|
19
|
+
})
|
|
20
|
+
.catch(() => {
|
|
21
|
+
throw new Error("Invalid login credentials");
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export async function createEmptyReport(body) {
|
|
25
|
+
const token = await auth();
|
|
26
|
+
return (await axios.post(config.auxtaURL + "create-empty-report", {
|
|
27
|
+
environment: body.environment,
|
|
28
|
+
digitalProductName: body.digitalProduct,
|
|
29
|
+
start: new Date(),
|
|
30
|
+
url: body.baseUrl
|
|
31
|
+
}, headers(token))).data.reportId;
|
|
32
|
+
}
|
|
33
|
+
export async function uploadScenario(stepLog, scenarioName, screenshot, errMessage) {
|
|
34
|
+
let scenarios = [];
|
|
35
|
+
let token = await auth();
|
|
36
|
+
let lastStep = stepLog[stepLog.length - 1];
|
|
37
|
+
const stepLogFormat = JSON.parse(JSON.stringify(stepLog));
|
|
38
|
+
stepLogFormat.pop();
|
|
39
|
+
let output = (await axios.post(config.auxtaURL + "create-scenario", {
|
|
40
|
+
json: {
|
|
41
|
+
name: scenarioName,
|
|
42
|
+
steps: [
|
|
43
|
+
...stepLogFormat,
|
|
44
|
+
(lastStep.result.status == 'failed')
|
|
45
|
+
? Object.assign(lastStep, {
|
|
46
|
+
result: {
|
|
47
|
+
...lastStep.result,
|
|
48
|
+
error_message: JSON.stringify(errMessage)
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
: lastStep,
|
|
52
|
+
{
|
|
53
|
+
keyword: "After",
|
|
54
|
+
result: {
|
|
55
|
+
status: "passed",
|
|
56
|
+
duration: 2678000000
|
|
57
|
+
},
|
|
58
|
+
embeddings: (screenshot) ? [{
|
|
59
|
+
data: screenshot.toString("base64"),
|
|
60
|
+
mime_type: "image/png"
|
|
61
|
+
}] : undefined,
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
}
|
|
65
|
+
}, headers(token))).data.scenarios;
|
|
66
|
+
scenarios.push({
|
|
67
|
+
scenarioRef: output.scenarioRef,
|
|
68
|
+
name: output.name,
|
|
69
|
+
status: output.status,
|
|
70
|
+
stepsCount: output.stepsCount
|
|
71
|
+
});
|
|
72
|
+
return scenarios;
|
|
73
|
+
}
|
|
74
|
+
export async function uploadFeature(scenarioId, scenarioName, uri, hasFailed) {
|
|
75
|
+
let token = await auth();
|
|
76
|
+
return (await axios.post(config.auxtaURL + "create-feature", {
|
|
77
|
+
json: {
|
|
78
|
+
name: scenarioName,
|
|
79
|
+
uri: uri
|
|
80
|
+
},
|
|
81
|
+
scenarios: scenarioId,
|
|
82
|
+
hasFailed: hasFailed
|
|
83
|
+
}, headers(token))).data;
|
|
84
|
+
}
|
|
85
|
+
export async function updateReport(reportId, feature, steps, isFinal) {
|
|
86
|
+
let token = await auth();
|
|
87
|
+
await axios.post(config.auxtaURL + "update-inprogress-report", {
|
|
88
|
+
reportId: reportId,
|
|
89
|
+
isFinal: isFinal,
|
|
90
|
+
data: {
|
|
91
|
+
feature: {
|
|
92
|
+
featureRef: feature.featureId,
|
|
93
|
+
name: feature.featureName,
|
|
94
|
+
uri: feature.featureUri,
|
|
95
|
+
status: feature.status,
|
|
96
|
+
scenariosCount: feature.scenariosCount
|
|
97
|
+
},
|
|
98
|
+
...steps
|
|
99
|
+
}
|
|
100
|
+
}, headers(token));
|
|
101
|
+
}
|
|
102
|
+
export async function getReport(reportId) {
|
|
103
|
+
let token = await auth();
|
|
104
|
+
return (await axios.post(config.auxtaURL + "get-report", { reportId: reportId }, headers(token))).data;
|
|
105
|
+
}
|
|
106
|
+
export async function getLastDayResults() {
|
|
107
|
+
let token = await auth();
|
|
108
|
+
return (await axios.get(config.auxtaURL + `get-last-day-results?url=${config.baseURL}`, headers(token))).data.results;
|
|
109
|
+
}
|
|
110
|
+
export async function postNotifications(body) {
|
|
111
|
+
let token = await auth();
|
|
112
|
+
await axios.post(`${config.auxtaURL}post-notification-after-run-background`, {
|
|
113
|
+
environmentName: body.environment,
|
|
114
|
+
digitalProductName: body.digitalProduct,
|
|
115
|
+
organizationName: body.organization,
|
|
116
|
+
reportId: body.reportId,
|
|
117
|
+
}, headers(token));
|
|
118
|
+
}
|
|
119
|
+
export async function postNotificationsOnFail(body) {
|
|
120
|
+
let token = await auth();
|
|
121
|
+
await axios.post(`${config.auxtaURL}post-notifications-after-case-fail-background`, {
|
|
122
|
+
environmentName: body.environment,
|
|
123
|
+
digitalProductName: body.digitalProduct,
|
|
124
|
+
organizationName: body.organization,
|
|
125
|
+
reportId: body.reportId,
|
|
126
|
+
}, headers(token));
|
|
127
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface RunTime {
|
|
2
|
+
duration: String;
|
|
3
|
+
startTime: Date;
|
|
4
|
+
endTime: Date;
|
|
5
|
+
}
|
|
6
|
+
export declare class Runtime {
|
|
7
|
+
private start;
|
|
8
|
+
private end;
|
|
9
|
+
private runtime;
|
|
10
|
+
constructor(s: Date, e: Date);
|
|
11
|
+
private calculateDuration;
|
|
12
|
+
private splitAtDecimanlMinutes;
|
|
13
|
+
private splitAtDecimanlHours;
|
|
14
|
+
private formatRuntime;
|
|
15
|
+
returnRuntime(): RunTime;
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class Runtime {
|
|
2
|
+
constructor(s, e) {
|
|
3
|
+
this.start = s;
|
|
4
|
+
this.end = e;
|
|
5
|
+
}
|
|
6
|
+
calculateDuration() {
|
|
7
|
+
let currentTime = new Date;
|
|
8
|
+
let duration = currentTime.getTime() - this.start.getTime();
|
|
9
|
+
return duration;
|
|
10
|
+
}
|
|
11
|
+
splitAtDecimanlMinutes(time) {
|
|
12
|
+
let minutes = time.toFixed(2).toString().split('.');
|
|
13
|
+
return `${minutes[0]}m ${(Number(minutes[1]) / 100 * 60).toFixed(0)}s`;
|
|
14
|
+
}
|
|
15
|
+
splitAtDecimanlHours(time) {
|
|
16
|
+
let hours = time.toFixed(2).toString().split('.');
|
|
17
|
+
let minutes = (Number(hours[1]) / 100 * 60).toFixed(2).toString().split('.');
|
|
18
|
+
return `${hours[0]}h ${minutes[0]}m ${(Number(minutes[1]) / 100 * 60).toFixed(0)}s`;
|
|
19
|
+
}
|
|
20
|
+
formatRuntime(duration) {
|
|
21
|
+
if (duration / 1000 < 60)
|
|
22
|
+
return `${(duration / 1000).toFixed(0)}s`;
|
|
23
|
+
else {
|
|
24
|
+
if (duration / 60000 < 60)
|
|
25
|
+
return this.splitAtDecimanlMinutes(duration / 60000);
|
|
26
|
+
else
|
|
27
|
+
return this.splitAtDecimanlHours(duration / 3600000);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
returnRuntime() {
|
|
31
|
+
let duration = this.formatRuntime(this.calculateDuration());
|
|
32
|
+
let startTime = this.start;
|
|
33
|
+
let endTime = this.end;
|
|
34
|
+
this.runtime = { duration, startTime, endTime };
|
|
35
|
+
return this.runtime;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RunTime } from "../services/runtime.service";
|
|
2
|
+
export declare class CalculateRuntime {
|
|
3
|
+
private runtime;
|
|
4
|
+
startTimeSeconds: string;
|
|
5
|
+
startTimeMinutes: string;
|
|
6
|
+
startTimeHours: string;
|
|
7
|
+
startTimeDay: string;
|
|
8
|
+
startTimeMonth: string;
|
|
9
|
+
endTimeSeconds: string;
|
|
10
|
+
endTimeMinutes: string;
|
|
11
|
+
endTimeHours: string;
|
|
12
|
+
endTimeDay: string;
|
|
13
|
+
endTimeMonth: string;
|
|
14
|
+
constructor(r: RunTime);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class CalculateRuntime {
|
|
2
|
+
constructor(r) {
|
|
3
|
+
this.runtime = r;
|
|
4
|
+
this.startTimeSeconds = (this.runtime.startTime.getSeconds() < 10) ? `0${this.runtime.startTime.getSeconds()}` : `${this.runtime.startTime.getSeconds()}`;
|
|
5
|
+
this.startTimeMinutes = (this.runtime.startTime.getMinutes() < 10) ? `0${this.runtime.startTime.getMinutes()}` : `${this.runtime.startTime.getMinutes()}`;
|
|
6
|
+
this.startTimeHours = (this.runtime.startTime.getHours() < 10) ? `0${this.runtime.startTime.getHours()}` : `${this.runtime.startTime.getHours()}`;
|
|
7
|
+
this.startTimeDay = (this.runtime.startTime.getDate() < 10) ? `0${this.runtime.startTime.getDate()}` : `${this.runtime.startTime.getDate()}`;
|
|
8
|
+
this.startTimeMonth = (this.runtime.startTime.getMonth() + 1 < 10) ? `0${this.runtime.startTime.getMonth() + 1}` : `${this.runtime.startTime.getMonth() + 1}`;
|
|
9
|
+
this.endTimeSeconds = (this.runtime.endTime.getSeconds() < 10) ? `0${this.runtime.endTime.getSeconds()}` : `${this.runtime.endTime.getSeconds()}`;
|
|
10
|
+
this.endTimeMinutes = (this.runtime.endTime.getMinutes() < 10) ? `0${this.runtime.endTime.getMinutes()}` : `${this.runtime.endTime.getMinutes()}`;
|
|
11
|
+
this.endTimeHours = (this.runtime.endTime.getHours() < 10) ? `0${this.runtime.endTime.getHours()}` : `${this.runtime.endTime.getHours()}`;
|
|
12
|
+
this.endTimeDay = (this.runtime.endTime.getDate() < 10) ? `0${this.runtime.endTime.getDate()}` : `${this.runtime.endTime.getDate()}`;
|
|
13
|
+
this.endTimeMonth = (this.runtime.endTime.getMonth() + 1 < 10) ? `0${this.runtime.endTime.getMonth() + 1}` : `${this.runtime.endTime.getMonth() + 1}`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import puppeteer from "../../puppeteer/puppeteer";
|
|
2
|
+
export async function captureScreenshot() {
|
|
3
|
+
try {
|
|
4
|
+
const pages = await puppeteer.defaultPage.browser().pages();
|
|
5
|
+
if (!pages.length)
|
|
6
|
+
return undefined;
|
|
7
|
+
const lastPage = pages[pages.length - 1] || puppeteer.defaultPage;
|
|
8
|
+
const screenshotBuffer = await lastPage.screenshot({
|
|
9
|
+
fullPage: true,
|
|
10
|
+
encoding: 'binary'
|
|
11
|
+
});
|
|
12
|
+
if (Buffer.isBuffer(screenshotBuffer))
|
|
13
|
+
return screenshotBuffer;
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startSuite(suites: string[], reportId?: string): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { config } from "../configs/config";
|
|
3
|
+
export async function startSuite(suites, reportId) {
|
|
4
|
+
if (suites.length === 0)
|
|
5
|
+
return;
|
|
6
|
+
const next = suites.shift();
|
|
7
|
+
console.log('Starting next suite: ' + next);
|
|
8
|
+
try {
|
|
9
|
+
await axios.post(`${config.netlifyPath}.netlify/functions/${next}?token=${config.token}`, { nextSuites: suites, reportId: reportId });
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
await startSuite(suites, reportId);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { StatusOfStep } from "../../auxta/enums/status-of.step";
|
|
2
|
+
export declare class FunctionHelper {
|
|
3
|
+
readonly defaultTimeout: number;
|
|
4
|
+
log(keyword: string, name: string, status: StatusOfStep): void;
|
|
5
|
+
suggest(name: string): void;
|
|
6
|
+
private getEscapedText;
|
|
7
|
+
clickByText(selector: string, text: string, page?: import("puppeteer-core").Page, dotOrText?: string): Promise<void>;
|
|
8
|
+
clickByTextWithClass(class_selector: string, class_name: string, selector: string, text: string, page?: import("puppeteer-core").Page, dotOrText?: string): Promise<void>;
|
|
9
|
+
waitForSelectorWithText(selector: string, text: string, page?: import("puppeteer-core").Page, dotOrText?: string): Promise<boolean>;
|
|
10
|
+
goto(url: string, page?: import("puppeteer-core").Page): Promise<void>;
|
|
11
|
+
type(field: string, value: string, page?: import("puppeteer-core").Page): Promise<void>;
|
|
12
|
+
waitForNetwork(page?: import("puppeteer-core").Page): Promise<void>;
|
|
13
|
+
timeout(timeout?: number, page?: import("puppeteer-core").Page): Promise<void>;
|
|
14
|
+
waitForSelector(option: string, selector: string, time?: number, page?: import("puppeteer-core").Page, log_message?: boolean): Promise<void>;
|
|
15
|
+
click(selector: string, logMessages?: boolean, page?: import("puppeteer-core").Page): Promise<void>;
|
|
16
|
+
urlContains(selector: string, page?: import("puppeteer-core").Page): Promise<void>;
|
|
17
|
+
pressEnter(page?: import("puppeteer-core").Page): Promise<void>;
|
|
18
|
+
clickAndWaitForPageToBeCreated(selector: string, page?: import("puppeteer-core").Page): Promise<void>;
|
|
19
|
+
closeLastPage(page?: import("puppeteer-core").Page): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
declare const _default: FunctionHelper;
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import log from "../../auxta/services/log.service";
|
|
2
|
+
import puppeteer from "../../puppeteer/puppeteer";
|
|
3
|
+
import { StatusOfStep } from "../../auxta/enums/status-of.step";
|
|
4
|
+
import { config } from "../../auxta/configs/config";
|
|
5
|
+
export class FunctionHelper {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.defaultTimeout = config.timeout;
|
|
8
|
+
}
|
|
9
|
+
log(keyword, name, status) {
|
|
10
|
+
log.push(keyword, name, status);
|
|
11
|
+
}
|
|
12
|
+
suggest(name) {
|
|
13
|
+
log.addSuggestion(name);
|
|
14
|
+
}
|
|
15
|
+
getEscapedText(text) {
|
|
16
|
+
const splitedQuotes = text.replace(/'/g, `', "'", '`);
|
|
17
|
+
return `concat('${splitedQuotes}', '')`;
|
|
18
|
+
}
|
|
19
|
+
async clickByText(selector, text, page = puppeteer.defaultPage, dotOrText = '.') {
|
|
20
|
+
const message = `I click on the '${text}' '${selector}'`;
|
|
21
|
+
try {
|
|
22
|
+
const [linkHandlers] = await page.$x(`//${selector}[${dotOrText} = ${this.getEscapedText(text)}]`);
|
|
23
|
+
if (linkHandlers) {
|
|
24
|
+
await linkHandlers.click();
|
|
25
|
+
log.push('Then', message, StatusOfStep.PASSED);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
}
|
|
31
|
+
log.push('Then', message, StatusOfStep.FAILED);
|
|
32
|
+
throw new Error(message);
|
|
33
|
+
}
|
|
34
|
+
async clickByTextWithClass(class_selector, class_name, selector, text, page = puppeteer.defaultPage, dotOrText = '.') {
|
|
35
|
+
const message = `I click on the '${text}' '${selector}'`;
|
|
36
|
+
try {
|
|
37
|
+
const [linkHandlers] = await page.$x(`//${class_selector}[contains(@class,${this.getEscapedText(class_name)})]//${selector}[${dotOrText} = ${this.getEscapedText(text)}]`);
|
|
38
|
+
if (linkHandlers) {
|
|
39
|
+
await linkHandlers.click();
|
|
40
|
+
log.push('Then', message, StatusOfStep.PASSED);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
}
|
|
46
|
+
log.push('Then', message, StatusOfStep.FAILED);
|
|
47
|
+
throw new Error(message);
|
|
48
|
+
}
|
|
49
|
+
async waitForSelectorWithText(selector, text, page = puppeteer.defaultPage, dotOrText = '.') {
|
|
50
|
+
const message = `I check for '${text}' on the current page`;
|
|
51
|
+
try {
|
|
52
|
+
await page.waitForSelector(selector, {
|
|
53
|
+
timeout: this.defaultTimeout
|
|
54
|
+
});
|
|
55
|
+
const linkHandlers = await page.$x(`//${selector}[${dotOrText} = ${this.getEscapedText(text)}]`);
|
|
56
|
+
if (linkHandlers.length > 0) {
|
|
57
|
+
log.push('And', message, StatusOfStep.PASSED);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
}
|
|
63
|
+
log.push('And', message, StatusOfStep.FAILED);
|
|
64
|
+
throw new Error(message);
|
|
65
|
+
}
|
|
66
|
+
async goto(url, page = puppeteer.defaultPage) {
|
|
67
|
+
await page.goto(url);
|
|
68
|
+
log.push('Then', `I go to the '${url}' page`, StatusOfStep.PASSED);
|
|
69
|
+
}
|
|
70
|
+
async type(field, value, page = puppeteer.defaultPage) {
|
|
71
|
+
try {
|
|
72
|
+
await page.waitForSelector(field, {
|
|
73
|
+
timeout: this.defaultTimeout
|
|
74
|
+
});
|
|
75
|
+
await page.type(field, value);
|
|
76
|
+
let elementName = await page.$eval(field, (e) => e.textContent);
|
|
77
|
+
if (!elementName || elementName === ' ')
|
|
78
|
+
elementName = field;
|
|
79
|
+
log.push('Then', `I type '${value}' into the '${elementName}' field`, StatusOfStep.PASSED);
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
const msg = `I type '${value}' into the '${field}' field`;
|
|
83
|
+
log.push('Then', msg, StatusOfStep.FAILED);
|
|
84
|
+
throw new Error(msg);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async waitForNetwork(page = puppeteer.defaultPage) {
|
|
88
|
+
let message = 'I wait for the page to load';
|
|
89
|
+
try {
|
|
90
|
+
await page.waitForNetworkIdle();
|
|
91
|
+
log.push('Then', message, StatusOfStep.PASSED);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
log.push('Then', message, StatusOfStep.FAILED);
|
|
95
|
+
throw new Error(message);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async timeout(timeout = this.defaultTimeout, page = puppeteer.defaultPage) {
|
|
99
|
+
await page.waitForTimeout(timeout);
|
|
100
|
+
}
|
|
101
|
+
async waitForSelector(option, selector, time = this.defaultTimeout, page = puppeteer.defaultPage, log_message = true) {
|
|
102
|
+
const message = `I check for the '${selector}' element to be ${option}`;
|
|
103
|
+
try {
|
|
104
|
+
await page.waitForSelector(selector, {
|
|
105
|
+
[option]: true,
|
|
106
|
+
timeout: time
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
if (log_message) {
|
|
111
|
+
log.push('And', message, StatusOfStep.FAILED);
|
|
112
|
+
}
|
|
113
|
+
throw new Error(message);
|
|
114
|
+
}
|
|
115
|
+
if (log_message) {
|
|
116
|
+
log.push('And', message, StatusOfStep.PASSED);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async click(selector, logMessages = true, page = puppeteer.defaultPage) {
|
|
120
|
+
try {
|
|
121
|
+
await page.waitForSelector(selector, {
|
|
122
|
+
timeout: this.defaultTimeout
|
|
123
|
+
});
|
|
124
|
+
let elementName = await page.$eval(selector, (e) => e.textContent);
|
|
125
|
+
if (!elementName || elementName === ' ')
|
|
126
|
+
elementName = selector;
|
|
127
|
+
await page.click(selector);
|
|
128
|
+
log.push('Then', `I click on the '${elementName}'`, StatusOfStep.PASSED);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
const msg = `I click on the '${selector}'`;
|
|
132
|
+
log.push('Then', msg, StatusOfStep.FAILED);
|
|
133
|
+
throw new Error(msg);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async urlContains(selector, page = puppeteer.defaultPage) {
|
|
137
|
+
const url = page.url();
|
|
138
|
+
let message = `I am on the ${selector} page`;
|
|
139
|
+
if (!url.includes(selector)) {
|
|
140
|
+
log.push('And', message, StatusOfStep.FAILED);
|
|
141
|
+
throw new Error(message);
|
|
142
|
+
}
|
|
143
|
+
log.push('And', message, StatusOfStep.PASSED);
|
|
144
|
+
}
|
|
145
|
+
async pressEnter(page = puppeteer.defaultPage) {
|
|
146
|
+
await page.keyboard.press('Enter');
|
|
147
|
+
}
|
|
148
|
+
async clickAndWaitForPageToBeCreated(selector, page = puppeteer.defaultPage) {
|
|
149
|
+
const nav = new Promise(res => page.browser().on('targetcreated', res));
|
|
150
|
+
await this.click(selector);
|
|
151
|
+
await nav;
|
|
152
|
+
}
|
|
153
|
+
async closeLastPage(page = puppeteer.defaultPage) {
|
|
154
|
+
const pages = await page.browser().pages();
|
|
155
|
+
await pages[pages.length - 1].close();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export default new FunctionHelper();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { UploadModel } from "../auxta/models/upload.model";
|
|
2
|
+
import puppeteer_core from 'puppeteer-core';
|
|
3
|
+
export declare class Puppeteer {
|
|
4
|
+
defaultPage: puppeteer_core.Page;
|
|
5
|
+
private browser;
|
|
6
|
+
startBrowser(): Promise<void>;
|
|
7
|
+
close(): Promise<void>;
|
|
8
|
+
run(event: any, callback: any, featureName?: string, scenarioName?: string, uploadModel?: UploadModel, close?: boolean): Promise<void>;
|
|
9
|
+
runRPA(event: any, callback: any, close?: boolean): Promise<any>;
|
|
10
|
+
private static setupHeader;
|
|
11
|
+
}
|
|
12
|
+
declare const _default: Puppeteer;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import chromium from 'chrome-aws-lambda';
|
|
2
|
+
import log from "../auxta/services/log.service";
|
|
3
|
+
import { captureScreenshot } from "../auxta/utilities/screenshot.helper";
|
|
4
|
+
import { onTestEnd } from "../auxta/hooks/report.hook";
|
|
5
|
+
import auxta from "../AuxTA";
|
|
6
|
+
import { StatusOfStep } from "../auxta/enums/status-of.step";
|
|
7
|
+
import { config } from "./../auxta/configs/config";
|
|
8
|
+
import { postNotificationsOnFail } from "../auxta/services/report.service";
|
|
9
|
+
export class Puppeteer {
|
|
10
|
+
async startBrowser() {
|
|
11
|
+
let args = [
|
|
12
|
+
'--start-maximized',
|
|
13
|
+
'--no-sandbox',
|
|
14
|
+
'--disable-setuid-sandbox',
|
|
15
|
+
'--disable-dev-shm-usage',
|
|
16
|
+
'--single-process'
|
|
17
|
+
];
|
|
18
|
+
if (process.env.ENVIRONMENT != 'LOCAL')
|
|
19
|
+
args.push(`--window-size=${config.screenWidth},${config.screenHeight}`);
|
|
20
|
+
this.browser = await chromium.puppeteer.launch({
|
|
21
|
+
executablePath: process.env.ENVIRONMENT === 'LOCAL' ? undefined : await chromium.executablePath,
|
|
22
|
+
args,
|
|
23
|
+
ignoreDefaultArgs: ["--enable-automation"],
|
|
24
|
+
defaultViewport: process.env.ENVIRONMENT === 'LOCAL' ? null : {
|
|
25
|
+
width: config.screenWidth,
|
|
26
|
+
height: config.screenHeight
|
|
27
|
+
},
|
|
28
|
+
headless: process.env.ENVIRONMENT == 'LOCAL' ? false : chromium.headless
|
|
29
|
+
});
|
|
30
|
+
this.defaultPage = (await this.browser.pages())[0];
|
|
31
|
+
await this.defaultPage.goto(config.baseURL, { waitUntil: 'networkidle0' });
|
|
32
|
+
await this.defaultPage.waitForNetworkIdle();
|
|
33
|
+
}
|
|
34
|
+
async close() {
|
|
35
|
+
if (this.browser) {
|
|
36
|
+
let pages = await this.browser.pages();
|
|
37
|
+
await Promise.all(pages.map((page) => page.close()));
|
|
38
|
+
await this.browser.close();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async run(event, callback, featureName = 'Test feature', scenarioName = 'Test scenario', uploadModel, close) {
|
|
42
|
+
try {
|
|
43
|
+
if (uploadModel === undefined)
|
|
44
|
+
uploadModel = auxta.getUploadModel();
|
|
45
|
+
if (close === undefined)
|
|
46
|
+
close = Puppeteer.setupHeader(event, uploadModel);
|
|
47
|
+
let screenshotBuffer;
|
|
48
|
+
let errMessage;
|
|
49
|
+
let statusCode = 200;
|
|
50
|
+
let consoleStack = [];
|
|
51
|
+
try {
|
|
52
|
+
await log.push('When', `Starting puppeteer process`, StatusOfStep.PASSED);
|
|
53
|
+
await this.startBrowser();
|
|
54
|
+
this.defaultPage.on('console', message => consoleStack.push(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
|
|
55
|
+
.on('pageerror', ({ message }) => consoleStack.push(message))
|
|
56
|
+
.on('response', response => consoleStack.push(`${response.status()} ${response.url()}`))
|
|
57
|
+
.on('requestfailed', request => consoleStack.push(`${request.failure() !== null ? request.failure()?.errorText : ""} ${request.url()}`));
|
|
58
|
+
await callback(event);
|
|
59
|
+
log.push('When', `Finished puppeteer process`, StatusOfStep.PASSED);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
console.log("Error", err);
|
|
63
|
+
errMessage = err;
|
|
64
|
+
statusCode = 500;
|
|
65
|
+
screenshotBuffer = await captureScreenshot();
|
|
66
|
+
log.push('When', `Finished puppeteer process`, StatusOfStep.FAILED);
|
|
67
|
+
await postNotificationsOnFail(uploadModel);
|
|
68
|
+
}
|
|
69
|
+
let url = this.defaultPage.url();
|
|
70
|
+
if (close)
|
|
71
|
+
await this.close();
|
|
72
|
+
await onTestEnd(uploadModel, featureName, scenarioName, statusCode, screenshotBuffer, !errMessage ? undefined : {
|
|
73
|
+
currentPageUrl: url,
|
|
74
|
+
console: consoleStack,
|
|
75
|
+
error: errMessage
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
console.log("Lib error:", e);
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
log.clear();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async runRPA(event, callback, close) {
|
|
86
|
+
let errMessage;
|
|
87
|
+
try {
|
|
88
|
+
if (close === undefined) {
|
|
89
|
+
if (event.queryStringParameters.close) {
|
|
90
|
+
close = event.queryStringParameters.close === "true";
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
close = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
let consoleStack = [];
|
|
97
|
+
try {
|
|
98
|
+
await log.push('When', `Starting puppeteer process`, StatusOfStep.PASSED);
|
|
99
|
+
await this.startBrowser();
|
|
100
|
+
this.defaultPage.on('console', message => consoleStack.push(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
|
|
101
|
+
.on('pageerror', ({ message }) => consoleStack.push(message))
|
|
102
|
+
.on('response', response => consoleStack.push(`${response.status()} ${response.url()}`))
|
|
103
|
+
.on('requestfailed', request => consoleStack.push(`${request.failure() !== null ? request.failure()?.errorText : ""} ${request.url()}`));
|
|
104
|
+
await callback(event);
|
|
105
|
+
log.push('When', `Finished puppeteer process`, StatusOfStep.PASSED);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
errMessage = err;
|
|
109
|
+
log.push('When', `Finished puppeteer process`, StatusOfStep.FAILED);
|
|
110
|
+
return errMessage;
|
|
111
|
+
}
|
|
112
|
+
if (close)
|
|
113
|
+
await this.close();
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
console.log("Lib error:", e);
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
log.clear();
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
static setupHeader(event, uploadModel) {
|
|
124
|
+
let close = true;
|
|
125
|
+
if (process.env.ENVIRONMENT !== 'LOCAL' && event.body) {
|
|
126
|
+
const body = JSON.parse(event.body);
|
|
127
|
+
uploadModel.reportId = body.reportId;
|
|
128
|
+
uploadModel.nextSuites = body.nextSuites;
|
|
129
|
+
}
|
|
130
|
+
else if (event.queryStringParameters.close) {
|
|
131
|
+
close = event.queryStringParameters.close === "true";
|
|
132
|
+
}
|
|
133
|
+
return close;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export default new Puppeteer();
|