Skip to content

Commit b807cdb

Browse files
committed
add db e2e test package
1 parent 103e113 commit b807cdb

File tree

13 files changed

+1687
-1
lines changed

13 files changed

+1687
-1
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"clean": "yarn clean:dist && yarn clean:node_modules",
1515
"clean:dist": "find packages -name 'dist' -type d -exec rm -rf {} +",
1616
"clean:node_modules": "find . -name 'node_modules' -type d -exec rm -rf {} +",
17-
"clean:all": "yarn clean && rm -rf .pnp.* .yarn/cache .yarn/install-state.gz"
17+
"clean:all": "yarn clean && rm -rf .pnp.* .yarn/cache .yarn/install-state.gz",
18+
"test:e2e-db": "yarn workspace @vue-skuilder/e2e-db test:e2e",
19+
"test:e2e-db-watch": "yarn workspace @vue-skuilder/e2e-db test:watch"
1820
},
1921
"private": true,
2022
"workspaces": [

packages/e2e-db/README.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# E2E Database Testing Package
2+
3+
This package provides end-to-end testing for the `@vue-skuilder/db` package public API against a live CouchDB instance.
4+
5+
## Purpose
6+
7+
- **Public API Testing**: Tests only the exported interfaces and functions from `@vue-skuilder/db`
8+
- **Real Database Verification**: Uses raw CouchDB connections to verify actual database state changes
9+
- **Bug Prevention**: Catches interface/implementation mismatches and data persistence issues
10+
- **Consumer Perspective**: Tests from the viewpoint of packages that consume the DB layer
11+
12+
## Architecture
13+
14+
### Test Structure
15+
```
16+
src/
17+
├── setup/
18+
│ ├── database.ts # CouchDB container management
19+
│ └── jest-setup.ts # Global test configuration
20+
├── helpers/
21+
│ ├── raw-couch.ts # Direct CouchDB assertions
22+
│ ├── test-data-factory.ts # Test data generation
23+
│ └── test-utils.ts # Common test utilities
24+
└── tests/
25+
├── regression/ # Bug prevention tests
26+
└── integration/ # Cross-package scenarios
27+
```
28+
29+
### Public API Only
30+
```typescript
31+
// ✅ ALLOWED - Public API imports
32+
import { initializeDataLayer, getDataLayer } from '@vue-skuilder/db';
33+
import { UserDBInterface, CourseDBInterface } from '@vue-skuilder/db/core';
34+
35+
// ❌ FORBIDDEN - Implementation details
36+
// import { User } from '@vue-skuilder/db/impl/pouch/userDB';
37+
```
38+
39+
## Getting Started
40+
41+
### Prerequisites
42+
- CouchDB test container running (handled automatically)
43+
- Node.js 18+
44+
- Yarn workspaces
45+
46+
### Running Tests
47+
48+
#### Quick Test Run
49+
```bash
50+
# From project root
51+
yarn workspace @vue-skuilder/e2e-db test:e2e
52+
```
53+
54+
#### Development Workflow
55+
```bash
56+
# Start CouchDB manually
57+
yarn couchdb:start
58+
59+
# Run tests in watch mode
60+
yarn workspace @vue-skuilder/e2e-db test:watch
61+
62+
# Stop CouchDB when done
63+
yarn couchdb:stop
64+
```
65+
66+
#### Individual Test Files
67+
```bash
68+
yarn workspace @vue-skuilder/e2e-db test -- scheduled-review-removal.test.ts
69+
```
70+
71+
## Test Categories
72+
73+
### 1. Regression Tests
74+
Located in `src/tests/regression/`
75+
76+
**Purpose**: Prevent specific bugs from reoccurring
77+
**Example**: `scheduled-review-removal.test.ts` - Catches the `removeScheduledCardReview` interface mismatch
78+
79+
### 2. Integration Tests
80+
Located in `src/tests/integration/`
81+
82+
**Purpose**: Test cross-package workflows and real usage patterns
83+
84+
### 3. Interface Compliance Tests
85+
**Purpose**: Verify that public API contracts work as documented
86+
87+
## Raw Database Verification
88+
89+
This package's key innovation is verifying actual database state changes, not just API responses.
90+
91+
```typescript
92+
// Schedule review via public API
93+
await user.scheduleCardReview(testReview);
94+
95+
// Verify via public API
96+
const reviews = await user.getPendingReviews();
97+
expect(reviews).toHaveLength(1);
98+
99+
// ✨ CRITICAL: Verify in raw database
100+
const rawCount = await rawCouch.getScheduledReviewCount(username);
101+
expect(rawCount).toBe(1);
102+
103+
// Remove via public API
104+
await user.removeScheduledCardReview(username, reviewId);
105+
106+
// ✨ CRITICAL: Verify actual removal from database
107+
const finalCount = await rawCouch.getScheduledReviewCount(username);
108+
expect(finalCount).toBe(0); // This would catch the bug!
109+
```
110+
111+
## Test Data Management
112+
113+
### Factories
114+
```typescript
115+
const testUser = testDataFactory.createTestUser('prefix');
116+
const testCourse = testDataFactory.createTestCourse('course-name');
117+
const testReview = testDataFactory.createTestScheduledReview(username, courseId);
118+
```
119+
120+
### Cleanup
121+
- Automatic cleanup between tests
122+
- Test databases are isolated
123+
- Raw database verification ensures no test pollution
124+
125+
## Key Test Patterns
126+
127+
### Basic Interface Test
128+
```typescript
129+
it('should perform operation and persist to database', async () => {
130+
// Setup
131+
const { user, testUser, rawCouch } = await TestUtils.createUserTestContext(dataLayer, rawCouch);
132+
133+
// Act via public API
134+
await user.someOperation(params);
135+
136+
// Assert via public API
137+
const result = await user.getOperationResult();
138+
expect(result).toBeDefined();
139+
140+
// Assert via raw database
141+
const rawResult = await rawCouch.verifyOperationInDatabase(testUser.username);
142+
expect(rawResult).toBe(true);
143+
});
144+
```
145+
146+
### Consumer Pattern Test
147+
```typescript
148+
it('reproduces exact platform-ui usage pattern', async () => {
149+
// Replicate exact imports and calls from platform-ui
150+
const dataLayer = await initializeDataLayer(config);
151+
const user = await dataLayer.getUserDB(username);
152+
153+
// Use exact calling pattern from consuming package
154+
await user.removeScheduledCardReview(user.getUsername(), reviewId);
155+
156+
// Verify it actually works
157+
const removed = await rawCouch.assertReviewRemoved(username, reviewId);
158+
expect(removed).toBe(true);
159+
});
160+
```
161+
162+
## Configuration
163+
164+
### Environment Variables
165+
- Tests automatically use `localhost:5984` CouchDB instance
166+
- No authentication required for test environment
167+
- Databases prefixed with test identifiers for isolation
168+
169+
### Jest Configuration
170+
- 30-second timeout for CouchDB operations
171+
- ESM support for modern imports
172+
- Custom matchers for database assertions
173+
174+
## Custom Jest Matchers
175+
176+
```typescript
177+
// Check document existence
178+
await expect({ username, documentId }).toExistInDatabase();
179+
180+
// Check document removal
181+
await expect({ username, documentId }).toBeRemovedFromDatabase();
182+
183+
// Check scheduled review count
184+
await expect(username).toHaveScheduledReviewCount(expectedCount);
185+
```
186+
187+
## Contributing
188+
189+
### Adding New Tests
190+
191+
1. **Regression Tests**: When a bug is found, add a test in `regression/` that reproduces it
192+
2. **Integration Tests**: When adding new features, test the complete workflow
193+
3. **Public API Only**: Never import from implementation packages
194+
195+
### Test Naming Convention
196+
- `*.test.ts` for test files
197+
- Descriptive test names that explain the scenario
198+
- Group related tests in `describe` blocks
199+
200+
### Database State Verification
201+
Always verify both:
202+
1. Public API responses (what the consumer sees)
203+
2. Raw database state (what actually persisted)
204+
205+
## Troubleshooting
206+
207+
### CouchDB Connection Issues
208+
```bash
209+
# Check CouchDB status
210+
yarn couchdb:status
211+
212+
# Restart if needed
213+
yarn couchdb:stop && yarn couchdb:start
214+
```
215+
216+
### Test Timeouts
217+
- Increase timeout in Jest config if needed
218+
- Check CouchDB container health
219+
- Verify network connectivity to localhost:5984
220+
221+
### Database Cleanup Issues
222+
- Tests automatically clean up between runs
223+
- Manual cleanup: `yarn couchdb:remove && yarn couchdb:start`
224+
225+
## Examples
226+
227+
See the existing tests for patterns:
228+
- `scheduled-review-removal.test.ts` - Interface mismatch detection
229+
- More examples coming as the test suite grows
230+
231+
This package ensures the database layer works correctly for all consumers while maintaining clean architectural boundaries.

packages/e2e-db/jest.config.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
testEnvironment: 'node',
4+
setupFilesAfterEnv: ['<rootDir>/src/setup/jest-setup.ts'],
5+
testTimeout: 30000,
6+
testMatch: ['<rootDir>/src/tests/**/*.test.ts'],
7+
collectCoverageFrom: ['src/**/*.ts', '!src/setup/**', '!src/**/*.d.ts'],
8+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9+
transform: {
10+
'^.+\\.ts$': 'ts-jest',
11+
},
12+
moduleNameMapper: {
13+
'^@/(.*)$': '<rootDir>/src/$1'
14+
},
15+
transformIgnorePatterns: [
16+
'node_modules/(?!(@vue-skuilder)/)'
17+
]
18+
};

packages/e2e-db/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "@vue-skuilder/e2e-db",
3+
"version": "0.1.0",
4+
"private": true,
5+
"description": "End-to-end tests for database layer public API",
6+
7+
"scripts": {
8+
"test": "jest",
9+
"test:watch": "jest --watch",
10+
"test:coverage": "jest --coverage",
11+
"db:start": "cd ../../ && yarn couchdb:start",
12+
"db:stop": "cd ../../ && yarn couchdb:stop",
13+
"test:e2e": "yarn db:start && yarn test && yarn db:stop",
14+
"type-check": "tsc --noEmit"
15+
},
16+
"dependencies": {
17+
"@vue-skuilder/common": "workspace:*",
18+
"@vue-skuilder/db": "workspace:*",
19+
"moment": "^2.29.4",
20+
"nano": "^10.1.3"
21+
},
22+
"devDependencies": {
23+
"@types/jest": "^29.5.5",
24+
"@types/nano": "^9.0.15",
25+
"jest": "^29.7.0",
26+
"ts-jest": "^29.1.1",
27+
"typescript": "~5.7.2"
28+
}
29+
}

0 commit comments

Comments
 (0)