diff --git a/src/lib/components/NoteEditor.svelte b/src/lib/components/NoteEditor.svelte index 4720a28..ba81099 100644 --- a/src/lib/components/NoteEditor.svelte +++ b/src/lib/components/NoteEditor.svelte @@ -83,24 +83,37 @@ async function performSave() { if (isSaving) return; - if (!title.trim() && !content.trim()) return; - if (!hasUnsavedChanges()) return; + // Snapshot current fields to avoid races with user edits during await + const snap = { title, content, color, checklistMode }; + if (!snap.title.trim() && !snap.content.trim()) return; + if ( + snap.title === lastSavedTitle && + snap.content === lastSavedContent && + snap.color === lastSavedColor && + snap.checklistMode === lastSavedChecklistMode + ) return; isSaving = true; try { if (currentlyNew) { - const created = await createNote({ title, content, color, checklistMode }); + const created = await createNote(snap); if (created) { noteId = created.id; currentlyNew = false; + lastSavedTitle = snap.title; + lastSavedContent = snap.content; + lastSavedColor = snap.color; + lastSavedChecklistMode = snap.checklistMode; } } else if (noteId) { - await updateNote(noteId, { title, content, color, checklistMode }); + const updated = await updateNote(noteId, snap); + if (updated) { + lastSavedTitle = snap.title; + lastSavedContent = snap.content; + lastSavedColor = snap.color; + lastSavedChecklistMode = snap.checklistMode; + } } - lastSavedTitle = title; - lastSavedContent = content; - lastSavedColor = color; - lastSavedChecklistMode = checklistMode; } finally { isSaving = false; } @@ -335,10 +348,8 @@ clearTimeout(autoSaveTimer); if (savingPromise) await savingPromise; // For feature-triggered saves (image upload, share), use 'Untitled' fallback - const prevTitle = title; if (!title.trim()) title = 'Untitled'; await performSave(); - if (!prevTitle.trim()) title = prevTitle; return noteId; } diff --git a/tests/e2e/auto-save.spec.ts b/tests/e2e/auto-save.spec.ts index 4b46646..399cbd1 100644 --- a/tests/e2e/auto-save.spec.ts +++ b/tests/e2e/auto-save.spec.ts @@ -41,20 +41,20 @@ test.describe('Auto-save', () => { }); test('Scenario: Empty note is not auto-saved', async ({ authenticatedPage: page }) => { + // Given the current number of notes + const noteCards = page.locator('[data-testid="note-card"]'); + const countBefore = await noteCards.count(); + // When the user opens a new note but leaves it empty await page.getByTestId('new-note-btn').click(); // And waits longer than the auto-save delay await page.waitForTimeout(3000); - // Then no note card appears in the list - const noteCards = page.locator('[data-testid="note-card"]'); - const countBefore = await noteCards.count(); - - // Close the empty editor + // And closes the empty editor await page.getByTestId('close-editor-btn').click(); - // And no new note was created + // Then no new note was created const countAfter = await noteCards.count(); expect(countAfter).toBe(countBefore); });