@auxcode/auxta 1.3.113 → 1.3.114
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 +149 -149
- package/build/AuxTA.d.ts +0 -2
- package/build/AuxTA.js +6 -4
- package/build/auxta/models/upload.model.d.ts +4 -1
- package/build/auxta/models/upload.model.js +8 -1
- package/build/macros/helpers/code.helper.js +34 -34
- package/build/macros/helpers/emailHelper.js +2 -2
- package/build/macros/helpers/extend-default-page.js +11 -8
- package/build/puppeteer/puppeteer.d.ts +2 -2
- package/build/puppeteer/puppeteer.js +42 -25
- package/package.json +35 -35
package/README.md
CHANGED
|
@@ -1,149 +1,149 @@
|
|
|
1
|
-
# AuxTA
|
|
2
|
-
|
|
3
|
-
## Guidelines for the Frontend Programmers
|
|
4
|
-
|
|
5
|
-
Every HTML element on a web page can be a selector, which can be used to create AuxTA scenarios.
|
|
6
|
-
|
|
7
|
-
Of course, not all HTML elemets are used as selectors to create AuxTA scenarios.
|
|
8
|
-
|
|
9
|
-
Those HTML elements, which will be used as selectors for AuxTA scenarios, should have a Unique ID. This way AuxTA scenarios are created the fastest.
|
|
10
|
-
|
|
11
|
-
The best candidate for this is the HTML "id" attribute.
|
|
12
|
-
|
|
13
|
-
The ID value should reflect the functionality of the place.
|
|
14
|
-
|
|
15
|
-
To create a unique ID, make it multipart, beginning with more general parts which are guaranteed to be unique. This way one creates namespaces, which make it easier after that to end up with a unique ID.
|
|
16
|
-
|
|
17
|
-
For expmple:
|
|
18
|
-
|
|
19
|
-
id="shop_cart_button_submit"
|
|
20
|
-
|
|
21
|
-
More than one of the same element, For example several tables on one page, each should have a unique ID.
|
|
22
|
-
|
|
23
|
-
If it has nested elements they can have the same selectors as in the other elements, but it’s not necessary.
|
|
24
|
-
|
|
25
|
-
## Implementing
|
|
26
|
-
|
|
27
|
-
The main thing is a `scenario`.
|
|
28
|
-
|
|
29
|
-
`Scenarios` consts of `steps.
|
|
30
|
-
|
|
31
|
-
### Helpers
|
|
32
|
-
|
|
33
|
-
Change so that there is one function per helper file.
|
|
34
|
-
|
|
35
|
-
### Clicking
|
|
36
|
-
|
|
37
|
-
All clicks wait for the selector by default and timeout w/ the standard timeout unless different is specified.
|
|
38
|
-
|
|
39
|
-
`timeout` It is recommended to have a standard timeout for the whole scenario and not to define spefici. `TODO`
|
|
40
|
-
|
|
41
|
-
auxta.clickByText `TO BE FIXED BY GEORGE TO ADD THE WAIT FOR SELECTOR WHICH IS MISSING`
|
|
42
|
-
|
|
43
|
-
auxta.clickByXPath
|
|
44
|
-
|
|
45
|
-
auxta.clickByClass
|
|
46
|
-
|
|
47
|
-
auxta.click() `THINK TO MAKE` `TODO`
|
|
48
|
-
|
|
49
|
-
waitforseelctorbytext `depreciated`
|
|
50
|
-
|
|
51
|
-
### Working with Tab
|
|
52
|
-
|
|
53
|
-
...
|
|
54
|
-
|
|
55
|
-
### Complex Workflows
|
|
56
|
-
|
|
57
|
-
#### Use Bulilding Blocks
|
|
58
|
-
|
|
59
|
-
Building Blocks do one simple thing each and allow you to build State Scripts and Scenrios.
|
|
60
|
-
|
|
61
|
-
#### Use State Scripts
|
|
62
|
-
|
|
63
|
-
State Scripts bring the system to a desired state from which a specific scenario begins.
|
|
64
|
-
|
|
65
|
-
#### Email
|
|
66
|
-
|
|
67
|
-
* (AuxTA) We do some action on the website.
|
|
68
|
-
* (Website) Sends an email to the email address of the user who did the action.
|
|
69
|
-
* (AuxTA) Should check that that the email was correctly sent. So we check:
|
|
70
|
-
* `auxta.checkMail(_from_name_, _from_email_, _subject_, _body_text_)`
|
|
71
|
-
* The email login is in the main config of the test suite.
|
|
72
|
-
* email
|
|
73
|
-
* API TOKEN
|
|
74
|
-
* For the moment we do it synchroneous (AuxTA waits for the email).
|
|
75
|
-
* The email must be newser than the time of the action on the Website.
|
|
76
|
-
* Must be _from_name_ (substring)
|
|
77
|
-
* Must be _from_email_ (substring)
|
|
78
|
-
* Must have _subject_ (substring)
|
|
79
|
-
* Must cotnain _body_text_ (substring)
|
|
80
|
-
* Quality of Service, if the email does not arrive w/in eg. 5 minutes we return an error w/ timeout.
|
|
81
|
-
*
|
|
82
|
-
* `auxta.clickInMail(_from_name_, _from_email_, _subject_, _click_on_)`
|
|
83
|
-
|
|
84
|
-
## Running
|
|
85
|
-
|
|
86
|
-
* Create a main function that calls the run() function which starts all tests
|
|
87
|
-
* Create a function for each test that calls the `auxtaPuppeteer.run(event, callback, featureName, scenarioName)`
|
|
88
|
-
function
|
|
89
|
-
|
|
90
|
-
## Puppeteer
|
|
91
|
-
|
|
92
|
-
https://pptr.dev
|
|
93
|
-
|
|
94
|
-
https://github.com/puppeteer/puppeteer
|
|
95
|
-
|
|
96
|
-
## Install
|
|
97
|
-
|
|
98
|
-
npm i
|
|
99
|
-
|
|
100
|
-
## Setup
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
{
|
|
104
|
-
# All background functions that will be run, listed
|
|
105
|
-
"suitesList": [
|
|
106
|
-
"{filename}-background"
|
|
107
|
-
],
|
|
108
|
-
# The tested site's url
|
|
109
|
-
"baseURL": "https://{sitename}/",
|
|
110
|
-
# The url where the tests are ran
|
|
111
|
-
"testsURL": "https://{sitename}/",
|
|
112
|
-
# The organization's name
|
|
113
|
-
"organization": "string",
|
|
114
|
-
# The digital product's name
|
|
115
|
-
"digitalProduct": "bedrijfsfinanciering.com",
|
|
116
|
-
# Max timeout in milliseconds
|
|
117
|
-
# Default 1000
|
|
118
|
-
"timeout": 1000,
|
|
119
|
-
# The credentials of the user that uploads the tests to the site
|
|
120
|
-
"email": "string",
|
|
121
|
-
"password": "string",
|
|
122
|
-
"token": "string"
|
|
123
|
-
# Screen width and height used in the testing
|
|
124
|
-
# Allows testing from mobile devices screens
|
|
125
|
-
"screenWidth": 1920,
|
|
126
|
-
"screenHeight": 1080,
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
##backlog
|
|
132
|
-
Implement a way to scout the skipped steps w/ $failed=true, $skipped=++
|
|
133
|
-
control click go to source directory
|
|
134
|
-
|
|
135
|
-
##Improvements
|
|
136
|
-
|
|
137
|
-
* introduce the new headless mode, by Puppeteer.
|
|
138
|
-
|
|
139
|
-
### platform improvements
|
|
140
|
-
|
|
141
|
-
Also some improvements to the platform in general:
|
|
142
|
-
|
|
143
|
-
* get the console state after a fail, this would increase the value of each failed report.
|
|
144
|
-
|
|
145
|
-
# Backlog
|
|
146
|
-
|
|
147
|
-
## 13 October 2024
|
|
148
|
-
|
|
149
|
-
Make so that there can be more than one helper file and that we have one function per helper file.
|
|
1
|
+
# AuxTA
|
|
2
|
+
|
|
3
|
+
## Guidelines for the Frontend Programmers
|
|
4
|
+
|
|
5
|
+
Every HTML element on a web page can be a selector, which can be used to create AuxTA scenarios.
|
|
6
|
+
|
|
7
|
+
Of course, not all HTML elemets are used as selectors to create AuxTA scenarios.
|
|
8
|
+
|
|
9
|
+
Those HTML elements, which will be used as selectors for AuxTA scenarios, should have a Unique ID. This way AuxTA scenarios are created the fastest.
|
|
10
|
+
|
|
11
|
+
The best candidate for this is the HTML "id" attribute.
|
|
12
|
+
|
|
13
|
+
The ID value should reflect the functionality of the place.
|
|
14
|
+
|
|
15
|
+
To create a unique ID, make it multipart, beginning with more general parts which are guaranteed to be unique. This way one creates namespaces, which make it easier after that to end up with a unique ID.
|
|
16
|
+
|
|
17
|
+
For expmple:
|
|
18
|
+
|
|
19
|
+
id="shop_cart_button_submit"
|
|
20
|
+
|
|
21
|
+
More than one of the same element, For example several tables on one page, each should have a unique ID.
|
|
22
|
+
|
|
23
|
+
If it has nested elements they can have the same selectors as in the other elements, but it’s not necessary.
|
|
24
|
+
|
|
25
|
+
## Implementing
|
|
26
|
+
|
|
27
|
+
The main thing is a `scenario`.
|
|
28
|
+
|
|
29
|
+
`Scenarios` consts of `steps.
|
|
30
|
+
|
|
31
|
+
### Helpers
|
|
32
|
+
|
|
33
|
+
Change so that there is one function per helper file.
|
|
34
|
+
|
|
35
|
+
### Clicking
|
|
36
|
+
|
|
37
|
+
All clicks wait for the selector by default and timeout w/ the standard timeout unless different is specified.
|
|
38
|
+
|
|
39
|
+
`timeout` It is recommended to have a standard timeout for the whole scenario and not to define spefici. `TODO`
|
|
40
|
+
|
|
41
|
+
auxta.clickByText `TO BE FIXED BY GEORGE TO ADD THE WAIT FOR SELECTOR WHICH IS MISSING`
|
|
42
|
+
|
|
43
|
+
auxta.clickByXPath
|
|
44
|
+
|
|
45
|
+
auxta.clickByClass
|
|
46
|
+
|
|
47
|
+
auxta.click() `THINK TO MAKE` `TODO`
|
|
48
|
+
|
|
49
|
+
waitforseelctorbytext `depreciated`
|
|
50
|
+
|
|
51
|
+
### Working with Tab
|
|
52
|
+
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
### Complex Workflows
|
|
56
|
+
|
|
57
|
+
#### Use Bulilding Blocks
|
|
58
|
+
|
|
59
|
+
Building Blocks do one simple thing each and allow you to build State Scripts and Scenrios.
|
|
60
|
+
|
|
61
|
+
#### Use State Scripts
|
|
62
|
+
|
|
63
|
+
State Scripts bring the system to a desired state from which a specific scenario begins.
|
|
64
|
+
|
|
65
|
+
#### Email
|
|
66
|
+
|
|
67
|
+
* (AuxTA) We do some action on the website.
|
|
68
|
+
* (Website) Sends an email to the email address of the user who did the action.
|
|
69
|
+
* (AuxTA) Should check that that the email was correctly sent. So we check:
|
|
70
|
+
* `auxta.checkMail(_from_name_, _from_email_, _subject_, _body_text_)`
|
|
71
|
+
* The email login is in the main config of the test suite.
|
|
72
|
+
* email
|
|
73
|
+
* API TOKEN
|
|
74
|
+
* For the moment we do it synchroneous (AuxTA waits for the email).
|
|
75
|
+
* The email must be newser than the time of the action on the Website.
|
|
76
|
+
* Must be _from_name_ (substring)
|
|
77
|
+
* Must be _from_email_ (substring)
|
|
78
|
+
* Must have _subject_ (substring)
|
|
79
|
+
* Must cotnain _body_text_ (substring)
|
|
80
|
+
* Quality of Service, if the email does not arrive w/in eg. 5 minutes we return an error w/ timeout.
|
|
81
|
+
*
|
|
82
|
+
* `auxta.clickInMail(_from_name_, _from_email_, _subject_, _click_on_)`
|
|
83
|
+
|
|
84
|
+
## Running
|
|
85
|
+
|
|
86
|
+
* Create a main function that calls the run() function which starts all tests
|
|
87
|
+
* Create a function for each test that calls the `auxtaPuppeteer.run(event, callback, featureName, scenarioName)`
|
|
88
|
+
function
|
|
89
|
+
|
|
90
|
+
## Puppeteer
|
|
91
|
+
|
|
92
|
+
https://pptr.dev
|
|
93
|
+
|
|
94
|
+
https://github.com/puppeteer/puppeteer
|
|
95
|
+
|
|
96
|
+
## Install
|
|
97
|
+
|
|
98
|
+
npm i
|
|
99
|
+
|
|
100
|
+
## Setup
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
{
|
|
104
|
+
# All background functions that will be run, listed
|
|
105
|
+
"suitesList": [
|
|
106
|
+
"{filename}-background"
|
|
107
|
+
],
|
|
108
|
+
# The tested site's url
|
|
109
|
+
"baseURL": "https://{sitename}/",
|
|
110
|
+
# The url where the tests are ran
|
|
111
|
+
"testsURL": "https://{sitename}/",
|
|
112
|
+
# The organization's name
|
|
113
|
+
"organization": "string",
|
|
114
|
+
# The digital product's name
|
|
115
|
+
"digitalProduct": "bedrijfsfinanciering.com",
|
|
116
|
+
# Max timeout in milliseconds
|
|
117
|
+
# Default 1000
|
|
118
|
+
"timeout": 1000,
|
|
119
|
+
# The credentials of the user that uploads the tests to the site
|
|
120
|
+
"email": "string",
|
|
121
|
+
"password": "string",
|
|
122
|
+
"token": "string"
|
|
123
|
+
# Screen width and height used in the testing
|
|
124
|
+
# Allows testing from mobile devices screens
|
|
125
|
+
"screenWidth": 1920,
|
|
126
|
+
"screenHeight": 1080,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
##backlog
|
|
132
|
+
Implement a way to scout the skipped steps w/ $failed=true, $skipped=++
|
|
133
|
+
control click go to source directory
|
|
134
|
+
|
|
135
|
+
##Improvements
|
|
136
|
+
|
|
137
|
+
* introduce the new headless mode, by Puppeteer.
|
|
138
|
+
|
|
139
|
+
### platform improvements
|
|
140
|
+
|
|
141
|
+
Also some improvements to the platform in general:
|
|
142
|
+
|
|
143
|
+
* get the console state after a fail, this would increase the value of each failed report.
|
|
144
|
+
|
|
145
|
+
# Backlog
|
|
146
|
+
|
|
147
|
+
## 13 October 2024
|
|
148
|
+
|
|
149
|
+
Make so that there can be more than one helper file and that we have one function per helper file.
|
package/build/AuxTA.d.ts
CHANGED
|
@@ -50,8 +50,6 @@ declare class AuxTA extends FunctionHelper {
|
|
|
50
50
|
reportId: string | undefined;
|
|
51
51
|
currentSuite: string | undefined;
|
|
52
52
|
retries: string;
|
|
53
|
-
} | {
|
|
54
|
-
statusCode: number;
|
|
55
53
|
} | undefined>;
|
|
56
54
|
startBrowserRPA(event: any, callback: any, baseURL: string, fileName?: string): Promise<any>;
|
|
57
55
|
getUploadModel(): UploadModel;
|
package/build/AuxTA.js
CHANGED
|
@@ -108,8 +108,8 @@ class AuxTA extends code_helper_1.FunctionHelper {
|
|
|
108
108
|
return (0, start_suite_helper_1.startSuite)(suites, reportId || (yield (0, report_service_1.createEmptyReport)(this.uploadModel)));
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
-
startBrowser(
|
|
112
|
-
return __awaiter(this,
|
|
111
|
+
startBrowser(event_1, callback_1, feature_1, scenario_1, overrideConfig_1) {
|
|
112
|
+
return __awaiter(this, arguments, void 0, function* (event, callback, feature, scenario, overrideConfig, singleFeature = false, fileName = '') {
|
|
113
113
|
this.changeModelData(overrideConfig);
|
|
114
114
|
if (singleFeature && process.env.ENVIRONMENT !== 'LOCAL') {
|
|
115
115
|
this.uploadModel.reportId = yield (0, report_service_1.createEmptyReport)(this.uploadModel);
|
|
@@ -121,8 +121,8 @@ class AuxTA extends code_helper_1.FunctionHelper {
|
|
|
121
121
|
return this.puppeteer.run(event, callback, feature, scenario);
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
|
-
startBrowserRPA(
|
|
125
|
-
return __awaiter(this,
|
|
124
|
+
startBrowserRPA(event_1, callback_1, baseURL_1) {
|
|
125
|
+
return __awaiter(this, arguments, void 0, function* (event, callback, baseURL, fileName = '') {
|
|
126
126
|
this.changeModelData({
|
|
127
127
|
baseURL: baseURL,
|
|
128
128
|
environment: '',
|
|
@@ -147,6 +147,8 @@ class AuxTA extends code_helper_1.FunctionHelper {
|
|
|
147
147
|
this.uploadModel.bucket = overrideConfig.bucket;
|
|
148
148
|
if (overrideConfig.isOfficial !== undefined)
|
|
149
149
|
this.uploadModel.isOfficial = overrideConfig.isOfficial;
|
|
150
|
+
if (overrideConfig.toRetry !== undefined)
|
|
151
|
+
this.uploadModel.toRetry = overrideConfig.toRetry;
|
|
150
152
|
this.config = (0, config_1.setupOverrideConfig)(overrideConfig);
|
|
151
153
|
}
|
|
152
154
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare class UploadModel {
|
|
2
2
|
private readonly _organization;
|
|
3
|
-
constructor(org: string, baseUrl: string, digitalProduct: string, environment: string, bucket: string, isOfficial: boolean);
|
|
3
|
+
constructor(org: string, baseUrl: string, digitalProduct: string, environment: string, bucket: string, isOfficial: boolean, toRetry?: boolean);
|
|
4
4
|
private _reportId;
|
|
5
5
|
get reportId(): string;
|
|
6
6
|
set reportId(value: string);
|
|
@@ -34,5 +34,8 @@ export declare class UploadModel {
|
|
|
34
34
|
private _isOfficial;
|
|
35
35
|
get isOfficial(): boolean;
|
|
36
36
|
set isOfficial(value: boolean);
|
|
37
|
+
private _toRetry;
|
|
38
|
+
get toRetry(): boolean;
|
|
39
|
+
set toRetry(value: boolean);
|
|
37
40
|
get organization(): string;
|
|
38
41
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UploadModel = void 0;
|
|
4
4
|
class UploadModel {
|
|
5
|
-
constructor(org, baseUrl, digitalProduct, environment, bucket, isOfficial) {
|
|
5
|
+
constructor(org, baseUrl, digitalProduct, environment, bucket, isOfficial, toRetry = false) {
|
|
6
6
|
this._reportId = '';
|
|
7
7
|
this._nextSuites = [];
|
|
8
8
|
this._currentSuite = '';
|
|
@@ -15,6 +15,7 @@ class UploadModel {
|
|
|
15
15
|
this._featureName = '';
|
|
16
16
|
this._scenarioName = '';
|
|
17
17
|
this._isOfficial = isOfficial;
|
|
18
|
+
this._toRetry = toRetry;
|
|
18
19
|
}
|
|
19
20
|
get reportId() {
|
|
20
21
|
return this._reportId;
|
|
@@ -82,6 +83,12 @@ class UploadModel {
|
|
|
82
83
|
set isOfficial(value) {
|
|
83
84
|
this._isOfficial = value;
|
|
84
85
|
}
|
|
86
|
+
get toRetry() {
|
|
87
|
+
return this._toRetry;
|
|
88
|
+
}
|
|
89
|
+
set toRetry(value) {
|
|
90
|
+
this._toRetry = value;
|
|
91
|
+
}
|
|
85
92
|
get organization() {
|
|
86
93
|
return this._organization;
|
|
87
94
|
}
|
|
@@ -43,16 +43,16 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
43
43
|
return response;
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
-
screenshot(
|
|
47
|
-
return __awaiter(this,
|
|
46
|
+
screenshot() {
|
|
47
|
+
return __awaiter(this, arguments, void 0, function* (page = puppeteer_1.default.defaultPage) {
|
|
48
48
|
const screenshotBuffer = yield (0, screenshot_helper_1.captureScreenshotPage)(page);
|
|
49
49
|
if (screenshotBuffer) {
|
|
50
50
|
return screenshotBuffer;
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
|
-
screenshotCompare(
|
|
55
|
-
return __awaiter(this,
|
|
54
|
+
screenshotCompare(key_1) {
|
|
55
|
+
return __awaiter(this, arguments, void 0, function* (key, threshold = 0.1, page = puppeteer_1.default.defaultPage) {
|
|
56
56
|
if (process.env.ENVIRONMENT !== 'LOCAL') {
|
|
57
57
|
const screenshotBuffer = yield (0, screenshot_helper_1.captureScreenshotPage)(page);
|
|
58
58
|
if (screenshotBuffer) {
|
|
@@ -74,8 +74,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
74
74
|
suggest(name) {
|
|
75
75
|
log_service_1.default.addSuggestion(name);
|
|
76
76
|
}
|
|
77
|
-
performanceFail(
|
|
78
|
-
return __awaiter(this,
|
|
77
|
+
performanceFail(name_1) {
|
|
78
|
+
return __awaiter(this, arguments, void 0, function* (name, screenshot = true, page = puppeteer_1.default.defaultPage) {
|
|
79
79
|
if (screenshot) {
|
|
80
80
|
const screenshotBuffer = yield (0, screenshot_helper_1.captureScreenshotPage)(page);
|
|
81
81
|
log_service_1.default.addPerformanceFail(name, screenshotBuffer);
|
|
@@ -85,8 +85,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
|
-
clickByText(
|
|
89
|
-
return __awaiter(this,
|
|
88
|
+
clickByText(selector_1, text_1) {
|
|
89
|
+
return __awaiter(this, arguments, void 0, function* (selector, text, dotOrText = '.', options = {}, page = puppeteer_1.default.defaultPage, time = this.defaultTimeout, log_message = true) {
|
|
90
90
|
const message = `I clicked on the '${text}' '${selector}'`;
|
|
91
91
|
try {
|
|
92
92
|
const [linkHandlers] = yield page.$$(`xpath/.//${selector}[contains(${dotOrText},"${text}")]`);
|
|
@@ -106,8 +106,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
106
106
|
}
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
|
-
clickByTextWithClass(
|
|
110
|
-
return __awaiter(this,
|
|
109
|
+
clickByTextWithClass(class_selector_1, class_name_1, selector_1, text_1) {
|
|
110
|
+
return __awaiter(this, arguments, void 0, function* (class_selector, class_name, selector, text, dotOrText = '.', page = puppeteer_1.default.defaultPage) {
|
|
111
111
|
const message = `I click on the '${text}' '${selector}'`;
|
|
112
112
|
try {
|
|
113
113
|
const [linkHandlers] = yield page.$$(`xpath/.//${class_selector}[contains(@class,${this.getEscapedText(class_name)})]//${selector}[contains(${dotOrText},"${text}")]`);
|
|
@@ -123,8 +123,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
123
123
|
throw new Error(message);
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
|
-
waitForSelectorWithText(
|
|
127
|
-
return __awaiter(this,
|
|
126
|
+
waitForSelectorWithText(selector_1, text_1) {
|
|
127
|
+
return __awaiter(this, arguments, void 0, function* (selector, text, dotOrText = '.', page = puppeteer_1.default.defaultPage) {
|
|
128
128
|
const message = `I check for '${text}' on the current page`;
|
|
129
129
|
try {
|
|
130
130
|
yield page.waitForSelector(selector, {
|
|
@@ -142,13 +142,13 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
142
142
|
throw new Error(message);
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
timeout(
|
|
146
|
-
return __awaiter(this,
|
|
145
|
+
timeout() {
|
|
146
|
+
return __awaiter(this, arguments, void 0, function* (timeout = this.defaultTimeout) {
|
|
147
147
|
yield new Promise(r => setTimeout(r, timeout));
|
|
148
148
|
});
|
|
149
149
|
}
|
|
150
|
-
waitForSelector(
|
|
151
|
-
return __awaiter(this,
|
|
150
|
+
waitForSelector(option_1, selector_1) {
|
|
151
|
+
return __awaiter(this, arguments, void 0, function* (option, selector, time = this.defaultTimeout, page = puppeteer_1.default.defaultPage, log_message = true) {
|
|
152
152
|
const message = `I checked for the '${selector}' element to be ${option}`;
|
|
153
153
|
try {
|
|
154
154
|
yield page.waitForSelector(selector, {
|
|
@@ -167,8 +167,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
167
167
|
}
|
|
168
168
|
});
|
|
169
169
|
}
|
|
170
|
-
urlContains(
|
|
171
|
-
return __awaiter(this,
|
|
170
|
+
urlContains(selector_1) {
|
|
171
|
+
return __awaiter(this, arguments, void 0, function* (selector, page = puppeteer_1.default.defaultPage) {
|
|
172
172
|
const url = page.url();
|
|
173
173
|
let message = `I am on the ${selector} page`;
|
|
174
174
|
if (!url.includes(selector)) {
|
|
@@ -178,8 +178,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
178
178
|
log_service_1.default.push('And', log_service_1.default.tag, message, status_of_step_1.StatusOfStep.PASSED);
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
|
-
forceState(
|
|
182
|
-
return __awaiter(this,
|
|
181
|
+
forceState(selector_1, state_1) {
|
|
182
|
+
return __awaiter(this, arguments, void 0, function* (selector, state, index = 0, page = puppeteer_1.default.defaultPage) {
|
|
183
183
|
this.cdp = yield page.target().createCDPSession();
|
|
184
184
|
const docNodeId = (yield this.cdp.send('DOM.getDocument')).root.nodeId;
|
|
185
185
|
const nodeIds = (yield this.cdp.send('DOM.querySelectorAll', {
|
|
@@ -194,18 +194,18 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
196
|
endForceState() {
|
|
197
|
-
var _a;
|
|
198
197
|
return __awaiter(this, void 0, void 0, function* () {
|
|
198
|
+
var _a;
|
|
199
199
|
(_a = this.cdp) === null || _a === void 0 ? void 0 : _a.detach();
|
|
200
200
|
});
|
|
201
201
|
}
|
|
202
|
-
pressEnter(
|
|
203
|
-
return __awaiter(this,
|
|
202
|
+
pressEnter() {
|
|
203
|
+
return __awaiter(this, arguments, void 0, function* (page = puppeteer_1.default.defaultPage) {
|
|
204
204
|
yield page.keyboard.press('Enter');
|
|
205
205
|
});
|
|
206
206
|
}
|
|
207
|
-
emulate(
|
|
208
|
-
return __awaiter(this,
|
|
207
|
+
emulate(phone_name_1) {
|
|
208
|
+
return __awaiter(this, arguments, void 0, function* (phone_name, page = puppeteer_1.default.defaultPage) {
|
|
209
209
|
const phone = puppeteer_2.KnownDevices[phone_name];
|
|
210
210
|
yield page.emulate(phone);
|
|
211
211
|
});
|
|
@@ -216,8 +216,8 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
216
216
|
yield puppeteer_1.default.startBrowser();
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
|
-
clickAndWaitForPageToBeCreated(
|
|
220
|
-
return __awaiter(this,
|
|
219
|
+
clickAndWaitForPageToBeCreated(selector_1) {
|
|
220
|
+
return __awaiter(this, arguments, void 0, function* (selector, page = puppeteer_1.default.defaultPage, newPage) {
|
|
221
221
|
if (newPage) {
|
|
222
222
|
const nav = new Promise(res => page.browser().on('targetcreated', res));
|
|
223
223
|
yield page.click(selector);
|
|
@@ -228,23 +228,23 @@ class FunctionHelper extends extend_default_page_1.ExtendDefaultPage {
|
|
|
228
228
|
}
|
|
229
229
|
});
|
|
230
230
|
}
|
|
231
|
-
waitForResponse(
|
|
232
|
-
return __awaiter(this,
|
|
231
|
+
waitForResponse(name_1) {
|
|
232
|
+
return __awaiter(this, arguments, void 0, function* (name, wait = true, page = puppeteer_1.default.defaultPage) {
|
|
233
233
|
if (wait) {
|
|
234
234
|
yield page.waitForResponse(response => response.url().includes(name));
|
|
235
235
|
this.log('Then', `I wait for response with name: ${name}`, status_of_step_1.StatusOfStep.PASSED);
|
|
236
236
|
}
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
|
-
closeLastPage(
|
|
240
|
-
return __awaiter(this,
|
|
239
|
+
closeLastPage() {
|
|
240
|
+
return __awaiter(this, arguments, void 0, function* (page = puppeteer_1.default.defaultPage) {
|
|
241
241
|
const pages = yield page.browser().pages();
|
|
242
242
|
yield pages[pages.length - 1].close();
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
|
-
microsoftLogin(
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
microsoftLogin(button_1, email_1, password_1) {
|
|
246
|
+
return __awaiter(this, arguments, void 0, function* (button, email, password, page = puppeteer_1.default.defaultPage, newPage = true, staySignIn = true) {
|
|
247
|
+
var _a;
|
|
248
248
|
const email_input = 'input[type="email"]';
|
|
249
249
|
const password_input = 'input[type="password"]';
|
|
250
250
|
yield this.clickAndWaitForPageToBeCreated(button, page, newPage);
|
|
@@ -17,8 +17,8 @@ const log_service_1 = __importDefault(require("../../auxta/services/log.service"
|
|
|
17
17
|
const AuxTA_1 = require("../../AuxTA");
|
|
18
18
|
const report_service_1 = require("../../auxta/services/report.service");
|
|
19
19
|
class EmailHelper {
|
|
20
|
-
verifyEmail(
|
|
21
|
-
return __awaiter(this,
|
|
20
|
+
verifyEmail(from_name_1, from_email_1, subject_1, body_1) {
|
|
21
|
+
return __awaiter(this, arguments, void 0, function* (from_name, from_email, subject, body, link = false) {
|
|
22
22
|
try {
|
|
23
23
|
log_service_1.default.push('Then', log_service_1.default.tag, `waiting 35 seconds`, AuxTA_1.StepStatus.PASSED);
|
|
24
24
|
yield new Promise(r => setTimeout(r, 35000));
|
|
@@ -20,8 +20,8 @@ class ExtendDefaultPage {
|
|
|
20
20
|
constructor() {
|
|
21
21
|
this.defaultTimeout = config_1.config.timeout;
|
|
22
22
|
}
|
|
23
|
-
extend_page_functions(
|
|
24
|
-
return __awaiter(this,
|
|
23
|
+
extend_page_functions(page_1) {
|
|
24
|
+
return __awaiter(this, arguments, void 0, function* (page, time = this.defaultTimeout) {
|
|
25
25
|
this.defaultTimeout = config_1.config.timeout;
|
|
26
26
|
const { goto: original_goto, click: original_click, type: original_type, waitForNetworkIdle: original_waitForNetworkIdle } = page;
|
|
27
27
|
page.goto = function goto(url, options) {
|
|
@@ -29,7 +29,8 @@ class ExtendDefaultPage {
|
|
|
29
29
|
return original_goto.apply(page, arguments);
|
|
30
30
|
};
|
|
31
31
|
page.click = function click(selector, options) {
|
|
32
|
-
|
|
32
|
+
var arguments_1 = arguments;
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
34
|
try {
|
|
34
35
|
yield page.waitForSelector(selector, {
|
|
35
36
|
timeout: time
|
|
@@ -37,7 +38,7 @@ class ExtendDefaultPage {
|
|
|
37
38
|
let elementName = yield page.$eval(selector, (e) => e.textContent);
|
|
38
39
|
if (!elementName || elementName === ' ')
|
|
39
40
|
elementName = selector;
|
|
40
|
-
yield original_click.apply(page,
|
|
41
|
+
yield original_click.apply(page, arguments_1);
|
|
41
42
|
log_service_1.default.push('Then', log_service_1.default.tag, `I click on the '${elementName}'`, status_of_step_1.StatusOfStep.PASSED);
|
|
42
43
|
}
|
|
43
44
|
catch (e) {
|
|
@@ -48,11 +49,12 @@ class ExtendDefaultPage {
|
|
|
48
49
|
});
|
|
49
50
|
};
|
|
50
51
|
page.waitForNetworkIdle = function waitForNetworkIdle(selector, option) {
|
|
51
|
-
|
|
52
|
+
var arguments_2 = arguments;
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
54
|
let message = 'I wait for the page to load';
|
|
53
55
|
let result;
|
|
54
56
|
try {
|
|
55
|
-
result = yield original_waitForNetworkIdle.apply(page,
|
|
57
|
+
result = yield original_waitForNetworkIdle.apply(page, arguments_2);
|
|
56
58
|
log_service_1.default.push('Then', log_service_1.default.tag, message, status_of_step_1.StatusOfStep.PASSED);
|
|
57
59
|
}
|
|
58
60
|
catch (e) {
|
|
@@ -63,12 +65,13 @@ class ExtendDefaultPage {
|
|
|
63
65
|
});
|
|
64
66
|
};
|
|
65
67
|
page.type = function type(field, value) {
|
|
66
|
-
|
|
68
|
+
var arguments_3 = arguments;
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
70
|
try {
|
|
68
71
|
yield page.waitForSelector(field, {
|
|
69
72
|
timeout: time
|
|
70
73
|
});
|
|
71
|
-
yield original_type.apply(page,
|
|
74
|
+
yield original_type.apply(page, arguments_3);
|
|
72
75
|
let elementName = yield page.$eval(field, (e) => e.textContent);
|
|
73
76
|
if (!elementName || elementName === ' ')
|
|
74
77
|
elementName = field;
|
|
@@ -6,6 +6,8 @@ export declare class Puppeteer {
|
|
|
6
6
|
private static setupHeader;
|
|
7
7
|
startBrowser(): Promise<void>;
|
|
8
8
|
close(): Promise<void>;
|
|
9
|
+
private initiateBrowser;
|
|
10
|
+
private logFail;
|
|
9
11
|
run(event: any, callback: any, featureName?: string, scenarioName?: string, uploadModel?: UploadModel): Promise<{
|
|
10
12
|
nextSuites?: undefined;
|
|
11
13
|
reportId?: undefined;
|
|
@@ -16,8 +18,6 @@ export declare class Puppeteer {
|
|
|
16
18
|
reportId: string | undefined;
|
|
17
19
|
currentSuite: string | undefined;
|
|
18
20
|
retries: string;
|
|
19
|
-
} | {
|
|
20
|
-
statusCode: number;
|
|
21
21
|
} | undefined>;
|
|
22
22
|
runRPA(event: any, callback: any, uploadModel?: UploadModel, close?: boolean): Promise<any>;
|
|
23
23
|
}
|
|
@@ -79,8 +79,24 @@ class Puppeteer {
|
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
initiateBrowser(consoleMessage, httpsMessage) {
|
|
83
83
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
yield this.startBrowser();
|
|
85
|
+
this.defaultPage.on('console', (message) => consoleMessage.push(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
|
|
86
|
+
.on('pageerror', ({ message }) => consoleMessage.push(message))
|
|
87
|
+
.on('response', (response) => httpsMessage.push(`${response.status()} ${response.url()}`))
|
|
88
|
+
.on('requestfailed', (request) => { var _a; return httpsMessage.push(`${request.failure() !== null ? (_a = request.failure()) === null || _a === void 0 ? void 0 : _a.errorText : ""} ${request.url()}`); });
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
logFail(consoleMessage) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const pages = yield this.defaultPage.browser().pages();
|
|
94
|
+
consoleMessage.push('pages');
|
|
95
|
+
consoleMessage.push(pages.length);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
run(event_1, callback_1) {
|
|
99
|
+
return __awaiter(this, arguments, void 0, function* (event, callback, featureName = 'Test feature', scenarioName = 'Test scenario', uploadModel) {
|
|
84
100
|
let close;
|
|
85
101
|
try {
|
|
86
102
|
if (uploadModel === undefined) {
|
|
@@ -95,44 +111,45 @@ class Puppeteer {
|
|
|
95
111
|
let statusCode = 200;
|
|
96
112
|
let consoleMessage = [];
|
|
97
113
|
let httpsMessage = [];
|
|
114
|
+
log_service_1.default.push('When', log_service_1.default.tag, `Starting puppeteer process`, status_of_step_1.StatusOfStep.PASSED);
|
|
98
115
|
try {
|
|
99
|
-
|
|
100
|
-
yield this.startBrowser();
|
|
101
|
-
this.defaultPage.on('console', (message) => consoleMessage.push(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
|
|
102
|
-
.on('pageerror', ({ message }) => consoleMessage.push(message))
|
|
103
|
-
.on('response', (response) => httpsMessage.push(`${response.status()} ${response.url()}`))
|
|
104
|
-
.on('requestfailed', (request) => { var _a; return httpsMessage.push(`${request.failure() !== null ? (_a = request.failure()) === null || _a === void 0 ? void 0 : _a.errorText : ""} ${request.url()}`); });
|
|
116
|
+
yield this.initiateBrowser(consoleMessage, httpsMessage);
|
|
105
117
|
yield callback(event);
|
|
106
118
|
log_service_1.default.push('When', log_service_1.default.tag, `Finished puppeteer process`, status_of_step_1.StatusOfStep.PASSED);
|
|
107
119
|
}
|
|
108
120
|
catch (err) {
|
|
109
121
|
console.log("Error message: \n", err);
|
|
110
122
|
if (process.env.ENVIRONMENT !== 'LOCAL') {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
if (uploadModel.toRetry) {
|
|
124
|
+
log_service_1.default.clear();
|
|
125
|
+
log_service_1.default.push('When', log_service_1.default.tag, `Retrying puppeteer process`, status_of_step_1.StatusOfStep.PASSED);
|
|
126
|
+
try {
|
|
127
|
+
yield this.close();
|
|
128
|
+
yield this.initiateBrowser(consoleMessage, httpsMessage);
|
|
129
|
+
yield callback(event);
|
|
130
|
+
log_service_1.default.push('When', log_service_1.default.tag, `Finished puppeteer process from the 2nd try`, status_of_step_1.StatusOfStep.PASSED);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
this.logFail(consoleMessage);
|
|
134
|
+
errMessage = err;
|
|
135
|
+
statusCode = 500;
|
|
136
|
+
screenshotBuffer = yield (0, screenshot_helper_1.captureScreenshot)();
|
|
137
|
+
log_service_1.default.push('When', log_service_1.default.tag, `Failed puppeteer process from the 2nd try`, status_of_step_1.StatusOfStep.FAILED);
|
|
124
138
|
}
|
|
125
|
-
return { statusCode: 204 };
|
|
126
139
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
140
|
+
else {
|
|
141
|
+
this.logFail(consoleMessage);
|
|
142
|
+
errMessage = err;
|
|
143
|
+
statusCode = 500;
|
|
144
|
+
screenshotBuffer = yield (0, screenshot_helper_1.captureScreenshot)();
|
|
145
|
+
log_service_1.default.push('When', log_service_1.default.tag, `Finished puppeteer process`, status_of_step_1.StatusOfStep.FAILED);
|
|
146
|
+
}
|
|
131
147
|
}
|
|
132
148
|
}
|
|
133
149
|
let url = this.defaultPage.url();
|
|
134
150
|
if (close)
|
|
135
151
|
yield this.close();
|
|
152
|
+
log_service_1.default.push('When', log_service_1.default.tag, `Finish line Status code: ${statusCode}`, status_of_step_1.StatusOfStep.PASSED);
|
|
136
153
|
return yield (0, report_hook_1.onTestEnd)(uploadModel, featureName, scenarioName, statusCode, screenshotBuffer, !errMessage ? undefined : {
|
|
137
154
|
currentPageUrl: url,
|
|
138
155
|
console: consoleMessage,
|
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@auxcode/auxta",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "./build/AuxTA.js",
|
|
6
|
-
"types": "./build/AuxTA.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"build/"
|
|
9
|
-
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"tsc": "tsc -p tsconfig.json",
|
|
12
|
-
"prepublish": "tsc",
|
|
13
|
-
"test": "npm run prepublish & node ./build/AuxTA.js"
|
|
14
|
-
},
|
|
15
|
-
"author": "auxcode",
|
|
16
|
-
"license": "ISC",
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@types/node": "^17.0.9",
|
|
19
|
-
"axios": "1.6.5",
|
|
20
|
-
"dotenv": "^10.0.0",
|
|
21
|
-
"dotenv-extended": "^2.9.0",
|
|
22
|
-
"fs": "^0.0.1-security",
|
|
23
|
-
"googleapis": "^118.0.0",
|
|
24
|
-
"js-base64": "^3.7.5",
|
|
25
|
-
"moment-timezone": "^0.5.45",
|
|
26
|
-
"node-2fa": "^2.0.3",
|
|
27
|
-
"nodemailer": "^6.9.9",
|
|
28
|
-
"puppeteer": "^22.0.0",
|
|
29
|
-
"readline": "^1.3.0",
|
|
30
|
-
"typescript": "^5.3.3"
|
|
31
|
-
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@babel/preset-typescript": "^7.23.3"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@auxcode/auxta",
|
|
3
|
+
"version": "1.3.114",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./build/AuxTA.js",
|
|
6
|
+
"types": "./build/AuxTA.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"build/"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"tsc": "tsc -p tsconfig.json",
|
|
12
|
+
"prepublish": "tsc",
|
|
13
|
+
"test": "npm run prepublish & node ./build/AuxTA.js"
|
|
14
|
+
},
|
|
15
|
+
"author": "auxcode",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@types/node": "^17.0.9",
|
|
19
|
+
"axios": "1.6.5",
|
|
20
|
+
"dotenv": "^10.0.0",
|
|
21
|
+
"dotenv-extended": "^2.9.0",
|
|
22
|
+
"fs": "^0.0.1-security",
|
|
23
|
+
"googleapis": "^118.0.0",
|
|
24
|
+
"js-base64": "^3.7.5",
|
|
25
|
+
"moment-timezone": "^0.5.45",
|
|
26
|
+
"node-2fa": "^2.0.3",
|
|
27
|
+
"nodemailer": "^6.9.9",
|
|
28
|
+
"puppeteer": "^22.0.0",
|
|
29
|
+
"readline": "^1.3.0",
|
|
30
|
+
"typescript": "^5.3.3"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@babel/preset-typescript": "^7.23.3"
|
|
34
|
+
}
|
|
35
|
+
}
|