Skip to content

Commit f598b53

Browse files
committed
chore(FR-2652): update E2E coverage report — admin model store 26/26 (100%)
1 parent 70241d4 commit f598b53

2 files changed

Lines changed: 93 additions & 65 deletions

File tree

e2e/E2E_COVERAGE_REPORT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# E2E Test Coverage Report
22

3-
> **Last Updated:** 2026-04-22
3+
> **Last Updated:** 2026-04-24
44
> **Router Source:** [`react/src/routes.tsx`](../react/src/routes.tsx)
55
> **E2E Root:** [`e2e/`](.)
66
>

e2e/admin-model-card/admin-model-card-delete.spec.ts

Lines changed: 92 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,49 @@ test.describe(
1515
() => {
1616
test.setTimeout(60000);
1717

18+
const createdResources: Array<{ cardName?: string; folderName?: string }> =
19+
[];
20+
1821
test.beforeEach(async ({ page, request }) => {
1922
await loginAsAdmin(page, request);
2023
});
2124

25+
test.afterEach(async ({ page }) => {
26+
const adminModelCardPage = new AdminModelCardPage(page);
27+
for (const r of [...createdResources].reverse()) {
28+
if (r.cardName) {
29+
try {
30+
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
31+
await adminModelCardPage.waitForTableLoad();
32+
await adminModelCardPage.applyNameFilter(r.cardName);
33+
const row = adminModelCardPage.getRowByName(r.cardName);
34+
if (await row.isVisible()) {
35+
await adminModelCardPage.deleteModelCardByName(r.cardName);
36+
}
37+
} catch {
38+
// ignore — card may have already been deleted by the test
39+
}
40+
}
41+
if (r.folderName) {
42+
try {
43+
await moveToTrashAndVerify(page, r.folderName, 'admin-data');
44+
} catch {
45+
// ignore — folder may already be in trash or deleted
46+
}
47+
try {
48+
await deleteForeverAndVerifyFromTrash(
49+
page,
50+
r.folderName,
51+
'admin-data',
52+
);
53+
} catch {
54+
// ignore — folder may already be permanently deleted
55+
}
56+
}
57+
}
58+
createdResources.length = 0;
59+
});
60+
2261
// 5.1 Superadmin can delete a model card via the trash icon with confirmation
2362
test('Superadmin can delete a model card via the trash icon with confirmation', async ({
2463
page,
@@ -29,6 +68,9 @@ test.describe(
2968
const folderName = `e2e-test-delete-single-folder-${timestamp}`;
3069
const cardName = `e2e-test-delete-single-${timestamp}`;
3170

71+
// Track folder for cleanup (card will be deleted by test, folder needs cleanup)
72+
createdResources.push({ folderName });
73+
3274
// Setup: create a dedicated folder and model card
3375
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
3476
await adminModelCardPage.waitForTableLoad();
@@ -47,13 +89,12 @@ test.describe(
4789

4890
const confirmDialog = adminModelCardPage.getDeleteConfirmDialog();
4991

50-
// Verify the confirmation dialog shows description and item name
92+
// Verify the confirmation dialog shows description text
93+
// (For single item + requireConfirmInput, the item list box is removed;
94+
// the card name appears in the description text instead)
5195
await expect(
5296
confirmDialog.getByText(/Are you sure you want to delete/),
5397
).toBeVisible();
54-
await expect(
55-
confirmDialog.getByText(cardName, { exact: true }).first(),
56-
).toBeVisible();
5798
await expect(
5899
confirmDialog.getByText('This action cannot be undone.'),
59100
).toBeVisible();
@@ -83,9 +124,7 @@ test.describe(
83124
'0 items',
84125
);
85126

86-
// Cleanup: move folder to trash then permanently delete
87-
await moveToTrashAndVerify(page, folderName, 'admin-data');
88-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
127+
// Card was successfully deleted — afterEach only needs to clean up the folder
89128
});
90129

91130
// 5.2 Superadmin can cancel a single-delete confirmation without deleting
@@ -98,6 +137,9 @@ test.describe(
98137
const folderName = `e2e-test-no-delete-folder-${timestamp}`;
99138
const cardName = `e2e-test-no-delete-${timestamp}`;
100139

140+
// Track both for cleanup (test does not delete them)
141+
createdResources.push({ cardName, folderName });
142+
101143
// Setup: create a dedicated folder and model card
102144
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
103145
await adminModelCardPage.waitForTableLoad();
@@ -122,11 +164,6 @@ test.describe(
122164

123165
// Verify the model card is still in the table
124166
await expect(adminModelCardPage.getRowByName(cardName)).toBeVisible();
125-
126-
// Cleanup: delete card only, then move folder to trash and permanently delete
127-
await adminModelCardPage.deleteModelCardByName(cardName);
128-
await moveToTrashAndVerify(page, folderName, 'admin-data');
129-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
130167
});
131168

132169
// 5.3 Superadmin can select multiple model cards and delete them in bulk
@@ -144,6 +181,9 @@ test.describe(
144181
`${filterPrefix}-3`,
145182
];
146183

184+
// Track folder for cleanup (cards will be deleted by test)
185+
createdResources.push({ folderName });
186+
147187
// Setup: create a shared folder via the "+" button for the first card,
148188
// then reuse it for the remaining cards
149189
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
@@ -171,7 +211,9 @@ test.describe(
171211
});
172212

173213
// Check the header checkbox to select all visible rows
174-
await adminModelCardPage.getHeaderCheckbox().check();
214+
// Use .click() instead of .check() — Ant Design's "select all" checkbox can be in
215+
// indeterminate state when some rows are pre-selected, and .check() fails in that case.
216+
await adminModelCardPage.getHeaderCheckbox().click();
175217

176218
// Verify the BAISelectionLabel appears showing selected count
177219
await expect(adminModelCardPage.getSelectionLabel()).toBeVisible();
@@ -194,7 +236,9 @@ test.describe(
194236
}
195237

196238
// Type "Delete" in the confirmation input (required for bulk delete)
197-
await bulkDialog.getByRole('textbox').fill('Delete');
239+
// Use getByLabel to find the input via its Form.Item label text, which is more
240+
// robust than getByRole('textbox') when allowClear is present on the Input.
241+
await bulkDialog.getByLabel(/Type.*to confirm/i).fill('Delete');
198242

199243
// Click Delete to confirm
200244
await bulkDialog.getByRole('button', { name: 'Delete' }).click();
@@ -205,10 +249,7 @@ test.describe(
205249
// Verify the selection label disappears
206250
await expect(adminModelCardPage.getSelectionLabel()).toBeHidden();
207251

208-
// Cleanup: model cards were deleted but the shared folder remains;
209-
// move it to trash and permanently delete
210-
await moveToTrashAndVerify(page, folderName, 'admin-data');
211-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
252+
// Cards were deleted by test — afterEach only needs to clean up the shared folder
212253
});
213254

214255
// 5.4 Superadmin can cancel bulk deletion
@@ -220,6 +261,10 @@ test.describe(
220261
const filterPrefix = `e2e-test-bulk-cancel-${timestamp}`;
221262
const cardNames = [`${filterPrefix}-1`, `${filterPrefix}-2`];
222263

264+
// Track both cards and folder for cleanup (test does not delete them)
265+
createdResources.push({ cardName: cardNames[0], folderName });
266+
createdResources.push({ cardName: cardNames[1] });
267+
223268
// Setup: create a shared folder via the "+" button for the first card,
224269
// then reuse it for the second card
225270
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
@@ -267,13 +312,6 @@ test.describe(
267312
for (const name of cardNames) {
268313
await expect(adminModelCardPage.getRowByName(name)).toBeVisible();
269314
}
270-
271-
// Cleanup: delete each model card (card only), then clean up the shared folder
272-
for (const name of cardNames) {
273-
await adminModelCardPage.deleteModelCardByName(name);
274-
}
275-
await moveToTrashAndVerify(page, folderName, 'admin-data');
276-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
277315
});
278316

279317
// 5.5 Superadmin can clear selection using the BAISelectionLabel clear button
@@ -286,6 +324,9 @@ test.describe(
286324
const folderName = `e2e-test-clear-sel-folder-${timestamp}`;
287325
const cardName = `e2e-test-clear-sel-${timestamp}`;
288326

327+
// Track both for cleanup (test does not delete them)
328+
createdResources.push({ cardName, folderName });
329+
289330
// Setup: create a model card so the table has at least one row with a checkbox
290331
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
291332
await adminModelCardPage.waitForTableLoad();
@@ -320,11 +361,6 @@ test.describe(
320361

321362
// Verify the BAISelectionLabel disappears
322363
await expect(adminModelCardPage.getSelectionLabel()).toBeHidden();
323-
324-
// Cleanup: delete the model card then clean up the folder
325-
await adminModelCardPage.deleteModelCardByName(cardName);
326-
await moveToTrashAndVerify(page, folderName, 'admin-data');
327-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
328364
});
329365

330366
// 5.6 Superadmin can select all model cards using the header checkbox
@@ -337,6 +373,9 @@ test.describe(
337373
const folderName = `e2e-test-select-all-folder-${timestamp}`;
338374
const cardName = `e2e-test-select-all-${timestamp}`;
339375

376+
// Track both for cleanup
377+
createdResources.push({ cardName, folderName });
378+
340379
// Setup: create a model card so the table has at least one row
341380
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
342381
await adminModelCardPage.waitForTableLoad();
@@ -370,17 +409,6 @@ test.describe(
370409
selectionText?.match(/(\d+) selected/)?.[1] ?? '0',
371410
);
372411
expect(selectedCount).toBeGreaterThan(0);
373-
374-
// Cleanup: navigate fresh to reset selection state, then delete the model card
375-
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
376-
await adminModelCardPage.waitForTableLoad();
377-
await adminModelCardPage.applyNameFilter(cardName);
378-
await expect(adminModelCardPage.getRowByName(cardName)).toBeVisible({
379-
timeout: 15000,
380-
});
381-
await adminModelCardPage.deleteModelCardByName(cardName);
382-
await moveToTrashAndVerify(page, folderName, 'admin-data');
383-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
384412
});
385413

386414
// 5.7 Superadmin can delete a model card and its associated folder together
@@ -393,6 +421,11 @@ test.describe(
393421
const folderName = `e2e-test-delete-folder-${timestamp}`;
394422
const cardName = `e2e-test-delete-with-folder-${timestamp}`;
395423

424+
// No createdResources.push here — this test fully handles its own cleanup:
425+
// the modal deletes the card, and deleteForeverAndVerifyFromTrash permanently
426+
// removes the folder at the end of the test body. afterEach must not attempt
427+
// to re-clean a folder that no longer exists (it would hang until timeout).
428+
396429
// Create a model card with a new dedicated folder via the "+" button
397430
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
398431
await adminModelCardPage.waitForTableLoad();
@@ -445,20 +478,27 @@ test.describe(
445478
await expect(goToTrashLink).toBeVisible();
446479

447480
// Click "Go to Data > Trash" and verify URL includes folder filter
481+
// The link navigates to /admin-data (not /data) with statusCategory=deleted and folder filter.
482+
// The filter param value may appear URL-encoded in various ways depending on the library
483+
// (e.g. `name+%3D%3D+%22folderName%22` or `name%20%3D%3D%20%22folderName%22`).
484+
// Use decodeURIComponent after re-encoding to normalize before comparison.
448485
await goToTrashLink.click();
449486
await page.waitForURL(
450-
(url) =>
451-
url.pathname === '/data' &&
452-
url.searchParams.get('statusCategory') === 'deleted' &&
453-
url.searchParams.get('filter') === `name == "${folderName}"`,
487+
(url) => {
488+
if (url.pathname !== '/admin-data') return false;
489+
if (url.searchParams.get('statusCategory') !== 'deleted')
490+
return false;
491+
const rawFilter = url.searchParams.get('filter') ?? '';
492+
return rawFilter === `name == "${folderName}"`;
493+
},
454494
{ timeout: 10000 },
455495
);
456496

457497
// Verify the folder row is visible in the trash list and permanently delete it
458498
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
459499
});
460500

461-
// 5.8 Superadmin deletes card only: notification shows correct message and Go to Trash navigates correctly
501+
// 5.8 Superadmin deletes card only: notification shows correct message (no folder link)
462502
test('Superadmin can delete a model card only and navigate to trash without folder filter', async ({
463503
page,
464504
}) => {
@@ -468,6 +508,9 @@ test.describe(
468508
const folderName = `e2e-test-keep-folder-${timestamp}`;
469509
const cardName = `e2e-test-delete-card-only-${timestamp}`;
470510

511+
// Track folder for cleanup (card is deleted by test, folder is kept)
512+
createdResources.push({ folderName });
513+
471514
// Create a model card with a new dedicated folder via the "+" button
472515
await page.goto(`${webuiEndpoint}/admin-serving?tab=model-store`);
473516
await adminModelCardPage.waitForTableLoad();
@@ -495,30 +538,15 @@ test.describe(
495538
// Confirm deletion
496539
await adminModelCardPage.getDeleteConfirmButton().click();
497540

498-
// Verify the notification message for card-only deletion
541+
// When folder is NOT deleted, a message.success() toast is shown (no "Go to Data > Trash" link)
542+
// Verify the success toast for card-only deletion
499543
await expect(
500544
page.getByText(
501545
'Model card has been deleted. The model folder was not deleted.',
502546
),
503547
).toBeVisible({ timeout: 15000 });
504548

505-
// Verify "Go to Data > Trash" link is visible
506-
const goToTrashLink = page.getByText('Go to Data > Trash');
507-
await expect(goToTrashLink).toBeVisible();
508-
509-
// Click "Go to Data > Trash" and verify URL (no folder filter)
510-
await goToTrashLink.click();
511-
await page.waitForURL(
512-
(url) =>
513-
url.pathname === '/data' &&
514-
url.searchParams.get('statusCategory') === 'deleted' &&
515-
!url.searchParams.has('filter'),
516-
{ timeout: 10000 },
517-
);
518-
519-
// Cleanup: move the kept test folder to trash then permanently delete it
520-
await moveToTrashAndVerify(page, folderName, 'admin-data');
521-
await deleteForeverAndVerifyFromTrash(page, folderName, 'admin-data');
549+
// Card was deleted; afterEach will clean up the folder
522550
});
523551
},
524552
);

0 commit comments

Comments
 (0)