feat/upload-bar (#30)

* feat/upload-bar: add a upload bar when user upload file, indicate the upload process

* feat/save-loading-status: add save status when click back button from editor

* fix: address PR review issues in upload and save features

- Replace deprecated substr() with substring() in UploadContext
- Fix broken error handling that checked stale task status
- Fix missing useEffect dependency in UploadStatus
- Fix CSS class conflict in progress bar styling
- Add error recovery for save state in Editor (reset on failure)
- Use .finally() instead of .then() to ensure refresh on upload failure
- Fix inconsistent indentation in UploadContext

* fix e2e tests

---------

Co-authored-by: Zimeng Xiong <zxzimeng@gmail.com>
This commit is contained in:
adamant368
2026-01-15 01:25:17 +08:00
committed by GitHub
parent cae8f3cbf6
commit 8f9b9b4945
9 changed files with 320 additions and 84 deletions
+2 -5
View File
@@ -272,11 +272,8 @@ test.describe("Drag and Drop - File Import", () => {
const fileInput = page.locator("#dashboard-import");
await fileInput.setInputFiles(fixturePath);
// Wait for import success modal
await expect(page.getByText("Import Successful")).toBeVisible({ timeout: 10000 });
// Dismiss the modal
await page.getByRole("button", { name: "OK" }).click();
// Wait for upload to complete - the UploadStatus component shows "Done" when finished
await expect(page.getByText("Uploads (Done)")).toBeVisible({ timeout: 10000 });
// Search for the imported drawing (it uses the filename as name)
await page.getByPlaceholder("Search drawings...").fill("small-image");
+14 -23
View File
@@ -219,9 +219,8 @@ test.describe.serial("Import Functionality", () => {
buffer: Buffer.from(fixtureContent),
});
// Wait for success modal
await expect(page.getByText("Import Successful")).toBeVisible({ timeout: 10000 });
await page.getByRole("button", { name: "OK" }).click();
// Wait for upload to complete - the UploadStatus component shows "Done" when finished
await expect(page.getByText("Uploads (Done)")).toBeVisible({ timeout: 10000 });
// Reload to ensure dashboard state reflects the newly imported drawing
await page.reload({ waitUntil: "networkidle" });
@@ -287,25 +286,16 @@ test.describe.serial("Import Functionality", () => {
buffer: Buffer.from(jsonContent),
});
// Wait for import result - could be success or failure
const successModal = page.getByText("Import Successful");
const failModal = page.getByText("Import Failed");
// Wait for upload to complete - the UploadStatus component shows "Done" when finished
await expect(page.getByText("Uploads (Done)")).toBeVisible({ timeout: 15000 });
await expect(successModal.or(failModal)).toBeVisible({ timeout: 15000 });
// If we got a failure, check the error
if (await failModal.isVisible()) {
// Get the error message
const errorText = await page.locator(".modal, [role='dialog']").textContent();
console.log("Import failed with:", errorText);
// Still click OK to dismiss
await page.getByRole("button", { name: "OK" }).click();
// Skip the rest of the test since import failed
// Check if upload failed (shows "Failed" text in the upload status)
const failedIndicator = page.getByText("Failed");
if (await failedIndicator.isVisible()) {
console.log("Import failed - skipping rest of test");
return;
}
await page.getByRole("button", { name: "OK" }).click();
// Reload to force a fresh fetch of drawings after import
await page.reload({ waitUntil: "networkidle" });
@@ -335,9 +325,10 @@ test.describe.serial("Import Functionality", () => {
buffer: Buffer.from(invalidContent),
});
// Should show error modal
await expect(page.getByText("Import Failed")).toBeVisible({ timeout: 10000 });
await page.getByRole("button", { name: "OK" }).click();
// Wait for upload to complete and check for failure indicator
await expect(page.getByText("Uploads (Done)")).toBeVisible({ timeout: 10000 });
// Should show "Failed" status in the upload status component
await expect(page.getByText("Failed")).toBeVisible();
});
test("should import multiple drawings at once", async ({ page }) => {
@@ -374,8 +365,8 @@ test.describe.serial("Import Functionality", () => {
const fileInput = page.locator("#dashboard-import");
await fileInput.setInputFiles(files);
await expect(page.getByText("Import Successful")).toBeVisible({ timeout: 10000 });
await page.getByRole("button", { name: "OK" }).click();
// Wait for upload to complete - the UploadStatus component shows "Done" when finished
await expect(page.getByText("Uploads (Done)")).toBeVisible({ timeout: 10000 });
// Verify both were imported by searching for the unique prefix
await page.getByPlaceholder("Search drawings...").fill(searchPrefix);