solokit 0.1.1__py3-none-any.whl
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.
- solokit/__init__.py +10 -0
- solokit/__version__.py +3 -0
- solokit/cli.py +374 -0
- solokit/core/__init__.py +1 -0
- solokit/core/cache.py +102 -0
- solokit/core/command_runner.py +278 -0
- solokit/core/config.py +453 -0
- solokit/core/config_validator.py +204 -0
- solokit/core/constants.py +291 -0
- solokit/core/error_formatter.py +279 -0
- solokit/core/error_handlers.py +346 -0
- solokit/core/exceptions.py +1567 -0
- solokit/core/file_ops.py +309 -0
- solokit/core/logging_config.py +166 -0
- solokit/core/output.py +99 -0
- solokit/core/performance.py +57 -0
- solokit/core/protocols.py +141 -0
- solokit/core/types.py +312 -0
- solokit/deployment/__init__.py +1 -0
- solokit/deployment/executor.py +411 -0
- solokit/git/__init__.py +1 -0
- solokit/git/integration.py +619 -0
- solokit/init/__init__.py +41 -0
- solokit/init/claude_commands_installer.py +87 -0
- solokit/init/dependency_installer.py +313 -0
- solokit/init/docs_structure.py +90 -0
- solokit/init/env_generator.py +160 -0
- solokit/init/environment_validator.py +334 -0
- solokit/init/git_hooks_installer.py +71 -0
- solokit/init/git_setup.py +188 -0
- solokit/init/gitignore_updater.py +195 -0
- solokit/init/initial_commit.py +145 -0
- solokit/init/initial_scans.py +109 -0
- solokit/init/orchestrator.py +246 -0
- solokit/init/readme_generator.py +207 -0
- solokit/init/session_structure.py +239 -0
- solokit/init/template_installer.py +424 -0
- solokit/learning/__init__.py +1 -0
- solokit/learning/archiver.py +115 -0
- solokit/learning/categorizer.py +126 -0
- solokit/learning/curator.py +428 -0
- solokit/learning/extractor.py +352 -0
- solokit/learning/reporter.py +351 -0
- solokit/learning/repository.py +254 -0
- solokit/learning/similarity.py +342 -0
- solokit/learning/validator.py +144 -0
- solokit/project/__init__.py +1 -0
- solokit/project/init.py +1162 -0
- solokit/project/stack.py +436 -0
- solokit/project/sync_plugin.py +438 -0
- solokit/project/tree.py +375 -0
- solokit/quality/__init__.py +1 -0
- solokit/quality/api_validator.py +424 -0
- solokit/quality/checkers/__init__.py +25 -0
- solokit/quality/checkers/base.py +114 -0
- solokit/quality/checkers/context7.py +221 -0
- solokit/quality/checkers/custom.py +162 -0
- solokit/quality/checkers/deployment.py +323 -0
- solokit/quality/checkers/documentation.py +179 -0
- solokit/quality/checkers/formatting.py +161 -0
- solokit/quality/checkers/integration.py +394 -0
- solokit/quality/checkers/linting.py +159 -0
- solokit/quality/checkers/security.py +261 -0
- solokit/quality/checkers/spec_completeness.py +127 -0
- solokit/quality/checkers/tests.py +184 -0
- solokit/quality/env_validator.py +306 -0
- solokit/quality/gates.py +655 -0
- solokit/quality/reporters/__init__.py +10 -0
- solokit/quality/reporters/base.py +25 -0
- solokit/quality/reporters/console.py +98 -0
- solokit/quality/reporters/json_reporter.py +34 -0
- solokit/quality/results.py +98 -0
- solokit/session/__init__.py +1 -0
- solokit/session/briefing/__init__.py +245 -0
- solokit/session/briefing/documentation_loader.py +53 -0
- solokit/session/briefing/formatter.py +476 -0
- solokit/session/briefing/git_context.py +282 -0
- solokit/session/briefing/learning_loader.py +212 -0
- solokit/session/briefing/milestone_builder.py +78 -0
- solokit/session/briefing/orchestrator.py +137 -0
- solokit/session/briefing/stack_detector.py +51 -0
- solokit/session/briefing/tree_generator.py +52 -0
- solokit/session/briefing/work_item_loader.py +209 -0
- solokit/session/briefing.py +353 -0
- solokit/session/complete.py +1188 -0
- solokit/session/status.py +246 -0
- solokit/session/validate.py +452 -0
- solokit/templates/.claude/commands/end.md +109 -0
- solokit/templates/.claude/commands/init.md +159 -0
- solokit/templates/.claude/commands/learn-curate.md +88 -0
- solokit/templates/.claude/commands/learn-search.md +62 -0
- solokit/templates/.claude/commands/learn-show.md +69 -0
- solokit/templates/.claude/commands/learn.md +136 -0
- solokit/templates/.claude/commands/start.md +114 -0
- solokit/templates/.claude/commands/status.md +22 -0
- solokit/templates/.claude/commands/validate.md +27 -0
- solokit/templates/.claude/commands/work-delete.md +119 -0
- solokit/templates/.claude/commands/work-graph.md +139 -0
- solokit/templates/.claude/commands/work-list.md +26 -0
- solokit/templates/.claude/commands/work-new.md +114 -0
- solokit/templates/.claude/commands/work-next.md +25 -0
- solokit/templates/.claude/commands/work-show.md +24 -0
- solokit/templates/.claude/commands/work-update.md +141 -0
- solokit/templates/CHANGELOG.md +17 -0
- solokit/templates/WORK_ITEM_TYPES.md +141 -0
- solokit/templates/__init__.py +1 -0
- solokit/templates/bug_spec.md +217 -0
- solokit/templates/config.schema.json +150 -0
- solokit/templates/dashboard_refine/base/.gitignore +36 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/layout.tsx +22 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/page.tsx +68 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/users/page.tsx +77 -0
- solokit/templates/dashboard_refine/base/app/globals.css +60 -0
- solokit/templates/dashboard_refine/base/app/layout.tsx +23 -0
- solokit/templates/dashboard_refine/base/app/page.tsx +9 -0
- solokit/templates/dashboard_refine/base/components/client-refine-wrapper.tsx +21 -0
- solokit/templates/dashboard_refine/base/components/layout/header.tsx +44 -0
- solokit/templates/dashboard_refine/base/components/layout/sidebar.tsx +82 -0
- solokit/templates/dashboard_refine/base/components/ui/button.tsx +53 -0
- solokit/templates/dashboard_refine/base/components/ui/card.tsx +78 -0
- solokit/templates/dashboard_refine/base/components/ui/table.tsx +116 -0
- solokit/templates/dashboard_refine/base/components.json +16 -0
- solokit/templates/dashboard_refine/base/lib/refine.tsx +65 -0
- solokit/templates/dashboard_refine/base/lib/utils.ts +13 -0
- solokit/templates/dashboard_refine/base/next.config.ts +10 -0
- solokit/templates/dashboard_refine/base/package.json.template +40 -0
- solokit/templates/dashboard_refine/base/postcss.config.mjs +8 -0
- solokit/templates/dashboard_refine/base/providers/refine-provider.tsx +26 -0
- solokit/templates/dashboard_refine/base/tailwind.config.ts +57 -0
- solokit/templates/dashboard_refine/base/tsconfig.json +27 -0
- solokit/templates/dashboard_refine/docker/Dockerfile +57 -0
- solokit/templates/dashboard_refine/docker/docker-compose.prod.yml +31 -0
- solokit/templates/dashboard_refine/docker/docker-compose.yml +21 -0
- solokit/templates/dashboard_refine/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/dashboard_refine/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/dashboard_refine/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/dashboard_refine/tier-1-essential/package.json.tier1.template +57 -0
- solokit/templates/dashboard_refine/tier-1-essential/tests/setup.ts +26 -0
- solokit/templates/dashboard_refine/tier-1-essential/tests/unit/example.test.tsx +73 -0
- solokit/templates/dashboard_refine/tier-2-standard/package.json.tier2.template +62 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/eslint.config.mjs +22 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/package.json.tier3.template +79 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/stryker.conf.json +38 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/dashboard.spec.ts +88 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/user-management.spec.ts +102 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/integration/dashboard.test.tsx +90 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/type-coverage.json +16 -0
- solokit/templates/dashboard_refine/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/dashboard_refine/tier-4-production/k6/dashboard-load-test.js +70 -0
- solokit/templates/dashboard_refine/tier-4-production/next.config.ts +46 -0
- solokit/templates/dashboard_refine/tier-4-production/package.json.tier4.template +89 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/deployment_spec.md +500 -0
- solokit/templates/feature_spec.md +248 -0
- solokit/templates/fullstack_nextjs/base/.gitignore +36 -0
- solokit/templates/fullstack_nextjs/base/app/api/example/route.ts +65 -0
- solokit/templates/fullstack_nextjs/base/app/globals.css +27 -0
- solokit/templates/fullstack_nextjs/base/app/layout.tsx +20 -0
- solokit/templates/fullstack_nextjs/base/app/page.tsx +32 -0
- solokit/templates/fullstack_nextjs/base/components/example-component.tsx +20 -0
- solokit/templates/fullstack_nextjs/base/lib/prisma.ts +17 -0
- solokit/templates/fullstack_nextjs/base/lib/utils.ts +13 -0
- solokit/templates/fullstack_nextjs/base/lib/validations.ts +20 -0
- solokit/templates/fullstack_nextjs/base/next.config.ts +7 -0
- solokit/templates/fullstack_nextjs/base/package.json.template +32 -0
- solokit/templates/fullstack_nextjs/base/postcss.config.mjs +8 -0
- solokit/templates/fullstack_nextjs/base/prisma/schema.prisma +21 -0
- solokit/templates/fullstack_nextjs/base/tailwind.config.ts +19 -0
- solokit/templates/fullstack_nextjs/base/tsconfig.json +27 -0
- solokit/templates/fullstack_nextjs/docker/Dockerfile +60 -0
- solokit/templates/fullstack_nextjs/docker/docker-compose.prod.yml +57 -0
- solokit/templates/fullstack_nextjs/docker/docker-compose.yml +47 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/package.json.tier1.template +48 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/api/example.test.ts +88 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/setup.ts +22 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/unit/example.test.tsx +22 -0
- solokit/templates/fullstack_nextjs/tier-2-standard/package.json.tier2.template +52 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/eslint.config.mjs +39 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/package.json.tier3.template +68 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/stryker.conf.json +33 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/e2e/flow.spec.ts +59 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/integration/api.test.ts +165 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/type-coverage.json +12 -0
- solokit/templates/fullstack_nextjs/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/fullstack_nextjs/tier-4-production/k6/load-test.js +45 -0
- solokit/templates/fullstack_nextjs/tier-4-production/next.config.ts +46 -0
- solokit/templates/fullstack_nextjs/tier-4-production/package.json.tier4.template +77 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/git-hooks/prepare-commit-msg +24 -0
- solokit/templates/integration_test_spec.md +363 -0
- solokit/templates/learnings.json +15 -0
- solokit/templates/ml_ai_fastapi/base/.gitignore +104 -0
- solokit/templates/ml_ai_fastapi/base/alembic/env.py +96 -0
- solokit/templates/ml_ai_fastapi/base/alembic.ini +114 -0
- solokit/templates/ml_ai_fastapi/base/pyproject.toml.template +91 -0
- solokit/templates/ml_ai_fastapi/base/requirements.txt.template +28 -0
- solokit/templates/ml_ai_fastapi/base/src/__init__.py +5 -0
- solokit/templates/ml_ai_fastapi/base/src/api/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/api/dependencies.py +20 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/example.py +134 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/health.py +66 -0
- solokit/templates/ml_ai_fastapi/base/src/core/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/core/config.py +64 -0
- solokit/templates/ml_ai_fastapi/base/src/core/database.py +50 -0
- solokit/templates/ml_ai_fastapi/base/src/main.py +64 -0
- solokit/templates/ml_ai_fastapi/base/src/models/__init__.py +7 -0
- solokit/templates/ml_ai_fastapi/base/src/models/example.py +61 -0
- solokit/templates/ml_ai_fastapi/base/src/services/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/services/example.py +115 -0
- solokit/templates/ml_ai_fastapi/docker/Dockerfile +59 -0
- solokit/templates/ml_ai_fastapi/docker/docker-compose.prod.yml +112 -0
- solokit/templates/ml_ai_fastapi/docker/docker-compose.yml +77 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pyproject.toml.tier1.template +112 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pyrightconfig.json +41 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pytest.ini +69 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/requirements-dev.txt +17 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/ruff.toml +81 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/conftest.py +72 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/test_main.py +49 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/test_example.py +113 -0
- solokit/templates/ml_ai_fastapi/tier-2-standard/pyproject.toml.tier2.template +130 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/locustfile.py +99 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/mutmut_config.py +53 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/pyproject.toml.tier3.template +150 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/conftest.py +74 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/test_api.py +131 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/pyproject.toml.tier4.template +162 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/requirements-prod.txt +25 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/api/routes/metrics.py +19 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/logging.py +74 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/monitoring.py +68 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/sentry.py +66 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/logging.py +79 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/tracing.py +60 -0
- solokit/templates/refactor_spec.md +287 -0
- solokit/templates/saas_t3/base/.gitignore +36 -0
- solokit/templates/saas_t3/base/app/api/trpc/[trpc]/route.ts +33 -0
- solokit/templates/saas_t3/base/app/globals.css +27 -0
- solokit/templates/saas_t3/base/app/layout.tsx +23 -0
- solokit/templates/saas_t3/base/app/page.tsx +31 -0
- solokit/templates/saas_t3/base/lib/api.tsx +77 -0
- solokit/templates/saas_t3/base/lib/utils.ts +13 -0
- solokit/templates/saas_t3/base/next.config.ts +7 -0
- solokit/templates/saas_t3/base/package.json.template +38 -0
- solokit/templates/saas_t3/base/postcss.config.mjs +8 -0
- solokit/templates/saas_t3/base/prisma/schema.prisma +20 -0
- solokit/templates/saas_t3/base/server/api/root.ts +19 -0
- solokit/templates/saas_t3/base/server/api/routers/example.ts +28 -0
- solokit/templates/saas_t3/base/server/api/trpc.ts +52 -0
- solokit/templates/saas_t3/base/server/db.ts +17 -0
- solokit/templates/saas_t3/base/tailwind.config.ts +19 -0
- solokit/templates/saas_t3/base/tsconfig.json +27 -0
- solokit/templates/saas_t3/docker/Dockerfile +60 -0
- solokit/templates/saas_t3/docker/docker-compose.prod.yml +59 -0
- solokit/templates/saas_t3/docker/docker-compose.yml +49 -0
- solokit/templates/saas_t3/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/saas_t3/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/saas_t3/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/saas_t3/tier-1-essential/package.json.tier1.template +54 -0
- solokit/templates/saas_t3/tier-1-essential/tests/setup.ts +22 -0
- solokit/templates/saas_t3/tier-1-essential/tests/unit/example.test.tsx +24 -0
- solokit/templates/saas_t3/tier-2-standard/package.json.tier2.template +58 -0
- solokit/templates/saas_t3/tier-3-comprehensive/eslint.config.mjs +39 -0
- solokit/templates/saas_t3/tier-3-comprehensive/package.json.tier3.template +74 -0
- solokit/templates/saas_t3/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/saas_t3/tier-3-comprehensive/stryker.conf.json +34 -0
- solokit/templates/saas_t3/tier-3-comprehensive/tests/e2e/home.spec.ts +41 -0
- solokit/templates/saas_t3/tier-3-comprehensive/tests/integration/api.test.ts +44 -0
- solokit/templates/saas_t3/tier-3-comprehensive/type-coverage.json +12 -0
- solokit/templates/saas_t3/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/saas_t3/tier-4-production/k6/load-test.js +51 -0
- solokit/templates/saas_t3/tier-4-production/next.config.ts +46 -0
- solokit/templates/saas_t3/tier-4-production/package.json.tier4.template +83 -0
- solokit/templates/saas_t3/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/saas_t3/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/saas_t3/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/saas_t3/tier-4-production/vercel.json +37 -0
- solokit/templates/security_spec.md +287 -0
- solokit/templates/stack-versions.yaml +617 -0
- solokit/templates/status_update.json +6 -0
- solokit/templates/template-registry.json +257 -0
- solokit/templates/work_items.json +11 -0
- solokit/testing/__init__.py +1 -0
- solokit/testing/integration_runner.py +550 -0
- solokit/testing/performance.py +637 -0
- solokit/visualization/__init__.py +1 -0
- solokit/visualization/dependency_graph.py +788 -0
- solokit/work_items/__init__.py +1 -0
- solokit/work_items/creator.py +217 -0
- solokit/work_items/delete.py +264 -0
- solokit/work_items/get_dependencies.py +185 -0
- solokit/work_items/get_dependents.py +113 -0
- solokit/work_items/get_metadata.py +121 -0
- solokit/work_items/get_next_recommendations.py +133 -0
- solokit/work_items/manager.py +235 -0
- solokit/work_items/milestones.py +137 -0
- solokit/work_items/query.py +376 -0
- solokit/work_items/repository.py +267 -0
- solokit/work_items/scheduler.py +184 -0
- solokit/work_items/spec_parser.py +838 -0
- solokit/work_items/spec_validator.py +493 -0
- solokit/work_items/updater.py +157 -0
- solokit/work_items/validator.py +205 -0
- solokit-0.1.1.dist-info/METADATA +640 -0
- solokit-0.1.1.dist-info/RECORD +323 -0
- solokit-0.1.1.dist-info/WHEEL +5 -0
- solokit-0.1.1.dist-info/entry_points.txt +2 -0
- solokit-0.1.1.dist-info/licenses/LICENSE +21 -0
- solokit-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { describe, it, expect, jest, beforeEach } from "@jest/globals";
|
|
2
|
+
import { NextRequest } from "next/server";
|
|
3
|
+
import { GET, POST } from "@/app/api/example/route";
|
|
4
|
+
|
|
5
|
+
// Mock Prisma client
|
|
6
|
+
jest.mock("@/lib/prisma", () => ({
|
|
7
|
+
prisma: {
|
|
8
|
+
user: {
|
|
9
|
+
findMany: jest.fn(),
|
|
10
|
+
create: jest.fn(),
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Import the mocked prisma after mocking
|
|
16
|
+
import { prisma } from "@/lib/prisma";
|
|
17
|
+
|
|
18
|
+
describe("API Integration Tests", () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("GET /api/example", () => {
|
|
24
|
+
it("should successfully fetch users from database", async () => {
|
|
25
|
+
const mockUsers = [
|
|
26
|
+
{
|
|
27
|
+
id: 1,
|
|
28
|
+
name: "John Doe",
|
|
29
|
+
email: "john@example.com",
|
|
30
|
+
createdAt: new Date("2024-01-01"),
|
|
31
|
+
updatedAt: new Date("2024-01-01"),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 2,
|
|
35
|
+
name: "Jane Smith",
|
|
36
|
+
email: "jane@example.com",
|
|
37
|
+
createdAt: new Date("2024-01-02"),
|
|
38
|
+
updatedAt: new Date("2024-01-02"),
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
(prisma.user.findMany as jest.Mock).mockResolvedValue(mockUsers);
|
|
43
|
+
|
|
44
|
+
const response = await GET();
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
|
|
47
|
+
expect(response.status).toBe(200);
|
|
48
|
+
expect(data).toHaveProperty("message");
|
|
49
|
+
expect(data.users).toEqual(mockUsers);
|
|
50
|
+
expect(prisma.user.findMany).toHaveBeenCalledWith({
|
|
51
|
+
take: 10,
|
|
52
|
+
orderBy: { createdAt: "desc" },
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should handle empty user list", async () => {
|
|
57
|
+
(prisma.user.findMany as jest.Mock).mockResolvedValue([]);
|
|
58
|
+
|
|
59
|
+
const response = await GET();
|
|
60
|
+
const data = await response.json();
|
|
61
|
+
|
|
62
|
+
expect(response.status).toBe(200);
|
|
63
|
+
expect(data.users).toEqual([]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should handle database connection errors", async () => {
|
|
67
|
+
(prisma.user.findMany as jest.Mock).mockRejectedValue(
|
|
68
|
+
new Error("Database connection failed")
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const response = await GET();
|
|
72
|
+
const data = await response.json();
|
|
73
|
+
|
|
74
|
+
expect(response.status).toBe(500);
|
|
75
|
+
expect(data).toHaveProperty("error", "Failed to fetch users");
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe("POST /api/example", () => {
|
|
80
|
+
it("should create user with valid input", async () => {
|
|
81
|
+
const mockUser = {
|
|
82
|
+
id: 1,
|
|
83
|
+
name: "New User",
|
|
84
|
+
email: "newuser@example.com",
|
|
85
|
+
createdAt: new Date(),
|
|
86
|
+
updatedAt: new Date(),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
(prisma.user.create as jest.Mock).mockResolvedValue(mockUser);
|
|
90
|
+
|
|
91
|
+
const request = new NextRequest("http://localhost:3000/api/example", {
|
|
92
|
+
method: "POST",
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
name: "New User",
|
|
95
|
+
email: "newuser@example.com",
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const response = await POST(request);
|
|
100
|
+
const data = await response.json();
|
|
101
|
+
|
|
102
|
+
expect(response.status).toBe(201);
|
|
103
|
+
expect(data).toEqual(mockUser);
|
|
104
|
+
expect(prisma.user.create).toHaveBeenCalledWith({
|
|
105
|
+
data: {
|
|
106
|
+
name: "New User",
|
|
107
|
+
email: "newuser@example.com",
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("should reject invalid email format", async () => {
|
|
113
|
+
const request = new NextRequest("http://localhost:3000/api/example", {
|
|
114
|
+
method: "POST",
|
|
115
|
+
body: JSON.stringify({
|
|
116
|
+
name: "Test User",
|
|
117
|
+
email: "invalid-email",
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const response = await POST(request);
|
|
122
|
+
const data = await response.json();
|
|
123
|
+
|
|
124
|
+
expect(response.status).toBe(400);
|
|
125
|
+
expect(data).toHaveProperty("error", "Validation failed");
|
|
126
|
+
expect(data).toHaveProperty("details");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("should reject empty name", async () => {
|
|
130
|
+
const request = new NextRequest("http://localhost:3000/api/example", {
|
|
131
|
+
method: "POST",
|
|
132
|
+
body: JSON.stringify({
|
|
133
|
+
name: "",
|
|
134
|
+
email: "test@example.com",
|
|
135
|
+
}),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const response = await POST(request);
|
|
139
|
+
const data = await response.json();
|
|
140
|
+
|
|
141
|
+
expect(response.status).toBe(400);
|
|
142
|
+
expect(data).toHaveProperty("error", "Validation failed");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("should handle database creation errors", async () => {
|
|
146
|
+
(prisma.user.create as jest.Mock).mockRejectedValue(
|
|
147
|
+
new Error("Duplicate email")
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const request = new NextRequest("http://localhost:3000/api/example", {
|
|
151
|
+
method: "POST",
|
|
152
|
+
body: JSON.stringify({
|
|
153
|
+
name: "Test User",
|
|
154
|
+
email: "test@example.com",
|
|
155
|
+
}),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const response = await POST(request);
|
|
159
|
+
const data = await response.json();
|
|
160
|
+
|
|
161
|
+
expect(response.status).toBe(500);
|
|
162
|
+
expect(data).toHaveProperty("error", "Failed to create user");
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import http from 'k6/http';
|
|
2
|
+
import { check, sleep } from 'k6';
|
|
3
|
+
|
|
4
|
+
// Test configuration
|
|
5
|
+
export const options = {
|
|
6
|
+
stages: [
|
|
7
|
+
{ duration: '30s', target: 20 }, // Ramp up to 20 users
|
|
8
|
+
{ duration: '1m', target: 20 }, // Stay at 20 users
|
|
9
|
+
{ duration: '30s', target: 0 }, // Ramp down to 0 users
|
|
10
|
+
],
|
|
11
|
+
thresholds: {
|
|
12
|
+
http_req_duration: ['p(95)<500'], // 95% of requests should be below 500ms
|
|
13
|
+
http_req_failed: ['rate<0.01'], // Less than 1% of requests should fail
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';
|
|
18
|
+
|
|
19
|
+
export default function () {
|
|
20
|
+
// Test home page
|
|
21
|
+
const homeRes = http.get(`${BASE_URL}/`);
|
|
22
|
+
check(homeRes, {
|
|
23
|
+
'home page status is 200': (r) => r.status === 200,
|
|
24
|
+
'home page loads within 2s': (r) => r.timings.duration < 2000,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
sleep(1);
|
|
28
|
+
|
|
29
|
+
// Test API endpoint
|
|
30
|
+
const apiRes = http.get(`${BASE_URL}/api/example`);
|
|
31
|
+
check(apiRes, {
|
|
32
|
+
'API status is 200': (r) => r.status === 200,
|
|
33
|
+
'API responds within 500ms': (r) => r.timings.duration < 500,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
sleep(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Summary handler
|
|
40
|
+
export function handleSummary(data) {
|
|
41
|
+
return {
|
|
42
|
+
'stdout': textSummary(data, { indent: ' ', enableColors: true }),
|
|
43
|
+
'reports/load-test-summary.json': JSON.stringify(data),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { NextConfig } from "next";
|
|
2
|
+
import { withSentryConfig } from "@sentry/nextjs";
|
|
3
|
+
|
|
4
|
+
const nextConfig: NextConfig = {
|
|
5
|
+
/* config options here */
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// Injected content via Sentry wizard below
|
|
9
|
+
export default withSentryConfig(nextConfig, {
|
|
10
|
+
// For all available options, see:
|
|
11
|
+
// https://github.com/getsentry/sentry-webpack-plugin#options
|
|
12
|
+
|
|
13
|
+
org: process.env.SENTRY_ORG,
|
|
14
|
+
project: process.env.SENTRY_PROJECT,
|
|
15
|
+
|
|
16
|
+
// Only print logs for uploading source maps in CI
|
|
17
|
+
silent: !process.env.CI,
|
|
18
|
+
|
|
19
|
+
// For all available options, see:
|
|
20
|
+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
21
|
+
|
|
22
|
+
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
23
|
+
widenClientFileUpload: true,
|
|
24
|
+
|
|
25
|
+
// Automatically annotate React components to show their full name in breadcrumbs and session replay
|
|
26
|
+
reactComponentAnnotation: {
|
|
27
|
+
enabled: true,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
|
31
|
+
// This can increase your server load as well as your hosting bill.
|
|
32
|
+
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
|
33
|
+
// side errors will fail.
|
|
34
|
+
tunnelRoute: "/monitoring",
|
|
35
|
+
|
|
36
|
+
// Hides source maps from generated client bundles
|
|
37
|
+
|
|
38
|
+
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
39
|
+
disableLogger: true,
|
|
40
|
+
|
|
41
|
+
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
|
|
42
|
+
// See the following for more information:
|
|
43
|
+
// https://docs.sentry.io/product/crons/
|
|
44
|
+
// https://vercel.com/docs/cron-jobs
|
|
45
|
+
automaticVercelMonitors: true,
|
|
46
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{project_name}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "{project_description}",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "next dev",
|
|
9
|
+
"build": "next build",
|
|
10
|
+
"start": "next start",
|
|
11
|
+
"lint": "next lint",
|
|
12
|
+
"type-check": "tsc --noEmit",
|
|
13
|
+
"test": "jest",
|
|
14
|
+
"test:watch": "jest --watch",
|
|
15
|
+
"test:coverage": "jest --coverage",
|
|
16
|
+
"test:e2e": "playwright test",
|
|
17
|
+
"test:e2e:ui": "playwright test --ui",
|
|
18
|
+
"test:integration": "jest --testPathPattern=integration",
|
|
19
|
+
"test:mutation": "stryker run",
|
|
20
|
+
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
|
|
21
|
+
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,md}\"",
|
|
22
|
+
"prepare": "husky install && patch-package",
|
|
23
|
+
"audit": "npm audit --audit-level=moderate",
|
|
24
|
+
"check:duplication": "jscpd .",
|
|
25
|
+
"check:types": "type-coverage",
|
|
26
|
+
"analyze": "ANALYZE=true npm run build",
|
|
27
|
+
"lighthouse": "lhci autorun",
|
|
28
|
+
"load-test": "k6 run k6/load-test.js"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"next": "16.0.1",
|
|
32
|
+
"react": "19.2.0",
|
|
33
|
+
"react-dom": "19.2.0",
|
|
34
|
+
"prisma": "6.19.0",
|
|
35
|
+
"@prisma/client": "6.19.0",
|
|
36
|
+
"zod": "4.1.12",
|
|
37
|
+
"tailwindcss": "4.1.17",
|
|
38
|
+
"@tailwindcss/postcss": "4.1.17",
|
|
39
|
+
"clsx": "2.1.1",
|
|
40
|
+
"tailwind-merge": "3.3.1",
|
|
41
|
+
"@sentry/nextjs": "10.23.0",
|
|
42
|
+
"@vercel/analytics": "1.5.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"typescript": "5.9.3",
|
|
46
|
+
"@types/node": "20.19.24",
|
|
47
|
+
"@types/react": "19.2.2",
|
|
48
|
+
"@types/react-dom": "19.2.2",
|
|
49
|
+
"eslint": "9.39.1",
|
|
50
|
+
"eslint-config-next": "16.0.1",
|
|
51
|
+
"@typescript-eslint/parser": "8.46.3",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "8.46.3",
|
|
53
|
+
"prettier": "3.6.2",
|
|
54
|
+
"jest": "30.2.0",
|
|
55
|
+
"@types/jest": "30.0.0",
|
|
56
|
+
"ts-jest": "29.4.5",
|
|
57
|
+
"jest-environment-jsdom": "30.2.0",
|
|
58
|
+
"@testing-library/react": "16.3.0",
|
|
59
|
+
"@testing-library/jest-dom": "6.9.1",
|
|
60
|
+
"husky": "9.1.7",
|
|
61
|
+
"lint-staged": "16.2.6",
|
|
62
|
+
"jscpd": "4.0.5",
|
|
63
|
+
"ts-prune": "0.10.3",
|
|
64
|
+
"type-coverage": "2.29.7",
|
|
65
|
+
"@stryker-mutator/core": "9.3.0",
|
|
66
|
+
"@stryker-mutator/jest-runner": "9.3.0",
|
|
67
|
+
"@playwright/test": "1.56.1",
|
|
68
|
+
"playwright": "1.56.1",
|
|
69
|
+
"@axe-core/playwright": "4.11.0",
|
|
70
|
+
"eslint-plugin-jest-dom": "5.5.0",
|
|
71
|
+
"eslint-plugin-testing-library": "7.13.3",
|
|
72
|
+
"patch-package": "8.0.1",
|
|
73
|
+
"@next/bundle-analyzer": "16.0.1",
|
|
74
|
+
"@lhci/cli": "0.15.1",
|
|
75
|
+
"dotenv-cli": "11.0.0"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/nextjs";
|
|
2
|
+
|
|
3
|
+
Sentry.init({
|
|
4
|
+
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
|
5
|
+
|
|
6
|
+
// Adjust this value in production, or use tracesSampler for greater control
|
|
7
|
+
tracesSampleRate: 1,
|
|
8
|
+
|
|
9
|
+
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
10
|
+
debug: false,
|
|
11
|
+
|
|
12
|
+
replaysOnErrorSampleRate: 1.0,
|
|
13
|
+
|
|
14
|
+
// This sets the sample rate to be 10%. You may want this to be 100% while
|
|
15
|
+
// in development and sample at a lower rate in production
|
|
16
|
+
replaysSessionSampleRate: 0.1,
|
|
17
|
+
|
|
18
|
+
// You can remove this option if you're not planning to use the Sentry Session Replay feature:
|
|
19
|
+
integrations: [
|
|
20
|
+
Sentry.replayIntegration({
|
|
21
|
+
// Additional Replay configuration goes in here, for example:
|
|
22
|
+
maskAllText: true,
|
|
23
|
+
blockAllMedia: true,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/nextjs";
|
|
2
|
+
|
|
3
|
+
Sentry.init({
|
|
4
|
+
dsn: process.env.SENTRY_DSN,
|
|
5
|
+
|
|
6
|
+
// Adjust this value in production, or use tracesSampler for greater control
|
|
7
|
+
tracesSampleRate: 1,
|
|
8
|
+
|
|
9
|
+
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
10
|
+
debug: false,
|
|
11
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/nextjs";
|
|
2
|
+
|
|
3
|
+
Sentry.init({
|
|
4
|
+
dsn: process.env.SENTRY_DSN,
|
|
5
|
+
|
|
6
|
+
// Adjust this value in production, or use tracesSampler for greater control
|
|
7
|
+
tracesSampleRate: 1,
|
|
8
|
+
|
|
9
|
+
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
10
|
+
debug: false,
|
|
11
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
COMMIT_MSG_FILE=$1
|
|
4
|
+
COMMIT_SOURCE=$2
|
|
5
|
+
|
|
6
|
+
# Only run for regular commits (not merges, amends, etc.)
|
|
7
|
+
if [ -z "$COMMIT_SOURCE" ]; then
|
|
8
|
+
cat >> "$COMMIT_MSG_FILE" << 'EOF'
|
|
9
|
+
|
|
10
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
11
|
+
# REMINDERS:
|
|
12
|
+
#
|
|
13
|
+
# 📝 CHANGELOG: Update CHANGELOG.md for notable changes
|
|
14
|
+
# (features, fixes, breaking changes)
|
|
15
|
+
#
|
|
16
|
+
# 💡 LEARNINGS: Add insights that will be auto-extracted during /sk:end
|
|
17
|
+
# LEARNING: <your learning here>
|
|
18
|
+
#
|
|
19
|
+
# Examples:
|
|
20
|
+
# LEARNING: JWT refresh tokens should expire faster than access tokens
|
|
21
|
+
# LEARNING: Always use parameterized queries to prevent SQL injection
|
|
22
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
23
|
+
EOF
|
|
24
|
+
fi
|