Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,36 @@ Always mark React component props as `Readonly<>` (e.g., `({ children }: Readonl

## Testing Guidelines

Prefer Vitest with Testing Library for logic in `.ts` files, keeping specs colocated with the code they exercise (`utility.test.ts`). Do not write tests for `.tsx` files—React components are covered by Playwright E2E tests instead. Mock network and storage boundaries through helpers from `@formbricks/*`. Run `pnpm test` before opening a PR and `pnpm test:coverage` when touching critical flows; keep coverage from regressing. End-to-end scenarios belong in `apps/web/playwright`, using descriptive filenames (`billing.spec.ts`) and tagging slow suites with `@slow` when necessary.
Principles:

- Confidence over coverage. Test behavior and outcomes; avoid brittle implementation-detail tests.

Do:

- E2E tests (Playwright): cover critical user flows and regression risks. Extend existing specs or add
focused new ones in `apps/web/playwright`, keep tests small and well-named, use descriptive filenames
such as `billing.spec.ts`, tag slow suites with `@slow`, and run the suite before opening a PR.
- Unit tests: cover stable, high-value logic in `.ts` files, such as validators, transformers,
evaluators, calculations, and edge cases. Keep assertions on inputs and outputs, colocate specs with
the code they exercise (`utility.test.ts`), and mock network and storage boundaries through helpers
from `@formbricks/*`.
- Manual QA, especially for releases: verify on staging and file bugs. If a bug is critical, backport and
re-test.
- Run `pnpm test` before opening a PR and `pnpm test:coverage` when touching critical flows.

Do not:

- Do not write component or UI unit tests for `.tsx` files; React components are covered by Playwright E2E
tests instead.
- Do not add coverage-driven or low-signal tests.
- Do not write tests that lock implementation details, markup, snapshots, or create churn.
- Do not create mega or flaky E2E tests; avoid timing hacks and unstable dependencies.

Heuristic:

- User journey risk: E2E.
- Pure logic or edge cases: unit test.
- Release readiness: manual QA plus bug/backport loop.

## Documentation (apps/docs)

Expand Down
37 changes: 21 additions & 16 deletions apps/web/modules/survey/editor/components/survey-editor-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import {
AlertTriangleIcon,
ChevronRightIcon,
Languages,
MailIcon,
PaintbrushIcon,
Rows3Icon,
SettingsIcon,
} from "lucide-react";
import { type JSX, useMemo } from "react";
import { Fragment, type JSX, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { TSurveyEditorTabs } from "@formbricks/types/surveys/types";
import { cn } from "@/lib/cn";
Expand Down Expand Up @@ -78,22 +79,26 @@ export const SurveyEditorTabs = ({
return (
<div className="fixed z-30 flex h-12 w-full items-center justify-center border-b bg-white md:w-2/3">
<nav className="flex h-full items-center gap-x-4" aria-label="Tabs">
{tabsToDisplay.map((tab) => (
<button
type="button"
key={tab.id}
onClick={() => setActiveId(tab.id)}
className={cn(
tab.id === activeId
? "border-brand-dark font-semibold text-slate-900"
: "border-transparent text-slate-500 hover:text-slate-700",
"flex h-full items-center border-b-2 px-3 text-sm font-medium"
{tabsToDisplay.map((tab, index) => (
<Fragment key={tab.id}>
<button
type="button"
onClick={() => setActiveId(tab.id)}
className={cn(
tab.id === activeId
? "border-brand-dark font-semibold text-slate-900"
: "border-transparent text-slate-500 hover:text-slate-700",
"flex h-full items-center border-b-2 px-3 text-sm font-medium"
)}
aria-current={tab.id === activeId ? "page" : undefined}>
{tab.icon && <div className="mr-2 size-5">{tab.icon}</div>}
{tab.label}
{tab.alert && <AlertTriangleIcon className="ml-1.5 size-4 text-amber-500" />}
</button>
{index < tabsToDisplay.length - 1 && (
<ChevronRightIcon className="size-4 text-slate-300" aria-hidden="true" />
)}
aria-current={tab.id === activeId ? "page" : undefined}>
{tab.icon && <div className="mr-2 size-5">{tab.icon}</div>}
{tab.label}
{tab.alert && <AlertTriangleIcon className="ml-1.5 size-4 text-amber-500" />}
</button>
</Fragment>
))}
</nav>
</div>
Expand Down
Loading