Skip to content

Commit 9ff92e6

Browse files
committed
refactor: update task-related E2E tests to utilize data-test-id attributes for improved targeting and maintainability
1 parent f07ed35 commit 9ff92e6

7 files changed

Lines changed: 86 additions & 79 deletions

File tree

frontend/web/e2e/task/create-task.spec.ts

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,40 @@ test.describe('创建任务', () => {
1313

1414
test('应该成功创建基本任务', async ({ page }) => {
1515
// 点击"新建任务"按钮
16-
await page.click('button:has-text("新建任务")')
16+
await page.locator('[data-test-id="task-create-button"]').click()
1717

18-
// 等待对话框出现(使用 role="heading" 而非文本)
18+
// 等待对话框出现
1919
await expect(page.getByRole('heading', { name: '新建任务' })).toBeVisible()
2020

2121
// 填写任务标题
22-
await page.fill('input[id="title"]', testTasks.basic.title)
23-
await page.fill('textarea[id="description"]', testTasks.basic.description)
22+
await page.locator('[data-test-id="task-create-title-input"]').fill(testTasks.basic.title)
23+
await page
24+
.locator('[data-test-id="task-create-description-input"]')
25+
.fill(testTasks.basic.description)
2426

2527
// 点击创建按钮
26-
await page.click('button:has-text("创建")')
28+
await page.locator('[data-test-id="task-create-submit-button"]').click()
2729

2830
// 等待对话框关闭
29-
await expect(page.locator('input[id="title"]')).not.toBeVisible()
31+
await expect(page.locator('[data-test-id="task-create-title-input"]')).not.toBeVisible()
3032

3133
// 验证任务出现在列表中(使用 first() 避免重复元素)
3234
await expect(page.locator(`text=${testTasks.basic.title}`).first()).toBeVisible()
3335
})
3436

3537
test('应该能够创建高优先级任务', async ({ page }) => {
36-
await page.click('button:has-text("新建任务")')
38+
await page.locator('[data-test-id="task-create-button"]').click()
3739

38-
await page.fill('input[id="title"]', testTasks.urgent.title)
39-
await page.fill('textarea[id="description"]', testTasks.urgent.description)
40+
await page.locator('[data-test-id="task-create-title-input"]').fill(testTasks.urgent.title)
41+
await page
42+
.locator('[data-test-id="task-create-description-input"]')
43+
.fill(testTasks.urgent.description)
4044

4145
// 选择优先级(在对话框内的 Select 组件)
42-
// 等待对话框内的 SelectTrigger 出现
43-
const dialog = page.locator('[role="dialog"]')
44-
await dialog.locator('button[role="combobox"]').click()
45-
await page.locator('[role="option"]', { hasText: '高' }).click()
46+
await page.locator('[data-test-id="task-create-priority-select"]').click()
47+
await page.locator('[role="option"]:has-text("高")').click()
4648

47-
await page.click('button:has-text("创建")')
49+
await page.locator('[data-test-id="task-create-submit-button"]').click()
4850

4951
// 验证任务创建成功
5052
await expect(page.locator(`text=${testTasks.urgent.title}`).first()).toBeVisible({
@@ -56,24 +58,24 @@ test.describe('创建任务', () => {
5658
})
5759

5860
test('应该能够创建带标签的任务', async ({ page }) => {
59-
await page.click('button:has-text("新建任务")')
61+
await page.locator('[data-test-id="task-create-button"]').click()
6062

61-
await page.fill('input[id="title"]', testTasks.withTags.title)
63+
await page.locator('[data-test-id="task-create-title-input"]').fill(testTasks.withTags.title)
6264

63-
// 添加标签(找到对话框内的标签输入框)
64-
const dialog = page.locator('[role="dialog"]')
65-
const tagInput = dialog.locator('input[placeholder*="标签"]')
65+
// 添加标签
66+
const tagInput = page.locator('[data-test-id="task-create-tag-input"]')
6667

6768
for (const tag of testTasks.withTags.tags || []) {
6869
await tagInput.fill(tag)
6970
// 使用点击"添加"按钮而不是回车(更可靠)
70-
await dialog.locator('button:has-text("添加")').click()
71+
await page.locator('[data-test-id="task-create-tag-add-button"]').click()
7172

7273
// 验证标签已添加到对话框中
74+
const dialog = page.locator('[role="dialog"]')
7375
await expect(dialog.locator(`text="${tag}"`)).toBeVisible()
7476
}
7577

76-
await page.click('button:has-text("创建")')
78+
await page.locator('[data-test-id="task-create-submit-button"]').click()
7779

7880
// 验证任务创建成功(使用 first() 避免重复)
7981
await expect(page.locator(`text=${testTasks.withTags.title}`).first()).toBeVisible({
@@ -82,37 +84,35 @@ test.describe('创建任务', () => {
8284
})
8385

8486
test('空标题应该无法创建', async ({ page }) => {
85-
await page.click('button:has-text("新建任务")')
87+
await page.locator('[data-test-id="task-create-button"]').click()
8688

8789
// 不填写标题,直接点击创建
88-
await page.fill('textarea[id="description"]', 'Only description')
90+
await page.locator('[data-test-id="task-create-description-input"]').fill('Only description')
8991

90-
// 监听对话框alert
91-
page.on('dialog', (dialog) => {
92-
expect(dialog.message()).toContain('标题')
93-
dialog.accept()
94-
})
95-
96-
await page.click('button:has-text("创建")')
92+
// 点击创建按钮
93+
await page.locator('[data-test-id="task-create-submit-button"]').click()
9794

98-
// 等待一下
95+
// 等待验证错误出现
9996
await page.waitForTimeout(500)
10097

101-
// 验证对话框仍然显示(未关闭)
102-
await expect(page.locator('input[id="title"]')).toBeVisible()
98+
// 验证对话框仍然显示(未关闭)- 表单验证失败,对话框应该保持打开
99+
await expect(page.locator('[data-test-id="task-create-title-input"]')).toBeVisible()
100+
101+
// 验证显示验证错误信息
102+
await expect(page.getByText('任务标题不能为空')).toBeVisible()
103103
})
104104

105105
test('取消创建应该关闭对话框', async ({ page }) => {
106-
await page.click('button:has-text("新建任务")')
106+
await page.locator('[data-test-id="task-create-button"]').click()
107107

108108
// 填写部分内容
109-
await page.fill('input[id="title"]', 'Will be cancelled')
109+
await page.locator('[data-test-id="task-create-title-input"]').fill('Will be cancelled')
110110

111111
// 点击取消按钮
112-
await page.click('button:has-text("取消")')
112+
await page.locator('[data-test-id="task-create-cancel-button"]').click()
113113

114114
// 验证对话框已关闭
115-
await expect(page.locator('input[id="title"]')).not.toBeVisible()
115+
await expect(page.locator('[data-test-id="task-create-title-input"]')).not.toBeVisible()
116116

117117
// 验证任务未创建
118118
await expect(page.locator('text=Will be cancelled')).not.toBeVisible()

frontend/web/e2e/task/task-flow.spec.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ test.describe('任务完整流程', () => {
1111
await page.goto('/tasks')
1212

1313
// 2. 创建任务
14-
await page.click('button:has-text("新建任务")')
15-
await page.fill('input[id="title"]', originalTitle)
16-
await page.fill('textarea[id="description"]', 'This task will go through full lifecycle')
17-
await page.click('button:has-text("创建")')
14+
await page.locator('[data-test-id="task-create-button"]').click()
15+
await page.locator('[data-test-id="task-create-title-input"]').fill(originalTitle)
16+
await page
17+
.locator('[data-test-id="task-create-description-input"]')
18+
.fill('This task will go through full lifecycle')
19+
await page.locator('[data-test-id="task-create-submit-button"]').click()
1820

1921
// 验证任务创建成功
2022
const originalTaskHeading = page.locator(`h3:has-text("${originalTitle}")`)
@@ -29,9 +31,9 @@ test.describe('任务完整流程', () => {
2931
await page.locator(`[data-test-id="task-edit-${taskId}"]`).click()
3032

3133
await expect(page.getByRole('heading', { name: '编辑任务' })).toBeVisible()
32-
await page.fill('input[id="edit-title"]', updatedTitle)
33-
await page.fill('textarea[id="edit-description"]', 'Updated description')
34-
await page.click('button:has-text("保存")')
34+
await page.locator('[data-test-id="task-edit-title-input"]').fill(updatedTitle)
35+
await page.locator('[data-test-id="task-edit-description-input"]').fill('Updated description')
36+
await page.locator('[data-test-id="task-edit-submit-button"]').click()
3537

3638
// 等待更新完成
3739
await page.waitForTimeout(1000)
@@ -63,7 +65,7 @@ test.describe('任务完整流程', () => {
6365
await expect(page.getByText('确认删除')).toBeVisible()
6466

6567
// 点击确认删除按钮
66-
await page.click('button:has-text("删除")')
68+
await page.locator('[data-test-id="confirm-dialog-confirm-button"]').click()
6769

6870
// 等待删除完成
6971
await page.waitForTimeout(2000)

frontend/web/e2e/task/task-operations.spec.ts

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ test.describe('任务操作', () => {
1111
const taskTitle = `Task to Complete ${Date.now()}`
1212

1313
// 先创建一个任务
14-
await page.click('button:has-text("新建任务")')
15-
await page.fill('input[id="title"]', taskTitle)
16-
await page.click('button:has-text("创建")')
14+
await page.locator('[data-test-id="task-create-button"]').click()
15+
await page.locator('[data-test-id="task-create-title-input"]').fill(taskTitle)
16+
await page.locator('[data-test-id="task-create-submit-button"]').click()
1717

1818
// 等待任务创建成功
1919
const taskHeading = page.locator(`h3:has-text("${taskTitle}")`)
@@ -37,9 +37,9 @@ test.describe('任务操作', () => {
3737
const taskTitle = `Task to Delete ${Date.now()}`
3838

3939
// 先创建一个任务
40-
await page.click('button:has-text("新建任务")')
41-
await page.fill('input[id="title"]', taskTitle)
42-
await page.click('button:has-text("创建")')
40+
await page.locator('[data-test-id="task-create-button"]').click()
41+
await page.locator('[data-test-id="task-create-title-input"]').fill(taskTitle)
42+
await page.locator('[data-test-id="task-create-submit-button"]').click()
4343

4444
// 等待任务创建成功
4545
const taskHeading = page.locator(`h3:has-text("${taskTitle}")`)
@@ -57,7 +57,7 @@ test.describe('任务操作', () => {
5757
await expect(page.getByText('确认删除')).toBeVisible()
5858

5959
// 点击确认删除按钮
60-
await page.click('button:has-text("删除")')
60+
await page.locator('[data-test-id="confirm-dialog-confirm-button"]').click()
6161

6262
// 等待删除完成(增加等待时间)
6363
await page.waitForTimeout(2000)
@@ -71,9 +71,9 @@ test.describe('任务操作', () => {
7171
const updatedTitle = `Updated Task Title ${Date.now()}`
7272

7373
// 先创建一个任务
74-
await page.click('button:has-text("新建任务")')
75-
await page.fill('input[id="title"]', originalTitle)
76-
await page.click('button:has-text("创建")')
74+
await page.locator('[data-test-id="task-create-button"]').click()
75+
await page.locator('[data-test-id="task-create-title-input"]').fill(originalTitle)
76+
await page.locator('[data-test-id="task-create-submit-button"]').click()
7777

7878
// 等待任务创建成功
7979
const taskHeading = page.locator(`h3:has-text("${originalTitle}")`)
@@ -90,10 +90,10 @@ test.describe('任务操作', () => {
9090
await expect(page.getByRole('heading', { name: '编辑任务' })).toBeVisible()
9191

9292
// 修改标题
93-
await page.fill('input[id="edit-title"]', updatedTitle)
93+
await page.locator('[data-test-id="task-edit-title-input"]').fill(updatedTitle)
9494

9595
// 保存
96-
await page.click('button:has-text("保存")')
96+
await page.locator('[data-test-id="task-edit-submit-button"]').click()
9797

9898
// 等待更新完成
9999
await page.waitForTimeout(1000)
@@ -108,22 +108,20 @@ test.describe('任务操作', () => {
108108
const lowPriorityTask = `Low Priority Task ${Date.now() + 1}`
109109

110110
// 创建高优先级任务
111-
await page.click('button:has-text("新建任务")')
112-
await page.fill('input[id="title"]', highPriorityTask)
111+
await page.locator('[data-test-id="task-create-button"]').click()
112+
await page.locator('[data-test-id="task-create-title-input"]').fill(highPriorityTask)
113113
// 优先级选择器使用 Select 组件
114-
const dialog1 = page.locator('[role="dialog"]')
115-
await dialog1.locator('button[role="combobox"]').click()
114+
await page.locator('[data-test-id="task-create-priority-select"]').click()
116115
await page.locator('[role="option"]:has-text("高")').click()
117-
await page.click('button:has-text("创建")')
116+
await page.locator('[data-test-id="task-create-submit-button"]').click()
118117
await expect(page.locator(`h3:has-text("${highPriorityTask}")`)).toBeVisible({ timeout: 5000 })
119118

120119
// 创建低优先级任务
121-
await page.click('button:has-text("新建任务")')
122-
await page.fill('input[id="title"]', lowPriorityTask)
123-
const dialog2 = page.locator('[role="dialog"]')
124-
await dialog2.locator('button[role="combobox"]').click()
120+
await page.locator('[data-test-id="task-create-button"]').click()
121+
await page.locator('[data-test-id="task-create-title-input"]').fill(lowPriorityTask)
122+
await page.locator('[data-test-id="task-create-priority-select"]').click()
125123
await page.locator('[role="option"]:has-text("低")').click()
126-
await page.click('button:has-text("创建")')
124+
await page.locator('[data-test-id="task-create-submit-button"]').click()
127125
await expect(page.locator(`h3:has-text("${lowPriorityTask}")`)).toBeVisible({ timeout: 5000 })
128126

129127
// 验证两个任务都显示

frontend/web/src/components/ConfirmDialog.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ export function ConfirmDialog({
6464
{description && <AlertDialogDescription>{description}</AlertDialogDescription>}
6565
</AlertDialogHeader>
6666
<AlertDialogFooter>
67-
<AlertDialogCancel disabled={loading}>{cancelText}</AlertDialogCancel>
67+
<AlertDialogCancel disabled={loading} data-test-id="confirm-dialog-cancel-button">
68+
{cancelText}
69+
</AlertDialogCancel>
6870
<AlertDialogAction
6971
onClick={handleConfirm}
7072
disabled={loading}
73+
data-test-id="confirm-dialog-confirm-button"
7174
className={
7275
variant === 'destructive'
7376
? 'bg-destructive text-destructive-foreground hover:bg-destructive/90'

frontend/web/src/features/task/components/TaskCreateDialog.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export function TaskCreateDialog({ open, onOpenChange }: TaskCreateDialogProps)
127127
<FormItem>
128128
<FormLabel>任务标题 *</FormLabel>
129129
<FormControl>
130-
<Input placeholder="输入任务标题" {...field} />
130+
<Input placeholder="输入任务标题" {...field} data-test-id="task-create-title-input" />
131131
</FormControl>
132132
<FormMessage />
133133
</FormItem>
@@ -142,7 +142,7 @@ export function TaskCreateDialog({ open, onOpenChange }: TaskCreateDialogProps)
142142
<FormItem>
143143
<FormLabel>任务描述</FormLabel>
144144
<FormControl>
145-
<Textarea placeholder="输入任务描述" rows={3} {...field} />
145+
<Textarea placeholder="输入任务描述" rows={3} {...field} data-test-id="task-create-description-input" />
146146
</FormControl>
147147
<FormMessage />
148148
</FormItem>
@@ -158,7 +158,7 @@ export function TaskCreateDialog({ open, onOpenChange }: TaskCreateDialogProps)
158158
<FormLabel>优先级</FormLabel>
159159
<Select onValueChange={field.onChange} defaultValue={field.value}>
160160
<FormControl>
161-
<SelectTrigger>
161+
<SelectTrigger data-test-id="task-create-priority-select">
162162
<SelectValue placeholder="选择优先级" />
163163
</SelectTrigger>
164164
</FormControl>
@@ -206,8 +206,9 @@ export function TaskCreateDialog({ open, onOpenChange }: TaskCreateDialogProps)
206206
}
207207
}}
208208
placeholder="输入标签后回车"
209+
data-test-id="task-create-tag-input"
209210
/>
210-
<Button type="button" onClick={handleAddTag} variant="outline">
211+
<Button type="button" onClick={handleAddTag} variant="outline" data-test-id="task-create-tag-add-button">
211212
添加
212213
</Button>
213214
</div>
@@ -241,10 +242,11 @@ export function TaskCreateDialog({ open, onOpenChange }: TaskCreateDialogProps)
241242
setTagInput('')
242243
onOpenChange(false)
243244
}}
245+
data-test-id="task-create-cancel-button"
244246
>
245247
取消
246248
</Button>
247-
<Button type="submit" disabled={createMutation.isPending}>
249+
<Button type="submit" disabled={createMutation.isPending} data-test-id="task-create-submit-button">
248250
{createMutation.isPending ? '创建中...' : '创建'}
249251
</Button>
250252
</DialogFooter>

frontend/web/src/features/task/components/TaskEditDialog.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export function TaskEditDialog({ open, onOpenChange, task }: TaskEditDialogProps
147147
<FormItem>
148148
<FormLabel>任务标题 *</FormLabel>
149149
<FormControl>
150-
<Input placeholder="输入任务标题" {...field} />
150+
<Input placeholder="输入任务标题" {...field} data-test-id="task-edit-title-input" />
151151
</FormControl>
152152
<FormMessage />
153153
</FormItem>
@@ -162,7 +162,7 @@ export function TaskEditDialog({ open, onOpenChange, task }: TaskEditDialogProps
162162
<FormItem>
163163
<FormLabel>任务描述</FormLabel>
164164
<FormControl>
165-
<Textarea placeholder="输入任务描述" rows={3} {...field} />
165+
<Textarea placeholder="输入任务描述" rows={3} {...field} data-test-id="task-edit-description-input" />
166166
</FormControl>
167167
<FormMessage />
168168
</FormItem>
@@ -178,7 +178,7 @@ export function TaskEditDialog({ open, onOpenChange, task }: TaskEditDialogProps
178178
<FormLabel>优先级</FormLabel>
179179
<Select onValueChange={field.onChange} value={field.value}>
180180
<FormControl>
181-
<SelectTrigger>
181+
<SelectTrigger data-test-id="task-edit-priority-select">
182182
<SelectValue placeholder="选择优先级" />
183183
</SelectTrigger>
184184
</FormControl>
@@ -226,8 +226,9 @@ export function TaskEditDialog({ open, onOpenChange, task }: TaskEditDialogProps
226226
}
227227
}}
228228
placeholder="输入标签后回车"
229+
data-test-id="task-edit-tag-input"
229230
/>
230-
<Button type="button" onClick={handleAddTag} variant="outline">
231+
<Button type="button" onClick={handleAddTag} variant="outline" data-test-id="task-edit-tag-add-button">
231232
添加
232233
</Button>
233234
</div>
@@ -261,10 +262,11 @@ export function TaskEditDialog({ open, onOpenChange, task }: TaskEditDialogProps
261262
setTagInput('')
262263
onOpenChange(false)
263264
}}
265+
data-test-id="task-edit-cancel-button"
264266
>
265267
取消
266268
</Button>
267-
<Button type="submit" disabled={updateMutation.isPending}>
269+
<Button type="submit" disabled={updateMutation.isPending} data-test-id="task-edit-submit-button">
268270
{updateMutation.isPending ? '保存中...' : '保存'}
269271
</Button>
270272
</DialogFooter>

frontend/web/src/pages/TasksPage/TasksPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export default function TasksPage() {
9595
{/* 操作栏 */}
9696
<div className="flex justify-between items-center mb-6">
9797
<div className="text-muted-foreground">{tasks.length} 个任务</div>
98-
<Button onClick={() => setIsCreateDialogOpen(true)}>
98+
<Button onClick={() => setIsCreateDialogOpen(true)} data-test-id="task-create-button">
9999
<Plus className="mr-2 h-4 w-4" /> 新建任务
100100
</Button>
101101
</div>

0 commit comments

Comments
 (0)