codeceptjs 3.6.4-beta.1 → 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 +30 -5
- package/lib/history.js +16 -3
- package/lib/pause.js +17 -3
- package/package.json +6 -6
- package/typings/index.d.ts +42 -19
- package/typings/promiseBasedTypes.d.ts +28 -9
- package/typings/types.d.ts +35 -14
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
|
@@ -11,12 +11,13 @@ const { beautify } = require('../utils');
|
|
|
11
11
|
* @typedef RESTConfig
|
|
12
12
|
* @type {object}
|
|
13
13
|
* @prop {string} [endpoint] - API base URL
|
|
14
|
-
* @prop {boolean} [prettyPrintJson=false] - pretty print json for response/request on console logs
|
|
15
|
-
* @prop {
|
|
16
|
-
* @prop {
|
|
14
|
+
* @prop {boolean} [prettyPrintJson=false] - pretty print json for response/request on console logs.
|
|
15
|
+
* @prop {boolean} [printCurl=false] - print cURL request on console logs. False by default.
|
|
16
|
+
* @prop {number} [timeout=1000] - timeout for requests in milliseconds. 10000ms by default.
|
|
17
|
+
* @prop {object} [defaultHeaders] - a list of default headers.
|
|
17
18
|
* @prop {object} [httpAgent] - create an agent with SSL certificate
|
|
18
|
-
* @prop {function} [onRequest] -
|
|
19
|
-
* @prop {function} [onResponse] -
|
|
19
|
+
* @prop {function} [onRequest] - an async function which can update request object.
|
|
20
|
+
* @prop {function} [onResponse] - an async function which can update response object.
|
|
20
21
|
* @prop {number} [maxUploadFileSize] - set the max content file size in MB when performing api calls.
|
|
21
22
|
*/
|
|
22
23
|
const config = {};
|
|
@@ -42,6 +43,7 @@ const config = {};
|
|
|
42
43
|
* }
|
|
43
44
|
*}
|
|
44
45
|
* ```
|
|
46
|
+
*
|
|
45
47
|
* With httpAgent
|
|
46
48
|
*
|
|
47
49
|
* ```js
|
|
@@ -192,6 +194,9 @@ class REST extends Helper {
|
|
|
192
194
|
}
|
|
193
195
|
|
|
194
196
|
this.options.prettyPrintJson ? this.debugSection('Request', beautify(JSON.stringify(_debugRequest))) : this.debugSection('Request', JSON.stringify(_debugRequest));
|
|
197
|
+
if (this.options.printCurl) {
|
|
198
|
+
this.debugSection('CURL Request', curlize(request));
|
|
199
|
+
}
|
|
195
200
|
|
|
196
201
|
let response;
|
|
197
202
|
try {
|
|
@@ -372,3 +377,23 @@ class REST extends Helper {
|
|
|
372
377
|
}
|
|
373
378
|
}
|
|
374
379
|
module.exports = REST;
|
|
380
|
+
|
|
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';
|
|
383
|
+
let curl = `curl --location --request ${request.method ? request.method.toUpperCase() : 'GET'} ${request.baseURL} `.replace("'", '');
|
|
384
|
+
|
|
385
|
+
if (request.headers) {
|
|
386
|
+
Object.entries(request.headers).forEach(([key, value]) => {
|
|
387
|
+
curl += `-H "${key}: ${value}" `;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!curl.toLowerCase().includes('content-type: application/json')) {
|
|
392
|
+
curl += '-H "Content-Type: application/json" ';
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (request.data) {
|
|
396
|
+
curl += `-d '${JSON.stringify(request.data)}'`;
|
|
397
|
+
}
|
|
398
|
+
return curl;
|
|
399
|
+
}
|
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",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"glob": "6.0.1",
|
|
99
99
|
"html-minifier-terser": "7.2.0",
|
|
100
100
|
"inquirer": "6.5.2",
|
|
101
|
-
"joi": "17.13.
|
|
101
|
+
"joi": "17.13.1",
|
|
102
102
|
"js-beautify": "1.15.1",
|
|
103
103
|
"lodash.clonedeep": "4.5.0",
|
|
104
104
|
"lodash.merge": "4.6.2",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"@types/node": "20.11.30",
|
|
129
129
|
"@wdio/sauce-service": "8.35.1",
|
|
130
130
|
"@wdio/selenium-standalone-service": "8.3.2",
|
|
131
|
-
"@wdio/utils": "8.
|
|
131
|
+
"@wdio/utils": "8.38.2",
|
|
132
132
|
"@xmldom/xmldom": "0.8.10",
|
|
133
133
|
"apollo-server-express": "2.25.3",
|
|
134
134
|
"chai-as-promised": "7.1.2",
|
|
@@ -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,8 +1180,6 @@ declare namespace CodeceptJS {
|
|
|
1154
1180
|
*
|
|
1155
1181
|
* ## Methods
|
|
1156
1182
|
*/
|
|
1157
|
-
// @ts-ignore
|
|
1158
|
-
// @ts-ignore
|
|
1159
1183
|
class ExpectHelper {
|
|
1160
1184
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
1161
1185
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
@@ -1267,8 +1291,6 @@ declare namespace CodeceptJS {
|
|
|
1267
1291
|
*
|
|
1268
1292
|
* ## Methods
|
|
1269
1293
|
*/
|
|
1270
|
-
// @ts-ignore
|
|
1271
|
-
// @ts-ignore
|
|
1272
1294
|
class ExpectHelper {
|
|
1273
1295
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
1274
1296
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): Promise<any>;
|
|
@@ -1940,8 +1962,6 @@ declare namespace CodeceptJS {
|
|
|
1940
1962
|
* @property [host = "0.0.0.0"] - Mock server host
|
|
1941
1963
|
* @property [httpsOpts] - key & cert values are the paths to .key and .crt files
|
|
1942
1964
|
*/
|
|
1943
|
-
// @ts-ignore
|
|
1944
|
-
// @ts-ignore
|
|
1945
1965
|
type MockServerConfig = {
|
|
1946
1966
|
port?: number;
|
|
1947
1967
|
host?: string;
|
|
@@ -2066,8 +2086,6 @@ declare namespace CodeceptJS {
|
|
|
2066
2086
|
*
|
|
2067
2087
|
* ## Methods
|
|
2068
2088
|
*/
|
|
2069
|
-
// @ts-ignore
|
|
2070
|
-
// @ts-ignore
|
|
2071
2089
|
class MockServer {
|
|
2072
2090
|
/**
|
|
2073
2091
|
* Start the mock server
|
|
@@ -8192,6 +8210,7 @@ declare namespace CodeceptJS {
|
|
|
8192
8210
|
* }
|
|
8193
8211
|
* }
|
|
8194
8212
|
* ```
|
|
8213
|
+
*
|
|
8195
8214
|
* With httpAgent
|
|
8196
8215
|
*
|
|
8197
8216
|
* ```js
|
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,8 +1204,6 @@ declare namespace CodeceptJS {
|
|
|
1178
1204
|
*
|
|
1179
1205
|
* ## Methods
|
|
1180
1206
|
*/
|
|
1181
|
-
// @ts-ignore
|
|
1182
|
-
// @ts-ignore
|
|
1183
1207
|
class ExpectHelper {
|
|
1184
1208
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
1185
1209
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
@@ -1291,8 +1315,6 @@ declare namespace CodeceptJS {
|
|
|
1291
1315
|
*
|
|
1292
1316
|
* ## Methods
|
|
1293
1317
|
*/
|
|
1294
|
-
// @ts-ignore
|
|
1295
|
-
// @ts-ignore
|
|
1296
1318
|
class ExpectHelper {
|
|
1297
1319
|
expectEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
1298
1320
|
expectNotEqual(actualValue: any, expectedValue: any, customErrorMsg?: any): void;
|
|
@@ -1967,8 +1989,6 @@ declare namespace CodeceptJS {
|
|
|
1967
1989
|
* @property [host = "0.0.0.0"] - Mock server host
|
|
1968
1990
|
* @property [httpsOpts] - key & cert values are the paths to .key and .crt files
|
|
1969
1991
|
*/
|
|
1970
|
-
// @ts-ignore
|
|
1971
|
-
// @ts-ignore
|
|
1972
1992
|
type MockServerConfig = {
|
|
1973
1993
|
port?: number;
|
|
1974
1994
|
host?: string;
|
|
@@ -2093,8 +2113,6 @@ declare namespace CodeceptJS {
|
|
|
2093
2113
|
*
|
|
2094
2114
|
* ## Methods
|
|
2095
2115
|
*/
|
|
2096
|
-
// @ts-ignore
|
|
2097
|
-
// @ts-ignore
|
|
2098
2116
|
class MockServer {
|
|
2099
2117
|
/**
|
|
2100
2118
|
* Start the mock server
|
|
@@ -8686,17 +8704,19 @@ declare namespace CodeceptJS {
|
|
|
8686
8704
|
/**
|
|
8687
8705
|
* ## Configuration
|
|
8688
8706
|
* @property [endpoint] - API base URL
|
|
8689
|
-
* @property [prettyPrintJson = false] - pretty print json for response/request on console logs
|
|
8690
|
-
* @property [
|
|
8691
|
-
* @property [
|
|
8707
|
+
* @property [prettyPrintJson = false] - pretty print json for response/request on console logs.
|
|
8708
|
+
* @property [printCurl = false] - print cURL request on console logs. False by default.
|
|
8709
|
+
* @property [timeout = 1000] - timeout for requests in milliseconds. 10000ms by default.
|
|
8710
|
+
* @property [defaultHeaders] - a list of default headers.
|
|
8692
8711
|
* @property [httpAgent] - create an agent with SSL certificate
|
|
8693
|
-
* @property [onRequest] -
|
|
8694
|
-
* @property [onResponse] -
|
|
8712
|
+
* @property [onRequest] - an async function which can update request object.
|
|
8713
|
+
* @property [onResponse] - an async function which can update response object.
|
|
8695
8714
|
* @property [maxUploadFileSize] - set the max content file size in MB when performing api calls.
|
|
8696
8715
|
*/
|
|
8697
8716
|
type RESTConfig = {
|
|
8698
8717
|
endpoint?: string;
|
|
8699
8718
|
prettyPrintJson?: boolean;
|
|
8719
|
+
printCurl?: boolean;
|
|
8700
8720
|
timeout?: number;
|
|
8701
8721
|
defaultHeaders?: any;
|
|
8702
8722
|
httpAgent?: any;
|
|
@@ -8725,6 +8745,7 @@ declare namespace CodeceptJS {
|
|
|
8725
8745
|
* }
|
|
8726
8746
|
* }
|
|
8727
8747
|
* ```
|
|
8748
|
+
*
|
|
8728
8749
|
* With httpAgent
|
|
8729
8750
|
*
|
|
8730
8751
|
* ```js
|