Skip to content

feat(frontend): one-click preview test-account login buttons#13486

Closed
ntindle wants to merge 3 commits into
devfrom
feat/preview-login-buttons
Closed

feat(frontend): one-click preview test-account login buttons#13486
ntindle wants to merge 3 commits into
devfrom
feat/preview-login-buttons

Conversation

@ntindle

@ntindle ntindle commented Jul 5, 2026

Copy link
Copy Markdown
Member

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.co Google 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:

  • Admin → preview-admin@agpt.co
  • Existing user → preview-existing@agpt.co
  • Clean user → preview-clean@agpt.co
  • Pro → preview-pro@agpt.co
  • Enterprise → preview-enterprise@agpt.co

New files under login/components/PreviewLoginButtons/:

  • PreviewLoginButtons.tsx — the section (design-system Button/Text, Phosphor FlaskIcon, AuthDivider).
  • usePreviewLoginButtons.ts — visibility + click/loading/redirect logic.
  • actions.ts — server actions: loginAsPreviewAccount(role) and isPreviewLoginConfigured().
  • helpers.ts — the role→label list.
  • __tests__/preview-login-buttons.test.tsx — integration tests.

page.tsx renders <PreviewLoginButtons /> at the bottom of the login form.

How

  • Visibility: the section only renders when environment.getPreviewStealingDev() returns a non-empty preview marker (NEXT_PUBLIC_PREVIEW_STEALING_DEV on a non-dev branch while NEXT_PUBLIC_APP_ENV === "dev"). It never shows on real dev or prod.
  • Auth: clicking a button calls the loginAsPreviewAccount server action with only the role name. The action maps the role to its preview-<role>@agpt.co email, reads the shared password server-side from process.env.PREVIEW_ACCOUNTS_PASSWORD, and reuses the existing login() action (supabase.auth.signInWithPassword). This bypasses the client-side @agpt.co → use Google SSO nudge in useLoginPage, which is intended for interactive staff login, not these seeded fixtures.
  • Secret handling: PREVIEW_ACCOUNTS_PASSWORD is a Vercel env injected by the deploy pipeline. It is not NEXT_PUBLIC, never committed, and never sent to the client. The client only ever learns a boolean via isPreviewLoginConfigured().
  • Disabled state: if PREVIEW_ACCOUNTS_PASSWORD is 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_PASSWORD secret is added to the preview deploy pipeline and (2) the five preview-*@agpt.co accounts exist in the dev-Supabase project (and are allowed past the auth.users gating 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/backend or autogpt_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 on auth.users (raises P0001 "… is not allowed to register") that is not in this repo — the frontend only detects it (app/api/auth/utils.ts isWaitlistError). The invite-system migrations that once added an InvitedUser table 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):

  • hidden when the preview marker is absent;
  • all five buttons visible + enabled in a configured preview;
  • clicking a button calls loginAsPreviewAccount with the right role;
  • disabled + hint shown when PREVIEW_ACCOUNTS_PASSWORD is unset.

Ran from autogpt_platform/frontend: pnpm format, pnpm lint, pnpm types all clean; new test file passes (4/4). The only failing test in the full test:unit run is a pre-existing timezone-dependent date test (ChatSearchModal/helpers.test.ts) unrelated to this change.

Checklist

  • Follows frontend conventions (design-system components, function declarations, ComponentName/ + useComponentName pattern, Phosphor icons, no legacy components)
  • Tests added for new behavior
  • pnpm format / pnpm lint / pnpm types pass
  • No secrets committed; password read server-side only

🤖 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 to preview-<role>@agpt.co and sign in via the existing login() flow using PREVIEW_ACCOUNTS_PASSWORD on the server only (client gets a boolean from isPreviewLoginConfigured()). loginAsPreviewAccount is 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 sanitized next), with toasts on failure.

page.tsx mounts <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.

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
@ntindle ntindle requested a review from a team as a code owner July 5, 2026 23:03
@ntindle ntindle requested review from Bentlybro and kcze and removed request for a team July 5, 2026 23:03
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Jul 5, 2026
@github-actions github-actions Bot added the platform/frontend AutoGPT Platform - Front end label Jul 5, 2026
@github-actions github-actions Bot added the size/l label Jul 5, 2026
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds 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.

Changes

Preview Login Buttons

Layer / File(s) Summary
Preview role data and server actions
.../PreviewLoginButtons/helpers.ts, .../PreviewLoginButtons/actions.ts, .../login/__tests__/preview-login-actions.test.ts
Defines PREVIEW_ROLES/PreviewRole, maps preview roles to account emails, and adds server actions for preview availability checks and preview-account login with test coverage.
usePreviewLoginButtons hook
.../PreviewLoginButtons/usePreviewLoginButtons.ts
Computes preview/config state, runs the async config check, and handles preview login by calling the server action, navigating with a sanitized next URL, and showing a destructive toast on error.
PreviewLoginButtons component and page wiring
.../PreviewLoginButtons/PreviewLoginButtons.tsx, .../login/page.tsx
Renders the preview-account divider, warning message, and role buttons from the hook, hides the UI outside preview mode, and inserts the component into the login page.
Preview login buttons tests
.../login/__tests__/preview-login-buttons.test.tsx
Verifies preview rendering, enabled and disabled states, login invocation, navigation outcomes, unmount handling, and failure toasts across preview and configuration scenarios.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: Pwuts, Bentlybro, 0ubbe

Poem

A rabbit tapped the login tree,
Five preview doors, one cup of tea.
Buttons bloom in tidy rows,
Through auth and tests the button garden grows.
🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: adding one-click preview test-account login buttons on the frontend.
Description check ✅ Passed The description is closely related to the changeset and accurately describes the preview login feature and its implementation.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/preview-login-buttons

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

This check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early.

🟢 Low Risk — File Overlap Only

These 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: openapi.json, lock files.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 value

Icon imported from /dist/ssr subpath 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/react directly 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 win

Consider adding a test for the login-failure/toast path.

Current tests cover hidden, enabled, click, and disabled states, but not the case where loginAsPreviewAccount resolves with { success: false, error } (or rejects), which should trigger the toast in usePreviewLoginButtons.

🤖 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 win

Duplicated role list drifts from helpers.ts.

PREVIEW_ACCOUNT_EMAILS re-enumerates the roles already defined in PREVIEW_ROLES/PreviewRole (helpers.ts), with a looser Record<string, string> type and role: string param. 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

📥 Commits

Reviewing files that changed from the base of the PR and between bd66b8d and d4a0ec1.

📒 Files selected for processing (6)
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/usePreviewLoginButtons.ts
  • autogpt_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 development

Format 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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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
No any types 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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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 pattern use{Method}{Version}{OperationName}, and regenerate with pnpm 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 /components folder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not use useCallback or useMemo unless 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 pattern use{Method}{Version}{OperationName}
Always import the -Icon-suffixed alias from @phosphor-icons/react (e.g. TrashIcon, PlusIcon, SquareIcon) — bare exports are deprecated
Do not use useCallback or useMemo unless asked to optimize a given function
Never use src/components/__legacy__/* — use design system components from src/components/

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.ts re-exports in the frontend

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_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 .ts file
Do not type hook returns; let TypeScript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_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 use unknown

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/helpers.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • 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/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_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}: No dark: 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.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_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 be type 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 with pnpm 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 to page.tsx using 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.ts for 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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/actions.ts
  • autogpt_platform/frontend/src/app/(no-navbar)/login/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • 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/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • autogpt_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.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • 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/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • 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/page.tsx
  • autogpt_platform/frontend/src/app/(no-navbar)/login/components/PreviewLoginButtons/PreviewLoginButtons.tsx
  • 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.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.next is already returned by login() 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

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.96%. Comparing base (bd66b8d) to head (91d7ce3).

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     
Flag Coverage Δ
platform-frontend 44.47% <100.00%> (+0.07%) ⬆️
platform-frontend-e2e 31.96% <32.00%> (+0.11%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Platform Backend 82.10% <ø> (ø)
Platform Frontend 48.79% <100.00%> (+0.13%) ⬆️
AutoGPT Libs ∅ <ø> (∅)
Classic AutoGPT 28.43% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ntindle

ntindle commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #13486 at d4a0ec1.

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

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ⚠️ — The client-side gating via 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 ⚠️ — 4 tests cover visibility states and basic click trigger, but the most important paths are untested: error handling (toast on failure), successful login (redirect), loading state (buttons disabled during auth), ?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

  1. Missing server-side environment guard (actions.ts:17) — The loginAsPreviewAccount server action only checks for PREVIEW_ACCOUNTS_PASSWORD but 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. Add if (!environment.getPreviewStealingDev()) return { success: false, error: "Not a preview environment" }; at the top of the function. (Flagged by: security, architect, discussion — 3 specialists)

  2. Success redirect path completely untested (preview-login-buttons.test.tsx:77) — The click test uses new Promise(() => {}) to deliberately avoid resolving, leaving the window.location.href = nextUrl || result.next || '/' logic uncovered. A bug in redirect handling would not be caught. Add a test where loginAsPreviewAccount resolves with { success: true, next: "/dashboard" } and assert window.location.href is set correctly. (Flagged by: testing — 1 specialist)

  3. No negative/error path test (preview-login-buttons.test.tsx) — Zero tests exercise the error scenario where loginAsPreviewAccount returns { success: false, error: "..." } or throws. The hook's try/catch block with toast notification is completely unvalidated. Add at least one test verifying the toast is shown on failure and loadingRole resets. (Flagged by: testing, quality — 2 specialists)

🟠 Should Fix

  1. Type the server action parameter as PreviewRole (actions.ts:17) — loginAsPreviewAccount(role: string) accepts arbitrary strings. Import PreviewRole from ./helpers and type accordingly. Also type PREVIEW_ACCOUNT_EMAILS as Record<PreviewRole, string>. This is defense-in-depth and makes the API contract explicit. (Flagged by: security, architect, quality, product — 4 specialists)

  2. 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} at PreviewLoginButtons.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)

  3. 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

  1. 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)
  2. Cache isPreviewLoginConfigured result (usePreviewLoginButtons.ts:20) — Use React Query with staleTime: Infinity or a module-level constant to avoid a network round-trip on every mount. (performance)
  3. Test ?next= redirect parameter (usePreviewLoginButtons.ts:15) — Mock useSearchParams to return next=/my-page and verify redirect target. (testing)

🔵 Nits

  1. Conditional render idiom (PreviewLoginButtons.tsx:35) — Use {!isConfigured && (...)} instead of {!isConfigured ? (...) : null} for consistency with codebase conventions.
  2. Redundant "use client" directive (PreviewLoginButtons.tsx:1) — Parent page.tsx is already a client component; children are implicitly client components.
  3. Grid layout imbalance (PreviewLoginButtons.tsx:36) — 5 items in grid-cols-2 orphans "Enterprise" on the last row. Consider col-span-2 for the last item or a flex layout.

QA Screenshots

Screenshot Description
Login page default No preview buttons in non-preview env ✅
Preview buttons enabled All 5 role buttons visible and enabled ✅
Preview buttons scrolled Full button set visible on scroll ✅
After admin click Login attempt fails gracefully (account not seeded locally) ✅
Disabled state Buttons visible with configuration hint when password unset ✅

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());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟠 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());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟡 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",
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🟢 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.

@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 🚧 Needs work in AutoGPT development kanban Jul 6, 2026
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
@github-actions github-actions Bot added size/xl and removed size/l labels Jul 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx (2)

165-181: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Unmount 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's active flag actually prevented the late setIsConfigured/setIsCheckingConfig calls — React removes unmounted DOM unconditionally. To meaningfully verify the guard, consider spying on console.error and asserting it was not called with the "Can't perform a React state update on an unmounted component" warning after resolveConfig(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 win

Stub and reset window.location in this suite.
Tests at 127-162 mutate window.location.href directly, but nothing restores it in beforeEach/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

📥 Commits

Reviewing files that changed from the base of the PR and between 715f70d and 91d7ce3.

📒 Files selected for processing (2)
  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-actions.test.ts
  • autogpt_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 development

Format 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.tsx
  • autogpt_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.tsx
  • autogpt_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
No any types 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.tsx
  • autogpt_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 pattern use{Method}{Version}{OperationName}, and regenerate with pnpm 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 /components folder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not use useCallback or useMemo unless 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 pattern use{Method}{Version}{OperationName}
Always import the -Icon-suffixed alias from @phosphor-icons/react (e.g. TrashIcon, PlusIcon, SquareIcon) — bare exports are deprecated
Do not use useCallback or useMemo unless asked to optimize a given function
Never use src/components/__legacy__/* — use design system components from src/components/

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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 use unknown

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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 with pnpm 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/(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}: No dark: 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 to page.tsx using 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/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.ts for API mocking

Files:

  • autogpt_platform/frontend/src/app/(no-navbar)/login/__tests__/preview-login-buttons.test.tsx
  • autogpt_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.tsx
  • autogpt_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.ts re-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 .ts file
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.tsx
  • autogpt_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.tsx
  • autogpt_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.tsx
  • autogpt_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.tsx
  • autogpt_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

@ntindle ntindle requested a review from 0ubbe July 7, 2026 07:57

@0ubbe 0ubbe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool ❤️ , minor nits

if (!active) return;
setIsConfigured(configured);
setIsCheckingConfig(false);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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", () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 💅🏽

@github-project-automation github-project-automation Bot moved this from 🚧 Needs work to 👍🏼 Mergeable in AutoGPT development kanban Jul 7, 2026
@ntindle

ntindle commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

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.

@ntindle ntindle closed this Jul 7, 2026
@github-project-automation github-project-automation Bot moved this to Done in Frontend Jul 7, 2026
@github-project-automation github-project-automation Bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform/frontend AutoGPT Platform - Front end size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants