Skip to content

Commit b46b1c2

Browse files
fix: Clear report form draft on successful submission (#907)
The localStorage draft was persisting after successful submission because the server action redirects before the cleanup effect could run. Fix: Add ClearReportDraft component to success page that clears localStorage when mounted, ensuring the draft is cleared before user navigates back. Added E2E test to verify: - Title and description are empty after "Report Another Issue" - Machine resets to default (not restored from draft) - localStorage is cleared on success page Closes PinPoint-gdk Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ab35a00 commit b46b1c2

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

e2e/smoke/public-reporting.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,62 @@ test.describe("Public Issue Reporting", () => {
157157
await page.getByRole("link", { name: "Report Another Issue" }).click();
158158
await expect(page).toHaveURL("/report");
159159
});
160+
161+
test("should clear form draft after successful submission", async ({
162+
page,
163+
}) => {
164+
// Submit an issue first - select the SECOND machine (index 1)
165+
await page.goto("/report");
166+
const select = page.getByTestId("machine-select");
167+
168+
// Get the first (default) machine value before changing
169+
const defaultMachineId = await select.inputValue();
170+
expect(defaultMachineId).toBeTruthy(); // Should have a default
171+
172+
// Select a different machine (use index 3 to ensure it's different from default)
173+
await select.selectOption({ index: 3 });
174+
const selectedMachineId = await select.inputValue();
175+
expect(selectedMachineId).not.toBe(defaultMachineId);
176+
await expect(page).toHaveURL(/machine=/);
177+
178+
const issueTitle = `${PUBLIC_PREFIX} Draft Clear Test ${Date.now()}`;
179+
await fillReportForm(page, {
180+
title: issueTitle,
181+
description: "This should not persist after submission.",
182+
includePriority: false,
183+
});
184+
185+
await page.getByRole("button", { name: "Submit Issue Report" }).click();
186+
await expect(page).toHaveURL("/report/success");
187+
188+
// Wait for success page to load and ClearReportDraft effect to run
189+
await expect(
190+
page.getByRole("heading", { name: "Issue Sent!" })
191+
).toBeVisible();
192+
193+
// Verify localStorage was cleared on success page
194+
const draftAfterSuccess = await page.evaluate(() =>
195+
window.localStorage.getItem("report_form_state")
196+
);
197+
expect(draftAfterSuccess).toBeNull();
198+
199+
// Click "Report Another Issue"
200+
await page.getByRole("link", { name: "Report Another Issue" }).click();
201+
202+
// Wait for the report page to load
203+
await expect(page).toHaveURL("/report");
204+
await expect(
205+
page.getByRole("heading", { name: "Report an Issue" })
206+
).toBeVisible();
207+
208+
// Verify text fields are empty (draft cleared, not restored)
209+
await expect(page.getByLabel("Issue Title")).toHaveValue("");
210+
await expect(page.getByLabel("Description")).toHaveValue("");
211+
212+
// Machine should be back to DEFAULT (first in list), not the one we selected
213+
// This verifies draft wasn't restored - the form uses first machine as default
214+
const machineAfterReset = await select.inputValue();
215+
expect(machineAfterReset).toBe(defaultMachineId);
216+
expect(machineAfterReset).not.toBe(selectedMachineId);
217+
});
160218
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
5+
/**
6+
* Client component that clears the report form draft from localStorage.
7+
* Mounted on the success page to ensure drafts are cleared after successful submission.
8+
*
9+
* This is needed because the server action redirects before the client-side
10+
* cleanup effect in the form component can run.
11+
*/
12+
export function ClearReportDraft(): null {
13+
useEffect(() => {
14+
window.localStorage.removeItem("report_form_state");
15+
}, []);
16+
17+
return null;
18+
}

src/app/report/success/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Link from "next/link";
33
import { CheckCircle } from "lucide-react";
44
import { Button } from "~/components/ui/button";
55
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
6+
import { ClearReportDraft } from "./clear-draft";
67

78
export default async function ReportSuccessPage({
89
searchParams,
@@ -35,6 +36,7 @@ export default async function ReportSuccessPage({
3536

3637
return (
3738
<main className="min-h-screen bg-surface py-12">
39+
<ClearReportDraft />
3840
<div className="container mx-auto max-w-xl px-4">
3941
<Card className="border-outline-variant bg-surface shadow-lg text-center p-6">
4042
<CardHeader className="space-y-3 pb-4">

0 commit comments

Comments
 (0)