feat(frontend): one-click preview test-account login buttons#13486
feat(frontend): one-click preview test-account login buttons#13486ntindle wants to merge 3 commits into
Conversation
Add a "Preview test accounts" section to the login page that renders one-click sign-in buttons for admin, existing, clean, pro and enterprise roles. The section is only shown when environment.getPreviewStealingDev() returns a non-empty preview marker, so it never appears on dev or prod. Each button calls a server action that maps the role to a preview-<role>@agpt.co email and reads the shared password server-side from PREVIEW_ACCOUNTS_PASSWORD, then reuses the existing login() action (supabase.auth.signInWithPassword). The password is never exposed to the client or committed. When PREVIEW_ACCOUNTS_PASSWORD is unset the buttons render disabled with a short hint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wj2E4V37tKjiGsXafYKDuk
WalkthroughAdds preview-account login support on the login page with role-based server actions, a stateful hook for configuration and login flow, a rendered button group, page wiring, and tests covering preview, navigation, and failure states. ChangesPreview Login Buttons
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 PR Overlap DetectionThis check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early. 🟢 Low Risk — File Overlap OnlyThese PRs touch the same files but different sections (click to expand)
Summary: 0 conflict(s), 0 medium risk, 1 low risk (out of 1 PRs with file overlap) Auto-generated on push. Ignores: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d4a0ec1. Configure here.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx (1)
6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueIcon imported from
/dist/ssrsubpath instead of package root.As per coding guidelines: "Always import the
-Icon-suffixed alias from@phosphor-icons/react(e.g.TrashIcon,PlusIcon,SquareIcon) — bare exports are deprecated." Consider importing from@phosphor-icons/reactdirectly for consistency with other components, unless this SSR subpath is an intentional, established convention elsewhere in the codebase.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx at line 6, The PreviewLoginButtons import is using the deprecated `/dist/ssr` subpath for FlaskIcon instead of the package root. Update the import in PreviewLoginButtons.tsx to use the appropriate `-Icon` alias from `@phosphor-icons/react` directly, and keep the symbol name consistent with other components so the icon import follows the established convention.Source: Coding guidelines
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx (1)
73-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding a test for the login-failure/toast path.
Current tests cover hidden, enabled, click, and disabled states, but not the case where
loginAsPreviewAccountresolves with{ success: false, error }(or rejects), which should trigger the toast inusePreviewLoginButtons.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(no-navbar)/login/__tests__/preview-login-buttons.test.tsx around lines 73 - 86, Add a test in the PreviewLoginButtons suite to cover the failure path in usePreviewLoginButtons: mock loginAsPreviewAccount to return { success: false, error } and verify the toast is shown, and optionally add a rejection case if the hook handles thrown errors the same way. Reuse the existing PreviewLoginButtons render/setup and the mockLoginAsPreviewAccount helper so the new test exercises the login-failure/toast behavior alongside the current click and disabled-state tests.autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts (1)
5-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated role list drifts from
helpers.ts.
PREVIEW_ACCOUNT_EMAILSre-enumerates the roles already defined inPREVIEW_ROLES/PreviewRole(helpers.ts), with a looserRecord<string, string>type androle: stringparam. Adding/removing a role in one file without the other silently breaks preview login for that role.♻️ Derive from PreviewRole for compile-time safety
+import { PreviewRole } from "./helpers"; + -const PREVIEW_ACCOUNT_EMAILS: Record<string, string> = { +const PREVIEW_ACCOUNT_EMAILS: Record<PreviewRole, string> = { admin: "preview-admin@agpt.co", existing: "preview-existing@agpt.co", clean: "preview-clean@agpt.co", pro: "preview-pro@agpt.co", enterprise: "preview-enterprise@agpt.co", }; ... -export async function loginAsPreviewAccount(role: string) { +export async function loginAsPreviewAccount(role: PreviewRole) { const email = PREVIEW_ACCOUNT_EMAILS[role]; - if (!email) { - return { success: false, error: "Unknown preview account" }; - }Also applies to: 17-18
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(no-navbar)/login/components/PreviewLoginButtons/actions.ts around lines 5 - 11, The preview login role list is duplicated here and can drift from the canonical roles in helpers.ts. Update PreviewLoginButtons/actions.ts to derive the email mapping from PREVIEW_ROLES/PreviewRole instead of using a loose Record<string, string>, and change the role parameter typing to PreviewRole so additions/removals are caught at compile time. Use the existing PREVIEW_ROLES and PreviewRole symbols to keep PREVIEW_ACCOUNT_EMAILS and the login action in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@autogpt_platform/frontend/src/app/`(no-navbar)/login/components/PreviewLoginButtons/actions.ts:
- Around line 13-29: Add the same preview-environment guard inside
loginAsPreviewAccount before calling login(...), so server-side access is
blocked unless the app is actually in preview mode, not just when
PREVIEW_ACCOUNTS_PASSWORD exists. Also update the role parameter to use
PreviewRole and make PREVIEW_ACCOUNT_EMAILS derive from PREVIEW_ROLES in
actions.ts to keep the allowed roles and email map in sync.
---
Nitpick comments:
In
`@autogpt_platform/frontend/src/app/`(no-navbar)/login/__tests__/preview-login-buttons.test.tsx:
- Around line 73-86: Add a test in the PreviewLoginButtons suite to cover the
failure path in usePreviewLoginButtons: mock loginAsPreviewAccount to return {
success: false, error } and verify the toast is shown, and optionally add a
rejection case if the hook handles thrown errors the same way. Reuse the
existing PreviewLoginButtons render/setup and the mockLoginAsPreviewAccount
helper so the new test exercises the login-failure/toast behavior alongside the
current click and disabled-state tests.
In
`@autogpt_platform/frontend/src/app/`(no-navbar)/login/components/PreviewLoginButtons/actions.ts:
- Around line 5-11: The preview login role list is duplicated here and can drift
from the canonical roles in helpers.ts. Update PreviewLoginButtons/actions.ts to
derive the email mapping from PREVIEW_ROLES/PreviewRole instead of using a loose
Record<string, string>, and change the role parameter typing to PreviewRole so
additions/removals are caught at compile time. Use the existing PREVIEW_ROLES
and PreviewRole symbols to keep PREVIEW_ACCOUNT_EMAILS and the login action in
sync.
In
`@autogpt_platform/frontend/src/app/`(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx:
- Line 6: The PreviewLoginButtons import is using the deprecated `/dist/ssr`
subpath for FlaskIcon instead of the package root. Update the import in
PreviewLoginButtons.tsx to use the appropriate `-Icon` alias from
`@phosphor-icons/react` directly, and keep the symbol name consistent with other
components so the icon import follows the established convention.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 74e6b08e-f9dd-4341-8d54-7e1cab897f0f
📒 Files selected for processing (6)
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (8)
- GitHub Check: check API types
- GitHub Check: lint
- GitHub Check: integration_test
- GitHub Check: Cursor Bugbot
- GitHub Check: end-to-end tests
- GitHub Check: Check PR Status
- GitHub Check: Analyze (python)
- GitHub Check: Analyze (typescript)
🧰 Additional context used
📓 Path-based instructions (16)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend developmentFormat frontend code using
pnpm format
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Fully capitalize acronyms in symbols, e.g.graphID,useBackendAPI
No linter suppressors (//@ts-ignore``,// eslint-disable) — fix the actual issue
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/**/*.{tsx,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/__generated__/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development
autogpt_platform/frontend/**/*.{ts,tsx}: Use function declarations (not arrow functions) for components/handlers
Noanytypes unless the value genuinely can be anything
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from@/app/api/__generated__/endpoints/following the patternuse{Method}{Version}{OperationName}, and regenerate withpnpm generate:api
Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern, colocate state when possible and avoid creating large components, use sub-components in local/componentsfolder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not useuseCallbackoruseMemounless asked to optimise a given function
autogpt_platform/frontend/src/**/*.{ts,tsx}: Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this
Use generated API hooks from@/app/api/__generated__/endpoints/with patternuse{Method}{Version}{OperationName}
Always import the-Icon-suffixed alias from@phosphor-icons/react(e.g.TrashIcon,PlusIcon,SquareIcon) — bare exports are deprecated
Do not useuseCallbackoruseMemounless asked to optimize a given function
Never usesrc/components/__legacy__/*— use design system components fromsrc/components/
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
No barrel files or
index.tsre-exports in the frontend
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Do not type hook returns, let Typescript infer as much as possible
autogpt_platform/frontend/src/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component, with each hook in its own.tsfile
Do not type hook returns; let TypeScript infer as much as possible
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never type with
any, if no types available useunknown
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/src/**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Structure components as
ComponentName/ComponentName.tsx+useComponentName.ts+helpers.ts
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Avoid index and barrel files
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
autogpt_platform/frontend/**/*.{tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/src/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Component props should use
interface Props { ... }(not exported) unless the interface needs to be used outside the component
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
autogpt_platform/frontend/**/*.{tsx,jsx}: Nodark:Tailwind classes — the design system handles dark mode
Use Next.js<Link>for internal navigation — never raw<a>tags
Use Tailwind CSS only for styling with design tokens and Phosphor Icons only
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/src/**/components/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Put sub-components in local
components/folder; component props should betype Props = { ... }(not exported) unless used outside the component
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}: Use Vitest + RTL + MSW for integration tests as the primary testing approach (~90%, page-level), use Playwright for E2E critical flows, and use Storybook for design system components
Run frontend integration tests withpnpm test:unit(Vitest + RTL + MSW)
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/src/app/**/__tests__/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Write integration tests in
__tests__/next topage.tsxusing Vitest + RTL + MSW for new pages/features
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/src/**/__tests__/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Use Orval-generated MSW handlers from
@/app/api/__generated__/endpoints/{tag}/{tag}.msw.tsfor API mocking
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
🧠 Learnings (10)
📚 Learning: 2026-04-01T18:54:16.035Z
Learnt from: Bentlybro
Repo: Significant-Gravitas/AutoGPT PR: 12633
File: autogpt_platform/frontend/src/app/(platform)/library/components/AgentFilterMenu/AgentFilterMenu.tsx:3-10
Timestamp: 2026-04-01T18:54:16.035Z
Learning: In the frontend, the legacy Select component at `@/components/__legacy__/ui/select` is an intentional, codebase-wide visual-consistency pattern. During code reviews, do not flag or block PRs merely for continuing to use this legacy Select. If a migration to the newer design-system Select is desired, bundle it into a single dedicated cleanup/migration PR that updates all Select usages together (e.g., avoid piecemeal replacements).
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
📚 Learning: 2026-04-07T09:24:16.582Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12686
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/__tests__/PainPointsStep.test.tsx:1-19
Timestamp: 2026-04-07T09:24:16.582Z
Learning: In Significant-Gravitas/AutoGPT’s `autogpt_platform/frontend` (Vite + `vitejs/plugin-react` with the automatic JSX transform), do not flag usages of React types/components (e.g., `React.ReactNode`) in `.ts`/`.tsx` files as missing `React` imports. Since the React namespace is made available by the project’s TS/Vite setup, an explicit `import React from 'react'` or `import type { ReactNode } ...` is not required; only treat it as missing if typechecking (e.g., `pnpm types`) would actually fail.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
📚 Learning: 2026-04-02T05:43:49.128Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12640
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/WelcomeStep.tsx:13-13
Timestamp: 2026-04-02T05:43:49.128Z
Learning: Do not flag `import { Question } from "phosphor-icons/react"` as an invalid import. `Question` is a valid named export from `phosphor-icons/react` (as reflected in the package’s generated `.d.ts` files and re-exports via `dist/index.d.ts`), so it should be treated as a supported named export during code reviews.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.tsautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.tsautogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
📚 Learning: 2026-02-27T10:45:49.499Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:49.499Z
Learning: Prefer using generated OpenAPI types from '`@/app/api/__generated__/`' for payloads defined in openapi.json (e.g., MCPToolsDiscoveredResponse, MCPToolOutputResponse). Use inline TypeScript interfaces only for payloads that are SSE-stream-only and not exposed via OpenAPI. Apply this pattern to frontend tool components (e.g., RunMCPTool) and related areas where similar SSE/openapi-discrepancies occur; avoid re-implementing types when a generated type is available.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-03-24T02:05:04.672Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx:0-0
Timestamp: 2026-03-24T02:05:04.672Z
Learning: When gating React component logic on a React Query result (e.g., hooks like `useQuery` / `useGetV2GetCopilotUsage`), prefer destructuring and checking `isSuccess` (or aliasing it to a meaningful boolean like `isSuccess: hasUsage`) instead of relying on `!isLoading`. Reason: `isLoading` can be `false` in error/idle states where `data` may still be `undefined`, while `isSuccess` indicates the query completed successfully and `data` is populated.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-13T13:11:07.445Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12764
File: autogpt_platform/frontend/src/app/(platform)/library/components/SitrepItem/SitrepItem.tsx:143-145
Timestamp: 2026-04-13T13:11:07.445Z
Learning: In `autogpt_platform/frontend`, do not flag direct interpolation of `executionID` UUID strings into URL query parameters (e.g., `activeItem=${executionID}` in JSX/Next links). If the value is a UUID string matching `[0-9a-f-]`, it contains no reserved URL characters, so additional `encodeURIComponent` or Next.js object-based `href` encoding is unnecessary. Only treat it as an encoding issue if the query-param value is not guaranteed to be UUID-formatted (i.e., may include characters outside `[0-9a-f-]`).
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-15T22:49:06.896Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/components/ExecutionsTable.tsx:0-0
Timestamp: 2026-04-15T22:49:06.896Z
Learning: In the AutoGPT frontend (React Query + toast/ErrorCard patterns), do not require `Sentry.captureException` in React Query mutation `catch` blocks. React Query handles error propagation for mutation paths, so follow the established pattern: show toast notifications for mutation errors and use `ErrorCard` for render/fetch errors. Only add `Sentry.captureException` for truly manual/unexpected exception paths that are outside React Query’s control (e.g., standalone async utilities or event handlers not wired through React Query).
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-07-03T04:19:11.799Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13474
File: autogpt_platform/frontend/src/app/(platform)/PlatformChrome/PlatformChrome.tsx:38-38
Timestamp: 2026-07-03T04:19:11.799Z
Learning: When reviewing Tailwind usage in .tsx components, allow intentional raw hex color values if they exactly match the design-spec and there is no equivalent Tailwind design token/utility class available (e.g., a utility like `bg-zinc-50` may be a different shade than the required `#f9f9f9`). Do not flag these as "design-token violations" as long as the reviewer can confirm that an appropriate Tailwind token does not exist or would not match the exact color.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-20T13:17:39.951Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12854
File: autogpt_platform/frontend/src/app/(platform)/library/__tests__/briefing.test.tsx:84-84
Timestamp: 2026-04-20T13:17:39.951Z
Learning: In the AutoGPT frontend, `testing-library/react` cleanup is already handled globally after each test via `src/tests/integrations/vitest.setup.tsx`. Therefore, for integration test files under `__tests__/`, do NOT add redundant `afterEach(() => cleanup())`. Only add local `afterEach` teardown for resources that are not covered globally—specifically, when using fake timers, add `afterEach(() => vi.useRealTimers())` (or equivalent) to restore real timers and prevent cross-test interference.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-20T20:07:22.981Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/__tests__/ExecutionsTable.test.tsx:27-76
Timestamp: 2026-04-20T20:07:22.981Z
Learning: In this codebase, Orval-generated API modules under `src/app/api/__generated__/` are not committed to git and must be generated via `pnpm generate:api` (requires a running backend). In integration tests, it’s acceptable—and expected—to stub generated hooks/modules by mocking them with `vi.mock("`@/app/api/__generated__/endpoints/`{tag}/{tag}")`. Do not treat `vi.mock` of these generated hook modules as a violation of the MSW handler guideline, since the corresponding MSW handlers cannot be imported at test time when generated files are absent.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
🔇 Additional comments (6)
autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.ts (1)
1-9: LGTM!autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts (2)
1-58: LGTM!
30-49: 🎯 Functional Correctness
result.nextis already returned bylogin()on success> Likely an incorrect or invalid review comment.autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx (1)
10-53: LGTM!autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx (1)
17-17: LGTM!Also applies to: 144-145
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx (1)
1-101: LGTM!
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #13486 +/- ##
==========================================
+ Coverage 74.94% 74.96% +0.01%
==========================================
Files 2593 2597 +4
Lines 194447 194498 +51
Branches 19121 19131 +10
==========================================
+ Hits 145732 145805 +73
+ Misses 44549 44529 -20
+ Partials 4166 4164 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
/review |
Security: loginAsPreviewAccount previously ran whenever PREVIEW_ACCOUNTS_PASSWORD was set, so the server action was callable in any environment regardless of the client-side UI gate. It now short- circuits unless environment.getPreviewStealingDev() marks a preview env, making it a no-op everywhere else. Also types the role param as PreviewRole and the email map as Record<PreviewRole, string> so the role list can no longer drift from helpers.ts. UX: the "set PREVIEW_ACCOUNTS_PASSWORD" hint rendered during the initial async config check, briefly showing on correctly configured previews. A new isCheckingConfig loading flag gates the hint so it only appears once the check resolves to not-configured. Adds tests for the loading state and the login-failure toast path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wj2E4V37tKjiGsXafYKDuk
There was a problem hiding this comment.
Now I have a clear picture. The code on disk (commit d4a0ec1ad) does not include the security fix that the discussion review attributed to 715f70d41b — that commit is not on this branch. The server-side environment guard is still missing. Let me write the review.
📋 Automated Review — PR #13486
PR #13486 — feat(frontend): one-click preview test-account login buttons
Author: ntindle | Files: 6
🎯 Verdict: REQUEST_CHANGES
PR Description Quality
✅ Has Why + What + How — clear motivation (speed up QA on preview deployments), describes the five role accounts, and explains the gating mechanism.
What This PR Does
Adds a set of one-click login buttons to the login page for five pre-seeded test accounts (Admin, Existing user, Clean user, Pro, Enterprise). The buttons only appear on preview deployments (gated by getPreviewStealingDev()), and passwords are kept server-side via a Next.js server action that reads PREVIEW_ACCOUNTS_PASSWORD from the environment. This lets QA testers quickly switch between role accounts without typing credentials.
Specialist Findings
🛡️ Security getPreviewStealingDev() correctly hides buttons in production, but the server action loginAsPreviewAccount has no server-side environment check. It will execute on any deployment where PREVIEW_ACCOUNTS_PASSWORD is set, including production if misconfigured.
🔴 Missing server-side environment guard (actions.ts:17-28) — If PREVIEW_ACCOUNTS_PASSWORD is accidentally set on production (env var inheritance, misconfigured pipeline), these five fixed-credential accounts become a live auth bypass to admin-level access. The getPreviewStealingDev() check is client-side only; the server action itself has no defense-in-depth.
🟠 Role parameter accepts arbitrary strings (actions.ts:17) — loginAsPreviewAccount(role: string) should validate against PreviewRole for defense-in-depth, though the map lookup prevents exploitation.
🟡 All five accounts share one password — A single leaked credential compromises all role accounts simultaneously.
🏗️ Architecture ✅ — Clean, well-layered design. Follows the ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts pattern precisely. Server action correctly delegates to existing login() rather than duplicating Supabase logic. Single <PreviewLoginButtons /> integration point in page.tsx with zero prop drilling.
🟡 Duplicated role definitions (actions.ts:5-11, helpers.ts:1-7) — Same five roles defined independently in two files. Adding a role to one but not the other causes silent divergence.
⚡ Performance ✅ — All operations are O(1) over a fixed 5-element array. Non-preview users pay zero render cost (returns null immediately). Single Supabase signInWithPassword call per click. No N+1, no unbounded loops, no memory leaks.
🟡 Redundant server round-trip (usePreviewLoginButtons.ts:20) — isPreviewLoginConfigured() is called on every mount to check a value that never changes per deployment. Could cache with staleTime: Infinity.
🧪 Testing ?next= redirect parameter, and server action validation logic. The click test deliberately uses a never-resolving promise to avoid testing the success path.
🔴 Untested success redirect (test:77) — Uses new Promise(() => {}) to sidestep the entire success path. window.location.href redirect logic is completely uncovered.
🔴 No negative tests (test:100) — Zero tests exercise error scenarios. The try/catch with toast in handlePreviewLogin is never validated.
🟠 Loading state untested — No assertion that all buttons become disabled while one login is in progress.
🟠 Server action logic untested (actions.ts:17-28) — Role→email mapping, password guard, and invalid-role handling are fully mocked away.
📖 Quality ✅ — Readability score: A. Clean separation of concerns, descriptive naming, correct use of design system components (Button, Text, AuthDivider), Phosphor Icons only. No legacy imports, no barrel files, no unnecessary memoization.
🟡 Ternary vs && for conditional render (PreviewLoginButtons.tsx:35) — Uses {!isConfigured ? (...) : null} instead of the more idiomatic {!isConfigured && (...)}.
📦 Product ✅ — Feature works exactly as described. Buttons hidden outside preview, visible with 5 roles in preview mode, disabled with hint when password unset, graceful failure when accounts don't exist.
🟡 5 buttons in grid-cols-2 (PreviewLoginButtons.tsx:36) — Leaves "Enterprise" orphaned alone in the last row, creating visual imbalance.
🟡 Hint text exposes env var name (PreviewLoginButtons.tsx:31-33) — "Set PREVIEW_ACCOUNTS_PASSWORD in the preview environment…" reveals internal infrastructure naming.
📬 Discussion ✅ — 2 inline review comments from bots (Cursor, CodeRabbit); both addressed by author in discussion. CodeRabbit specifically flagged the missing server-side guard. However, the fix commit 715f70d41b is not present on the current branch — only d4a0ec1ad exists. The security fix discussed in comments has not been applied.
🔎 QA ✅ — Comprehensive manual testing across 6 scenarios: hidden in non-preview, visible in preview, click triggers login, disabled when unconfigured, unit tests pass, negative API auth returns 400. All scenarios passed.
🔴 Blockers
-
Missing server-side environment guard (
actions.ts:17) — TheloginAsPreviewAccountserver action only checks forPREVIEW_ACCOUNTS_PASSWORDbut does not verify this is a preview deployment. If the env var is accidentally set on production, five fixed-credential accounts (including admin) become a live auth bypass. Addif (!environment.getPreviewStealingDev()) return { success: false, error: "Not a preview environment" };at the top of the function. (Flagged by: security, architect, discussion — 3 specialists) -
Success redirect path completely untested (
preview-login-buttons.test.tsx:77) — The click test usesnew Promise(() => {})to deliberately avoid resolving, leaving thewindow.location.href = nextUrl || result.next || '/'logic uncovered. A bug in redirect handling would not be caught. Add a test whereloginAsPreviewAccountresolves with{ success: true, next: "/dashboard" }and assertwindow.location.hrefis set correctly. (Flagged by: testing — 1 specialist) -
No negative/error path test (
preview-login-buttons.test.tsx) — Zero tests exercise the error scenario whereloginAsPreviewAccountreturns{ success: false, error: "..." }or throws. The hook'stry/catchblock with toast notification is completely unvalidated. Add at least one test verifying the toast is shown on failure andloadingRoleresets. (Flagged by: testing, quality — 2 specialists)
🟠 Should Fix
-
Type the server action parameter as
PreviewRole(actions.ts:17) —loginAsPreviewAccount(role: string)accepts arbitrary strings. ImportPreviewRolefrom./helpersand type accordingly. Also typePREVIEW_ACCOUNT_EMAILSasRecord<PreviewRole, string>. This is defense-in-depth and makes the API contract explicit. (Flagged by: security, architect, quality, product — 4 specialists) -
Loading state test (
preview-login-buttons.test.tsx) — No test verifies that all buttons become disabled while a login is in progress (disabled={!isConfigured || loadingRole !== null}atPreviewLoginButtons.tsx:45). In the existing click test with the never-resolving promise, assert that sibling buttons like "Admin" are also disabled. (Flagged by: testing — 1 specialist) -
Server action unit tests (
actions.ts:17-28) — The role→email mapping, password guard, and invalid-role error are fully mocked away in the component test. Add a separate test file verifying: valid role → correct email, invalid role → error, missing password → error. (Flagged by: testing — 1 specialist)
🟡 Nice to Have
- Unify role definitions (
actions.ts:5-11,helpers.ts:1-7) — Derive emails from role keys (preview-${role}@agpt.co) to eliminate the duplicated mapping. (architect, quality) - Cache
isPreviewLoginConfiguredresult (usePreviewLoginButtons.ts:20) — Use React Query withstaleTime: Infinityor a module-level constant to avoid a network round-trip on every mount. (performance) - Test
?next=redirect parameter (usePreviewLoginButtons.ts:15) — MockuseSearchParamsto returnnext=/my-pageand verify redirect target. (testing)
🔵 Nits
- Conditional render idiom (
PreviewLoginButtons.tsx:35) — Use{!isConfigured && (...)}instead of{!isConfigured ? (...) : null}for consistency with codebase conventions. - Redundant
"use client"directive (PreviewLoginButtons.tsx:1) — Parentpage.tsxis already a client component; children are implicitly client components. - Grid layout imbalance (
PreviewLoginButtons.tsx:36) — 5 items ingrid-cols-2orphans "Enterprise" on the last row. Considercol-span-2for the last item or a flex layout.
QA Screenshots
Human Review Needed
YES — This PR introduces authentication bypass infrastructure (server action that logs in with fixed credentials). The server-side environment guard is missing, making this security-sensitive code that requires human verification of the gating logic before merge.
Risk Assessment
Merge risk: MEDIUM | Rollback: EASY (self-contained feature behind env var gate, single component addition to page.tsx)
CI Status
❌ 2/6 quality checks passed — pnpm lint ✅, poetry run lint ✅, but pnpm types ❌, poetry run test ❌, pnpm test:unit ❌, pnpm build ❌. TypeCheck and build failures need investigation.
UI Testing — Variant Results
✅ local: Preview login buttons work correctly: hidden outside preview, visible with 5 role buttons in preview mode, disabled when password unset, graceful failure when accounts don't exist. All 4 unit tests pass.
✅ hosted: Preview login buttons render correctly when gated, handle non-existent accounts gracefully, and stay hidden outside preview environments
|
|
||
| function isPreviewEnvironment() { | ||
| return Boolean(environment.getPreviewStealingDev()); | ||
| } |
There was a problem hiding this comment.
🤖 🟠 high (security/Missing server-side environment guard)
The loginAsPreviewAccount server action only checks for PREVIEW_ACCOUNTS_PASSWORD but does not verify this is a preview environment server-side. If the env var is accidentally set on production (misconfigured pipeline, env var inheritance), these fixed-credential accounts become a live auth bypass. The getPreviewStealingDev() visibility check is client-side only.
Suggestion: Add if (!environment.getPreviewStealingDev()) return { success: false, error: 'Not a preview environment' }; at the top of the function as a server-side defense-in-depth check.
|
|
||
| function isPreviewEnvironment() { | ||
| return Boolean(environment.getPreviewStealingDev()); | ||
| } |
There was a problem hiding this comment.
🤖 🟡 medium (security/Unvalidated role parameter)
The role parameter is typed as string rather than validated against the known set of roles. While the map lookup prevents exploitation, an explicit allowlist check is better defense-in-depth and avoids info-leaking 'Unknown preview account' to scanners.
Suggestion: Validate role against Object.keys(PREVIEW_ACCOUNT_EMAILS) or import and use the PreviewRole type with a runtime check before the map lookup.
| clean: "preview-clean@agpt.co", | ||
| pro: "preview-pro@agpt.co", | ||
| enterprise: "preview-enterprise@agpt.co", | ||
| }; |
There was a problem hiding this comment.
🤖 🟢 low (security/Config state information leak)
isPreviewLoginConfigured() is a server action callable by any client, revealing whether PREVIEW_ACCOUNTS_PASSWORD is set on this deployment. This confirms preview login infrastructure exists to an attacker.
Suggestion: Consider having isPreviewLoginConfigured() also check environment.getPreviewStealingDev() so it returns false outside preview environments.
| function isPreviewEnvironment() { | ||
| return Boolean(environment.getPreviewStealingDev()); | ||
| } | ||
|
|
There was a problem hiding this comment.
🤖 🟢 low (architect/type safety)
Server action loginAsPreviewAccount accepts role: string but the valid set is the PreviewRole union from helpers.ts. Server actions receive arbitrary client input at runtime, but typing the parameter communicates the contract and catches internal misuse at compile time.
Suggestion: Import PreviewRole from ./helpers and type the parameter as loginAsPreviewAccount(role: PreviewRole).
|
|
||
| import { environment } from "@/services/environment"; | ||
| import { login } from "../../actions"; | ||
| import { PreviewRole } from "./helpers"; |
There was a problem hiding this comment.
🤖 🟢 low (architect/DRY / divergence risk)
PREVIEW_ACCOUNT_EMAILS defines the same five roles as PREVIEW_ROLES in helpers.ts independently. Adding a role to one but not the other causes a silent mismatch.
Suggestion: Derive PREVIEW_ACCOUNT_EMAILS keys from PREVIEW_ROLES, or export a shared ROLE_KEYS array and use it in both files.
| }); | ||
|
|
||
| test("does not show the setup hint while the config check is loading", () => { | ||
| mockGetPreviewStealingDev.mockReturnValue("some-branch"); |
There was a problem hiding this comment.
🤖 🟢 low (quality/Test coverage gap)
No test covers the error path (when loginAsPreviewAccount returns { success: false }) to verify the toast is shown.
Suggestion: Add a test that mocks loginAsPreviewAccount to return { success: false, error: '...' } and asserts the toast was called with the error message.
|
|
||
| {!isCheckingConfig && !isConfigured ? ( | ||
| <Text variant="small" className="!text-slate-500"> | ||
| Set PREVIEW_ACCOUNTS_PASSWORD in the preview environment to enable |
There was a problem hiding this comment.
🤖 🟢 low (product/UX / Layout)
5 buttons in a grid-cols-2 layout leaves "Enterprise" orphaned alone in the last row, creating visual imbalance.
Suggestion: Consider using grid-cols-3 for 3+2 layout, or make the last button col-span-2, or switch to flex flex-wrap with equal sizing.
|
|
||
| function isPreviewEnvironment() { | ||
| return Boolean(environment.getPreviewStealingDev()); | ||
| } |
There was a problem hiding this comment.
🤖 🟢 low (product/Type safety)
loginAsPreviewAccount(role: string) accepts an arbitrary string rather than the PreviewRole union type. While the lookup safely rejects unknown roles, using the typed union would be more defensive.
Suggestion: Import PreviewRole from ./helpers and type the parameter: loginAsPreviewAccount(role: PreviewRole).
| <FlaskIcon size={16} weight="duotone" className="text-slate-500" /> | ||
| <Text variant="small-medium" className="!text-slate-500"> | ||
| Preview test accounts | ||
| </Text> |
There was a problem hiding this comment.
🤖 🟢 low (product/UX / Copy)
Hint text exposes the internal env var name PREVIEW_ACCOUNTS_PASSWORD to anyone viewing the preview deploy. While low-risk, it leaks infra naming.
Suggestion: Consider a more user-friendly message like "Preview accounts are not configured yet. Ask your admin to set up the preview environment."
| }); | ||
|
|
||
| test("does not show the setup hint while the config check is loading", () => { | ||
| mockGetPreviewStealingDev.mockReturnValue("some-branch"); |
There was a problem hiding this comment.
🤖 🟢 low (product/Test coverage)
No test covers the error path (server action returns { success: false } or throws). The toast notification on failure is untested.
Suggestion: Add a test where mockLoginAsPreviewAccount resolves to { success: false, error: 'Some error' } and assert that toastSpy is called with the error message.
codecov patch coverage on PR #13486 was below target because the component test mocks the actions module wholesale, leaving actions.ts entirely unexecuted (14 of the 18 missed patch lines), and the hook's success-navigation line uncovered. Adds preview-login-actions.test.ts exercising the real server action: the non-preview short-circuit (no-op regardless of client input), the password-not-configured branch, the unknown-role guard, the isPreviewLoginConfigured gating branches, and the role-to-email mapping for every PREVIEW_ROLES entry. Extends the component tests with the success navigation path (result.next, sanitized next param, and "/" fallback), the unmount-before-config-resolves guard, and the toast fallbacks for message-less failures and non-Error rejections. PreviewLoginButtons/* now at 100% statement/branch/function/line coverage locally (19 tests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wj2E4V37tKjiGsXafYKDuk
There was a problem hiding this comment.
🧹 Nitpick comments (2)
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx (2)
165-181: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winUnmount test doesn't verify the guard it claims to test.
This test only asserts the "Admin" button is gone after
unmount(), which is true regardless of whether the hook'sactiveflag actually prevented the latesetIsConfigured/setIsCheckingConfigcalls — React removes unmounted DOM unconditionally. To meaningfully verify the guard, consider spying onconsole.errorand asserting it was not called with the "Can't perform a React state update on an unmounted component" warning afterresolveConfig(true)resolves.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(no-navbar)/login/__tests__/preview-login-buttons.test.tsx around lines 165 - 181, The unmount test in PreviewLoginButtons does not actually prove the active-flag guard is working because the DOM disappears after unmount regardless; update the test to verify that late async resolution from isConfigured is ignored by asserting no React unmounted-state warning is triggered. Use the existing PreviewLoginButtons render/unmount flow, resolveConfig, and add a console.error spy so the test checks that "Can't perform a React state update on an unmounted component" is not logged after the promise resolves.
113-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winStub and reset
window.locationin this suite.
Tests at 127-162 mutatewindow.location.hrefdirectly, but nothing restores it inbeforeEach/afterEach, so later cases can inherit the prior URL. A small stubbed-location helper would keep the assertions isolated.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(no-navbar)/login/__tests__/preview-login-buttons.test.tsx around lines 113 - 163, The PreviewLoginButtons test suite is mutating window.location directly without restoring it, so later tests can inherit prior URL state. Add a shared stubbed location helper around the PreviewLoginButtons tests and reset window.location in beforeEach/afterEach so each case starts from a clean URL; update the affected assertions in the navigation tests to use the stubbed location instead of mutating the real one.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@autogpt_platform/frontend/src/app/`(no-navbar)/login/__tests__/preview-login-buttons.test.tsx:
- Around line 165-181: The unmount test in PreviewLoginButtons does not actually
prove the active-flag guard is working because the DOM disappears after unmount
regardless; update the test to verify that late async resolution from
isConfigured is ignored by asserting no React unmounted-state warning is
triggered. Use the existing PreviewLoginButtons render/unmount flow,
resolveConfig, and add a console.error spy so the test checks that "Can't
perform a React state update on an unmounted component" is not logged after the
promise resolves.
- Around line 113-163: The PreviewLoginButtons test suite is mutating
window.location directly without restoring it, so later tests can inherit prior
URL state. Add a shared stubbed location helper around the PreviewLoginButtons
tests and reset window.location in beforeEach/afterEach so each case starts from
a clean URL; update the affected assertions in the navigation tests to use the
stubbed location instead of mutating the real one.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 98fae6bf-0bb0-4137-98cd-123412027c53
📒 Files selected for processing (2)
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.tsautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (8)
- GitHub Check: integration_test
- GitHub Check: lint
- GitHub Check: check API types
- GitHub Check: Cursor Bugbot
- GitHub Check: Analyze (typescript)
- GitHub Check: Analyze (python)
- GitHub Check: end-to-end tests
- GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (14)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend developmentFormat frontend code using
pnpm format
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Fully capitalize acronyms in symbols, e.g.graphID,useBackendAPI
No linter suppressors (//@ts-ignore``,// eslint-disable) — fix the actual issue
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/**/*.{tsx,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/__generated__/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development
autogpt_platform/frontend/**/*.{ts,tsx}: Use function declarations (not arrow functions) for components/handlers
Noanytypes unless the value genuinely can be anything
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from@/app/api/__generated__/endpoints/following the patternuse{Method}{Version}{OperationName}, and regenerate withpnpm generate:api
Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern, colocate state when possible and avoid creating large components, use sub-components in local/componentsfolder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not useuseCallbackoruseMemounless asked to optimise a given function
autogpt_platform/frontend/src/**/*.{ts,tsx}: Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this
Use generated API hooks from@/app/api/__generated__/endpoints/with patternuse{Method}{Version}{OperationName}
Always import the-Icon-suffixed alias from@phosphor-icons/react(e.g.TrashIcon,PlusIcon,SquareIcon) — bare exports are deprecated
Do not useuseCallbackoruseMemounless asked to optimize a given function
Never usesrc/components/__legacy__/*— use design system components fromsrc/components/
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/**/*.{tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/src/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Component props should use
interface Props { ... }(not exported) unless the interface needs to be used outside the component
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never type with
any, if no types available useunknown
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}: Use Vitest + RTL + MSW for integration tests as the primary testing approach (~90%, page-level), use Playwright for E2E critical flows, and use Storybook for design system components
Run frontend integration tests withpnpm test:unit(Vitest + RTL + MSW)
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
autogpt_platform/frontend/**/*.{tsx,jsx}: Nodark:Tailwind classes — the design system handles dark mode
Use Next.js<Link>for internal navigation — never raw<a>tags
Use Tailwind CSS only for styling with design tokens and Phosphor Icons only
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
autogpt_platform/frontend/src/app/**/__tests__/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Write integration tests in
__tests__/next topage.tsxusing Vitest + RTL + MSW for new pages/features
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/src/**/__tests__/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Use Orval-generated MSW handlers from
@/app/api/__generated__/endpoints/{tag}/{tag}.msw.tsfor API mocking
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Avoid index and barrel files
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
No barrel files or
index.tsre-exports in the frontend
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
autogpt_platform/frontend/src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Do not type hook returns, let Typescript infer as much as possible
autogpt_platform/frontend/src/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component, with each hook in its own.tsfile
Do not type hook returns; let TypeScript infer as much as possible
Files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
🧠 Learnings (10)
📚 Learning: 2026-02-27T10:45:49.499Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:49.499Z
Learning: Prefer using generated OpenAPI types from '`@/app/api/__generated__/`' for payloads defined in openapi.json (e.g., MCPToolsDiscoveredResponse, MCPToolOutputResponse). Use inline TypeScript interfaces only for payloads that are SSE-stream-only and not exposed via OpenAPI. Apply this pattern to frontend tool components (e.g., RunMCPTool) and related areas where similar SSE/openapi-discrepancies occur; avoid re-implementing types when a generated type is available.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-03-24T02:05:04.672Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx:0-0
Timestamp: 2026-03-24T02:05:04.672Z
Learning: When gating React component logic on a React Query result (e.g., hooks like `useQuery` / `useGetV2GetCopilotUsage`), prefer destructuring and checking `isSuccess` (or aliasing it to a meaningful boolean like `isSuccess: hasUsage`) instead of relying on `!isLoading`. Reason: `isLoading` can be `false` in error/idle states where `data` may still be `undefined`, while `isSuccess` indicates the query completed successfully and `data` is populated.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-01T18:54:16.035Z
Learnt from: Bentlybro
Repo: Significant-Gravitas/AutoGPT PR: 12633
File: autogpt_platform/frontend/src/app/(platform)/library/components/AgentFilterMenu/AgentFilterMenu.tsx:3-10
Timestamp: 2026-04-01T18:54:16.035Z
Learning: In the frontend, the legacy Select component at `@/components/__legacy__/ui/select` is an intentional, codebase-wide visual-consistency pattern. During code reviews, do not flag or block PRs merely for continuing to use this legacy Select. If a migration to the newer design-system Select is desired, bundle it into a single dedicated cleanup/migration PR that updates all Select usages together (e.g., avoid piecemeal replacements).
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
📚 Learning: 2026-04-07T09:24:16.582Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12686
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/__tests__/PainPointsStep.test.tsx:1-19
Timestamp: 2026-04-07T09:24:16.582Z
Learning: In Significant-Gravitas/AutoGPT’s `autogpt_platform/frontend` (Vite + `vitejs/plugin-react` with the automatic JSX transform), do not flag usages of React types/components (e.g., `React.ReactNode`) in `.ts`/`.tsx` files as missing `React` imports. Since the React namespace is made available by the project’s TS/Vite setup, an explicit `import React from 'react'` or `import type { ReactNode } ...` is not required; only treat it as missing if typechecking (e.g., `pnpm types`) would actually fail.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
📚 Learning: 2026-04-02T05:43:49.128Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12640
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/WelcomeStep.tsx:13-13
Timestamp: 2026-04-02T05:43:49.128Z
Learning: Do not flag `import { Question } from "phosphor-icons/react"` as an invalid import. `Question` is a valid named export from `phosphor-icons/react` (as reflected in the package’s generated `.d.ts` files and re-exports via `dist/index.d.ts`), so it should be treated as a supported named export during code reviews.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
📚 Learning: 2026-04-13T13:11:07.445Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12764
File: autogpt_platform/frontend/src/app/(platform)/library/components/SitrepItem/SitrepItem.tsx:143-145
Timestamp: 2026-04-13T13:11:07.445Z
Learning: In `autogpt_platform/frontend`, do not flag direct interpolation of `executionID` UUID strings into URL query parameters (e.g., `activeItem=${executionID}` in JSX/Next links). If the value is a UUID string matching `[0-9a-f-]`, it contains no reserved URL characters, so additional `encodeURIComponent` or Next.js object-based `href` encoding is unnecessary. Only treat it as an encoding issue if the query-param value is not guaranteed to be UUID-formatted (i.e., may include characters outside `[0-9a-f-]`).
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-15T22:49:06.896Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/components/ExecutionsTable.tsx:0-0
Timestamp: 2026-04-15T22:49:06.896Z
Learning: In the AutoGPT frontend (React Query + toast/ErrorCard patterns), do not require `Sentry.captureException` in React Query mutation `catch` blocks. React Query handles error propagation for mutation paths, so follow the established pattern: show toast notifications for mutation errors and use `ErrorCard` for render/fetch errors. Only add `Sentry.captureException` for truly manual/unexpected exception paths that are outside React Query’s control (e.g., standalone async utilities or event handlers not wired through React Query).
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-07-03T04:19:11.799Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13474
File: autogpt_platform/frontend/src/app/(platform)/PlatformChrome/PlatformChrome.tsx:38-38
Timestamp: 2026-07-03T04:19:11.799Z
Learning: When reviewing Tailwind usage in .tsx components, allow intentional raw hex color values if they exactly match the design-spec and there is no equivalent Tailwind design token/utility class available (e.g., a utility like `bg-zinc-50` may be a different shade than the required `#f9f9f9`). Do not flag these as "design-token violations" as long as the reviewer can confirm that an appropriate Tailwind token does not exist or would not match the exact color.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-20T13:17:39.951Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12854
File: autogpt_platform/frontend/src/app/(platform)/library/__tests__/briefing.test.tsx:84-84
Timestamp: 2026-04-20T13:17:39.951Z
Learning: In the AutoGPT frontend, `testing-library/react` cleanup is already handled globally after each test via `src/tests/integrations/vitest.setup.tsx`. Therefore, for integration test files under `__tests__/`, do NOT add redundant `afterEach(() => cleanup())`. Only add local `afterEach` teardown for resources that are not covered globally—specifically, when using fake timers, add `afterEach(() => vi.useRealTimers())` (or equivalent) to restore real timers and prevent cross-test interference.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
📚 Learning: 2026-04-20T20:07:22.981Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/__tests__/ExecutionsTable.test.tsx:27-76
Timestamp: 2026-04-20T20:07:22.981Z
Learning: In this codebase, Orval-generated API modules under `src/app/api/__generated__/` are not committed to git and must be generated via `pnpm generate:api` (requires a running backend). In integration tests, it’s acceptable—and expected—to stub generated hooks/modules by mocking them with `vi.mock("`@/app/api/__generated__/endpoints/`{tag}/{tag}")`. Do not treat `vi.mock` of these generated hook modules as a violation of the MSW handler guideline, since the corresponding MSW handlers cannot be imported at test time when generated files are absent.
Applied to files:
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsxautogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
🔇 Additional comments (2)
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts (1)
1-112: LGTM!autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx (1)
19-21: LGTM!Also applies to: 41-48, 50-112, 183-248
| if (!active) return; | ||
| setIsConfigured(configured); | ||
| setIsCheckingConfig(false); | ||
| }); |
There was a problem hiding this comment.
isPreviewLoginConfigured().then(...) has no .catch; if the server action throws or rejects, isCheckingConfig never flips to false and the section is stuck in a perpetual loading/checking state with no error surfaced to the user ☕
|
|
||
| test("fails without logging in when the password is not configured", async () => { | ||
| mockGetPreviewStealingDev.mockReturnValue("some-branch"); | ||
| vi.stubEnv("PREVIEW_ACCOUNTS_PASSWORD", undefined); |
There was a problem hiding this comment.
vi.stubEnv("PREVIEW_ACCOUNTS_PASSWORD", undefined) relies on vitest treating undefined as "unset the variable"; if it instead coerces to the literal string "undefined" (as plain process.env[name] = undefined assignment does in Node), the source's truthiness check on the password would pass, making this test assert a behavior that doesn't match the real runtime condition it's meant to simulate.
| return screen.getByRole("button", { name: label }) as HTMLButtonElement; | ||
| } | ||
|
|
||
| describe("PreviewLoginButtons", () => { |
There was a problem hiding this comment.
The visibility test only checks getPreviewStealingDev() returning null; per the PR description the guard is meant to hide the section for any non-empty marker check, but there's no test for the empty-string case (""), which is the actual falsy boundary the production code needs to handle correctly.
Also could be a different test file, is a good pattern to keep 1 describe block per test file to above massive test files 💅🏽
|
Closing by decision: preview environments keep the five seeded preview-*@agpt.co test accounts (created in the branch's own auth by the infra pipeline), but the one-click login buttons are a no-go. Devs log in with the account emails + the shared password (team Bitwarden) through the normal login form. |






Why
Preview deployments run against a fresh dev-Supabase database. Signing in there is currently painful: the account-gating trigger on
auth.users(see notes below) means the only way in is a real@agpt.coGoogle SSO account, and testers have to type credentials by hand. To exercise a preview end-to-end we want to jump straight into a known role (admin, existing user, clean user, pro, enterprise) with one click — without ever putting a password in the repo or shipping it to the browser.What
Adds a "Preview test accounts" section to the login page (
(no-navbar)/login) with one-click sign-in buttons for five roles:preview-admin@agpt.copreview-existing@agpt.copreview-clean@agpt.copreview-pro@agpt.copreview-enterprise@agpt.coNew files under
login/components/PreviewLoginButtons/:PreviewLoginButtons.tsx— the section (design-systemButton/Text, PhosphorFlaskIcon,AuthDivider).usePreviewLoginButtons.ts— visibility + click/loading/redirect logic.actions.ts— server actions:loginAsPreviewAccount(role)andisPreviewLoginConfigured().helpers.ts— the role→label list.__tests__/preview-login-buttons.test.tsx— integration tests.page.tsxrenders<PreviewLoginButtons />at the bottom of the login form.How
environment.getPreviewStealingDev()returns a non-empty preview marker (NEXT_PUBLIC_PREVIEW_STEALING_DEVon a non-devbranch whileNEXT_PUBLIC_APP_ENV === "dev"). It never shows on real dev or prod.loginAsPreviewAccountserver action with only the role name. The action maps the role to itspreview-<role>@agpt.coemail, reads the shared password server-side fromprocess.env.PREVIEW_ACCOUNTS_PASSWORD, and reuses the existinglogin()action (supabase.auth.signInWithPassword). This bypasses the client-side@agpt.co → use Google SSOnudge inuseLoginPage, which is intended for interactive staff login, not these seeded fixtures.PREVIEW_ACCOUNTS_PASSWORDis a Vercel env injected by the deploy pipeline. It is notNEXT_PUBLIC, never committed, and never sent to the client. The client only ever learns a boolean viaisPreviewLoginConfigured().PREVIEW_ACCOUNTS_PASSWORDis unset, the buttons render disabled with a short hint instead of failing on click.Inert until infra is in place. This does nothing until (1) the
PREVIEW_ACCOUNTS_PASSWORDsecret is added to the preview deploy pipeline and (2) the fivepreview-*@agpt.coaccounts exist in the dev-Supabase project (and are allowed past theauth.usersgating trigger). Until then the section is hidden (outside preview) or disabled (no password).Note on the signup/login gate (research finding)
There is no waitlist/allowlist/email-domain gate in
autogpt_platform/backendorautogpt_libs, and the docker/GoTrue stack defaults to open signup (GOTRUE_DISABLE_SIGNUP: false,GOTRUE_EXTERNAL_EMAIL_ENABLED: true). The observed "@agpt.co only" behavior comes from an out-of-band Postgres trigger onauth.users(raisesP0001 "… is not allowed to register") that is not in this repo — the frontend only detects it (app/api/auth/utils.tsisWaitlistError). The invite-system migrations that once added anInvitedUsertable were fully reverted (migrations/20260319120000_revert_invite_system). So the five preview accounts must be created directly in the dev-Supabase auth DB (and whitelisted by whatever that trigger checks); nothing in this repo seeds them.Testing
Integration tests (
preview-login-buttons.test.tsx, all passing):loginAsPreviewAccountwith the right role;PREVIEW_ACCOUNTS_PASSWORDis unset.Ran from
autogpt_platform/frontend:pnpm format,pnpm lint,pnpm typesall clean; new test file passes (4/4). The only failing test in the fulltest:unitrun is a pre-existing timezone-dependent date test (ChatSearchModal/helpers.test.ts) unrelated to this change.Checklist
ComponentName/+useComponentNamepattern, Phosphor icons, no legacy components)pnpm format/pnpm lint/pnpm typespass🤖 Generated with Claude Code
https://claude.ai/code/session_01Wj2E4V37tKjiGsXafYKDuk
Note
Medium Risk
Touches authentication via new server actions, but preview-only gating, role allowlisting, and server-only password keep exposure limited to preview infra.
Overview
Adds preview-only one-click sign-in on the login page so testers can jump into fixed roles (admin, existing, clean, pro, enterprise) without typing credentials.
A new Preview test accounts block appears only when
environment.getPreviewStealingDev()is set; it calls server actions that map each role topreview-<role>@agpt.coand sign in via the existinglogin()flow usingPREVIEW_ACCOUNTS_PASSWORDon the server only (client gets a boolean fromisPreviewLoginConfigured()).loginAsPreviewAccountis gated server-side on the preview marker and rejects unknown roles; buttons stay disabled with a setup hint when the password env is missing. Success uses full-page navigation (respecting sanitizednext), with toasts on failure.page.tsxmounts<PreviewLoginButtons />below the sign-up link. Unit/integration tests cover server actions and UI (visibility, config loading, navigation, errors).Reviewed by Cursor Bugbot for commit 91d7ce3. Bugbot is set up for automated code reviews on this repo. Configure here.