codeceptjs 3.6.4-beta.2 → 3.6.4
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/lib/ai.js +47 -1
- package/lib/helper/AI.js +84 -7
- package/lib/helper/REST.js +33 -2
- package/lib/history.js +16 -3
- package/lib/pause.js +17 -3
- package/package.json +4 -4
- package/typings/index.d.ts +42 -19
- package/typings/promiseBasedTypes.d.ts +46 -5
- package/typings/types.d.ts +48 -5
package/lib/ai.js
CHANGED
|
@@ -31,6 +31,36 @@ const defaultPrompts = {
|
|
|
31
31
|
Here is HTML code of a page where the failure has happened: \n\n${html}`,
|
|
32
32
|
}];
|
|
33
33
|
},
|
|
34
|
+
|
|
35
|
+
generatePageObject: (html, extraPrompt = '', rootLocator = null) => [{
|
|
36
|
+
role: 'user',
|
|
37
|
+
content: `As a test automation engineer I am creating a Page Object for a web application using CodeceptJS.
|
|
38
|
+
Here is an sample page object:
|
|
39
|
+
|
|
40
|
+
const { I } = inject();
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
|
|
44
|
+
// setting locators
|
|
45
|
+
element1: '#selector',
|
|
46
|
+
element2: '.selector',
|
|
47
|
+
element3: locate().withText('text'),
|
|
48
|
+
|
|
49
|
+
// seting methods
|
|
50
|
+
doSomethingOnPage(params) {
|
|
51
|
+
// ...
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
I want to generate a Page Object for the page I provide.
|
|
56
|
+
Write JavaScript code in similar manner to list all locators on the page.
|
|
57
|
+
Use locators in order of preference: by text (use locate().withText()), label, CSS, XPath.
|
|
58
|
+
Avoid TailwindCSS, Bootstrap or React style formatting classes in locators.
|
|
59
|
+
Add methods to to interact with page when needed.
|
|
60
|
+
${extraPrompt}
|
|
61
|
+
${rootLocator ? `All provided elements are inside '${rootLocator}'. Declare it as root variable and for every locator use locate(...).inside(root)` : ''}
|
|
62
|
+
Add only locators from this HTML: \n\n${html}`,
|
|
63
|
+
}],
|
|
34
64
|
};
|
|
35
65
|
|
|
36
66
|
class AiAssistant {
|
|
@@ -182,10 +212,26 @@ class AiAssistant {
|
|
|
182
212
|
return this.config.response(response);
|
|
183
213
|
}
|
|
184
214
|
|
|
215
|
+
/**
|
|
216
|
+
*
|
|
217
|
+
* @param {*} extraPrompt
|
|
218
|
+
* @param {*} locator
|
|
219
|
+
* @returns
|
|
220
|
+
*/
|
|
221
|
+
async generatePageObject(extraPrompt = null, locator = null) {
|
|
222
|
+
if (!this.isEnabled) return [];
|
|
223
|
+
if (!this.minifiedHtml) throw new Error('No HTML context provided');
|
|
224
|
+
|
|
225
|
+
const response = await this.createCompletion(this.prompts.generatePageObject(this.minifiedHtml, locator, extraPrompt));
|
|
226
|
+
if (!response) return [];
|
|
227
|
+
|
|
228
|
+
return this.config.response(response);
|
|
229
|
+
}
|
|
230
|
+
|
|
185
231
|
calculateTokens(messages) {
|
|
186
232
|
// we implement naive approach for calculating tokens with no extra requests
|
|
187
233
|
// this approach was tested via https://platform.openai.com/tokenizer
|
|
188
|
-
// we need it to display current
|
|
234
|
+
// we need it to display current tokens usage so users could analyze effectiveness of AI
|
|
189
235
|
|
|
190
236
|
const inputString = messages.map(m => m.content).join(' ').trim();
|
|
191
237
|
const numWords = (inputString.match(/[^\s\-:=]+/g) || []).length;
|
package/lib/helper/AI.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
const Helper = require('@codeceptjs/helper');
|
|
2
|
+
const ora = require('ora-classic');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
2
5
|
const ai = require('../ai');
|
|
3
6
|
const standardActingHelpers = require('../plugin/standardActingHelpers');
|
|
4
7
|
const Container = require('../container');
|
|
5
8
|
const { splitByChunks, minifyHtml } = require('../html');
|
|
9
|
+
const { beautify } = require('../utils');
|
|
10
|
+
const output = require('../output');
|
|
11
|
+
const { registerVariable } = require('../pause');
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* AI Helper for CodeceptJS.
|
|
@@ -10,6 +16,8 @@ const { splitByChunks, minifyHtml } = require('../html');
|
|
|
10
16
|
* This helper class provides integration with the AI GPT-3.5 or 4 language model for generating responses to questions or prompts within the context of web pages. It allows you to interact with the GPT-3.5 model to obtain intelligent responses based on HTML fragments or general prompts.
|
|
11
17
|
* This helper should be enabled with any web helpers like Playwright or Puppeteer or WebDrvier to ensure the HTML context is available.
|
|
12
18
|
*
|
|
19
|
+
* Use it only in development mode. It is recommended to run it only inside pause() mode.
|
|
20
|
+
*
|
|
13
21
|
* ## Configuration
|
|
14
22
|
*
|
|
15
23
|
* This helper should be configured in codecept.json or codecept.conf.js
|
|
@@ -66,9 +74,9 @@ class AI extends Helper {
|
|
|
66
74
|
|
|
67
75
|
if (htmlChunks.length > 1) messages.push({ role: 'user', content: 'If action is not possible on this page, do not propose anything, I will send another HTML fragment' });
|
|
68
76
|
|
|
69
|
-
const response = await this.
|
|
77
|
+
const response = await this._processAIRequest(messages);
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
output.print(response);
|
|
72
80
|
|
|
73
81
|
responses.push(response);
|
|
74
82
|
}
|
|
@@ -96,15 +104,15 @@ class AI extends Helper {
|
|
|
96
104
|
{ role: 'user', content: `Within this HTML: ${minifyHtml(html)}` },
|
|
97
105
|
];
|
|
98
106
|
|
|
99
|
-
const response = await this.
|
|
107
|
+
const response = await this._processAIRequest(messages);
|
|
100
108
|
|
|
101
|
-
|
|
109
|
+
output.print(response);
|
|
102
110
|
|
|
103
111
|
return response;
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
/**
|
|
107
|
-
* Send a general request to
|
|
115
|
+
* Send a general request to AI and return response.
|
|
108
116
|
* @param {string} prompt
|
|
109
117
|
* @returns {Promise<string>} - A Promise that resolves to the generated response from the GPT model.
|
|
110
118
|
*/
|
|
@@ -113,10 +121,79 @@ class AI extends Helper {
|
|
|
113
121
|
{ role: 'user', content: prompt },
|
|
114
122
|
];
|
|
115
123
|
|
|
116
|
-
const response = await this.
|
|
124
|
+
const response = await this._processAIRequest(messages);
|
|
125
|
+
|
|
126
|
+
output.print(response);
|
|
127
|
+
|
|
128
|
+
return response;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Generates PageObject for current page using AI.
|
|
133
|
+
*
|
|
134
|
+
* It saves the PageObject to the output directory. You can review the page object and adjust it as needed and move to pages directory.
|
|
135
|
+
* Prompt can be customized in a global config file.
|
|
136
|
+
*
|
|
137
|
+
* ```js
|
|
138
|
+
* // create page object for whole page
|
|
139
|
+
* I.askForPageObject('home');
|
|
140
|
+
*
|
|
141
|
+
* // create page object with extra prompt
|
|
142
|
+
* I.askForPageObject('home', 'implement signIn(username, password) method');
|
|
143
|
+
*
|
|
144
|
+
* // create page object for a specific element
|
|
145
|
+
* I.askForPageObject('home', null, '.detail');
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* Asks for a page object based on the provided page name, locator, and extra prompt.
|
|
149
|
+
*
|
|
150
|
+
* @async
|
|
151
|
+
* @param {string} pageName - The name of the page to retrieve the object for.
|
|
152
|
+
* @param {string|null} [extraPrompt=null] - An optional extra prompt for additional context or information.
|
|
153
|
+
* @param {string|null} [locator=null] - An optional locator to find a specific element on the page.
|
|
154
|
+
* @returns {Promise<Object>} A promise that resolves to the requested page object.
|
|
155
|
+
*/
|
|
156
|
+
async askForPageObject(pageName, extraPrompt = null, locator = null) {
|
|
157
|
+
const html = locator ? await this.helper.grabHTMLFrom(locator) : await this.helper.grabSource();
|
|
158
|
+
|
|
159
|
+
const spinner = ora(' Processing AI request...').start();
|
|
160
|
+
await this.aiAssistant.setHtmlContext(html);
|
|
161
|
+
const response = await this.aiAssistant.generatePageObject(extraPrompt, locator);
|
|
162
|
+
spinner.stop();
|
|
163
|
+
|
|
164
|
+
if (!response[0]) {
|
|
165
|
+
output.error('No response from AI');
|
|
166
|
+
return '';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const code = beautify(response[0]);
|
|
117
170
|
|
|
118
|
-
|
|
171
|
+
output.print('----- Generated PageObject ----');
|
|
172
|
+
output.print(code);
|
|
173
|
+
output.print('-------------------------------');
|
|
119
174
|
|
|
175
|
+
const fileName = path.join(output_dir, `${pageName}Page-${Date.now()}.js`);
|
|
176
|
+
|
|
177
|
+
output.print(output.styles.bold(`Page object for ${pageName} is saved to ${output.styles.bold(fileName)}`));
|
|
178
|
+
fs.writeFileSync(fileName, code);
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
registerVariable('page', require(fileName));
|
|
182
|
+
output.success('Page object registered for this session as `page` variable');
|
|
183
|
+
output.print('Use `=>page.methodName()` in shell to run methods of page object');
|
|
184
|
+
output.print('Use `click(page.locatorName)` to check locators of page object');
|
|
185
|
+
} catch (err) {
|
|
186
|
+
output.error('Error while registering page object');
|
|
187
|
+
output.error(err.message);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return code;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async _processAIRequest(messages) {
|
|
194
|
+
const spinner = ora(' Processing AI request...').start();
|
|
195
|
+
const response = await this.aiAssistant.createCompletion(messages);
|
|
196
|
+
spinner.stop();
|
|
120
197
|
return response;
|
|
121
198
|
}
|
|
122
199
|
}
|
package/lib/helper/REST.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const axios = require('axios').default;
|
|
2
2
|
const Helper = require('@codeceptjs/helper');
|
|
3
|
+
const { Agent } = require('https');
|
|
3
4
|
const Secret = require('../secret');
|
|
4
5
|
|
|
5
6
|
const { beautify } = require('../utils');
|
|
@@ -14,6 +15,7 @@ const { beautify } = require('../utils');
|
|
|
14
15
|
* @prop {boolean} [printCurl=false] - print cURL request on console logs. False by default.
|
|
15
16
|
* @prop {number} [timeout=1000] - timeout for requests in milliseconds. 10000ms by default.
|
|
16
17
|
* @prop {object} [defaultHeaders] - a list of default headers.
|
|
18
|
+
* @prop {object} [httpAgent] - create an agent with SSL certificate
|
|
17
19
|
* @prop {function} [onRequest] - an async function which can update request object.
|
|
18
20
|
* @prop {function} [onResponse] - an async function which can update response object.
|
|
19
21
|
* @prop {number} [maxUploadFileSize] - set the max content file size in MB when performing api calls.
|
|
@@ -42,6 +44,25 @@ const config = {};
|
|
|
42
44
|
*}
|
|
43
45
|
* ```
|
|
44
46
|
*
|
|
47
|
+
* With httpAgent
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* {
|
|
51
|
+
* helpers: {
|
|
52
|
+
* REST: {
|
|
53
|
+
* endpoint: 'http://site.com/api',
|
|
54
|
+
* prettyPrintJson: true,
|
|
55
|
+
* httpAgent: {
|
|
56
|
+
* key: fs.readFileSync(__dirname + '/path/to/keyfile.key'),
|
|
57
|
+
* cert: fs.readFileSync(__dirname + '/path/to/certfile.cert'),
|
|
58
|
+
* rejectUnauthorized: false,
|
|
59
|
+
* keepAlive: true
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
45
66
|
* ## Access From Helpers
|
|
46
67
|
*
|
|
47
68
|
* Send REST requests by accessing `_executeRequest` method:
|
|
@@ -77,7 +98,14 @@ class REST extends Helper {
|
|
|
77
98
|
this._setConfig(config);
|
|
78
99
|
|
|
79
100
|
this.headers = { ...this.options.defaultHeaders };
|
|
80
|
-
|
|
101
|
+
|
|
102
|
+
// Create an agent with SSL certificate
|
|
103
|
+
if (this.options.httpAgent) {
|
|
104
|
+
if (!this.options.httpAgent.key || !this.options.httpAgent.cert) throw Error('Please recheck your httpAgent config!');
|
|
105
|
+
this.httpsAgent = new Agent(this.options.httpAgent);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.axios = this.httpsAgent ? axios.create({ httpsAgent: this.httpsAgent }) : axios.create();
|
|
81
109
|
// @ts-ignore
|
|
82
110
|
this.axios.defaults.headers = this.options.defaultHeaders;
|
|
83
111
|
}
|
|
@@ -166,7 +194,9 @@ class REST extends Helper {
|
|
|
166
194
|
}
|
|
167
195
|
|
|
168
196
|
this.options.prettyPrintJson ? this.debugSection('Request', beautify(JSON.stringify(_debugRequest))) : this.debugSection('Request', JSON.stringify(_debugRequest));
|
|
169
|
-
if (this.options.printCurl)
|
|
197
|
+
if (this.options.printCurl) {
|
|
198
|
+
this.debugSection('CURL Request', curlize(request));
|
|
199
|
+
}
|
|
170
200
|
|
|
171
201
|
let response;
|
|
172
202
|
try {
|
|
@@ -349,6 +379,7 @@ class REST extends Helper {
|
|
|
349
379
|
module.exports = REST;
|
|
350
380
|
|
|
351
381
|
function curlize(request) {
|
|
382
|
+
if (request.data?.constructor.name.toLowerCase() === 'formdata') return 'cURL is not printed as the request body is not a JSON';
|
|
352
383
|
let curl = `curl --location --request ${request.method ? request.method.toUpperCase() : 'GET'} ${request.baseURL} `.replace("'", '');
|
|
353
384
|
|
|
354
385
|
if (request.headers) {
|
package/lib/history.js
CHANGED
|
@@ -10,6 +10,9 @@ const output = require('./output');
|
|
|
10
10
|
*/
|
|
11
11
|
class ReplHistory {
|
|
12
12
|
constructor() {
|
|
13
|
+
if (global.output_dir) {
|
|
14
|
+
this.historyFile = path.join(global.output_dir, 'cli-history');
|
|
15
|
+
}
|
|
13
16
|
this.commands = [];
|
|
14
17
|
}
|
|
15
18
|
|
|
@@ -21,16 +24,26 @@ class ReplHistory {
|
|
|
21
24
|
this.commands.pop();
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
load() {
|
|
28
|
+
if (!this.historyFile) return;
|
|
29
|
+
if (!fs.existsSync(this.historyFile)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const history = fs.readFileSync(this.historyFile, 'utf-8');
|
|
34
|
+
return history.split('\n').reverse().filter(line => line.startsWith('I.')).map(line => line.slice(2));
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
save() {
|
|
38
|
+
if (!this.historyFile) return;
|
|
25
39
|
if (this.commands.length === 0) {
|
|
26
40
|
return;
|
|
27
41
|
}
|
|
28
42
|
|
|
29
|
-
const historyFile = path.join(global.output_dir, 'cli-history');
|
|
30
43
|
const commandSnippet = `\n\n<<< Recorded commands on ${new Date()}\n${this.commands.join('\n')}`;
|
|
31
|
-
fs.appendFileSync(historyFile, commandSnippet);
|
|
44
|
+
fs.appendFileSync(this.historyFile, commandSnippet);
|
|
32
45
|
|
|
33
|
-
output.print(colors.yellow(` Commands have been saved to ${historyFile}`));
|
|
46
|
+
output.print(colors.yellow(` Commands have been saved to ${this.historyFile}`));
|
|
34
47
|
|
|
35
48
|
this.commands = [];
|
|
36
49
|
}
|
package/lib/pause.js
CHANGED
|
@@ -56,7 +56,15 @@ function pauseSession(passedObject = {}) {
|
|
|
56
56
|
output.print(colors.blue(' Ideas: ask it to fill forms for you or to click'));
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
|
|
60
|
+
rl = readline.createInterface({
|
|
61
|
+
input: process.stdin,
|
|
62
|
+
output: process.stdout,
|
|
63
|
+
terminal: true,
|
|
64
|
+
completer,
|
|
65
|
+
history: history.load(),
|
|
66
|
+
historySize: 50, // Adjust the history size as needed
|
|
67
|
+
});
|
|
60
68
|
|
|
61
69
|
rl.on('line', parseInput);
|
|
62
70
|
rl.on('close', () => {
|
|
@@ -105,7 +113,7 @@ async function parseInput(cmd) {
|
|
|
105
113
|
if (cmd.trim().startsWith('=>')) {
|
|
106
114
|
isCustomCommand = true;
|
|
107
115
|
cmd = cmd.trim().substring(2, cmd.length);
|
|
108
|
-
} else if (aiAssistant.isEnabled && !cmd.match(/^\w+\(/) && cmd.includes(' ')) {
|
|
116
|
+
} else if (aiAssistant.isEnabled && cmd.trim() && !cmd.match(/^\w+\(/) && cmd.includes(' ')) {
|
|
109
117
|
const currentOutputLevel = output.level();
|
|
110
118
|
output.level(0);
|
|
111
119
|
const res = I.grabSource();
|
|
@@ -121,7 +129,7 @@ async function parseInput(cmd) {
|
|
|
121
129
|
output.level(currentOutputLevel);
|
|
122
130
|
}
|
|
123
131
|
|
|
124
|
-
const spinner = ora("Processing
|
|
132
|
+
const spinner = ora("Processing AI request...").start();
|
|
125
133
|
cmd = await aiAssistant.writeSteps(cmd);
|
|
126
134
|
spinner.stop();
|
|
127
135
|
output.print('');
|
|
@@ -200,4 +208,10 @@ function completer(line) {
|
|
|
200
208
|
return [hits && hits.length ? hits : completions, line];
|
|
201
209
|
}
|
|
202
210
|
|
|
211
|
+
function registerVariable(name, value) {
|
|
212
|
+
registeredVariables[name] = value;
|
|
213
|
+
}
|
|
214
|
+
|
|
203
215
|
module.exports = pause;
|
|
216
|
+
|
|
217
|
+
module.exports.registerVariable = registerVariable;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.6.4
|
|
3
|
+
"version": "3.6.4",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -72,14 +72,14 @@
|
|
|
72
72
|
"@codeceptjs/helper": "2.0.4",
|
|
73
73
|
"@cucumber/cucumber-expressions": "17",
|
|
74
74
|
"@cucumber/gherkin": "26",
|
|
75
|
-
"@cucumber/messages": "
|
|
75
|
+
"@cucumber/messages": "25.0.1",
|
|
76
76
|
"@xmldom/xmldom": "0.8.10",
|
|
77
77
|
"acorn": "8.11.3",
|
|
78
78
|
"arrify": "2.0.1",
|
|
79
79
|
"axios": "1.7.2",
|
|
80
80
|
"chai": "5.1.1",
|
|
81
81
|
"chai-deep-match": "1.2.1",
|
|
82
|
-
"chai-exclude": "2.1.
|
|
82
|
+
"chai-exclude": "2.1.1",
|
|
83
83
|
"chai-json-schema": "1.5.1",
|
|
84
84
|
"chai-json-schema-ajv": "5.2.4",
|
|
85
85
|
"chai-match-pattern": "1.3.0",
|
|
@@ -179,4 +179,4 @@
|
|
|
179
179
|
"strict": false
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
|
-
}
|
|
182
|
+
}
|
package/typings/index.d.ts
CHANGED
|
@@ -44,6 +44,44 @@ declare namespace CodeceptJS {
|
|
|
44
44
|
Scenario: number;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
type AiPrompt = {
|
|
48
|
+
role: string;
|
|
49
|
+
content: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type AiConfig = {
|
|
53
|
+
/** request function to send prompts to AI provider */
|
|
54
|
+
request: (messages: any) => Promise<string>,
|
|
55
|
+
|
|
56
|
+
/** custom prompts */
|
|
57
|
+
prompts?: {
|
|
58
|
+
/** Returns prompt to write CodeceptJS steps inside pause mode */
|
|
59
|
+
writeStep?: (html: string, input: string) => Array<AiPrompt>;
|
|
60
|
+
/** Returns prompt to heal step when test fails on CI if healing is on */
|
|
61
|
+
healStep?: (html: string, object) => Array<AiPrompt>;
|
|
62
|
+
/** Returns prompt to generate page object inside pause mode */
|
|
63
|
+
generatePageObject?: (html: string, extraPrompt?: string, rootLocator?: string) => Array<AiPrompt>;
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
/** max tokens to use */
|
|
67
|
+
maxTokens?: number,
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/** configuration for processing HTML for GPT */
|
|
71
|
+
html?: {
|
|
72
|
+
/** max size of HTML to be sent to OpenAI to avoid token limit */
|
|
73
|
+
maxLength?: number,
|
|
74
|
+
/** should HTML be changed by removing non-interactive elements */
|
|
75
|
+
simplify?: boolean,
|
|
76
|
+
/** should HTML be minified before sending */
|
|
77
|
+
minify?: boolean,
|
|
78
|
+
interactiveElements?: Array<string>,
|
|
79
|
+
textElements?: Array<string>,
|
|
80
|
+
allowedAttrs?: Array<string>,
|
|
81
|
+
allowedRoles?: Array<string>,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
47
85
|
type MainConfig = {
|
|
48
86
|
/** Pattern to locate CodeceptJS tests.
|
|
49
87
|
* Allows to enter glob pattern or an Array<string> of patterns to match tests / test file names.
|
|
@@ -165,6 +203,9 @@ declare namespace CodeceptJS {
|
|
|
165
203
|
*/
|
|
166
204
|
JSONResponse?: any;
|
|
167
205
|
|
|
206
|
+
/** Enable AI features for development purposes */
|
|
207
|
+
AI?: any;
|
|
208
|
+
|
|
168
209
|
[key: string]: any;
|
|
169
210
|
},
|
|
170
211
|
/**
|
|
@@ -353,25 +394,7 @@ declare namespace CodeceptJS {
|
|
|
353
394
|
/**
|
|
354
395
|
* [AI](https://codecept.io/ai/) features configuration.
|
|
355
396
|
*/
|
|
356
|
-
ai?:
|
|
357
|
-
/** OpenAI model to use */
|
|
358
|
-
model?: string,
|
|
359
|
-
/** temperature, measure of randomness. Lower is better. */
|
|
360
|
-
temperature?: number,
|
|
361
|
-
/** configuration for processing HTML for GPT */
|
|
362
|
-
html?: {
|
|
363
|
-
/** max size of HTML to be sent to OpenAI to avoid token limit */
|
|
364
|
-
maxLength?: number,
|
|
365
|
-
/** should HTML be changed by removing non-interactive elements */
|
|
366
|
-
simplify?: boolean,
|
|
367
|
-
/** should HTML be minified before sending */
|
|
368
|
-
minify?: boolean,
|
|
369
|
-
interactiveElements?: Array<string>,
|
|
370
|
-
textElements?: Array<string>,
|
|
371
|
-
allowedAttrs?: Array<string>,
|
|
372
|
-
allowedRoles?: Array<string>,
|
|
373
|
-
}
|
|
374
|
-
},
|
|
397
|
+
ai?: AiConfig,
|
|
375
398
|
|
|
376
399
|
/**
|
|
377
400
|
* Enable full promise-based helper methods for [TypeScript](https://codecept.io/typescript/) project.
|
|
@@ -5,6 +5,8 @@ declare namespace CodeceptJS {
|
|
|
5
5
|
* This helper class provides integration with the AI GPT-3.5 or 4 language model for generating responses to questions or prompts within the context of web pages. It allows you to interact with the GPT-3.5 model to obtain intelligent responses based on HTML fragments or general prompts.
|
|
6
6
|
* This helper should be enabled with any web helpers like Playwright or Puppeteer or WebDrvier to ensure the HTML context is available.
|
|
7
7
|
*
|
|
8
|
+
* Use it only in development mode. It is recommended to run it only inside pause() mode.
|
|
9
|
+
*
|
|
8
10
|
* ## Configuration
|
|
9
11
|
*
|
|
10
12
|
* This helper should be configured in codecept.json or codecept.conf.js
|
|
@@ -34,10 +36,34 @@ declare namespace CodeceptJS {
|
|
|
34
36
|
*/
|
|
35
37
|
askGptOnPageFragment(prompt: string, locator: string): Promise<string>;
|
|
36
38
|
/**
|
|
37
|
-
* Send a general request to
|
|
39
|
+
* Send a general request to AI and return response.
|
|
38
40
|
* @returns - A Promise that resolves to the generated response from the GPT model.
|
|
39
41
|
*/
|
|
40
42
|
askGptGeneralPrompt(prompt: string): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Generates PageObject for current page using AI.
|
|
45
|
+
*
|
|
46
|
+
* It saves the PageObject to the output directory. You can review the page object and adjust it as needed and move to pages directory.
|
|
47
|
+
* Prompt can be customized in a global config file.
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* // create page object for whole page
|
|
51
|
+
* I.askForPageObject('home');
|
|
52
|
+
*
|
|
53
|
+
* // create page object with extra prompt
|
|
54
|
+
* I.askForPageObject('home', 'implement signIn(username, password) method');
|
|
55
|
+
*
|
|
56
|
+
* // create page object for a specific element
|
|
57
|
+
* I.askForPageObject('home', null, '.detail');
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* Asks for a page object based on the provided page name, locator, and extra prompt.
|
|
61
|
+
* @param pageName - The name of the page to retrieve the object for.
|
|
62
|
+
* @param [extraPrompt = null] - An optional extra prompt for additional context or information.
|
|
63
|
+
* @param [locator = null] - An optional locator to find a specific element on the page.
|
|
64
|
+
* @returns A promise that resolves to the requested page object.
|
|
65
|
+
*/
|
|
66
|
+
askForPageObject(pageName: string, extraPrompt?: string | null, locator?: string | null): Promise<object>;
|
|
41
67
|
}
|
|
42
68
|
/**
|
|
43
69
|
* Helper for managing remote data using REST API.
|
|
@@ -1154,7 +1180,6 @@ declare namespace CodeceptJS {
|
|
|
1154
1180
|
*
|
|
1155
1181
|
* ## Methods
|
|
1156
1182
|
*/
|
|
1157
|
-
// @ts-ignore
|
|
1158
1183
|
class ExpectHelper {
|
|
1159
1184
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
1160
1185
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
@@ -1266,7 +1291,6 @@ declare namespace CodeceptJS {
|
|
|
1266
1291
|
*
|
|
1267
1292
|
* ## Methods
|
|
1268
1293
|
*/
|
|
1269
|
-
// @ts-ignore
|
|
1270
1294
|
class ExpectHelper {
|
|
1271
1295
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
1272
1296
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
@@ -1938,7 +1962,6 @@ declare namespace CodeceptJS {
|
|
|
1938
1962
|
* @property [host = "0.0.0.0"] - Mock server host
|
|
1939
1963
|
* @property [httpsOpts] - key & cert values are the paths to .key and .crt files
|
|
1940
1964
|
*/
|
|
1941
|
-
// @ts-ignore
|
|
1942
1965
|
type MockServerConfig = {
|
|
1943
1966
|
port?: number;
|
|
1944
1967
|
host?: string;
|
|
@@ -2063,7 +2086,6 @@ declare namespace CodeceptJS {
|
|
|
2063
2086
|
*
|
|
2064
2087
|
* ## Methods
|
|
2065
2088
|
*/
|
|
2066
|
-
// @ts-ignore
|
|
2067
2089
|
class MockServer {
|
|
2068
2090
|
/**
|
|
2069
2091
|
* Start the mock server
|
|
@@ -8189,6 +8211,25 @@ declare namespace CodeceptJS {
|
|
|
8189
8211
|
* }
|
|
8190
8212
|
* ```
|
|
8191
8213
|
*
|
|
8214
|
+
* With httpAgent
|
|
8215
|
+
*
|
|
8216
|
+
* ```js
|
|
8217
|
+
* {
|
|
8218
|
+
* helpers: {
|
|
8219
|
+
* REST: {
|
|
8220
|
+
* endpoint: 'http://site.com/api',
|
|
8221
|
+
* prettyPrintJson: true,
|
|
8222
|
+
* httpAgent: {
|
|
8223
|
+
* key: fs.readFileSync(__dirname + '/path/to/keyfile.key'),
|
|
8224
|
+
* cert: fs.readFileSync(__dirname + '/path/to/certfile.cert'),
|
|
8225
|
+
* rejectUnauthorized: false,
|
|
8226
|
+
* keepAlive: true
|
|
8227
|
+
* }
|
|
8228
|
+
* }
|
|
8229
|
+
* }
|
|
8230
|
+
* }
|
|
8231
|
+
* ```
|
|
8232
|
+
*
|
|
8192
8233
|
* ## Access From Helpers
|
|
8193
8234
|
*
|
|
8194
8235
|
* Send REST requests by accessing `_executeRequest` method:
|
package/typings/types.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ declare namespace CodeceptJS {
|
|
|
5
5
|
* This helper class provides integration with the AI GPT-3.5 or 4 language model for generating responses to questions or prompts within the context of web pages. It allows you to interact with the GPT-3.5 model to obtain intelligent responses based on HTML fragments or general prompts.
|
|
6
6
|
* This helper should be enabled with any web helpers like Playwright or Puppeteer or WebDrvier to ensure the HTML context is available.
|
|
7
7
|
*
|
|
8
|
+
* Use it only in development mode. It is recommended to run it only inside pause() mode.
|
|
9
|
+
*
|
|
8
10
|
* ## Configuration
|
|
9
11
|
*
|
|
10
12
|
* This helper should be configured in codecept.json or codecept.conf.js
|
|
@@ -34,10 +36,34 @@ declare namespace CodeceptJS {
|
|
|
34
36
|
*/
|
|
35
37
|
askGptOnPageFragment(prompt: string, locator: string): Promise<string>;
|
|
36
38
|
/**
|
|
37
|
-
* Send a general request to
|
|
39
|
+
* Send a general request to AI and return response.
|
|
38
40
|
* @returns - A Promise that resolves to the generated response from the GPT model.
|
|
39
41
|
*/
|
|
40
42
|
askGptGeneralPrompt(prompt: string): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Generates PageObject for current page using AI.
|
|
45
|
+
*
|
|
46
|
+
* It saves the PageObject to the output directory. You can review the page object and adjust it as needed and move to pages directory.
|
|
47
|
+
* Prompt can be customized in a global config file.
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* // create page object for whole page
|
|
51
|
+
* I.askForPageObject('home');
|
|
52
|
+
*
|
|
53
|
+
* // create page object with extra prompt
|
|
54
|
+
* I.askForPageObject('home', 'implement signIn(username, password) method');
|
|
55
|
+
*
|
|
56
|
+
* // create page object for a specific element
|
|
57
|
+
* I.askForPageObject('home', null, '.detail');
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* Asks for a page object based on the provided page name, locator, and extra prompt.
|
|
61
|
+
* @param pageName - The name of the page to retrieve the object for.
|
|
62
|
+
* @param [extraPrompt = null] - An optional extra prompt for additional context or information.
|
|
63
|
+
* @param [locator = null] - An optional locator to find a specific element on the page.
|
|
64
|
+
* @returns A promise that resolves to the requested page object.
|
|
65
|
+
*/
|
|
66
|
+
askForPageObject(pageName: string, extraPrompt?: string | null, locator?: string | null): Promise<object>;
|
|
41
67
|
}
|
|
42
68
|
/**
|
|
43
69
|
* Helper for managing remote data using REST API.
|
|
@@ -1178,7 +1204,6 @@ declare namespace CodeceptJS {
|
|
|
1178
1204
|
*
|
|
1179
1205
|
* ## Methods
|
|
1180
1206
|
*/
|
|
1181
|
-
// @ts-ignore
|
|
1182
1207
|
class ExpectHelper {
|
|
1183
1208
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
1184
1209
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
@@ -1290,7 +1315,6 @@ declare namespace CodeceptJS {
|
|
|
1290
1315
|
*
|
|
1291
1316
|
* ## Methods
|
|
1292
1317
|
*/
|
|
1293
|
-
// @ts-ignore
|
|
1294
1318
|
class ExpectHelper {
|
|
1295
1319
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
1296
1320
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
@@ -1965,7 +1989,6 @@ declare namespace CodeceptJS {
|
|
|
1965
1989
|
* @property [host = "0.0.0.0"] - Mock server host
|
|
1966
1990
|
* @property [httpsOpts] - key & cert values are the paths to .key and .crt files
|
|
1967
1991
|
*/
|
|
1968
|
-
// @ts-ignore
|
|
1969
1992
|
type MockServerConfig = {
|
|
1970
1993
|
port?: number;
|
|
1971
1994
|
host?: string;
|
|
@@ -2090,7 +2113,6 @@ declare namespace CodeceptJS {
|
|
|
2090
2113
|
*
|
|
2091
2114
|
* ## Methods
|
|
2092
2115
|
*/
|
|
2093
|
-
// @ts-ignore
|
|
2094
2116
|
class MockServer {
|
|
2095
2117
|
/**
|
|
2096
2118
|
* Start the mock server
|
|
@@ -8686,6 +8708,7 @@ declare namespace CodeceptJS {
|
|
|
8686
8708
|
* @property [printCurl = false] - print cURL request on console logs. False by default.
|
|
8687
8709
|
* @property [timeout = 1000] - timeout for requests in milliseconds. 10000ms by default.
|
|
8688
8710
|
* @property [defaultHeaders] - a list of default headers.
|
|
8711
|
+
* @property [httpAgent] - create an agent with SSL certificate
|
|
8689
8712
|
* @property [onRequest] - an async function which can update request object.
|
|
8690
8713
|
* @property [onResponse] - an async function which can update response object.
|
|
8691
8714
|
* @property [maxUploadFileSize] - set the max content file size in MB when performing api calls.
|
|
@@ -8696,6 +8719,7 @@ declare namespace CodeceptJS {
|
|
|
8696
8719
|
printCurl?: boolean;
|
|
8697
8720
|
timeout?: number;
|
|
8698
8721
|
defaultHeaders?: any;
|
|
8722
|
+
httpAgent?: any;
|
|
8699
8723
|
onRequest?: (...params: any[]) => any;
|
|
8700
8724
|
onResponse?: (...params: any[]) => any;
|
|
8701
8725
|
maxUploadFileSize?: number;
|
|
@@ -8722,6 +8746,25 @@ declare namespace CodeceptJS {
|
|
|
8722
8746
|
* }
|
|
8723
8747
|
* ```
|
|
8724
8748
|
*
|
|
8749
|
+
* With httpAgent
|
|
8750
|
+
*
|
|
8751
|
+
* ```js
|
|
8752
|
+
* {
|
|
8753
|
+
* helpers: {
|
|
8754
|
+
* REST: {
|
|
8755
|
+
* endpoint: 'http://site.com/api',
|
|
8756
|
+
* prettyPrintJson: true,
|
|
8757
|
+
* httpAgent: {
|
|
8758
|
+
* key: fs.readFileSync(__dirname + '/path/to/keyfile.key'),
|
|
8759
|
+
* cert: fs.readFileSync(__dirname + '/path/to/certfile.cert'),
|
|
8760
|
+
* rejectUnauthorized: false,
|
|
8761
|
+
* keepAlive: true
|
|
8762
|
+
* }
|
|
8763
|
+
* }
|
|
8764
|
+
* }
|
|
8765
|
+
* }
|
|
8766
|
+
* ```
|
|
8767
|
+
*
|
|
8725
8768
|
* ## Access From Helpers
|
|
8726
8769
|
*
|
|
8727
8770
|
* Send REST requests by accessing `_executeRequest` method:
|