mirror of
https://github.com/bretzel-app/crumbs.git
synced 2026-10-12 12:06:57 +02:00
fix: address review feedback on auto-save
- Snapshot fields at start of performSave to avoid race with user edits during async save (fields could change between await and lastSaved update) - Only update lastSaved tracking on successful save, so failed saves are retried on the next debounce cycle - Stop restoring title after Untitled fallback in autoSave(), which was re-triggering the auto-save effect - Capture note count before opening editor in empty-note e2e test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
Fred Cabassut
co-authored by
Claude Opus 4.6
parent
07b27c01e7
commit
9d1c898b84
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user