Skip to content

Commit f669be0

Browse files
DavertMikDavertMik
and
DavertMik
authored
Feat/els module (#4703)
* added els functions * implemented els module * added els to package.json * els functions & terminal improvements * fixed metastep display * remove not used test --------- Co-authored-by: DavertMik <davert@testomat.io>
1 parent eeb5a02 commit f669be0

27 files changed

+4033
-3656
lines changed

docs/els.md

+289
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
## Element Access
2+
3+
The `els` module provides low-level element manipulation functions for CodeceptJS tests, allowing for more granular control over element interactions and assertions. However, because element representation differs between frameworks, tests using element functions are not portable between helpers. So if you set to use Playwright you won't be able to witch to WebDriver with one config change in CodeceptJS.
4+
5+
### Usage
6+
7+
Import the els functions in your test file:
8+
9+
```js
10+
const { element, eachElement, expectElement, expectAnyElement, expectAllElements } = require('codeceptjs/els');
11+
```
12+
13+
## element
14+
15+
The `element` function allows you to perform custom operations on the first matching element found by a locator. It provides a low-level way to interact with elements when the built-in helper methods aren't sufficient.
16+
17+
### Syntax
18+
19+
```js
20+
element(purpose, locator, fn);
21+
// or
22+
element(locator, fn);
23+
```
24+
25+
### Parameters
26+
27+
- `purpose` (optional) - A string describing the operation being performed. If omitted, a default purpose will be generated from the function.
28+
- `locator` - A locator string/object to find the element(s).
29+
- `fn` - An async function that receives the element as its argument and performs the desired operation. `el` argument represents an element of an underlying engine used: Playwright, WebDriver, or Puppeteer.
30+
31+
### Returns
32+
33+
Returns the result of the provided async function executed on the first matching element.
34+
35+
### Example
36+
37+
```js
38+
Scenario('my test', async ({ I }) => {
39+
// combine element function with standard steps:
40+
I.amOnPage('/cart');
41+
42+
// but use await every time you use element function
43+
await element(
44+
// with explicit purpose
45+
'check custom attribute',
46+
'.button',
47+
async el => await el.getAttribute('data-test'),
48+
);
49+
50+
// or simply
51+
await element('.button', async el => {
52+
return await el.isEnabled();
53+
});
54+
});
55+
```
56+
57+
### Notes
58+
59+
- Only works with helpers that implement the `_locate` method
60+
- The function will only operate on the first element found, even if multiple elements match the locator
61+
- The provided callback must be an async function
62+
- Throws an error if no helper with `_locate` method is enabled
63+
64+
## eachElement
65+
66+
The `eachElement` function allows you to perform operations on each element that matches a locator. It's useful for iterating through multiple elements and performing the same operation on each one.
67+
68+
### Syntax
69+
70+
```js
71+
eachElement(purpose, locator, fn);
72+
// or
73+
eachElement(locator, fn);
74+
```
75+
76+
### Parameters
77+
78+
- `purpose` (optional) - A string describing the operation being performed. If omitted, a default purpose will be generated from the function.
79+
- `locator` - A locator string/object to find the element(s).
80+
- `fn` - An async function that receives two arguments:
81+
- `el` - The current element being processed
82+
- `index` - The index of the current element in the collection
83+
84+
### Returns
85+
86+
Returns a promise that resolves when all elements have been processed. If any element operation fails, the function will throw the first encountered error.
87+
88+
### Example
89+
90+
```js
91+
Scenario('my test', async ({ I }) => {
92+
// combine element function with standard steps:
93+
I.click('/hotels');
94+
95+
// iterate over elements but don't forget to put await
96+
await eachElement(
97+
'validate list items', // explain your actions for future review
98+
'.list-item', // locator
99+
async (el, index) => {
100+
const text = await el.getText();
101+
console.log(`Item ${index}: ${text}`);
102+
},
103+
);
104+
105+
// Or simply check if all checkboxes are checked
106+
await eachElement('input[type="checkbox"]', async el => {
107+
const isChecked = await el.isSelected();
108+
if (!isChecked) {
109+
throw new Error('Found unchecked checkbox');
110+
}
111+
});
112+
});
113+
```
114+
115+
### Notes
116+
117+
- Only works with helpers that implement the `_locate` method
118+
- The function will process all elements that match the locator
119+
- The provided callback must be an async function
120+
- If an operation fails on any element, the error is logged and the function continues processing remaining elements
121+
- After all elements are processed, if any errors occurred, the first error is thrown
122+
- Throws an error if no helper with `_locate` method is enabled
123+
124+
## expectElement
125+
126+
The `expectElement` function allows you to perform assertions on the first element that matches a locator. It's designed for validating element properties or states and will throw an assertion error if the condition is not met.
127+
128+
### Syntax
129+
130+
```js
131+
expectElement(locator, fn);
132+
```
133+
134+
### Parameters
135+
136+
- `locator` - A locator string/object to find the element(s).
137+
- `fn` - An async function that receives the element as its argument and should return a boolean value:
138+
- `true` - The assertion passed
139+
- `false` - The assertion failed
140+
141+
### Returns
142+
143+
Returns a promise that resolves when the assertion is complete. Throws an assertion error if the condition is not met.
144+
145+
### Example
146+
147+
```js
148+
// Check if a button is enabled
149+
await expectElement('.submit-button', async el => {
150+
return await el.isEnabled();
151+
});
152+
153+
// Verify element has specific text content
154+
await expectElement('.header', async el => {
155+
const text = await el.getText();
156+
return text === 'Welcome';
157+
});
158+
159+
// Check for specific attribute value
160+
await expectElement('#user-profile', async el => {
161+
const role = await el.getAttribute('role');
162+
return role === 'button';
163+
});
164+
```
165+
166+
### Notes
167+
168+
- Only works with helpers that implement the `_locate` method
169+
- The function will only check the first element found, even if multiple elements match the locator
170+
- The provided callback must be an async function that returns a boolean
171+
- The assertion message will include both the locator and the function used for validation
172+
- Throws an error if no helper with `_locate` method is enabled
173+
174+
## expectAnyElement
175+
176+
The `expectAnyElement` function allows you to perform assertions where at least one element from a collection should satisfy the condition. It's useful when you need to verify that at least one element among many matches your criteria.
177+
178+
### Syntax
179+
180+
```js
181+
expectAnyElement(locator, fn);
182+
```
183+
184+
### Parameters
185+
186+
- `locator` - A locator string/object to find the element(s).
187+
- `fn` - An async function that receives the element as its argument and should return a boolean value:
188+
- `true` - The assertion passed for this element
189+
- `false` - The assertion failed for this element
190+
191+
### Returns
192+
193+
Returns a promise that resolves when the assertion is complete. Throws an assertion error if no elements satisfy the condition.
194+
195+
### Example
196+
197+
```js
198+
Scenario('validate any element matches criteria', async ({ I }) => {
199+
// Navigate to the page
200+
I.amOnPage('/products');
201+
202+
// Check if any product is marked as "in stock"
203+
await expectAnyElement('.product-item', async el => {
204+
const status = await el.getAttribute('data-status');
205+
return status === 'in-stock';
206+
});
207+
208+
// Verify at least one price is below $100
209+
await expectAnyElement('.price-tag', async el => {
210+
const price = await el.getText();
211+
return parseFloat(price.replace('$', '')) < 100;
212+
});
213+
214+
// Check if any button in the list is enabled
215+
await expectAnyElement('.action-button', async el => {
216+
return await el.isEnabled();
217+
});
218+
});
219+
```
220+
221+
### Notes
222+
223+
- Only works with helpers that implement the `_locate` method
224+
- The function will check all matching elements until it finds one that satisfies the condition
225+
- Stops checking elements once the first matching condition is found
226+
- The provided callback must be an async function that returns a boolean
227+
- Throws an assertion error if no elements satisfy the condition
228+
- Throws an error if no helper with `_locate` method is enabled
229+
230+
## expectAllElements
231+
232+
The `expectAllElements` function verifies that every element matching the locator satisfies the given condition. It's useful when you need to ensure that all elements in a collection meet specific criteria.
233+
234+
### Syntax
235+
236+
```js
237+
expectAllElements(locator, fn);
238+
```
239+
240+
### Parameters
241+
242+
- `locator` - A locator string/object to find the element(s).
243+
- `fn` - An async function that receives the element as its argument and should return a boolean value:
244+
- `true` - The assertion passed for this element
245+
- `false` - The assertion failed for this element
246+
247+
### Returns
248+
249+
Returns a promise that resolves when all assertions are complete. Throws an assertion error as soon as any element fails the condition.
250+
251+
### Example
252+
253+
```js
254+
Scenario('validate all elements meet criteria', async ({ I }) => {
255+
// Navigate to the page
256+
I.amOnPage('/dashboard');
257+
258+
// Verify all required fields have the required attribute
259+
await expectAllElements('.required-field', async el => {
260+
const required = await el.getAttribute('required');
261+
return required !== null;
262+
});
263+
264+
// Check if all checkboxes in a form are checked
265+
await expectAllElements('input[type="checkbox"]', async el => {
266+
return await el.isSelected();
267+
});
268+
269+
// Verify all items in a list have non-empty text
270+
await expectAllElements('.list-item', async el => {
271+
const text = await el.getText();
272+
return text.trim().length > 0;
273+
});
274+
275+
// Ensure all buttons in a section are enabled
276+
await expectAllElements('#action-section button', async el => {
277+
return await el.isEnabled();
278+
});
279+
});
280+
```
281+
282+
### Notes
283+
284+
- Only works with helpers that implement the `_locate` method
285+
- The function checks every element that matches the locator
286+
- Fails fast: stops checking elements as soon as one fails the condition
287+
- The provided callback must be an async function that returns a boolean
288+
- The assertion message will include which element number failed (e.g., "element #2 of...")
289+
- Throws an error if no helper with `_locate` method is enabled

docs/helpers/AI.md

+14-16
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ Use it only in development mode. It is recommended to run it only inside pause()
2222

2323
This helper should be configured in codecept.conf.{js|ts}
2424

25-
* `chunkSize`: - The maximum number of characters to send to the AI API at once. We split HTML fragments by 8000 chars to not exceed token limit. Increase this value if you use GPT-4.
25+
- `chunkSize`: - The maximum number of characters to send to the AI API at once. We split HTML fragments by 8000 chars to not exceed token limit. Increase this value if you use GPT-4.
2626

2727
### Parameters
2828

29-
* `config` &#x20;
29+
- `config` &#x20;
3030

3131
### askForPageObject
3232

@@ -37,22 +37,22 @@ Prompt can be customized in a global config file.
3737

3838
```js
3939
// create page object for whole page
40-
I.askForPageObject('home');
40+
I.askForPageObject('home')
4141

4242
// create page object with extra prompt
43-
I.askForPageObject('home', 'implement signIn(username, password) method');
43+
I.askForPageObject('home', 'implement signIn(username, password) method')
4444

4545
// create page object for a specific element
46-
I.askForPageObject('home', null, '.detail');
46+
I.askForPageObject('home', null, '.detail')
4747
```
4848

4949
Asks for a page object based on the provided page name, locator, and extra prompt.
5050

5151
#### Parameters
5252

53-
* `pageName` **[string][1]** The name of the page to retrieve the object for.
54-
* `extraPrompt` **([string][1] | null)** An optional extra prompt for additional context or information.
55-
* `locator` **([string][1] | null)** An optional locator to find a specific element on the page.
53+
- `pageName` **[string][1]** The name of the page to retrieve the object for.
54+
- `extraPrompt` **([string][1] | null)** An optional extra prompt for additional context or information.
55+
- `locator` **([string][1] | null)** An optional locator to find a specific element on the page.
5656

5757
Returns **[Promise][2]<[Object][3]>** A promise that resolves to the requested page object.
5858

@@ -62,7 +62,7 @@ Send a general request to AI and return response.
6262

6363
#### Parameters
6464

65-
* `prompt` **[string][1]**&#x20;
65+
- `prompt` **[string][1]**&#x20;
6666

6767
Returns **[Promise][2]<[string][1]>** A Promise that resolves to the generated response from the GPT model.
6868

@@ -71,12 +71,12 @@ Returns **[Promise][2]<[string][1]>** A Promise that resolves to the generated r
7171
Asks the AI GPT language model a question based on the provided prompt within the context of the current page's HTML.
7272

7373
```js
74-
I.askGptOnPage('what does this page do?');
74+
I.askGptOnPage('what does this page do?')
7575
```
7676

7777
#### Parameters
7878

79-
* `prompt` **[string][1]** The question or prompt to ask the GPT model.
79+
- `prompt` **[string][1]** The question or prompt to ask the GPT model.
8080

8181
Returns **[Promise][2]<[string][1]>** A Promise that resolves to the generated responses from the GPT model, joined by newlines.
8282

@@ -85,18 +85,16 @@ Returns **[Promise][2]<[string][1]>** A Promise that resolves to the generated r
8585
Asks the AI a question based on the provided prompt within the context of a specific HTML fragment on the current page.
8686

8787
```js
88-
I.askGptOnPageFragment('describe features of this screen', '.screen');
88+
I.askGptOnPageFragment('describe features of this screen', '.screen')
8989
```
9090

9191
#### Parameters
9292

93-
* `prompt` **[string][1]** The question or prompt to ask the GPT-3.5 model.
94-
* `locator` **[string][1]** The locator or selector used to identify the HTML fragment on the page.
93+
- `prompt` **[string][1]** The question or prompt to ask the GPT-3.5 model.
94+
- `locator` **[string][1]** The locator or selector used to identify the HTML fragment on the page.
9595

9696
Returns **[Promise][2]<[string][1]>** A Promise that resolves to the generated response from the GPT model.
9797

9898
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
99-
10099
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
101-
102100
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

0 commit comments

Comments
 (0)