ShadowWolf1999 commited on
Commit
b35b6d0
·
verified ·
1 Parent(s): 9e71caf

对当前页面进行 美化 首先 用例都是和 fsd 或者userstory绑定的。 另外给出各种类型的用例 并且 可以随时编辑 最好是jira风格

Browse files
Files changed (3) hide show
  1. components/testcase-dashboard.js +239 -20
  2. index.html +15 -4
  3. style.css +17 -1
components/testcase-dashboard.js CHANGED
@@ -21,15 +21,16 @@ class TestcaseDashboard extends HTMLElement {
21
  min-height: 100vh;
22
  background: var(--jira-bg);
23
  }
24
-
25
  .header {
26
  background: linear-gradient(135deg, var(--jira-blue) 0%, var(--jira-purple) 100%);
27
  color: white;
28
  padding: 1.5rem 2rem;
29
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
 
 
 
30
  }
31
-
32
- .filter-bar {
33
  display: flex;
34
  gap: 0.75rem;
35
  padding: 1rem;
@@ -71,16 +72,100 @@ class TestcaseDashboard extends HTMLElement {
71
  color: var(--jira-blue);
72
  font-weight: 600;
73
  }
74
-
75
  .testcase-card {
76
  background: var(--jira-card-bg);
77
  border: 1px solid var(--jira-border);
78
  border-radius: 4px;
79
  margin-bottom: 0.75rem;
80
  box-shadow: 0 1px 1px rgba(9, 30, 66, 0.25);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
- .status-indicator {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  width: 4px;
85
  height: 100%;
86
  position: absolute;
@@ -117,14 +202,61 @@ class TestcaseDashboard extends HTMLElement {
117
  grid-template-columns: 1fr 300px;
118
  gap: 1.5rem;
119
  }
120
-
121
  .stats-card {
122
  background: var(--jira-card-bg);
123
  border-radius: 4px;
124
  padding: 1rem;
125
  box-shadow: 0 1px 1px rgba(9, 30, 66, 0.25);
 
 
126
  }
127
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
  <div class="header">
130
  <div class="container">
@@ -174,13 +306,36 @@ class TestcaseDashboard extends HTMLElement {
174
  <div class="stats-grid">
175
  ${this.generateStats()}
176
  </div>
177
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  </aside>
179
  </div>
180
  </div>
181
  `;
182
  }
183
-
184
  generateTestCases() {
185
  const testCases = [
186
  {
@@ -189,7 +344,12 @@ class TestcaseDashboard extends HTMLElement {
189
  type: 'Manual',
190
  status: 'Passed',
191
  stage: 'SIT',
192
- priority: 'High'
 
 
 
 
 
193
  },
194
  {
195
  id: 'TC-002',
@@ -197,7 +357,12 @@ class TestcaseDashboard extends HTMLElement {
197
  type: 'API Auto',
198
  status: 'Failed',
199
  stage: 'UAT',
200
- priority: 'Medium'
 
 
 
 
 
201
  },
202
  {
203
  id: 'TC-003',
@@ -205,14 +370,51 @@ class TestcaseDashboard extends HTMLElement {
205
  type: 'UI Auto',
206
  status: 'Pending',
207
  stage: 'PVT',
208
- priority: 'Low'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  }
210
  ];
211
-
212
- return testCases.map(tc => `
213
- <div class="testcase-card">
214
  <div class="status-indicator status-${tc.status.toLowerCase()}"></div>
215
- <div class="p-4">
 
 
 
 
 
 
 
216
  <div class="flex items-center">
217
  <div class="type-icon type-${tc.type.toLowerCase().replace(' ', '-')}">
218
  ${this.getTypeIcon(tc.type)}
@@ -222,12 +424,25 @@ class TestcaseDashboard extends HTMLElement {
222
  <div class="text-sm text-gray-600">${tc.id} • ${tc.stage}</div>
223
  </div>
224
  <div class="ml-auto">
225
- <span class="priority-badge">${tc.priority}</span>
226
  </div>
227
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  </div>
229
  </div>
230
- `).join('');
231
  }
232
 
233
  generateStats() {
@@ -250,12 +465,16 @@ class TestcaseDashboard extends HTMLElement {
250
  </div>
251
  `;
252
  }
253
-
254
  getTypeIcon(type) {
255
  const icons = {
256
  'Manual': '👨‍💻',
257
  'UI Auto': '🖥️',
258
- 'API Auto': '🔌'
 
 
 
 
 
259
  };
260
  return icons[type] || '📋';
261
  }
 
21
  min-height: 100vh;
22
  background: var(--jira-bg);
23
  }
 
24
  .header {
25
  background: linear-gradient(135deg, var(--jira-blue) 0%, var(--jira-purple) 100%);
26
  color: white;
27
  padding: 1.5rem 2rem;
28
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
29
+ position: sticky;
30
+ top: 0;
31
+ z-index: 100;
32
  }
33
+ .filter-bar {
 
34
  display: flex;
35
  gap: 0.75rem;
36
  padding: 1rem;
 
72
  color: var(--jira-blue);
73
  font-weight: 600;
74
  }
 
75
  .testcase-card {
76
  background: var(--jira-card-bg);
77
  border: 1px solid var(--jira-border);
78
  border-radius: 4px;
79
  margin-bottom: 0.75rem;
80
  box-shadow: 0 1px 1px rgba(9, 30, 66, 0.25);
81
+ transition: all 0.2s ease;
82
+ position: relative;
83
+ overflow: hidden;
84
+ }
85
+
86
+ .testcase-card:hover {
87
+ transform: translateY(-2px);
88
+ box-shadow: 0 4px 8px rgba(9, 30, 66, 0.15);
89
+ }
90
+
91
+ .testcase-card-header {
92
+ display: flex;
93
+ align-items: center;
94
+ padding: 0.75rem 1rem;
95
+ border-bottom: 1px solid var(--jira-border);
96
+ background: rgba(244, 245, 247, 0.5);
97
+ }
98
+
99
+ .testcase-card-body {
100
+ padding: 1rem;
101
+ }
102
+
103
+ .testcase-card-footer {
104
+ display: flex;
105
+ justify-content: space-between;
106
+ padding: 0.75rem 1rem;
107
+ border-top: 1px solid var(--jira-border);
108
+ background: rgba(244, 245, 247, 0.5);
109
+ }
110
+
111
+ .fsd-badge {
112
+ background: #EAE6FF;
113
+ color: #403294;
114
+ padding: 0.25rem 0.5rem;
115
+ border-radius: 3px;
116
+ font-size: 0.75rem;
117
+ font-weight: 500;
118
+ margin-right: 0.5rem;
119
+ }
120
+
121
+ .user-story-badge {
122
+ background: #E3FCEF;
123
+ color: #006644;
124
+ padding: 0.25rem 0.5rem;
125
+ border-radius: 3px;
126
+ font-size: 0.75rem;
127
+ font-weight: 500;
128
  }
129
 
130
+ .priority-badge {
131
+ display: inline-block;
132
+ padding: 0.25rem 0.5rem;
133
+ border-radius: 3px;
134
+ font-size: 0.75rem;
135
+ font-weight: 500;
136
+ }
137
+
138
+ .priority-high {
139
+ background: #FFEBE6;
140
+ color: #DE350B;
141
+ }
142
+
143
+ .priority-medium {
144
+ background: #FFF0B3;
145
+ color: #FF991F;
146
+ }
147
+
148
+ .priority-low {
149
+ background: #E3FCEF;
150
+ color: #00875A;
151
+ }
152
+
153
+ .edit-btn {
154
+ background: transparent;
155
+ border: 1px solid var(--jira-border);
156
+ color: var(--jira-text-sub);
157
+ padding: 0.25rem 0.5rem;
158
+ border-radius: 3px;
159
+ cursor: pointer;
160
+ font-size: 0.75rem;
161
+ transition: all 0.2s;
162
+ }
163
+
164
+ .edit-btn:hover {
165
+ background: rgba(9,30,66,0.08);
166
+ color: var(--jira-blue);
167
+ }
168
+ .status-indicator {
169
  width: 4px;
170
  height: 100%;
171
  position: absolute;
 
202
  grid-template-columns: 1fr 300px;
203
  gap: 1.5rem;
204
  }
 
205
  .stats-card {
206
  background: var(--jira-card-bg);
207
  border-radius: 4px;
208
  padding: 1rem;
209
  box-shadow: 0 1px 1px rgba(9, 30, 66, 0.25);
210
+ position: sticky;
211
+ top: 100px;
212
  }
213
+
214
+ .stats-grid {
215
+ display: grid;
216
+ grid-template-columns: repeat(2, 1fr);
217
+ gap: 1rem;
218
+ margin-top: 1rem;
219
+ }
220
+
221
+ .stat-item {
222
+ background: rgba(244, 245, 247, 0.5);
223
+ border-radius: 4px;
224
+ padding: 0.75rem;
225
+ text-align: center;
226
+ }
227
+
228
+ .stat-value {
229
+ font-size: 1.5rem;
230
+ font-weight: 600;
231
+ }
232
+
233
+ .stat-label {
234
+ font-size: 0.75rem;
235
+ color: var(--jira-text-sub);
236
+ }
237
+
238
+ .type-filter {
239
+ margin-top: 1rem;
240
+ }
241
+
242
+ .type-filter-item {
243
+ display: flex;
244
+ align-items: center;
245
+ padding: 0.5rem;
246
+ border-radius: 4px;
247
+ cursor: pointer;
248
+ }
249
+
250
+ .type-filter-item:hover {
251
+ background: rgba(9,30,66,0.08);
252
+ }
253
+
254
+ .type-filter-count {
255
+ margin-left: auto;
256
+ color: var(--jira-text-sub);
257
+ font-size: 0.75rem;
258
+ }
259
+ </style>
260
 
261
  <div class="header">
262
  <div class="container">
 
306
  <div class="stats-grid">
307
  ${this.generateStats()}
308
  </div>
309
+
310
+ <div class="type-filter">
311
+ <h4 class="mt-4 mb-2">Test Types</h4>
312
+ <div class="type-filter-item">
313
+ <span>👨‍💻 Manual</span>
314
+ <span class="type-filter-count">12</span>
315
+ </div>
316
+ <div class="type-filter-item">
317
+ <span>🖥️ UI Auto</span>
318
+ <span class="type-filter-count">8</span>
319
+ </div>
320
+ <div class="type-filter-item">
321
+ <span>🔌 API Auto</span>
322
+ <span class="type-filter-count">15</span>
323
+ </div>
324
+ <div class="type-filter-item">
325
+ <span>⏱️ Performance</span>
326
+ <span class="type-filter-count">5</span>
327
+ </div>
328
+ <div class="type-filter-item">
329
+ <span>🔒 Security</span>
330
+ <span class="type-filter-count">3</span>
331
+ </div>
332
+ </div>
333
+ </div>
334
  </aside>
335
  </div>
336
  </div>
337
  `;
338
  }
 
339
  generateTestCases() {
340
  const testCases = [
341
  {
 
344
  type: 'Manual',
345
  status: 'Passed',
346
  stage: 'SIT',
347
+ priority: 'High',
348
+ fsd: 'FSD-101',
349
+ userStory: 'US-42',
350
+ description: 'Validate user can authenticate with valid credentials',
351
+ steps: '1. Navigate to login page\n2. Enter valid credentials\n3. Click login button',
352
+ expected: 'User should be authenticated and redirected to dashboard'
353
  },
354
  {
355
  id: 'TC-002',
 
357
  type: 'API Auto',
358
  status: 'Failed',
359
  stage: 'UAT',
360
+ priority: 'Medium',
361
+ fsd: 'FSD-102',
362
+ userStory: 'US-43',
363
+ description: 'Validate API returns correct response format',
364
+ steps: '1. Send GET request to /api/users\n2. Verify response format',
365
+ expected: 'Response should match OpenAPI specification'
366
  },
367
  {
368
  id: 'TC-003',
 
370
  type: 'UI Auto',
371
  status: 'Pending',
372
  stage: 'PVT',
373
+ priority: 'Low',
374
+ fsd: 'FSD-103',
375
+ userStory: 'US-44',
376
+ description: 'Verify dashboard components render correctly',
377
+ steps: '1. Load dashboard page\n2. Check all components',
378
+ expected: 'All components should render without errors'
379
+ },
380
+ {
381
+ id: 'TC-004',
382
+ title: 'Performance benchmark',
383
+ type: 'Performance',
384
+ status: 'Passed',
385
+ stage: 'SIT',
386
+ priority: 'Medium',
387
+ fsd: 'FSD-104',
388
+ userStory: 'US-45',
389
+ description: 'Measure API response times under load',
390
+ steps: '1. Run load test with 1000 concurrent users\n2. Record response times',
391
+ expected: '95% of requests should complete in <500ms'
392
+ },
393
+ {
394
+ id: 'TC-005',
395
+ title: 'Security vulnerability scan',
396
+ type: 'Security',
397
+ status: 'Failed',
398
+ stage: 'UAT',
399
+ priority: 'High',
400
+ fsd: 'FSD-105',
401
+ userStory: 'US-46',
402
+ description: 'Check for common security vulnerabilities',
403
+ steps: '1. Run OWASP ZAP scan\n2. Analyze results',
404
+ expected: 'No critical vulnerabilities found'
405
  }
406
  ];
407
+ return testCases.map(tc => `
408
+ <div class="testcase-card" data-id="${tc.id}">
 
409
  <div class="status-indicator status-${tc.status.toLowerCase()}"></div>
410
+ <div class="testcase-card-header">
411
+ <span class="fsd-badge">${tc.fsd}</span>
412
+ <span class="user-story-badge">${tc.userStory}</span>
413
+ <button class="edit-btn ml-auto" onclick="this.closest('.testcase-card').classList.toggle('expanded')">
414
+ Edit
415
+ </button>
416
+ </div>
417
+ <div class="testcase-card-body">
418
  <div class="flex items-center">
419
  <div class="type-icon type-${tc.type.toLowerCase().replace(' ', '-')}">
420
  ${this.getTypeIcon(tc.type)}
 
424
  <div class="text-sm text-gray-600">${tc.id} • ${tc.stage}</div>
425
  </div>
426
  <div class="ml-auto">
427
+ <span class="priority-badge priority-${tc.priority.toLowerCase()}">${tc.priority}</span>
428
  </div>
429
  </div>
430
+ <div class="mt-3">
431
+ <div class="text-sm"><strong>Description:</strong> ${tc.description}</div>
432
+ <div class="text-sm mt-1"><strong>Steps:</strong><pre>${tc.steps}</pre></div>
433
+ <div class="text-sm mt-1"><strong>Expected:</strong> ${tc.expected}</div>
434
+ </div>
435
+ </div>
436
+ <div class="testcase-card-footer">
437
+ <div class="text-xs text-gray-500">Last updated: ${new Date().toLocaleDateString()}</div>
438
+ <div class="flex gap-2">
439
+ <button class="edit-btn">Comment</button>
440
+ <button class="edit-btn">Attach</button>
441
+ <button class="edit-btn">Clone</button>
442
+ </div>
443
  </div>
444
  </div>
445
+ `).join('');
446
  }
447
 
448
  generateStats() {
 
465
  </div>
466
  `;
467
  }
 
468
  getTypeIcon(type) {
469
  const icons = {
470
  'Manual': '👨‍💻',
471
  'UI Auto': '🖥️',
472
+ 'API Auto': '🔌',
473
+ 'Performance': '⏱️',
474
+ 'Security': '🔒',
475
+ 'Accessibility': '♿',
476
+ 'Compatibility': '🔄',
477
+ 'Regression': '🔁'
478
  };
479
  return icons[type] || '📋';
480
  }
index.html CHANGED
@@ -4,16 +4,27 @@
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>TestCase Visualizer Pro</title>
8
- <meta name="description" content="TestCase Visualizer Pro - Visualize your FSD test cases with clarity">
9
- <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
12
  <link rel="stylesheet" href="style.css">
13
  </head>
14
  <body>
15
  <testcase-dashboard></testcase-dashboard>
16
-
17
  <script src="components/testcase-dashboard.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
18
  </body>
19
  </html>
 
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>FSD Test Case Manager | Jira Style</title>
8
+ <meta name="description" content="FSD Test Case Manager - Jira-style interface for managing test cases linked to FSDs and User Stories">
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
12
  <link rel="stylesheet" href="style.css">
13
  </head>
14
  <body>
15
  <testcase-dashboard></testcase-dashboard>
 
16
  <script src="components/testcase-dashboard.js"></script>
17
+ <script>
18
+ // Simple edit functionality demonstration
19
+ document.addEventListener('click', function(e) {
20
+ if (e.target.classList.contains('edit-btn')) {
21
+ const card = e.target.closest('.testcase-card');
22
+ if (card) {
23
+ // In a real app, this would open a modal or inline editor
24
+ alert(`Editing test case ${card.dataset.id}`);
25
+ }
26
+ }
27
+ });
28
+ </script>
29
  </body>
30
  </html>
style.css CHANGED
@@ -31,7 +31,23 @@ body {
31
  .text-red-600 {
32
  color: #DE350B;
33
  }
34
-
35
  .text-yellow-600 {
36
  color: #FF991F;
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  .text-red-600 {
32
  color: #DE350B;
33
  }
 
34
  .text-yellow-600 {
35
  color: #FF991F;
36
  }
37
+
38
+ .mt-1 { margin-top: 0.25rem; }
39
+ .mt-2 { margin-top: 0.5rem; }
40
+ .mt-3 { margin-top: 0.75rem; }
41
+ .mt-4 { margin-top: 1rem; }
42
+ .mb-2 { margin-bottom: 0.5rem; }
43
+
44
+ .gap-2 { gap: 0.5rem; }
45
+
46
+ pre {
47
+ white-space: pre-wrap;
48
+ font-family: inherit;
49
+ margin: 0.5rem 0;
50
+ padding: 0.5rem;
51
+ background: rgba(9,30,66,0.04);
52
+ border-radius: 3px;
53
+ }