@sun-asterisk/sungen 2.2.2 → 2.3.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 +66 -37
- package/dist/cli/commands/update.d.ts +3 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +21 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/gherkin-parser/index.d.ts +2 -0
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +17 -3
- package/dist/generators/gherkin-parser/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +8 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/attribute-assertion.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-value-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +12 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +12 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.js +95 -57
- package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +9 -0
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +32 -0
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js +56 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/table-patterns.js +8 -5
- package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +16 -0
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/orchestrator/ai-rules-updater.d.ts +13 -0
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -0
- package/dist/orchestrator/ai-rules-updater.js +157 -0
- package/dist/orchestrator/ai-rules-updater.js.map +1 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +2 -27
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts +1 -0
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +70 -3
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +18 -9
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -4
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -6
- package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +22 -9
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +170 -24
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +118 -12
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +16 -2
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +124 -71
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -5
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +12 -4
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +11 -6
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +22 -9
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +170 -24
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +93 -12
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +16 -2
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +124 -72
- package/dist/orchestrator/templates/readme.md +13 -8
- package/package.json +1 -1
- package/src/cli/commands/update.ts +18 -0
- package/src/cli/index.ts +3 -1
- package/src/generators/gherkin-parser/index.ts +20 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +8 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/attribute-assertion.hbs +3 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-value-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +12 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +12 -1
- package/src/generators/test-generator/patterns/assertion-patterns.ts +106 -65
- package/src/generators/test-generator/patterns/index.ts +41 -0
- package/src/generators/test-generator/patterns/interaction-patterns.ts +58 -1
- package/src/generators/test-generator/patterns/table-patterns.ts +8 -5
- package/src/generators/test-generator/utils/selector-resolver.ts +16 -0
- package/src/orchestrator/ai-rules-updater.ts +139 -0
- package/src/orchestrator/project-initializer.ts +2 -32
- package/src/orchestrator/screen-manager.ts +72 -3
- package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +18 -9
- package/src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -4
- package/src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -6
- package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +22 -9
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +170 -24
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +118 -12
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +16 -2
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +124 -71
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -5
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +12 -4
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +11 -6
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +22 -9
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +170 -24
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +93 -12
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +16 -2
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +124 -72
- package/src/orchestrator/templates/readme.md +13 -8
- package/docs/gherkin standards/gherkin-core-standard.md +0 -428
- package/docs/gherkin standards/gherkin-core-standard.vi.md +0 -513
- package/docs/gherkin-dictionary.md +0 -1071
- package/docs/makeauth.md +0 -225
|
@@ -1,513 +0,0 @@
|
|
|
1
|
-
# Tiêu Chuẩn Gherkin - Cốt Lõi v2
|
|
2
|
-
|
|
3
|
-
**Áp dụng cho: Kiểm thử thủ công & Kiểm thử tự động**
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1️⃣ Định Dạng Scenario (Cấp độ Flow)
|
|
8
|
-
|
|
9
|
-
### Định dạng
|
|
10
|
-
```gherkin
|
|
11
|
-
Scenario: <Ai> <Làm gì> <Để đạt kết quả gì>
|
|
12
|
-
Given ...
|
|
13
|
-
When ...
|
|
14
|
-
Then ...
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### Nguyên tắc
|
|
18
|
-
- **1 Scenario = 1 hành vi nghiệp vụ hoàn chỉnh**
|
|
19
|
-
- **Given**: Trạng thái / điều kiện ban đầu
|
|
20
|
-
- **When**: Hành động chính (trigger)
|
|
21
|
-
- **Then**: Kết quả quan sát được (assertion)
|
|
22
|
-
|
|
23
|
-
### Ví dụ
|
|
24
|
-
```gherkin
|
|
25
|
-
Scenario: User logs in successfully with valid credentials
|
|
26
|
-
Given User is on [Login] page
|
|
27
|
-
When User fill [Email] field with {{valid_email}}
|
|
28
|
-
And User fill [Password] field with {{valid_password}}
|
|
29
|
-
And User click [Submit] button
|
|
30
|
-
Then User see [Dashboard] page
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## 2️⃣ Ngữ Pháp (Cấp độ Step)
|
|
36
|
-
|
|
37
|
-
### Định dạng
|
|
38
|
-
```
|
|
39
|
-
[Keyword] User <Action> [Target Name] <Target Type> <with {{Value}}> <is State>
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 17 Mẫu Pattern
|
|
43
|
-
|
|
44
|
-
| # | Mẫu | Ví dụ |
|
|
45
|
-
|---|------|-------|
|
|
46
|
-
| ① | Hành động đơn giản | `click [Submit] button` |
|
|
47
|
-
| ② | Hành động với dữ liệu | `fill [Email] field with {{email}}` |
|
|
48
|
-
| ③ | Xác nhận trạng thái | `see [Submit] button is disabled` |
|
|
49
|
-
| ④ | Trạng thái với dữ liệu | `see [Panel] dialog with {{title}} is hidden` |
|
|
50
|
-
| ⑤ | Hai đối tượng (kéo thả) | `drag [Card] to [Column]` |
|
|
51
|
-
| ⑥ | Phím toàn cục | `press Enter key` |
|
|
52
|
-
| ⑦ | Phím trên đối tượng | `press Enter on [Search] field` |
|
|
53
|
-
| ⑧ | Chờ thời gian | `wait for 3 seconds` |
|
|
54
|
-
| ⑨ | Chờ element | `wait for [Loader] spinner is hidden` |
|
|
55
|
-
| ⑩ | Cuộn trang | `scroll to [Footer] section` |
|
|
56
|
-
| ⑪ | Chuyển frame | `switch to [Payment] frame` |
|
|
57
|
-
| ⑫ | Có (số lượng/thuộc tính) | `see [Avatar] image has {{src}}` |
|
|
58
|
-
| ⑬ | Ô bảng theo chỉ số hàng | `see [Users] table row 1 [Name] cell {{name}}` |
|
|
59
|
-
| ⑭ | Ô bảng theo bộ lọc hàng | `see [Users] table row {{filter}} [Status] cell {{status}}` |
|
|
60
|
-
| ⑮ | Hành động trong hàng bảng | `click [Edit] button in [Users] table row {{filter}}` |
|
|
61
|
-
| ⑯ | Điều hướng | `is on [Dashboard] page` / `navigate to [Settings] page` |
|
|
62
|
-
| ⑰ | Xác nhận văn bản | `see [Title] heading contains {{text}}` |
|
|
63
|
-
|
|
64
|
-
### Quy tắc
|
|
65
|
-
- ✅ `Actor` + `Action` là **bắt buộc**
|
|
66
|
-
- ✅ `Target` là **bắt buộc** với hầu hết action (trừ `wait for` timeout)
|
|
67
|
-
- ✅ `with {{Value}}` chỉ dùng khi action cần dữ liệu
|
|
68
|
-
- ✅ `is State` để xác nhận trạng thái element
|
|
69
|
-
- ❌ Không viết tự do (free-text)
|
|
70
|
-
- ❌ Không dùng từ đồng nghĩa
|
|
71
|
-
|
|
72
|
-
### Cấu trúc chi tiết
|
|
73
|
-
|
|
74
|
-
| Thành phần | Bắt buộc | Ví dụ |
|
|
75
|
-
|-----------|----------|---------|
|
|
76
|
-
| Actor | ✅ Luôn luôn | `User` |
|
|
77
|
-
| Action | ✅ Luôn luôn | `click`, `fill`, `see` |
|
|
78
|
-
| Target | ✅ Hầu hết | `[Login] button` |
|
|
79
|
-
| Value | ⚠️ Khi cần | `{{valid_email}}` |
|
|
80
|
-
| State | ⚠️ Khi cần | `is disabled` |
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## 3️⃣ Actor (Tác nhân)
|
|
85
|
-
|
|
86
|
-
### Actor được phép
|
|
87
|
-
- ✅ **`User`** (duy nhất)
|
|
88
|
-
|
|
89
|
-
### Quy tắc
|
|
90
|
-
- **Chỉ dùng**: `User`
|
|
91
|
-
- **KHÔNG dùng**: `System`, `Backend`, `API`, `App`
|
|
92
|
-
- Hành vi của hệ thống được verify bằng `Then`, không phải Actor
|
|
93
|
-
|
|
94
|
-
### Ví dụ
|
|
95
|
-
```gherkin
|
|
96
|
-
✅ User is on [Login] page
|
|
97
|
-
✅ User click [Submit] button
|
|
98
|
-
❌ System sends verification email
|
|
99
|
-
❌ Backend validates password
|
|
100
|
-
❌ API returns success response
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
> **Lý do**: Hành vi hệ thống là *kết quả* cần verify, không phải là actor thực hiện bước.
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## 4️⃣ Action (Hành động)
|
|
108
|
-
|
|
109
|
-
### Các Action được phép (20 loại)
|
|
110
|
-
|
|
111
|
-
| Action | Trường hợp sử dụng | Ví dụ |
|
|
112
|
-
|--------|----------|---------|
|
|
113
|
-
| `click` | Click button/link/element | `User click [Submit] button` |
|
|
114
|
-
| `fill` | Nhập text vào input field | `User fill [Email] field with {{email}}` |
|
|
115
|
-
| `select` | Chọn option từ dropdown | `User select [Country] dropdown with {{country}}` |
|
|
116
|
-
| `check` | Đánh dấu checkbox | `User check [Remember me] checkbox` |
|
|
117
|
-
| `uncheck` | Bỏ đánh dấu checkbox | `User uncheck [Newsletter] checkbox` |
|
|
118
|
-
| `toggle` | Bật/tắt switch | `User toggle [Dark mode] switch` |
|
|
119
|
-
| `upload` | Tải file lên | `User upload [Avatar] file with {{avatar_path}}` |
|
|
120
|
-
| `hover` | Di chuột lên element | `User hover [Info] icon` |
|
|
121
|
-
| `drag` | Kéo thả element | `User drag [Card] to [Column]` |
|
|
122
|
-
| `clear` | Xóa nội dung input | `User clear [Search] field` |
|
|
123
|
-
| `see` | Verify hiển thị / trạng thái | `User see [Error] message` |
|
|
124
|
-
| `press` | Nhấn phím bàn phím | `User press Enter key` |
|
|
125
|
-
| `expand` | Mở rộng element | `User expand [Details] row` |
|
|
126
|
-
| `collapse` | Thu gọn element | `User collapse [Details] row` |
|
|
127
|
-
| `double click` | Double click element | `User double click [Cell] cell` |
|
|
128
|
-
| `scroll to` | Cuộn đến element | `User scroll to [Footer] section` |
|
|
129
|
-
| `switch to` | Chuyển sang frame | `User switch to [Payment] frame` |
|
|
130
|
-
| `wait for` | Đợi element/điều kiện | `User wait for [Loader] spinner` |
|
|
131
|
-
| `is on` | Xác nhận đang ở trang | `User is on [Login] page` |
|
|
132
|
-
| `navigate to` | Điều hướng đến trang | `User navigate to [Settings] page` |
|
|
133
|
-
|
|
134
|
-
> **Ghi chú**: `is on` và `navigate to` đều dùng cho điều hướng. `is on` là dạng ưu tiên cho step `Given`.
|
|
135
|
-
|
|
136
|
-
### Quy tắc
|
|
137
|
-
- ✅ Sử dụng **động từ chính xác** từ danh sách trên
|
|
138
|
-
- ❌ Không dùng từ đồng nghĩa: `type`, `enter`, `input`, `verify`, `expect`, v.v.
|
|
139
|
-
- ❌ Không dùng action kết hợp: `click and wait`, `fill and submit`
|
|
140
|
-
|
|
141
|
-
### Anti-patterns (Mẫu sai)
|
|
142
|
-
```gherkin
|
|
143
|
-
❌ User types {{password}} into [Password] field → Dùng: User fill [Password] field with {{password}}
|
|
144
|
-
❌ User presses [Enter] key → Dùng: User press Enter key
|
|
145
|
-
❌ User checks [Terms] checkbox → Dùng: User check [Terms] checkbox
|
|
146
|
-
❌ User verifies [Success] message appears → Dùng: User see [Success] message
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## 5️⃣ Target (Đối tượng)
|
|
152
|
-
|
|
153
|
-
### Định dạng
|
|
154
|
-
```
|
|
155
|
-
[name] <element type>
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Các loại Element (40+)
|
|
159
|
-
|
|
160
|
-
#### Tương tác cơ bản
|
|
161
|
-
|
|
162
|
-
| Loại Element | Khi nào dùng | Ví dụ |
|
|
163
|
-
|--------------|-------------|---------|
|
|
164
|
-
| `button` | Nút có thể click | `[Submit] button` |
|
|
165
|
-
| `link` | Hyperlink | `[Forgot password] link` |
|
|
166
|
-
| `field` | Text input | `[Email] field` |
|
|
167
|
-
| `textarea` | Text area nhiều dòng | `[Message] textarea` |
|
|
168
|
-
| `heading` | Tiêu đề (h1-h6) | `[Welcome] heading` |
|
|
169
|
-
| `text` | Nội dung text | `[Price] text` |
|
|
170
|
-
| `image` | Hình ảnh | `[Avatar] image` |
|
|
171
|
-
| `icon` | Icon/hình ảnh nhỏ | `[Close] icon` |
|
|
172
|
-
|
|
173
|
-
#### Form controls
|
|
174
|
-
|
|
175
|
-
| Loại Element | Khi nào dùng | Ví dụ |
|
|
176
|
-
|--------------|-------------|---------|
|
|
177
|
-
| `checkbox` | Checkbox input | `[Remember me] checkbox` |
|
|
178
|
-
| `radio` | Radio button | `[Payment method] radio` |
|
|
179
|
-
| `switch` | Toggle switch | `[Dark mode] switch` |
|
|
180
|
-
| `dropdown` | Select/combobox | `[Country] dropdown` |
|
|
181
|
-
| `option` | Option trong dropdown | `[Vietnam] option` |
|
|
182
|
-
| `slider` | Thanh trượt | `[Volume] slider` |
|
|
183
|
-
| `uploader` | Vùng upload file | `[Document] uploader` |
|
|
184
|
-
| `file` | File input | `[Avatar] file` |
|
|
185
|
-
|
|
186
|
-
#### Overlay & navigation
|
|
187
|
-
|
|
188
|
-
| Loại Element | Khi nào dùng | Ví dụ |
|
|
189
|
-
|--------------|-------------|---------|
|
|
190
|
-
| `dialog` | Hộp thoại | `[Confirm] dialog` |
|
|
191
|
-
| `modal` | Modal overlay | `[Edit] modal` |
|
|
192
|
-
| `menu` | Menu dropdown | `[Actions] menu` |
|
|
193
|
-
| `menuitem` | Mục trong menu | `[Delete] menuitem` |
|
|
194
|
-
| `tab` | Tab header | `[Settings] tab` |
|
|
195
|
-
| `tabpanel` | Nội dung tab | `[General] tabpanel` |
|
|
196
|
-
| `tooltip` | Tooltip | `[Help] tooltip` |
|
|
197
|
-
| `alert` | Thông báo | `[Error] alert` |
|
|
198
|
-
|
|
199
|
-
#### Cấu trúc & layout
|
|
200
|
-
|
|
201
|
-
| Loại Element | Khi nào dùng | Ví dụ |
|
|
202
|
-
|--------------|-------------|---------|
|
|
203
|
-
| `list` | Danh sách | `[Results] list` |
|
|
204
|
-
| `listitem` | Mục trong danh sách | `[Item 1] listitem` |
|
|
205
|
-
| `table` | Bảng dữ liệu | `[Users] table` |
|
|
206
|
-
| `row` | Hàng trong bảng | `[Row 1] row` |
|
|
207
|
-
| `cell` | Ô trong bảng | `[Name] cell` |
|
|
208
|
-
| `column` | Cột | `[Status] column` |
|
|
209
|
-
| `columnheader` | Tiêu đề cột | `[Name] columnheader` |
|
|
210
|
-
| `region` | Vùng landmark | `[Main] region` |
|
|
211
|
-
| `section` | Section | `[Footer] section` |
|
|
212
|
-
| `nav` | Thanh navigation | `[Main] nav` |
|
|
213
|
-
| `banner` | Banner | `[Top] banner` |
|
|
214
|
-
| `header` | Header | `[Page] header` |
|
|
215
|
-
| `footer` | Footer | `[Page] footer` |
|
|
216
|
-
|
|
217
|
-
#### Đặc biệt
|
|
218
|
-
|
|
219
|
-
| Loại Element | Khi nào dùng | Ví dụ |
|
|
220
|
-
|--------------|-------------|---------|
|
|
221
|
-
| `page` | Toàn bộ trang | `[Login] page` |
|
|
222
|
-
| `spinner` | Loading indicator | `[Loader] spinner` |
|
|
223
|
-
| `progressbar` | Thanh tiến trình | `[Upload] progressbar` |
|
|
224
|
-
| `tree` | Cấu trúc cây | `[Files] tree` |
|
|
225
|
-
| `treeitem` | Mục trong cây | `[Folder] treeitem` |
|
|
226
|
-
| `frame` | Iframe | `[Payment] frame` |
|
|
227
|
-
| `iframe` | Iframe (tương đương frame) | `[Embed] iframe` |
|
|
228
|
-
|
|
229
|
-
### Quy tắc
|
|
230
|
-
- ✅ Dùng **tên có nghĩa nghiệp vụ/UI**, không dùng selector kỹ thuật
|
|
231
|
-
- ✅ Giữ tên **đơn giản và mô tả rõ**
|
|
232
|
-
- ❌ Không dùng CSS selector: `#email`, `.btn-primary`
|
|
233
|
-
- ❌ Không dùng XPath: `//input[@id='email']`
|
|
234
|
-
- ❌ Không dùng ID: `email-input`, `submit-btn-123`
|
|
235
|
-
|
|
236
|
-
### Ví dụ
|
|
237
|
-
```gherkin
|
|
238
|
-
✅ User click [Login] button
|
|
239
|
-
✅ User fill [Email address] field with {{email}}
|
|
240
|
-
✅ User check [Remember me] checkbox
|
|
241
|
-
✅ User toggle [Dark mode] switch
|
|
242
|
-
✅ User see [Welcome back] heading
|
|
243
|
-
|
|
244
|
-
❌ User click [#submit-btn] button
|
|
245
|
-
❌ User fill [input.email-field] field
|
|
246
|
-
❌ User see [div.alert-success] message
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## 6️⃣ Value (Giá trị)
|
|
252
|
-
|
|
253
|
-
### Định dạng
|
|
254
|
-
```
|
|
255
|
-
{{value}}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### Quy ước đặt tên
|
|
259
|
-
- **snake_case** (chữ thường với dấu gạch dưới)
|
|
260
|
-
- Mô tả rõ ràng và theo ngữ cảnh
|
|
261
|
-
|
|
262
|
-
### Quy tắc
|
|
263
|
-
- ✅ Sử dụng cú pháp `{{variable}}`
|
|
264
|
-
- ✅ Tên phản ánh **mục đích của dữ liệu**, không phải nội dung
|
|
265
|
-
- ❌ Không hard-code dữ liệu trong step
|
|
266
|
-
- ❌ Không chứa dữ liệu thật (email, password, token)
|
|
267
|
-
- ❌ Không chứa giá trị theo môi trường (URL, API key)
|
|
268
|
-
|
|
269
|
-
### Ví dụ
|
|
270
|
-
|
|
271
|
-
| ✅ Đúng | ❌ Sai |
|
|
272
|
-
|--------|-------|
|
|
273
|
-
| `{{valid_email}}` | `{{user@example.com}}` |
|
|
274
|
-
| `{{invalid_password}}` | `{{123456}}` |
|
|
275
|
-
| `{{expired_otp}}` | `{{999999}}` |
|
|
276
|
-
| `{{admin_username}}` | `{{admin}}` |
|
|
277
|
-
| `{{product_name}}` | `{{iPhone 15 Pro}}` |
|
|
278
|
-
|
|
279
|
-
### Tổ chức dữ liệu
|
|
280
|
-
```yaml
|
|
281
|
-
# test-data/login.yaml
|
|
282
|
-
valid_email: "user@example.com"
|
|
283
|
-
valid_password: "SecurePass123!"
|
|
284
|
-
invalid_email: "not-an-email"
|
|
285
|
-
expired_otp: "000000"
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## 7️⃣ Assertion (Xác nhận)
|
|
291
|
-
|
|
292
|
-
### Động từ
|
|
293
|
-
- **Chính**: `see` (xác nhận hiển thị / trạng thái)
|
|
294
|
-
|
|
295
|
-
### States (Trạng thái)
|
|
296
|
-
|
|
297
|
-
Thêm `is <state>` vào cuối step `see` hoặc `wait for` để xác nhận trạng thái:
|
|
298
|
-
|
|
299
|
-
| State | Mô tả | Ví dụ |
|
|
300
|
-
|-------|--------|-------|
|
|
301
|
-
| `hidden` | Element bị ẩn | `User see [Modal] dialog is hidden` |
|
|
302
|
-
| `visible` | Element hiển thị | `User see [Banner] section is visible` |
|
|
303
|
-
| `disabled` | Element bị vô hiệu | `User see [Submit] button is disabled` |
|
|
304
|
-
| `enabled` | Element có thể tương tác | `User see [Submit] button is enabled` |
|
|
305
|
-
| `checked` | Checkbox/radio được chọn | `User see [Terms] checkbox is checked` |
|
|
306
|
-
| `unchecked` | Checkbox/radio chưa chọn | `User see [Terms] checkbox is unchecked` |
|
|
307
|
-
| `focused` | Element đang được focus | `User see [Email] field is focused` |
|
|
308
|
-
| `empty` | Element rỗng | `User see [Search] field is empty` |
|
|
309
|
-
| `loading` | Element đang tải | `User see [Content] section is loading` |
|
|
310
|
-
| `selected` | Element được chọn | `User see [Tab 1] tab is selected` |
|
|
311
|
-
| `sorted ascending` | Sắp xếp tăng dần | `User see [Name] columnheader is sorted ascending` |
|
|
312
|
-
| `sorted descending` | Sắp xếp giảm dần | `User see [Name] columnheader is sorted descending` |
|
|
313
|
-
|
|
314
|
-
### Quy tắc
|
|
315
|
-
- ✅ Assertion **chỉ xuất hiện trong `Then`**
|
|
316
|
-
- ✅ Verify **trạng thái hệ thống / output**
|
|
317
|
-
- ✅ Mỗi step = **1 assertion**
|
|
318
|
-
- ❌ Không mô tả hành động của user
|
|
319
|
-
- ❌ Không dùng từ đồng nghĩa: `verify`, `expect`, `check`, `observe`, `validate`
|
|
320
|
-
|
|
321
|
-
### Các mẫu Assertion
|
|
322
|
-
|
|
323
|
-
| Mẫu | Trường hợp sử dụng | Ví dụ |
|
|
324
|
-
|---------|----------|---------|
|
|
325
|
-
| Hiển thị đơn giản | Element có thể nhìn thấy | `User see [Login] button` |
|
|
326
|
-
| Hiển thị với giá trị | Element chứa text cụ thể | `User see [Welcome] heading with {{username}}` |
|
|
327
|
-
| Xác nhận trạng thái | Element ở trạng thái nhất định | `User see [Submit] button is disabled` |
|
|
328
|
-
| Trạng thái với giá trị | Element có giá trị và trạng thái | `User see [Panel] dialog with {{title}} is hidden` |
|
|
329
|
-
| Chứa text | Element chứa text | `User see [Title] heading contains {{text}}` |
|
|
330
|
-
| Có thuộc tính | Element có thuộc tính/giá trị | `User see [Avatar] image has {{src}}` |
|
|
331
|
-
| Verify page | Xác nhận điều hướng | `User is on [Dashboard] page` |
|
|
332
|
-
| Chờ ẩn | Đợi element biến mất | `User wait for [Loader] spinner is hidden` |
|
|
333
|
-
|
|
334
|
-
### Xác nhận bảng (Table Assertions)
|
|
335
|
-
|
|
336
|
-
| Mẫu | Ví dụ |
|
|
337
|
-
|------|-------|
|
|
338
|
-
| Ô theo chỉ số hàng | `User see [Users] table row 1 [Name] cell {{name}}` |
|
|
339
|
-
| Ô theo bộ lọc hàng | `User see [Users] table row {{filter}} [Status] cell {{status}}` |
|
|
340
|
-
| Hành động trong hàng | `User click [Edit] button in [Users] table row {{filter}}` |
|
|
341
|
-
| Đếm số hàng | `User see [Users] table has {{count}} rows` |
|
|
342
|
-
| Bảng rỗng | `User see [Users] table is empty` |
|
|
343
|
-
| Có cột | `User see [Users] table has [Email] column` |
|
|
344
|
-
|
|
345
|
-
### Ví dụ
|
|
346
|
-
```gherkin
|
|
347
|
-
✅ Then User see [Error] alert
|
|
348
|
-
✅ And User see [Dashboard] page
|
|
349
|
-
✅ And User see [Welcome] heading with {{username}}
|
|
350
|
-
✅ And User see [Submit] button is disabled
|
|
351
|
-
✅ And User see [Terms] checkbox is checked
|
|
352
|
-
✅ And User see [Users] table row 1 [Name] cell {{name}}
|
|
353
|
-
|
|
354
|
-
❌ Then User verifies [Error] message
|
|
355
|
-
❌ Then System displays [Dashboard] page
|
|
356
|
-
❌ Then [Success] message appears
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
|
-
## 🏷️ Tags
|
|
362
|
-
|
|
363
|
-
### Scenario Tags
|
|
364
|
-
|
|
365
|
-
| Tag | Mô tả |
|
|
366
|
-
|-----|-------|
|
|
367
|
-
| `@auth:<role>` | Sử dụng trạng thái auth Playwright cho role đã cho |
|
|
368
|
-
| `@no-auth` | Tắt authentication kế thừa |
|
|
369
|
-
| `@steps:<name>` | Đánh dấu scenario là khối step tái sử dụng |
|
|
370
|
-
| `@extend:<name>` | Chèn step từ khối `@steps` trước step hiện tại |
|
|
371
|
-
| `@manual` | Bỏ qua scenario khi sinh code |
|
|
372
|
-
|
|
373
|
-
Tags có thể áp dụng ở **cấp Feature** (kế thừa cho tất cả scenario) hoặc **cấp Scenario** (ghi đè Feature).
|
|
374
|
-
|
|
375
|
-
**Thứ tự ưu tiên Auth**: Scenario kế thừa `@auth` > Scenario gốc `@auth` > Feature `@auth`
|
|
376
|
-
|
|
377
|
-
### Step tái sử dụng (@steps / @extend)
|
|
378
|
-
|
|
379
|
-
Dùng `@steps:<name>` để định nghĩa khối tái sử dụng và `@extend:<name>` để kế thừa:
|
|
380
|
-
|
|
381
|
-
```gherkin
|
|
382
|
-
@auth:user @steps:open-dialog
|
|
383
|
-
Scenario: Open kudos dialog
|
|
384
|
-
Given User is on [Kudo] page
|
|
385
|
-
When User click [Notifications] button
|
|
386
|
-
And User click [Write Kudos] menuitem
|
|
387
|
-
Then User see [Panel] dialog with {{kudo_title}}
|
|
388
|
-
|
|
389
|
-
@auth:user @extend:open-dialog
|
|
390
|
-
Scenario: User sends a thank you message
|
|
391
|
-
Given User is on [Panel] dialog with {{kudo_title}}
|
|
392
|
-
When User click [Search] button
|
|
393
|
-
And User fill [Search] field with {{teammate_name}}
|
|
394
|
-
And User click [Teammate] row with {{teammate_name}}
|
|
395
|
-
And User fill [Title] field with {{teammate_title}}
|
|
396
|
-
And User fill [Message] textarea with {{teammate_message}}
|
|
397
|
-
And User click [Hashtag] button with {{hashtag_1}}
|
|
398
|
-
And User click [Send] button
|
|
399
|
-
And User wait for [Panel] dialog with {{kudo_title}} is hidden
|
|
400
|
-
Then User see [Panel] modal with {{kudo_title}} is hidden
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
**Hành vi:**
|
|
404
|
-
- Scenario `@steps` sinh test riêng VÀ đăng ký step để tái sử dụng
|
|
405
|
-
- Scenario `@extend` nhận step gốc chèn vào đầu — test hoàn toàn độc lập
|
|
406
|
-
- Nhiều scenario có thể extend cùng một khối `@steps`
|
|
407
|
-
- Code sinh ra có comment phân đoạn: `// [from @steps:<name>]`
|
|
408
|
-
|
|
409
|
-
### Annotation cấp Step (cú pháp comment)
|
|
410
|
-
|
|
411
|
-
| Annotation | Hiệu lực |
|
|
412
|
-
|-----------|--------|
|
|
413
|
-
| `# @ignore` | Bỏ qua step này khi sinh code |
|
|
414
|
-
| `# @ignore-testcase` | Bỏ qua toàn bộ scenario khi sinh code |
|
|
415
|
-
| `# @skip-production` | Bỏ qua step trong môi trường production |
|
|
416
|
-
|
|
417
|
-
---
|
|
418
|
-
|
|
419
|
-
## 📋 Ví Dụ Hoàn Chỉnh
|
|
420
|
-
|
|
421
|
-
```gherkin
|
|
422
|
-
Feature: User Authentication
|
|
423
|
-
Path: /auth/login
|
|
424
|
-
|
|
425
|
-
@auth:admin
|
|
426
|
-
Scenario: User logs in successfully with valid credentials
|
|
427
|
-
Given User is on [Login] page
|
|
428
|
-
When User fill [Email] field with {{valid_email}}
|
|
429
|
-
And User fill [Password] field with {{valid_password}}
|
|
430
|
-
And User check [Remember me] checkbox
|
|
431
|
-
And User click [Submit] button
|
|
432
|
-
Then User see [Dashboard] page
|
|
433
|
-
And User see [Welcome] heading with {{username}}
|
|
434
|
-
|
|
435
|
-
@no-auth
|
|
436
|
-
Scenario: User fails to login with invalid credentials
|
|
437
|
-
Given User is on [Login] page
|
|
438
|
-
When User fill [Email] field with {{invalid_email}}
|
|
439
|
-
And User fill [Password] field with {{invalid_password}}
|
|
440
|
-
And User click [Submit] button
|
|
441
|
-
Then User see [Error] alert
|
|
442
|
-
And User see [Submit] button is enabled
|
|
443
|
-
And User see [Login] page
|
|
444
|
-
|
|
445
|
-
@no-auth
|
|
446
|
-
Scenario: User registers with preferred language
|
|
447
|
-
Given User is on [Registration] page
|
|
448
|
-
When User fill [Email] field with {{new_email}}
|
|
449
|
-
And User fill [Password] field with {{new_password}}
|
|
450
|
-
And User select [Language] dropdown with {{preferred_language}}
|
|
451
|
-
And User check [Terms] checkbox
|
|
452
|
-
And User click [Sign up] button
|
|
453
|
-
Then User see [Verification] page
|
|
454
|
-
|
|
455
|
-
Scenario: User manages settings with various controls
|
|
456
|
-
Given User is on [Settings] page
|
|
457
|
-
When User toggle [Dark mode] switch
|
|
458
|
-
And User select [Timezone] dropdown with {{timezone}}
|
|
459
|
-
And User upload [Avatar] file with {{avatar_path}}
|
|
460
|
-
And User press Enter key
|
|
461
|
-
And User scroll to [Save] section
|
|
462
|
-
And User click [Save] button
|
|
463
|
-
And User wait for [Loader] spinner is hidden
|
|
464
|
-
Then User see [Success] alert
|
|
465
|
-
And User see [Dark mode] switch is checked
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
---
|
|
469
|
-
|
|
470
|
-
## ✅ Tham Khảo Nhanh
|
|
471
|
-
|
|
472
|
-
### Nên làm ✅
|
|
473
|
-
- Dùng **20 action chuẩn** từ danh sách action
|
|
474
|
-
- Dùng **`User`** là actor duy nhất
|
|
475
|
-
- Dùng định dạng **`[Target] <element type>`**
|
|
476
|
-
- Dùng **`{{snake_case}}`** cho giá trị
|
|
477
|
-
- Dùng **`is <state>`** cho xác nhận trạng thái
|
|
478
|
-
- Dùng **tags** (`@auth`, `@steps`, `@extend`) để quản lý scenario
|
|
479
|
-
- **1 Scenario = 1 flow nghiệp vụ**
|
|
480
|
-
- **1 Step = 1 action hoặc assertion**
|
|
481
|
-
|
|
482
|
-
### Không nên làm ❌
|
|
483
|
-
- Không dùng từ đồng nghĩa hoặc viết tự do
|
|
484
|
-
- Không dùng system/backend/API làm actor
|
|
485
|
-
- Không dùng selector kỹ thuật (CSS/XPath/ID)
|
|
486
|
-
- Không hard-code dữ liệu trong step
|
|
487
|
-
- Không dùng action kết hợp
|
|
488
|
-
- Không dùng `verify`/`check`/`expect` thay cho `see`
|
|
489
|
-
|
|
490
|
-
---
|
|
491
|
-
|
|
492
|
-
## 🎯 Lợi Ích
|
|
493
|
-
|
|
494
|
-
| Lợi ích | Mô tả |
|
|
495
|
-
|---------|-------------|
|
|
496
|
-
| **Nhất quán** | Cùng 17 mẫu pattern cho tất cả test case |
|
|
497
|
-
| **Dễ đọc** | Người không kỹ thuật cũng hiểu được |
|
|
498
|
-
| **Dễ bảo trì** | Dễ cập nhật khi UI thay đổi |
|
|
499
|
-
| **Sẵn sàng tự động** | Ánh xạ trực tiếp sang Playwright code |
|
|
500
|
-
| **Không mơ hồ** | Mỗi step chỉ có một cách hiểu |
|
|
501
|
-
| **Hỗ trợ công cụ** | Tương thích với framework Sungen v2 |
|
|
502
|
-
| **Tái sử dụng** | `@steps` / `@extend` giúp tái sử dụng flow |
|
|
503
|
-
|
|
504
|
-
---
|
|
505
|
-
|
|
506
|
-
## 📚 Tài Liệu Liên Quan
|
|
507
|
-
- [Từ điển Gherkin](../gherkin-dictionary.md) — Ngữ pháp đầy đủ, 17 mẫu pattern, quy tắc compiler
|
|
508
|
-
|
|
509
|
-
---
|
|
510
|
-
|
|
511
|
-
**Phiên bản**: 2.0
|
|
512
|
-
**Trạng thái**: Final
|
|
513
|
-
**Cập nhật lần cuối**: 19 tháng 3, 2026
|