Skip to content

Commit fd94bf9

Browse files
fix: add duration: 8000 to all toast.error() calls (#87) (#88)
Co-authored-by: Ona <no-reply@ona.com>
1 parent 28f185c commit fd94bf9

5 files changed

Lines changed: 74 additions & 11 deletions

File tree

.agents/conventions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ import { toast } from "sonner";
168168
const { error } = await supabase.from("pages").insert({ ... });
169169
if (error) {
170170
captureSupabaseError(error, "pages.insert");
171-
toast.error("Failed to create page");
171+
toast.error("Failed to create page", { duration: 8000 });
172172
}
173173
```
174174

src/components/page-menu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export function PageMenu({
4444
const handleExport = useCallback(() => {
4545
const editor = editorRef.current;
4646
if (!editor) {
47-
toast.error("Editor not ready");
47+
toast.error("Editor not ready", { duration: 8000 });
4848
return;
4949
}
5050

src/components/sidebar/page-tree.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export function PageTree({ userId }: PageTreeProps) {
136136

137137
if (error) {
138138
captureSupabaseError(error, "page-tree:fetch-pages");
139-
toast.error("Failed to load pages");
139+
toast.error("Failed to load pages", { duration: 8000 });
140140
}
141141

142142
if (data) {
@@ -189,7 +189,7 @@ export function PageTree({ userId }: PageTreeProps) {
189189

190190
if (error) {
191191
captureSupabaseError(error, "page-tree:create-page");
192-
toast.error("Failed to create page");
192+
toast.error("Failed to create page", { duration: 8000 });
193193
return;
194194
}
195195
if (!newPage) return;
@@ -215,7 +215,7 @@ export function PageTree({ userId }: PageTreeProps) {
215215

216216
if (error) {
217217
captureSupabaseError(error, "page-tree:delete-page");
218-
toast.error("Failed to delete page");
218+
toast.error("Failed to delete page", { duration: 8000 });
219219
} else {
220220
const removedIds = new Set([
221221
deleteTarget.page.id,
@@ -275,7 +275,7 @@ export function PageTree({ userId }: PageTreeProps) {
275275
for (const result of results) {
276276
if (result.error) {
277277
captureSupabaseError(result.error, "page-tree:swap-positions");
278-
toast.error("Failed to reorder page");
278+
toast.error("Failed to reorder page", { duration: 8000 });
279279
break;
280280
}
281281
}
@@ -315,7 +315,7 @@ export function PageTree({ userId }: PageTreeProps) {
315315

316316
if (error) {
317317
captureSupabaseError(error, "page-tree:nest-page");
318-
toast.error("Failed to nest page");
318+
toast.error("Failed to nest page", { duration: 8000 });
319319
}
320320
}
321321

@@ -367,7 +367,7 @@ export function PageTree({ userId }: PageTreeProps) {
367367
for (const result of results) {
368368
if (result.error) {
369369
captureSupabaseError(result.error, "page-tree:unnest-page");
370-
toast.error("Failed to unnest page");
370+
toast.error("Failed to unnest page", { duration: 8000 });
371371
break;
372372
}
373373
}
@@ -455,7 +455,7 @@ export function PageTree({ userId }: PageTreeProps) {
455455

456456
if (error) {
457457
captureSupabaseError(error, "page-tree:drop-inside");
458-
toast.error("Failed to move page");
458+
toast.error("Failed to move page", { duration: 8000 });
459459
}
460460
} else {
461461
const newParentId = targetPage.parent_id;
@@ -493,7 +493,7 @@ export function PageTree({ userId }: PageTreeProps) {
493493

494494
if (error) {
495495
captureSupabaseError(error, "page-tree:drop-reorder");
496-
toast.error("Failed to move page");
496+
toast.error("Failed to move page", { duration: 8000 });
497497
break;
498498
}
499499
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { describe, it, expect } from "vitest";
2+
import { readFileSync, readdirSync, statSync } from "fs";
3+
import { join, relative } from "path";
4+
5+
/**
6+
* Regression test for issue #87: toast.error() calls must specify
7+
* { duration: 8000 } per the design spec (8 seconds for errors).
8+
*
9+
* Scans all .tsx/.ts source files under src/ for toast.error() calls
10+
* and verifies each one includes the duration option.
11+
*/
12+
13+
function collectFiles(dir: string, ext: string[]): string[] {
14+
const results: string[] = [];
15+
for (const entry of readdirSync(dir)) {
16+
const full = join(dir, entry);
17+
if (statSync(full).isDirectory()) {
18+
if (entry === "node_modules" || entry === ".next") continue;
19+
results.push(...collectFiles(full, ext));
20+
} else if (ext.some((e) => full.endsWith(e))) {
21+
results.push(full);
22+
}
23+
}
24+
return results;
25+
}
26+
27+
describe("toast.error() duration matches design spec", () => {
28+
const srcDir = join(__dirname, "..");
29+
const files = collectFiles(srcDir, [".ts", ".tsx"]).filter(
30+
(f) => !f.endsWith(".test.ts") && !f.endsWith(".test.tsx")
31+
);
32+
33+
it("every toast.error() call includes { duration: 8000 }", () => {
34+
const violations: string[] = [];
35+
36+
for (const file of files) {
37+
const content = readFileSync(file, "utf-8");
38+
const lines = content.split("\n");
39+
40+
for (let i = 0; i < lines.length; i++) {
41+
if (!lines[i].includes("toast.error(")) continue;
42+
43+
// Collect the full statement (may span multiple lines)
44+
let statement = lines[i];
45+
let j = i;
46+
while (j < lines.length - 1 && !statement.includes(");")) {
47+
j++;
48+
statement += " " + lines[j];
49+
}
50+
51+
if (!statement.includes("duration: 8000")) {
52+
const rel = relative(srcDir, file);
53+
violations.push(`${rel}:${i + 1}: ${lines[i].trim()}`);
54+
}
55+
}
56+
}
57+
58+
expect(
59+
violations,
60+
`toast.error() calls missing { duration: 8000 } (design spec: 8s for errors):\n${violations.join("\n")}`
61+
).toHaveLength(0);
62+
});
63+
});

src/components/workspace-home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function WorkspaceHome({
4141

4242
if (error) {
4343
captureSupabaseError(error, "workspace-home:create-page");
44-
toast.error("Failed to create page");
44+
toast.error("Failed to create page", { duration: 8000 });
4545
return;
4646
}
4747
if (!newPage) return;

0 commit comments

Comments
 (0)