assuremind 1.3.0 → 1.4.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/README.md +63 -1
- package/dist/cli/index.js +248 -194
- package/dist/index.d.mts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +9 -9
- package/dist/index.mjs +12 -12
- package/docs/STUDIO.md +96 -1
- package/docs/WRITING-STEPS.md +171 -0
- package/package.json +4 -2
- package/templates/docs/WRITING-STEPS.md +171 -0
- package/ui/dist/assets/index-DqkGvedS.js +1024 -0
- package/ui/dist/assets/index-Dry-Q0Et.css +1 -0
- package/ui/dist/index.html +15 -15
- package/ui/dist/assets/index-Bkr40QZS.js +0 -942
- package/ui/dist/assets/index-Bz5b82ao.css +0 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Writing Test Steps
|
|
2
|
+
|
|
3
|
+
A reference for describing test steps in plain English. Type a step in the **Test Editor** (or `assuremind generate`) and AssureMind turns it into Playwright code.
|
|
4
|
+
|
|
5
|
+
Two engines handle generation:
|
|
6
|
+
- **⚡ Template engine** — deterministic, zero AI cost. Handles the common phrasings below (marked ⚡).
|
|
7
|
+
- **AI engine** — handles anything else, and (with **MCP** on) sees the real page to pick accurate locators.
|
|
8
|
+
|
|
9
|
+
Tips that apply everywhere:
|
|
10
|
+
- Put the **target name in quotes** for reliability: `Click the "Sign in" button`.
|
|
11
|
+
- Insert dynamic data with the **Fake Data** picker (`{{FAKE_*}}`) and uploaded files with the **Files** picker (`{{FILE:name}}`).
|
|
12
|
+
- Reference saved values with `{{VAR_NAME}}`; `{{BASE_URL}}` is your configured base URL.
|
|
13
|
+
- Prefix any assertion with **"Soft"** to keep running on failure (`Soft verify …`).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## UI steps
|
|
18
|
+
|
|
19
|
+
### Navigation ⚡
|
|
20
|
+
```text
|
|
21
|
+
Go to https://example.com
|
|
22
|
+
Navigate to /dashboard
|
|
23
|
+
Open https://demoqa.com/upload-download
|
|
24
|
+
Go back
|
|
25
|
+
Refresh the page
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Click — buttons, links, tabs ⚡
|
|
29
|
+
Name the role so the right locator is used (`getByRole`):
|
|
30
|
+
```text
|
|
31
|
+
Click the "Login" button
|
|
32
|
+
Click on "Submit"
|
|
33
|
+
Click the "Dashboard" link
|
|
34
|
+
Click the "Settings" tab
|
|
35
|
+
Double click the "Row 1" element
|
|
36
|
+
Right click the "File" element
|
|
37
|
+
```
|
|
38
|
+
> The role word should match the element's **actual ARIA role**. A control that looks like a button but is `<a role="button">` is still a button; a plain `<a href>` is a link.
|
|
39
|
+
|
|
40
|
+
### Text input ⚡
|
|
41
|
+
```text
|
|
42
|
+
Enter "deepak" in the Username field
|
|
43
|
+
Type {{FAKE_INTERNET_EMAIL}} in the Email field
|
|
44
|
+
Fill "secret123" in the Password field # password → getByLabel automatically
|
|
45
|
+
Enter {{FAKE_NUMBER_INT}} in the Quantity field # number → spinbutton role
|
|
46
|
+
Clear the Search field
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Dropdowns, checkboxes, radios ⚡
|
|
50
|
+
```text
|
|
51
|
+
Select "India" from the Country dropdown
|
|
52
|
+
Check the "Remember me" checkbox
|
|
53
|
+
Uncheck the "Subscribe" checkbox
|
|
54
|
+
Select the "Male" radio button
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Keyboard ⚡
|
|
58
|
+
```text
|
|
59
|
+
Press Enter
|
|
60
|
+
Press Escape
|
|
61
|
+
Press Tab
|
|
62
|
+
Press "Control+A"
|
|
63
|
+
Type "hello" and press Enter
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Waits, scroll, hover, screenshot ⚡
|
|
67
|
+
```text
|
|
68
|
+
Wait for 2 seconds
|
|
69
|
+
Wait for the page to load
|
|
70
|
+
Scroll down
|
|
71
|
+
Scroll to bottom
|
|
72
|
+
Hover over the "Profile" menu
|
|
73
|
+
Take a screenshot
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### File upload ⚡
|
|
77
|
+
Upload a file with the **Files** picker, then reference its `{{FILE:name}}` token:
|
|
78
|
+
```text
|
|
79
|
+
Upload {{FILE:resume.pdf}} to the Resume field
|
|
80
|
+
Upload {{FILE:resume.pdf}} to the Resume field and wait for 'Upload complete' # most reliable
|
|
81
|
+
Upload {{FILE:photo.png}} # page's file input
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### File download ⚡
|
|
85
|
+
Downloads are auto-captured (Reports → Downloads, and attached to Allure). The step waits until the file finishes:
|
|
86
|
+
```text
|
|
87
|
+
Download the "Export CSV" link
|
|
88
|
+
Click the "Download" button to download
|
|
89
|
+
Download the file by clicking "Report PDF"
|
|
90
|
+
Click "Download invoice" and wait for download
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Assertions ⚡
|
|
94
|
+
```text
|
|
95
|
+
Verify "Welcome back" is visible
|
|
96
|
+
Verify "Error" is not visible
|
|
97
|
+
Verify the page title is "Dashboard"
|
|
98
|
+
Verify the URL contains "/dashboard"
|
|
99
|
+
Verify the "Email" field has value "user@test.com"
|
|
100
|
+
Soft verify "Saved successfully" is visible # continues on failure
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Scenarios the AI handles (MCP recommended)
|
|
104
|
+
```text
|
|
105
|
+
Login as admin using {{ADMIN_EMAIL}} and {{DEFAULT_PASSWORD}}
|
|
106
|
+
Click the "Submit" button inside the payment iframe
|
|
107
|
+
Fill the card number "4111111111111111" in the Stripe iframe
|
|
108
|
+
Accept the confirmation dialog after clicking "Delete"
|
|
109
|
+
Verify the table has 5 rows
|
|
110
|
+
Click the element inside the shadow DOM component
|
|
111
|
+
```
|
|
112
|
+
- **iframes** → wrapped in `page.frameLocator(...)` automatically.
|
|
113
|
+
- **shadow DOM** → locator chaining (`page.locator('host').locator('inner')`).
|
|
114
|
+
- **dialogs** → a `page.once('dialog', …)` handler is added before the trigger.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## API steps
|
|
119
|
+
|
|
120
|
+
Mark a suite/case as **API** type. Steps use Playwright's `page.request` API. Use `{{BASE_URL}}` and saved variables.
|
|
121
|
+
|
|
122
|
+
### Basic requests
|
|
123
|
+
```text
|
|
124
|
+
Send a GET request to {{BASE_URL}}/api/users and verify status is 200
|
|
125
|
+
Send a POST request to {{BASE_URL}}/api/users with body { "name": "John", "email": "john@test.com" } and verify status 201
|
|
126
|
+
Send a PUT request to {{BASE_URL}}/api/users/1 with body { "name": "Jane" }
|
|
127
|
+
Send a DELETE request to {{BASE_URL}}/api/users/1 and verify status 204
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Auth — extract and reuse a token
|
|
131
|
+
```text
|
|
132
|
+
POST to {{BASE_URL}}/api/login with { "email": "{{ADMIN_EMAIL}}", "password": "{{DEFAULT_PASSWORD}}" }, save token as AUTH_TOKEN
|
|
133
|
+
GET {{BASE_URL}}/api/profile with Authorization Bearer {{AUTH_TOKEN}} and verify status 200
|
|
134
|
+
```
|
|
135
|
+
- "save / store / extract … as NAME" → `context.setVariable('NAME', …)`.
|
|
136
|
+
- `{{AUTH_TOKEN}}` (or `context.getVariable`) reuses it in later steps/cases.
|
|
137
|
+
|
|
138
|
+
### Assertions on the response
|
|
139
|
+
```text
|
|
140
|
+
Verify the response status is 200
|
|
141
|
+
Verify the response body has property "id"
|
|
142
|
+
Verify the response field "name" equals "Admin"
|
|
143
|
+
Verify the response has 5 users
|
|
144
|
+
Verify the content-type header contains "application/json"
|
|
145
|
+
Verify the response time is under 500 ms
|
|
146
|
+
Soft verify the response status is 200
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Headers, query params, form bodies
|
|
150
|
+
```text
|
|
151
|
+
Send a GET request to {{BASE_URL}}/api/search with query { "q": "phone", "page": "1" }
|
|
152
|
+
Send a POST to {{BASE_URL}}/api/upload with form { "name": "doc", "type": "pdf" }
|
|
153
|
+
Send a GET to {{BASE_URL}}/api/data with header "X-Api-Key" "{{API_KEY}}"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Soft vs hard assertions
|
|
159
|
+
- **Hard** (default): the test stops at the first failure.
|
|
160
|
+
- **Soft**: prefix with **"Soft"** (`Soft verify …`) — failures are collected and the test keeps going. In the Recorder, use `Ctrl+Shift+Click` for a soft assertion.
|
|
161
|
+
|
|
162
|
+
## Variables & dynamic data
|
|
163
|
+
| Token | Resolves to |
|
|
164
|
+
|-------|-------------|
|
|
165
|
+
| `{{BASE_URL}}` | Configured base URL for the active environment |
|
|
166
|
+
| `{{FAKE_PERSON_FULLNAME}}`, `{{FAKE_INTERNET_EMAIL}}`, … | Fresh random data each run (Fake Data picker) |
|
|
167
|
+
| `{{FILE:resume.pdf}}` | `fixtures/uploads/resume.pdf` (Files picker) |
|
|
168
|
+
| `{{MY_VAR}}` | A value from Variables or saved earlier with `context.setVariable` |
|
|
169
|
+
|
|
170
|
+
## Editing generated code
|
|
171
|
+
Every step's code is editable — expand the step (chevron) and edit the code block directly, or click the **✎** to change the instruction and **regenerate** (wand). Use this for anything the engines don't phrase exactly the way your app needs.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assuremind",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "AI-powered codeless UI & API automation framework",
|
|
5
5
|
"author": "Deepak Hiremath",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,12 +41,14 @@
|
|
|
41
41
|
"ai",
|
|
42
42
|
"codeless",
|
|
43
43
|
"no-code",
|
|
44
|
+
"zero-code",
|
|
44
45
|
"test-automation",
|
|
45
46
|
"qa",
|
|
46
47
|
"self-healing",
|
|
47
48
|
"claude",
|
|
48
49
|
"openai",
|
|
49
50
|
"gemini",
|
|
51
|
+
"ollama",
|
|
50
52
|
"ui-testing"
|
|
51
53
|
],
|
|
52
54
|
"scripts": {
|
|
@@ -74,7 +76,7 @@
|
|
|
74
76
|
"@google/generative-ai": "^0.21.0",
|
|
75
77
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
76
78
|
"@playwright/mcp": "^0.0.70",
|
|
77
|
-
"@playwright/test": "^1.
|
|
79
|
+
"@playwright/test": "^1.60.0",
|
|
78
80
|
"allure-commandline": "^2.38.1",
|
|
79
81
|
"allure-js-commons": "^3.0.0",
|
|
80
82
|
"allure-playwright": "^3.0.0",
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Writing Test Steps
|
|
2
|
+
|
|
3
|
+
A reference for describing test steps in plain English. Type a step in the **Test Editor** (or `assuremind generate`) and AssureMind turns it into Playwright code.
|
|
4
|
+
|
|
5
|
+
Two engines handle generation:
|
|
6
|
+
- **⚡ Template engine** — deterministic, zero AI cost. Handles the common phrasings below (marked ⚡).
|
|
7
|
+
- **AI engine** — handles anything else, and (with **MCP** on) sees the real page to pick accurate locators.
|
|
8
|
+
|
|
9
|
+
Tips that apply everywhere:
|
|
10
|
+
- Put the **target name in quotes** for reliability: `Click the "Sign in" button`.
|
|
11
|
+
- Insert dynamic data with the **Fake Data** picker (`{{FAKE_*}}`) and uploaded files with the **Files** picker (`{{FILE:name}}`).
|
|
12
|
+
- Reference saved values with `{{VAR_NAME}}`; `{{BASE_URL}}` is your configured base URL.
|
|
13
|
+
- Prefix any assertion with **"Soft"** to keep running on failure (`Soft verify …`).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## UI steps
|
|
18
|
+
|
|
19
|
+
### Navigation ⚡
|
|
20
|
+
```text
|
|
21
|
+
Go to https://example.com
|
|
22
|
+
Navigate to /dashboard
|
|
23
|
+
Open https://demoqa.com/upload-download
|
|
24
|
+
Go back
|
|
25
|
+
Refresh the page
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Click — buttons, links, tabs ⚡
|
|
29
|
+
Name the role so the right locator is used (`getByRole`):
|
|
30
|
+
```text
|
|
31
|
+
Click the "Login" button
|
|
32
|
+
Click on "Submit"
|
|
33
|
+
Click the "Dashboard" link
|
|
34
|
+
Click the "Settings" tab
|
|
35
|
+
Double click the "Row 1" element
|
|
36
|
+
Right click the "File" element
|
|
37
|
+
```
|
|
38
|
+
> The role word should match the element's **actual ARIA role**. A control that looks like a button but is `<a role="button">` is still a button; a plain `<a href>` is a link.
|
|
39
|
+
|
|
40
|
+
### Text input ⚡
|
|
41
|
+
```text
|
|
42
|
+
Enter "deepak" in the Username field
|
|
43
|
+
Type {{FAKE_INTERNET_EMAIL}} in the Email field
|
|
44
|
+
Fill "secret123" in the Password field # password → getByLabel automatically
|
|
45
|
+
Enter {{FAKE_NUMBER_INT}} in the Quantity field # number → spinbutton role
|
|
46
|
+
Clear the Search field
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Dropdowns, checkboxes, radios ⚡
|
|
50
|
+
```text
|
|
51
|
+
Select "India" from the Country dropdown
|
|
52
|
+
Check the "Remember me" checkbox
|
|
53
|
+
Uncheck the "Subscribe" checkbox
|
|
54
|
+
Select the "Male" radio button
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Keyboard ⚡
|
|
58
|
+
```text
|
|
59
|
+
Press Enter
|
|
60
|
+
Press Escape
|
|
61
|
+
Press Tab
|
|
62
|
+
Press "Control+A"
|
|
63
|
+
Type "hello" and press Enter
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Waits, scroll, hover, screenshot ⚡
|
|
67
|
+
```text
|
|
68
|
+
Wait for 2 seconds
|
|
69
|
+
Wait for the page to load
|
|
70
|
+
Scroll down
|
|
71
|
+
Scroll to bottom
|
|
72
|
+
Hover over the "Profile" menu
|
|
73
|
+
Take a screenshot
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### File upload ⚡
|
|
77
|
+
Upload a file with the **Files** picker, then reference its `{{FILE:name}}` token:
|
|
78
|
+
```text
|
|
79
|
+
Upload {{FILE:resume.pdf}} to the Resume field
|
|
80
|
+
Upload {{FILE:resume.pdf}} to the Resume field and wait for 'Upload complete' # most reliable
|
|
81
|
+
Upload {{FILE:photo.png}} # page's file input
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### File download ⚡
|
|
85
|
+
Downloads are auto-captured (Reports → Downloads, and attached to Allure). The step waits until the file finishes:
|
|
86
|
+
```text
|
|
87
|
+
Download the "Export CSV" link
|
|
88
|
+
Click the "Download" button to download
|
|
89
|
+
Download the file by clicking "Report PDF"
|
|
90
|
+
Click "Download invoice" and wait for download
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Assertions ⚡
|
|
94
|
+
```text
|
|
95
|
+
Verify "Welcome back" is visible
|
|
96
|
+
Verify "Error" is not visible
|
|
97
|
+
Verify the page title is "Dashboard"
|
|
98
|
+
Verify the URL contains "/dashboard"
|
|
99
|
+
Verify the "Email" field has value "user@test.com"
|
|
100
|
+
Soft verify "Saved successfully" is visible # continues on failure
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Scenarios the AI handles (MCP recommended)
|
|
104
|
+
```text
|
|
105
|
+
Login as admin using {{ADMIN_EMAIL}} and {{DEFAULT_PASSWORD}}
|
|
106
|
+
Click the "Submit" button inside the payment iframe
|
|
107
|
+
Fill the card number "4111111111111111" in the Stripe iframe
|
|
108
|
+
Accept the confirmation dialog after clicking "Delete"
|
|
109
|
+
Verify the table has 5 rows
|
|
110
|
+
Click the element inside the shadow DOM component
|
|
111
|
+
```
|
|
112
|
+
- **iframes** → wrapped in `page.frameLocator(...)` automatically.
|
|
113
|
+
- **shadow DOM** → locator chaining (`page.locator('host').locator('inner')`).
|
|
114
|
+
- **dialogs** → a `page.once('dialog', …)` handler is added before the trigger.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## API steps
|
|
119
|
+
|
|
120
|
+
Mark a suite/case as **API** type. Steps use Playwright's `page.request` API. Use `{{BASE_URL}}` and saved variables.
|
|
121
|
+
|
|
122
|
+
### Basic requests
|
|
123
|
+
```text
|
|
124
|
+
Send a GET request to {{BASE_URL}}/api/users and verify status is 200
|
|
125
|
+
Send a POST request to {{BASE_URL}}/api/users with body { "name": "John", "email": "john@test.com" } and verify status 201
|
|
126
|
+
Send a PUT request to {{BASE_URL}}/api/users/1 with body { "name": "Jane" }
|
|
127
|
+
Send a DELETE request to {{BASE_URL}}/api/users/1 and verify status 204
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Auth — extract and reuse a token
|
|
131
|
+
```text
|
|
132
|
+
POST to {{BASE_URL}}/api/login with { "email": "{{ADMIN_EMAIL}}", "password": "{{DEFAULT_PASSWORD}}" }, save token as AUTH_TOKEN
|
|
133
|
+
GET {{BASE_URL}}/api/profile with Authorization Bearer {{AUTH_TOKEN}} and verify status 200
|
|
134
|
+
```
|
|
135
|
+
- "save / store / extract … as NAME" → `context.setVariable('NAME', …)`.
|
|
136
|
+
- `{{AUTH_TOKEN}}` (or `context.getVariable`) reuses it in later steps/cases.
|
|
137
|
+
|
|
138
|
+
### Assertions on the response
|
|
139
|
+
```text
|
|
140
|
+
Verify the response status is 200
|
|
141
|
+
Verify the response body has property "id"
|
|
142
|
+
Verify the response field "name" equals "Admin"
|
|
143
|
+
Verify the response has 5 users
|
|
144
|
+
Verify the content-type header contains "application/json"
|
|
145
|
+
Verify the response time is under 500 ms
|
|
146
|
+
Soft verify the response status is 200
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Headers, query params, form bodies
|
|
150
|
+
```text
|
|
151
|
+
Send a GET request to {{BASE_URL}}/api/search with query { "q": "phone", "page": "1" }
|
|
152
|
+
Send a POST to {{BASE_URL}}/api/upload with form { "name": "doc", "type": "pdf" }
|
|
153
|
+
Send a GET to {{BASE_URL}}/api/data with header "X-Api-Key" "{{API_KEY}}"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Soft vs hard assertions
|
|
159
|
+
- **Hard** (default): the test stops at the first failure.
|
|
160
|
+
- **Soft**: prefix with **"Soft"** (`Soft verify …`) — failures are collected and the test keeps going. In the Recorder, use `Ctrl+Shift+Click` for a soft assertion.
|
|
161
|
+
|
|
162
|
+
## Variables & dynamic data
|
|
163
|
+
| Token | Resolves to |
|
|
164
|
+
|-------|-------------|
|
|
165
|
+
| `{{BASE_URL}}` | Configured base URL for the active environment |
|
|
166
|
+
| `{{FAKE_PERSON_FULLNAME}}`, `{{FAKE_INTERNET_EMAIL}}`, … | Fresh random data each run (Fake Data picker) |
|
|
167
|
+
| `{{FILE:resume.pdf}}` | `fixtures/uploads/resume.pdf` (Files picker) |
|
|
168
|
+
| `{{MY_VAR}}` | A value from Variables or saved earlier with `context.setVariable` |
|
|
169
|
+
|
|
170
|
+
## Editing generated code
|
|
171
|
+
Every step's code is editable — expand the step (chevron) and edit the code block directly, or click the **✎** to change the instruction and **regenerate** (wand). Use this for anything the engines don't phrase exactly the way your app needs.
|