@etus/bhono-app 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +46 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.d.ts +1 -0
- package/dist/cli.test.js +26 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/generator.d.ts +14 -0
- package/dist/generator.js +142 -0
- package/dist/generator.js.map +1 -0
- package/dist/generator.test.d.ts +1 -0
- package/dist/generator.test.js +127 -0
- package/dist/generator.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +25 -0
- package/dist/prompts.js +83 -0
- package/dist/prompts.js.map +1 -0
- package/dist/prompts.test.d.ts +1 -0
- package/dist/prompts.test.js +24 -0
- package/dist/prompts.test.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +37 -0
- package/dist/providers/cloudflare.js +61 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/cloudflare.test.d.ts +1 -0
- package/dist/providers/cloudflare.test.js +29 -0
- package/dist/providers/cloudflare.test.js.map +1 -0
- package/dist/providers/github.d.ts +16 -0
- package/dist/providers/github.js +57 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/github.test.d.ts +1 -0
- package/dist/providers/github.test.js +16 -0
- package/dist/providers/github.test.js.map +1 -0
- package/dist/templates.d.ts +8 -0
- package/dist/templates.js +88 -0
- package/dist/templates.js.map +1 -0
- package/dist/templates.test.d.ts +1 -0
- package/dist/templates.test.js +26 -0
- package/dist/templates.test.js.map +1 -0
- package/package.json +36 -0
- package/templates/base/.claude/agents/architect-review.md +160 -0
- package/templates/base/.claude/agents/backend-architect.md +308 -0
- package/templates/base/.claude/agents/code-reviewer.md +170 -0
- package/templates/base/.claude/agents/performance-engineer.md +166 -0
- package/templates/base/.claude/agents/test-automator.md +219 -0
- package/templates/base/.claude/commands/check-skill-rules.md +53 -0
- package/templates/base/.claude/commands/claude-md.md +250 -0
- package/templates/base/.claude/commands/code-prompt.md +212 -0
- package/templates/base/.claude/commands/explain-code.md +194 -0
- package/templates/base/.claude/commands/init-projec.md +89 -0
- package/templates/base/.claude/commands/linear/README.md +297 -0
- package/templates/base/.claude/commands/linear/create-issue.md +190 -0
- package/templates/base/.claude/commands/linear/implement-issue.md +248 -0
- package/templates/base/.claude/commands/linear/process-triage.md +399 -0
- package/templates/base/.claude/commands/linear/setup.md +180 -0
- package/templates/base/.claude/commands/prime.md +9 -0
- package/templates/base/.claude/commands/review-gap.md +10 -0
- package/templates/base/.claude/commands/setup-aa.md +311 -0
- package/templates/base/.claude/commands/ship.md +262 -0
- package/templates/base/.claude/commands/tools.md +3 -0
- package/templates/base/.claude/docs/claude-progress.txt +107 -0
- package/templates/base/.claude/hooks/package-lock.json +556 -0
- package/templates/base/.claude/hooks/package.json +16 -0
- package/templates/base/.claude/hooks/skill-activation-prompt.sh +7 -0
- package/templates/base/.claude/hooks/skill-activation-prompt.ts +142 -0
- package/templates/base/.claude/hooks/tsconfig.json +19 -0
- package/templates/base/.claude/scripts/check-updates.sh +85 -0
- package/templates/base/.claude/scripts/install_pkgs.sh +66 -0
- package/templates/base/.claude/scripts/setup-project.sh +177 -0
- package/templates/base/.claude/scripts/validate-skill-rules.sh +94 -0
- package/templates/base/.claude/settings.json +113 -0
- package/templates/base/.claude/settings.local.json +11 -0
- package/templates/base/.claude/skills/architecture-analyzer/SKILL.md +531 -0
- package/templates/base/.claude/skills/architecture-analyzer/assets/report-template.md +215 -0
- package/templates/base/.claude/skills/architecture-analyzer/references/c4-templates.md +234 -0
- package/templates/base/.claude/skills/architecture-analyzer/references/confidence-levels.md +203 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/analyze_structure.py +266 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/analyze_tech_debt.py +776 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/extract_apis.py +338 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/generate_c4.py +283 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/generate_erd.py +935 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/map_dependencies.py +555 -0
- package/templates/base/.claude/skills/dev-browser/SKILL.md +318 -0
- package/templates/base/.claude/skills/dev-browser/bun.lock +443 -0
- package/templates/base/.claude/skills/dev-browser/package-lock.json +2927 -0
- package/templates/base/.claude/skills/dev-browser/package.json +27 -0
- package/templates/base/.claude/skills/dev-browser/scripts/start-server.ts +117 -0
- package/templates/base/.claude/skills/dev-browser/server.sh +24 -0
- package/templates/base/.claude/skills/dev-browser/src/client.ts +403 -0
- package/templates/base/.claude/skills/dev-browser/src/index.ts +281 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/__tests__/snapshot.test.ts +223 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/browser-script.ts +877 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/index.ts +14 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/inject.ts +13 -0
- package/templates/base/.claude/skills/dev-browser/src/types.ts +27 -0
- package/templates/base/.claude/skills/dev-browser/tsconfig.json +36 -0
- package/templates/base/.claude/skills/dev-browser/vitest.config.ts +12 -0
- package/templates/base/.claude/skills/linear/SKILL.md +440 -0
- package/templates/base/.claude/skills/linear/examples.md +262 -0
- package/templates/base/.claude/skills/linear/lib/client.ts +51 -0
- package/templates/base/.claude/skills/linear/lib/config.ts +106 -0
- package/templates/base/.claude/skills/linear/lib/output.ts +34 -0
- package/templates/base/.claude/skills/linear/package-lock.json +698 -0
- package/templates/base/.claude/skills/linear/package.json +27 -0
- package/templates/base/.claude/skills/linear/reference.md +263 -0
- package/templates/base/.claude/skills/linear/scripts/comments/create.ts +47 -0
- package/templates/base/.claude/skills/linear/scripts/comments/list.ts +47 -0
- package/templates/base/.claude/skills/linear/scripts/issues/archive.ts +30 -0
- package/templates/base/.claude/skills/linear/scripts/issues/create.ts +279 -0
- package/templates/base/.claude/skills/linear/scripts/issues/get.ts +68 -0
- package/templates/base/.claude/skills/linear/scripts/issues/list.ts +67 -0
- package/templates/base/.claude/skills/linear/scripts/issues/update.ts +281 -0
- package/templates/base/.claude/skills/linear/scripts/labels/add-to-issue.ts +63 -0
- package/templates/base/.claude/skills/linear/scripts/labels/create.ts +45 -0
- package/templates/base/.claude/skills/linear/scripts/labels/list.ts +30 -0
- package/templates/base/.claude/skills/linear/scripts/list-teams.ts +52 -0
- package/templates/base/.claude/skills/linear/scripts/setup/setup-credentials.ts +96 -0
- package/templates/base/.claude/skills/linear/scripts/status/list.ts +31 -0
- package/templates/base/.claude/skills/linear/scripts/status/set-by-name.ts +78 -0
- package/templates/base/.claude/skills/linear/scripts/status/update.ts +44 -0
- package/templates/base/.claude/skills/linear/scripts/users/list.ts +59 -0
- package/templates/base/.claude/skills/linear/scripts/users/me.ts +20 -0
- package/templates/base/.claude/skills/linear/templates/README.md +203 -0
- package/templates/base/.claude/skills/linear/templates/api-reference.md +258 -0
- package/templates/base/.claude/skills/linear/templates/bug-report.md +99 -0
- package/templates/base/.claude/skills/linear/templates/feature-request.md +118 -0
- package/templates/base/.claude/skills/linear/templates/security-issue.md +162 -0
- package/templates/base/.claude/skills/linear/templates/sprint-task.md +175 -0
- package/templates/base/.claude/skills/linear/templates/tech-debt.md +137 -0
- package/templates/base/.claude/skills/linear/tsconfig.json +17 -0
- package/templates/base/.claude/skills/linear/workflows/issue-lifecycle.md +317 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/SKILL.md +113 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/assets/global-setup.template.js +97 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/assets/playwright.config.template.js +171 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/assets/test-template.spec.js +163 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/README.md +26 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/ads.email-deeplink.spec.ts +12 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/mobile.realism.spec.ts +16 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/smoke.home.spec.ts +6 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/architecture.md +578 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/best-practices.md +260 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/ci-reporting.md +86 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/debugging.md +629 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/mobile-realism.md +50 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/optimization.md +488 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/patterns.md +513 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/resources.md +44 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/visual-a11y.md +66 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/scripts/auth-setup.js +202 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/scripts/performance-analyzer.js +240 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/scripts/trace-url.js +132 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/ci/github-actions.playwright.yml +78 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/fixtures.ts +44 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/global-setup.template.js +97 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/global.setup.ts +35 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/helpers/ad-gpt-observer.ts +80 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/helpers/chromium-mobile-profile.ts +93 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/playwright.config.template.js +171 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/playwright.config.ts +126 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/test-template.spec.js +163 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/tests/email-deeplink.ads.spec.ts +44 -0
- package/templates/base/.claude/skills/skill-rules.json +184 -0
- package/templates/base/.claude/skills/wrangler/SKILL.md +209 -0
- package/templates/base/.claude/skills/wrangler/resources/api.md +494 -0
- package/templates/base/.claude/skills/wrangler/resources/bundling.md +83 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/cert.md +64 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/check.md +66 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/containers.md +157 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/d1.md +843 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/delete.md +27 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/deploy.md +139 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/deployments.md +56 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/dev.md +157 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/dispatch-namespace.md +69 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/docs.md +61 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/how-to-run.md +62 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/hyperdrive.md +425 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/init.md +31 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/kv-bulk.md +265 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/kv-key.md +353 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/kv-namespace.md +265 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/login.md +23 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/logout.md +19 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/mtls-certificate.md +69 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/pages.md +175 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/pipelines.md +76 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/queues.md +132 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/r2-bucket.md +342 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/r2-object.md +267 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/r2-sql.md +65 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/rollback.md +40 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/secret.md +308 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/secrets-store-secret.md +100 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/secrets-store-store.md +60 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/setup.md +67 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/tail.md +37 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/telemetry.md +64 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/triggers.md +39 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/types.md +73 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/vectorize.md +941 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/versions.md +95 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/whoami.md +49 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/workflows.md +117 -0
- package/templates/base/.claude/skills/wrangler/resources/commands.md +138 -0
- package/templates/base/.claude/skills/wrangler/resources/configuration.md +2176 -0
- package/templates/base/.claude/skills/wrangler/resources/custom-builds.md +55 -0
- package/templates/base/.claude/skills/wrangler/resources/deprecations.md +279 -0
- package/templates/base/.claude/skills/wrangler/resources/enviroments.md +416 -0
- package/templates/base/.claude/skills/wrangler/resources/extract_sections.py +119 -0
- package/templates/base/.claude/skills/wrangler/resources/process_content.py +94 -0
- package/templates/base/.claude/skills/wrangler/resources/system-enviroments-variables.md +120 -0
- package/templates/base/.dev.vars.example +15 -0
- package/templates/base/.env.example +29 -0
- package/templates/base/.github/workflows/test.yml +127 -0
- package/templates/base/.nycrc.json +16 -0
- package/templates/base/CLAUDE.md +218 -0
- package/templates/base/README.md +670 -0
- package/templates/base/auth-setup-error.png +0 -0
- package/templates/base/config/drizzle.config.ts +10 -0
- package/templates/base/config/eslint.config.js +364 -0
- package/templates/base/config/wrangler.json +76 -0
- package/templates/base/docs/app_spec.txt +879 -0
- package/templates/base/docs/app_spec_template.md +681 -0
- package/templates/base/docs/architecture/README.md +8 -0
- package/templates/base/docs/architecture/data-requirements.md +109 -0
- package/templates/base/docs/architecture/erd.md +91 -0
- package/templates/base/docs/features/feature_list.json +3128 -0
- package/templates/base/docs/hono-boilerplate-plan.md +1774 -0
- package/templates/base/docs/test-coverage-gap-analysis.md +242 -0
- package/templates/base/docs/testing.md +188 -0
- package/templates/base/index.html +16 -0
- package/templates/base/package.json +115 -0
- package/templates/base/playwright.config.ts +158 -0
- package/templates/base/pnpm-lock.yaml +8175 -0
- package/templates/base/scripts/capture-prod-session.ts +250 -0
- package/templates/base/scripts/generate-openapi.ts +23 -0
- package/templates/base/scripts/init.sh +121 -0
- package/templates/base/src/client/__tests__/button.test.tsx +30 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-dashboard-stats-cards-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-quick-action-cards-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-recent-activity-section-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-user-first-name-in-welcome-message-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-user-information-in-sidebar-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-render-dashboard-when-authenticated-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-show-navigation-sidebar-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-unauthenticated-should-redirect-to-login-when-not-authenticated-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-display-Google-OAuth-login-button-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-have-a-link-back-to-home-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-render-login-content-without-waiting-for-authentication-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-render-login-page-at--login-route-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-show-Terms-of-Service-and-Privacy-Policy-links-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-trigger-OAuth-flow-when-clicking-login-button-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-display-404-text-on-not-found-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-have-navigation-options-on-404-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-render-404-page-for-unknown-routes-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-account-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-integrations-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-settings-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-team-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-home-page-navigation-should-display-navigation-links-on-home-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-home-page-navigation-should-have-correct-link-destinations-on-home-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-allow-access-to-home-page-without-authentication-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-allow-access-to-login-page-without-authentication-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-dashboard-to-login-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-settings-to-login-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-team-to-login-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/authenticated-layout.test.tsx +252 -0
- package/templates/base/src/client/__tests__/routes/dashboard.test.tsx +136 -0
- package/templates/base/src/client/__tests__/routes/error-components.test.tsx +186 -0
- package/templates/base/src/client/__tests__/routes/login.test.tsx +112 -0
- package/templates/base/src/client/__tests__/routes/navigation.test.tsx +272 -0
- package/templates/base/src/client/__tests__/routes/root-layout.test.tsx +65 -0
- package/templates/base/src/client/__tests__/setup-browser.ts +15 -0
- package/templates/base/src/client/__tests__/setup.ts +32 -0
- package/templates/base/src/client/__tests__/test-utils.tsx +135 -0
- package/templates/base/src/client/api/.gitkeep +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-can-be-collapsed-by-default-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-expands-when-collapsed-and-expand-button-is-clicked-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-handles-logout-button-click-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-handles-navigation-clicks-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-hides-navigation-labels-when-collapsed-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-highlights-active-route-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-renders-sidebar-navigation-items-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-shows-keyboard-shortcut-hint-when-expanded-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-shows-user-info-when-authenticated-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-shows-user-initials-in-avatar-fallback-1.png +0 -0
- package/templates/base/src/client/components/__tests__/error-boundary.test.tsx +97 -0
- package/templates/base/src/client/components/__tests__/sidebar.test.tsx +281 -0
- package/templates/base/src/client/components/error-boundary.tsx +68 -0
- package/templates/base/src/client/components/icons.tsx +106 -0
- package/templates/base/src/client/components/layout/.gitkeep +0 -0
- package/templates/base/src/client/components/sidebar.tsx +267 -0
- package/templates/base/src/client/components/ui/.gitkeep +0 -0
- package/templates/base/src/client/components/ui/__tests__/avatar.test.tsx +308 -0
- package/templates/base/src/client/components/ui/__tests__/card.test.tsx +214 -0
- package/templates/base/src/client/components/ui/__tests__/dialog.test.tsx +297 -0
- package/templates/base/src/client/components/ui/__tests__/error-fallback.test.tsx +145 -0
- package/templates/base/src/client/components/ui/__tests__/input.test.tsx +98 -0
- package/templates/base/src/client/components/ui/__tests__/loading-skeleton.test.tsx +139 -0
- package/templates/base/src/client/components/ui/__tests__/skeleton.test.tsx +44 -0
- package/templates/base/src/client/components/ui/__tests__/sonner.test.tsx +28 -0
- package/templates/base/src/client/components/ui/__tests__/tabs.test.tsx +233 -0
- package/templates/base/src/client/components/ui/avatar.tsx +101 -0
- package/templates/base/src/client/components/ui/badge.tsx +46 -0
- package/templates/base/src/client/components/ui/button.tsx +72 -0
- package/templates/base/src/client/components/ui/card.tsx +86 -0
- package/templates/base/src/client/components/ui/dialog.tsx +140 -0
- package/templates/base/src/client/components/ui/error-fallback.tsx +179 -0
- package/templates/base/src/client/components/ui/form.tsx +172 -0
- package/templates/base/src/client/components/ui/input.tsx +24 -0
- package/templates/base/src/client/components/ui/label.tsx +22 -0
- package/templates/base/src/client/components/ui/loading-skeleton.tsx +154 -0
- package/templates/base/src/client/components/ui/separator.tsx +33 -0
- package/templates/base/src/client/components/ui/skeleton.tsx +16 -0
- package/templates/base/src/client/components/ui/sonner.tsx +29 -0
- package/templates/base/src/client/components/ui/tabs.tsx +121 -0
- package/templates/base/src/client/hooks/.gitkeep +0 -0
- package/templates/base/src/client/hooks/__tests__/use-auth.test.tsx +306 -0
- package/templates/base/src/client/hooks/__tests__/use-theme.test.tsx +172 -0
- package/templates/base/src/client/hooks/use-auth.ts +53 -0
- package/templates/base/src/client/hooks/use-theme.tsx +78 -0
- package/templates/base/src/client/index.css +881 -0
- package/templates/base/src/client/lib/query-client.ts +11 -0
- package/templates/base/src/client/lib/utils.ts +7 -0
- package/templates/base/src/client/main.tsx +26 -0
- package/templates/base/src/client/routeTree.gen.ts +258 -0
- package/templates/base/src/client/router.ts +15 -0
- package/templates/base/src/client/routes/$.tsx +77 -0
- package/templates/base/src/client/routes/.gitkeep +0 -0
- package/templates/base/src/client/routes/__root.tsx +34 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-accept-invitation-button-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-decline-button-linking-to-homepage-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-invitation-details--email--workspace--role--1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-have-a-logo-link-to-homepage-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-render-invitation-page-with-inviter-name-and-workspace-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-show-terms-of-service-and-privacy-policy-links-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/invite.test.tsx +138 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-render-Active-Sessions-section-with-session-cards-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-render-page-with-correct-title--Account--1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-API-Access-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-Connected-Accounts-section-with-Google-connected-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-Danger-Zone-section-with-delete-button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-Security-section-with-Two-Factor-Authentication-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-API-documentation-section-should-display-API-documentation-link-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-Create-Webhook-Dialog-should-have-Add-Webhook-trigger-button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-category-filters-should-display-all-category-buttons-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-display-all-integration-cards-with-names-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-display-category-badges-on-cards-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Configure-button-for-connected-integrations-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Connect-button-for-not-connected-integrations-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Connected-badge-for-connected-integrations-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-Available-Integrations-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-Webhooks-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-connected-count-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-page-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-search-input-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-render-with-correct-title--Integrations--1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-filter-integrations-based-on-search-query-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-search-by-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-show-no-results-message-when-search-has-no-matches-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-existing-webhook-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-events-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-last-delivery-info-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-success-status-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-have-Add-Webhook-button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Account-tab-should-display-connected-accounts-section-with-Google-provider-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Account-tab-should-display-sessions-and-danger-zone-sections-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-all-notification-toggle-options-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-email-notifications-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-toggle-switches-for-notification-options-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-have-toggles-checked-by-default-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display--Save-Changes--button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-personal-information-form-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-profile-picture-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-email-in-disabled-email-input-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-initials-in-avatar-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-name-in-the-name-input-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-display-all-three-tabs-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-display-page-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-render-with-correct-title--Settings--1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-show-Profile-tab-as-default-active-tab-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-switch-to-Account-tab-when-clicked-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-switch-to-Notifications-tab-when-clicked-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-display-Active-Members-section-with-member-count-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-display-Pending-Invitations-section-with-invitation-details-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-have-invite-member-button-that-can-be-clicked-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-render-page-with-correct-title-and-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-render-search-input-that-filters-team-members-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-show-current-user-with---you---indicator-and-role-badge-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/account.test.tsx +324 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/integrations.test.tsx +520 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/settings.test.tsx +414 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/team.test.tsx +374 -0
- package/templates/base/src/client/routes/_authenticated/account.tsx +416 -0
- package/templates/base/src/client/routes/_authenticated/dashboard.tsx +151 -0
- package/templates/base/src/client/routes/_authenticated/integrations.tsx +553 -0
- package/templates/base/src/client/routes/_authenticated/settings.tsx +310 -0
- package/templates/base/src/client/routes/_authenticated/team.tsx +395 -0
- package/templates/base/src/client/routes/_authenticated.tsx +69 -0
- package/templates/base/src/client/routes/index.tsx +155 -0
- package/templates/base/src/client/routes/invite.$token.tsx +191 -0
- package/templates/base/src/client/routes/login.tsx +92 -0
- package/templates/base/src/server/__tests__/fixtures.ts +461 -0
- package/templates/base/src/server/__tests__/mocks/__tests__/db.test.ts +239 -0
- package/templates/base/src/server/__tests__/mocks/__tests__/kv.test.ts +293 -0
- package/templates/base/src/server/__tests__/mocks/__tests__/r2.test.ts +363 -0
- package/templates/base/src/server/__tests__/mocks/db.ts +186 -0
- package/templates/base/src/server/__tests__/mocks/index.ts +33 -0
- package/templates/base/src/server/__tests__/mocks/kv.ts +286 -0
- package/templates/base/src/server/__tests__/mocks/r2.ts +397 -0
- package/templates/base/src/server/__tests__/setup.ts +281 -0
- package/templates/base/src/server/auth/__tests__/guards.test.ts +162 -0
- package/templates/base/src/server/auth/guards.ts +92 -0
- package/templates/base/src/server/auth/permissions.test.ts +45 -0
- package/templates/base/src/server/auth/permissions.ts +139 -0
- package/templates/base/src/server/auth/roles.test.ts +169 -0
- package/templates/base/src/server/auth/roles.ts +141 -0
- package/templates/base/src/server/db/client.ts +12 -0
- package/templates/base/src/server/db/schema/accounts.ts +20 -0
- package/templates/base/src/server/db/schema/audit-logs.ts +26 -0
- package/templates/base/src/server/db/schema/index.ts +7 -0
- package/templates/base/src/server/db/schema/invitations.ts +30 -0
- package/templates/base/src/server/db/schema/refresh-tokens.ts +22 -0
- package/templates/base/src/server/db/schema/user-accounts.ts +25 -0
- package/templates/base/src/server/db/schema/users.ts +33 -0
- package/templates/base/src/server/db/seed.ts +267 -0
- package/templates/base/src/server/env.test.ts +84 -0
- package/templates/base/src/server/env.ts +78 -0
- package/templates/base/src/server/index.ts +82 -0
- package/templates/base/src/server/lib/audit.ts +73 -0
- package/templates/base/src/server/lib/audited-db.test.ts +107 -0
- package/templates/base/src/server/lib/audited-db.ts +154 -0
- package/templates/base/src/server/lib/email.test.ts +116 -0
- package/templates/base/src/server/lib/email.ts +82 -0
- package/templates/base/src/server/lib/errors.test.ts +49 -0
- package/templates/base/src/server/lib/errors.ts +64 -0
- package/templates/base/src/server/lib/oauth.test.ts +238 -0
- package/templates/base/src/server/lib/oauth.ts +113 -0
- package/templates/base/src/server/lib/pagination.test.ts +52 -0
- package/templates/base/src/server/lib/pagination.ts +32 -0
- package/templates/base/src/server/lib/password.test.ts +151 -0
- package/templates/base/src/server/lib/password.ts +151 -0
- package/templates/base/src/server/lib/providers.test.ts +105 -0
- package/templates/base/src/server/lib/providers.ts +62 -0
- package/templates/base/src/server/lib/r2-storage.test.ts +202 -0
- package/templates/base/src/server/lib/r2-storage.ts +107 -0
- package/templates/base/src/server/lib/schema-helpers.ts +16 -0
- package/templates/base/src/server/lib/session.test.ts +758 -0
- package/templates/base/src/server/lib/session.ts +267 -0
- package/templates/base/src/server/lib/tokens.test.ts +208 -0
- package/templates/base/src/server/lib/tokens.ts +65 -0
- package/templates/base/src/server/lib/transaction.test.ts +45 -0
- package/templates/base/src/server/lib/transaction.ts +24 -0
- package/templates/base/src/server/middleware/account.test.ts +201 -0
- package/templates/base/src/server/middleware/account.ts +66 -0
- package/templates/base/src/server/middleware/auth.test.ts +345 -0
- package/templates/base/src/server/middleware/auth.ts +146 -0
- package/templates/base/src/server/middleware/cors.test.ts +88 -0
- package/templates/base/src/server/middleware/cors.ts +26 -0
- package/templates/base/src/server/middleware/error-handler.test.ts +69 -0
- package/templates/base/src/server/middleware/error-handler.ts +43 -0
- package/templates/base/src/server/middleware/index.ts +8 -0
- package/templates/base/src/server/middleware/rate-limit.test.ts +472 -0
- package/templates/base/src/server/middleware/rate-limit.ts +294 -0
- package/templates/base/src/server/middleware/request-context.test.ts +175 -0
- package/templates/base/src/server/middleware/request-context.ts +28 -0
- package/templates/base/src/server/middleware/request-logger.test.ts +92 -0
- package/templates/base/src/server/middleware/request-logger.ts +50 -0
- package/templates/base/src/server/routes/accounts/__tests__/handlers.test.ts +460 -0
- package/templates/base/src/server/routes/accounts/handlers.ts +179 -0
- package/templates/base/src/server/routes/accounts/index.ts +55 -0
- package/templates/base/src/server/routes/accounts/routes.ts +205 -0
- package/templates/base/src/server/routes/accounts/schemas.ts +31 -0
- package/templates/base/src/server/routes/api.ts +37 -0
- package/templates/base/src/server/routes/audits/__tests__/handlers.test.ts +349 -0
- package/templates/base/src/server/routes/audits/handlers.ts +37 -0
- package/templates/base/src/server/routes/audits/index.ts +14 -0
- package/templates/base/src/server/routes/audits/routes.ts +29 -0
- package/templates/base/src/server/routes/audits/schemas.ts +43 -0
- package/templates/base/src/server/routes/auth/__tests__/handlers.test.ts +381 -0
- package/templates/base/src/server/routes/auth/handlers.ts +222 -0
- package/templates/base/src/server/routes/auth/index.ts +37 -0
- package/templates/base/src/server/routes/auth/routes.ts +136 -0
- package/templates/base/src/server/routes/auth/schemas.ts +48 -0
- package/templates/base/src/server/routes/auth/test-login.ts +156 -0
- package/templates/base/src/server/routes/health/__tests__/handlers.test.ts +237 -0
- package/templates/base/src/server/routes/health/handlers.ts +83 -0
- package/templates/base/src/server/routes/health/index.ts +13 -0
- package/templates/base/src/server/routes/health/routes.ts +90 -0
- package/templates/base/src/server/routes/index.ts +53 -0
- package/templates/base/src/server/routes/invitations/__tests__/handlers.test.ts +473 -0
- package/templates/base/src/server/routes/invitations/handlers.ts +71 -0
- package/templates/base/src/server/routes/invitations/index.ts +25 -0
- package/templates/base/src/server/routes/invitations/routes.ts +69 -0
- package/templates/base/src/server/routes/invitations/schemas.ts +39 -0
- package/templates/base/src/server/routes/openapi.ts +14 -0
- package/templates/base/src/server/routes/schemas.ts +53 -0
- package/templates/base/src/server/routes/storage/__tests__/handlers.test.ts +408 -0
- package/templates/base/src/server/routes/storage/handlers.ts +100 -0
- package/templates/base/src/server/routes/storage/index.ts +42 -0
- package/templates/base/src/server/routes/storage/routes.ts +91 -0
- package/templates/base/src/server/routes/storage/schemas.ts +56 -0
- package/templates/base/src/server/routes/users/__tests__/handlers.test.ts +526 -0
- package/templates/base/src/server/routes/users/handlers.ts +228 -0
- package/templates/base/src/server/routes/users/index.ts +67 -0
- package/templates/base/src/server/routes/users/routes.ts +265 -0
- package/templates/base/src/server/routes/users/schemas.ts +67 -0
- package/templates/base/src/server/services/__tests__/accounts.test.ts +764 -0
- package/templates/base/src/server/services/__tests__/audits.test.ts +235 -0
- package/templates/base/src/server/services/__tests__/auth.test.ts +765 -0
- package/templates/base/src/server/services/__tests__/invitations.test.ts +704 -0
- package/templates/base/src/server/services/__tests__/users.test.ts +755 -0
- package/templates/base/src/server/services/accounts.ts +269 -0
- package/templates/base/src/server/services/audits.ts +82 -0
- package/templates/base/src/server/services/auth.ts +225 -0
- package/templates/base/src/server/services/index.ts +6 -0
- package/templates/base/src/server/services/invitations.ts +306 -0
- package/templates/base/src/server/services/users.ts +350 -0
- package/templates/base/src/server/types/auth.ts +36 -0
- package/templates/base/src/server/types/index.ts +117 -0
- package/templates/base/src/shared/schemas/.gitkeep +0 -0
- package/templates/base/src/shared/schemas/__tests__/schemas.test.ts +547 -0
- package/templates/base/src/shared/schemas/account.ts +15 -0
- package/templates/base/src/shared/schemas/index.ts +6 -0
- package/templates/base/src/shared/schemas/invitation.ts +9 -0
- package/templates/base/src/shared/schemas/profile.ts +10 -0
- package/templates/base/src/shared/schemas/user.ts +16 -0
- package/templates/base/src/shared/schemas/webhook.ts +12 -0
- package/templates/base/src/shared/types/.gitkeep +0 -0
- package/templates/base/src/shared/types/account.ts +12 -0
- package/templates/base/src/shared/types/api.ts +1399 -0
- package/templates/base/src/shared/types/auth.ts +24 -0
- package/templates/base/src/shared/types/index.ts +5 -0
- package/templates/base/src/shared/types/user.ts +31 -0
- package/templates/base/src/test/vitest-zod-matcher.ts +37 -0
- package/templates/base/src/test/vitest.d.ts +19 -0
- package/templates/base/tests/e2e/README.md +141 -0
- package/templates/base/tests/e2e/a11y/accessibility.spec.ts +925 -0
- package/templates/base/tests/e2e/a11y/keyboard-navigation.spec.ts +610 -0
- package/templates/base/tests/e2e/api/accounts.spec.ts +148 -0
- package/templates/base/tests/e2e/api/audit-logs.spec.ts +130 -0
- package/templates/base/tests/e2e/api/authenticated-api.spec.ts +311 -0
- package/templates/base/tests/e2e/api/storage.spec.ts +109 -0
- package/templates/base/tests/e2e/auth-flows.unauth.spec.ts +117 -0
- package/templates/base/tests/e2e/auth-logout.unauth.spec.ts +103 -0
- package/templates/base/tests/e2e/auth.setup.ts +115 -0
- package/templates/base/tests/e2e/auth.spec.ts +146 -0
- package/templates/base/tests/e2e/compatibility/cross-browser.spec.ts +152 -0
- package/templates/base/tests/e2e/compatibility/cross-browser.spec.ts-snapshots/login-chromium-chromium-darwin.png +0 -0
- package/templates/base/tests/e2e/crud/account.spec.ts +356 -0
- package/templates/base/tests/e2e/crud/integrations.spec.ts +419 -0
- package/templates/base/tests/e2e/crud/team.spec.ts +287 -0
- package/templates/base/tests/e2e/crud/users.spec.ts +239 -0
- package/templates/base/tests/e2e/errors/error-boundary.spec.ts +428 -0
- package/templates/base/tests/e2e/errors/error-handling.spec.ts +47 -0
- package/templates/base/tests/e2e/errors/error-handling.unauth.spec.ts +205 -0
- package/templates/base/tests/e2e/fixtures.ts +266 -0
- package/templates/base/tests/e2e/forms/validation.spec.ts +569 -0
- package/templates/base/tests/e2e/invitations/invite-flow.unauth.spec.ts +204 -0
- package/templates/base/tests/e2e/journeys/account-lifecycle.spec.ts +314 -0
- package/templates/base/tests/e2e/journeys/audit-investigation.spec.ts +299 -0
- package/templates/base/tests/e2e/journeys/auth-onboarding.spec.ts +232 -0
- package/templates/base/tests/e2e/journeys/critical-flows.spec.ts +281 -0
- package/templates/base/tests/e2e/journeys/error-recovery.spec.ts +354 -0
- package/templates/base/tests/e2e/journeys/file-management.spec.ts +307 -0
- package/templates/base/tests/e2e/journeys/integrations.spec.ts +372 -0
- package/templates/base/tests/e2e/journeys/multi-account.spec.ts +317 -0
- package/templates/base/tests/e2e/journeys/rbac-enforcement.spec.ts +389 -0
- package/templates/base/tests/e2e/journeys/settings-profile.spec.ts +400 -0
- package/templates/base/tests/e2e/journeys/team-collaboration.spec.ts +410 -0
- package/templates/base/tests/e2e/mobile/responsive.spec.ts +178 -0
- package/templates/base/tests/e2e/navigation/routing.spec.ts +371 -0
- package/templates/base/tests/e2e/navigation/sidebar.spec.ts +425 -0
- package/templates/base/tests/e2e/pages/ui-features.spec.ts +393 -0
- package/templates/base/tests/e2e/performance/baselines.spec.ts +162 -0
- package/templates/base/tests/e2e/performance/benchmarks.spec.ts +371 -0
- package/templates/base/tests/e2e/smoke.unauth.spec.ts +196 -0
- package/templates/base/tests/e2e/visual/components.spec.ts +650 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/confirmation-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dark-mode-background-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dark-mode-card-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dark-mode-sidebar-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dashboard-card-single-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dialog-content-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dialog-with-backdrop-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/empty-search-results-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/input-default-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/input-focus-ring-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/primary-button-focus-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/primary-button-hover-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/primary-button-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/sidebar-active-nav-item-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/sidebar-collapsed-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/sidebar-navigation-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts +192 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/account-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/create-webhook-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/dashboard-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/delete-account-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/integrations-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/invite-member-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/login-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/settings-account-tab-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/settings-profile-tab-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/sidebar-navigation-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/team-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts +230 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/404-page-chromium-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/404-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/account-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/login-page-chromium-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/login-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/settings-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/team-invite-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/team-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/webhook-create-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/theme-colors.spec.ts +293 -0
- package/templates/base/tests/e2e/visual/ui-components.spec.ts +502 -0
- package/templates/base/tests/integration/accounts/crud.test.ts +1402 -0
- package/templates/base/tests/integration/audits/list.test.ts +1133 -0
- package/templates/base/tests/integration/auth/auth-service.test.ts +415 -0
- package/templates/base/tests/integration/auth/invitation-token.test.ts +529 -0
- package/templates/base/tests/integration/auth/logout.test.ts +524 -0
- package/templates/base/tests/integration/auth/oauth.test.ts +768 -0
- package/templates/base/tests/integration/auth/refresh-token.test.ts +364 -0
- package/templates/base/tests/integration/auth/session-expiry.test.ts +569 -0
- package/templates/base/tests/integration/auth/session.test.ts +520 -0
- package/templates/base/tests/integration/auth/super-admin.test.ts +451 -0
- package/templates/base/tests/integration/authorization/analytics-role.test.ts +1026 -0
- package/templates/base/tests/integration/authorization/billing-role.test.ts +776 -0
- package/templates/base/tests/integration/authorization/guards-roles.test.ts +539 -0
- package/templates/base/tests/integration/authorization/multi-tenancy.test.ts +1112 -0
- package/templates/base/tests/integration/authorization/role-hierarchy.test.ts +931 -0
- package/templates/base/tests/integration/authorization/roles.test.ts +1347 -0
- package/templates/base/tests/integration/config/production-behavior.test.ts +536 -0
- package/templates/base/tests/integration/db/constraints.test.ts +695 -0
- package/templates/base/tests/integration/fixtures/accounts.ts +136 -0
- package/templates/base/tests/integration/fixtures/index.ts +232 -0
- package/templates/base/tests/integration/fixtures/invitations.ts +195 -0
- package/templates/base/tests/integration/fixtures/users.ts +144 -0
- package/templates/base/tests/integration/health/health.test.ts +351 -0
- package/templates/base/tests/integration/invitations/crud.test.ts +1457 -0
- package/templates/base/tests/integration/invitations/email.test.ts +506 -0
- package/templates/base/tests/integration/lib/email.test.ts +174 -0
- package/templates/base/tests/integration/lib/oauth.test.ts +368 -0
- package/templates/base/tests/integration/lib/password.test.ts +192 -0
- package/templates/base/tests/integration/lib/schema-helpers.test.ts +129 -0
- package/templates/base/tests/integration/lib/tokens.test.ts +304 -0
- package/templates/base/tests/integration/middleware/auth.test.ts +499 -0
- package/templates/base/tests/integration/middleware/cors.test.ts +334 -0
- package/templates/base/tests/integration/middleware/request-context.test.ts +156 -0
- package/templates/base/tests/integration/middleware/request-logger.test.ts +313 -0
- package/templates/base/tests/integration/performance/response-times.test.ts +509 -0
- package/templates/base/tests/integration/security/cookie-security.test.ts +567 -0
- package/templates/base/tests/integration/security/csrf-protection.test.ts +542 -0
- package/templates/base/tests/integration/security/jwt-validation.test.ts +209 -0
- package/templates/base/tests/integration/security/log-sanitization.test.ts +658 -0
- package/templates/base/tests/integration/security/rate-limiting.test.ts +1251 -0
- package/templates/base/tests/integration/security/sql-injection.test.ts +663 -0
- package/templates/base/tests/integration/security/token-hashing.test.ts +371 -0
- package/templates/base/tests/integration/security/xss-prevention.test.ts +541 -0
- package/templates/base/tests/integration/setup.ts +834 -0
- package/templates/base/tests/integration/smoke.test.ts +288 -0
- package/templates/base/tests/integration/storage/upload.test.ts +1162 -0
- package/templates/base/tests/integration/storage/validation.test.ts +746 -0
- package/templates/base/tests/integration/users/crud.test.ts +1297 -0
- package/templates/base/tests/integration/users/list.test.ts +698 -0
- package/templates/base/tests/integration/vitest.config.ts +80 -0
- package/templates/base/tsconfig.app.json +18 -0
- package/templates/base/tsconfig.json +39 -0
- package/templates/base/tsconfig.node.json +16 -0
- package/templates/base/tsconfig.server.json +26 -0
- package/templates/base/tsconfig.tsbuildinfo +1 -0
- package/templates/base/vite.config.ts +46 -0
- package/templates/base/vitest.config.browser.ts +47 -0
- package/templates/base/vitest.config.frontend.ts +47 -0
- package/templates/base/vitest.config.ts +82 -0
- package/templates/base/vitest.workspace.ts +22 -0
- package/templates/modules/audit-logs/.gitkeep +0 -0
- package/templates/modules/billing/.gitkeep +0 -0
- package/templates/modules/invitations/.gitkeep +0 -0
- package/templates/modules/storage/.gitkeep +0 -0
- package/templates/modules/webhooks/.gitkeep +0 -0
- package/templates/providers/auth-email/.gitkeep +0 -0
- package/templates/providers/auth-github/.gitkeep +0 -0
- package/templates/providers/auth-google/.gitkeep +0 -0
- package/templates/providers/email-resend/.gitkeep +0 -0
- package/templates/providers/email-sendgrid/.gitkeep +0 -0
|
@@ -0,0 +1,3128 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"category": "functional",
|
|
4
|
+
"description": "Google OAuth login initiates redirect to Google authorization page",
|
|
5
|
+
"steps": [
|
|
6
|
+
"Step 1: Navigate to /auth/login",
|
|
7
|
+
"Step 2: Verify redirect to Google OAuth authorization URL",
|
|
8
|
+
"Step 3: Verify state parameter is included for CSRF protection",
|
|
9
|
+
"Step 4: Verify PKCE code_challenge parameter is present"
|
|
10
|
+
],
|
|
11
|
+
"passes": false
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"category": "functional",
|
|
15
|
+
"description": "OAuth callback creates user session and redirects to dashboard",
|
|
16
|
+
"steps": [
|
|
17
|
+
"Step 1: Complete Google OAuth authorization",
|
|
18
|
+
"Step 2: Redirect to /auth/callback with code and state",
|
|
19
|
+
"Step 3: Verify user session is created in KV store",
|
|
20
|
+
"Step 4: Verify session_id cookie is set with httpOnly flag",
|
|
21
|
+
"Step 5: Verify redirect to /dashboard"
|
|
22
|
+
],
|
|
23
|
+
"passes": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"category": "functional",
|
|
27
|
+
"description": "OAuth callback creates new user if first-time login",
|
|
28
|
+
"steps": [
|
|
29
|
+
"Step 1: Complete Google OAuth with new Google account",
|
|
30
|
+
"Step 2: Redirect to /auth/callback",
|
|
31
|
+
"Step 3: Verify new user record created in database",
|
|
32
|
+
"Step 4: Verify user's googleId is stored",
|
|
33
|
+
"Step 5: Verify email and name from OAuth provider are saved",
|
|
34
|
+
"Step 6: Verify SIGNUP audit event is logged",
|
|
35
|
+
"Step 7: Verify redirect to dashboard"
|
|
36
|
+
],
|
|
37
|
+
"passes": false
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"category": "functional",
|
|
41
|
+
"description": "OAuth callback links existing user if email matches",
|
|
42
|
+
"steps": [
|
|
43
|
+
"Step 1: Ensure user with matching email exists in database",
|
|
44
|
+
"Step 2: Complete Google OAuth with that email",
|
|
45
|
+
"Step 3: Verify user record is updated with googleId",
|
|
46
|
+
"Step 4: Verify LOGIN audit event is logged",
|
|
47
|
+
"Step 5: Verify session is created for existing user"
|
|
48
|
+
],
|
|
49
|
+
"passes": false
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"category": "functional",
|
|
53
|
+
"description": "Super admin pre-registration grants isSuperAdmin flag on first login",
|
|
54
|
+
"steps": [
|
|
55
|
+
"Step 1: Configure SUPER_ADMIN_EMAILS environment variable",
|
|
56
|
+
"Step 2: Complete OAuth login with pre-registered email",
|
|
57
|
+
"Step 3: Verify user is created with isSuperAdmin=true",
|
|
58
|
+
"Step 4: Verify user can access super admin only endpoints"
|
|
59
|
+
],
|
|
60
|
+
"passes": false
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"category": "functional",
|
|
64
|
+
"description": "Logout destroys session and clears cookies",
|
|
65
|
+
"steps": [
|
|
66
|
+
"Step 1: Log in and verify session exists",
|
|
67
|
+
"Step 2: Send POST request to /auth/logout",
|
|
68
|
+
"Step 3: Verify session is deleted from KV store",
|
|
69
|
+
"Step 4: Verify session_id cookie is cleared",
|
|
70
|
+
"Step 5: Verify LOGOUT audit event is logged",
|
|
71
|
+
"Step 6: Verify subsequent requests are unauthenticated"
|
|
72
|
+
],
|
|
73
|
+
"passes": false
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"category": "functional",
|
|
77
|
+
"description": "Logout redirects to login page",
|
|
78
|
+
"steps": [
|
|
79
|
+
"Step 1: Log in as authenticated user",
|
|
80
|
+
"Step 2: Click logout button",
|
|
81
|
+
"Step 3: Verify redirect to /login page"
|
|
82
|
+
],
|
|
83
|
+
"passes": false
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"category": "functional",
|
|
87
|
+
"description": "/auth/me returns current user information",
|
|
88
|
+
"steps": [
|
|
89
|
+
"Step 1: Log in as authenticated user",
|
|
90
|
+
"Step 2: Send GET request to /auth/me",
|
|
91
|
+
"Step 3: Verify response contains user id, email, name, avatarUrl",
|
|
92
|
+
"Step 4: Verify response contains isSuperAdmin flag"
|
|
93
|
+
],
|
|
94
|
+
"passes": false
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"category": "functional",
|
|
98
|
+
"description": "/auth/me returns 401 for unauthenticated requests",
|
|
99
|
+
"steps": [
|
|
100
|
+
"Step 1: Clear all session cookies",
|
|
101
|
+
"Step 2: Send GET request to /auth/me without session",
|
|
102
|
+
"Step 3: Verify 401 Unauthorized response"
|
|
103
|
+
],
|
|
104
|
+
"passes": false
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"category": "functional",
|
|
108
|
+
"description": "Session expiration requires re-authentication",
|
|
109
|
+
"steps": [
|
|
110
|
+
"Step 1: Log in and note session creation time",
|
|
111
|
+
"Step 2: Wait for session to expire (or manually expire in KV)",
|
|
112
|
+
"Step 3: Attempt to access protected endpoint",
|
|
113
|
+
"Step 4: Verify 401 response",
|
|
114
|
+
"Step 5: Verify redirect to login page"
|
|
115
|
+
],
|
|
116
|
+
"passes": false
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"category": "functional",
|
|
120
|
+
"description": "Invitation token is stored in cookie during OAuth flow",
|
|
121
|
+
"steps": [
|
|
122
|
+
"Step 1: Navigate to /auth/invite/:token with valid token",
|
|
123
|
+
"Step 2: Verify invitation token is stored in cookie",
|
|
124
|
+
"Step 3: Verify redirect to /auth/login",
|
|
125
|
+
"Step 4: Complete OAuth login",
|
|
126
|
+
"Step 5: Verify user is automatically added to invited account"
|
|
127
|
+
],
|
|
128
|
+
"passes": false
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"category": "functional",
|
|
132
|
+
"description": "Invalid invitation token shows error message",
|
|
133
|
+
"steps": [
|
|
134
|
+
"Step 1: Navigate to /auth/invite/:token with invalid token",
|
|
135
|
+
"Step 2: Verify error message is displayed",
|
|
136
|
+
"Step 3: Verify user is not added to any account"
|
|
137
|
+
],
|
|
138
|
+
"passes": false
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"category": "functional",
|
|
142
|
+
"description": "Expired invitation token shows expiration error",
|
|
143
|
+
"steps": [
|
|
144
|
+
"Step 1: Create invitation with expired date",
|
|
145
|
+
"Step 2: Navigate to /auth/invite/:token",
|
|
146
|
+
"Step 3: Verify expiration error message",
|
|
147
|
+
"Step 4: Verify user is not added to account"
|
|
148
|
+
],
|
|
149
|
+
"passes": false
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"category": "functional",
|
|
153
|
+
"description": "List users returns paginated results",
|
|
154
|
+
"steps": [
|
|
155
|
+
"Step 1: Log in as authenticated user",
|
|
156
|
+
"Step 2: Send GET /api/users?page=1&limit=10",
|
|
157
|
+
"Step 3: Verify response contains data array",
|
|
158
|
+
"Step 4: Verify meta contains total, page, pages, hasMore",
|
|
159
|
+
"Step 5: Verify at most 10 users returned"
|
|
160
|
+
],
|
|
161
|
+
"passes": false
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"category": "functional",
|
|
165
|
+
"description": "List users supports search by email",
|
|
166
|
+
"steps": [
|
|
167
|
+
"Step 1: Log in as authenticated user",
|
|
168
|
+
"Step 2: Send GET /api/users?query=test@example.com",
|
|
169
|
+
"Step 3: Verify only matching users returned",
|
|
170
|
+
"Step 4: Verify partial email matches work"
|
|
171
|
+
],
|
|
172
|
+
"passes": false
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"category": "functional",
|
|
176
|
+
"description": "List users supports search by name",
|
|
177
|
+
"steps": [
|
|
178
|
+
"Step 1: Log in as authenticated user",
|
|
179
|
+
"Step 2: Send GET /api/users?query=John",
|
|
180
|
+
"Step 3: Verify users with matching names returned",
|
|
181
|
+
"Step 4: Verify case-insensitive search"
|
|
182
|
+
],
|
|
183
|
+
"passes": false
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"category": "functional",
|
|
187
|
+
"description": "Get user by ID returns user details",
|
|
188
|
+
"steps": [
|
|
189
|
+
"Step 1: Log in as authenticated user",
|
|
190
|
+
"Step 2: Send GET /api/users/:id with valid user ID",
|
|
191
|
+
"Step 3: Verify response contains complete user object",
|
|
192
|
+
"Step 4: Verify all user fields are present"
|
|
193
|
+
],
|
|
194
|
+
"passes": false
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"category": "functional",
|
|
198
|
+
"description": "Get user by ID returns 404 for non-existent user",
|
|
199
|
+
"steps": [
|
|
200
|
+
"Step 1: Log in as authenticated user",
|
|
201
|
+
"Step 2: Send GET /api/users/:id with non-existent UUID",
|
|
202
|
+
"Step 3: Verify 404 Not Found response"
|
|
203
|
+
],
|
|
204
|
+
"passes": false
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"category": "functional",
|
|
208
|
+
"description": "Update user requires ADMIN role",
|
|
209
|
+
"steps": [
|
|
210
|
+
"Step 1: Log in as user with VIEWER role",
|
|
211
|
+
"Step 2: Attempt PATCH /api/users/:id with new name",
|
|
212
|
+
"Step 3: Verify 403 Forbidden response",
|
|
213
|
+
"Step 4: Log in as user with ADMIN role",
|
|
214
|
+
"Step 5: Attempt same PATCH request",
|
|
215
|
+
"Step 6: Verify 200 success response"
|
|
216
|
+
],
|
|
217
|
+
"passes": false
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"category": "functional",
|
|
221
|
+
"description": "Update user changes name successfully",
|
|
222
|
+
"steps": [
|
|
223
|
+
"Step 1: Log in as ADMIN user",
|
|
224
|
+
"Step 2: Send PATCH /api/users/:id with { name: 'New Name' }",
|
|
225
|
+
"Step 3: Verify user name is updated in response",
|
|
226
|
+
"Step 4: Verify UPDATE audit event is logged",
|
|
227
|
+
"Step 5: Verify GET /api/users/:id returns updated name"
|
|
228
|
+
],
|
|
229
|
+
"passes": false
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"category": "functional",
|
|
233
|
+
"description": "Update user changes status to inactive",
|
|
234
|
+
"steps": [
|
|
235
|
+
"Step 1: Log in as ADMIN user",
|
|
236
|
+
"Step 2: Send PATCH /api/users/:id with { status: 'inactive' }",
|
|
237
|
+
"Step 3: Verify user status is updated",
|
|
238
|
+
"Step 4: Verify audit event logged with status change"
|
|
239
|
+
],
|
|
240
|
+
"passes": false
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"category": "functional",
|
|
244
|
+
"description": "Delete user performs soft delete",
|
|
245
|
+
"steps": [
|
|
246
|
+
"Step 1: Log in as ADMIN user",
|
|
247
|
+
"Step 2: Send DELETE /api/users/:id",
|
|
248
|
+
"Step 3: Verify 204 No Content response",
|
|
249
|
+
"Step 4: Verify user has deletedAt timestamp set",
|
|
250
|
+
"Step 5: Verify DELETE audit event is logged",
|
|
251
|
+
"Step 6: Verify user no longer appears in list"
|
|
252
|
+
],
|
|
253
|
+
"passes": false
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"category": "functional",
|
|
257
|
+
"description": "Delete user requires ADMIN role",
|
|
258
|
+
"steps": [
|
|
259
|
+
"Step 1: Log in as VIEWER user",
|
|
260
|
+
"Step 2: Attempt DELETE /api/users/:id",
|
|
261
|
+
"Step 3: Verify 403 Forbidden response"
|
|
262
|
+
],
|
|
263
|
+
"passes": false
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"category": "functional",
|
|
267
|
+
"description": "Restore user requires Super Admin",
|
|
268
|
+
"steps": [
|
|
269
|
+
"Step 1: Soft delete a user",
|
|
270
|
+
"Step 2: Log in as regular ADMIN (not super)",
|
|
271
|
+
"Step 3: Attempt POST /api/users/:id/restore",
|
|
272
|
+
"Step 4: Verify 403 Forbidden response",
|
|
273
|
+
"Step 5: Log in as Super Admin",
|
|
274
|
+
"Step 6: Attempt POST /api/users/:id/restore",
|
|
275
|
+
"Step 7: Verify user is restored (deletedAt = null)"
|
|
276
|
+
],
|
|
277
|
+
"passes": false
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"category": "functional",
|
|
281
|
+
"description": "Bulk assign users to accounts",
|
|
282
|
+
"steps": [
|
|
283
|
+
"Step 1: Log in as MANAGER user",
|
|
284
|
+
"Step 2: Prepare list of user-account-role assignments",
|
|
285
|
+
"Step 3: Send POST /api/users/accounts with items array",
|
|
286
|
+
"Step 4: Verify response contains count of assignments",
|
|
287
|
+
"Step 5: Verify user_accounts records created",
|
|
288
|
+
"Step 6: Verify users can access their new accounts"
|
|
289
|
+
],
|
|
290
|
+
"passes": false
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"category": "functional",
|
|
294
|
+
"description": "Bulk remove users from accounts",
|
|
295
|
+
"steps": [
|
|
296
|
+
"Step 1: Log in as MANAGER user",
|
|
297
|
+
"Step 2: Prepare list of user-account removals",
|
|
298
|
+
"Step 3: Send DELETE /api/users/accounts with items array",
|
|
299
|
+
"Step 4: Verify response contains count of removals",
|
|
300
|
+
"Step 5: Verify user_accounts records deleted",
|
|
301
|
+
"Step 6: Verify users can no longer access removed accounts"
|
|
302
|
+
],
|
|
303
|
+
"passes": false
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"category": "functional",
|
|
307
|
+
"description": "List accounts returns user's accounts",
|
|
308
|
+
"steps": [
|
|
309
|
+
"Step 1: Log in as authenticated user",
|
|
310
|
+
"Step 2: Send GET /api/accounts",
|
|
311
|
+
"Step 3: Verify only accounts user belongs to are returned",
|
|
312
|
+
"Step 4: Verify pagination meta is present"
|
|
313
|
+
],
|
|
314
|
+
"passes": false
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"category": "functional",
|
|
318
|
+
"description": "Get account by ID returns account details",
|
|
319
|
+
"steps": [
|
|
320
|
+
"Step 1: Log in as account member",
|
|
321
|
+
"Step 2: Send GET /api/accounts/:id",
|
|
322
|
+
"Step 3: Verify account details returned",
|
|
323
|
+
"Step 4: Verify all account fields present"
|
|
324
|
+
],
|
|
325
|
+
"passes": false
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"category": "functional",
|
|
329
|
+
"description": "Get account returns 403 for non-member",
|
|
330
|
+
"steps": [
|
|
331
|
+
"Step 1: Log in as user not in target account",
|
|
332
|
+
"Step 2: Send GET /api/accounts/:id for that account",
|
|
333
|
+
"Step 3: Verify 403 Forbidden response"
|
|
334
|
+
],
|
|
335
|
+
"passes": false
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"category": "functional",
|
|
339
|
+
"description": "Create account requires Super Admin",
|
|
340
|
+
"steps": [
|
|
341
|
+
"Step 1: Log in as regular user",
|
|
342
|
+
"Step 2: Attempt POST /api/accounts with { name: 'New Account' }",
|
|
343
|
+
"Step 3: Verify 403 Forbidden response",
|
|
344
|
+
"Step 4: Log in as Super Admin",
|
|
345
|
+
"Step 5: Attempt same POST request",
|
|
346
|
+
"Step 6: Verify 201 Created response"
|
|
347
|
+
],
|
|
348
|
+
"passes": false
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"category": "functional",
|
|
352
|
+
"description": "Create account validates required fields",
|
|
353
|
+
"steps": [
|
|
354
|
+
"Step 1: Log in as Super Admin",
|
|
355
|
+
"Step 2: Send POST /api/accounts with empty body",
|
|
356
|
+
"Step 3: Verify validation error for missing name",
|
|
357
|
+
"Step 4: Send POST /api/accounts with { name: '' }",
|
|
358
|
+
"Step 5: Verify validation error for empty name"
|
|
359
|
+
],
|
|
360
|
+
"passes": false
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"category": "functional",
|
|
364
|
+
"description": "Update account requires Account ADMIN role",
|
|
365
|
+
"steps": [
|
|
366
|
+
"Step 1: Log in as account VIEWER",
|
|
367
|
+
"Step 2: Attempt PATCH /api/accounts/:id",
|
|
368
|
+
"Step 3: Verify 403 Forbidden",
|
|
369
|
+
"Step 4: Log in as account ADMIN",
|
|
370
|
+
"Step 5: Attempt PATCH /api/accounts/:id with { name: 'Updated' }",
|
|
371
|
+
"Step 6: Verify 200 success"
|
|
372
|
+
],
|
|
373
|
+
"passes": false
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"category": "functional",
|
|
377
|
+
"description": "Delete account requires Super Admin",
|
|
378
|
+
"steps": [
|
|
379
|
+
"Step 1: Log in as account ADMIN (not super)",
|
|
380
|
+
"Step 2: Attempt DELETE /api/accounts/:id",
|
|
381
|
+
"Step 3: Verify 403 Forbidden",
|
|
382
|
+
"Step 4: Log in as Super Admin",
|
|
383
|
+
"Step 5: Attempt DELETE /api/accounts/:id",
|
|
384
|
+
"Step 6: Verify 204 No Content",
|
|
385
|
+
"Step 7: Verify soft delete with deletedAt set"
|
|
386
|
+
],
|
|
387
|
+
"passes": false
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"category": "functional",
|
|
391
|
+
"description": "Restore account requires Super Admin",
|
|
392
|
+
"steps": [
|
|
393
|
+
"Step 1: Soft delete an account",
|
|
394
|
+
"Step 2: Log in as regular ADMIN",
|
|
395
|
+
"Step 3: Attempt POST /api/accounts/:id/restore",
|
|
396
|
+
"Step 4: Verify 403 Forbidden",
|
|
397
|
+
"Step 5: Log in as Super Admin",
|
|
398
|
+
"Step 6: Attempt POST /api/accounts/:id/restore",
|
|
399
|
+
"Step 7: Verify account restored"
|
|
400
|
+
],
|
|
401
|
+
"passes": false
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"category": "functional",
|
|
405
|
+
"description": "Create invitation sends email to new user",
|
|
406
|
+
"steps": [
|
|
407
|
+
"Step 1: Log in as account member",
|
|
408
|
+
"Step 2: Send POST /api/invitations with { email: 'new@example.com', role: 'VIEWER' }",
|
|
409
|
+
"Step 3: Verify 201 Created response",
|
|
410
|
+
"Step 4: Verify invitation record created in database",
|
|
411
|
+
"Step 5: Verify invitation token generated (64 chars)",
|
|
412
|
+
"Step 6: Verify email sent via SendGrid",
|
|
413
|
+
"Step 7: Verify expiration set to 7 days",
|
|
414
|
+
"Step 8: Verify INSERT audit event logged"
|
|
415
|
+
],
|
|
416
|
+
"passes": false
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
"category": "functional",
|
|
420
|
+
"description": "Create invitation links existing user immediately",
|
|
421
|
+
"steps": [
|
|
422
|
+
"Step 1: Ensure target user exists in system",
|
|
423
|
+
"Step 2: Log in as account member",
|
|
424
|
+
"Step 3: Send POST /api/invitations for existing user's email",
|
|
425
|
+
"Step 4: Verify response { linked: true }",
|
|
426
|
+
"Step 5: Verify user_accounts record created",
|
|
427
|
+
"Step 6: Verify no email sent"
|
|
428
|
+
],
|
|
429
|
+
"passes": false
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"category": "functional",
|
|
433
|
+
"description": "Create invitation prevents duplicate invitations",
|
|
434
|
+
"steps": [
|
|
435
|
+
"Step 1: Send invitation to email@example.com",
|
|
436
|
+
"Step 2: Attempt to send another invitation to same email for same account",
|
|
437
|
+
"Step 3: Verify error response about existing invitation"
|
|
438
|
+
],
|
|
439
|
+
"passes": false
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"category": "functional",
|
|
443
|
+
"description": "List invitations returns pending invitations for account",
|
|
444
|
+
"steps": [
|
|
445
|
+
"Step 1: Create multiple invitations for account",
|
|
446
|
+
"Step 2: Log in as account member",
|
|
447
|
+
"Step 3: Send GET /api/invitations",
|
|
448
|
+
"Step 4: Verify all pending invitations returned",
|
|
449
|
+
"Step 5: Verify accepted invitations not included"
|
|
450
|
+
],
|
|
451
|
+
"passes": false
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"category": "functional",
|
|
455
|
+
"description": "Delete invitation revokes pending invitation",
|
|
456
|
+
"steps": [
|
|
457
|
+
"Step 1: Create an invitation",
|
|
458
|
+
"Step 2: Log in as MANAGER user",
|
|
459
|
+
"Step 3: Send DELETE /api/invitations/:id",
|
|
460
|
+
"Step 4: Verify 204 No Content",
|
|
461
|
+
"Step 5: Verify invitation deleted from database",
|
|
462
|
+
"Step 6: Verify DELETE audit event logged",
|
|
463
|
+
"Step 7: Verify token no longer works for acceptance"
|
|
464
|
+
],
|
|
465
|
+
"passes": false
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"category": "functional",
|
|
469
|
+
"description": "Delete invitation requires MANAGER role",
|
|
470
|
+
"steps": [
|
|
471
|
+
"Step 1: Create an invitation",
|
|
472
|
+
"Step 2: Log in as VIEWER user",
|
|
473
|
+
"Step 3: Attempt DELETE /api/invitations/:id",
|
|
474
|
+
"Step 4: Verify 403 Forbidden"
|
|
475
|
+
],
|
|
476
|
+
"passes": false
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"category": "functional",
|
|
480
|
+
"description": "Query audit logs returns paginated results",
|
|
481
|
+
"steps": [
|
|
482
|
+
"Step 1: Generate some audit events (login, create, update)",
|
|
483
|
+
"Step 2: Log in as ADMIN user",
|
|
484
|
+
"Step 3: Send GET /api/audits?page=1&limit=10",
|
|
485
|
+
"Step 4: Verify data array with audit logs",
|
|
486
|
+
"Step 5: Verify pagination meta"
|
|
487
|
+
],
|
|
488
|
+
"passes": false
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"category": "functional",
|
|
492
|
+
"description": "Query audit logs filters by entity type",
|
|
493
|
+
"steps": [
|
|
494
|
+
"Step 1: Generate events for different entities",
|
|
495
|
+
"Step 2: Log in as ADMIN user",
|
|
496
|
+
"Step 3: Send GET /api/audits?entity=User",
|
|
497
|
+
"Step 4: Verify only User entity logs returned"
|
|
498
|
+
],
|
|
499
|
+
"passes": false
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
"category": "functional",
|
|
503
|
+
"description": "Query audit logs filters by action type",
|
|
504
|
+
"steps": [
|
|
505
|
+
"Step 1: Generate INSERT, UPDATE, DELETE events",
|
|
506
|
+
"Step 2: Log in as ADMIN user",
|
|
507
|
+
"Step 3: Send GET /api/audits?action=INSERT",
|
|
508
|
+
"Step 4: Verify only INSERT actions returned"
|
|
509
|
+
],
|
|
510
|
+
"passes": false
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"category": "functional",
|
|
514
|
+
"description": "Query audit logs filters by entity ID",
|
|
515
|
+
"steps": [
|
|
516
|
+
"Step 1: Generate events for specific entity",
|
|
517
|
+
"Step 2: Log in as ADMIN user",
|
|
518
|
+
"Step 3: Send GET /api/audits?entityId=<uuid>",
|
|
519
|
+
"Step 4: Verify only logs for that entity returned"
|
|
520
|
+
],
|
|
521
|
+
"passes": false
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
"category": "functional",
|
|
525
|
+
"description": "Audit logs require ADMIN or ANALYTICS role",
|
|
526
|
+
"steps": [
|
|
527
|
+
"Step 1: Log in as VIEWER user",
|
|
528
|
+
"Step 2: Attempt GET /api/audits",
|
|
529
|
+
"Step 3: Verify 403 Forbidden",
|
|
530
|
+
"Step 4: Log in as ANALYTICS user",
|
|
531
|
+
"Step 5: Attempt GET /api/audits",
|
|
532
|
+
"Step 6: Verify 200 success"
|
|
533
|
+
],
|
|
534
|
+
"passes": false
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
"category": "functional",
|
|
538
|
+
"description": "Super admin sees audit logs for all accounts",
|
|
539
|
+
"steps": [
|
|
540
|
+
"Step 1: Create events in multiple accounts",
|
|
541
|
+
"Step 2: Log in as Super Admin",
|
|
542
|
+
"Step 3: Send GET /api/audits",
|
|
543
|
+
"Step 4: Verify logs from all accounts visible"
|
|
544
|
+
],
|
|
545
|
+
"passes": false
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"category": "functional",
|
|
549
|
+
"description": "Regular admin sees only own account's audit logs",
|
|
550
|
+
"steps": [
|
|
551
|
+
"Step 1: Create events in multiple accounts",
|
|
552
|
+
"Step 2: Log in as regular ADMIN",
|
|
553
|
+
"Step 3: Send GET /api/audits",
|
|
554
|
+
"Step 4: Verify only current account's logs visible"
|
|
555
|
+
],
|
|
556
|
+
"passes": false
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
"category": "functional",
|
|
560
|
+
"description": "Generate presigned upload URL for R2",
|
|
561
|
+
"steps": [
|
|
562
|
+
"Step 1: Log in as authenticated user",
|
|
563
|
+
"Step 2: Send POST /api/storage/upload-url with { filename: 'test.jpg', contentType: 'image/jpeg' }",
|
|
564
|
+
"Step 3: Verify response contains uploadUrl",
|
|
565
|
+
"Step 4: Verify response contains key",
|
|
566
|
+
"Step 5: Verify response contains publicUrl"
|
|
567
|
+
],
|
|
568
|
+
"passes": false
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"category": "functional",
|
|
572
|
+
"description": "Upload file directly to R2",
|
|
573
|
+
"steps": [
|
|
574
|
+
"Step 1: Log in as authenticated user",
|
|
575
|
+
"Step 2: Generate upload URL for file",
|
|
576
|
+
"Step 3: Send PUT /api/storage/upload/:key with file data",
|
|
577
|
+
"Step 4: Verify 200 response with key, url, size",
|
|
578
|
+
"Step 5: Verify file accessible at publicUrl"
|
|
579
|
+
],
|
|
580
|
+
"passes": false
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
"category": "functional",
|
|
584
|
+
"description": "Delete file from R2",
|
|
585
|
+
"steps": [
|
|
586
|
+
"Step 1: Upload a file to R2",
|
|
587
|
+
"Step 2: Log in as authenticated user",
|
|
588
|
+
"Step 3: Send DELETE /api/storage/:key",
|
|
589
|
+
"Step 4: Verify 204 No Content",
|
|
590
|
+
"Step 5: Verify file no longer accessible"
|
|
591
|
+
],
|
|
592
|
+
"passes": false
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
"category": "functional",
|
|
596
|
+
"description": "Storage endpoints require authentication",
|
|
597
|
+
"steps": [
|
|
598
|
+
"Step 1: Clear session cookies",
|
|
599
|
+
"Step 2: Attempt POST /api/storage/upload-url",
|
|
600
|
+
"Step 3: Verify 401 Unauthorized"
|
|
601
|
+
],
|
|
602
|
+
"passes": false
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"category": "functional",
|
|
606
|
+
"description": "Health check returns status ok",
|
|
607
|
+
"steps": [
|
|
608
|
+
"Step 1: Send GET /health",
|
|
609
|
+
"Step 2: Verify 200 response",
|
|
610
|
+
"Step 3: Verify response contains { status: 'ok' }",
|
|
611
|
+
"Step 4: Verify timestamp is present",
|
|
612
|
+
"Step 5: Verify environment field present"
|
|
613
|
+
],
|
|
614
|
+
"passes": false
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"category": "functional",
|
|
618
|
+
"description": "OpenAPI documentation is accessible",
|
|
619
|
+
"steps": [
|
|
620
|
+
"Step 1: Send GET /api/doc",
|
|
621
|
+
"Step 2: Verify JSON response with OpenAPI schema",
|
|
622
|
+
"Step 3: Verify paths are documented",
|
|
623
|
+
"Step 4: Verify schemas are defined"
|
|
624
|
+
],
|
|
625
|
+
"passes": false
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"category": "functional",
|
|
629
|
+
"description": "Swagger UI is accessible",
|
|
630
|
+
"steps": [
|
|
631
|
+
"Step 1: Navigate to /api/swagger",
|
|
632
|
+
"Step 2: Verify Swagger UI loads",
|
|
633
|
+
"Step 3: Verify endpoints are listed",
|
|
634
|
+
"Step 4: Verify Try It Out functionality works"
|
|
635
|
+
],
|
|
636
|
+
"passes": false
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"category": "functional",
|
|
640
|
+
"description": "Request context includes transactionId for tracing",
|
|
641
|
+
"steps": [
|
|
642
|
+
"Step 1: Make an API request",
|
|
643
|
+
"Step 2: Check response headers for transaction ID",
|
|
644
|
+
"Step 3: Verify audit logs contain matching transactionId",
|
|
645
|
+
"Step 4: Verify related operations share same transactionId"
|
|
646
|
+
],
|
|
647
|
+
"passes": false
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
"category": "functional",
|
|
651
|
+
"description": "Account middleware extracts accountId from query parameter",
|
|
652
|
+
"steps": [
|
|
653
|
+
"Step 1: Log in as user with multiple accounts",
|
|
654
|
+
"Step 2: Send request with ?accountId=<uuid>",
|
|
655
|
+
"Step 3: Verify request is scoped to that account",
|
|
656
|
+
"Step 4: Verify response data from correct account"
|
|
657
|
+
],
|
|
658
|
+
"passes": false
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
"category": "functional",
|
|
662
|
+
"description": "Account middleware extracts accountId from header",
|
|
663
|
+
"steps": [
|
|
664
|
+
"Step 1: Log in as user with multiple accounts",
|
|
665
|
+
"Step 2: Send request with X-Account-Id header",
|
|
666
|
+
"Step 3: Verify request is scoped to that account"
|
|
667
|
+
],
|
|
668
|
+
"passes": false
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
"category": "functional",
|
|
672
|
+
"description": "Role hierarchy enforces permission levels",
|
|
673
|
+
"steps": [
|
|
674
|
+
"Step 1: Verify ADMIN > MANAGER > EDITOR > AUTHOR > VIEWER",
|
|
675
|
+
"Step 2: Test VIEWER cannot perform EDITOR actions",
|
|
676
|
+
"Step 3: Test EDITOR cannot perform MANAGER actions",
|
|
677
|
+
"Step 4: Test MANAGER cannot perform ADMIN actions",
|
|
678
|
+
"Step 5: Verify BILLING is non-hierarchical",
|
|
679
|
+
"Step 6: Verify ANALYTICS is non-hierarchical"
|
|
680
|
+
],
|
|
681
|
+
"passes": false
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
"category": "functional",
|
|
685
|
+
"description": "VIEWER role has read-only access",
|
|
686
|
+
"steps": [
|
|
687
|
+
"Step 1: Log in as VIEWER user",
|
|
688
|
+
"Step 2: Verify GET requests succeed (list, get)",
|
|
689
|
+
"Step 3: Verify POST requests fail (create)",
|
|
690
|
+
"Step 4: Verify PATCH requests fail (update)",
|
|
691
|
+
"Step 5: Verify DELETE requests fail"
|
|
692
|
+
],
|
|
693
|
+
"passes": false
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
"category": "functional",
|
|
697
|
+
"description": "EDITOR role can create and modify content",
|
|
698
|
+
"steps": [
|
|
699
|
+
"Step 1: Log in as EDITOR user",
|
|
700
|
+
"Step 2: Verify can create resources",
|
|
701
|
+
"Step 3: Verify can update resources",
|
|
702
|
+
"Step 4: Verify cannot manage users",
|
|
703
|
+
"Step 5: Verify cannot delete accounts"
|
|
704
|
+
],
|
|
705
|
+
"passes": false
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
"category": "functional",
|
|
709
|
+
"description": "MANAGER role can manage team members",
|
|
710
|
+
"steps": [
|
|
711
|
+
"Step 1: Log in as MANAGER user",
|
|
712
|
+
"Step 2: Verify can create invitations",
|
|
713
|
+
"Step 3: Verify can revoke invitations",
|
|
714
|
+
"Step 4: Verify can assign users to accounts",
|
|
715
|
+
"Step 5: Verify cannot delete accounts"
|
|
716
|
+
],
|
|
717
|
+
"passes": false
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
"category": "functional",
|
|
721
|
+
"description": "ADMIN role has full account management",
|
|
722
|
+
"steps": [
|
|
723
|
+
"Step 1: Log in as ADMIN user",
|
|
724
|
+
"Step 2: Verify can update account settings",
|
|
725
|
+
"Step 3: Verify can manage all users in account",
|
|
726
|
+
"Step 4: Verify can view audit logs",
|
|
727
|
+
"Step 5: Verify cannot create new accounts (super admin only)"
|
|
728
|
+
],
|
|
729
|
+
"passes": false
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
"category": "functional",
|
|
733
|
+
"description": "BILLING role can access financial operations",
|
|
734
|
+
"steps": [
|
|
735
|
+
"Step 1: Log in as BILLING user",
|
|
736
|
+
"Step 2: Verify access to billing endpoints",
|
|
737
|
+
"Step 3: Verify cannot manage users",
|
|
738
|
+
"Step 4: Verify cannot modify account settings"
|
|
739
|
+
],
|
|
740
|
+
"passes": false
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
"category": "functional",
|
|
744
|
+
"description": "ANALYTICS role can access reporting",
|
|
745
|
+
"steps": [
|
|
746
|
+
"Step 1: Log in as ANALYTICS user",
|
|
747
|
+
"Step 2: Verify can access audit logs",
|
|
748
|
+
"Step 3: Verify can access analytics endpoints",
|
|
749
|
+
"Step 4: Verify cannot modify data"
|
|
750
|
+
],
|
|
751
|
+
"passes": false
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
"category": "functional",
|
|
755
|
+
"description": "Landing page loads for unauthenticated users",
|
|
756
|
+
"steps": [
|
|
757
|
+
"Step 1: Clear all cookies",
|
|
758
|
+
"Step 2: Navigate to /",
|
|
759
|
+
"Step 3: Verify landing page displays",
|
|
760
|
+
"Step 4: Verify hero section visible",
|
|
761
|
+
"Step 5: Verify features section visible",
|
|
762
|
+
"Step 6: Verify CTA buttons work"
|
|
763
|
+
],
|
|
764
|
+
"passes": false
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
"category": "functional",
|
|
768
|
+
"description": "Login page displays Google OAuth button",
|
|
769
|
+
"steps": [
|
|
770
|
+
"Step 1: Navigate to /login",
|
|
771
|
+
"Step 2: Verify login card displays",
|
|
772
|
+
"Step 3: Verify Google sign-in button visible",
|
|
773
|
+
"Step 4: Click Google button",
|
|
774
|
+
"Step 5: Verify redirect to /auth/login"
|
|
775
|
+
],
|
|
776
|
+
"passes": false
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
"category": "functional",
|
|
780
|
+
"description": "Login page redirects authenticated users to dashboard",
|
|
781
|
+
"steps": [
|
|
782
|
+
"Step 1: Log in successfully",
|
|
783
|
+
"Step 2: Navigate to /login",
|
|
784
|
+
"Step 3: Verify automatic redirect to /dashboard"
|
|
785
|
+
],
|
|
786
|
+
"passes": false
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
"category": "functional",
|
|
790
|
+
"description": "Invitation page validates token and shows invitation details",
|
|
791
|
+
"steps": [
|
|
792
|
+
"Step 1: Create invitation for account",
|
|
793
|
+
"Step 2: Navigate to /invite/:token",
|
|
794
|
+
"Step 3: Verify invitation details displayed",
|
|
795
|
+
"Step 4: Verify account name shown",
|
|
796
|
+
"Step 5: Verify role shown",
|
|
797
|
+
"Step 6: Verify accept button visible"
|
|
798
|
+
],
|
|
799
|
+
"passes": false
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
"category": "functional",
|
|
803
|
+
"description": "Dashboard displays welcome message with user's name",
|
|
804
|
+
"steps": [
|
|
805
|
+
"Step 1: Log in as 'John Doe'",
|
|
806
|
+
"Step 2: Navigate to /dashboard",
|
|
807
|
+
"Step 3: Verify 'Welcome, John' or similar message displays"
|
|
808
|
+
],
|
|
809
|
+
"passes": false
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
"category": "functional",
|
|
813
|
+
"description": "Dashboard displays stats cards",
|
|
814
|
+
"steps": [
|
|
815
|
+
"Step 1: Log in as authenticated user",
|
|
816
|
+
"Step 2: Navigate to /dashboard",
|
|
817
|
+
"Step 3: Verify users count card visible",
|
|
818
|
+
"Step 4: Verify accounts count card visible",
|
|
819
|
+
"Step 5: Verify API requests card visible",
|
|
820
|
+
"Step 6: Verify uptime card visible"
|
|
821
|
+
],
|
|
822
|
+
"passes": false
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
"category": "functional",
|
|
826
|
+
"description": "Dashboard displays quick action cards",
|
|
827
|
+
"steps": [
|
|
828
|
+
"Step 1: Navigate to /dashboard",
|
|
829
|
+
"Step 2: Verify 'Invite Team' quick action visible",
|
|
830
|
+
"Step 3: Verify 'Database' quick action visible",
|
|
831
|
+
"Step 4: Verify 'Security' quick action visible",
|
|
832
|
+
"Step 5: Verify clicking action navigates correctly"
|
|
833
|
+
],
|
|
834
|
+
"passes": false
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
"category": "functional",
|
|
838
|
+
"description": "Team management page lists active members",
|
|
839
|
+
"steps": [
|
|
840
|
+
"Step 1: Add multiple users to account",
|
|
841
|
+
"Step 2: Navigate to /team",
|
|
842
|
+
"Step 3: Verify all active members listed",
|
|
843
|
+
"Step 4: Verify name, email, role displayed for each",
|
|
844
|
+
"Step 5: Verify avatar displayed for each"
|
|
845
|
+
],
|
|
846
|
+
"passes": false
|
|
847
|
+
},
|
|
848
|
+
{
|
|
849
|
+
"category": "functional",
|
|
850
|
+
"description": "Team management page supports search/filter",
|
|
851
|
+
"steps": [
|
|
852
|
+
"Step 1: Add multiple team members",
|
|
853
|
+
"Step 2: Navigate to /team",
|
|
854
|
+
"Step 3: Enter search query in search box",
|
|
855
|
+
"Step 4: Verify list filters by name/email",
|
|
856
|
+
"Step 5: Clear search and verify full list returns"
|
|
857
|
+
],
|
|
858
|
+
"passes": false
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
"category": "functional",
|
|
862
|
+
"description": "Team management invite member dialog opens",
|
|
863
|
+
"steps": [
|
|
864
|
+
"Step 1: Navigate to /team",
|
|
865
|
+
"Step 2: Click 'Invite Member' button",
|
|
866
|
+
"Step 3: Verify dialog opens",
|
|
867
|
+
"Step 4: Verify email input field present",
|
|
868
|
+
"Step 5: Verify role selector present",
|
|
869
|
+
"Step 6: Verify send button present"
|
|
870
|
+
],
|
|
871
|
+
"passes": false
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
"category": "functional",
|
|
875
|
+
"description": "Team management creates invitation from dialog",
|
|
876
|
+
"steps": [
|
|
877
|
+
"Step 1: Open invite dialog on /team",
|
|
878
|
+
"Step 2: Enter email address",
|
|
879
|
+
"Step 3: Select role from dropdown",
|
|
880
|
+
"Step 4: Click send button",
|
|
881
|
+
"Step 5: Verify success toast displayed",
|
|
882
|
+
"Step 6: Verify dialog closes",
|
|
883
|
+
"Step 7: Verify invitation appears in pending list"
|
|
884
|
+
],
|
|
885
|
+
"passes": false
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
"category": "functional",
|
|
889
|
+
"description": "Team management shows pending invitations with expiry",
|
|
890
|
+
"steps": [
|
|
891
|
+
"Step 1: Create several invitations",
|
|
892
|
+
"Step 2: Navigate to /team",
|
|
893
|
+
"Step 3: Scroll to pending invitations section",
|
|
894
|
+
"Step 4: Verify each invitation shows email",
|
|
895
|
+
"Step 5: Verify each shows expiry countdown",
|
|
896
|
+
"Step 6: Verify resend button visible",
|
|
897
|
+
"Step 7: Verify revoke button visible"
|
|
898
|
+
],
|
|
899
|
+
"passes": false
|
|
900
|
+
},
|
|
901
|
+
{
|
|
902
|
+
"category": "functional",
|
|
903
|
+
"description": "Team management can revoke pending invitation",
|
|
904
|
+
"steps": [
|
|
905
|
+
"Step 1: Create an invitation",
|
|
906
|
+
"Step 2: Navigate to /team",
|
|
907
|
+
"Step 3: Click revoke button on invitation",
|
|
908
|
+
"Step 4: Confirm in dialog if prompted",
|
|
909
|
+
"Step 5: Verify success toast",
|
|
910
|
+
"Step 6: Verify invitation removed from list"
|
|
911
|
+
],
|
|
912
|
+
"passes": false
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
"category": "functional",
|
|
916
|
+
"description": "Settings page displays user profile",
|
|
917
|
+
"steps": [
|
|
918
|
+
"Step 1: Navigate to /settings",
|
|
919
|
+
"Step 2: Verify profile card displays avatar",
|
|
920
|
+
"Step 3: Verify name displayed",
|
|
921
|
+
"Step 4: Verify email displayed"
|
|
922
|
+
],
|
|
923
|
+
"passes": false
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"category": "functional",
|
|
927
|
+
"description": "Settings page allows profile editing",
|
|
928
|
+
"steps": [
|
|
929
|
+
"Step 1: Navigate to /settings",
|
|
930
|
+
"Step 2: Click edit profile button",
|
|
931
|
+
"Step 3: Modify name in form",
|
|
932
|
+
"Step 4: Submit form",
|
|
933
|
+
"Step 5: Verify success toast",
|
|
934
|
+
"Step 6: Verify name updated in display"
|
|
935
|
+
],
|
|
936
|
+
"passes": false
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
"category": "functional",
|
|
940
|
+
"description": "Settings page shows connected accounts",
|
|
941
|
+
"steps": [
|
|
942
|
+
"Step 1: Navigate to /settings",
|
|
943
|
+
"Step 2: Scroll to connected accounts section",
|
|
944
|
+
"Step 3: Verify Google account connection shown",
|
|
945
|
+
"Step 4: Verify connection status indicator"
|
|
946
|
+
],
|
|
947
|
+
"passes": false
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
"category": "functional",
|
|
951
|
+
"description": "Settings page shows notification preferences",
|
|
952
|
+
"steps": [
|
|
953
|
+
"Step 1: Navigate to /settings",
|
|
954
|
+
"Step 2: Find notification preferences section",
|
|
955
|
+
"Step 3: Verify toggle switches present",
|
|
956
|
+
"Step 4: Toggle a preference",
|
|
957
|
+
"Step 5: Verify preference persists on reload"
|
|
958
|
+
],
|
|
959
|
+
"passes": false
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
"category": "functional",
|
|
963
|
+
"description": "Account security page shows active sessions",
|
|
964
|
+
"steps": [
|
|
965
|
+
"Step 1: Navigate to /account",
|
|
966
|
+
"Step 2: Find active sessions section",
|
|
967
|
+
"Step 3: Verify current session listed",
|
|
968
|
+
"Step 4: Verify device/browser info shown",
|
|
969
|
+
"Step 5: Verify location info if available"
|
|
970
|
+
],
|
|
971
|
+
"passes": false
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
"category": "functional",
|
|
975
|
+
"description": "Account security page shows danger zone",
|
|
976
|
+
"steps": [
|
|
977
|
+
"Step 1: Navigate to /account",
|
|
978
|
+
"Step 2: Scroll to danger zone section",
|
|
979
|
+
"Step 3: Verify export data option visible",
|
|
980
|
+
"Step 4: Verify delete account option visible",
|
|
981
|
+
"Step 5: Verify actions require confirmation"
|
|
982
|
+
],
|
|
983
|
+
"passes": false
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
"category": "functional",
|
|
987
|
+
"description": "Account deletion requires confirmation",
|
|
988
|
+
"steps": [
|
|
989
|
+
"Step 1: Navigate to /account",
|
|
990
|
+
"Step 2: Click delete account button",
|
|
991
|
+
"Step 3: Verify confirmation dialog opens",
|
|
992
|
+
"Step 4: Verify warning message displayed",
|
|
993
|
+
"Step 5: Verify must type confirmation text",
|
|
994
|
+
"Step 6: Cancel and verify dialog closes"
|
|
995
|
+
],
|
|
996
|
+
"passes": false
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
"category": "functional",
|
|
1000
|
+
"description": "Integrations page displays integration grid",
|
|
1001
|
+
"steps": [
|
|
1002
|
+
"Step 1: Navigate to /integrations",
|
|
1003
|
+
"Step 2: Verify integration grid displays",
|
|
1004
|
+
"Step 3: Verify Slack integration card",
|
|
1005
|
+
"Step 4: Verify Discord integration card",
|
|
1006
|
+
"Step 5: Verify Stripe integration card",
|
|
1007
|
+
"Step 6: Verify GitHub integration card"
|
|
1008
|
+
],
|
|
1009
|
+
"passes": false
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
"category": "functional",
|
|
1013
|
+
"description": "Integrations page supports category filtering",
|
|
1014
|
+
"steps": [
|
|
1015
|
+
"Step 1: Navigate to /integrations",
|
|
1016
|
+
"Step 2: Find category filter",
|
|
1017
|
+
"Step 3: Select a category",
|
|
1018
|
+
"Step 4: Verify grid filters to show only that category"
|
|
1019
|
+
],
|
|
1020
|
+
"passes": false
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
"category": "functional",
|
|
1024
|
+
"description": "Integrations page supports search",
|
|
1025
|
+
"steps": [
|
|
1026
|
+
"Step 1: Navigate to /integrations",
|
|
1027
|
+
"Step 2: Enter search term (e.g., 'slack')",
|
|
1028
|
+
"Step 3: Verify only matching integrations shown"
|
|
1029
|
+
],
|
|
1030
|
+
"passes": false
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
"category": "functional",
|
|
1034
|
+
"description": "Integrations page webhook configuration section",
|
|
1035
|
+
"steps": [
|
|
1036
|
+
"Step 1: Navigate to /integrations",
|
|
1037
|
+
"Step 2: Find webhooks section",
|
|
1038
|
+
"Step 3: Click create webhook button",
|
|
1039
|
+
"Step 4: Verify dialog opens with URL field",
|
|
1040
|
+
"Step 5: Verify event selection available"
|
|
1041
|
+
],
|
|
1042
|
+
"passes": false
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
"category": "functional",
|
|
1046
|
+
"description": "Sidebar navigation works correctly",
|
|
1047
|
+
"steps": [
|
|
1048
|
+
"Step 1: Log in and view sidebar",
|
|
1049
|
+
"Step 2: Click Dashboard link",
|
|
1050
|
+
"Step 3: Verify navigation to /dashboard",
|
|
1051
|
+
"Step 4: Click Team link",
|
|
1052
|
+
"Step 5: Verify navigation to /team",
|
|
1053
|
+
"Step 6: Repeat for Settings, Account, Integrations"
|
|
1054
|
+
],
|
|
1055
|
+
"passes": false
|
|
1056
|
+
},
|
|
1057
|
+
{
|
|
1058
|
+
"category": "functional",
|
|
1059
|
+
"description": "Sidebar shows user profile card",
|
|
1060
|
+
"steps": [
|
|
1061
|
+
"Step 1: Log in as authenticated user",
|
|
1062
|
+
"Step 2: View sidebar",
|
|
1063
|
+
"Step 3: Verify avatar displayed",
|
|
1064
|
+
"Step 4: Verify user name displayed",
|
|
1065
|
+
"Step 5: Verify logout button accessible"
|
|
1066
|
+
],
|
|
1067
|
+
"passes": false
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
"category": "functional",
|
|
1071
|
+
"description": "Sidebar logout button logs user out",
|
|
1072
|
+
"steps": [
|
|
1073
|
+
"Step 1: Log in and view sidebar",
|
|
1074
|
+
"Step 2: Click logout button",
|
|
1075
|
+
"Step 3: Verify session destroyed",
|
|
1076
|
+
"Step 4: Verify redirect to login page"
|
|
1077
|
+
],
|
|
1078
|
+
"passes": false
|
|
1079
|
+
},
|
|
1080
|
+
{
|
|
1081
|
+
"category": "functional",
|
|
1082
|
+
"description": "Protected routes redirect unauthenticated users to login",
|
|
1083
|
+
"steps": [
|
|
1084
|
+
"Step 1: Clear session cookies",
|
|
1085
|
+
"Step 2: Navigate to /dashboard",
|
|
1086
|
+
"Step 3: Verify redirect to /login",
|
|
1087
|
+
"Step 4: Navigate to /team",
|
|
1088
|
+
"Step 5: Verify redirect to /login"
|
|
1089
|
+
],
|
|
1090
|
+
"passes": false
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
"category": "functional",
|
|
1094
|
+
"description": "Form validation shows inline error messages",
|
|
1095
|
+
"steps": [
|
|
1096
|
+
"Step 1: Navigate to form (e.g., invite dialog)",
|
|
1097
|
+
"Step 2: Submit with empty required fields",
|
|
1098
|
+
"Step 3: Verify inline error messages appear",
|
|
1099
|
+
"Step 4: Verify specific field validation messages"
|
|
1100
|
+
],
|
|
1101
|
+
"passes": false
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
"category": "functional",
|
|
1105
|
+
"description": "Form submission shows loading state",
|
|
1106
|
+
"steps": [
|
|
1107
|
+
"Step 1: Fill out a form",
|
|
1108
|
+
"Step 2: Click submit button",
|
|
1109
|
+
"Step 3: Verify button shows loading indicator",
|
|
1110
|
+
"Step 4: Verify button is disabled during submission"
|
|
1111
|
+
],
|
|
1112
|
+
"passes": false
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
"category": "functional",
|
|
1116
|
+
"description": "Toast notifications appear for success actions",
|
|
1117
|
+
"steps": [
|
|
1118
|
+
"Step 1: Perform successful action (e.g., save settings)",
|
|
1119
|
+
"Step 2: Verify success toast appears",
|
|
1120
|
+
"Step 3: Verify toast has green styling",
|
|
1121
|
+
"Step 4: Verify toast auto-dismisses"
|
|
1122
|
+
],
|
|
1123
|
+
"passes": false
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
"category": "functional",
|
|
1127
|
+
"description": "Toast notifications appear for error actions",
|
|
1128
|
+
"steps": [
|
|
1129
|
+
"Step 1: Trigger an error (e.g., invalid form submission)",
|
|
1130
|
+
"Step 2: Verify error toast appears",
|
|
1131
|
+
"Step 3: Verify toast has red styling",
|
|
1132
|
+
"Step 4: Verify error message is descriptive"
|
|
1133
|
+
],
|
|
1134
|
+
"passes": false
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
"category": "functional",
|
|
1138
|
+
"description": "Error boundary catches and displays runtime errors",
|
|
1139
|
+
"steps": [
|
|
1140
|
+
"Step 1: Trigger a runtime error in component",
|
|
1141
|
+
"Step 2: Verify error boundary catches error",
|
|
1142
|
+
"Step 3: Verify error message displayed",
|
|
1143
|
+
"Step 4: Verify retry button available",
|
|
1144
|
+
"Step 5: Verify go home button available"
|
|
1145
|
+
],
|
|
1146
|
+
"passes": false
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
"category": "functional",
|
|
1150
|
+
"description": "404 page displays for unknown routes",
|
|
1151
|
+
"steps": [
|
|
1152
|
+
"Step 1: Navigate to /nonexistent-page",
|
|
1153
|
+
"Step 2: Verify 404 page displays",
|
|
1154
|
+
"Step 3: Verify helpful message shown",
|
|
1155
|
+
"Step 4: Verify link to home page"
|
|
1156
|
+
],
|
|
1157
|
+
"passes": false
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
"category": "functional",
|
|
1161
|
+
"description": "API returns proper 404 for unknown endpoints",
|
|
1162
|
+
"steps": [
|
|
1163
|
+
"Step 1: Send GET /api/unknown-endpoint",
|
|
1164
|
+
"Step 2: Verify 404 response status",
|
|
1165
|
+
"Step 3: Verify error message in response body"
|
|
1166
|
+
],
|
|
1167
|
+
"passes": false
|
|
1168
|
+
},
|
|
1169
|
+
{
|
|
1170
|
+
"category": "functional",
|
|
1171
|
+
"description": "API returns proper 401 for unauthenticated requests",
|
|
1172
|
+
"steps": [
|
|
1173
|
+
"Step 1: Clear all auth cookies/headers",
|
|
1174
|
+
"Step 2: Send GET to protected endpoint",
|
|
1175
|
+
"Step 3: Verify 401 Unauthorized response",
|
|
1176
|
+
"Step 4: Verify no sensitive data leaked"
|
|
1177
|
+
],
|
|
1178
|
+
"passes": false
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
"category": "functional",
|
|
1182
|
+
"description": "API returns proper 403 for unauthorized actions",
|
|
1183
|
+
"steps": [
|
|
1184
|
+
"Step 1: Log in as VIEWER user",
|
|
1185
|
+
"Step 2: Attempt admin-only action",
|
|
1186
|
+
"Step 3: Verify 403 Forbidden response",
|
|
1187
|
+
"Step 4: Verify meaningful error message"
|
|
1188
|
+
],
|
|
1189
|
+
"passes": false
|
|
1190
|
+
},
|
|
1191
|
+
{
|
|
1192
|
+
"category": "functional",
|
|
1193
|
+
"description": "API validation returns 400 for invalid input",
|
|
1194
|
+
"steps": [
|
|
1195
|
+
"Step 1: Send POST with invalid JSON",
|
|
1196
|
+
"Step 2: Verify 400 Bad Request response",
|
|
1197
|
+
"Step 3: Verify validation errors listed",
|
|
1198
|
+
"Step 4: Verify field-specific error messages"
|
|
1199
|
+
],
|
|
1200
|
+
"passes": false
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
"category": "functional",
|
|
1204
|
+
"description": "API handles malformed UUIDs gracefully",
|
|
1205
|
+
"steps": [
|
|
1206
|
+
"Step 1: Send GET /api/users/not-a-uuid",
|
|
1207
|
+
"Step 2: Verify proper error response",
|
|
1208
|
+
"Step 3: Verify no stack trace in production"
|
|
1209
|
+
],
|
|
1210
|
+
"passes": false
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
"category": "functional",
|
|
1214
|
+
"description": "CORS allows requests from configured origins",
|
|
1215
|
+
"steps": [
|
|
1216
|
+
"Step 1: Configure CORS_ORIGINS in env",
|
|
1217
|
+
"Step 2: Make request from allowed origin",
|
|
1218
|
+
"Step 3: Verify request succeeds",
|
|
1219
|
+
"Step 4: Verify proper CORS headers in response"
|
|
1220
|
+
],
|
|
1221
|
+
"passes": false
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
"category": "functional",
|
|
1225
|
+
"description": "CORS blocks requests from unknown origins",
|
|
1226
|
+
"steps": [
|
|
1227
|
+
"Step 1: Make request from unlisted origin",
|
|
1228
|
+
"Step 2: Verify CORS headers reject request",
|
|
1229
|
+
"Step 3: Verify no data returned"
|
|
1230
|
+
],
|
|
1231
|
+
"passes": false
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
"category": "functional",
|
|
1235
|
+
"description": "Session cookie has httpOnly flag",
|
|
1236
|
+
"steps": [
|
|
1237
|
+
"Step 1: Log in successfully",
|
|
1238
|
+
"Step 2: Inspect session_id cookie",
|
|
1239
|
+
"Step 3: Verify httpOnly flag is set",
|
|
1240
|
+
"Step 4: Verify cookie not accessible via JavaScript"
|
|
1241
|
+
],
|
|
1242
|
+
"passes": false
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
"category": "functional",
|
|
1246
|
+
"description": "Session cookie has secure flag in production",
|
|
1247
|
+
"steps": [
|
|
1248
|
+
"Step 1: Deploy to production",
|
|
1249
|
+
"Step 2: Log in successfully",
|
|
1250
|
+
"Step 3: Inspect session_id cookie",
|
|
1251
|
+
"Step 4: Verify secure flag is set"
|
|
1252
|
+
],
|
|
1253
|
+
"passes": false
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
"category": "functional",
|
|
1257
|
+
"description": "Session cookie has sameSite=Lax",
|
|
1258
|
+
"steps": [
|
|
1259
|
+
"Step 1: Log in successfully",
|
|
1260
|
+
"Step 2: Inspect session_id cookie",
|
|
1261
|
+
"Step 3: Verify sameSite attribute is Lax"
|
|
1262
|
+
],
|
|
1263
|
+
"passes": false
|
|
1264
|
+
},
|
|
1265
|
+
{
|
|
1266
|
+
"category": "functional",
|
|
1267
|
+
"description": "Soft deleted records are excluded from list queries",
|
|
1268
|
+
"steps": [
|
|
1269
|
+
"Step 1: Create a user",
|
|
1270
|
+
"Step 2: Soft delete the user",
|
|
1271
|
+
"Step 3: Query GET /api/users",
|
|
1272
|
+
"Step 4: Verify deleted user not in results"
|
|
1273
|
+
],
|
|
1274
|
+
"passes": false
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
"category": "functional",
|
|
1278
|
+
"description": "Soft deleted records preserve data integrity",
|
|
1279
|
+
"steps": [
|
|
1280
|
+
"Step 1: Create user with account relationships",
|
|
1281
|
+
"Step 2: Soft delete the user",
|
|
1282
|
+
"Step 3: Verify user record still in database",
|
|
1283
|
+
"Step 4: Verify relationships intact",
|
|
1284
|
+
"Step 5: Verify audit logs reference user"
|
|
1285
|
+
],
|
|
1286
|
+
"passes": false
|
|
1287
|
+
},
|
|
1288
|
+
{
|
|
1289
|
+
"category": "functional",
|
|
1290
|
+
"description": "Audit log captures IP address",
|
|
1291
|
+
"steps": [
|
|
1292
|
+
"Step 1: Perform an action that creates audit log",
|
|
1293
|
+
"Step 2: Query audit logs for that action",
|
|
1294
|
+
"Step 3: Verify ipAddress field populated"
|
|
1295
|
+
],
|
|
1296
|
+
"passes": false
|
|
1297
|
+
},
|
|
1298
|
+
{
|
|
1299
|
+
"category": "functional",
|
|
1300
|
+
"description": "Audit log captures User-Agent",
|
|
1301
|
+
"steps": [
|
|
1302
|
+
"Step 1: Perform an action from browser",
|
|
1303
|
+
"Step 2: Query audit logs",
|
|
1304
|
+
"Step 3: Verify userAgent field contains browser info"
|
|
1305
|
+
],
|
|
1306
|
+
"passes": false
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
"category": "functional",
|
|
1310
|
+
"description": "Audit log captures before/after state for updates",
|
|
1311
|
+
"steps": [
|
|
1312
|
+
"Step 1: Update a user's name",
|
|
1313
|
+
"Step 2: Query audit logs for UPDATE action",
|
|
1314
|
+
"Step 3: Verify changes field contains old value",
|
|
1315
|
+
"Step 4: Verify changes field contains new value"
|
|
1316
|
+
],
|
|
1317
|
+
"passes": false
|
|
1318
|
+
},
|
|
1319
|
+
{
|
|
1320
|
+
"category": "functional",
|
|
1321
|
+
"description": "Multiple accounts can have same user with different roles",
|
|
1322
|
+
"steps": [
|
|
1323
|
+
"Step 1: Create two accounts",
|
|
1324
|
+
"Step 2: Add same user to both accounts",
|
|
1325
|
+
"Step 3: Assign ADMIN role in account A",
|
|
1326
|
+
"Step 4: Assign VIEWER role in account B",
|
|
1327
|
+
"Step 5: Verify user has correct role in each context"
|
|
1328
|
+
],
|
|
1329
|
+
"passes": false
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
"category": "functional",
|
|
1333
|
+
"description": "User can switch between accounts",
|
|
1334
|
+
"steps": [
|
|
1335
|
+
"Step 1: Log in as user with multiple accounts",
|
|
1336
|
+
"Step 2: Make request to account A",
|
|
1337
|
+
"Step 3: Make request to account B",
|
|
1338
|
+
"Step 4: Verify correct data isolation for each"
|
|
1339
|
+
],
|
|
1340
|
+
"passes": false
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
"category": "functional",
|
|
1344
|
+
"description": "Test login endpoint works in development mode",
|
|
1345
|
+
"steps": [
|
|
1346
|
+
"Step 1: Set environment to development",
|
|
1347
|
+
"Step 2: Send POST to /auth/test-login with user data",
|
|
1348
|
+
"Step 3: Verify session created",
|
|
1349
|
+
"Step 4: Verify can access protected routes"
|
|
1350
|
+
],
|
|
1351
|
+
"passes": false
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
"category": "functional",
|
|
1355
|
+
"description": "Test login endpoint disabled in production",
|
|
1356
|
+
"steps": [
|
|
1357
|
+
"Step 1: Set environment to production",
|
|
1358
|
+
"Step 2: Attempt POST to /auth/test-login",
|
|
1359
|
+
"Step 3: Verify 404 or 403 response"
|
|
1360
|
+
],
|
|
1361
|
+
"passes": false
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
"category": "style",
|
|
1365
|
+
"description": "Landing page hero section has proper layout",
|
|
1366
|
+
"steps": [
|
|
1367
|
+
"Step 1: Navigate to /",
|
|
1368
|
+
"Step 2: Take screenshot of hero section",
|
|
1369
|
+
"Step 3: Verify headline is prominent",
|
|
1370
|
+
"Step 4: Verify subheadline is readable",
|
|
1371
|
+
"Step 5: Verify CTA buttons are prominent"
|
|
1372
|
+
],
|
|
1373
|
+
"passes": false
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
"category": "style",
|
|
1377
|
+
"description": "Login page card is centered on screen",
|
|
1378
|
+
"steps": [
|
|
1379
|
+
"Step 1: Navigate to /login",
|
|
1380
|
+
"Step 2: Take screenshot",
|
|
1381
|
+
"Step 3: Verify card is horizontally centered",
|
|
1382
|
+
"Step 4: Verify card is vertically centered"
|
|
1383
|
+
],
|
|
1384
|
+
"passes": false
|
|
1385
|
+
},
|
|
1386
|
+
{
|
|
1387
|
+
"category": "style",
|
|
1388
|
+
"description": "Dashboard uses consistent card styling",
|
|
1389
|
+
"steps": [
|
|
1390
|
+
"Step 1: Navigate to /dashboard",
|
|
1391
|
+
"Step 2: Inspect all cards on page",
|
|
1392
|
+
"Step 3: Verify consistent border radius",
|
|
1393
|
+
"Step 4: Verify consistent shadow depth",
|
|
1394
|
+
"Step 5: Verify consistent padding"
|
|
1395
|
+
],
|
|
1396
|
+
"passes": false
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
"category": "style",
|
|
1400
|
+
"description": "Primary buttons use brand color",
|
|
1401
|
+
"steps": [
|
|
1402
|
+
"Step 1: Find primary button on page",
|
|
1403
|
+
"Step 2: Verify background matches brand color",
|
|
1404
|
+
"Step 3: Verify text is readable on background",
|
|
1405
|
+
"Step 4: Verify hover state changes color"
|
|
1406
|
+
],
|
|
1407
|
+
"passes": false
|
|
1408
|
+
},
|
|
1409
|
+
{
|
|
1410
|
+
"category": "style",
|
|
1411
|
+
"description": "Secondary buttons have outline style",
|
|
1412
|
+
"steps": [
|
|
1413
|
+
"Step 1: Find secondary button on page",
|
|
1414
|
+
"Step 2: Verify outline border visible",
|
|
1415
|
+
"Step 3: Verify background is transparent",
|
|
1416
|
+
"Step 4: Verify hover state fills background"
|
|
1417
|
+
],
|
|
1418
|
+
"passes": false
|
|
1419
|
+
},
|
|
1420
|
+
{
|
|
1421
|
+
"category": "style",
|
|
1422
|
+
"description": "Destructive buttons use red color",
|
|
1423
|
+
"steps": [
|
|
1424
|
+
"Step 1: Find destructive button (e.g., delete)",
|
|
1425
|
+
"Step 2: Verify red background color (#dc2626)",
|
|
1426
|
+
"Step 3: Verify white text for contrast"
|
|
1427
|
+
],
|
|
1428
|
+
"passes": false
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"category": "style",
|
|
1432
|
+
"description": "Avatar component shows user initials as fallback",
|
|
1433
|
+
"steps": [
|
|
1434
|
+
"Step 1: Find user without avatar URL",
|
|
1435
|
+
"Step 2: View avatar component",
|
|
1436
|
+
"Step 3: Verify initials displayed",
|
|
1437
|
+
"Step 4: Verify initials derived from name"
|
|
1438
|
+
],
|
|
1439
|
+
"passes": false
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
"category": "style",
|
|
1443
|
+
"description": "Avatar component displays image when URL provided",
|
|
1444
|
+
"steps": [
|
|
1445
|
+
"Step 1: Find user with avatar URL",
|
|
1446
|
+
"Step 2: View avatar component",
|
|
1447
|
+
"Step 3: Verify image displays correctly",
|
|
1448
|
+
"Step 4: Verify image is circular"
|
|
1449
|
+
],
|
|
1450
|
+
"passes": false
|
|
1451
|
+
},
|
|
1452
|
+
{
|
|
1453
|
+
"category": "style",
|
|
1454
|
+
"description": "Badge component has correct variant styling",
|
|
1455
|
+
"steps": [
|
|
1456
|
+
"Step 1: Find badges on page (e.g., role badges)",
|
|
1457
|
+
"Step 2: Verify default variant styling",
|
|
1458
|
+
"Step 3: Verify secondary variant if present",
|
|
1459
|
+
"Step 4: Verify destructive variant if present"
|
|
1460
|
+
],
|
|
1461
|
+
"passes": false
|
|
1462
|
+
},
|
|
1463
|
+
{
|
|
1464
|
+
"category": "style",
|
|
1465
|
+
"description": "Input fields have focus ring on focus",
|
|
1466
|
+
"steps": [
|
|
1467
|
+
"Step 1: Find input field",
|
|
1468
|
+
"Step 2: Click to focus input",
|
|
1469
|
+
"Step 3: Verify focus ring appears",
|
|
1470
|
+
"Step 4: Verify ring uses brand color"
|
|
1471
|
+
],
|
|
1472
|
+
"passes": false
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
"category": "style",
|
|
1476
|
+
"description": "Input fields show error state for validation",
|
|
1477
|
+
"steps": [
|
|
1478
|
+
"Step 1: Find input with validation",
|
|
1479
|
+
"Step 2: Trigger validation error",
|
|
1480
|
+
"Step 3: Verify red border appears",
|
|
1481
|
+
"Step 4: Verify error message displays below"
|
|
1482
|
+
],
|
|
1483
|
+
"passes": false
|
|
1484
|
+
},
|
|
1485
|
+
{
|
|
1486
|
+
"category": "style",
|
|
1487
|
+
"description": "Dialog modal has overlay backdrop",
|
|
1488
|
+
"steps": [
|
|
1489
|
+
"Step 1: Open any dialog",
|
|
1490
|
+
"Step 2: Verify semi-transparent overlay behind",
|
|
1491
|
+
"Step 3: Verify dialog content above overlay",
|
|
1492
|
+
"Step 4: Verify clicking overlay closes dialog"
|
|
1493
|
+
],
|
|
1494
|
+
"passes": false
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
"category": "style",
|
|
1498
|
+
"description": "Dialog animates in with scale effect",
|
|
1499
|
+
"steps": [
|
|
1500
|
+
"Step 1: Open any dialog",
|
|
1501
|
+
"Step 2: Observe animation",
|
|
1502
|
+
"Step 3: Verify scale-in animation",
|
|
1503
|
+
"Step 4: Verify animation is smooth (150ms)"
|
|
1504
|
+
],
|
|
1505
|
+
"passes": false
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
"category": "style",
|
|
1509
|
+
"description": "Skeleton loading states show pulse animation",
|
|
1510
|
+
"steps": [
|
|
1511
|
+
"Step 1: Navigate to page while data loading",
|
|
1512
|
+
"Step 2: Observe skeleton elements",
|
|
1513
|
+
"Step 3: Verify pulse animation active",
|
|
1514
|
+
"Step 4: Verify skeletons match content layout"
|
|
1515
|
+
],
|
|
1516
|
+
"passes": false
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
"category": "style",
|
|
1520
|
+
"description": "Sidebar has correct width and background",
|
|
1521
|
+
"steps": [
|
|
1522
|
+
"Step 1: View sidebar on authenticated page",
|
|
1523
|
+
"Step 2: Verify sidebar width is consistent",
|
|
1524
|
+
"Step 3: Verify background color matches design",
|
|
1525
|
+
"Step 4: Verify border separates from content"
|
|
1526
|
+
],
|
|
1527
|
+
"passes": false
|
|
1528
|
+
},
|
|
1529
|
+
{
|
|
1530
|
+
"category": "style",
|
|
1531
|
+
"description": "Sidebar navigation links have hover states",
|
|
1532
|
+
"steps": [
|
|
1533
|
+
"Step 1: View sidebar navigation",
|
|
1534
|
+
"Step 2: Hover over navigation link",
|
|
1535
|
+
"Step 3: Verify background color changes",
|
|
1536
|
+
"Step 4: Verify active link has distinct style"
|
|
1537
|
+
],
|
|
1538
|
+
"passes": false
|
|
1539
|
+
},
|
|
1540
|
+
{
|
|
1541
|
+
"category": "style",
|
|
1542
|
+
"description": "Page headers have consistent typography",
|
|
1543
|
+
"steps": [
|
|
1544
|
+
"Step 1: Navigate through authenticated pages",
|
|
1545
|
+
"Step 2: Compare page header styles",
|
|
1546
|
+
"Step 3: Verify font size is consistent",
|
|
1547
|
+
"Step 4: Verify font weight is consistent",
|
|
1548
|
+
"Step 5: Verify spacing below header is consistent"
|
|
1549
|
+
],
|
|
1550
|
+
"passes": false
|
|
1551
|
+
},
|
|
1552
|
+
{
|
|
1553
|
+
"category": "style",
|
|
1554
|
+
"description": "Tables have proper styling and hover states",
|
|
1555
|
+
"steps": [
|
|
1556
|
+
"Step 1: Find table on team or users page",
|
|
1557
|
+
"Step 2: Verify header row styling",
|
|
1558
|
+
"Step 3: Verify alternating row colors or borders",
|
|
1559
|
+
"Step 4: Hover over row",
|
|
1560
|
+
"Step 5: Verify hover highlight effect"
|
|
1561
|
+
],
|
|
1562
|
+
"passes": false
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
"category": "style",
|
|
1566
|
+
"description": "Separators use correct border color",
|
|
1567
|
+
"steps": [
|
|
1568
|
+
"Step 1: Find horizontal separator",
|
|
1569
|
+
"Step 2: Verify color matches design system",
|
|
1570
|
+
"Step 3: Verify thickness is 1px"
|
|
1571
|
+
],
|
|
1572
|
+
"passes": false
|
|
1573
|
+
},
|
|
1574
|
+
{
|
|
1575
|
+
"category": "style",
|
|
1576
|
+
"description": "Dark mode uses correct background colors",
|
|
1577
|
+
"steps": [
|
|
1578
|
+
"Step 1: Enable dark mode",
|
|
1579
|
+
"Step 2: Verify background is near-black (#0a0a0a)",
|
|
1580
|
+
"Step 3: Verify card background matches spec",
|
|
1581
|
+
"Step 4: Verify foreground text is off-white (#fafafa)"
|
|
1582
|
+
],
|
|
1583
|
+
"passes": false
|
|
1584
|
+
},
|
|
1585
|
+
{
|
|
1586
|
+
"category": "style",
|
|
1587
|
+
"description": "Dark mode uses correct border colors",
|
|
1588
|
+
"steps": [
|
|
1589
|
+
"Step 1: Enable dark mode",
|
|
1590
|
+
"Step 2: Inspect card borders",
|
|
1591
|
+
"Step 3: Verify border color is dark gray (#262626)"
|
|
1592
|
+
],
|
|
1593
|
+
"passes": false
|
|
1594
|
+
},
|
|
1595
|
+
{
|
|
1596
|
+
"category": "style",
|
|
1597
|
+
"description": "Light mode uses correct background colors",
|
|
1598
|
+
"steps": [
|
|
1599
|
+
"Step 1: Ensure light mode active",
|
|
1600
|
+
"Step 2: Verify background is white (#ffffff)",
|
|
1601
|
+
"Step 3: Verify foreground text is near-black (#0a0a0a)"
|
|
1602
|
+
],
|
|
1603
|
+
"passes": false
|
|
1604
|
+
},
|
|
1605
|
+
{
|
|
1606
|
+
"category": "style",
|
|
1607
|
+
"description": "Light mode uses correct border colors",
|
|
1608
|
+
"steps": [
|
|
1609
|
+
"Step 1: Ensure light mode active",
|
|
1610
|
+
"Step 2: Inspect card borders",
|
|
1611
|
+
"Step 3: Verify border color is light gray (#e5e5e5)"
|
|
1612
|
+
],
|
|
1613
|
+
"passes": false
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
"category": "style",
|
|
1617
|
+
"description": "Typography uses Inter font family",
|
|
1618
|
+
"steps": [
|
|
1619
|
+
"Step 1: Load any page",
|
|
1620
|
+
"Step 2: Inspect body font-family",
|
|
1621
|
+
"Step 3: Verify Inter is primary font",
|
|
1622
|
+
"Step 4: Verify system-ui as fallback"
|
|
1623
|
+
],
|
|
1624
|
+
"passes": false
|
|
1625
|
+
},
|
|
1626
|
+
{
|
|
1627
|
+
"category": "style",
|
|
1628
|
+
"description": "Code/monospace uses JetBrains Mono",
|
|
1629
|
+
"steps": [
|
|
1630
|
+
"Step 1: Find code element on page",
|
|
1631
|
+
"Step 2: Inspect font-family",
|
|
1632
|
+
"Step 3: Verify JetBrains Mono is primary",
|
|
1633
|
+
"Step 4: Verify Consolas as fallback"
|
|
1634
|
+
],
|
|
1635
|
+
"passes": false
|
|
1636
|
+
},
|
|
1637
|
+
{
|
|
1638
|
+
"category": "style",
|
|
1639
|
+
"description": "Text sizing follows scale (xs through 3xl)",
|
|
1640
|
+
"steps": [
|
|
1641
|
+
"Step 1: Find text elements on page",
|
|
1642
|
+
"Step 2: Verify text-sm is 0.875rem",
|
|
1643
|
+
"Step 3: Verify text-base is 1rem",
|
|
1644
|
+
"Step 4: Verify text-lg is 1.125rem"
|
|
1645
|
+
],
|
|
1646
|
+
"passes": false
|
|
1647
|
+
},
|
|
1648
|
+
{
|
|
1649
|
+
"category": "style",
|
|
1650
|
+
"description": "Spacing uses 4px base scale",
|
|
1651
|
+
"steps": [
|
|
1652
|
+
"Step 1: Inspect padding on various elements",
|
|
1653
|
+
"Step 2: Verify p-2 equals 8px",
|
|
1654
|
+
"Step 3: Verify p-4 equals 16px",
|
|
1655
|
+
"Step 4: Verify gap-4 equals 16px"
|
|
1656
|
+
],
|
|
1657
|
+
"passes": false
|
|
1658
|
+
},
|
|
1659
|
+
{
|
|
1660
|
+
"category": "style",
|
|
1661
|
+
"description": "Border radius matches design system",
|
|
1662
|
+
"steps": [
|
|
1663
|
+
"Step 1: Find various rounded elements",
|
|
1664
|
+
"Step 2: Verify rounded-md equals 6px",
|
|
1665
|
+
"Step 3: Verify rounded-lg equals 8px",
|
|
1666
|
+
"Step 4: Verify avatars use rounded-full"
|
|
1667
|
+
],
|
|
1668
|
+
"passes": false
|
|
1669
|
+
},
|
|
1670
|
+
{
|
|
1671
|
+
"category": "style",
|
|
1672
|
+
"description": "Shadows provide appropriate elevation",
|
|
1673
|
+
"steps": [
|
|
1674
|
+
"Step 1: Find elevated cards",
|
|
1675
|
+
"Step 2: Verify shadow provides depth",
|
|
1676
|
+
"Step 3: Verify modals have larger shadow",
|
|
1677
|
+
"Step 4: Verify dropdowns have shadow-lg"
|
|
1678
|
+
],
|
|
1679
|
+
"passes": false
|
|
1680
|
+
},
|
|
1681
|
+
{
|
|
1682
|
+
"category": "style",
|
|
1683
|
+
"description": "Transitions use 150ms ease-in-out",
|
|
1684
|
+
"steps": [
|
|
1685
|
+
"Step 1: Hover over button",
|
|
1686
|
+
"Step 2: Observe transition smoothness",
|
|
1687
|
+
"Step 3: Verify transition duration is 150ms"
|
|
1688
|
+
],
|
|
1689
|
+
"passes": false
|
|
1690
|
+
},
|
|
1691
|
+
{
|
|
1692
|
+
"category": "style",
|
|
1693
|
+
"description": "Page transitions use fade-in animation",
|
|
1694
|
+
"steps": [
|
|
1695
|
+
"Step 1: Navigate between pages",
|
|
1696
|
+
"Step 2: Observe page transition",
|
|
1697
|
+
"Step 3: Verify fade effect applied"
|
|
1698
|
+
],
|
|
1699
|
+
"passes": false
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
"category": "style",
|
|
1703
|
+
"description": "Mobile sidebar collapses correctly",
|
|
1704
|
+
"steps": [
|
|
1705
|
+
"Step 1: Resize to mobile viewport (< 768px)",
|
|
1706
|
+
"Step 2: Verify sidebar is hidden",
|
|
1707
|
+
"Step 3: Verify hamburger menu appears",
|
|
1708
|
+
"Step 4: Click hamburger",
|
|
1709
|
+
"Step 5: Verify sidebar slides in"
|
|
1710
|
+
],
|
|
1711
|
+
"passes": false
|
|
1712
|
+
},
|
|
1713
|
+
{
|
|
1714
|
+
"category": "style",
|
|
1715
|
+
"description": "Mobile layout adjusts padding and margins",
|
|
1716
|
+
"steps": [
|
|
1717
|
+
"Step 1: View page on mobile viewport",
|
|
1718
|
+
"Step 2: Verify reduced padding on edges",
|
|
1719
|
+
"Step 3: Verify content fits screen width",
|
|
1720
|
+
"Step 4: Verify no horizontal scroll needed"
|
|
1721
|
+
],
|
|
1722
|
+
"passes": false
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
"category": "style",
|
|
1726
|
+
"description": "Tablet layout shows intermediate design",
|
|
1727
|
+
"steps": [
|
|
1728
|
+
"Step 1: Resize to tablet viewport (768-1024px)",
|
|
1729
|
+
"Step 2: Verify layout adapts appropriately",
|
|
1730
|
+
"Step 3: Verify cards may stack or reduce columns"
|
|
1731
|
+
],
|
|
1732
|
+
"passes": false
|
|
1733
|
+
},
|
|
1734
|
+
{
|
|
1735
|
+
"category": "style",
|
|
1736
|
+
"description": "Toast notifications appear in bottom-right",
|
|
1737
|
+
"steps": [
|
|
1738
|
+
"Step 1: Trigger a toast notification",
|
|
1739
|
+
"Step 2: Verify toast appears in bottom-right",
|
|
1740
|
+
"Step 3: Verify toast has proper padding",
|
|
1741
|
+
"Step 4: Verify toast has close button"
|
|
1742
|
+
],
|
|
1743
|
+
"passes": false
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
"category": "style",
|
|
1747
|
+
"description": "Success toast has green styling",
|
|
1748
|
+
"steps": [
|
|
1749
|
+
"Step 1: Trigger success action",
|
|
1750
|
+
"Step 2: Observe success toast",
|
|
1751
|
+
"Step 3: Verify green accent color",
|
|
1752
|
+
"Step 4: Verify checkmark icon if present"
|
|
1753
|
+
],
|
|
1754
|
+
"passes": false
|
|
1755
|
+
},
|
|
1756
|
+
{
|
|
1757
|
+
"category": "style",
|
|
1758
|
+
"description": "Error toast has red styling",
|
|
1759
|
+
"steps": [
|
|
1760
|
+
"Step 1: Trigger error action",
|
|
1761
|
+
"Step 2: Observe error toast",
|
|
1762
|
+
"Step 3: Verify red accent color",
|
|
1763
|
+
"Step 4: Verify error icon if present"
|
|
1764
|
+
],
|
|
1765
|
+
"passes": false
|
|
1766
|
+
},
|
|
1767
|
+
{
|
|
1768
|
+
"category": "style",
|
|
1769
|
+
"description": "Main content has max-width constraint",
|
|
1770
|
+
"steps": [
|
|
1771
|
+
"Step 1: View page on wide screen",
|
|
1772
|
+
"Step 2: Verify content has max-width",
|
|
1773
|
+
"Step 3: Verify content is centered",
|
|
1774
|
+
"Step 4: Verify side margins grow on ultra-wide"
|
|
1775
|
+
],
|
|
1776
|
+
"passes": false
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
"category": "style",
|
|
1780
|
+
"description": "Form labels are properly associated with inputs",
|
|
1781
|
+
"steps": [
|
|
1782
|
+
"Step 1: Find form with labels",
|
|
1783
|
+
"Step 2: Verify labels use htmlFor attribute",
|
|
1784
|
+
"Step 3: Click label and verify input focuses"
|
|
1785
|
+
],
|
|
1786
|
+
"passes": false
|
|
1787
|
+
},
|
|
1788
|
+
{
|
|
1789
|
+
"category": "style",
|
|
1790
|
+
"description": "Loading buttons show spinner icon",
|
|
1791
|
+
"steps": [
|
|
1792
|
+
"Step 1: Submit a form",
|
|
1793
|
+
"Step 2: Observe button during submission",
|
|
1794
|
+
"Step 3: Verify spinner animation visible",
|
|
1795
|
+
"Step 4: Verify button text may change to 'Loading...'"
|
|
1796
|
+
],
|
|
1797
|
+
"passes": false
|
|
1798
|
+
},
|
|
1799
|
+
{
|
|
1800
|
+
"category": "functional",
|
|
1801
|
+
"description": "Keyboard navigation works for all interactive elements",
|
|
1802
|
+
"steps": [
|
|
1803
|
+
"Step 1: Start at top of page",
|
|
1804
|
+
"Step 2: Press Tab to navigate through elements",
|
|
1805
|
+
"Step 3: Verify all buttons, links, inputs are reachable",
|
|
1806
|
+
"Step 4: Verify focus indicators are visible",
|
|
1807
|
+
"Step 5: Press Enter to activate focused button"
|
|
1808
|
+
],
|
|
1809
|
+
"passes": false
|
|
1810
|
+
},
|
|
1811
|
+
{
|
|
1812
|
+
"category": "functional",
|
|
1813
|
+
"description": "Escape key closes open dialogs",
|
|
1814
|
+
"steps": [
|
|
1815
|
+
"Step 1: Open any dialog",
|
|
1816
|
+
"Step 2: Press Escape key",
|
|
1817
|
+
"Step 3: Verify dialog closes",
|
|
1818
|
+
"Step 4: Verify focus returns to trigger element"
|
|
1819
|
+
],
|
|
1820
|
+
"passes": false
|
|
1821
|
+
},
|
|
1822
|
+
{
|
|
1823
|
+
"category": "functional",
|
|
1824
|
+
"description": "Focus trap works in modal dialogs",
|
|
1825
|
+
"steps": [
|
|
1826
|
+
"Step 1: Open modal dialog",
|
|
1827
|
+
"Step 2: Tab through dialog elements",
|
|
1828
|
+
"Step 3: Verify focus stays within dialog",
|
|
1829
|
+
"Step 4: Verify cannot Tab to elements behind modal"
|
|
1830
|
+
],
|
|
1831
|
+
"passes": false
|
|
1832
|
+
},
|
|
1833
|
+
{
|
|
1834
|
+
"category": "functional",
|
|
1835
|
+
"description": "Form submits on Enter key in text fields",
|
|
1836
|
+
"steps": [
|
|
1837
|
+
"Step 1: Fill out form completely",
|
|
1838
|
+
"Step 2: Focus on text input",
|
|
1839
|
+
"Step 3: Press Enter",
|
|
1840
|
+
"Step 4: Verify form submits"
|
|
1841
|
+
],
|
|
1842
|
+
"passes": false
|
|
1843
|
+
},
|
|
1844
|
+
{
|
|
1845
|
+
"category": "style",
|
|
1846
|
+
"description": "Color contrast meets WCAG AA standards",
|
|
1847
|
+
"steps": [
|
|
1848
|
+
"Step 1: Run contrast checker on text/background",
|
|
1849
|
+
"Step 2: Verify body text has 4.5:1 ratio",
|
|
1850
|
+
"Step 3: Verify large text has 3:1 ratio",
|
|
1851
|
+
"Step 4: Check both light and dark modes"
|
|
1852
|
+
],
|
|
1853
|
+
"passes": false
|
|
1854
|
+
},
|
|
1855
|
+
{
|
|
1856
|
+
"category": "functional",
|
|
1857
|
+
"description": "ARIA labels present on icon-only buttons",
|
|
1858
|
+
"steps": [
|
|
1859
|
+
"Step 1: Find icon-only buttons",
|
|
1860
|
+
"Step 2: Verify aria-label attribute present",
|
|
1861
|
+
"Step 3: Verify label describes action"
|
|
1862
|
+
],
|
|
1863
|
+
"passes": false
|
|
1864
|
+
},
|
|
1865
|
+
{
|
|
1866
|
+
"category": "functional",
|
|
1867
|
+
"description": "Screen reader announces page title changes",
|
|
1868
|
+
"steps": [
|
|
1869
|
+
"Step 1: Enable screen reader",
|
|
1870
|
+
"Step 2: Navigate between pages",
|
|
1871
|
+
"Step 3: Verify page title announced"
|
|
1872
|
+
],
|
|
1873
|
+
"passes": false
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
"category": "functional",
|
|
1877
|
+
"description": "Images have alt text",
|
|
1878
|
+
"steps": [
|
|
1879
|
+
"Step 1: Find images on page",
|
|
1880
|
+
"Step 2: Verify alt attribute present",
|
|
1881
|
+
"Step 3: Verify alt text is descriptive"
|
|
1882
|
+
],
|
|
1883
|
+
"passes": false
|
|
1884
|
+
},
|
|
1885
|
+
{
|
|
1886
|
+
"category": "functional",
|
|
1887
|
+
"description": "Pagination works correctly with keyboard",
|
|
1888
|
+
"steps": [
|
|
1889
|
+
"Step 1: Navigate to paginated list",
|
|
1890
|
+
"Step 2: Tab to pagination controls",
|
|
1891
|
+
"Step 3: Press Enter on next page",
|
|
1892
|
+
"Step 4: Verify page content updates"
|
|
1893
|
+
],
|
|
1894
|
+
"passes": false
|
|
1895
|
+
},
|
|
1896
|
+
{
|
|
1897
|
+
"category": "functional",
|
|
1898
|
+
"description": "Page load time under 500ms on edge",
|
|
1899
|
+
"steps": [
|
|
1900
|
+
"Step 1: Clear browser cache",
|
|
1901
|
+
"Step 2: Navigate to dashboard",
|
|
1902
|
+
"Step 3: Measure time to first contentful paint",
|
|
1903
|
+
"Step 4: Verify under 500ms"
|
|
1904
|
+
],
|
|
1905
|
+
"passes": false
|
|
1906
|
+
},
|
|
1907
|
+
{
|
|
1908
|
+
"category": "functional",
|
|
1909
|
+
"description": "API response time under 100ms",
|
|
1910
|
+
"steps": [
|
|
1911
|
+
"Step 1: Make API request",
|
|
1912
|
+
"Step 2: Measure response time",
|
|
1913
|
+
"Step 3: Verify under 100ms for simple queries"
|
|
1914
|
+
],
|
|
1915
|
+
"passes": false
|
|
1916
|
+
},
|
|
1917
|
+
{
|
|
1918
|
+
"category": "functional",
|
|
1919
|
+
"description": "Optimistic updates provide instant feedback",
|
|
1920
|
+
"steps": [
|
|
1921
|
+
"Step 1: Perform update action (e.g., toggle)",
|
|
1922
|
+
"Step 2: Verify UI updates immediately",
|
|
1923
|
+
"Step 3: Verify no loading spinner for optimistic actions"
|
|
1924
|
+
],
|
|
1925
|
+
"passes": false
|
|
1926
|
+
},
|
|
1927
|
+
{
|
|
1928
|
+
"category": "functional",
|
|
1929
|
+
"description": "Failed optimistic updates rollback correctly",
|
|
1930
|
+
"steps": [
|
|
1931
|
+
"Step 1: Trigger optimistic update",
|
|
1932
|
+
"Step 2: Simulate server error",
|
|
1933
|
+
"Step 3: Verify UI rolls back to previous state",
|
|
1934
|
+
"Step 4: Verify error toast displayed"
|
|
1935
|
+
],
|
|
1936
|
+
"passes": false
|
|
1937
|
+
},
|
|
1938
|
+
{
|
|
1939
|
+
"category": "functional",
|
|
1940
|
+
"description": "Network errors show retry option",
|
|
1941
|
+
"steps": [
|
|
1942
|
+
"Step 1: Disconnect network",
|
|
1943
|
+
"Step 2: Attempt to load data",
|
|
1944
|
+
"Step 3: Verify network error message",
|
|
1945
|
+
"Step 4: Reconnect network",
|
|
1946
|
+
"Step 5: Click retry button",
|
|
1947
|
+
"Step 6: Verify data loads"
|
|
1948
|
+
],
|
|
1949
|
+
"passes": false
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
"category": "functional",
|
|
1953
|
+
"description": "TanStack Query caches data correctly",
|
|
1954
|
+
"steps": [
|
|
1955
|
+
"Step 1: Load page with data",
|
|
1956
|
+
"Step 2: Navigate away",
|
|
1957
|
+
"Step 3: Navigate back",
|
|
1958
|
+
"Step 4: Verify data displays instantly from cache",
|
|
1959
|
+
"Step 5: Verify background refetch occurs"
|
|
1960
|
+
],
|
|
1961
|
+
"passes": false
|
|
1962
|
+
},
|
|
1963
|
+
{
|
|
1964
|
+
"category": "functional",
|
|
1965
|
+
"description": "Stale data is refetched on window focus",
|
|
1966
|
+
"steps": [
|
|
1967
|
+
"Step 1: Load page with data",
|
|
1968
|
+
"Step 2: Switch to different browser tab",
|
|
1969
|
+
"Step 3: Wait for stale time to pass",
|
|
1970
|
+
"Step 4: Switch back to app tab",
|
|
1971
|
+
"Step 5: Verify data refetch triggered"
|
|
1972
|
+
],
|
|
1973
|
+
"passes": false
|
|
1974
|
+
},
|
|
1975
|
+
{
|
|
1976
|
+
"category": "functional",
|
|
1977
|
+
"description": "File upload progress shows percentage",
|
|
1978
|
+
"steps": [
|
|
1979
|
+
"Step 1: Upload a large file",
|
|
1980
|
+
"Step 2: Verify progress indicator appears",
|
|
1981
|
+
"Step 3: Verify percentage increases",
|
|
1982
|
+
"Step 4: Verify completion shows 100%"
|
|
1983
|
+
],
|
|
1984
|
+
"passes": false
|
|
1985
|
+
},
|
|
1986
|
+
{
|
|
1987
|
+
"category": "functional",
|
|
1988
|
+
"description": "File upload cancellation works",
|
|
1989
|
+
"steps": [
|
|
1990
|
+
"Step 1: Start uploading large file",
|
|
1991
|
+
"Step 2: Click cancel button",
|
|
1992
|
+
"Step 3: Verify upload stops",
|
|
1993
|
+
"Step 4: Verify partial file cleaned up"
|
|
1994
|
+
],
|
|
1995
|
+
"passes": false
|
|
1996
|
+
},
|
|
1997
|
+
{
|
|
1998
|
+
"category": "functional",
|
|
1999
|
+
"description": "Invalid file types rejected on upload",
|
|
2000
|
+
"steps": [
|
|
2001
|
+
"Step 1: Attempt to upload disallowed file type",
|
|
2002
|
+
"Step 2: Verify error message about file type",
|
|
2003
|
+
"Step 3: Verify upload does not proceed"
|
|
2004
|
+
],
|
|
2005
|
+
"passes": false
|
|
2006
|
+
},
|
|
2007
|
+
{
|
|
2008
|
+
"category": "functional",
|
|
2009
|
+
"description": "File size limits enforced on upload",
|
|
2010
|
+
"steps": [
|
|
2011
|
+
"Step 1: Attempt to upload file exceeding size limit",
|
|
2012
|
+
"Step 2: Verify error message about file size",
|
|
2013
|
+
"Step 3: Verify upload does not proceed"
|
|
2014
|
+
],
|
|
2015
|
+
"passes": false
|
|
2016
|
+
},
|
|
2017
|
+
{
|
|
2018
|
+
"category": "functional",
|
|
2019
|
+
"description": "Drizzle ORM generates correct SQL for queries",
|
|
2020
|
+
"steps": [
|
|
2021
|
+
"Step 1: Make API request that triggers query",
|
|
2022
|
+
"Step 2: Enable query logging",
|
|
2023
|
+
"Step 3: Verify SQL is efficient",
|
|
2024
|
+
"Step 4: Verify no N+1 queries"
|
|
2025
|
+
],
|
|
2026
|
+
"passes": false
|
|
2027
|
+
},
|
|
2028
|
+
{
|
|
2029
|
+
"category": "functional",
|
|
2030
|
+
"description": "Database indexes are used for common queries",
|
|
2031
|
+
"steps": [
|
|
2032
|
+
"Step 1: Query users by email",
|
|
2033
|
+
"Step 2: Verify index scan in query plan",
|
|
2034
|
+
"Step 3: Query audit logs by timestamp",
|
|
2035
|
+
"Step 4: Verify index is used"
|
|
2036
|
+
],
|
|
2037
|
+
"passes": false
|
|
2038
|
+
},
|
|
2039
|
+
{
|
|
2040
|
+
"category": "functional",
|
|
2041
|
+
"description": "Concurrent requests handled correctly",
|
|
2042
|
+
"steps": [
|
|
2043
|
+
"Step 1: Send multiple parallel requests",
|
|
2044
|
+
"Step 2: Verify all complete successfully",
|
|
2045
|
+
"Step 3: Verify no race conditions in data",
|
|
2046
|
+
"Step 4: Verify transaction isolation maintained"
|
|
2047
|
+
],
|
|
2048
|
+
"passes": false
|
|
2049
|
+
},
|
|
2050
|
+
{
|
|
2051
|
+
"category": "functional",
|
|
2052
|
+
"description": "Long-running operations don't block other requests",
|
|
2053
|
+
"steps": [
|
|
2054
|
+
"Step 1: Start slow operation (e.g., large export)",
|
|
2055
|
+
"Step 2: Make other API requests",
|
|
2056
|
+
"Step 3: Verify other requests complete quickly"
|
|
2057
|
+
],
|
|
2058
|
+
"passes": false
|
|
2059
|
+
},
|
|
2060
|
+
{
|
|
2061
|
+
"category": "functional",
|
|
2062
|
+
"description": "Email invitation contains correct link",
|
|
2063
|
+
"steps": [
|
|
2064
|
+
"Step 1: Create invitation",
|
|
2065
|
+
"Step 2: Capture sent email content",
|
|
2066
|
+
"Step 3: Verify invitation link format",
|
|
2067
|
+
"Step 4: Verify link includes token",
|
|
2068
|
+
"Step 5: Click link and verify it works"
|
|
2069
|
+
],
|
|
2070
|
+
"passes": false
|
|
2071
|
+
},
|
|
2072
|
+
{
|
|
2073
|
+
"category": "functional",
|
|
2074
|
+
"description": "Email invitation shows account name",
|
|
2075
|
+
"steps": [
|
|
2076
|
+
"Step 1: Create invitation for 'Acme Corp'",
|
|
2077
|
+
"Step 2: Capture sent email",
|
|
2078
|
+
"Step 3: Verify 'Acme Corp' appears in email",
|
|
2079
|
+
"Step 4: Verify inviter's name appears"
|
|
2080
|
+
],
|
|
2081
|
+
"passes": false
|
|
2082
|
+
},
|
|
2083
|
+
{
|
|
2084
|
+
"category": "functional",
|
|
2085
|
+
"description": "Invitation email uses correct sender address",
|
|
2086
|
+
"steps": [
|
|
2087
|
+
"Step 1: Configure SENDGRID_FROM_EMAIL",
|
|
2088
|
+
"Step 2: Create invitation",
|
|
2089
|
+
"Step 3: Verify email From matches config"
|
|
2090
|
+
],
|
|
2091
|
+
"passes": false
|
|
2092
|
+
},
|
|
2093
|
+
{
|
|
2094
|
+
"category": "functional",
|
|
2095
|
+
"description": "URL state preserved for redirect parameter",
|
|
2096
|
+
"steps": [
|
|
2097
|
+
"Step 1: Navigate to /dashboard as unauthenticated",
|
|
2098
|
+
"Step 2: Verify redirect to /login?redirect=/dashboard",
|
|
2099
|
+
"Step 3: Complete login",
|
|
2100
|
+
"Step 4: Verify redirect to /dashboard"
|
|
2101
|
+
],
|
|
2102
|
+
"passes": false
|
|
2103
|
+
},
|
|
2104
|
+
{
|
|
2105
|
+
"category": "functional",
|
|
2106
|
+
"description": "Browser back button works correctly",
|
|
2107
|
+
"steps": [
|
|
2108
|
+
"Step 1: Navigate dashboard → team → settings",
|
|
2109
|
+
"Step 2: Click browser back button",
|
|
2110
|
+
"Step 3: Verify navigate to team",
|
|
2111
|
+
"Step 4: Click back again",
|
|
2112
|
+
"Step 5: Verify navigate to dashboard"
|
|
2113
|
+
],
|
|
2114
|
+
"passes": false
|
|
2115
|
+
},
|
|
2116
|
+
{
|
|
2117
|
+
"category": "functional",
|
|
2118
|
+
"description": "TanStack Router file-based routing works",
|
|
2119
|
+
"steps": [
|
|
2120
|
+
"Step 1: Navigate to /dashboard",
|
|
2121
|
+
"Step 2: Verify correct route component loads",
|
|
2122
|
+
"Step 3: Navigate to /team",
|
|
2123
|
+
"Step 4: Verify correct component loads"
|
|
2124
|
+
],
|
|
2125
|
+
"passes": false
|
|
2126
|
+
},
|
|
2127
|
+
{
|
|
2128
|
+
"category": "functional",
|
|
2129
|
+
"description": "Route params extracted correctly",
|
|
2130
|
+
"steps": [
|
|
2131
|
+
"Step 1: Navigate to /invite/:token",
|
|
2132
|
+
"Step 2: Verify token param extracted",
|
|
2133
|
+
"Step 3: Verify component receives token value"
|
|
2134
|
+
],
|
|
2135
|
+
"passes": false
|
|
2136
|
+
},
|
|
2137
|
+
{
|
|
2138
|
+
"category": "functional",
|
|
2139
|
+
"description": "Query parameters preserved across navigation",
|
|
2140
|
+
"steps": [
|
|
2141
|
+
"Step 1: Navigate to /team?filter=admin",
|
|
2142
|
+
"Step 2: Verify filter param used",
|
|
2143
|
+
"Step 3: Navigate to subpage and back",
|
|
2144
|
+
"Step 4: Verify filter param retained if appropriate"
|
|
2145
|
+
],
|
|
2146
|
+
"passes": false
|
|
2147
|
+
},
|
|
2148
|
+
{
|
|
2149
|
+
"category": "functional",
|
|
2150
|
+
"description": "React Hook Form validates on blur",
|
|
2151
|
+
"steps": [
|
|
2152
|
+
"Step 1: Focus form field",
|
|
2153
|
+
"Step 2: Enter invalid value",
|
|
2154
|
+
"Step 3: Blur field (click away)",
|
|
2155
|
+
"Step 4: Verify validation error shows"
|
|
2156
|
+
],
|
|
2157
|
+
"passes": false
|
|
2158
|
+
},
|
|
2159
|
+
{
|
|
2160
|
+
"category": "functional",
|
|
2161
|
+
"description": "Zod schema validation produces helpful errors",
|
|
2162
|
+
"steps": [
|
|
2163
|
+
"Step 1: Submit form with invalid data",
|
|
2164
|
+
"Step 2: Verify error messages are human-readable",
|
|
2165
|
+
"Step 3: Verify errors point to specific fields"
|
|
2166
|
+
],
|
|
2167
|
+
"passes": false
|
|
2168
|
+
},
|
|
2169
|
+
{
|
|
2170
|
+
"category": "functional",
|
|
2171
|
+
"description": "Form reset clears all fields and errors",
|
|
2172
|
+
"steps": [
|
|
2173
|
+
"Step 1: Fill form with some errors",
|
|
2174
|
+
"Step 2: Click reset/cancel button",
|
|
2175
|
+
"Step 3: Verify all fields cleared",
|
|
2176
|
+
"Step 4: Verify error messages cleared"
|
|
2177
|
+
],
|
|
2178
|
+
"passes": false
|
|
2179
|
+
},
|
|
2180
|
+
{
|
|
2181
|
+
"category": "functional",
|
|
2182
|
+
"description": "Select/dropdown keyboard navigation works",
|
|
2183
|
+
"steps": [
|
|
2184
|
+
"Step 1: Focus select field",
|
|
2185
|
+
"Step 2: Press Enter/Space to open",
|
|
2186
|
+
"Step 3: Use arrow keys to navigate options",
|
|
2187
|
+
"Step 4: Press Enter to select",
|
|
2188
|
+
"Step 5: Verify selection applied"
|
|
2189
|
+
],
|
|
2190
|
+
"passes": false
|
|
2191
|
+
},
|
|
2192
|
+
{
|
|
2193
|
+
"category": "functional",
|
|
2194
|
+
"description": "Build completes without errors",
|
|
2195
|
+
"steps": [
|
|
2196
|
+
"Step 1: Run pnpm build",
|
|
2197
|
+
"Step 2: Verify no TypeScript errors",
|
|
2198
|
+
"Step 3: Verify no build warnings",
|
|
2199
|
+
"Step 4: Verify output files generated"
|
|
2200
|
+
],
|
|
2201
|
+
"passes": false
|
|
2202
|
+
},
|
|
2203
|
+
{
|
|
2204
|
+
"category": "functional",
|
|
2205
|
+
"description": "TypeScript strict mode passes",
|
|
2206
|
+
"steps": [
|
|
2207
|
+
"Step 1: Run pnpm typecheck",
|
|
2208
|
+
"Step 2: Verify no type errors",
|
|
2209
|
+
"Step 3: Verify strict null checks pass"
|
|
2210
|
+
],
|
|
2211
|
+
"passes": false
|
|
2212
|
+
},
|
|
2213
|
+
{
|
|
2214
|
+
"category": "functional",
|
|
2215
|
+
"description": "ESLint passes without errors",
|
|
2216
|
+
"steps": [
|
|
2217
|
+
"Step 1: Run pnpm lint",
|
|
2218
|
+
"Step 2: Verify no linting errors",
|
|
2219
|
+
"Step 3: Verify code follows style guide"
|
|
2220
|
+
],
|
|
2221
|
+
"passes": false
|
|
2222
|
+
},
|
|
2223
|
+
{
|
|
2224
|
+
"category": "functional",
|
|
2225
|
+
"description": "Unit tests achieve 95% coverage on server",
|
|
2226
|
+
"steps": [
|
|
2227
|
+
"Step 1: Run pnpm test:coverage",
|
|
2228
|
+
"Step 2: Verify server code at 95%+ coverage",
|
|
2229
|
+
"Step 3: Verify all services tested",
|
|
2230
|
+
"Step 4: Verify all routes tested"
|
|
2231
|
+
],
|
|
2232
|
+
"passes": false
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
"category": "functional",
|
|
2236
|
+
"description": "Unit tests achieve 90% coverage on client",
|
|
2237
|
+
"steps": [
|
|
2238
|
+
"Step 1: Run pnpm test:client --coverage",
|
|
2239
|
+
"Step 2: Verify client code at 90%+ coverage",
|
|
2240
|
+
"Step 3: Verify components tested"
|
|
2241
|
+
],
|
|
2242
|
+
"passes": false
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
"category": "functional",
|
|
2246
|
+
"description": "E2E tests pass on Chromium",
|
|
2247
|
+
"steps": [
|
|
2248
|
+
"Step 1: Run pnpm test:e2e --project=chromium",
|
|
2249
|
+
"Step 2: Verify all tests pass",
|
|
2250
|
+
"Step 3: Verify no flaky tests"
|
|
2251
|
+
],
|
|
2252
|
+
"passes": false
|
|
2253
|
+
},
|
|
2254
|
+
{
|
|
2255
|
+
"category": "functional",
|
|
2256
|
+
"description": "E2E tests pass on Firefox",
|
|
2257
|
+
"steps": [
|
|
2258
|
+
"Step 1: Run pnpm test:e2e --project=firefox",
|
|
2259
|
+
"Step 2: Verify all tests pass"
|
|
2260
|
+
],
|
|
2261
|
+
"passes": false
|
|
2262
|
+
},
|
|
2263
|
+
{
|
|
2264
|
+
"category": "functional",
|
|
2265
|
+
"description": "E2E tests pass on WebKit",
|
|
2266
|
+
"steps": [
|
|
2267
|
+
"Step 1: Run pnpm test:e2e --project=webkit",
|
|
2268
|
+
"Step 2: Verify all tests pass"
|
|
2269
|
+
],
|
|
2270
|
+
"passes": false
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
"category": "functional",
|
|
2274
|
+
"description": "Smoke tests verify basic app functionality",
|
|
2275
|
+
"steps": [
|
|
2276
|
+
"Step 1: Run pnpm test:e2e --grep @smoke",
|
|
2277
|
+
"Step 2: Verify health check passes",
|
|
2278
|
+
"Step 3: Verify login flow works",
|
|
2279
|
+
"Step 4: Verify basic navigation works"
|
|
2280
|
+
],
|
|
2281
|
+
"passes": false
|
|
2282
|
+
},
|
|
2283
|
+
{
|
|
2284
|
+
"category": "functional",
|
|
2285
|
+
"description": "Critical path tests must all pass",
|
|
2286
|
+
"steps": [
|
|
2287
|
+
"Step 1: Run pnpm test:e2e --grep @critical",
|
|
2288
|
+
"Step 2: Verify auth flow passes",
|
|
2289
|
+
"Step 3: Verify core CRUD operations pass"
|
|
2290
|
+
],
|
|
2291
|
+
"passes": false
|
|
2292
|
+
},
|
|
2293
|
+
{
|
|
2294
|
+
"category": "functional",
|
|
2295
|
+
"description": "Deployment to Cloudflare Workers succeeds",
|
|
2296
|
+
"steps": [
|
|
2297
|
+
"Step 1: Run pnpm deploy",
|
|
2298
|
+
"Step 2: Verify wrangler deploys successfully",
|
|
2299
|
+
"Step 3: Verify worker URL accessible",
|
|
2300
|
+
"Step 4: Verify D1 migrations applied"
|
|
2301
|
+
],
|
|
2302
|
+
"passes": false
|
|
2303
|
+
},
|
|
2304
|
+
{
|
|
2305
|
+
"category": "functional",
|
|
2306
|
+
"description": "Environment variables work in production",
|
|
2307
|
+
"steps": [
|
|
2308
|
+
"Step 1: Set secrets via wrangler",
|
|
2309
|
+
"Step 2: Deploy to Cloudflare",
|
|
2310
|
+
"Step 3: Verify OAuth works with secrets",
|
|
2311
|
+
"Step 4: Verify JWT signing works"
|
|
2312
|
+
],
|
|
2313
|
+
"passes": false
|
|
2314
|
+
},
|
|
2315
|
+
{
|
|
2316
|
+
"category": "functional",
|
|
2317
|
+
"description": "D1 migrations run without errors",
|
|
2318
|
+
"steps": [
|
|
2319
|
+
"Step 1: Run pnpm db:migrate:local",
|
|
2320
|
+
"Step 2: Verify all migrations apply",
|
|
2321
|
+
"Step 3: Verify schema matches expected"
|
|
2322
|
+
],
|
|
2323
|
+
"passes": false
|
|
2324
|
+
},
|
|
2325
|
+
{
|
|
2326
|
+
"category": "functional",
|
|
2327
|
+
"description": "Database seeding creates test data",
|
|
2328
|
+
"steps": [
|
|
2329
|
+
"Step 1: Run pnpm db:seed",
|
|
2330
|
+
"Step 2: Verify test users created",
|
|
2331
|
+
"Step 3: Verify test accounts created",
|
|
2332
|
+
"Step 4: Verify relationships established"
|
|
2333
|
+
],
|
|
2334
|
+
"passes": false
|
|
2335
|
+
},
|
|
2336
|
+
{
|
|
2337
|
+
"category": "functional",
|
|
2338
|
+
"description": "Cloudflare type generation works",
|
|
2339
|
+
"steps": [
|
|
2340
|
+
"Step 1: Run pnpm cf-typegen",
|
|
2341
|
+
"Step 2: Verify types generated",
|
|
2342
|
+
"Step 3: Verify bindings typed correctly"
|
|
2343
|
+
],
|
|
2344
|
+
"passes": false
|
|
2345
|
+
},
|
|
2346
|
+
{
|
|
2347
|
+
"category": "functional",
|
|
2348
|
+
"description": "R2 bucket accessible from worker",
|
|
2349
|
+
"steps": [
|
|
2350
|
+
"Step 1: Deploy worker with R2 binding",
|
|
2351
|
+
"Step 2: Upload file via API",
|
|
2352
|
+
"Step 3: Verify file stored in R2",
|
|
2353
|
+
"Step 4: Verify file accessible via URL"
|
|
2354
|
+
],
|
|
2355
|
+
"passes": false
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2358
|
+
"category": "functional",
|
|
2359
|
+
"description": "KV namespace stores sessions correctly",
|
|
2360
|
+
"steps": [
|
|
2361
|
+
"Step 1: Log in to application",
|
|
2362
|
+
"Step 2: Verify session stored in KV",
|
|
2363
|
+
"Step 3: Read session data from KV",
|
|
2364
|
+
"Step 4: Verify session data is correct"
|
|
2365
|
+
],
|
|
2366
|
+
"passes": false
|
|
2367
|
+
},
|
|
2368
|
+
{
|
|
2369
|
+
"category": "functional",
|
|
2370
|
+
"description": "Path aliases resolve correctly (@/, @shared/, @server/)",
|
|
2371
|
+
"steps": [
|
|
2372
|
+
"Step 1: Use @/ import in client code",
|
|
2373
|
+
"Step 2: Use @shared/ import",
|
|
2374
|
+
"Step 3: Use @server/ import in server code",
|
|
2375
|
+
"Step 4: Verify all imports resolve",
|
|
2376
|
+
"Step 5: Verify build succeeds"
|
|
2377
|
+
],
|
|
2378
|
+
"passes": false
|
|
2379
|
+
},
|
|
2380
|
+
{
|
|
2381
|
+
"category": "functional",
|
|
2382
|
+
"description": "Environment-specific configuration loads correctly",
|
|
2383
|
+
"steps": [
|
|
2384
|
+
"Step 1: Set ENVIRONMENT to development",
|
|
2385
|
+
"Step 2: Verify dev-specific features enabled",
|
|
2386
|
+
"Step 3: Set ENVIRONMENT to production",
|
|
2387
|
+
"Step 4: Verify prod-specific features enabled"
|
|
2388
|
+
],
|
|
2389
|
+
"passes": false
|
|
2390
|
+
},
|
|
2391
|
+
{
|
|
2392
|
+
"category": "functional",
|
|
2393
|
+
"description": "Error messages sanitized in production",
|
|
2394
|
+
"steps": [
|
|
2395
|
+
"Step 1: Trigger error in production mode",
|
|
2396
|
+
"Step 2: Verify no stack trace in response",
|
|
2397
|
+
"Step 3: Verify generic error message shown"
|
|
2398
|
+
],
|
|
2399
|
+
"passes": false
|
|
2400
|
+
},
|
|
2401
|
+
{
|
|
2402
|
+
"category": "style",
|
|
2403
|
+
"description": "Integration cards have consistent sizing",
|
|
2404
|
+
"steps": [
|
|
2405
|
+
"Step 1: Navigate to /integrations",
|
|
2406
|
+
"Step 2: Verify all cards same size",
|
|
2407
|
+
"Step 3: Verify logo placement consistent",
|
|
2408
|
+
"Step 4: Verify description truncation consistent"
|
|
2409
|
+
],
|
|
2410
|
+
"passes": false
|
|
2411
|
+
},
|
|
2412
|
+
{
|
|
2413
|
+
"category": "style",
|
|
2414
|
+
"description": "Stats cards on dashboard have icons",
|
|
2415
|
+
"steps": [
|
|
2416
|
+
"Step 1: Navigate to /dashboard",
|
|
2417
|
+
"Step 2: Verify each stat card has icon",
|
|
2418
|
+
"Step 3: Verify icons are appropriately sized"
|
|
2419
|
+
],
|
|
2420
|
+
"passes": false
|
|
2421
|
+
},
|
|
2422
|
+
{
|
|
2423
|
+
"category": "style",
|
|
2424
|
+
"description": "Empty states have helpful messaging",
|
|
2425
|
+
"steps": [
|
|
2426
|
+
"Step 1: View page with no data (e.g., no team members)",
|
|
2427
|
+
"Step 2: Verify empty state illustration or icon",
|
|
2428
|
+
"Step 3: Verify helpful message explains how to add data"
|
|
2429
|
+
],
|
|
2430
|
+
"passes": false
|
|
2431
|
+
},
|
|
2432
|
+
{
|
|
2433
|
+
"category": "style",
|
|
2434
|
+
"description": "Dropdown menus align correctly",
|
|
2435
|
+
"steps": [
|
|
2436
|
+
"Step 1: Click dropdown trigger",
|
|
2437
|
+
"Step 2: Verify menu aligns to trigger",
|
|
2438
|
+
"Step 3: Verify menu doesn't overflow viewport"
|
|
2439
|
+
],
|
|
2440
|
+
"passes": false
|
|
2441
|
+
},
|
|
2442
|
+
{
|
|
2443
|
+
"category": "style",
|
|
2444
|
+
"description": "Tooltips appear on hover for truncated text",
|
|
2445
|
+
"steps": [
|
|
2446
|
+
"Step 1: Find truncated text element",
|
|
2447
|
+
"Step 2: Hover over it",
|
|
2448
|
+
"Step 3: Verify tooltip shows full text"
|
|
2449
|
+
],
|
|
2450
|
+
"passes": false
|
|
2451
|
+
},
|
|
2452
|
+
{
|
|
2453
|
+
"category": "functional",
|
|
2454
|
+
"description": "Console has no errors in production",
|
|
2455
|
+
"steps": [
|
|
2456
|
+
"Step 1: Load application in production mode",
|
|
2457
|
+
"Step 2: Open browser console",
|
|
2458
|
+
"Step 3: Navigate through all pages",
|
|
2459
|
+
"Step 4: Verify no JavaScript errors"
|
|
2460
|
+
],
|
|
2461
|
+
"passes": false
|
|
2462
|
+
},
|
|
2463
|
+
{
|
|
2464
|
+
"category": "functional",
|
|
2465
|
+
"description": "Console has no warnings in production",
|
|
2466
|
+
"steps": [
|
|
2467
|
+
"Step 1: Load application in production mode",
|
|
2468
|
+
"Step 2: Open browser console",
|
|
2469
|
+
"Step 3: Navigate through all pages",
|
|
2470
|
+
"Step 4: Verify no React warnings"
|
|
2471
|
+
],
|
|
2472
|
+
"passes": false
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
"category": "functional",
|
|
2476
|
+
"description": "Sensitive data not logged to console",
|
|
2477
|
+
"steps": [
|
|
2478
|
+
"Step 1: Enable console logging",
|
|
2479
|
+
"Step 2: Perform authentication",
|
|
2480
|
+
"Step 3: Verify no passwords in logs",
|
|
2481
|
+
"Step 4: Verify no tokens in logs",
|
|
2482
|
+
"Step 5: Verify no secrets in logs"
|
|
2483
|
+
],
|
|
2484
|
+
"passes": false
|
|
2485
|
+
},
|
|
2486
|
+
{
|
|
2487
|
+
"category": "functional",
|
|
2488
|
+
"description": "API rate limiting prevents abuse",
|
|
2489
|
+
"steps": [
|
|
2490
|
+
"Step 1: Configure rate limits",
|
|
2491
|
+
"Step 2: Send requests exceeding limit",
|
|
2492
|
+
"Step 3: Verify 429 Too Many Requests",
|
|
2493
|
+
"Step 4: Verify retry-after header"
|
|
2494
|
+
],
|
|
2495
|
+
"passes": false
|
|
2496
|
+
},
|
|
2497
|
+
{
|
|
2498
|
+
"category": "functional",
|
|
2499
|
+
"description": "Input sanitization prevents XSS",
|
|
2500
|
+
"steps": [
|
|
2501
|
+
"Step 1: Enter script tag in input field",
|
|
2502
|
+
"Step 2: Submit form",
|
|
2503
|
+
"Step 3: Verify script is escaped in display",
|
|
2504
|
+
"Step 4: Verify no XSS execution"
|
|
2505
|
+
],
|
|
2506
|
+
"passes": false
|
|
2507
|
+
},
|
|
2508
|
+
{
|
|
2509
|
+
"category": "functional",
|
|
2510
|
+
"description": "SQL injection prevented by parameterized queries",
|
|
2511
|
+
"steps": [
|
|
2512
|
+
"Step 1: Enter SQL injection attempt in search",
|
|
2513
|
+
"Step 2: Submit query",
|
|
2514
|
+
"Step 3: Verify query is parameterized",
|
|
2515
|
+
"Step 4: Verify no SQL injection executed"
|
|
2516
|
+
],
|
|
2517
|
+
"passes": false
|
|
2518
|
+
},
|
|
2519
|
+
{
|
|
2520
|
+
"category": "functional",
|
|
2521
|
+
"description": "CSRF protection via session cookies",
|
|
2522
|
+
"steps": [
|
|
2523
|
+
"Step 1: Verify session cookies have SameSite",
|
|
2524
|
+
"Step 2: Attempt cross-site request",
|
|
2525
|
+
"Step 3: Verify request fails or is rejected"
|
|
2526
|
+
],
|
|
2527
|
+
"passes": false
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
"category": "functional",
|
|
2531
|
+
"description": "Account domain uniqueness enforced",
|
|
2532
|
+
"steps": [
|
|
2533
|
+
"Step 1: Create account with domain 'acme.com'",
|
|
2534
|
+
"Step 2: Attempt to create another with same domain",
|
|
2535
|
+
"Step 3: Verify error about duplicate domain"
|
|
2536
|
+
],
|
|
2537
|
+
"passes": false
|
|
2538
|
+
},
|
|
2539
|
+
{
|
|
2540
|
+
"category": "functional",
|
|
2541
|
+
"description": "User googleId uniqueness enforced",
|
|
2542
|
+
"steps": [
|
|
2543
|
+
"Step 1: Create user with googleId 'abc123'",
|
|
2544
|
+
"Step 2: Attempt to create another with same googleId",
|
|
2545
|
+
"Step 3: Verify error or existing user returned"
|
|
2546
|
+
],
|
|
2547
|
+
"passes": false
|
|
2548
|
+
},
|
|
2549
|
+
{
|
|
2550
|
+
"category": "functional",
|
|
2551
|
+
"description": "Invitation (accountId, email) uniqueness enforced",
|
|
2552
|
+
"steps": [
|
|
2553
|
+
"Step 1: Create invitation for email in account",
|
|
2554
|
+
"Step 2: Attempt duplicate invitation",
|
|
2555
|
+
"Step 3: Verify error about existing invitation"
|
|
2556
|
+
],
|
|
2557
|
+
"passes": false
|
|
2558
|
+
},
|
|
2559
|
+
{
|
|
2560
|
+
"category": "functional",
|
|
2561
|
+
"description": "Primary key constraints work on user_accounts",
|
|
2562
|
+
"steps": [
|
|
2563
|
+
"Step 1: Add user to account",
|
|
2564
|
+
"Step 2: Attempt to add same user-account pair",
|
|
2565
|
+
"Step 3: Verify constraint error"
|
|
2566
|
+
],
|
|
2567
|
+
"passes": false
|
|
2568
|
+
},
|
|
2569
|
+
{
|
|
2570
|
+
"category": "functional",
|
|
2571
|
+
"description": "CASCADE delete removes user_accounts on user delete",
|
|
2572
|
+
"steps": [
|
|
2573
|
+
"Step 1: Create user with account memberships",
|
|
2574
|
+
"Step 2: Hard delete user (bypass soft delete for test)",
|
|
2575
|
+
"Step 3: Verify user_accounts records deleted"
|
|
2576
|
+
],
|
|
2577
|
+
"passes": false
|
|
2578
|
+
},
|
|
2579
|
+
{
|
|
2580
|
+
"category": "functional",
|
|
2581
|
+
"description": "CASCADE delete removes user_accounts on account delete",
|
|
2582
|
+
"steps": [
|
|
2583
|
+
"Step 1: Create account with user memberships",
|
|
2584
|
+
"Step 2: Hard delete account (bypass soft delete for test)",
|
|
2585
|
+
"Step 3: Verify user_accounts records deleted"
|
|
2586
|
+
],
|
|
2587
|
+
"passes": false
|
|
2588
|
+
},
|
|
2589
|
+
{
|
|
2590
|
+
"category": "functional",
|
|
2591
|
+
"description": "Refresh token is hashed before storage",
|
|
2592
|
+
"steps": [
|
|
2593
|
+
"Step 1: Generate refresh token",
|
|
2594
|
+
"Step 2: Store token in database",
|
|
2595
|
+
"Step 3: Query token record",
|
|
2596
|
+
"Step 4: Verify stored value is SHA-256 hash",
|
|
2597
|
+
"Step 5: Verify original token cannot be recovered"
|
|
2598
|
+
],
|
|
2599
|
+
"passes": false
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
"category": "functional",
|
|
2603
|
+
"description": "JWT_SECRET must be at least 32 characters",
|
|
2604
|
+
"steps": [
|
|
2605
|
+
"Step 1: Set JWT_SECRET to short value",
|
|
2606
|
+
"Step 2: Attempt to start application",
|
|
2607
|
+
"Step 3: Verify startup fails with error",
|
|
2608
|
+
"Step 4: Set JWT_SECRET to 32+ chars",
|
|
2609
|
+
"Step 5: Verify startup succeeds"
|
|
2610
|
+
],
|
|
2611
|
+
"passes": false
|
|
2612
|
+
},
|
|
2613
|
+
{
|
|
2614
|
+
"category": "functional",
|
|
2615
|
+
"description": "Session expiry removes access",
|
|
2616
|
+
"steps": [
|
|
2617
|
+
"Step 1: Create session with short expiry",
|
|
2618
|
+
"Step 2: Wait for expiry",
|
|
2619
|
+
"Step 3: Attempt to use expired session",
|
|
2620
|
+
"Step 4: Verify 401 response"
|
|
2621
|
+
],
|
|
2622
|
+
"passes": false
|
|
2623
|
+
},
|
|
2624
|
+
{
|
|
2625
|
+
"category": "functional",
|
|
2626
|
+
"description": "Invitation expiry after 7 days",
|
|
2627
|
+
"steps": [
|
|
2628
|
+
"Step 1: Create invitation",
|
|
2629
|
+
"Step 2: Verify expiresAt is 7 days from now",
|
|
2630
|
+
"Step 3: Manually set expiresAt to past",
|
|
2631
|
+
"Step 4: Attempt to accept invitation",
|
|
2632
|
+
"Step 5: Verify expiration error"
|
|
2633
|
+
],
|
|
2634
|
+
"passes": false
|
|
2635
|
+
},
|
|
2636
|
+
{
|
|
2637
|
+
"category": "functional",
|
|
2638
|
+
"description": "Presigned upload URL expires after 1 hour",
|
|
2639
|
+
"steps": [
|
|
2640
|
+
"Step 1: Generate presigned URL",
|
|
2641
|
+
"Step 2: Wait or manually expire",
|
|
2642
|
+
"Step 3: Attempt to use expired URL",
|
|
2643
|
+
"Step 4: Verify upload fails"
|
|
2644
|
+
],
|
|
2645
|
+
"passes": false
|
|
2646
|
+
},
|
|
2647
|
+
{
|
|
2648
|
+
"category": "functional",
|
|
2649
|
+
"description": "Complete new user onboarding journey from invitation to dashboard",
|
|
2650
|
+
"steps": [
|
|
2651
|
+
"Step 1: Admin creates invitation for new user email with EDITOR role",
|
|
2652
|
+
"Step 2: Verify invitation email is sent with correct link and account name",
|
|
2653
|
+
"Step 3: New user clicks invitation link in email",
|
|
2654
|
+
"Step 4: Verify invitation page shows account name and role",
|
|
2655
|
+
"Step 5: New user clicks accept and is redirected to Google OAuth",
|
|
2656
|
+
"Step 6: Complete Google OAuth authentication",
|
|
2657
|
+
"Step 7: Verify new user record is created with correct email and name",
|
|
2658
|
+
"Step 8: Verify user is automatically added to invited account with EDITOR role",
|
|
2659
|
+
"Step 9: Verify SIGNUP audit event is logged with transaction ID",
|
|
2660
|
+
"Step 10: Verify redirect to dashboard with welcome message",
|
|
2661
|
+
"Step 11: Verify sidebar shows correct user profile",
|
|
2662
|
+
"Step 12: Verify user can access team page but cannot delete users"
|
|
2663
|
+
],
|
|
2664
|
+
"passes": false
|
|
2665
|
+
},
|
|
2666
|
+
{
|
|
2667
|
+
"category": "functional",
|
|
2668
|
+
"description": "Complete team member lifecycle from invite to removal",
|
|
2669
|
+
"steps": [
|
|
2670
|
+
"Step 1: Log in as account ADMIN user",
|
|
2671
|
+
"Step 2: Navigate to team management page",
|
|
2672
|
+
"Step 3: Click invite member button",
|
|
2673
|
+
"Step 4: Enter new member email and select VIEWER role",
|
|
2674
|
+
"Step 5: Submit invitation and verify success toast",
|
|
2675
|
+
"Step 6: Verify invitation appears in pending list with 7-day expiry",
|
|
2676
|
+
"Step 7: New member accepts invitation and logs in",
|
|
2677
|
+
"Step 8: Verify new member appears in active members list",
|
|
2678
|
+
"Step 9: Admin changes member role from VIEWER to EDITOR",
|
|
2679
|
+
"Step 10: Verify audit log shows role change with before/after state",
|
|
2680
|
+
"Step 11: Admin removes member from account",
|
|
2681
|
+
"Step 12: Verify member no longer in active list",
|
|
2682
|
+
"Step 13: Verify member can no longer access account resources"
|
|
2683
|
+
],
|
|
2684
|
+
"passes": false
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
"category": "functional",
|
|
2688
|
+
"description": "Complete user profile update journey with all validations",
|
|
2689
|
+
"steps": [
|
|
2690
|
+
"Step 1: Log in as authenticated user",
|
|
2691
|
+
"Step 2: Navigate to settings page",
|
|
2692
|
+
"Step 3: Verify current profile information displayed",
|
|
2693
|
+
"Step 4: Click edit profile button",
|
|
2694
|
+
"Step 5: Clear name field and attempt to save",
|
|
2695
|
+
"Step 6: Verify validation error for empty name",
|
|
2696
|
+
"Step 7: Enter valid new name",
|
|
2697
|
+
"Step 8: Submit form and verify loading state on button",
|
|
2698
|
+
"Step 9: Verify success toast appears",
|
|
2699
|
+
"Step 10: Verify profile card shows updated name",
|
|
2700
|
+
"Step 11: Navigate away and back to settings",
|
|
2701
|
+
"Step 12: Verify updated name persists from database"
|
|
2702
|
+
],
|
|
2703
|
+
"passes": false
|
|
2704
|
+
},
|
|
2705
|
+
{
|
|
2706
|
+
"category": "functional",
|
|
2707
|
+
"description": "Complete audit log investigation workflow",
|
|
2708
|
+
"steps": [
|
|
2709
|
+
"Step 1: Perform several actions (create user, update user, delete user)",
|
|
2710
|
+
"Step 2: Log in as ADMIN or ANALYTICS user",
|
|
2711
|
+
"Step 3: Navigate to audit logs (or use API)",
|
|
2712
|
+
"Step 4: Verify all recent actions appear in log",
|
|
2713
|
+
"Step 5: Filter by entity type 'User'",
|
|
2714
|
+
"Step 6: Verify only User events shown",
|
|
2715
|
+
"Step 7: Filter by action type 'UPDATE'",
|
|
2716
|
+
"Step 8: Verify only UPDATE actions shown",
|
|
2717
|
+
"Step 9: Click on specific audit entry",
|
|
2718
|
+
"Step 10: Verify changes field shows before/after values",
|
|
2719
|
+
"Step 11: Verify IP address and user agent captured",
|
|
2720
|
+
"Step 12: Verify transaction ID groups related operations"
|
|
2721
|
+
],
|
|
2722
|
+
"passes": false
|
|
2723
|
+
},
|
|
2724
|
+
{
|
|
2725
|
+
"category": "functional",
|
|
2726
|
+
"description": "Complete file upload and management workflow",
|
|
2727
|
+
"steps": [
|
|
2728
|
+
"Step 1: Log in as authenticated user",
|
|
2729
|
+
"Step 2: Navigate to file storage area",
|
|
2730
|
+
"Step 3: Click upload button",
|
|
2731
|
+
"Step 4: Select file from local system",
|
|
2732
|
+
"Step 5: Verify file type validation (if applicable)",
|
|
2733
|
+
"Step 6: Verify file size validation (if applicable)",
|
|
2734
|
+
"Step 7: Start upload and verify progress indicator",
|
|
2735
|
+
"Step 8: Wait for upload completion (100%)",
|
|
2736
|
+
"Step 9: Verify success message and file appears in list",
|
|
2737
|
+
"Step 10: Click to view/download file",
|
|
2738
|
+
"Step 11: Verify file is accessible via public URL",
|
|
2739
|
+
"Step 12: Delete file and verify removal from list",
|
|
2740
|
+
"Step 13: Verify file no longer accessible via URL"
|
|
2741
|
+
],
|
|
2742
|
+
"passes": false
|
|
2743
|
+
},
|
|
2744
|
+
{
|
|
2745
|
+
"category": "functional",
|
|
2746
|
+
"description": "Complete multi-account user experience",
|
|
2747
|
+
"steps": [
|
|
2748
|
+
"Step 1: Super admin creates Account A",
|
|
2749
|
+
"Step 2: Super admin creates Account B",
|
|
2750
|
+
"Step 3: Add same user to Account A with ADMIN role",
|
|
2751
|
+
"Step 4: Add same user to Account B with VIEWER role",
|
|
2752
|
+
"Step 5: Log in as that user",
|
|
2753
|
+
"Step 6: Verify user can see both accounts in account list",
|
|
2754
|
+
"Step 7: Switch to Account A context",
|
|
2755
|
+
"Step 8: Verify full ADMIN capabilities (edit account, manage users)",
|
|
2756
|
+
"Step 9: Switch to Account B context",
|
|
2757
|
+
"Step 10: Verify restricted VIEWER capabilities (read-only)",
|
|
2758
|
+
"Step 11: Attempt admin action in Account B",
|
|
2759
|
+
"Step 12: Verify 403 Forbidden response"
|
|
2760
|
+
],
|
|
2761
|
+
"passes": false
|
|
2762
|
+
},
|
|
2763
|
+
{
|
|
2764
|
+
"category": "functional",
|
|
2765
|
+
"description": "Complete OAuth login flow with PKCE security",
|
|
2766
|
+
"steps": [
|
|
2767
|
+
"Step 1: Navigate to /login page",
|
|
2768
|
+
"Step 2: Click Google sign-in button",
|
|
2769
|
+
"Step 3: Verify redirect to Google with state parameter",
|
|
2770
|
+
"Step 4: Verify PKCE code_challenge in OAuth URL",
|
|
2771
|
+
"Step 5: Complete Google authentication",
|
|
2772
|
+
"Step 6: Verify callback receives authorization code",
|
|
2773
|
+
"Step 7: Verify code_verifier is used to exchange code for tokens",
|
|
2774
|
+
"Step 8: Verify session is created in KV store",
|
|
2775
|
+
"Step 9: Verify session_id cookie is set with httpOnly, secure, sameSite",
|
|
2776
|
+
"Step 10: Verify redirect to dashboard",
|
|
2777
|
+
"Step 11: Verify /auth/me returns correct user info",
|
|
2778
|
+
"Step 12: Verify LOGIN audit event logged with IP and user agent"
|
|
2779
|
+
],
|
|
2780
|
+
"passes": false
|
|
2781
|
+
},
|
|
2782
|
+
{
|
|
2783
|
+
"category": "functional",
|
|
2784
|
+
"description": "Complete error recovery and retry workflow",
|
|
2785
|
+
"steps": [
|
|
2786
|
+
"Step 1: Log in as authenticated user",
|
|
2787
|
+
"Step 2: Navigate to page that loads data",
|
|
2788
|
+
"Step 3: Disconnect network to simulate failure",
|
|
2789
|
+
"Step 4: Attempt to navigate to another page",
|
|
2790
|
+
"Step 5: Verify network error message displayed",
|
|
2791
|
+
"Step 6: Verify retry button is available",
|
|
2792
|
+
"Step 7: Reconnect network",
|
|
2793
|
+
"Step 8: Click retry button",
|
|
2794
|
+
"Step 9: Verify data loads successfully",
|
|
2795
|
+
"Step 10: Verify no error state remains",
|
|
2796
|
+
"Step 11: Verify TanStack Query cache is updated",
|
|
2797
|
+
"Step 12: Navigate away and back to verify cache works"
|
|
2798
|
+
],
|
|
2799
|
+
"passes": false
|
|
2800
|
+
},
|
|
2801
|
+
{
|
|
2802
|
+
"category": "functional",
|
|
2803
|
+
"description": "Complete form validation and submission workflow",
|
|
2804
|
+
"steps": [
|
|
2805
|
+
"Step 1: Navigate to form (invite member dialog)",
|
|
2806
|
+
"Step 2: Click submit without filling fields",
|
|
2807
|
+
"Step 3: Verify inline validation errors appear",
|
|
2808
|
+
"Step 4: Enter invalid email format",
|
|
2809
|
+
"Step 5: Verify email validation error",
|
|
2810
|
+
"Step 6: Enter valid email",
|
|
2811
|
+
"Step 7: Verify email validation error clears",
|
|
2812
|
+
"Step 8: Select role from dropdown using keyboard",
|
|
2813
|
+
"Step 9: Press Enter to submit form",
|
|
2814
|
+
"Step 10: Verify loading state on submit button",
|
|
2815
|
+
"Step 11: Verify button is disabled during submission",
|
|
2816
|
+
"Step 12: Verify success toast on completion",
|
|
2817
|
+
"Step 13: Verify form resets for next entry"
|
|
2818
|
+
],
|
|
2819
|
+
"passes": false
|
|
2820
|
+
},
|
|
2821
|
+
{
|
|
2822
|
+
"category": "functional",
|
|
2823
|
+
"description": "Complete pagination and search workflow",
|
|
2824
|
+
"steps": [
|
|
2825
|
+
"Step 1: Seed database with 50+ users",
|
|
2826
|
+
"Step 2: Navigate to users list page",
|
|
2827
|
+
"Step 3: Verify first page shows 10 users",
|
|
2828
|
+
"Step 4: Verify pagination shows total count",
|
|
2829
|
+
"Step 5: Click next page button",
|
|
2830
|
+
"Step 6: Verify second page of users loads",
|
|
2831
|
+
"Step 7: Verify URL updates with page parameter",
|
|
2832
|
+
"Step 8: Enter search term in search box",
|
|
2833
|
+
"Step 9: Verify list filters to matching users",
|
|
2834
|
+
"Step 10: Verify pagination resets to page 1",
|
|
2835
|
+
"Step 11: Clear search",
|
|
2836
|
+
"Step 12: Verify full list returns with original pagination"
|
|
2837
|
+
],
|
|
2838
|
+
"passes": false
|
|
2839
|
+
},
|
|
2840
|
+
{
|
|
2841
|
+
"category": "functional",
|
|
2842
|
+
"description": "Complete session lifecycle from login to logout",
|
|
2843
|
+
"steps": [
|
|
2844
|
+
"Step 1: Navigate to login page",
|
|
2845
|
+
"Step 2: Complete Google OAuth login",
|
|
2846
|
+
"Step 3: Verify session cookie is set",
|
|
2847
|
+
"Step 4: Access protected route successfully",
|
|
2848
|
+
"Step 5: Note session creation time",
|
|
2849
|
+
"Step 6: Wait or manually advance time near expiry",
|
|
2850
|
+
"Step 7: Verify session refresh occurs automatically",
|
|
2851
|
+
"Step 8: Click logout button",
|
|
2852
|
+
"Step 9: Verify session is deleted from KV",
|
|
2853
|
+
"Step 10: Verify session cookie is cleared",
|
|
2854
|
+
"Step 11: Verify redirect to login page",
|
|
2855
|
+
"Step 12: Attempt to access protected route",
|
|
2856
|
+
"Step 13: Verify redirect to login with 401"
|
|
2857
|
+
],
|
|
2858
|
+
"passes": false
|
|
2859
|
+
},
|
|
2860
|
+
{
|
|
2861
|
+
"category": "functional",
|
|
2862
|
+
"description": "Complete account creation and configuration by super admin",
|
|
2863
|
+
"steps": [
|
|
2864
|
+
"Step 1: Log in as Super Admin",
|
|
2865
|
+
"Step 2: Navigate to account management",
|
|
2866
|
+
"Step 3: Click create new account",
|
|
2867
|
+
"Step 4: Enter account name 'Acme Corporation'",
|
|
2868
|
+
"Step 5: Add optional description",
|
|
2869
|
+
"Step 6: Submit and verify 201 Created",
|
|
2870
|
+
"Step 7: Verify INSERT audit event logged",
|
|
2871
|
+
"Step 8: Navigate to new account settings",
|
|
2872
|
+
"Step 9: Update account description",
|
|
2873
|
+
"Step 10: Verify UPDATE audit event with changes",
|
|
2874
|
+
"Step 11: Add first user to account as ADMIN",
|
|
2875
|
+
"Step 12: Verify user can access new account"
|
|
2876
|
+
],
|
|
2877
|
+
"passes": false
|
|
2878
|
+
},
|
|
2879
|
+
{
|
|
2880
|
+
"category": "functional",
|
|
2881
|
+
"description": "Complete soft delete and restore workflow for user",
|
|
2882
|
+
"steps": [
|
|
2883
|
+
"Step 1: Log in as ADMIN user",
|
|
2884
|
+
"Step 2: Create a new user or select existing user",
|
|
2885
|
+
"Step 3: Verify user appears in active users list",
|
|
2886
|
+
"Step 4: Click delete user button",
|
|
2887
|
+
"Step 5: Confirm deletion in dialog",
|
|
2888
|
+
"Step 6: Verify user removed from active list",
|
|
2889
|
+
"Step 7: Verify DELETE audit event logged",
|
|
2890
|
+
"Step 8: Query database to confirm deletedAt is set",
|
|
2891
|
+
"Step 9: Log in as Super Admin",
|
|
2892
|
+
"Step 10: Navigate to deleted users (or API)",
|
|
2893
|
+
"Step 11: Click restore user",
|
|
2894
|
+
"Step 12: Verify user reappears in active list",
|
|
2895
|
+
"Step 13: Verify user's account relationships preserved"
|
|
2896
|
+
],
|
|
2897
|
+
"passes": false
|
|
2898
|
+
},
|
|
2899
|
+
{
|
|
2900
|
+
"category": "functional",
|
|
2901
|
+
"description": "Complete RBAC enforcement across all operations",
|
|
2902
|
+
"steps": [
|
|
2903
|
+
"Step 1: Create test account with users in each role",
|
|
2904
|
+
"Step 2: Log in as VIEWER",
|
|
2905
|
+
"Step 3: Verify can list users (GET succeeds)",
|
|
2906
|
+
"Step 4: Attempt to create user (POST fails 403)",
|
|
2907
|
+
"Step 5: Log in as EDITOR",
|
|
2908
|
+
"Step 6: Verify can create resources",
|
|
2909
|
+
"Step 7: Attempt to manage invitations (fails 403)",
|
|
2910
|
+
"Step 8: Log in as MANAGER",
|
|
2911
|
+
"Step 9: Verify can create and revoke invitations",
|
|
2912
|
+
"Step 10: Attempt to update account settings (fails 403)",
|
|
2913
|
+
"Step 11: Log in as ADMIN",
|
|
2914
|
+
"Step 12: Verify full account management capabilities",
|
|
2915
|
+
"Step 13: Attempt to create new account (fails 403, super admin only)"
|
|
2916
|
+
],
|
|
2917
|
+
"passes": false
|
|
2918
|
+
},
|
|
2919
|
+
{
|
|
2920
|
+
"category": "style",
|
|
2921
|
+
"description": "Complete responsive design verification across breakpoints",
|
|
2922
|
+
"steps": [
|
|
2923
|
+
"Step 1: Load dashboard on desktop (1920px)",
|
|
2924
|
+
"Step 2: Verify full sidebar visible with all navigation",
|
|
2925
|
+
"Step 3: Verify stats cards in grid layout",
|
|
2926
|
+
"Step 4: Resize to laptop (1366px)",
|
|
2927
|
+
"Step 5: Verify layout adjusts appropriately",
|
|
2928
|
+
"Step 6: Resize to tablet (768px)",
|
|
2929
|
+
"Step 7: Verify sidebar collapses or becomes toggleable",
|
|
2930
|
+
"Step 8: Verify cards may stack vertically",
|
|
2931
|
+
"Step 9: Resize to mobile (375px)",
|
|
2932
|
+
"Step 10: Verify hamburger menu appears",
|
|
2933
|
+
"Step 11: Verify content fits without horizontal scroll",
|
|
2934
|
+
"Step 12: Tap hamburger and verify sidebar slides in"
|
|
2935
|
+
],
|
|
2936
|
+
"passes": false
|
|
2937
|
+
},
|
|
2938
|
+
{
|
|
2939
|
+
"category": "style",
|
|
2940
|
+
"description": "Complete dark mode visual verification",
|
|
2941
|
+
"steps": [
|
|
2942
|
+
"Step 1: Enable dark mode via system preference or toggle",
|
|
2943
|
+
"Step 2: Navigate to landing page",
|
|
2944
|
+
"Step 3: Verify background is near-black (#0a0a0a)",
|
|
2945
|
+
"Step 4: Verify text is off-white (#fafafa)",
|
|
2946
|
+
"Step 5: Navigate to dashboard",
|
|
2947
|
+
"Step 6: Verify card backgrounds match dark theme",
|
|
2948
|
+
"Step 7: Verify borders use dark gray (#262626)",
|
|
2949
|
+
"Step 8: Navigate to form page",
|
|
2950
|
+
"Step 9: Verify input fields have dark styling",
|
|
2951
|
+
"Step 10: Open modal dialog",
|
|
2952
|
+
"Step 11: Verify modal uses dark theme",
|
|
2953
|
+
"Step 12: Verify all interactive elements have visible focus states"
|
|
2954
|
+
],
|
|
2955
|
+
"passes": false
|
|
2956
|
+
},
|
|
2957
|
+
{
|
|
2958
|
+
"category": "functional",
|
|
2959
|
+
"description": "Complete keyboard accessibility navigation test",
|
|
2960
|
+
"steps": [
|
|
2961
|
+
"Step 1: Navigate to authenticated page",
|
|
2962
|
+
"Step 2: Press Tab and verify focus on first interactive element",
|
|
2963
|
+
"Step 3: Continue Tab through sidebar navigation",
|
|
2964
|
+
"Step 4: Verify all nav links are focusable",
|
|
2965
|
+
"Step 5: Press Enter on Team link",
|
|
2966
|
+
"Step 6: Verify navigation occurs",
|
|
2967
|
+
"Step 7: Tab to Invite button",
|
|
2968
|
+
"Step 8: Press Enter to open dialog",
|
|
2969
|
+
"Step 9: Verify focus moves into dialog",
|
|
2970
|
+
"Step 10: Tab through dialog fields",
|
|
2971
|
+
"Step 11: Press Escape to close dialog",
|
|
2972
|
+
"Step 12: Verify focus returns to trigger button"
|
|
2973
|
+
],
|
|
2974
|
+
"passes": false
|
|
2975
|
+
},
|
|
2976
|
+
{
|
|
2977
|
+
"category": "functional",
|
|
2978
|
+
"description": "Complete CI/CD pipeline verification",
|
|
2979
|
+
"steps": [
|
|
2980
|
+
"Step 1: Run pnpm lint and verify no errors",
|
|
2981
|
+
"Step 2: Run pnpm typecheck and verify no type errors",
|
|
2982
|
+
"Step 3: Run pnpm test:run and verify all unit tests pass",
|
|
2983
|
+
"Step 4: Check unit test coverage meets thresholds (95% server, 90% client)",
|
|
2984
|
+
"Step 5: Run pnpm test:e2e --grep @smoke",
|
|
2985
|
+
"Step 6: Verify smoke tests pass",
|
|
2986
|
+
"Step 7: Run pnpm test:e2e --grep @critical",
|
|
2987
|
+
"Step 8: Verify critical path tests pass",
|
|
2988
|
+
"Step 9: Run pnpm build",
|
|
2989
|
+
"Step 10: Verify build completes without errors",
|
|
2990
|
+
"Step 11: Run pnpm deploy --dry-run",
|
|
2991
|
+
"Step 12: Verify deployment configuration is valid"
|
|
2992
|
+
],
|
|
2993
|
+
"passes": false
|
|
2994
|
+
},
|
|
2995
|
+
{
|
|
2996
|
+
"category": "functional",
|
|
2997
|
+
"description": "Complete database migration and seeding workflow",
|
|
2998
|
+
"steps": [
|
|
2999
|
+
"Step 1: Drop local database to start fresh",
|
|
3000
|
+
"Step 2: Run pnpm db:migrate:local",
|
|
3001
|
+
"Step 3: Verify all migrations apply successfully",
|
|
3002
|
+
"Step 4: Verify all tables are created (users, accounts, etc.)",
|
|
3003
|
+
"Step 5: Verify all indexes are created",
|
|
3004
|
+
"Step 6: Verify all foreign keys are established",
|
|
3005
|
+
"Step 7: Run pnpm db:seed",
|
|
3006
|
+
"Step 8: Verify test users are created",
|
|
3007
|
+
"Step 9: Verify test accounts are created",
|
|
3008
|
+
"Step 10: Verify user-account relationships established",
|
|
3009
|
+
"Step 11: Start application and login with seeded user",
|
|
3010
|
+
"Step 12: Verify seeded data accessible through UI"
|
|
3011
|
+
],
|
|
3012
|
+
"passes": false
|
|
3013
|
+
},
|
|
3014
|
+
{
|
|
3015
|
+
"category": "functional",
|
|
3016
|
+
"description": "Complete invitation expiration and cleanup workflow",
|
|
3017
|
+
"steps": [
|
|
3018
|
+
"Step 1: Create invitation for new email",
|
|
3019
|
+
"Step 2: Verify expiresAt is set to 7 days in future",
|
|
3020
|
+
"Step 3: Verify invitation appears in pending list",
|
|
3021
|
+
"Step 4: Manually update invitation expiresAt to past date",
|
|
3022
|
+
"Step 5: Navigate to invitation link",
|
|
3023
|
+
"Step 6: Verify expiration error message displayed",
|
|
3024
|
+
"Step 7: Verify invitation not listed as valid",
|
|
3025
|
+
"Step 8: Attempt to accept expired invitation",
|
|
3026
|
+
"Step 9: Verify proper error response",
|
|
3027
|
+
"Step 10: Create new invitation for same email",
|
|
3028
|
+
"Step 11: Verify new invitation replaces or coexists with expired",
|
|
3029
|
+
"Step 12: Accept new invitation successfully"
|
|
3030
|
+
],
|
|
3031
|
+
"passes": false
|
|
3032
|
+
},
|
|
3033
|
+
{
|
|
3034
|
+
"category": "functional",
|
|
3035
|
+
"description": "Complete API documentation and testing workflow",
|
|
3036
|
+
"steps": [
|
|
3037
|
+
"Step 1: Navigate to /api/doc",
|
|
3038
|
+
"Step 2: Verify OpenAPI JSON schema loads",
|
|
3039
|
+
"Step 3: Verify all endpoints documented",
|
|
3040
|
+
"Step 4: Navigate to /api/swagger",
|
|
3041
|
+
"Step 5: Verify Swagger UI renders correctly",
|
|
3042
|
+
"Step 6: Expand auth endpoints",
|
|
3043
|
+
"Step 7: Verify request/response schemas shown",
|
|
3044
|
+
"Step 8: Click 'Try It Out' on /health endpoint",
|
|
3045
|
+
"Step 9: Execute request",
|
|
3046
|
+
"Step 10: Verify response matches schema",
|
|
3047
|
+
"Step 11: Test authenticated endpoint with session cookie",
|
|
3048
|
+
"Step 12: Verify authentication works in Swagger UI"
|
|
3049
|
+
],
|
|
3050
|
+
"passes": false
|
|
3051
|
+
},
|
|
3052
|
+
{
|
|
3053
|
+
"category": "functional",
|
|
3054
|
+
"description": "Complete security audit checklist verification",
|
|
3055
|
+
"steps": [
|
|
3056
|
+
"Step 1: Verify session cookie has httpOnly flag",
|
|
3057
|
+
"Step 2: Verify session cookie has secure flag (production)",
|
|
3058
|
+
"Step 3: Verify session cookie has sameSite=Lax",
|
|
3059
|
+
"Step 4: Verify refresh tokens are hashed (SHA-256)",
|
|
3060
|
+
"Step 5: Verify passwords/secrets not in any logs",
|
|
3061
|
+
"Step 6: Verify CORS configuration is restrictive",
|
|
3062
|
+
"Step 7: Verify error messages don't leak stack traces",
|
|
3063
|
+
"Step 8: Verify rate limiting is enabled",
|
|
3064
|
+
"Step 9: Test SQL injection prevention",
|
|
3065
|
+
"Step 10: Test XSS prevention in inputs",
|
|
3066
|
+
"Step 11: Verify CSRF protection via cookies",
|
|
3067
|
+
"Step 12: Verify JWT_SECRET length validation"
|
|
3068
|
+
],
|
|
3069
|
+
"passes": false
|
|
3070
|
+
},
|
|
3071
|
+
{
|
|
3072
|
+
"category": "functional",
|
|
3073
|
+
"description": "Complete Cloudflare Workers deployment verification",
|
|
3074
|
+
"steps": [
|
|
3075
|
+
"Step 1: Run pnpm cf-typegen",
|
|
3076
|
+
"Step 2: Verify Cloudflare types generated",
|
|
3077
|
+
"Step 3: Set required secrets via wrangler",
|
|
3078
|
+
"Step 4: Run pnpm db:migrate:remote",
|
|
3079
|
+
"Step 5: Verify D1 migrations applied",
|
|
3080
|
+
"Step 6: Run pnpm deploy",
|
|
3081
|
+
"Step 7: Verify worker deployment succeeds",
|
|
3082
|
+
"Step 8: Access deployed worker URL",
|
|
3083
|
+
"Step 9: Verify /health endpoint responds",
|
|
3084
|
+
"Step 10: Test OAuth flow on production",
|
|
3085
|
+
"Step 11: Verify KV sessions work",
|
|
3086
|
+
"Step 12: Verify R2 file uploads work"
|
|
3087
|
+
],
|
|
3088
|
+
"passes": false
|
|
3089
|
+
},
|
|
3090
|
+
{
|
|
3091
|
+
"category": "style",
|
|
3092
|
+
"description": "Complete design system consistency audit",
|
|
3093
|
+
"steps": [
|
|
3094
|
+
"Step 1: Verify Inter font loaded for body text",
|
|
3095
|
+
"Step 2: Verify JetBrains Mono for code elements",
|
|
3096
|
+
"Step 3: Verify text-sm is 0.875rem (14px)",
|
|
3097
|
+
"Step 4: Verify spacing uses 4px base (p-2=8px, p-4=16px)",
|
|
3098
|
+
"Step 5: Verify border-radius: rounded-md=6px, rounded-lg=8px",
|
|
3099
|
+
"Step 6: Verify card shadows match design spec",
|
|
3100
|
+
"Step 7: Verify primary button uses brand color",
|
|
3101
|
+
"Step 8: Verify destructive button uses red (#dc2626)",
|
|
3102
|
+
"Step 9: Verify transitions are 150ms ease-in-out",
|
|
3103
|
+
"Step 10: Verify focus rings use brand color",
|
|
3104
|
+
"Step 11: Verify toast positioning (bottom-right)",
|
|
3105
|
+
"Step 12: Verify modal overlay and scale animation"
|
|
3106
|
+
],
|
|
3107
|
+
"passes": false
|
|
3108
|
+
},
|
|
3109
|
+
{
|
|
3110
|
+
"category": "functional",
|
|
3111
|
+
"description": "Complete TanStack Query state management verification",
|
|
3112
|
+
"steps": [
|
|
3113
|
+
"Step 1: Navigate to page that fetches data",
|
|
3114
|
+
"Step 2: Verify data is fetched and displayed",
|
|
3115
|
+
"Step 3: Open React DevTools Query tab",
|
|
3116
|
+
"Step 4: Verify query cache contains data",
|
|
3117
|
+
"Step 5: Navigate away from page",
|
|
3118
|
+
"Step 6: Navigate back to page",
|
|
3119
|
+
"Step 7: Verify data displays instantly from cache",
|
|
3120
|
+
"Step 8: Verify background refetch occurs",
|
|
3121
|
+
"Step 9: Switch browser tabs and wait",
|
|
3122
|
+
"Step 10: Return to app tab",
|
|
3123
|
+
"Step 11: Verify refetchOnWindowFocus triggers",
|
|
3124
|
+
"Step 12: Perform mutation and verify cache invalidation"
|
|
3125
|
+
],
|
|
3126
|
+
"passes": false
|
|
3127
|
+
}
|
|
3128
|
+
]
|