@qavajs/cypress 2.8.0 → 2.9.0
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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +206 -17
- package/defineQavajs.d.ts +27 -0
- package/index.d.ts +11 -0
- package/lib/actions.js +1 -1
- package/lib/conditionExpect.js +12 -0
- package/lib/execute.js +13 -4
- package/lib/pageObjects.js +1 -1
- package/lib/valueValidation.js +1 -3
- package/package.json +22 -4
- package/po.d.ts +53 -0
- package/tsconfig.json +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,21 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
|
|
|
10
10
|
:pencil: - chore
|
|
11
11
|
:microscope: - experimental
|
|
12
12
|
|
|
13
|
+
## [2.9.0]
|
|
14
|
+
- :pencil: added TypeScript declaration files (`index.d.ts`, `po.d.ts`, `defineQavajs.d.ts`)
|
|
15
|
+
- :pencil: added `tsconfig.json`
|
|
16
|
+
- :pencil: added `types` and `exports` fields to `package.json`
|
|
17
|
+
|
|
18
|
+
## [2.8.2]
|
|
19
|
+
- :rocket: added `clickable` condition (checks element is visible and not disabled)
|
|
20
|
+
- :beetle: fixed `validateAllOf` exiting after first successful match instead of validating all values
|
|
21
|
+
- :beetle: fixed circular reference in `I expect {value} {validation} at least one of:` step
|
|
22
|
+
- :beetle: fixed `execute` steps throwing generic JS error on invalid function string — now surfaces a descriptive message
|
|
23
|
+
- :pencil: added `engines` field to `package.json` (`node >= 18`)
|
|
24
|
+
|
|
25
|
+
## [2.8.1]
|
|
26
|
+
- :beetle: fixed native selector logging to display `[function]` instead of function body
|
|
27
|
+
|
|
13
28
|
## [2.8.0]
|
|
14
29
|
- :rocket: improved memory and page object logging
|
|
15
30
|
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 @qavajs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @qavajs/cypress
|
|
2
|
-
qavajs
|
|
2
|
+
[](https://www.npmjs.com/package/@qavajs/cypress)
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
|
|
5
|
+
Gherkin/BDD step definitions for web testing with Cypress. Part of the [qavajs](https://github.com/qavajs) framework.
|
|
3
6
|
|
|
4
7
|
## Installation
|
|
5
8
|
|
|
@@ -8,49 +11,235 @@ npm install @qavajs/cypress @qavajs/cypress-runner-adapter @qavajs/memory
|
|
|
8
11
|
```
|
|
9
12
|
|
|
10
13
|
## Configuration
|
|
11
|
-
|
|
14
|
+
|
|
15
|
+
**cypress.config.js**
|
|
12
16
|
```javascript
|
|
13
17
|
const { defineConfig } = require('cypress');
|
|
14
18
|
const cucumber = require('@qavajs/cypress-runner-adapter/adapter');
|
|
19
|
+
|
|
15
20
|
module.exports = defineConfig({
|
|
16
21
|
e2e: {
|
|
17
|
-
specPattern: 'cypress/features/**/*.feature',
|
|
18
|
-
supportFile: 'cypress/support/e2e.js',
|
|
22
|
+
specPattern: 'cypress/features/**/*.feature',
|
|
23
|
+
supportFile: 'cypress/support/e2e.js',
|
|
19
24
|
setupNodeEvents(on, config) {
|
|
20
|
-
on('file:preprocessor', cucumber)
|
|
25
|
+
on('file:preprocessor', cucumber);
|
|
21
26
|
},
|
|
22
27
|
},
|
|
23
28
|
});
|
|
24
|
-
|
|
25
29
|
```
|
|
26
|
-
|
|
30
|
+
|
|
31
|
+
**cypress/support/e2e.js**
|
|
27
32
|
```typescript
|
|
28
33
|
import defineQavajs from '@qavajs/cypress/defineQavajs';
|
|
29
34
|
import '@qavajs/cypress';
|
|
30
35
|
|
|
31
|
-
import PageObject from '../page_object
|
|
32
|
-
import Memory from '../memory';
|
|
36
|
+
import PageObject from '../page_object';
|
|
37
|
+
import Memory from '../memory';
|
|
33
38
|
|
|
34
39
|
defineQavajs({
|
|
35
40
|
pageObject: new PageObject(),
|
|
36
41
|
memory: new Memory()
|
|
37
42
|
});
|
|
43
|
+
```
|
|
38
44
|
|
|
45
|
+
## Page Objects
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
Page objects define element locators used in step definitions.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { locator } from '@qavajs/cypress/po';
|
|
51
|
+
|
|
52
|
+
class Header {
|
|
53
|
+
Logo = locator('.logo');
|
|
54
|
+
Nav = locator('nav');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default class App {
|
|
58
|
+
// Simple CSS/XPath selector
|
|
59
|
+
SearchInput = locator('#search');
|
|
60
|
+
SearchButton = locator('#searchBtn');
|
|
61
|
+
Results = locator('.result-item');
|
|
62
|
+
|
|
63
|
+
// Parameterized selector
|
|
64
|
+
ResultByIndex = locator.template(idx => `.result-item:nth-child(${idx})`);
|
|
65
|
+
|
|
66
|
+
// Custom Cypress query
|
|
67
|
+
ActiveTab = locator.native(({ cy }) => cy.get('.tab').filter('.active'));
|
|
41
68
|
|
|
42
|
-
|
|
43
|
-
|
|
69
|
+
// Nested component
|
|
70
|
+
Header = locator('header').as(Header);
|
|
71
|
+
}
|
|
44
72
|
```
|
|
45
|
-
|
|
73
|
+
|
|
74
|
+
Elements are referenced in steps by their property name (e.g. `'Search Input'` or `'Header > Logo'` for nested components).
|
|
75
|
+
|
|
76
|
+
## Memory
|
|
77
|
+
|
|
78
|
+
The memory class stores values accessible in steps via the `$key` syntax.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
export default class Memory {
|
|
82
|
+
baseUrl = 'https://example.com';
|
|
83
|
+
testUser = 'user@example.com';
|
|
84
|
+
// Functions are called on access
|
|
85
|
+
timestamp = () => Date.now();
|
|
86
|
+
uppercase = (str: string) => str.toUpperCase();
|
|
87
|
+
}
|
|
46
88
|
```
|
|
47
89
|
|
|
48
|
-
|
|
90
|
+
Use `$key` in any step parameter to reference a memory value, `$key()` to call a function, and `$key.property` for nested access.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Step Definitions
|
|
95
|
+
|
|
96
|
+
### Navigation & Actions
|
|
97
|
+
|
|
98
|
+
| Step | Description |
|
|
99
|
+
|------|-------------|
|
|
100
|
+
| `I open '{value}' url` | Navigate to a URL |
|
|
101
|
+
| `I reload page` | Reload current page |
|
|
102
|
+
| `I go back` | Browser back |
|
|
103
|
+
| `I go forward` | Browser forward |
|
|
104
|
+
| `I click '{locator}'` | Click an element |
|
|
105
|
+
| `I force click '{locator}'` | Force-click (bypasses actionability checks) |
|
|
106
|
+
| `I double click '{locator}'` | Double-click |
|
|
107
|
+
| `I right click '{locator}'` | Right-click |
|
|
108
|
+
| `I type '{value}' to '{locator}'` | Type text into an element |
|
|
109
|
+
| `I type '{value}' into '{locator}'` | Alias for type |
|
|
110
|
+
| `I clear '{locator}'` | Clear an input |
|
|
111
|
+
| `I clear '{locator}' and type '{value}'` | Clear then type |
|
|
112
|
+
| `I press '{value}' key` | Press a keyboard key or combo (e.g. `Enter`, `Control+C`) |
|
|
113
|
+
| `I press '{value}' key {int} times` | Press key N times |
|
|
114
|
+
| `I hover over '{locator}'` | Hover over element |
|
|
115
|
+
| `I select '{value}' option from '{locator}' dropdown` | Select by text |
|
|
116
|
+
| `I select {int} option from '{locator}' dropdown` | Select by index |
|
|
117
|
+
| `I click '{value}' text in '{locator}' collection` | Click item in collection by text |
|
|
118
|
+
| `I upload '{value}' to '{locator}'` | Upload a file |
|
|
119
|
+
| `I scroll to '{locator}'` | Scroll element into view |
|
|
120
|
+
| `I scroll by '{value}'` | Scroll page by `x, y` offset |
|
|
121
|
+
| `I scroll by '{value}' in '{locator}'` | Scroll within element |
|
|
122
|
+
|
|
123
|
+
### Alerts & Dialogs
|
|
124
|
+
|
|
125
|
+
| Step | Description |
|
|
126
|
+
|------|-------------|
|
|
127
|
+
| `I will accept alert` | Accept the next alert |
|
|
128
|
+
| `I will dismiss alert` | Dismiss the next alert |
|
|
129
|
+
| `I will type '{value}' to alert` | Type into the next prompt |
|
|
130
|
+
|
|
131
|
+
### Validations
|
|
132
|
+
|
|
133
|
+
| Step | Description |
|
|
134
|
+
|------|-------------|
|
|
135
|
+
| `I expect '{locator}' {condition}` | Assert element condition (see Conditions) |
|
|
136
|
+
| `I expect text of '{locator}' {validation} '{value}'` | Assert element text |
|
|
137
|
+
| `I expect value of '{locator}' {validation} '{value}'` | Assert input value |
|
|
138
|
+
| `I expect '{attr}' attribute of '{locator}' {validation} '{value}'` | Assert attribute |
|
|
139
|
+
| `I expect '{prop}' property of '{locator}' {validation} '{value}'` | Assert property |
|
|
140
|
+
| `I expect '{expr}' custom property of '{locator}' {validation} '{value}'` | Assert via JS function (e.g. `$js(e => e.prop('value'))`) |
|
|
141
|
+
| `I expect '{prop}' css property of '{locator}' {validation} '{value}'` | Assert CSS property |
|
|
142
|
+
| `I expect current url {validation} '{value}'` | Assert current URL |
|
|
143
|
+
| `I expect page title {validation} '{value}'` | Assert page title |
|
|
144
|
+
| `I expect number of elements in '{locator}' collection {validation} '{value}'` | Assert collection count |
|
|
145
|
+
| `I expect every element in '{locator}' collection {condition}` | Assert all elements in collection |
|
|
146
|
+
| `I expect text of alert {validation} '{value}'` | Assert alert text |
|
|
147
|
+
|
|
148
|
+
**Conditions:** `to be visible`, `not to be visible`, `to be hidden`, `to be present`, `not to be present`, `to be enabled`, `to be disabled`, `to be in viewport`, `to be clickable`
|
|
149
|
+
|
|
150
|
+
**Validations:** `equal`, `strictly equal`, `deeply equal`, `contain`, `match`, `above`, `below`, `greater than`, `less than`, `have type`, `have property`, `have member`, `include members`, `case insensitive equal`, `satisfy`
|
|
151
|
+
|
|
152
|
+
### Memory Steps
|
|
153
|
+
|
|
154
|
+
| Step | Description |
|
|
155
|
+
|------|-------------|
|
|
156
|
+
| `I save text of '{locator}' as '{key}'` | Save element text |
|
|
157
|
+
| `I save value of '{locator}' as '{key}'` | Save input value |
|
|
158
|
+
| `I save '{attr}' attribute of '{locator}' as '{key}'` | Save attribute value |
|
|
159
|
+
| `I save '{prop}' property of '{locator}' as '{key}'` | Save property value |
|
|
160
|
+
| `I save '{expr}' custom property of '{locator}' as '{key}'` | Save JS expression result |
|
|
161
|
+
| `I save text of every element of '{locator}' collection as '{key}'` | Save array of texts |
|
|
162
|
+
| `I save current url as '{key}'` | Save current URL |
|
|
163
|
+
| `I save page title as '{key}'` | Save page title |
|
|
164
|
+
| `I save bounding rect of '{locator}' as '{key}'` | Save element bounding rect |
|
|
165
|
+
| `I save '{value}' to memory as '{key}'` | Store a literal value |
|
|
166
|
+
| `I set '{key}' = '{value}'` | Alias for save to memory |
|
|
167
|
+
| `I save json to memory as '{key}':` + docstring | Store a JSON object |
|
|
168
|
+
| `I save key-value pairs to memory as '{key}':` + table | Store a map |
|
|
169
|
+
| `I save multiline string to memory as '{key}':` + docstring | Store a multiline string |
|
|
170
|
+
|
|
171
|
+
### Mouse Interactions
|
|
172
|
+
|
|
173
|
+
| Step | Description |
|
|
174
|
+
|------|-------------|
|
|
175
|
+
| `I press {mouseButton} mouse button on '{value}'` | Press mouse button at `x, y` |
|
|
176
|
+
| `I release {mouseButton} mouse button on '{value}'` | Release mouse button at `x, y` |
|
|
177
|
+
| `I move mouse to '{value}'` | Move mouse to `x, y` |
|
|
178
|
+
| `I scroll mouse wheel by '{value}' on '{value}'` | Scroll wheel at `x, y` |
|
|
179
|
+
|
|
180
|
+
**Mouse buttons:** `left`, `right`, `middle`
|
|
181
|
+
|
|
182
|
+
### JavaScript Execution
|
|
183
|
+
|
|
184
|
+
| Step | Description |
|
|
185
|
+
|------|-------------|
|
|
186
|
+
| `I execute '{script}' function` | Execute JS in page context |
|
|
187
|
+
| `I execute '{script}' function and save result as '{key}'` | Execute and save return value |
|
|
188
|
+
| `I execute '{script}' function on '{locator}'` | Execute JS with element as `arguments[0]` |
|
|
189
|
+
| `I execute '{script}' function on '{locator}' and save result as '{key}'` | Execute on element and save result |
|
|
190
|
+
|
|
191
|
+
### Storage & Cookies
|
|
192
|
+
|
|
193
|
+
| Step | Description |
|
|
194
|
+
|------|-------------|
|
|
195
|
+
| `I set '{name}' cookie '{value}'` | Set a cookie |
|
|
196
|
+
| `I save value of '{name}' cookie as '{key}'` | Read a cookie |
|
|
197
|
+
| `I set '{key}' local storage value as '{value}'` | Set localStorage item |
|
|
198
|
+
| `I set '{key}' session storage value as '{value}'` | Set sessionStorage item |
|
|
199
|
+
| `I save value of '{key}' local storage as '{memKey}'` | Read localStorage item |
|
|
200
|
+
| `I save value of '{key}' session storage as '{memKey}'` | Read sessionStorage item |
|
|
201
|
+
|
|
202
|
+
### HTTP Requests
|
|
203
|
+
|
|
204
|
+
| Step | Description |
|
|
205
|
+
|------|-------------|
|
|
206
|
+
| `I create '{method}' request '{key}'` | Create HTTP request object (GET, POST, etc.) |
|
|
207
|
+
| `I create GraphQL request '{key}'` | Create GraphQL request object |
|
|
208
|
+
| `I add '{url}' url to '{request}'` | Set request URL |
|
|
209
|
+
| `I add headers to '{request}':` + table | Add headers (key/value table) |
|
|
210
|
+
| `I add body to '{request}':` + docstring | Set request body (JSON) |
|
|
211
|
+
| `I add form data body to '{request}':` + table | Set multipart form data |
|
|
212
|
+
| `I add query to GraphQL '{request}':` + docstring | Set GraphQL query |
|
|
213
|
+
| `I add variables to GraphQL '{request}':` + docstring | Set GraphQL variables |
|
|
214
|
+
| `I send '{request}' request and save response as '{key}'` | Send request and save response |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Example Feature
|
|
219
|
+
|
|
220
|
+
```gherkin
|
|
221
|
+
Feature: Search
|
|
222
|
+
|
|
223
|
+
Scenario: User searches for a product
|
|
224
|
+
Given I open '$baseUrl' url
|
|
225
|
+
When I type 'laptop' to 'Search Input'
|
|
226
|
+
And I click 'Search Button'
|
|
227
|
+
Then I expect number of elements in 'Results' collection above '0'
|
|
228
|
+
And I save text of 'Results' as 'firstResult'
|
|
229
|
+
And I expect '$firstResult' to contain 'laptop'
|
|
49
230
|
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Development
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Install dependencies
|
|
238
|
+
npm install
|
|
239
|
+
|
|
240
|
+
# Run tests
|
|
50
241
|
npm run test
|
|
51
|
-
```
|
|
52
242
|
|
|
53
|
-
|
|
54
|
-
```
|
|
243
|
+
# Open Cypress GUI
|
|
55
244
|
npm run debug
|
|
56
245
|
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Options passed to {@link defineQavajs} to wire up the qavajs runtime. */
|
|
2
|
+
export interface QavajsOptions {
|
|
3
|
+
/** Root page-object instance or class used to resolve element aliases. */
|
|
4
|
+
pageObject: object;
|
|
5
|
+
/** Memory instance used for expression interpolation and value storage. */
|
|
6
|
+
memory: object;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Initialise the qavajs runtime by attaching the page-object and memory
|
|
11
|
+
* instances to the Cypress `window` object so step definitions can access them.
|
|
12
|
+
* Call this once in your Cypress support file before any tests run.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Page-object and memory configuration.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import defineQavajs from '@qavajs/cypress/defineQavajs';
|
|
19
|
+
* import App from './page_object';
|
|
20
|
+
* import Memory from './memory';
|
|
21
|
+
*
|
|
22
|
+
* defineQavajs({ pageObject: new App(), memory: new Memory() });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function defineQavajs(options: QavajsOptions): void;
|
|
26
|
+
|
|
27
|
+
export default defineQavajs;
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Side-effect import that registers all qavajs Cucumber step definitions
|
|
3
|
+
* (actions, validations, memory, HTTP, mouse, storage, etc.) with the
|
|
4
|
+
* `@qavajs/cypress-runner-adapter` runtime.
|
|
5
|
+
*
|
|
6
|
+
* Import this once in your Cypress support file:
|
|
7
|
+
* ```ts
|
|
8
|
+
* import '@qavajs/cypress';
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/lib/actions.js
CHANGED
package/lib/conditionExpect.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
chai.Assertion.addMethod('beClickable', function () {
|
|
2
|
+
const subject = this._obj;
|
|
3
|
+
this.assert(
|
|
4
|
+
subject.is(':visible') && !subject.is(':disabled'),
|
|
5
|
+
'expected #{this} to be clickable',
|
|
6
|
+
'expected #{this} not to be clickable',
|
|
7
|
+
subject
|
|
8
|
+
);
|
|
9
|
+
});
|
|
10
|
+
|
|
1
11
|
chai.Assertion.addMethod('inViewport', function (ER) {
|
|
2
12
|
const subject = this._obj;
|
|
3
13
|
|
|
@@ -21,6 +31,7 @@ chai.Assertion.addMethod('inViewport', function (ER) {
|
|
|
21
31
|
|
|
22
32
|
export const conditionValidations = {
|
|
23
33
|
PRESENT: 'present',
|
|
34
|
+
CLICKABLE: 'clickable',
|
|
24
35
|
VISIBLE: 'visible',
|
|
25
36
|
INVISIBLE: 'invisible',
|
|
26
37
|
ENABLED: 'enabled',
|
|
@@ -37,6 +48,7 @@ export const conditionWaitRegexp = new RegExp(`(${notClause}${toBeClause}${valid
|
|
|
37
48
|
|
|
38
49
|
const expects = {
|
|
39
50
|
[conditionValidations.PRESENT]: 'exist',
|
|
51
|
+
[conditionValidations.CLICKABLE]: 'beClickable',
|
|
40
52
|
[conditionValidations.VISIBLE]: 'be.visible',
|
|
41
53
|
[conditionValidations.INVISIBLE]: 'be.hidden',
|
|
42
54
|
[conditionValidations.ENABLED]: 'be.enabled',
|
package/lib/execute.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { When } from '@qavajs/cypress-runner-adapter';
|
|
2
2
|
|
|
3
|
+
function toFunction(fnContent) {
|
|
4
|
+
if (typeof fnContent !== 'string') return fnContent;
|
|
5
|
+
try {
|
|
6
|
+
return new Function(`return ${fnContent}`);
|
|
7
|
+
} catch (e) {
|
|
8
|
+
throw new Error(`Failed to parse function expression: "${fnContent}"\n${e.message}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
3
12
|
/**
|
|
4
13
|
* Execute client function
|
|
5
14
|
* @param {string} functionKey - memory key of function
|
|
@@ -8,7 +17,7 @@ import { When } from '@qavajs/cypress-runner-adapter';
|
|
|
8
17
|
*/
|
|
9
18
|
When('I execute {value} function', function (functionKey) {
|
|
10
19
|
const fnContent = functionKey.value();
|
|
11
|
-
const fn =
|
|
20
|
+
const fn = toFunction(fnContent);
|
|
12
21
|
cy.window().then(win => {
|
|
13
22
|
fn.apply(win);
|
|
14
23
|
});
|
|
@@ -23,7 +32,7 @@ When('I execute {value} function', function (functionKey) {
|
|
|
23
32
|
*/
|
|
24
33
|
When('I execute {value} function and save result as {value}', function (functionKey, memoryKey) {
|
|
25
34
|
const fnContent = functionKey.value();
|
|
26
|
-
const fn =
|
|
35
|
+
const fn = toFunction(fnContent);
|
|
27
36
|
cy.window().then(win => {
|
|
28
37
|
memoryKey.set(fn.apply(win));
|
|
29
38
|
});
|
|
@@ -38,7 +47,7 @@ When('I execute {value} function and save result as {value}', function (function
|
|
|
38
47
|
*/
|
|
39
48
|
When('I execute {value} function on {locator}', function (functionKey, locator) {
|
|
40
49
|
const fnContent = functionKey.value();
|
|
41
|
-
const fn =
|
|
50
|
+
const fn = toFunction(fnContent);
|
|
42
51
|
cy.window().then(win => {
|
|
43
52
|
locator.then((e) => {
|
|
44
53
|
fn.apply(win, e);
|
|
@@ -57,7 +66,7 @@ When(
|
|
|
57
66
|
'I execute {value} function on {locator} and save result as {value}',
|
|
58
67
|
function (functionKey, locator, memoryKey) {
|
|
59
68
|
const fnContent = functionKey.value();
|
|
60
|
-
const fn =
|
|
69
|
+
const fn = toFunction(fnContent);
|
|
61
70
|
cy.window().then(win => {
|
|
62
71
|
locator.then((e) => {
|
|
63
72
|
memoryKey.set(fn.apply(win, e));
|
package/lib/pageObjects.js
CHANGED
package/lib/valueValidation.js
CHANGED
|
@@ -155,8 +155,7 @@ Then(
|
|
|
155
155
|
cy.then(() => {
|
|
156
156
|
const actualValue = actual.value();
|
|
157
157
|
const expectedValues = dataTable2Array(this, expected);
|
|
158
|
-
|
|
159
|
-
validateAnyOf(actualValue, expectedValues, validation);
|
|
158
|
+
validateAnyOf(actualValue, expectedValues, valueExpect);
|
|
160
159
|
});
|
|
161
160
|
}
|
|
162
161
|
);
|
|
@@ -222,7 +221,6 @@ function validateAllOf(AR, ERs, validation){
|
|
|
222
221
|
for (const ER of ERs) {
|
|
223
222
|
try {
|
|
224
223
|
validation(AR, ER);
|
|
225
|
-
return;
|
|
226
224
|
} catch (err) {
|
|
227
225
|
errorCollector.push(err);
|
|
228
226
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qavajs/cypress",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "qavajs for cypress runner",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./index.d.ts",
|
|
10
|
+
"default": "./index.js"
|
|
11
|
+
},
|
|
12
|
+
"./po": {
|
|
13
|
+
"types": "./po.d.ts",
|
|
14
|
+
"default": "./po.js"
|
|
15
|
+
},
|
|
16
|
+
"./defineQavajs": {
|
|
17
|
+
"types": "./defineQavajs.d.ts",
|
|
18
|
+
"default": "./defineQavajs.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
6
21
|
"scripts": {
|
|
7
22
|
"debug": "cypress open --config-file test-e2e/cypress.config.js",
|
|
8
23
|
"debug:it": "MODE=it cypress open --config-file test-e2e/cypress.config.js",
|
|
@@ -28,9 +43,12 @@
|
|
|
28
43
|
"homepage": "https://github.com/qavajs/cypress#readme",
|
|
29
44
|
"author": "Alexandr Galichenko",
|
|
30
45
|
"license": "MIT",
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
},
|
|
31
49
|
"devDependencies": {
|
|
32
|
-
"@qavajs/cypress-runner-adapter": "^1.
|
|
33
|
-
"@qavajs/memory": "^1.
|
|
34
|
-
"cypress": "^15.
|
|
50
|
+
"@qavajs/cypress-runner-adapter": "^1.11.0",
|
|
51
|
+
"@qavajs/memory": "^1.11.0",
|
|
52
|
+
"cypress": "^15.15.0"
|
|
35
53
|
}
|
|
36
54
|
}
|
package/po.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Determines how a selector is resolved against the DOM. */
|
|
2
|
+
export type SelectorType = 'simple' | 'template' | 'native';
|
|
3
|
+
|
|
4
|
+
/** Represents a page-object element definition. */
|
|
5
|
+
export declare class Selector {
|
|
6
|
+
/** selector string */
|
|
7
|
+
selector: string | null;
|
|
8
|
+
/** Resolution strategy used when traversing the element chain. */
|
|
9
|
+
type: SelectorType;
|
|
10
|
+
/** Optional component class whose properties describe child elements. */
|
|
11
|
+
component?: new () => object;
|
|
12
|
+
|
|
13
|
+
constructor(selector: string | null, type?: SelectorType);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Attach a component class to this selector so its properties can be
|
|
17
|
+
* used as child element aliases.
|
|
18
|
+
* @param component - Component class whose instance defines child aliases.
|
|
19
|
+
*/
|
|
20
|
+
as(component: new () => object): this;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface LocatorFn {
|
|
24
|
+
/**
|
|
25
|
+
* Create a simple selector entry.
|
|
26
|
+
* @param selector - Selector string.
|
|
27
|
+
*/
|
|
28
|
+
(selector: string): Selector;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create a template selector whose final value is produced by calling
|
|
32
|
+
* `Alias (argument)` at query time, allowing dynamic substitution.
|
|
33
|
+
* @param selector - Function that receives the runtime argument and returns the selector string.
|
|
34
|
+
*/
|
|
35
|
+
template(selector: (argument: string) => string): Selector;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a native selector resolved via a custom Cypress command chain.
|
|
39
|
+
* The function receives context at query time and must return a Chainable.
|
|
40
|
+
* @param selector - Function that builds and returns a Cypress Chainable.
|
|
41
|
+
*/
|
|
42
|
+
native(selector: (ctx: { parent: Cypress.Chainable; cy: Cypress.cy; argument: string }) => Cypress.Chainable): Selector;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create a component-only node with no selector of its own.
|
|
46
|
+
* Useful when the root of a sub-tree is already in scope.
|
|
47
|
+
* @param component - Component class whose instance defines child aliases.
|
|
48
|
+
*/
|
|
49
|
+
as(component: new () => object): Selector;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Factory for building page-object element definitions. */
|
|
53
|
+
export declare const locator: LocatorFn;
|