From d44506dd0134b971d425f28f04f1de5a8521a12f Mon Sep 17 00:00:00 2001 From: default Date: Tue, 2 Jun 2026 03:51:54 +0000 Subject: [PATCH] Fix TypeScript errors in products page and Harvest Reach components --- src/app/admin/products/page.tsx | 2 +- .../admin/HarvestReach/SegmentBuilderPage.tsx | 2 +- .../admin/HarvestReach/SegmentListSidebar.tsx | 4 +- src/components/admin/ProductsClient.tsx | 8 +- test-results/.last-run.json | 8 +- .../error-context.md | 152 ++++++++++++++++++ .../error-context.md | 152 ++++++++++++++++++ .../error-context.md | 152 ++++++++++++++++++ 8 files changed, 473 insertions(+), 7 deletions(-) create mode 100644 test-results/login-login-flow-admin-session-persists-across-page-reloads-production/error-context.md create mode 100644 test-results/login-login-flow-login-wit-18f75-ws-error-and-stays-on-login-production/error-context.md create mode 100644 test-results/login-login-flow-login-wit-e85a2-n-and-shows-admin-dashboard-production/error-context.md diff --git a/src/app/admin/products/page.tsx b/src/app/admin/products/page.tsx index bc7914d..70db689 100644 --- a/src/app/admin/products/page.tsx +++ b/src/app/admin/products/page.tsx @@ -69,7 +69,7 @@ export default async function AdminProductsPage() { return (
- +
); } \ No newline at end of file diff --git a/src/components/admin/HarvestReach/SegmentBuilderPage.tsx b/src/components/admin/HarvestReach/SegmentBuilderPage.tsx index 1cfc9be..bf6020a 100644 --- a/src/components/admin/HarvestReach/SegmentBuilderPage.tsx +++ b/src/components/admin/HarvestReach/SegmentBuilderPage.tsx @@ -14,7 +14,7 @@ type Props = { }; // Icon components -const LayersIcon = (className: string) => ( +const LayersIcon = ({ className }: { className: string }) => ( diff --git a/src/components/admin/HarvestReach/SegmentListSidebar.tsx b/src/components/admin/HarvestReach/SegmentListSidebar.tsx index 9a73afe..c4a9155 100644 --- a/src/components/admin/HarvestReach/SegmentListSidebar.tsx +++ b/src/components/admin/HarvestReach/SegmentListSidebar.tsx @@ -6,7 +6,7 @@ import { AdminButton, AdminIconButton, AdminSearchInput } from "@/components/adm // Icon components const Icons = { - plus: (className: string) => ( + Plus: ({ className }: { className: string }) => ( @@ -47,7 +47,7 @@ export default function SegmentListSidebar({ segments, activeSegmentId, onSelect variant="primary" size="sm" > - + diff --git a/src/components/admin/ProductsClient.tsx b/src/components/admin/ProductsClient.tsx index e8e2e8a..d58c4d2 100644 --- a/src/components/admin/ProductsClient.tsx +++ b/src/components/admin/ProductsClient.tsx @@ -74,7 +74,7 @@ const PackageIconHeader = () => ( ); -export default function ProductsClient({ products, brandId }: { products: Product[]; brandId: string }) { +export default function ProductsClient({ products, brandId }: { products: Product[]; brandId?: string }) { const router = useRouter(); const [, startTransition] = useTransition(); const [search, setSearch] = useState(""); @@ -234,6 +234,12 @@ export default function ProductsClient({ products, brandId }: { products: Produc } try { + if (!brandId) { + setError("Brand ID is required"); + setSaving(false); + return; + } + let result; const imageUrl = pendingImageUrl || formData.image_url || null; diff --git a/test-results/.last-run.json b/test-results/.last-run.json index cbcc1fb..9e24987 100644 --- a/test-results/.last-run.json +++ b/test-results/.last-run.json @@ -1,4 +1,8 @@ { - "status": "passed", - "failedTests": [] + "status": "failed", + "failedTests": [ + "9baefabce98ea24ee76d-2f6f670dfe942637faf7", + "9baefabce98ea24ee76d-f58eca1309366ec2998a", + "9baefabce98ea24ee76d-4a32d345869f5c6ceb12" + ] } \ No newline at end of file diff --git a/test-results/login-login-flow-admin-session-persists-across-page-reloads-production/error-context.md b/test-results/login-login-flow-admin-session-persists-across-page-reloads-production/error-context.md new file mode 100644 index 0000000..9122b57 --- /dev/null +++ b/test-results/login-login-flow-admin-session-persists-across-page-reloads-production/error-context.md @@ -0,0 +1,152 @@ +# Instructions + +- Following Playwright test failed. +- Explain why, be concise, respect Playwright best practices. +- Provide a snippet of code with the fix, if possible. + +# Test info + +- Name: login/login-flow.spec.ts >> admin session persists across page reloads +- Location: tests/login/login-flow.spec.ts:65:5 + +# Error details + +``` +Error: page.fill: value: expected string, got undefined +``` + +# Page snapshot + +```yaml +- generic [active] [ref=e1]: + - banner [ref=e2]: + - generic [ref=e3]: + - link "Route Commerce" [ref=e4] [cursor=pointer]: + - /url: / + - navigation [ref=e5]: + - link "Tuxedo" [ref=e6] [cursor=pointer]: + - /url: /tuxedo + - link "IRD" [ref=e7] [cursor=pointer]: + - /url: /indian-river-direct + - link "Admin" [ref=e8] [cursor=pointer]: + - /url: /admin + - button "Switch to dark mode" [ref=e9]: + - img [ref=e10] + - link "Cart (0)" [ref=e12] [cursor=pointer]: + - /url: /cart + - main [ref=e13]: + - generic [ref=e14]: + - generic [ref=e15]: + - heading "Admin Login" [level=1] [ref=e16] + - paragraph [ref=e17]: Sign in with your account. + - generic [ref=e18]: + - generic [ref=e19]: + - generic [ref=e20]: Email + - textbox "Email" [ref=e21]: + - /placeholder: admin@example.com + - generic [ref=e22]: + - generic [ref=e23]: Password + - textbox "Password" [ref=e24]: + - /placeholder: •••••••• + - button "Sign In" [ref=e25] + - button "Forgot password?" [ref=e26] + - link "← Back to storefront" [ref=e27] [cursor=pointer]: + - /url: / + - contentinfo [ref=e28]: + - generic [ref=e30]: + - paragraph [ref=e31]: © 2026 Route Commerce. All rights reserved. + - navigation [ref=e32]: + - link "Privacy Policy" [ref=e33] [cursor=pointer]: + - /url: /privacy-policy + - link "Terms & Conditions" [ref=e34] [cursor=pointer]: + - /url: /terms-and-conditions + - link "Powered by Route Commerce" [ref=e35] [cursor=pointer]: + - /url: https://cielohermosa.com + - alert [ref=e36] +``` + +# Test source + +```ts + 1 | import { test, expect } from "@playwright/test"; + 2 | + 3 | // ───────────────────────────────────────────────────────────── + 4 | // Login flow: credentials → /api/login JSON → redirect to /admin + 5 | // ───────────────────────────────────────────────────────────── + 6 | test("login with valid credentials redirects to /admin and shows admin dashboard", async ({ + 7 | page, + 8 | }) => { + 9 | // Navigate to login page + 10 | await page.goto("/login"); + 11 | + 12 | // Fill credentials + 13 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + 14 | await page.fill("#password", process.env.TEST_ADMIN_PASSWORD!); + 15 | + 16 | // Submit form + 17 | await page.click('button[type="submit"]'); + 18 | + 19 | // Wait for navigation to /admin — the JSON response + client nav must happen + 20 | await page.waitForURL("**/admin", { timeout: 10000 }); + 21 | + 22 | // Admin dashboard must be rendered (Control Center heading or admin layout) + 23 | await expect(page.locator("body")).not.toContainText("Access Denied"); + 24 | await expect(page.locator("body")).not.toContainText("Login failed"); + 25 | }); + 26 | + 27 | // ───────────────────────────────────────────────────────────── + 28 | // Login failure: bad password shows error, stays on /login + 29 | // ───────────────────────────────────────────────────────────── + 30 | test("login with wrong password shows error and stays on /login", async ({ + 31 | page, + 32 | }) => { + 33 | await page.goto("/login"); + 34 | + 35 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + 36 | await page.fill("#password", "wrongpassword123!"); + 37 | + 38 | await page.click('button[type="submit"]'); + 39 | + 40 | // Error message should appear + 41 | await expect(page.locator('[role="alert"]')).toBeVisible({ timeout: 5000 }); + 42 | // Should NOT navigate away from login + 43 | await expect(page).toHaveURL(/\/login/); + 44 | }); + 45 | + 46 | // ───────────────────────────────────────────────────────────── + 47 | // Login with missing fields shows validation error + 48 | // ───────────────────────────────────────────────────────────── + 49 | test("login with missing email shows validation error", async ({ page }) => { + 50 | await page.goto("/login"); + 51 | + 52 | // Don't fill email, only password + 53 | await page.fill("#password", "something"); + 54 | + 55 | await page.click('button[type="submit"]'); + 56 | + 57 | // Browser validation should fire (email required) + 58 | await expect(page.locator("#email")).toHaveAttribute("required", ""); + 59 | }); + 60 | + 61 | // ───────────────────────────────────────────────────────────── + 62 | // Session persistence: after login, navigating to /admin + 63 | // should load without re-authenticating + 64 | // ───────────────────────────────────────────────────────────── + 65 | test("admin session persists across page reloads", async ({ page }) => { + 66 | // Login first + 67 | await page.goto("/login"); +> 68 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + | ^ Error: page.fill: value: expected string, got undefined + 69 | await page.fill("#password", process.env.TEST_ADMIN_PASSWORD!); + 70 | await page.click('button[type="submit"]'); + 71 | await page.waitForURL("**/admin", { timeout: 10000 }); + 72 | + 73 | // Reload the page + 74 | await page.reload(); + 75 | + 76 | // Should still be on /admin (session cookie keeps user logged in) + 77 | await expect(page).toHaveURL(/\/admin/); + 78 | await expect(page.locator("body")).not.toContainText("Access Denied"); + 79 | }); + 80 | +``` \ No newline at end of file diff --git a/test-results/login-login-flow-login-wit-18f75-ws-error-and-stays-on-login-production/error-context.md b/test-results/login-login-flow-login-wit-18f75-ws-error-and-stays-on-login-production/error-context.md new file mode 100644 index 0000000..3daf2c5 --- /dev/null +++ b/test-results/login-login-flow-login-wit-18f75-ws-error-and-stays-on-login-production/error-context.md @@ -0,0 +1,152 @@ +# Instructions + +- Following Playwright test failed. +- Explain why, be concise, respect Playwright best practices. +- Provide a snippet of code with the fix, if possible. + +# Test info + +- Name: login/login-flow.spec.ts >> login with wrong password shows error and stays on /login +- Location: tests/login/login-flow.spec.ts:30:5 + +# Error details + +``` +Error: page.fill: value: expected string, got undefined +``` + +# Page snapshot + +```yaml +- generic [active] [ref=e1]: + - banner [ref=e2]: + - generic [ref=e3]: + - link "Route Commerce" [ref=e4] [cursor=pointer]: + - /url: / + - navigation [ref=e5]: + - link "Tuxedo" [ref=e6] [cursor=pointer]: + - /url: /tuxedo + - link "IRD" [ref=e7] [cursor=pointer]: + - /url: /indian-river-direct + - link "Admin" [ref=e8] [cursor=pointer]: + - /url: /admin + - button "Switch to dark mode" [ref=e9]: + - img [ref=e10] + - link "Cart (0)" [ref=e12] [cursor=pointer]: + - /url: /cart + - main [ref=e13]: + - generic [ref=e14]: + - generic [ref=e15]: + - heading "Admin Login" [level=1] [ref=e16] + - paragraph [ref=e17]: Sign in with your account. + - generic [ref=e18]: + - generic [ref=e19]: + - generic [ref=e20]: Email + - textbox "Email" [ref=e21]: + - /placeholder: admin@example.com + - generic [ref=e22]: + - generic [ref=e23]: Password + - textbox "Password" [ref=e24]: + - /placeholder: •••••••• + - button "Sign In" [ref=e25] + - button "Forgot password?" [ref=e26] + - link "← Back to storefront" [ref=e27] [cursor=pointer]: + - /url: / + - contentinfo [ref=e28]: + - generic [ref=e30]: + - paragraph [ref=e31]: © 2026 Route Commerce. All rights reserved. + - navigation [ref=e32]: + - link "Privacy Policy" [ref=e33] [cursor=pointer]: + - /url: /privacy-policy + - link "Terms & Conditions" [ref=e34] [cursor=pointer]: + - /url: /terms-and-conditions + - link "Powered by Route Commerce" [ref=e35] [cursor=pointer]: + - /url: https://cielohermosa.com + - alert [ref=e36] +``` + +# Test source + +```ts + 1 | import { test, expect } from "@playwright/test"; + 2 | + 3 | // ───────────────────────────────────────────────────────────── + 4 | // Login flow: credentials → /api/login JSON → redirect to /admin + 5 | // ───────────────────────────────────────────────────────────── + 6 | test("login with valid credentials redirects to /admin and shows admin dashboard", async ({ + 7 | page, + 8 | }) => { + 9 | // Navigate to login page + 10 | await page.goto("/login"); + 11 | + 12 | // Fill credentials + 13 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + 14 | await page.fill("#password", process.env.TEST_ADMIN_PASSWORD!); + 15 | + 16 | // Submit form + 17 | await page.click('button[type="submit"]'); + 18 | + 19 | // Wait for navigation to /admin — the JSON response + client nav must happen + 20 | await page.waitForURL("**/admin", { timeout: 10000 }); + 21 | + 22 | // Admin dashboard must be rendered (Control Center heading or admin layout) + 23 | await expect(page.locator("body")).not.toContainText("Access Denied"); + 24 | await expect(page.locator("body")).not.toContainText("Login failed"); + 25 | }); + 26 | + 27 | // ───────────────────────────────────────────────────────────── + 28 | // Login failure: bad password shows error, stays on /login + 29 | // ───────────────────────────────────────────────────────────── + 30 | test("login with wrong password shows error and stays on /login", async ({ + 31 | page, + 32 | }) => { + 33 | await page.goto("/login"); + 34 | +> 35 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + | ^ Error: page.fill: value: expected string, got undefined + 36 | await page.fill("#password", "wrongpassword123!"); + 37 | + 38 | await page.click('button[type="submit"]'); + 39 | + 40 | // Error message should appear + 41 | await expect(page.locator('[role="alert"]')).toBeVisible({ timeout: 5000 }); + 42 | // Should NOT navigate away from login + 43 | await expect(page).toHaveURL(/\/login/); + 44 | }); + 45 | + 46 | // ───────────────────────────────────────────────────────────── + 47 | // Login with missing fields shows validation error + 48 | // ───────────────────────────────────────────────────────────── + 49 | test("login with missing email shows validation error", async ({ page }) => { + 50 | await page.goto("/login"); + 51 | + 52 | // Don't fill email, only password + 53 | await page.fill("#password", "something"); + 54 | + 55 | await page.click('button[type="submit"]'); + 56 | + 57 | // Browser validation should fire (email required) + 58 | await expect(page.locator("#email")).toHaveAttribute("required", ""); + 59 | }); + 60 | + 61 | // ───────────────────────────────────────────────────────────── + 62 | // Session persistence: after login, navigating to /admin + 63 | // should load without re-authenticating + 64 | // ───────────────────────────────────────────────────────────── + 65 | test("admin session persists across page reloads", async ({ page }) => { + 66 | // Login first + 67 | await page.goto("/login"); + 68 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + 69 | await page.fill("#password", process.env.TEST_ADMIN_PASSWORD!); + 70 | await page.click('button[type="submit"]'); + 71 | await page.waitForURL("**/admin", { timeout: 10000 }); + 72 | + 73 | // Reload the page + 74 | await page.reload(); + 75 | + 76 | // Should still be on /admin (session cookie keeps user logged in) + 77 | await expect(page).toHaveURL(/\/admin/); + 78 | await expect(page.locator("body")).not.toContainText("Access Denied"); + 79 | }); + 80 | +``` \ No newline at end of file diff --git a/test-results/login-login-flow-login-wit-e85a2-n-and-shows-admin-dashboard-production/error-context.md b/test-results/login-login-flow-login-wit-e85a2-n-and-shows-admin-dashboard-production/error-context.md new file mode 100644 index 0000000..daa973b --- /dev/null +++ b/test-results/login-login-flow-login-wit-e85a2-n-and-shows-admin-dashboard-production/error-context.md @@ -0,0 +1,152 @@ +# Instructions + +- Following Playwright test failed. +- Explain why, be concise, respect Playwright best practices. +- Provide a snippet of code with the fix, if possible. + +# Test info + +- Name: login/login-flow.spec.ts >> login with valid credentials redirects to /admin and shows admin dashboard +- Location: tests/login/login-flow.spec.ts:6:5 + +# Error details + +``` +Error: page.fill: value: expected string, got undefined +``` + +# Page snapshot + +```yaml +- generic [active] [ref=e1]: + - banner [ref=e2]: + - generic [ref=e3]: + - link "Route Commerce" [ref=e4] [cursor=pointer]: + - /url: / + - navigation [ref=e5]: + - link "Tuxedo" [ref=e6] [cursor=pointer]: + - /url: /tuxedo + - link "IRD" [ref=e7] [cursor=pointer]: + - /url: /indian-river-direct + - link "Admin" [ref=e8] [cursor=pointer]: + - /url: /admin + - button "Switch to dark mode" [ref=e9]: + - img [ref=e10] + - link "Cart (0)" [ref=e12] [cursor=pointer]: + - /url: /cart + - main [ref=e13]: + - generic [ref=e14]: + - generic [ref=e15]: + - heading "Admin Login" [level=1] [ref=e16] + - paragraph [ref=e17]: Sign in with your account. + - generic [ref=e18]: + - generic [ref=e19]: + - generic [ref=e20]: Email + - textbox "Email" [ref=e21]: + - /placeholder: admin@example.com + - generic [ref=e22]: + - generic [ref=e23]: Password + - textbox "Password" [ref=e24]: + - /placeholder: •••••••• + - button "Sign In" [ref=e25] + - button "Forgot password?" [ref=e26] + - link "← Back to storefront" [ref=e27] [cursor=pointer]: + - /url: / + - contentinfo [ref=e28]: + - generic [ref=e30]: + - paragraph [ref=e31]: © 2026 Route Commerce. All rights reserved. + - navigation [ref=e32]: + - link "Privacy Policy" [ref=e33] [cursor=pointer]: + - /url: /privacy-policy + - link "Terms & Conditions" [ref=e34] [cursor=pointer]: + - /url: /terms-and-conditions + - link "Powered by Route Commerce" [ref=e35] [cursor=pointer]: + - /url: https://cielohermosa.com + - alert [ref=e36] +``` + +# Test source + +```ts + 1 | import { test, expect } from "@playwright/test"; + 2 | + 3 | // ───────────────────────────────────────────────────────────── + 4 | // Login flow: credentials → /api/login JSON → redirect to /admin + 5 | // ───────────────────────────────────────────────────────────── + 6 | test("login with valid credentials redirects to /admin and shows admin dashboard", async ({ + 7 | page, + 8 | }) => { + 9 | // Navigate to login page + 10 | await page.goto("/login"); + 11 | + 12 | // Fill credentials +> 13 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + | ^ Error: page.fill: value: expected string, got undefined + 14 | await page.fill("#password", process.env.TEST_ADMIN_PASSWORD!); + 15 | + 16 | // Submit form + 17 | await page.click('button[type="submit"]'); + 18 | + 19 | // Wait for navigation to /admin — the JSON response + client nav must happen + 20 | await page.waitForURL("**/admin", { timeout: 10000 }); + 21 | + 22 | // Admin dashboard must be rendered (Control Center heading or admin layout) + 23 | await expect(page.locator("body")).not.toContainText("Access Denied"); + 24 | await expect(page.locator("body")).not.toContainText("Login failed"); + 25 | }); + 26 | + 27 | // ───────────────────────────────────────────────────────────── + 28 | // Login failure: bad password shows error, stays on /login + 29 | // ───────────────────────────────────────────────────────────── + 30 | test("login with wrong password shows error and stays on /login", async ({ + 31 | page, + 32 | }) => { + 33 | await page.goto("/login"); + 34 | + 35 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + 36 | await page.fill("#password", "wrongpassword123!"); + 37 | + 38 | await page.click('button[type="submit"]'); + 39 | + 40 | // Error message should appear + 41 | await expect(page.locator('[role="alert"]')).toBeVisible({ timeout: 5000 }); + 42 | // Should NOT navigate away from login + 43 | await expect(page).toHaveURL(/\/login/); + 44 | }); + 45 | + 46 | // ───────────────────────────────────────────────────────────── + 47 | // Login with missing fields shows validation error + 48 | // ───────────────────────────────────────────────────────────── + 49 | test("login with missing email shows validation error", async ({ page }) => { + 50 | await page.goto("/login"); + 51 | + 52 | // Don't fill email, only password + 53 | await page.fill("#password", "something"); + 54 | + 55 | await page.click('button[type="submit"]'); + 56 | + 57 | // Browser validation should fire (email required) + 58 | await expect(page.locator("#email")).toHaveAttribute("required", ""); + 59 | }); + 60 | + 61 | // ───────────────────────────────────────────────────────────── + 62 | // Session persistence: after login, navigating to /admin + 63 | // should load without re-authenticating + 64 | // ───────────────────────────────────────────────────────────── + 65 | test("admin session persists across page reloads", async ({ page }) => { + 66 | // Login first + 67 | await page.goto("/login"); + 68 | await page.fill("#email", process.env.TEST_ADMIN_EMAIL!); + 69 | await page.fill("#password", process.env.TEST_ADMIN_PASSWORD!); + 70 | await page.click('button[type="submit"]'); + 71 | await page.waitForURL("**/admin", { timeout: 10000 }); + 72 | + 73 | // Reload the page + 74 | await page.reload(); + 75 | + 76 | // Should still be on /admin (session cookie keeps user logged in) + 77 | await expect(page).toHaveURL(/\/admin/); + 78 | await expect(page.locator("body")).not.toContainText("Access Denied"); + 79 | }); + 80 | +``` \ No newline at end of file