Add notification toasts and surface persistence failures instead of failing silently

This commit is contained in:
2026-06-05 11:19:50 +03:00
parent c50f141d57
commit 3839f92f1d
10 changed files with 644 additions and 5 deletions
+45
View File
@@ -0,0 +1,45 @@
import { describe, expect, it } from 'vitest';
import { StorageQuotaError } from '../infrastructure/snippet-store';
import { storageErrorNotification } from './storage-errors';
describe('storageErrorNotification', () => {
describe('a failure the user can fix (storage full)', () => {
it('tells them the step to take and carries no diagnostic detail', () => {
const n = storageErrorNotification('save', new StorageQuotaError());
expect(n.kind).toBe('error');
expect(n.title).toBe('Storage full');
expect(n.message.toLowerCase()).toContain('delete');
// Nothing to report — the fix is in the user's hands.
expect(n.detail).toBeUndefined();
});
});
describe('a failure the user cannot fix', () => {
it('explains a load failure and attaches a reportable diagnostic', () => {
const n = storageErrorNotification('load', new DOMException('blocked', 'SecurityError'));
expect(n.kind).toBe('error');
expect(n.title).toBe("Couldn't open your library");
expect(n.detail).toBeDefined();
// The diagnostic names the operation and the underlying error.
expect(n.detail).toContain('load');
expect(n.detail).toContain('SecurityError');
expect(n.detail).toContain('blocked');
});
it('uses the right title for a failed save vs delete and includes detail', () => {
const save = storageErrorNotification('save', new Error('boom'));
expect(save.title).toBe("Couldn't save your changes");
expect(save.detail).toContain('save failed');
expect(save.detail).toContain('boom');
const del = storageErrorNotification('delete', new Error('boom'));
expect(del.title).toBe("Couldn't delete the snippet");
expect(del.detail).toContain('delete failed');
});
it('describes a non-Error throw without crashing', () => {
const n = storageErrorNotification('save', 'weird string');
expect(n.detail).toContain('weird string');
});
});
});