@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,307 @@
|
|
|
1
|
+
import { test, expect, isAuthenticated, apiRequest, getAccountId, closeAllDialogs } from '../fixtures'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* File Upload Management Journey Tests
|
|
5
|
+
*
|
|
6
|
+
* These tests verify complete file management flows,
|
|
7
|
+
* including requesting upload URLs, validating file operations,
|
|
8
|
+
* and handling storage errors gracefully.
|
|
9
|
+
*
|
|
10
|
+
* Note: Some tests may skip if R2 storage is not configured.
|
|
11
|
+
*
|
|
12
|
+
* @tags @journey @storage @files
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
test.describe('File Upload Management Journey @journey @storage', () => {
|
|
16
|
+
test.describe('Upload URL Request Flow', () => {
|
|
17
|
+
test.beforeEach(async ({ page }) => {
|
|
18
|
+
const authenticated = await isAuthenticated(page)
|
|
19
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
20
|
+
|
|
21
|
+
const accountId = getAccountId()
|
|
22
|
+
test.skip(!accountId, 'No account ID available')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test.afterEach(async ({ page }) => {
|
|
26
|
+
await closeAllDialogs(page)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('should request upload URL for image file', async ({ page }) => {
|
|
30
|
+
// Step 1: Request upload URL for a JPEG image
|
|
31
|
+
const response = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
32
|
+
data: {
|
|
33
|
+
filename: 'test-image.jpg',
|
|
34
|
+
contentType: 'image/jpeg',
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Step 2: Handle both configured and unconfigured R2 states
|
|
39
|
+
expect([200, 400]).toContain(response.status())
|
|
40
|
+
|
|
41
|
+
const body = await response.json()
|
|
42
|
+
|
|
43
|
+
if (response.status() === 200) {
|
|
44
|
+
// Step 3: Verify successful response structure
|
|
45
|
+
expect(body).toHaveProperty('url')
|
|
46
|
+
expect(body).toHaveProperty('name')
|
|
47
|
+
expect(body).toHaveProperty('publicUrl')
|
|
48
|
+
|
|
49
|
+
// Step 4: Verify URL format
|
|
50
|
+
expect(body.url).toContain('/api/storage/upload/')
|
|
51
|
+
expect(typeof body.publicUrl).toBe('string')
|
|
52
|
+
} else {
|
|
53
|
+
// R2 not configured - verify error structure
|
|
54
|
+
expect(body).toHaveProperty('error')
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('should request upload URL for PNG file', async ({ page }) => {
|
|
59
|
+
// Step 1: Request upload URL for a PNG image
|
|
60
|
+
const response = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
61
|
+
data: {
|
|
62
|
+
filename: 'avatar.png',
|
|
63
|
+
contentType: 'image/png',
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// Step 2: Handle both configured and unconfigured states
|
|
68
|
+
expect([200, 400]).toContain(response.status())
|
|
69
|
+
|
|
70
|
+
const body = await response.json()
|
|
71
|
+
|
|
72
|
+
if (response.status() === 200) {
|
|
73
|
+
expect(body).toHaveProperty('url')
|
|
74
|
+
expect(body.name).toContain('.png')
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('should request upload URL for PDF document', async ({ page }) => {
|
|
79
|
+
// Step 1: Request upload URL for a PDF document
|
|
80
|
+
const response = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
81
|
+
data: {
|
|
82
|
+
filename: 'document.pdf',
|
|
83
|
+
contentType: 'application/pdf',
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
expect([200, 400]).toContain(response.status())
|
|
88
|
+
|
|
89
|
+
const body = await response.json()
|
|
90
|
+
|
|
91
|
+
if (response.status() === 200) {
|
|
92
|
+
expect(body).toHaveProperty('url')
|
|
93
|
+
expect(body.name).toContain('.pdf')
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test.describe('File Validation Flow', () => {
|
|
99
|
+
test.beforeEach(async ({ page }) => {
|
|
100
|
+
const authenticated = await isAuthenticated(page)
|
|
101
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
102
|
+
|
|
103
|
+
const accountId = getAccountId()
|
|
104
|
+
test.skip(!accountId, 'No account ID available')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('should reject upload request with missing filename', async ({ page }) => {
|
|
108
|
+
// Step 1: Request with missing filename
|
|
109
|
+
const response = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
110
|
+
data: {
|
|
111
|
+
contentType: 'image/jpeg',
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// Step 2: Should return validation error
|
|
116
|
+
expect(response.status()).toBe(400)
|
|
117
|
+
|
|
118
|
+
const body = await response.json()
|
|
119
|
+
expect(body).toHaveProperty('error')
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('should reject upload request with missing content type', async ({ page }) => {
|
|
123
|
+
// Step 1: Request with missing content type
|
|
124
|
+
const response = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
125
|
+
data: {
|
|
126
|
+
filename: 'test.jpg',
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Step 2: Should return validation error
|
|
131
|
+
expect(response.status()).toBe(400)
|
|
132
|
+
|
|
133
|
+
const body = await response.json()
|
|
134
|
+
expect(body).toHaveProperty('error')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('should reject upload request with empty body', async ({ page }) => {
|
|
138
|
+
// Step 1: Request with empty body
|
|
139
|
+
const response = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
140
|
+
data: {},
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// Step 2: Should return validation error
|
|
144
|
+
expect(response.status()).toBe(400)
|
|
145
|
+
|
|
146
|
+
const body = await response.json()
|
|
147
|
+
expect(body).toHaveProperty('error')
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
test.describe('File Deletion Flow', () => {
|
|
152
|
+
test.beforeEach(async ({ page }) => {
|
|
153
|
+
const authenticated = await isAuthenticated(page)
|
|
154
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
155
|
+
|
|
156
|
+
const accountId = getAccountId()
|
|
157
|
+
test.skip(!accountId, 'No account ID available')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
test('should return 404 for non-existent file deletion', async ({ page }) => {
|
|
161
|
+
// Step 1: Attempt to delete a non-existent file
|
|
162
|
+
const nonExistentKey = encodeURIComponent('test/non-existent-file-12345.jpg')
|
|
163
|
+
const response = await apiRequest(page, 'delete', `/api/storage/${nonExistentKey}`)
|
|
164
|
+
|
|
165
|
+
// Step 2: Should return 404 (not found) or 400 (R2 not configured)
|
|
166
|
+
expect([404, 400]).toContain(response.status())
|
|
167
|
+
|
|
168
|
+
const body = await response.json()
|
|
169
|
+
expect(body).toHaveProperty('error')
|
|
170
|
+
expect(body.error).toHaveProperty('message')
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test('should handle deletion of randomly named files gracefully', async ({ page }) => {
|
|
174
|
+
// Step 1: Generate random file keys to test deletion
|
|
175
|
+
const randomKeys = [
|
|
176
|
+
`temp/file-${Date.now()}.jpg`,
|
|
177
|
+
`uploads/image-${Math.random().toString(36).substring(7)}.png`,
|
|
178
|
+
`avatars/user-${Date.now()}.webp`,
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
for (const key of randomKeys) {
|
|
182
|
+
const encodedKey = encodeURIComponent(key)
|
|
183
|
+
const response = await apiRequest(page, 'delete', `/api/storage/${encodedKey}`)
|
|
184
|
+
|
|
185
|
+
// Step 2: All should return not found or R2 error
|
|
186
|
+
expect([404, 400]).toContain(response.status())
|
|
187
|
+
|
|
188
|
+
const body = await response.json()
|
|
189
|
+
expect(body).toHaveProperty('error')
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
test.describe('File Upload Error Handling', () => {
|
|
195
|
+
test.beforeEach(async ({ page }) => {
|
|
196
|
+
const authenticated = await isAuthenticated(page)
|
|
197
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
198
|
+
|
|
199
|
+
const accountId = getAccountId()
|
|
200
|
+
test.skip(!accountId, 'No account ID available')
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
test('should return error for upload with empty body', async ({ page }) => {
|
|
204
|
+
// Step 1: Attempt upload with empty body
|
|
205
|
+
const testKey = encodeURIComponent('test/empty-upload.txt')
|
|
206
|
+
const response = await apiRequest(page, 'put', `/api/storage/upload/${testKey}`, {
|
|
207
|
+
headers: {
|
|
208
|
+
'content-type': 'text/plain',
|
|
209
|
+
},
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
// Step 2: Should return 400 error
|
|
213
|
+
expect(response.status()).toBe(400)
|
|
214
|
+
|
|
215
|
+
const body = await response.json()
|
|
216
|
+
expect(body).toHaveProperty('error')
|
|
217
|
+
expect(body.error).toHaveProperty('message')
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test.describe('Profile Picture Upload Journey', () => {
|
|
222
|
+
test.beforeEach(async ({ page }) => {
|
|
223
|
+
const authenticated = await isAuthenticated(page)
|
|
224
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
test.afterEach(async ({ page }) => {
|
|
228
|
+
await closeAllDialogs(page)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
test('should display profile picture section in settings', async ({ page }) => {
|
|
232
|
+
// Step 1: Navigate to settings page
|
|
233
|
+
await page.goto('/settings')
|
|
234
|
+
await expect(page.getByRole('heading', { name: /settings/i })).toBeVisible()
|
|
235
|
+
|
|
236
|
+
// Step 2: Verify Profile Picture section exists
|
|
237
|
+
await expect(page.getByRole('heading', { name: 'Profile Picture' })).toBeVisible()
|
|
238
|
+
|
|
239
|
+
// Step 3: Verify Change Photo button is present
|
|
240
|
+
const changePhotoButton = page.getByRole('button', { name: /change photo/i })
|
|
241
|
+
await expect(changePhotoButton).toBeVisible()
|
|
242
|
+
await expect(changePhotoButton).toBeEnabled()
|
|
243
|
+
|
|
244
|
+
// Step 4: Verify file size limit hint
|
|
245
|
+
await expect(page.getByText(/max 2mb/i)).toBeVisible()
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('should have file input for profile picture upload', async ({ page }) => {
|
|
249
|
+
// Step 1: Navigate to settings page
|
|
250
|
+
await page.goto('/settings')
|
|
251
|
+
|
|
252
|
+
// Step 2: Verify hidden file input exists
|
|
253
|
+
const fileInput = page.locator('input[type="file"]')
|
|
254
|
+
await expect(fileInput).toHaveCount(1)
|
|
255
|
+
|
|
256
|
+
// Step 3: Verify file input accepts images
|
|
257
|
+
const acceptAttr = await fileInput.getAttribute('accept')
|
|
258
|
+
expect(acceptAttr).toContain('image/')
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
test.describe('Complete File Management Workflow', () => {
|
|
263
|
+
test.beforeEach(async ({ page }) => {
|
|
264
|
+
const authenticated = await isAuthenticated(page)
|
|
265
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
266
|
+
|
|
267
|
+
const accountId = getAccountId()
|
|
268
|
+
test.skip(!accountId, 'No account ID available')
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
test('complete file management workflow via API', async ({ page }) => {
|
|
272
|
+
// Step 1: Request upload URL
|
|
273
|
+
const uploadUrlResponse = await apiRequest(page, 'post', '/api/storage/upload-url', {
|
|
274
|
+
data: {
|
|
275
|
+
filename: `workflow-test-${Date.now()}.jpg`,
|
|
276
|
+
contentType: 'image/jpeg',
|
|
277
|
+
},
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
// Step 2: Handle R2 configuration state
|
|
281
|
+
if (uploadUrlResponse.status() === 400) {
|
|
282
|
+
// R2 not configured - test passes with graceful handling
|
|
283
|
+
const body = await uploadUrlResponse.json()
|
|
284
|
+
expect(body).toHaveProperty('error')
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
expect(uploadUrlResponse.status()).toBe(200)
|
|
289
|
+
const uploadData = await uploadUrlResponse.json()
|
|
290
|
+
|
|
291
|
+
// Step 3: Verify upload URL structure
|
|
292
|
+
expect(uploadData).toHaveProperty('url')
|
|
293
|
+
expect(uploadData).toHaveProperty('name')
|
|
294
|
+
expect(uploadData).toHaveProperty('publicUrl')
|
|
295
|
+
|
|
296
|
+
// Step 4: Verify the file key format
|
|
297
|
+
expect(uploadData.name).toMatch(/^[a-zA-Z0-9-_/.]+$/)
|
|
298
|
+
|
|
299
|
+
// Step 5: Try to delete the file (cleanup)
|
|
300
|
+
const encodedKey = encodeURIComponent(uploadData.name)
|
|
301
|
+
const deleteResponse = await apiRequest(page, 'delete', `/api/storage/${encodedKey}`)
|
|
302
|
+
|
|
303
|
+
// Should return 404 (file not actually uploaded) or success
|
|
304
|
+
expect([200, 404, 400]).toContain(deleteResponse.status())
|
|
305
|
+
})
|
|
306
|
+
})
|
|
307
|
+
})
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { test, expect, isAuthenticated, closeAllDialogs } from '../fixtures'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Integration Management Journey Tests
|
|
5
|
+
*
|
|
6
|
+
* These tests verify complete integration management user flows,
|
|
7
|
+
* including browsing integrations, webhooks, and API documentation.
|
|
8
|
+
*
|
|
9
|
+
* @tags @critical @journey @integrations
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
test.describe('Integration Management Journeys @critical @journey @integrations', () => {
|
|
13
|
+
test.describe('Integrations 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 integrations page with header', async ({ page }) => {
|
|
24
|
+
await page.goto('/integrations')
|
|
25
|
+
|
|
26
|
+
// Verify page loads with main heading
|
|
27
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
28
|
+
|
|
29
|
+
// Verify description
|
|
30
|
+
await expect(page.getByText(/connect third-party services and manage webhooks/i)).toBeVisible()
|
|
31
|
+
|
|
32
|
+
// Verify connected count indicator
|
|
33
|
+
await expect(page.getByText(/\d+ connected/)).toBeVisible()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('should display search input', async ({ page }) => {
|
|
37
|
+
await page.goto('/integrations')
|
|
38
|
+
|
|
39
|
+
// Verify search input is visible
|
|
40
|
+
const searchInput = page.getByPlaceholder(/search integrations/i)
|
|
41
|
+
await expect(searchInput).toBeVisible()
|
|
42
|
+
await expect(searchInput).toBeEnabled()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('should display category filter buttons', async ({ page }) => {
|
|
46
|
+
await page.goto('/integrations')
|
|
47
|
+
|
|
48
|
+
// Verify all category buttons are visible
|
|
49
|
+
await expect(page.getByRole('button', { name: 'All' })).toBeVisible()
|
|
50
|
+
await expect(page.getByRole('button', { name: 'Communication' })).toBeVisible()
|
|
51
|
+
await expect(page.getByRole('button', { name: 'Payments' })).toBeVisible()
|
|
52
|
+
await expect(page.getByRole('button', { name: 'Development' })).toBeVisible()
|
|
53
|
+
await expect(page.getByRole('button', { name: 'Automation' })).toBeVisible()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('should display available integrations section', async ({ page }) => {
|
|
57
|
+
await page.goto('/integrations')
|
|
58
|
+
|
|
59
|
+
// Verify Available Integrations heading
|
|
60
|
+
await expect(page.getByRole('heading', { name: /available integrations/i })).toBeVisible()
|
|
61
|
+
|
|
62
|
+
// Verify some integration cards are visible (using first() to handle multiple matches)
|
|
63
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
64
|
+
await expect(page.getByText('Discord').first()).toBeVisible()
|
|
65
|
+
await expect(page.getByText('Stripe').first()).toBeVisible()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('should display integration cards with details', async ({ page }) => {
|
|
69
|
+
await page.goto('/integrations')
|
|
70
|
+
|
|
71
|
+
// Verify Slack integration card
|
|
72
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
73
|
+
await expect(page.getByText(/send notifications and updates to slack channels/i)).toBeVisible()
|
|
74
|
+
|
|
75
|
+
// Verify Stripe integration card
|
|
76
|
+
await expect(page.getByText('Stripe').first()).toBeVisible()
|
|
77
|
+
await expect(page.getByText(/process payments and manage subscriptions/i)).toBeVisible()
|
|
78
|
+
|
|
79
|
+
// Verify GitHub integration card
|
|
80
|
+
await expect(page.getByText('GitHub').first()).toBeVisible()
|
|
81
|
+
await expect(page.getByText(/sync repositories and track issues/i)).toBeVisible()
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test.describe('Integration Search Journey', () => {
|
|
86
|
+
test.beforeEach(async ({ page }) => {
|
|
87
|
+
const authenticated = await isAuthenticated(page)
|
|
88
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test.afterEach(async ({ page }) => {
|
|
92
|
+
await closeAllDialogs(page)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('should filter integrations by search', async ({ page }) => {
|
|
96
|
+
await page.goto('/integrations')
|
|
97
|
+
|
|
98
|
+
// Type in search
|
|
99
|
+
const searchInput = page.getByPlaceholder(/search integrations/i)
|
|
100
|
+
await searchInput.fill('slack')
|
|
101
|
+
|
|
102
|
+
// Verify only Slack is visible
|
|
103
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
104
|
+
|
|
105
|
+
// Verify other integrations are not visible
|
|
106
|
+
await expect(page.getByText('Discord').first()).not.toBeVisible()
|
|
107
|
+
await expect(page.getByText('Stripe').first()).not.toBeVisible()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('should show no results message when search has no matches', async ({ page }) => {
|
|
111
|
+
await page.goto('/integrations')
|
|
112
|
+
|
|
113
|
+
// Type search that has no matches
|
|
114
|
+
const searchInput = page.getByPlaceholder(/search integrations/i)
|
|
115
|
+
await searchInput.fill('nonexistentintegration')
|
|
116
|
+
|
|
117
|
+
// Verify no results message
|
|
118
|
+
await expect(page.getByText(/no integrations found matching your search/i)).toBeVisible()
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('should clear search and show all integrations', async ({ page }) => {
|
|
122
|
+
await page.goto('/integrations')
|
|
123
|
+
|
|
124
|
+
const searchInput = page.getByPlaceholder(/search integrations/i)
|
|
125
|
+
|
|
126
|
+
// Search for specific integration
|
|
127
|
+
await searchInput.fill('github')
|
|
128
|
+
await expect(page.getByText('GitHub').first()).toBeVisible()
|
|
129
|
+
await expect(page.getByText('Slack').first()).not.toBeVisible()
|
|
130
|
+
|
|
131
|
+
// Clear search
|
|
132
|
+
await searchInput.clear()
|
|
133
|
+
|
|
134
|
+
// Verify all integrations are back
|
|
135
|
+
await expect(page.getByText('GitHub').first()).toBeVisible()
|
|
136
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
137
|
+
await expect(page.getByText('Stripe').first()).toBeVisible()
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test.describe('Integration Category Filter Journey', () => {
|
|
142
|
+
test.beforeEach(async ({ page }) => {
|
|
143
|
+
const authenticated = await isAuthenticated(page)
|
|
144
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test.afterEach(async ({ page }) => {
|
|
148
|
+
await closeAllDialogs(page)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
test('should filter by Communication category', async ({ page }) => {
|
|
152
|
+
await page.goto('/integrations')
|
|
153
|
+
|
|
154
|
+
// Click Communication category
|
|
155
|
+
await page.getByRole('button', { name: 'Communication' }).click()
|
|
156
|
+
|
|
157
|
+
// Verify only communication integrations are visible
|
|
158
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
159
|
+
await expect(page.getByText('Discord').first()).toBeVisible()
|
|
160
|
+
|
|
161
|
+
// Verify other categories are not visible
|
|
162
|
+
await expect(page.getByText('Stripe').first()).not.toBeVisible()
|
|
163
|
+
await expect(page.getByText('GitHub').first()).not.toBeVisible()
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('should filter by Development category', async ({ page }) => {
|
|
167
|
+
await page.goto('/integrations')
|
|
168
|
+
|
|
169
|
+
// Click Development category
|
|
170
|
+
await page.getByRole('button', { name: 'Development' }).click()
|
|
171
|
+
|
|
172
|
+
// Verify only development integrations are visible
|
|
173
|
+
await expect(page.getByText('GitHub').first()).toBeVisible()
|
|
174
|
+
await expect(page.getByText('Linear').first()).toBeVisible()
|
|
175
|
+
|
|
176
|
+
// Verify other categories are not visible
|
|
177
|
+
await expect(page.getByText('Slack').first()).not.toBeVisible()
|
|
178
|
+
await expect(page.getByText('Stripe').first()).not.toBeVisible()
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('should return to all integrations when All is clicked', async ({ page }) => {
|
|
182
|
+
await page.goto('/integrations')
|
|
183
|
+
|
|
184
|
+
// First filter by a category
|
|
185
|
+
await page.getByRole('button', { name: 'Payments' }).click()
|
|
186
|
+
await expect(page.getByText('Stripe').first()).toBeVisible()
|
|
187
|
+
await expect(page.getByText('Slack').first()).not.toBeVisible()
|
|
188
|
+
|
|
189
|
+
// Click All to reset filter
|
|
190
|
+
await page.getByRole('button', { name: 'All' }).click()
|
|
191
|
+
|
|
192
|
+
// Verify all integrations are visible
|
|
193
|
+
await expect(page.getByText('Stripe').first()).toBeVisible()
|
|
194
|
+
await expect(page.getByText('Slack').first()).toBeVisible()
|
|
195
|
+
await expect(page.getByText('GitHub').first()).toBeVisible()
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test.describe('Webhook Management Journey', () => {
|
|
200
|
+
test.beforeEach(async ({ page }) => {
|
|
201
|
+
const authenticated = await isAuthenticated(page)
|
|
202
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test.afterEach(async ({ page }) => {
|
|
206
|
+
await closeAllDialogs(page)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('should display webhooks section', async ({ page }) => {
|
|
210
|
+
await page.goto('/integrations')
|
|
211
|
+
|
|
212
|
+
// Verify Webhooks heading
|
|
213
|
+
await expect(page.getByRole('heading', { name: /webhooks/i })).toBeVisible()
|
|
214
|
+
|
|
215
|
+
// Verify webhooks description
|
|
216
|
+
await expect(page.getByText(/receive real-time notifications when events happen/i)).toBeVisible()
|
|
217
|
+
|
|
218
|
+
// Verify Add Webhook button
|
|
219
|
+
const addWebhookButton = page.getByRole('button', { name: 'Add Webhook' }).first()
|
|
220
|
+
await expect(addWebhookButton).toBeVisible()
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
test('should display existing webhook details', async ({ page }) => {
|
|
224
|
+
await page.goto('/integrations')
|
|
225
|
+
|
|
226
|
+
// Verify webhook URL is displayed
|
|
227
|
+
await expect(page.getByText('https://api.example.com/webhooks/receive')).toBeVisible()
|
|
228
|
+
|
|
229
|
+
// Verify event badges are shown
|
|
230
|
+
await expect(page.getByText('user.created')).toBeVisible()
|
|
231
|
+
await expect(page.getByText('user.updated')).toBeVisible()
|
|
232
|
+
|
|
233
|
+
// Verify last delivery info
|
|
234
|
+
await expect(page.getByText(/last delivery/i)).toBeVisible()
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
test('should open create webhook dialog', async ({ page }) => {
|
|
238
|
+
await page.goto('/integrations')
|
|
239
|
+
|
|
240
|
+
// Click Add Webhook button
|
|
241
|
+
const addWebhookButton = page.getByRole('button', { name: 'Add Webhook' }).first()
|
|
242
|
+
await addWebhookButton.click()
|
|
243
|
+
|
|
244
|
+
// Verify dialog opens
|
|
245
|
+
await expect(page.getByRole('heading', { name: /create webhook/i })).toBeVisible()
|
|
246
|
+
|
|
247
|
+
// Verify dialog description
|
|
248
|
+
await expect(page.getByText(/configure a url to receive post requests/i)).toBeVisible()
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
test('should display webhook form fields', async ({ page }) => {
|
|
252
|
+
await page.goto('/integrations')
|
|
253
|
+
|
|
254
|
+
// Open dialog
|
|
255
|
+
await page.getByRole('button', { name: 'Add Webhook' }).first().click()
|
|
256
|
+
|
|
257
|
+
// Verify Endpoint URL field
|
|
258
|
+
await expect(page.getByLabel(/endpoint url/i)).toBeVisible()
|
|
259
|
+
await expect(page.getByPlaceholder('https://api.example.com/webhooks')).toBeVisible()
|
|
260
|
+
|
|
261
|
+
// Verify Events section
|
|
262
|
+
await expect(page.getByText(/events to subscribe/i)).toBeVisible()
|
|
263
|
+
|
|
264
|
+
// Verify event buttons
|
|
265
|
+
await expect(page.getByRole('button', { name: 'User Created' })).toBeVisible()
|
|
266
|
+
await expect(page.getByRole('button', { name: 'User Updated' })).toBeVisible()
|
|
267
|
+
await expect(page.getByRole('button', { name: 'User Deleted' })).toBeVisible()
|
|
268
|
+
await expect(page.getByRole('button', { name: 'Team Member Added' })).toBeVisible()
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
test('should enable create button when form is valid', async ({ page }) => {
|
|
272
|
+
await page.goto('/integrations')
|
|
273
|
+
|
|
274
|
+
// Open dialog
|
|
275
|
+
await page.getByRole('button', { name: 'Add Webhook' }).first().click()
|
|
276
|
+
|
|
277
|
+
// Verify Create button is initially disabled
|
|
278
|
+
const createButton = page.getByRole('button', { name: 'Create Webhook', exact: true })
|
|
279
|
+
await expect(createButton).toBeDisabled()
|
|
280
|
+
|
|
281
|
+
// Fill in URL
|
|
282
|
+
await page.getByPlaceholder('https://api.example.com/webhooks').fill('https://test.example.com/webhook')
|
|
283
|
+
|
|
284
|
+
// Still disabled (no events selected)
|
|
285
|
+
await expect(createButton).toBeDisabled()
|
|
286
|
+
|
|
287
|
+
// Select an event
|
|
288
|
+
await page.getByRole('button', { name: 'User Created' }).click()
|
|
289
|
+
|
|
290
|
+
// Now button should be enabled
|
|
291
|
+
await expect(createButton).toBeEnabled()
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
test('should cancel webhook creation', async ({ page }) => {
|
|
295
|
+
await page.goto('/integrations')
|
|
296
|
+
|
|
297
|
+
// Open dialog
|
|
298
|
+
await page.getByRole('button', { name: 'Add Webhook' }).first().click()
|
|
299
|
+
await expect(page.getByRole('heading', { name: /create webhook/i })).toBeVisible()
|
|
300
|
+
|
|
301
|
+
// Fill in form
|
|
302
|
+
await page.getByPlaceholder('https://api.example.com/webhooks').fill('https://cancel-test.com/webhook')
|
|
303
|
+
await page.getByRole('button', { name: 'User Created' }).click()
|
|
304
|
+
|
|
305
|
+
// Click Cancel
|
|
306
|
+
await page.getByRole('button', { name: 'Cancel' }).click()
|
|
307
|
+
|
|
308
|
+
// Verify dialog is closed
|
|
309
|
+
await expect(page.getByRole('heading', { name: /create webhook/i })).not.toBeVisible()
|
|
310
|
+
|
|
311
|
+
// Verify we're still on integrations page
|
|
312
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
test.describe('API Documentation Journey', () => {
|
|
317
|
+
test.beforeEach(async ({ page }) => {
|
|
318
|
+
const authenticated = await isAuthenticated(page)
|
|
319
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
test.afterEach(async ({ page }) => {
|
|
323
|
+
await closeAllDialogs(page)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
test('should display API documentation section', async ({ page }) => {
|
|
327
|
+
await page.goto('/integrations')
|
|
328
|
+
|
|
329
|
+
// Verify Build Custom Integrations section
|
|
330
|
+
await expect(page.getByText('Build Custom Integrations')).toBeVisible()
|
|
331
|
+
await expect(page.getByText(/use our api to build your own integrations/i)).toBeVisible()
|
|
332
|
+
|
|
333
|
+
// Verify View API Docs button
|
|
334
|
+
const apiDocsButton = page.getByRole('button', { name: /view api docs/i })
|
|
335
|
+
await expect(apiDocsButton).toBeVisible()
|
|
336
|
+
await expect(apiDocsButton).toBeEnabled()
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
test.describe('Integration Navigation Journey', () => {
|
|
341
|
+
test.beforeEach(async ({ page }) => {
|
|
342
|
+
const authenticated = await isAuthenticated(page)
|
|
343
|
+
test.skip(!authenticated, 'No authenticated session available')
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
test.afterEach(async ({ page }) => {
|
|
347
|
+
await closeAllDialogs(page)
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
test('should navigate from integrations to other pages and back', async ({ page }) => {
|
|
351
|
+
// Start at integrations
|
|
352
|
+
await page.goto('/integrations')
|
|
353
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
354
|
+
|
|
355
|
+
// Navigate to dashboard
|
|
356
|
+
await page.goto('/dashboard')
|
|
357
|
+
await expect(page).toHaveURL(/dashboard/)
|
|
358
|
+
|
|
359
|
+
// Return to integrations
|
|
360
|
+
await page.goto('/integrations')
|
|
361
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
362
|
+
|
|
363
|
+
// Navigate to team
|
|
364
|
+
await page.goto('/team')
|
|
365
|
+
await expect(page.getByRole('heading', { name: /team members/i })).toBeVisible()
|
|
366
|
+
|
|
367
|
+
// Return to integrations
|
|
368
|
+
await page.goto('/integrations')
|
|
369
|
+
await expect(page.getByRole('heading', { name: 'Integrations', exact: true })).toBeVisible()
|
|
370
|
+
})
|
|
371
|
+
})
|
|
372
|
+
})
|