@tinkcarlos/skillora 0.2.0
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/.claude/skills/.temp-skill-index.md +245 -0
- package/.claude/skills/SKILL.md +264 -0
- package/.claude/skills/api-scaffolding/SKILL.md +431 -0
- package/.claude/skills/api-scaffolding/agents/backend-architect.md +282 -0
- package/.claude/skills/api-scaffolding/agents/django-pro.md +144 -0
- package/.claude/skills/api-scaffolding/agents/fastapi-pro.md +156 -0
- package/.claude/skills/api-scaffolding/agents/graphql-architect.md +146 -0
- package/.claude/skills/api-scaffolding/skills/fastapi-templates/SKILL.md +171 -0
- package/.claude/skills/api-testing-observability/SKILL.md +583 -0
- package/.claude/skills/api-testing-observability/agents/api-documenter.md +146 -0
- package/.claude/skills/api-testing-observability/commands/api-mock.md +1320 -0
- package/.claude/skills/brainstorming/SKILL.md +283 -0
- package/.claude/skills/bug-fixing/SKILL.md +382 -0
- package/.claude/skills/bug-fixing/references/backend-guide.md +132 -0
- package/.claude/skills/bug-fixing/references/bug-guide.md +354 -0
- package/.claude/skills/bug-fixing/references/bug-record-template.md +134 -0
- package/.claude/skills/bug-fixing/references/bug-records.md +88 -0
- package/.claude/skills/bug-fixing/references/code-review-gate.md +81 -0
- package/.claude/skills/bug-fixing/references/common-bugs.md +140 -0
- package/.claude/skills/bug-fixing/references/complete-workflow.md +361 -0
- package/.claude/skills/bug-fixing/references/config-driven-fixes.md +136 -0
- package/.claude/skills/bug-fixing/references/context-isolation-protocol.md +268 -0
- package/.claude/skills/bug-fixing/references/cross-surface-regression.md +120 -0
- package/.claude/skills/bug-fixing/references/database-investigation.md +129 -0
- package/.claude/skills/bug-fixing/references/dependency-and-integrity-protocol.md +369 -0
- package/.claude/skills/bug-fixing/references/fix-completeness-checklist.md +239 -0
- package/.claude/skills/bug-fixing/references/frontend-guide.md +219 -0
- package/.claude/skills/bug-fixing/references/fullstack-joint-guide.md +123 -0
- package/.claude/skills/bug-fixing/references/functional-breakage.md +117 -0
- package/.claude/skills/bug-fixing/references/ide-lint-errors-guide.md +176 -0
- package/.claude/skills/bug-fixing/references/impact-analysis.md +511 -0
- package/.claude/skills/bug-fixing/references/investigation-checklist.md +263 -0
- package/.claude/skills/bug-fixing/references/knowledge-extraction-guide.md +531 -0
- package/.claude/skills/bug-fixing/references/knowledge-workflow.md +212 -0
- package/.claude/skills/bug-fixing/references/post-edit-quality-gate.md +30 -0
- package/.claude/skills/bug-fixing/references/python-env-and-testing.md +126 -0
- package/.claude/skills/bug-fixing/references/rca-guide.md +428 -0
- package/.claude/skills/bug-fixing/references/similar-bug-patterns.md +113 -0
- package/.claude/skills/bug-fixing/references/skill-delegation-guide.md +350 -0
- package/.claude/skills/bug-fixing/references/skill-orchestration.md +155 -0
- package/.claude/skills/bug-fixing/references/testing-strategy.md +350 -0
- package/.claude/skills/bug-fixing/references/tooling-build-scripts.md +162 -0
- package/.claude/skills/bug-fixing/references/user-input-validation.md +77 -0
- package/.claude/skills/bug-fixing/references/ux-patterns.md +158 -0
- package/.claude/skills/bug-fixing/references/windows-terminal-hygiene.md +106 -0
- package/.claude/skills/bug-fixing/references/zero-regression-matrix.md +239 -0
- package/.claude/skills/bug-fixing/references/zero-risk-protocol.md +102 -0
- package/.claude/skills/bug-fixing/scripts/format_code.py +611 -0
- package/.claude/skills/bug-fixing/scripts/generate_report_template.py +74 -0
- package/.claude/skills/bug-fixing/scripts/lint_check.py +816 -0
- package/.claude/skills/bug-fixing/scripts/requirements.txt +36 -0
- package/.claude/skills/cicd-pipeline/SKILL.md +300 -0
- package/.claude/skills/code-review/SKILL.md +535 -0
- package/.claude/skills/code-review/references/anti-pattern-scan.md +102 -0
- package/.claude/skills/code-review/references/automated-analysis.md +456 -0
- package/.claude/skills/code-review/references/backend-common-issues.md +589 -0
- package/.claude/skills/code-review/references/backend-expert-guide.md +415 -0
- package/.claude/skills/code-review/references/backend-review.md +868 -0
- package/.claude/skills/code-review/references/batch-processing-strategy.md +198 -0
- package/.claude/skills/code-review/references/call-chain-analysis-protocol.md +166 -0
- package/.claude/skills/code-review/references/common-patterns.md +321 -0
- package/.claude/skills/code-review/references/configuration-review.md +425 -0
- package/.claude/skills/code-review/references/control-flow-completeness.md +114 -0
- package/.claude/skills/code-review/references/database-review.md +298 -0
- package/.claude/skills/code-review/references/dependency-and-integrity-protocol.md +313 -0
- package/.claude/skills/code-review/references/external-standards.md +51 -0
- package/.claude/skills/code-review/references/feature-review.md +329 -0
- package/.claude/skills/code-review/references/file-review-template.md +326 -0
- package/.claude/skills/code-review/references/frontend-advanced.md +654 -0
- package/.claude/skills/code-review/references/frontend-common-issues.md +482 -0
- package/.claude/skills/code-review/references/frontend-expert-guide.md +342 -0
- package/.claude/skills/code-review/references/frontend-review.md +783 -0
- package/.claude/skills/code-review/references/fullstack-consistency.md +418 -0
- package/.claude/skills/code-review/references/fullstack-review.md +477 -0
- package/.claude/skills/code-review/references/functional-completeness.md +386 -0
- package/.claude/skills/code-review/references/hidden-bugs-detection.md +473 -0
- package/.claude/skills/code-review/references/ide-lint-errors-guide.md +173 -0
- package/.claude/skills/code-review/references/infrastructure-review.md +453 -0
- package/.claude/skills/code-review/references/iteration-review.md +264 -0
- package/.claude/skills/code-review/references/job-review.md +335 -0
- package/.claude/skills/code-review/references/layered-checklist-protocol.md +157 -0
- package/.claude/skills/code-review/references/logic-completeness.md +535 -0
- package/.claude/skills/code-review/references/mandatory-checklist.md +288 -0
- package/.claude/skills/code-review/references/multi-language-guide.md +800 -0
- package/.claude/skills/code-review/references/new-project-review.md +226 -0
- package/.claude/skills/code-review/references/non-code-files-review.md +451 -0
- package/.claude/skills/code-review/references/overlooked-issues.md +657 -0
- package/.claude/skills/code-review/references/platform-specific-review.md +195 -0
- package/.claude/skills/code-review/references/precision-analysis-protocol.md +260 -0
- package/.claude/skills/code-review/references/python-patterns.md +494 -0
- package/.claude/skills/code-review/references/rca-techniques.md +362 -0
- package/.claude/skills/code-review/references/report-template.md +430 -0
- package/.claude/skills/code-review/references/resource-limits-and-degradation.md +137 -0
- package/.claude/skills/code-review/references/review-dimensions.md +311 -0
- package/.claude/skills/code-review/references/review-guide.md +202 -0
- package/.claude/skills/code-review/references/review-knowledge-workflow.md +257 -0
- package/.claude/skills/code-review/references/review-progress-tracker-protocol.md +172 -0
- package/.claude/skills/code-review/references/review-record-template.md +195 -0
- package/.claude/skills/code-review/references/skill-orchestration.md +143 -0
- package/.claude/skills/code-review/references/ui-ux-review.md +470 -0
- package/.claude/skills/containerization/SKILL.md +313 -0
- package/.claude/skills/database-migrations/agents/database-admin.md +142 -0
- package/.claude/skills/database-migrations/agents/database-optimizer.md +144 -0
- package/.claude/skills/database-migrations/commands/migration-observability.md +408 -0
- package/.claude/skills/database-migrations/commands/sql-migrations.md +492 -0
- package/.claude/skills/finishing-a-development-branch/SKILL.md +319 -0
- package/.claude/skills/frontend-design/LICENSE.txt +177 -0
- package/.claude/skills/frontend-design/SKILL.md +587 -0
- package/.claude/skills/frontend-design/references/color-consistency.md +487 -0
- package/.claude/skills/frontend-design/references/color-palettes-full.md +657 -0
- package/.claude/skills/frontend-design/references/design-system-generator.md +285 -0
- package/.claude/skills/frontend-design/references/font-pairings-full.md +705 -0
- package/.claude/skills/frontend-design/references/industry-anti-patterns.md +281 -0
- package/.claude/skills/frontend-design/references/layout-anti-patterns.md +582 -0
- package/.claude/skills/frontend-design/references/motion-patterns.md +659 -0
- package/.claude/skills/frontend-design/references/pre-delivery-checklist.md +153 -0
- package/.claude/skills/frontend-design/references/responsive-design.md +555 -0
- package/.claude/skills/frontend-design/references/style-modification-rules.md +335 -0
- package/.claude/skills/frontend-design/references/ui-styles-full.md +383 -0
- package/.claude/skills/frontend-design/references/ui-styles-rating.md +191 -0
- package/.claude/skills/frontend-design/references/ux-guidelines.md +640 -0
- package/.claude/skills/fullstack-developer/SKILL.md +512 -0
- package/.claude/skills/fullstack-developer/references/api-contract-guide.md +312 -0
- package/.claude/skills/fullstack-developer/references/api-response-patterns.md +223 -0
- package/.claude/skills/fullstack-developer/references/async-patterns.md +220 -0
- package/.claude/skills/fullstack-developer/references/bug-prevention.md +914 -0
- package/.claude/skills/fullstack-developer/references/code-quality-checklist.md +271 -0
- package/.claude/skills/fullstack-developer/references/complete-development-workflow.md +278 -0
- package/.claude/skills/fullstack-developer/references/context-isolation-protocol.md +256 -0
- package/.claude/skills/fullstack-developer/references/database-migration.md +331 -0
- package/.claude/skills/fullstack-developer/references/dependency-and-integrity-protocol.md +390 -0
- package/.claude/skills/fullstack-developer/references/development-phases.md +333 -0
- package/.claude/skills/fullstack-developer/references/expert-guide.md +214 -0
- package/.claude/skills/fullstack-developer/references/file-import-patterns.md +114 -0
- package/.claude/skills/fullstack-developer/references/graceful-degradation-patterns.md +78 -0
- package/.claude/skills/fullstack-developer/references/ide-lint-errors-guide.md +183 -0
- package/.claude/skills/fullstack-developer/references/integration-testing.md +301 -0
- package/.claude/skills/fullstack-developer/references/mock-api-patterns.md +307 -0
- package/.claude/skills/fullstack-developer/references/phase-gate-template.md +249 -0
- package/.claude/skills/fullstack-developer/references/post-edit-quality-gate.md +30 -0
- package/.claude/skills/fullstack-developer/references/python-engineering.md +79 -0
- package/.claude/skills/fullstack-developer/references/skill-orchestration.md +214 -0
- package/.claude/skills/fullstack-developer/references/skill-router-table.md +304 -0
- package/.claude/skills/fullstack-developer/references/state-sync.md +217 -0
- package/.claude/skills/fullstack-developer/references/ui-testing-checklist.md +292 -0
- package/.claude/skills/fullstack-developer/scripts/format_code.py +611 -0
- package/.claude/skills/fullstack-developer/scripts/lint_check.py +816 -0
- package/.claude/skills/fullstack-developer/scripts/requirements.txt +36 -0
- package/.claude/skills/performance-optimization/SKILL.md +250 -0
- package/.claude/skills/product-requirements/SKILL.md +357 -0
- package/.claude/skills/product-requirements/references/acceptance-criteria.md +335 -0
- package/.claude/skills/product-requirements/references/answer-first-questioning-protocol.md +299 -0
- package/.claude/skills/product-requirements/references/competitive-analysis-guide.md +183 -0
- package/.claude/skills/product-requirements/references/document-accuracy-protocol.md +253 -0
- package/.claude/skills/product-requirements/references/document-management-protocol.md +278 -0
- package/.claude/skills/product-requirements/references/external-standards.md +62 -0
- package/.claude/skills/product-requirements/references/feature-spec-template.md +359 -0
- package/.claude/skills/product-requirements/references/knowledge-acquisition-protocol.md +251 -0
- package/.claude/skills/product-requirements/references/plan-execution-protocol.md +334 -0
- package/.claude/skills/product-requirements/references/plan-generation-protocol.md +264 -0
- package/.claude/skills/product-requirements/references/prioritization-frameworks.md +80 -0
- package/.claude/skills/product-requirements/references/requirement-decomposition-protocol.md +291 -0
- package/.claude/skills/product-requirements/references/user-story-examples.md +297 -0
- package/.claude/skills/product-requirements/references/workflow-templates.md +266 -0
- package/.claude/skills/react-best-practices/SKILL.md +198 -0
- package/.claude/skills/react-best-practices/references/advanced-patterns.md +94 -0
- package/.claude/skills/react-best-practices/references/bundle-optimization.md +182 -0
- package/.claude/skills/react-best-practices/references/client-data-fetching.md +112 -0
- package/.claude/skills/react-best-practices/references/complete-guide.md +2249 -0
- package/.claude/skills/react-best-practices/references/eliminating-waterfalls.md +169 -0
- package/.claude/skills/react-best-practices/references/javascript-performance.md +256 -0
- package/.claude/skills/react-best-practices/references/rendering-performance.md +230 -0
- package/.claude/skills/react-best-practices/references/rerender-optimization.md +214 -0
- package/.claude/skills/react-best-practices/references/server-performance.md +182 -0
- package/.claude/skills/security-audit/SKILL.md +226 -0
- package/.claude/skills/shared-references/advanced-debugging-techniques.md +186 -0
- package/.claude/skills/shared-references/code-quality-checklist.md +218 -0
- package/.claude/skills/shared-references/code-review-efficiency-guide.md +125 -0
- package/.claude/skills/shared-references/mcp-dependency-compatibility-protocol.md +276 -0
- package/.claude/skills/shared-references/skill-call-graph.md +230 -0
- package/.claude/skills/shared-references/skill-orchestration-protocol.md +281 -0
- package/.claude/skills/shared-references/subagent-dispatch-templates.md +199 -0
- package/.claude/skills/skill-expert-skills/LICENSE.txt +204 -0
- package/.claude/skills/skill-expert-skills/QUICK_NAVIGATION.md +374 -0
- package/.claude/skills/skill-expert-skills/SKILL.md +247 -0
- package/.claude/skills/skill-expert-skills/docs/_index.md +91 -0
- package/.claude/skills/skill-expert-skills/references/deep-research-methodology.md +389 -0
- package/.claude/skills/skill-expert-skills/references/docs-generation-workflow.md +398 -0
- package/.claude/skills/skill-expert-skills/references/domain-expertise-protocol.md +343 -0
- package/.claude/skills/skill-expert-skills/references/domain-knowledge/_index.md +54 -0
- package/.claude/skills/skill-expert-skills/references/domain-knowledge/backend-expertise.md +517 -0
- package/.claude/skills/skill-expert-skills/references/domain-knowledge/bug-fixing-expertise.md +363 -0
- package/.claude/skills/skill-expert-skills/references/domain-knowledge/code-review-expertise.md +392 -0
- package/.claude/skills/skill-expert-skills/references/domain-knowledge/frontend-expertise.md +410 -0
- package/.claude/skills/skill-expert-skills/references/domain-knowledge-template.md +503 -0
- package/.claude/skills/skill-expert-skills/references/examples.md +782 -0
- package/.claude/skills/skill-expert-skills/references/integration-examples.md +655 -0
- package/.claude/skills/skill-expert-skills/references/knowledge-validation-checklist.md +246 -0
- package/.claude/skills/skill-expert-skills/references/latest-knowledge-acquisition.md +461 -0
- package/.claude/skills/skill-expert-skills/references/mcp-tools-guide.md +439 -0
- package/.claude/skills/skill-expert-skills/references/official-best-practices.md +616 -0
- package/.claude/skills/skill-expert-skills/references/patterns.md +218 -0
- package/.claude/skills/skill-expert-skills/references/plugin-skills-guide.md +432 -0
- package/.claude/skills/skill-expert-skills/references/requirement-elicitation-protocol.md +290 -0
- package/.claude/skills/skill-expert-skills/references/skill-creator-SKILL.md +353 -0
- package/.claude/skills/skill-expert-skills/references/skill-templates.md +583 -0
- package/.claude/skills/skill-expert-skills/references/skills-knowledge-base.md +561 -0
- package/.claude/skills/skill-expert-skills/references/tools-guide.md +379 -0
- package/.claude/skills/skill-expert-skills/references/troubleshooting.md +378 -0
- package/.claude/skills/skill-expert-skills/references/universality-guide.md +205 -0
- package/.claude/skills/skill-expert-skills/references/writing-style-guide.md +466 -0
- package/.claude/skills/skill-expert-skills/scripts/__pycache__/quick_validate.cpython-313.pyc +0 -0
- package/.claude/skills/skill-expert-skills/scripts/__pycache__/universal_validate.cpython-313.pyc +0 -0
- package/.claude/skills/skill-expert-skills/scripts/analyze_trigger.py +425 -0
- package/.claude/skills/skill-expert-skills/scripts/diff_with_official.py +188 -0
- package/.claude/skills/skill-expert-skills/scripts/init_skill.py +349 -0
- package/.claude/skills/skill-expert-skills/scripts/package_skill.py +156 -0
- package/.claude/skills/skill-expert-skills/scripts/quick_validate.py +493 -0
- package/.claude/skills/skill-expert-skills/scripts/requirements.txt +2 -0
- package/.claude/skills/skill-expert-skills/scripts/universal_validate.py +182 -0
- package/.claude/skills/skill-expert-skills/scripts/upgrade_skill.py +431 -0
- package/.claude/skills/subagent-driven-development/SKILL.md +268 -0
- package/.claude/skills/test-driven-development/SKILL.md +246 -0
- package/.claude/skills/test-driven-development/references/testing-anti-patterns.md +192 -0
- package/.claude/skills/using-git-worktrees/SKILL.md +266 -0
- package/.claude/skills/using-skillstack/SKILL.md +127 -0
- package/.claude/skills/vercel-deploy/SKILL.md +166 -0
- package/.claude/skills/vercel-deploy/scripts/deploy.sh +249 -0
- package/.claude/skills/verification-before-completion/SKILL.md +305 -0
- package/.claude/skills/writing-plans/SKILL.md +259 -0
- package/README.md +69 -0
- package/bin/cli.js +468 -0
- package/lib/init.js +333 -0
- package/package.json +29 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Frontend-Backend Integration Testing
|
|
2
|
+
|
|
3
|
+
> Verify the full data flow works end-to-end.
|
|
4
|
+
|
|
5
|
+
## Integration Test Workflow
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ INTEGRATION FLOW │
|
|
10
|
+
├─────────────────────────────────────────────────────────────┤
|
|
11
|
+
│ │
|
|
12
|
+
│ User Action → Frontend → API Call → Backend → Database │
|
|
13
|
+
│ │ │
|
|
14
|
+
│ └───────────────────────────────────────────────────┐ │
|
|
15
|
+
│ │ │
|
|
16
|
+
│ UI Update ← Frontend ← Response ← Backend ← Database │ │
|
|
17
|
+
│ │
|
|
18
|
+
└─────────────────────────────────────────────────────────────┘
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Contract Verification
|
|
24
|
+
|
|
25
|
+
### Step 1: Compare API Specs
|
|
26
|
+
|
|
27
|
+
| Frontend Expects | Backend Provides | Match? |
|
|
28
|
+
|------------------|------------------|--------|
|
|
29
|
+
| `GET /api/users` | `GET /api/users` | ✅ |
|
|
30
|
+
| `{ data: User[] }` | `{ data: User[] }` | ✅ |
|
|
31
|
+
| `User.name` (string) | `User.name` (string) | ✅ |
|
|
32
|
+
| `User.createdAt` | `User.created_at` | ❌ Mismatch! |
|
|
33
|
+
|
|
34
|
+
### Step 2: Field Mapping
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Common mismatches to check
|
|
38
|
+
const fieldMappingChecks = {
|
|
39
|
+
// Naming convention differences
|
|
40
|
+
'created_at': 'createdAt', // snake_case vs camelCase
|
|
41
|
+
'user_id': 'userId',
|
|
42
|
+
|
|
43
|
+
// Type differences
|
|
44
|
+
'id': 'number vs string',
|
|
45
|
+
'date': 'ISO string vs Date object',
|
|
46
|
+
'amount': 'number vs string',
|
|
47
|
+
|
|
48
|
+
// Nesting differences
|
|
49
|
+
'user.profile.name': 'user.name',
|
|
50
|
+
'data.items': 'items',
|
|
51
|
+
};
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Step 3: Response Transformation
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// If backend uses snake_case, frontend uses camelCase
|
|
58
|
+
function transformResponse<T>(data: any): T {
|
|
59
|
+
if (Array.isArray(data)) {
|
|
60
|
+
return data.map(transformResponse) as T;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (data !== null && typeof data === 'object') {
|
|
64
|
+
return Object.keys(data).reduce((result, key) => {
|
|
65
|
+
const camelKey = key.replace(/_([a-z])/g, g => g[1].toUpperCase());
|
|
66
|
+
result[camelKey] = transformResponse(data[key]);
|
|
67
|
+
return result;
|
|
68
|
+
}, {} as any);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Integration Test Checklist
|
|
78
|
+
|
|
79
|
+
### For Each Endpoint
|
|
80
|
+
|
|
81
|
+
```markdown
|
|
82
|
+
## Endpoint: [METHOD] [PATH]
|
|
83
|
+
|
|
84
|
+
### Request
|
|
85
|
+
- [ ] URL is correct
|
|
86
|
+
- [ ] HTTP method is correct
|
|
87
|
+
- [ ] Headers are set (Auth, Content-Type)
|
|
88
|
+
- [ ] Query params serialized correctly
|
|
89
|
+
- [ ] Request body format matches spec
|
|
90
|
+
|
|
91
|
+
### Response
|
|
92
|
+
- [ ] Status code handled correctly
|
|
93
|
+
- [ ] Response body parsed correctly
|
|
94
|
+
- [ ] All fields mapped correctly
|
|
95
|
+
- [ ] Nested objects work
|
|
96
|
+
- [ ] Arrays work
|
|
97
|
+
- [ ] Null/undefined handled
|
|
98
|
+
|
|
99
|
+
### Error Handling
|
|
100
|
+
- [ ] 400 Bad Request → validation message
|
|
101
|
+
- [ ] 401 Unauthorized → redirect to login
|
|
102
|
+
- [ ] 403 Forbidden → permission denied UI
|
|
103
|
+
- [ ] 404 Not Found → not found UI
|
|
104
|
+
- [ ] 500 Server Error → generic error UI
|
|
105
|
+
- [ ] Network Error → connectivity message
|
|
106
|
+
|
|
107
|
+
### Edge Cases
|
|
108
|
+
- [ ] Empty response
|
|
109
|
+
- [ ] Large dataset
|
|
110
|
+
- [ ] Slow response (loading state)
|
|
111
|
+
- [ ] Timeout
|
|
112
|
+
- [ ] Concurrent requests
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Test Scenarios
|
|
118
|
+
|
|
119
|
+
### CRUD Operations
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
describe('User CRUD Integration', () => {
|
|
123
|
+
describe('Create User', () => {
|
|
124
|
+
it('creates user with valid data', async () => {
|
|
125
|
+
// Arrange
|
|
126
|
+
const userData = { name: 'Test', email: 'test@example.com' };
|
|
127
|
+
|
|
128
|
+
// Act
|
|
129
|
+
const result = await api.createUser(userData);
|
|
130
|
+
|
|
131
|
+
// Assert
|
|
132
|
+
expect(result.id).toBeDefined();
|
|
133
|
+
expect(result.name).toBe(userData.name);
|
|
134
|
+
expect(result.email).toBe(userData.email);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('shows validation errors for invalid data', async () => {
|
|
138
|
+
// Arrange
|
|
139
|
+
const invalidData = { name: '', email: 'invalid' };
|
|
140
|
+
|
|
141
|
+
// Act & Assert
|
|
142
|
+
await expect(api.createUser(invalidData)).rejects.toMatchObject({
|
|
143
|
+
status: 422,
|
|
144
|
+
errors: expect.objectContaining({
|
|
145
|
+
name: expect.any(String),
|
|
146
|
+
email: expect.any(String)
|
|
147
|
+
})
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('Read Users', () => {
|
|
153
|
+
it('fetches paginated user list', async () => {
|
|
154
|
+
const result = await api.getUsers({ page: 1, limit: 10 });
|
|
155
|
+
|
|
156
|
+
expect(result.data).toBeInstanceOf(Array);
|
|
157
|
+
expect(result.total).toBeGreaterThanOrEqual(0);
|
|
158
|
+
expect(result.data.length).toBeLessThanOrEqual(10);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('fetches single user by ID', async () => {
|
|
162
|
+
const user = await api.getUser(1);
|
|
163
|
+
|
|
164
|
+
expect(user.id).toBe(1);
|
|
165
|
+
expect(user.name).toBeDefined();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('returns 404 for non-existent user', async () => {
|
|
169
|
+
await expect(api.getUser(99999)).rejects.toMatchObject({
|
|
170
|
+
status: 404
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('Update User', () => {
|
|
176
|
+
it('updates user with valid data', async () => {
|
|
177
|
+
const updates = { name: 'Updated Name' };
|
|
178
|
+
const result = await api.updateUser(1, updates);
|
|
179
|
+
|
|
180
|
+
expect(result.name).toBe('Updated Name');
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe('Delete User', () => {
|
|
185
|
+
it('deletes user successfully', async () => {
|
|
186
|
+
await expect(api.deleteUser(1)).resolves.not.toThrow();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Authentication Flow
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
describe('Auth Integration', () => {
|
|
196
|
+
it('completes login flow', async () => {
|
|
197
|
+
// 1. Submit login form
|
|
198
|
+
const response = await api.login({ email: 'user@test.com', password: 'password' });
|
|
199
|
+
|
|
200
|
+
// 2. Token received
|
|
201
|
+
expect(response.token).toBeDefined();
|
|
202
|
+
|
|
203
|
+
// 3. Token stored
|
|
204
|
+
expect(localStorage.getItem('token')).toBe(response.token);
|
|
205
|
+
|
|
206
|
+
// 4. Subsequent requests include token
|
|
207
|
+
const profile = await api.getProfile();
|
|
208
|
+
expect(profile.email).toBe('user@test.com');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('handles invalid credentials', async () => {
|
|
212
|
+
await expect(
|
|
213
|
+
api.login({ email: 'wrong@test.com', password: 'wrong' })
|
|
214
|
+
).rejects.toMatchObject({ status: 401 });
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('handles expired token', async () => {
|
|
218
|
+
// Set expired token
|
|
219
|
+
localStorage.setItem('token', 'expired_token');
|
|
220
|
+
|
|
221
|
+
// Request should fail and redirect to login
|
|
222
|
+
await expect(api.getProfile()).rejects.toMatchObject({ status: 401 });
|
|
223
|
+
|
|
224
|
+
// Should trigger logout/redirect
|
|
225
|
+
expect(localStorage.getItem('token')).toBeNull();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Data Flow
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
describe('Data Flow Integration', () => {
|
|
234
|
+
it('form submission to database to display', async () => {
|
|
235
|
+
// 1. User fills form
|
|
236
|
+
const formData = { title: 'New Item', description: 'Test' };
|
|
237
|
+
|
|
238
|
+
// 2. Form submits to API
|
|
239
|
+
const created = await api.createItem(formData);
|
|
240
|
+
expect(created.id).toBeDefined();
|
|
241
|
+
|
|
242
|
+
// 3. Data stored in database (backend handles)
|
|
243
|
+
|
|
244
|
+
// 4. Fetch updated list
|
|
245
|
+
const list = await api.getItems();
|
|
246
|
+
|
|
247
|
+
// 5. New item appears in list
|
|
248
|
+
expect(list.data.some(item => item.id === created.id)).toBe(true);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Common Integration Issues
|
|
256
|
+
|
|
257
|
+
| Issue | Symptom | Solution |
|
|
258
|
+
|-------|---------|----------|
|
|
259
|
+
| CORS error | Network error in browser | Backend: Add CORS headers |
|
|
260
|
+
| 401 on all requests | Always unauthorized | Check auth header format |
|
|
261
|
+
| Field missing | Data not displaying | Check field name mapping |
|
|
262
|
+
| Type error | Crash when using data | Check type transformations |
|
|
263
|
+
| Stale data | Old data after update | Invalidate cache, refetch |
|
|
264
|
+
| Race condition | Inconsistent data | Add loading state, debounce |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Integration Debug Checklist
|
|
269
|
+
|
|
270
|
+
```markdown
|
|
271
|
+
## When Integration Fails
|
|
272
|
+
|
|
273
|
+
### 1. Check Network Tab
|
|
274
|
+
- [ ] Request URL correct?
|
|
275
|
+
- [ ] Request method correct?
|
|
276
|
+
- [ ] Request headers correct?
|
|
277
|
+
- [ ] Request body correct?
|
|
278
|
+
- [ ] Response status?
|
|
279
|
+
- [ ] Response body?
|
|
280
|
+
|
|
281
|
+
### 2. Check Console
|
|
282
|
+
- [ ] Any JavaScript errors?
|
|
283
|
+
- [ ] Any CORS errors?
|
|
284
|
+
- [ ] Any network errors?
|
|
285
|
+
|
|
286
|
+
### 3. Check Backend Logs
|
|
287
|
+
- [ ] Request received?
|
|
288
|
+
- [ ] Processing error?
|
|
289
|
+
- [ ] Database error?
|
|
290
|
+
|
|
291
|
+
### 4. Compare Contracts
|
|
292
|
+
- [ ] Field names match?
|
|
293
|
+
- [ ] Data types match?
|
|
294
|
+
- [ ] Required fields present?
|
|
295
|
+
|
|
296
|
+
### 5. Test in Isolation
|
|
297
|
+
- [ ] API works in Postman/curl?
|
|
298
|
+
- [ ] Frontend works with mock?
|
|
299
|
+
- [ ] Only fails when connected?
|
|
300
|
+
```
|
|
301
|
+
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# Mock API Patterns
|
|
2
|
+
|
|
3
|
+
> Frontend should never wait for backend. Use mocks, integrate later.
|
|
4
|
+
|
|
5
|
+
## Mock Strategy
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ MOCK → REAL TRANSITION │
|
|
10
|
+
├─────────────────────────────────────────────────────────────┤
|
|
11
|
+
│ │
|
|
12
|
+
│ Phase 1: Mock Development │
|
|
13
|
+
│ ┌─────────────┐ ┌─────────────┐ │
|
|
14
|
+
│ │ Frontend │ ───► │ Mock API │ │
|
|
15
|
+
│ └─────────────┘ └─────────────┘ │
|
|
16
|
+
│ │
|
|
17
|
+
│ Phase 2: Integration │
|
|
18
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
19
|
+
│ │ Frontend │ ───► │ API Layer │ ───► │ Real API │ │
|
|
20
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
21
|
+
│ │ │
|
|
22
|
+
│ └── Toggle via config │
|
|
23
|
+
└─────────────────────────────────────────────────────────────┘
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Mock Implementation Patterns
|
|
29
|
+
|
|
30
|
+
### Pattern 1: Simple Toggle
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// config.ts
|
|
34
|
+
export const USE_MOCK = process.env.NODE_ENV === 'development' && !process.env.REAL_API;
|
|
35
|
+
|
|
36
|
+
// api/users.ts
|
|
37
|
+
import { mockUsers } from './mocks/users';
|
|
38
|
+
|
|
39
|
+
export async function getUsers() {
|
|
40
|
+
if (USE_MOCK) {
|
|
41
|
+
// Simulate network delay
|
|
42
|
+
await new Promise(r => setTimeout(r, 300));
|
|
43
|
+
return { data: mockUsers, total: mockUsers.length };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const response = await fetch('/api/users');
|
|
47
|
+
return response.json();
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Pattern 2: API Adapter
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// api/adapter.ts
|
|
55
|
+
interface ApiAdapter {
|
|
56
|
+
getUsers(): Promise<User[]>;
|
|
57
|
+
createUser(data: UserCreate): Promise<User>;
|
|
58
|
+
getUser(id: number): Promise<User>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// api/mock-adapter.ts
|
|
62
|
+
export const mockAdapter: ApiAdapter = {
|
|
63
|
+
async getUsers() {
|
|
64
|
+
await delay(200);
|
|
65
|
+
return [...mockUsers];
|
|
66
|
+
},
|
|
67
|
+
async createUser(data) {
|
|
68
|
+
await delay(300);
|
|
69
|
+
const newUser = { ...data, id: Date.now(), created_at: new Date().toISOString() };
|
|
70
|
+
mockUsers.push(newUser);
|
|
71
|
+
return newUser;
|
|
72
|
+
},
|
|
73
|
+
async getUser(id) {
|
|
74
|
+
await delay(100);
|
|
75
|
+
const user = mockUsers.find(u => u.id === id);
|
|
76
|
+
if (!user) throw new ApiError(404, 'User not found');
|
|
77
|
+
return user;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// api/real-adapter.ts
|
|
82
|
+
export const realAdapter: ApiAdapter = {
|
|
83
|
+
async getUsers() {
|
|
84
|
+
return fetchApi('/api/users');
|
|
85
|
+
},
|
|
86
|
+
async createUser(data) {
|
|
87
|
+
return fetchApi('/api/users', { method: 'POST', body: data });
|
|
88
|
+
},
|
|
89
|
+
async getUser(id) {
|
|
90
|
+
return fetchApi(`/api/users/${id}`);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// api/index.ts
|
|
95
|
+
import { USE_MOCK } from '../config';
|
|
96
|
+
export const api = USE_MOCK ? mockAdapter : realAdapter;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Pattern 3: MSW (Mock Service Worker)
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// mocks/handlers.ts
|
|
103
|
+
import { rest } from 'msw';
|
|
104
|
+
|
|
105
|
+
export const handlers = [
|
|
106
|
+
rest.get('/api/users', (req, res, ctx) => {
|
|
107
|
+
return res(
|
|
108
|
+
ctx.delay(200),
|
|
109
|
+
ctx.json({
|
|
110
|
+
data: mockUsers,
|
|
111
|
+
total: mockUsers.length
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
}),
|
|
115
|
+
|
|
116
|
+
rest.post('/api/users', async (req, res, ctx) => {
|
|
117
|
+
const body = await req.json();
|
|
118
|
+
const newUser = {
|
|
119
|
+
id: Date.now(),
|
|
120
|
+
...body,
|
|
121
|
+
created_at: new Date().toISOString()
|
|
122
|
+
};
|
|
123
|
+
return res(ctx.status(201), ctx.json(newUser));
|
|
124
|
+
}),
|
|
125
|
+
|
|
126
|
+
rest.get('/api/users/:id', (req, res, ctx) => {
|
|
127
|
+
const { id } = req.params;
|
|
128
|
+
const user = mockUsers.find(u => u.id === Number(id));
|
|
129
|
+
|
|
130
|
+
if (!user) {
|
|
131
|
+
return res(
|
|
132
|
+
ctx.status(404),
|
|
133
|
+
ctx.json({ error: 'User not found' })
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return res(ctx.json(user));
|
|
138
|
+
})
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
// mocks/browser.ts
|
|
142
|
+
import { setupWorker } from 'msw';
|
|
143
|
+
import { handlers } from './handlers';
|
|
144
|
+
|
|
145
|
+
export const worker = setupWorker(...handlers);
|
|
146
|
+
|
|
147
|
+
// main.tsx
|
|
148
|
+
if (process.env.NODE_ENV === 'development') {
|
|
149
|
+
const { worker } = await import('./mocks/browser');
|
|
150
|
+
await worker.start();
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Mock Data Generation
|
|
157
|
+
|
|
158
|
+
### Static Mock Data
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// mocks/data/users.ts
|
|
162
|
+
import type { User } from '@/types';
|
|
163
|
+
|
|
164
|
+
export const mockUsers: User[] = [
|
|
165
|
+
{
|
|
166
|
+
id: 1,
|
|
167
|
+
email: 'admin@example.com',
|
|
168
|
+
name: 'Admin User',
|
|
169
|
+
role: 'admin',
|
|
170
|
+
created_at: '2024-01-01T00:00:00Z'
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: 2,
|
|
174
|
+
email: 'user@example.com',
|
|
175
|
+
name: 'Regular User',
|
|
176
|
+
role: 'user',
|
|
177
|
+
created_at: '2024-01-15T00:00:00Z'
|
|
178
|
+
},
|
|
179
|
+
// Add more as needed
|
|
180
|
+
];
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Dynamic Mock Data (Faker)
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { faker } from '@faker-js/faker';
|
|
187
|
+
|
|
188
|
+
export function generateMockUser(overrides = {}): User {
|
|
189
|
+
return {
|
|
190
|
+
id: faker.number.int({ min: 1, max: 10000 }),
|
|
191
|
+
email: faker.internet.email(),
|
|
192
|
+
name: faker.person.fullName(),
|
|
193
|
+
role: faker.helpers.arrayElement(['admin', 'user', 'guest']),
|
|
194
|
+
created_at: faker.date.past().toISOString(),
|
|
195
|
+
...overrides
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function generateMockUsers(count: number): User[] {
|
|
200
|
+
return Array.from({ length: count }, () => generateMockUser());
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Error Simulation
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// mocks/error-scenarios.ts
|
|
210
|
+
|
|
211
|
+
export const mockWithErrors = {
|
|
212
|
+
// Simulate network error
|
|
213
|
+
async getWithNetworkError() {
|
|
214
|
+
throw new Error('Network error');
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
// Simulate 500 error
|
|
218
|
+
async getWithServerError() {
|
|
219
|
+
return {
|
|
220
|
+
status: 500,
|
|
221
|
+
body: { error: 'Internal server error' }
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
// Simulate timeout
|
|
226
|
+
async getWithTimeout() {
|
|
227
|
+
await new Promise(r => setTimeout(r, 30000));
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
// Simulate validation error
|
|
231
|
+
async createWithValidationError() {
|
|
232
|
+
return {
|
|
233
|
+
status: 422,
|
|
234
|
+
body: {
|
|
235
|
+
errors: {
|
|
236
|
+
email: 'Email is invalid',
|
|
237
|
+
password: 'Password too short'
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
// Simulate auth error
|
|
244
|
+
async getWithAuthError() {
|
|
245
|
+
return {
|
|
246
|
+
status: 401,
|
|
247
|
+
body: { error: 'Unauthorized' }
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Mock Configuration
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// config/mock.ts
|
|
259
|
+
|
|
260
|
+
export const mockConfig = {
|
|
261
|
+
// Enable/disable mocks
|
|
262
|
+
enabled: process.env.VITE_USE_MOCK === 'true',
|
|
263
|
+
|
|
264
|
+
// Simulate network delay (ms)
|
|
265
|
+
delay: {
|
|
266
|
+
min: 100,
|
|
267
|
+
max: 500
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
// Simulate random failures (for testing error handling)
|
|
271
|
+
failureRate: 0, // 0-1, set to 0.1 for 10% failures
|
|
272
|
+
|
|
273
|
+
// Log mock calls
|
|
274
|
+
logging: true
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export function delay(ms?: number) {
|
|
278
|
+
const time = ms ?? Math.random() * (mockConfig.delay.max - mockConfig.delay.min) + mockConfig.delay.min;
|
|
279
|
+
return new Promise(r => setTimeout(r, time));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function shouldFail() {
|
|
283
|
+
return Math.random() < mockConfig.failureRate;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Transition Checklist
|
|
290
|
+
|
|
291
|
+
### Before Switching to Real API
|
|
292
|
+
|
|
293
|
+
- [ ] Mock covers all endpoints
|
|
294
|
+
- [ ] Mock handles all error cases
|
|
295
|
+
- [ ] UI works with mock data
|
|
296
|
+
- [ ] Loading states implemented
|
|
297
|
+
- [ ] Error states implemented
|
|
298
|
+
|
|
299
|
+
### After Switching to Real API
|
|
300
|
+
|
|
301
|
+
- [ ] Environment config set correctly
|
|
302
|
+
- [ ] All endpoints work
|
|
303
|
+
- [ ] Auth tokens handled
|
|
304
|
+
- [ ] Data format matches
|
|
305
|
+
- [ ] Error responses handled
|
|
306
|
+
- [ ] Remove unused mock code (or keep for testing)
|
|
307
|
+
|