@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,410 @@
|
|
|
1
|
+
import { test, expect, isAuthenticated, waitForNavigation, closeAllDialogs, apiRequest, getAccountId } from '../fixtures'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Team Collaboration Journey Tests
|
|
5
|
+
*
|
|
6
|
+
* These tests verify complete team collaboration user flows,
|
|
7
|
+
* including team management, member invitations, and navigation.
|
|
8
|
+
*
|
|
9
|
+
* @tags @critical @journey @team
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
test.describe('Team Collaboration Journeys @critical @journey @team', () => {
|
|
13
|
+
test.describe('Team 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 team dashboard with member count', async ({ page }) => {
|
|
24
|
+
await page.goto('/team')
|
|
25
|
+
|
|
26
|
+
// Verify team page loads with main heading
|
|
27
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
28
|
+
|
|
29
|
+
// Verify description text is present
|
|
30
|
+
await expect(page.getByText(/manage your team and invite new members/i)).toBeVisible()
|
|
31
|
+
|
|
32
|
+
// Verify Active Members card is displayed
|
|
33
|
+
await expect(page.getByText(/active members/i)).toBeVisible()
|
|
34
|
+
|
|
35
|
+
// Verify member count is shown (e.g., "1 member in your workspace" or "2 members in your workspace")
|
|
36
|
+
await expect(page.getByText(/member[s]? in your workspace/i)).toBeVisible()
|
|
37
|
+
|
|
38
|
+
// Verify the invite member button is present and enabled (use first() due to nested button structure)
|
|
39
|
+
const inviteButton = page.locator('button').filter({ hasText: 'Invite Member' }).first()
|
|
40
|
+
await expect(inviteButton).toBeVisible()
|
|
41
|
+
await expect(inviteButton).toBeEnabled()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('should show team member list with details', async ({ page }) => {
|
|
45
|
+
await page.goto('/team')
|
|
46
|
+
|
|
47
|
+
// Verify the team members list section is visible
|
|
48
|
+
await expect(page.getByText(/active members/i)).toBeVisible()
|
|
49
|
+
|
|
50
|
+
// Verify at least one member row is displayed
|
|
51
|
+
const memberList = page.locator('[class*="divide-y"]').first()
|
|
52
|
+
await expect(memberList).toBeVisible()
|
|
53
|
+
|
|
54
|
+
// Verify member details are shown (avatar area exists)
|
|
55
|
+
const memberRows = memberList.locator('> div')
|
|
56
|
+
await expect(memberRows.first()).toBeVisible()
|
|
57
|
+
|
|
58
|
+
// Verify member name is displayed
|
|
59
|
+
const memberName = page.locator('.font-medium').first()
|
|
60
|
+
await expect(memberName).toBeVisible()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('should identify current user as owner/admin', async ({ page }) => {
|
|
64
|
+
await page.goto('/team')
|
|
65
|
+
|
|
66
|
+
// Verify current user is marked with "(you)" indicator
|
|
67
|
+
await expect(page.getByText('(you)')).toBeVisible()
|
|
68
|
+
|
|
69
|
+
// Verify owner role badge is displayed for the current user
|
|
70
|
+
const ownerBadge = page.locator('.capitalize').filter({ hasText: /owner/i })
|
|
71
|
+
await expect(ownerBadge).toBeVisible()
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test.describe('Member Invitation Journey', () => {
|
|
76
|
+
test.beforeEach(async ({ page }) => {
|
|
77
|
+
const authenticated = await isAuthenticated(page)
|
|
78
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test.afterEach(async ({ page }) => {
|
|
82
|
+
await closeAllDialogs(page)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('should complete invitation dialog opening', async ({ page }) => {
|
|
86
|
+
await page.goto('/team')
|
|
87
|
+
|
|
88
|
+
// Wait for page to fully load
|
|
89
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
90
|
+
|
|
91
|
+
// Click the invite member button (use first() due to nested button structure)
|
|
92
|
+
const inviteButton = page.locator('button').filter({ hasText: 'Invite Member' }).first()
|
|
93
|
+
await expect(inviteButton).toBeVisible()
|
|
94
|
+
await inviteButton.click()
|
|
95
|
+
|
|
96
|
+
// Verify dialog opens
|
|
97
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
98
|
+
|
|
99
|
+
// Verify dialog has the correct title
|
|
100
|
+
await expect(page.getByRole('heading', { name: /invite team member/i })).toBeVisible()
|
|
101
|
+
|
|
102
|
+
// Verify dialog description is shown
|
|
103
|
+
await expect(page.getByText(/send an invitation to join your workspace/i)).toBeVisible()
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('should show role selection options in invite dialog', async ({ page }) => {
|
|
107
|
+
await page.goto('/team')
|
|
108
|
+
|
|
109
|
+
// Wait for page to fully load
|
|
110
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
111
|
+
|
|
112
|
+
// Open invite dialog (use first() due to nested button structure)
|
|
113
|
+
await page.locator('button').filter({ hasText: 'Invite Member' }).first().click()
|
|
114
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
115
|
+
|
|
116
|
+
// Verify Member role button is visible
|
|
117
|
+
const memberRoleButton = page.getByRole('button', { name: /^member$/i })
|
|
118
|
+
await expect(memberRoleButton).toBeVisible()
|
|
119
|
+
|
|
120
|
+
// Verify Admin role button is visible
|
|
121
|
+
const adminRoleButton = page.getByRole('button', { name: /^admin$/i })
|
|
122
|
+
await expect(adminRoleButton).toBeVisible()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('should display role descriptions when selecting roles', async ({ page }) => {
|
|
126
|
+
await page.goto('/team')
|
|
127
|
+
|
|
128
|
+
// Wait for page to fully load
|
|
129
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
130
|
+
|
|
131
|
+
// Open invite dialog (use first() due to nested button structure)
|
|
132
|
+
await page.locator('button').filter({ hasText: 'Invite Member' }).first().click()
|
|
133
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
134
|
+
|
|
135
|
+
// Member role is default - verify member description is shown
|
|
136
|
+
await expect(page.getByText(/members can view and collaborate/i)).toBeVisible()
|
|
137
|
+
|
|
138
|
+
// Click Admin role button
|
|
139
|
+
const adminRoleButton = page.getByRole('button', { name: /^admin$/i })
|
|
140
|
+
await adminRoleButton.click()
|
|
141
|
+
|
|
142
|
+
// Verify admin role description is now shown
|
|
143
|
+
await expect(page.getByText(/admins can manage team settings/i)).toBeVisible()
|
|
144
|
+
|
|
145
|
+
// Click Member role button again
|
|
146
|
+
const memberRoleButton = page.getByRole('button', { name: /^member$/i })
|
|
147
|
+
await memberRoleButton.click()
|
|
148
|
+
|
|
149
|
+
// Verify member description is shown again
|
|
150
|
+
await expect(page.getByText(/members can view and collaborate/i)).toBeVisible()
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
test('should enable send button only with valid email', async ({ page }) => {
|
|
154
|
+
await page.goto('/team')
|
|
155
|
+
|
|
156
|
+
// Wait for page to fully load
|
|
157
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
158
|
+
|
|
159
|
+
// Open invite dialog (use first() due to nested button structure)
|
|
160
|
+
await page.locator('button').filter({ hasText: 'Invite Member' }).first().click()
|
|
161
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
162
|
+
|
|
163
|
+
// Verify Send Invitation button is initially disabled (no email)
|
|
164
|
+
const sendButton = page.getByRole('button', { name: /send invitation/i })
|
|
165
|
+
await expect(sendButton).toBeDisabled()
|
|
166
|
+
|
|
167
|
+
// Enter a valid email
|
|
168
|
+
const emailInput = page.getByLabel(/email address/i)
|
|
169
|
+
await expect(emailInput).toBeVisible()
|
|
170
|
+
await emailInput.fill('test-invite@example.com')
|
|
171
|
+
|
|
172
|
+
// Verify Send Invitation button is now enabled
|
|
173
|
+
await expect(sendButton).toBeEnabled()
|
|
174
|
+
|
|
175
|
+
// Clear the email
|
|
176
|
+
await emailInput.clear()
|
|
177
|
+
|
|
178
|
+
// Verify Send Invitation button is disabled again
|
|
179
|
+
await expect(sendButton).toBeDisabled()
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
test('should cancel invitation without sending', async ({ page }) => {
|
|
183
|
+
await page.goto('/team')
|
|
184
|
+
|
|
185
|
+
// Wait for page to fully load
|
|
186
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
187
|
+
|
|
188
|
+
// Open invite dialog (use first() due to nested button structure)
|
|
189
|
+
await page.locator('button').filter({ hasText: 'Invite Member' }).first().click()
|
|
190
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
191
|
+
|
|
192
|
+
// Fill in email (to simulate a partial flow)
|
|
193
|
+
const emailInput = page.getByLabel(/email address/i)
|
|
194
|
+
await emailInput.fill('cancel-test@example.com')
|
|
195
|
+
|
|
196
|
+
// Select Admin role
|
|
197
|
+
const adminRoleButton = page.getByRole('button', { name: /^admin$/i })
|
|
198
|
+
await adminRoleButton.click()
|
|
199
|
+
|
|
200
|
+
// Click Cancel button
|
|
201
|
+
const cancelButton = page.getByRole('button', { name: /cancel/i })
|
|
202
|
+
await expect(cancelButton).toBeVisible()
|
|
203
|
+
await cancelButton.click()
|
|
204
|
+
|
|
205
|
+
// Verify dialog is closed without sending invitation
|
|
206
|
+
await expect(page.getByRole('dialog')).not.toBeVisible()
|
|
207
|
+
|
|
208
|
+
// Verify we're still on the team page
|
|
209
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
test.describe('Pending Invitations Journey', () => {
|
|
214
|
+
test.beforeEach(async ({ page }) => {
|
|
215
|
+
const authenticated = await isAuthenticated(page)
|
|
216
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
test.afterEach(async ({ page }) => {
|
|
220
|
+
await closeAllDialogs(page)
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
test('should display pending invitations section', async ({ page }) => {
|
|
224
|
+
await page.goto('/team')
|
|
225
|
+
|
|
226
|
+
// Check if pending invitations section exists
|
|
227
|
+
const pendingSection = page.getByText(/pending invitation/i)
|
|
228
|
+
const pendingCount = await pendingSection.count()
|
|
229
|
+
|
|
230
|
+
// If pending invitations exist, verify the section structure
|
|
231
|
+
if (pendingCount > 0) {
|
|
232
|
+
await expect(pendingSection.first()).toBeVisible()
|
|
233
|
+
|
|
234
|
+
// Verify the section has a description about pending count
|
|
235
|
+
await expect(page.getByText(/\d+ pending invitation/i)).toBeVisible()
|
|
236
|
+
}
|
|
237
|
+
// Test passes if no pending invitations (UI adapts accordingly)
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
test('should show invitation details when present', async ({ page }) => {
|
|
241
|
+
await page.goto('/team')
|
|
242
|
+
|
|
243
|
+
// Check for pending invitations section
|
|
244
|
+
const pendingSection = page.getByRole('heading', { name: /pending invitation/i })
|
|
245
|
+
const hasPending = await pendingSection.isVisible({ timeout: 2000 }).catch(() => false)
|
|
246
|
+
|
|
247
|
+
if (hasPending) {
|
|
248
|
+
// Verify invitation email is displayed
|
|
249
|
+
const invitationEmail = page.getByText(/@example\.com|@.*\.\w+/)
|
|
250
|
+
await expect(invitationEmail.first()).toBeVisible()
|
|
251
|
+
|
|
252
|
+
// Verify expiry information is shown
|
|
253
|
+
const expiryText = page.getByText(/expires in \d+ day/i)
|
|
254
|
+
await expect(expiryText.first()).toBeVisible()
|
|
255
|
+
|
|
256
|
+
// Verify Pending badge is visible
|
|
257
|
+
const pendingBadge = page.locator('[class*="Badge"]').filter({ hasText: /pending/i })
|
|
258
|
+
await expect(pendingBadge.first()).toBeVisible()
|
|
259
|
+
}
|
|
260
|
+
// Test passes if no pending invitations
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
test('should show revoke option for pending invitations', async ({ page }) => {
|
|
264
|
+
await page.goto('/team')
|
|
265
|
+
|
|
266
|
+
// Check for pending invitations section
|
|
267
|
+
const pendingSection = page.getByRole('heading', { name: /pending invitation/i })
|
|
268
|
+
const hasPending = await pendingSection.isVisible({ timeout: 2000 }).catch(() => false)
|
|
269
|
+
|
|
270
|
+
if (hasPending) {
|
|
271
|
+
// Verify Revoke button is visible for pending invitations
|
|
272
|
+
const revokeButton = page.getByRole('button', { name: /revoke/i })
|
|
273
|
+
await expect(revokeButton.first()).toBeVisible()
|
|
274
|
+
|
|
275
|
+
// Verify Resend button is also available
|
|
276
|
+
const resendButton = page.getByRole('button', { name: /resend/i })
|
|
277
|
+
await expect(resendButton.first()).toBeVisible()
|
|
278
|
+
}
|
|
279
|
+
// Test passes if no pending invitations
|
|
280
|
+
})
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
test.describe('Member Management Journey', () => {
|
|
284
|
+
test.beforeEach(async ({ page }) => {
|
|
285
|
+
const authenticated = await isAuthenticated(page)
|
|
286
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
test.afterEach(async ({ page }) => {
|
|
290
|
+
await closeAllDialogs(page)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('should show member action menu', async ({ page }) => {
|
|
294
|
+
await page.goto('/team')
|
|
295
|
+
|
|
296
|
+
// Verify team members section is visible
|
|
297
|
+
await expect(page.getByText(/active members/i)).toBeVisible()
|
|
298
|
+
|
|
299
|
+
// Look for action menu button (three dots) for non-current-user members
|
|
300
|
+
// Note: The current user doesn't have an action menu
|
|
301
|
+
const actionButtons = page.locator('button').filter({ has: page.locator('[class*="more"]') })
|
|
302
|
+
const actionCount = await actionButtons.count()
|
|
303
|
+
|
|
304
|
+
// If there are other team members, action buttons should be visible
|
|
305
|
+
if (actionCount > 0) {
|
|
306
|
+
await expect(actionButtons.first()).toBeVisible()
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Verify current user is displayed without action menu
|
|
310
|
+
await expect(page.getByText('(you)')).toBeVisible()
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
test('should navigate from team to member settings', async ({ page }) => {
|
|
314
|
+
// Start at team page
|
|
315
|
+
await page.goto('/team')
|
|
316
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
317
|
+
|
|
318
|
+
// Verify settings link is present in navigation
|
|
319
|
+
const settingsLink = page.getByRole('link', { name: /settings/i })
|
|
320
|
+
await expect(settingsLink).toBeVisible()
|
|
321
|
+
|
|
322
|
+
// Navigate to settings page directly (more reliable than clicking)
|
|
323
|
+
await page.goto('/settings')
|
|
324
|
+
await expect(page).not.toHaveURL(/login/)
|
|
325
|
+
|
|
326
|
+
// Verify settings page loaded
|
|
327
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
328
|
+
|
|
329
|
+
// Verify profile tab is visible (Profile tab contains icon + text)
|
|
330
|
+
const profileTab = page.getByRole('tab').filter({ hasText: /profile/i })
|
|
331
|
+
await expect(profileTab).toBeVisible()
|
|
332
|
+
|
|
333
|
+
// Verify account tab is visible
|
|
334
|
+
const accountTab = page.getByRole('tab').filter({ hasText: /account/i })
|
|
335
|
+
await expect(accountTab).toBeVisible()
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
test.describe('Team to Dashboard Navigation', () => {
|
|
340
|
+
test.beforeEach(async ({ page }) => {
|
|
341
|
+
const authenticated = await isAuthenticated(page)
|
|
342
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
test.afterEach(async ({ page }) => {
|
|
346
|
+
await closeAllDialogs(page)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
test('should navigate from dashboard to team and back', async ({ page }) => {
|
|
350
|
+
// Start at dashboard
|
|
351
|
+
await page.goto('/dashboard')
|
|
352
|
+
await expect(page).not.toHaveURL(/login/)
|
|
353
|
+
await expect(page).toHaveURL(/dashboard/)
|
|
354
|
+
|
|
355
|
+
// Wait for dashboard to load
|
|
356
|
+
await expect(page.getByRole('navigation')).toBeVisible()
|
|
357
|
+
|
|
358
|
+
// Verify team link is visible
|
|
359
|
+
const teamLink = page.getByRole('link', { name: /team/i })
|
|
360
|
+
await expect(teamLink).toBeVisible()
|
|
361
|
+
|
|
362
|
+
// Navigate to team page directly
|
|
363
|
+
await page.goto('/team')
|
|
364
|
+
await expect(page).not.toHaveURL(/login/)
|
|
365
|
+
|
|
366
|
+
// Verify team page loaded
|
|
367
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
368
|
+
|
|
369
|
+
// Verify dashboard link is visible
|
|
370
|
+
const dashboardLink = page.getByRole('link', { name: /dashboard/i })
|
|
371
|
+
await expect(dashboardLink).toBeVisible()
|
|
372
|
+
|
|
373
|
+
// Navigate back to dashboard
|
|
374
|
+
await page.goto('/dashboard')
|
|
375
|
+
await expect(page).toHaveURL(/dashboard/)
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
test('should maintain team context across navigation', async ({ page }) => {
|
|
379
|
+
// Start at team page and verify initial state
|
|
380
|
+
await page.goto('/team')
|
|
381
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
382
|
+
|
|
383
|
+
// Verify team member is displayed
|
|
384
|
+
await expect(page.getByText('(you)')).toBeVisible()
|
|
385
|
+
|
|
386
|
+
// Verify navigation links are present
|
|
387
|
+
await expect(page.getByRole('link', { name: /settings/i })).toBeVisible()
|
|
388
|
+
await expect(page.getByRole('link', { name: /integrations/i })).toBeVisible()
|
|
389
|
+
|
|
390
|
+
// Navigate to settings page directly
|
|
391
|
+
await page.goto('/settings')
|
|
392
|
+
await expect(page).not.toHaveURL(/login/)
|
|
393
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
394
|
+
|
|
395
|
+
// Navigate to integrations page directly
|
|
396
|
+
await page.goto('/integrations')
|
|
397
|
+
await expect(page).not.toHaveURL(/login/)
|
|
398
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
399
|
+
|
|
400
|
+
// Return to team page
|
|
401
|
+
await page.goto('/team')
|
|
402
|
+
await expect(page).not.toHaveURL(/login/)
|
|
403
|
+
|
|
404
|
+
// Verify team page content is still correct
|
|
405
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
406
|
+
await expect(page.getByText('(you)')).toBeVisible()
|
|
407
|
+
await expect(page.getByText(/active members/i)).toBeVisible()
|
|
408
|
+
})
|
|
409
|
+
})
|
|
410
|
+
})
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { test, expect, isAuthenticated } from '../fixtures'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mobile Responsive Journey Tests
|
|
5
|
+
*
|
|
6
|
+
* These tests verify that the application works correctly
|
|
7
|
+
* on mobile viewports and handles responsive design properly.
|
|
8
|
+
*
|
|
9
|
+
* @tags @mobile @responsive
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Define mobile viewport
|
|
13
|
+
const mobileViewport = { width: 375, height: 667 } // iPhone SE
|
|
14
|
+
|
|
15
|
+
test.describe('Mobile Responsive - Public Pages @mobile @responsive', () => {
|
|
16
|
+
test.use({ viewport: mobileViewport })
|
|
17
|
+
|
|
18
|
+
test('login page should be usable on mobile', async ({ page }) => {
|
|
19
|
+
await page.goto('/login')
|
|
20
|
+
|
|
21
|
+
// Verify login page loads correctly on mobile
|
|
22
|
+
await expect(page.getByText('Welcome back')).toBeVisible()
|
|
23
|
+
|
|
24
|
+
// Verify OAuth button is visible and tappable
|
|
25
|
+
const googleOAuthButton = page.getByRole('button', { name: /continue with google/i })
|
|
26
|
+
await expect(googleOAuthButton).toBeVisible()
|
|
27
|
+
await expect(googleOAuthButton).toBeEnabled()
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test.describe('Mobile Responsive - Authenticated Pages @mobile @responsive', () => {
|
|
32
|
+
test.use({ viewport: mobileViewport })
|
|
33
|
+
|
|
34
|
+
test.beforeEach(async ({ page }) => {
|
|
35
|
+
const authenticated = await isAuthenticated(page)
|
|
36
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('dashboard should be responsive on mobile', async ({ page }) => {
|
|
40
|
+
await page.goto('/dashboard')
|
|
41
|
+
|
|
42
|
+
// Verify page loads
|
|
43
|
+
await expect(page).not.toHaveURL(/login/)
|
|
44
|
+
|
|
45
|
+
// Verify main content is visible
|
|
46
|
+
await expect(page.getByRole('main')).toBeVisible()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('team page should be responsive on mobile', async ({ page }) => {
|
|
50
|
+
await page.goto('/team')
|
|
51
|
+
|
|
52
|
+
// Verify page loads
|
|
53
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
54
|
+
|
|
55
|
+
// Verify Invite Member button is accessible
|
|
56
|
+
const inviteButton = page.locator('button').filter({ hasText: 'Invite Member' }).first()
|
|
57
|
+
await expect(inviteButton).toBeVisible()
|
|
58
|
+
|
|
59
|
+
// Verify team member count is visible
|
|
60
|
+
await expect(page.getByText(/active members/i)).toBeVisible()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('invite dialog should work on mobile', async ({ page }) => {
|
|
64
|
+
await page.goto('/team')
|
|
65
|
+
|
|
66
|
+
// Open invite dialog
|
|
67
|
+
await page.locator('button').filter({ hasText: 'Invite Member' }).first().click()
|
|
68
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
69
|
+
|
|
70
|
+
// Verify dialog is usable on mobile
|
|
71
|
+
const emailInput = page.getByLabel(/email address/i)
|
|
72
|
+
await expect(emailInput).toBeVisible()
|
|
73
|
+
await emailInput.fill('mobile-test@example.com')
|
|
74
|
+
|
|
75
|
+
// Verify buttons are tappable
|
|
76
|
+
const sendButton = page.getByRole('button', { name: /send invitation/i })
|
|
77
|
+
await expect(sendButton).toBeEnabled()
|
|
78
|
+
|
|
79
|
+
// Close dialog
|
|
80
|
+
await page.getByRole('button', { name: /cancel/i }).click()
|
|
81
|
+
await expect(page.getByRole('dialog')).not.toBeVisible()
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('settings page should be responsive on mobile', async ({ page }) => {
|
|
85
|
+
await page.goto('/settings')
|
|
86
|
+
|
|
87
|
+
// Verify page loads
|
|
88
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
89
|
+
|
|
90
|
+
// Verify tabs are accessible
|
|
91
|
+
const profileTab = page.getByRole('tab', { name: /profile/i })
|
|
92
|
+
await expect(profileTab).toBeVisible()
|
|
93
|
+
|
|
94
|
+
// Verify form inputs are accessible
|
|
95
|
+
const nameInput = page.getByLabel(/full name/i)
|
|
96
|
+
await expect(nameInput).toBeVisible()
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('integrations page should be responsive on mobile', async ({ page }) => {
|
|
100
|
+
await page.goto('/integrations')
|
|
101
|
+
|
|
102
|
+
// Verify page loads
|
|
103
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
104
|
+
|
|
105
|
+
// Verify search is accessible
|
|
106
|
+
const searchInput = page.getByPlaceholder(/search integrations/i)
|
|
107
|
+
await expect(searchInput).toBeVisible()
|
|
108
|
+
|
|
109
|
+
// Verify integration cards are visible
|
|
110
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('account page should be responsive on mobile', async ({ page }) => {
|
|
114
|
+
await page.goto('/account')
|
|
115
|
+
|
|
116
|
+
// Verify page loads
|
|
117
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
118
|
+
|
|
119
|
+
// Verify key sections are visible
|
|
120
|
+
await expect(page.getByRole('heading', { name: /connected accounts/i })).toBeVisible()
|
|
121
|
+
await expect(page.getByRole('heading', { name: /^security$/i })).toBeVisible()
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('navigation should work on mobile', async ({ page }) => {
|
|
125
|
+
// Start at dashboard
|
|
126
|
+
await page.goto('/dashboard')
|
|
127
|
+
await expect(page).not.toHaveURL(/login/)
|
|
128
|
+
|
|
129
|
+
// Navigate to team
|
|
130
|
+
await page.goto('/team')
|
|
131
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
132
|
+
|
|
133
|
+
// Navigate to settings
|
|
134
|
+
await page.goto('/settings')
|
|
135
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
136
|
+
|
|
137
|
+
// Navigate to integrations
|
|
138
|
+
await page.goto('/integrations')
|
|
139
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
140
|
+
|
|
141
|
+
// Navigate to account
|
|
142
|
+
await page.goto('/account')
|
|
143
|
+
await expect(page.getByRole('heading', { name: /^account$/i, level: 1 })).toBeVisible()
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test.describe('Tablet Responsive Journeys @tablet @responsive', () => {
|
|
148
|
+
test.use({ viewport: { width: 768, height: 1024 } }) // iPad
|
|
149
|
+
|
|
150
|
+
test.beforeEach(async ({ page }) => {
|
|
151
|
+
const authenticated = await isAuthenticated(page)
|
|
152
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
test('dashboard should work on tablet', async ({ page }) => {
|
|
156
|
+
await page.goto('/dashboard')
|
|
157
|
+
await expect(page).not.toHaveURL(/login/)
|
|
158
|
+
await expect(page.getByRole('main')).toBeVisible()
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('team page should work on tablet', async ({ page }) => {
|
|
162
|
+
await page.goto('/team')
|
|
163
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
164
|
+
await expect(page.getByText(/active members/i)).toBeVisible()
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
test('settings page should work on tablet', async ({ page }) => {
|
|
168
|
+
await page.goto('/settings')
|
|
169
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
170
|
+
await expect(page.getByRole('tab', { name: /profile/i })).toBeVisible()
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test('integrations page should work on tablet', async ({ page }) => {
|
|
174
|
+
await page.goto('/integrations')
|
|
175
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
176
|
+
await expect(page.getByPlaceholder(/search integrations/i)).toBeVisible()
|
|
177
|
+
})
|
|
178
|
+
})
|