@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,204 @@
|
|
|
1
|
+
import { test, expect } from '../fixtures'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Invitation Flow E2E Tests
|
|
5
|
+
*
|
|
6
|
+
* Tests for the invitation acceptance flow via /invite/:token routes.
|
|
7
|
+
* These are public pages that don't require authentication.
|
|
8
|
+
*
|
|
9
|
+
* @tags @invitation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
test.describe('Invitation Flow @invitation', () => {
|
|
13
|
+
test.describe('Valid Invitation Token', () => {
|
|
14
|
+
test('should display invitation page for valid token @critical', async ({ page }) => {
|
|
15
|
+
// Navigate to invitation page with a valid token
|
|
16
|
+
await page.goto('/invite/valid-token-123')
|
|
17
|
+
|
|
18
|
+
// Should see the invitation card with h3 heading (CardTitle uses h3)
|
|
19
|
+
await expect(page.getByRole('heading', { name: /you've been invited/i })).toBeVisible()
|
|
20
|
+
|
|
21
|
+
// Should display workspace name (in the details section with exact match)
|
|
22
|
+
await expect(page.getByText('Acme Inc', { exact: true }).first()).toBeVisible()
|
|
23
|
+
|
|
24
|
+
// Should display inviter name (in the description)
|
|
25
|
+
await expect(page.getByText('John Doe', { exact: true })).toBeVisible()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('should have accept invitation button when valid @critical', async ({ page }) => {
|
|
29
|
+
await page.goto('/invite/valid-token-123')
|
|
30
|
+
|
|
31
|
+
// Should have Accept Invitation button
|
|
32
|
+
const acceptButton = page.getByRole('button', { name: /accept invitation/i })
|
|
33
|
+
await expect(acceptButton).toBeVisible()
|
|
34
|
+
await expect(acceptButton).toBeEnabled()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('should display invitation details correctly', async ({ page }) => {
|
|
38
|
+
await page.goto('/invite/valid-token-123')
|
|
39
|
+
|
|
40
|
+
// Should show email in the details section (exact match)
|
|
41
|
+
await expect(page.getByText('invited@example.com', { exact: true })).toBeVisible()
|
|
42
|
+
|
|
43
|
+
// Should show workspace in the details section
|
|
44
|
+
await expect(page.getByText('Acme Inc', { exact: true }).first()).toBeVisible()
|
|
45
|
+
|
|
46
|
+
// Should show role in the details section
|
|
47
|
+
await expect(page.getByText('member', { exact: true })).toBeVisible()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('should have decline button', async ({ page }) => {
|
|
51
|
+
await page.goto('/invite/valid-token-123')
|
|
52
|
+
|
|
53
|
+
// Should have Decline button
|
|
54
|
+
const declineButton = page.getByRole('link', { name: /decline/i })
|
|
55
|
+
await expect(declineButton).toBeVisible()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('should show terms and privacy policy links', async ({ page }) => {
|
|
59
|
+
await page.goto('/invite/valid-token-123')
|
|
60
|
+
|
|
61
|
+
// Should show legal text with links
|
|
62
|
+
await expect(page.getByText(/terms of service/i)).toBeVisible()
|
|
63
|
+
await expect(page.getByText(/privacy policy/i)).toBeVisible()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('should accept invitation and show success message @critical', async ({ page }) => {
|
|
67
|
+
await page.goto('/invite/valid-token-123')
|
|
68
|
+
|
|
69
|
+
// Click accept button
|
|
70
|
+
const acceptButton = page.getByRole('button', { name: /accept invitation/i })
|
|
71
|
+
await acceptButton.click()
|
|
72
|
+
|
|
73
|
+
// Should show loading state (use button-specific selector to avoid matching other text)
|
|
74
|
+
await expect(page.getByRole('button', { name: /accepting/i })).toBeVisible()
|
|
75
|
+
|
|
76
|
+
// After acceptance, should show success message (use more flexible matching)
|
|
77
|
+
await expect(page.getByRole('heading', { name: /welcome to/i })).toBeVisible({
|
|
78
|
+
timeout: 5000,
|
|
79
|
+
})
|
|
80
|
+
await expect(page.getByText(/your invitation has been accepted/i)).toBeVisible()
|
|
81
|
+
|
|
82
|
+
// Should have button to go to dashboard
|
|
83
|
+
await expect(page.getByRole('link', { name: /go to dashboard/i })).toBeVisible()
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test.describe('Invitation URL Handling', () => {
|
|
88
|
+
test('should handle invitation URL with query parameters', async ({ page }) => {
|
|
89
|
+
// Navigate with query parameters
|
|
90
|
+
await page.goto('/invite/valid-token-123?ref=email&utm_source=notification')
|
|
91
|
+
|
|
92
|
+
// Should still display the invitation page correctly
|
|
93
|
+
await expect(page.getByRole('heading', { name: /you've been invited/i })).toBeVisible()
|
|
94
|
+
await expect(page.getByRole('button', { name: /accept invitation/i })).toBeVisible()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('should handle various token formats', async ({ page }) => {
|
|
98
|
+
// Test with different token formats
|
|
99
|
+
const tokens = [
|
|
100
|
+
'abc123',
|
|
101
|
+
'token-with-dashes',
|
|
102
|
+
'TOKEN_WITH_UNDERSCORES',
|
|
103
|
+
'mixedCase123Token',
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
for (const token of tokens) {
|
|
107
|
+
await page.goto(`/invite/${token}`)
|
|
108
|
+
// Should load the invitation page (mock returns valid for all tokens)
|
|
109
|
+
await expect(page.getByRole('heading', { name: /you've been invited/i })).toBeVisible()
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test.describe('Navigation', () => {
|
|
115
|
+
test('should have header with logo link to homepage', async ({ page }) => {
|
|
116
|
+
await page.goto('/invite/valid-token-123')
|
|
117
|
+
|
|
118
|
+
// Should have header with logo
|
|
119
|
+
const logoLink = page.getByRole('link').filter({ has: page.locator('svg') }).first()
|
|
120
|
+
await expect(logoLink).toBeVisible()
|
|
121
|
+
|
|
122
|
+
// Logo should link to homepage
|
|
123
|
+
await expect(logoLink).toHaveAttribute('href', '/')
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('should navigate to homepage when clicking decline', async ({ page }) => {
|
|
127
|
+
await page.goto('/invite/valid-token-123')
|
|
128
|
+
|
|
129
|
+
// Click decline
|
|
130
|
+
await page.getByRole('link', { name: /decline/i }).click()
|
|
131
|
+
|
|
132
|
+
// Should navigate to homepage
|
|
133
|
+
await expect(page).toHaveURL('/')
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test.describe('Accessibility', () => {
|
|
138
|
+
test('should have proper heading hierarchy', async ({ page }) => {
|
|
139
|
+
await page.goto('/invite/valid-token-123')
|
|
140
|
+
|
|
141
|
+
// CardTitle uses h3 for the main heading
|
|
142
|
+
const heading = page.getByRole('heading', { level: 3 })
|
|
143
|
+
await expect(heading).toBeVisible()
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
test('should have accessible button labels', async ({ page }) => {
|
|
147
|
+
await page.goto('/invite/valid-token-123')
|
|
148
|
+
|
|
149
|
+
// Buttons should have accessible names
|
|
150
|
+
await expect(page.getByRole('button', { name: /accept invitation/i })).toBeVisible()
|
|
151
|
+
await expect(page.getByRole('link', { name: /decline/i })).toBeVisible()
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Note: The following tests are for invalid/expired token scenarios.
|
|
158
|
+
* Currently, the invitation page uses mock data that always returns valid.
|
|
159
|
+
* These tests document the expected behavior when the backend is implemented.
|
|
160
|
+
*
|
|
161
|
+
* To fully test these scenarios, the backend API should be implemented to:
|
|
162
|
+
* 1. Validate tokens against the database
|
|
163
|
+
* 2. Return appropriate error states for invalid/expired tokens
|
|
164
|
+
*/
|
|
165
|
+
test.describe('Invalid Invitation Scenarios @invitation', () => {
|
|
166
|
+
test.describe.skip('Invalid Token Handling (requires backend)', () => {
|
|
167
|
+
test('should show error for invalid token', async ({ page }) => {
|
|
168
|
+
await page.goto('/invite/invalid-token')
|
|
169
|
+
|
|
170
|
+
// Should show invalid invitation message
|
|
171
|
+
await expect(page.getByRole('heading', { name: /invalid invitation/i })).toBeVisible()
|
|
172
|
+
await expect(
|
|
173
|
+
page.getByText(/this invitation link is not valid/i)
|
|
174
|
+
).toBeVisible()
|
|
175
|
+
|
|
176
|
+
// Should have button to go to homepage
|
|
177
|
+
await expect(page.getByRole('link', { name: /go to homepage/i })).toBeVisible()
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
test('should show error for expired token', async ({ page }) => {
|
|
181
|
+
await page.goto('/invite/expired-token')
|
|
182
|
+
|
|
183
|
+
// Should show expired invitation message
|
|
184
|
+
await expect(page.getByRole('heading', { name: /invitation expired/i })).toBeVisible()
|
|
185
|
+
await expect(
|
|
186
|
+
page.getByText(/this invitation link has expired/i)
|
|
187
|
+
).toBeVisible()
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('should redirect authenticated user trying to accept own invite', async ({ page }) => {
|
|
191
|
+
// This test would require:
|
|
192
|
+
// 1. Being authenticated as user@example.com
|
|
193
|
+
// 2. Trying to accept an invite sent to user@example.com
|
|
194
|
+
// The expected behavior is to show a message or redirect
|
|
195
|
+
|
|
196
|
+
await page.goto('/invite/own-invite-token')
|
|
197
|
+
|
|
198
|
+
// Should show appropriate message
|
|
199
|
+
await expect(
|
|
200
|
+
page.getByText(/you cannot accept your own invitation/i)
|
|
201
|
+
).toBeVisible()
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
})
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { test, expect, isAuthenticated, closeAllDialogs } from '../fixtures'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Account Lifecycle Journey Tests
|
|
5
|
+
*
|
|
6
|
+
* These tests verify complete account management user flows,
|
|
7
|
+
* including security settings, sessions, and account deletion.
|
|
8
|
+
*
|
|
9
|
+
* @tags @critical @journey @account
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
test.describe('Account Lifecycle Journeys @critical @journey @account', () => {
|
|
13
|
+
test.describe('Account Overview Journey', () => {
|
|
14
|
+
test.beforeEach(async ({ page }) => {
|
|
15
|
+
const authenticated = await isAuthenticated(page)
|
|
16
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test.afterEach(async ({ page }) => {
|
|
20
|
+
await closeAllDialogs(page)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('should display account page with header', async ({ page }) => {
|
|
24
|
+
await page.goto('/account')
|
|
25
|
+
|
|
26
|
+
// Verify page loads with main heading
|
|
27
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
28
|
+
|
|
29
|
+
// Verify description
|
|
30
|
+
await expect(page.getByText(/manage your account settings, security, and connected services/i)).toBeVisible()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('should display connected accounts section', async ({ page }) => {
|
|
34
|
+
await page.goto('/account')
|
|
35
|
+
|
|
36
|
+
// Verify Connected Accounts heading
|
|
37
|
+
await expect(page.getByRole('heading', { name: /connected accounts/i })).toBeVisible()
|
|
38
|
+
|
|
39
|
+
// Verify description
|
|
40
|
+
await expect(page.getByText(/manage oauth providers linked to your account/i)).toBeVisible()
|
|
41
|
+
|
|
42
|
+
// Verify Google is connected
|
|
43
|
+
await expect(page.getByText('Google')).toBeVisible()
|
|
44
|
+
await expect(page.locator('.text-xs').filter({ hasText: /connected/i }).first()).toBeVisible()
|
|
45
|
+
|
|
46
|
+
// Verify GitHub option exists
|
|
47
|
+
await expect(page.getByText('GitHub').first()).toBeVisible()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('should display security section', async ({ page }) => {
|
|
51
|
+
await page.goto('/account')
|
|
52
|
+
|
|
53
|
+
// Verify Security heading
|
|
54
|
+
await expect(page.getByRole('heading', { name: /^security$/i })).toBeVisible()
|
|
55
|
+
|
|
56
|
+
// Verify description
|
|
57
|
+
await expect(page.getByText(/keep your account secure with these settings/i)).toBeVisible()
|
|
58
|
+
|
|
59
|
+
// Verify Two-Factor Authentication option
|
|
60
|
+
await expect(page.getByText(/two-factor authentication/i)).toBeVisible()
|
|
61
|
+
await expect(page.getByText(/recommended/i).first()).toBeVisible()
|
|
62
|
+
|
|
63
|
+
// Verify Password option
|
|
64
|
+
await expect(page.getByText('Password').first()).toBeVisible()
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test.describe('Security Settings Journey', () => {
|
|
69
|
+
test.beforeEach(async ({ page }) => {
|
|
70
|
+
const authenticated = await isAuthenticated(page)
|
|
71
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test.afterEach(async ({ page }) => {
|
|
75
|
+
await closeAllDialogs(page)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('should display two-factor authentication option', async ({ page }) => {
|
|
79
|
+
await page.goto('/account')
|
|
80
|
+
|
|
81
|
+
// Verify Two-Factor Authentication card
|
|
82
|
+
await expect(page.getByText(/two-factor authentication/i)).toBeVisible()
|
|
83
|
+
await expect(page.getByText(/add an extra layer of security to your account/i)).toBeVisible()
|
|
84
|
+
|
|
85
|
+
// Verify Enable button
|
|
86
|
+
const enableButton = page.getByRole('button', { name: /enable/i })
|
|
87
|
+
await expect(enableButton).toBeVisible()
|
|
88
|
+
await expect(enableButton).toBeEnabled()
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('should display password option as disabled for OAuth users', async ({ page }) => {
|
|
92
|
+
await page.goto('/account')
|
|
93
|
+
|
|
94
|
+
// Verify Password option
|
|
95
|
+
await expect(page.getByText('Password').first()).toBeVisible()
|
|
96
|
+
await expect(page.getByText(/using oauth login - no password set/i)).toBeVisible()
|
|
97
|
+
|
|
98
|
+
// Verify Change button is disabled
|
|
99
|
+
const changeButton = page.getByRole('button', { name: /change/i })
|
|
100
|
+
await expect(changeButton).toBeVisible()
|
|
101
|
+
await expect(changeButton).toBeDisabled()
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test.describe('Active Sessions Journey', () => {
|
|
106
|
+
test.beforeEach(async ({ page }) => {
|
|
107
|
+
const authenticated = await isAuthenticated(page)
|
|
108
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test.afterEach(async ({ page }) => {
|
|
112
|
+
await closeAllDialogs(page)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('should display active sessions section', async ({ page }) => {
|
|
116
|
+
await page.goto('/account')
|
|
117
|
+
|
|
118
|
+
// Verify Active Sessions heading
|
|
119
|
+
await expect(page.getByRole('heading', { name: /active sessions/i })).toBeVisible()
|
|
120
|
+
|
|
121
|
+
// Verify description
|
|
122
|
+
await expect(page.getByText(/devices where you're currently logged in/i)).toBeVisible()
|
|
123
|
+
|
|
124
|
+
// Verify Sign out all button
|
|
125
|
+
const signOutAllButton = page.getByRole('button', { name: /sign out all/i })
|
|
126
|
+
await expect(signOutAllButton).toBeVisible()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('should display current session with badge', async ({ page }) => {
|
|
130
|
+
await page.goto('/account')
|
|
131
|
+
|
|
132
|
+
// Verify current session is marked
|
|
133
|
+
await expect(page.getByText('Current', { exact: true })).toBeVisible()
|
|
134
|
+
|
|
135
|
+
// Verify device info is shown
|
|
136
|
+
await expect(page.getByText(/chrome on macos/i)).toBeVisible()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('should display other sessions', async ({ page }) => {
|
|
140
|
+
await page.goto('/account')
|
|
141
|
+
|
|
142
|
+
// Verify other session is shown
|
|
143
|
+
await expect(page.getByText(/safari on iphone/i)).toBeVisible()
|
|
144
|
+
|
|
145
|
+
// Verify location and time info
|
|
146
|
+
await expect(page.getByText(/san francisco, ca/i).first()).toBeVisible()
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test.describe('API Access Journey', () => {
|
|
151
|
+
test.beforeEach(async ({ page }) => {
|
|
152
|
+
const authenticated = await isAuthenticated(page)
|
|
153
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test.afterEach(async ({ page }) => {
|
|
157
|
+
await closeAllDialogs(page)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
test('should display API access section', async ({ page }) => {
|
|
161
|
+
await page.goto('/account')
|
|
162
|
+
|
|
163
|
+
// Verify API Access heading
|
|
164
|
+
await expect(page.getByRole('heading', { name: /api access/i })).toBeVisible()
|
|
165
|
+
|
|
166
|
+
// Verify description
|
|
167
|
+
await expect(page.getByText(/manage api keys for programmatic access/i)).toBeVisible()
|
|
168
|
+
|
|
169
|
+
// Verify Create Key button
|
|
170
|
+
const createKeyButton = page.getByRole('button', { name: /create key/i })
|
|
171
|
+
await expect(createKeyButton).toBeVisible()
|
|
172
|
+
await expect(createKeyButton).toBeEnabled()
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
test('should display empty state for API keys', async ({ page }) => {
|
|
176
|
+
await page.goto('/account')
|
|
177
|
+
|
|
178
|
+
// Verify empty state message
|
|
179
|
+
await expect(page.getByText(/no api keys created yet/i)).toBeVisible()
|
|
180
|
+
await expect(page.getByText(/create a key to get started with the api/i)).toBeVisible()
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test.describe('Danger Zone Journey', () => {
|
|
185
|
+
test.beforeEach(async ({ page }) => {
|
|
186
|
+
const authenticated = await isAuthenticated(page)
|
|
187
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test.afterEach(async ({ page }) => {
|
|
191
|
+
await closeAllDialogs(page)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
test('should display danger zone section', async ({ page }) => {
|
|
195
|
+
await page.goto('/account')
|
|
196
|
+
|
|
197
|
+
// Verify Danger Zone heading
|
|
198
|
+
await expect(page.getByRole('heading', { name: /danger zone/i })).toBeVisible()
|
|
199
|
+
|
|
200
|
+
// Verify description
|
|
201
|
+
await expect(page.getByText(/irreversible and destructive actions/i)).toBeVisible()
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
test('should display export data option', async ({ page }) => {
|
|
205
|
+
await page.goto('/account')
|
|
206
|
+
|
|
207
|
+
// Verify Export Data option
|
|
208
|
+
await expect(page.getByText('Export Data')).toBeVisible()
|
|
209
|
+
await expect(page.getByText(/download a copy of all your data/i)).toBeVisible()
|
|
210
|
+
|
|
211
|
+
// Verify Export button
|
|
212
|
+
const exportButton = page.getByRole('button', { name: 'Export' })
|
|
213
|
+
await expect(exportButton).toBeVisible()
|
|
214
|
+
await expect(exportButton).toBeEnabled()
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
test('should display delete account option', async ({ page }) => {
|
|
218
|
+
await page.goto('/account')
|
|
219
|
+
|
|
220
|
+
// Verify Delete Account option
|
|
221
|
+
await expect(page.getByText('Delete Account').first()).toBeVisible()
|
|
222
|
+
await expect(page.getByText(/permanently delete your account and data/i)).toBeVisible()
|
|
223
|
+
|
|
224
|
+
// Verify Delete button
|
|
225
|
+
const deleteButton = page.getByRole('button', { name: 'Delete' }).first()
|
|
226
|
+
await expect(deleteButton).toBeVisible()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test('should open delete account confirmation dialog', async ({ page }) => {
|
|
230
|
+
await page.goto('/account')
|
|
231
|
+
|
|
232
|
+
// Click Delete button
|
|
233
|
+
const deleteButton = page.getByRole('button', { name: 'Delete' }).first()
|
|
234
|
+
await deleteButton.click()
|
|
235
|
+
|
|
236
|
+
// Verify dialog opens
|
|
237
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
238
|
+
await expect(page.getByRole('heading', { name: /delete account/i })).toBeVisible()
|
|
239
|
+
|
|
240
|
+
// Verify warning message
|
|
241
|
+
await expect(page.getByText(/this action cannot be undone/i)).toBeVisible()
|
|
242
|
+
await expect(page.getByText(/all your data will be permanently deleted/i)).toBeVisible()
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
test('should require email confirmation for account deletion', async ({ page }) => {
|
|
246
|
+
await page.goto('/account')
|
|
247
|
+
|
|
248
|
+
// Open delete dialog
|
|
249
|
+
await page.getByRole('button', { name: 'Delete' }).first().click()
|
|
250
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
251
|
+
|
|
252
|
+
// Verify Delete Account button is disabled initially
|
|
253
|
+
const confirmDeleteButton = page.getByRole('button', { name: 'Delete Account' })
|
|
254
|
+
await expect(confirmDeleteButton).toBeDisabled()
|
|
255
|
+
|
|
256
|
+
// Type incorrect email
|
|
257
|
+
const confirmInput = page.getByPlaceholder(/enter your email/i)
|
|
258
|
+
await confirmInput.fill('wrong@email.com')
|
|
259
|
+
|
|
260
|
+
// Button should still be disabled
|
|
261
|
+
await expect(confirmDeleteButton).toBeDisabled()
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
test('should cancel account deletion', async ({ page }) => {
|
|
265
|
+
await page.goto('/account')
|
|
266
|
+
|
|
267
|
+
// Open delete dialog
|
|
268
|
+
await page.getByRole('button', { name: 'Delete' }).first().click()
|
|
269
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
270
|
+
|
|
271
|
+
// Click Cancel
|
|
272
|
+
await page.getByRole('button', { name: 'Cancel' }).click()
|
|
273
|
+
|
|
274
|
+
// Verify dialog is closed
|
|
275
|
+
await expect(page.getByRole('dialog')).not.toBeVisible()
|
|
276
|
+
|
|
277
|
+
// Verify we're still on account page
|
|
278
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
279
|
+
})
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
test.describe('Account Navigation Journey', () => {
|
|
283
|
+
test.beforeEach(async ({ page }) => {
|
|
284
|
+
const authenticated = await isAuthenticated(page)
|
|
285
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
test.afterEach(async ({ page }) => {
|
|
289
|
+
await closeAllDialogs(page)
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
test('should navigate from account to other pages and back', async ({ page }) => {
|
|
293
|
+
// Start at account
|
|
294
|
+
await page.goto('/account')
|
|
295
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
296
|
+
|
|
297
|
+
// Navigate to dashboard
|
|
298
|
+
await page.goto('/dashboard')
|
|
299
|
+
await expect(page).toHaveURL(/dashboard/)
|
|
300
|
+
|
|
301
|
+
// Return to account
|
|
302
|
+
await page.goto('/account')
|
|
303
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
304
|
+
|
|
305
|
+
// Navigate to settings
|
|
306
|
+
await page.goto('/settings')
|
|
307
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
308
|
+
|
|
309
|
+
// Return to account
|
|
310
|
+
await page.goto('/account')
|
|
311
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
312
|
+
})
|
|
313
|
+
})
|
|
314
|
+
})
|