Skip to content

Commit b40c3c2

Browse files
Copilothotlong
andcommitted
Add Protocol TCK package (@objectql/protocol-tck)
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 0f4fdf0 commit b40c3c2

5 files changed

Lines changed: 775 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Changelog
2+
3+
## 4.0.3
4+
5+
### Added
6+
- Initial release of Protocol TCK
7+
- Core CRUD operation tests
8+
- Query operation tests (filter, pagination, sorting)
9+
- Metadata operation tests
10+
- Error handling tests
11+
- Batch operation tests
12+
- Performance benchmarking support
13+
- Comprehensive test coverage for all ObjectQL protocols
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
# ObjectQL Protocol TCK (Technology Compatibility Kit)
2+
3+
A comprehensive test suite to ensure all ObjectQL protocol implementations provide consistent behavior.
4+
5+
## Purpose
6+
7+
The Protocol TCK provides a standardized set of tests that all ObjectQL protocol implementations must pass. This ensures:
8+
9+
- **Consistency**: All protocols behave the same way for core operations
10+
- **Compatibility**: Applications can switch protocols without code changes
11+
- **Quality**: Protocols are thoroughly tested against a known specification
12+
- **Performance**: Optional benchmarks to track protocol efficiency
13+
14+
## Supported Protocols
15+
16+
- **GraphQL** - GraphQL queries, mutations, and subscriptions
17+
- **OData V4** - OData query language with $expand and $batch
18+
- **REST** - RESTful HTTP API
19+
- **JSON-RPC** - JSON-RPC 2.0 protocol
20+
21+
## Usage
22+
23+
### With Vitest
24+
25+
```typescript
26+
import { describe } from 'vitest';
27+
import { runProtocolTCK, ProtocolEndpoint } from '@objectql/protocol-tck';
28+
import { MyProtocol } from './my-protocol';
29+
30+
class MyProtocolEndpoint implements ProtocolEndpoint {
31+
async execute(operation) {
32+
// Implement protocol-specific request/response handling
33+
}
34+
35+
async getMetadata() {
36+
// Return protocol metadata
37+
}
38+
}
39+
40+
describe('MyProtocol TCK', () => {
41+
runProtocolTCK(
42+
() => new MyProtocolEndpoint(),
43+
'MyProtocol',
44+
{
45+
skip: {
46+
// Skip tests for unsupported features
47+
subscriptions: true,
48+
federation: true
49+
},
50+
timeout: 30000,
51+
performance: {
52+
enabled: true,
53+
thresholds: {
54+
create: 100, // milliseconds
55+
read: 50,
56+
update: 100,
57+
delete: 50,
58+
query: 200
59+
}
60+
}
61+
}
62+
);
63+
});
64+
```
65+
66+
## Test Categories
67+
68+
### 1. Core CRUD Operations
69+
- ✅ Create entities
70+
- ✅ Read entities by ID
71+
- ✅ Update entities
72+
- ✅ Delete entities
73+
- ✅ Auto-generated IDs
74+
- ✅ Timestamps
75+
76+
### 2. Query Operations
77+
- ✅ Query all entities
78+
- ✅ Filter by conditions
79+
- ✅ Pagination (limit/offset)
80+
- ✅ Sorting (orderBy)
81+
- ✅ Combined filters + sort + pagination
82+
83+
### 3. Metadata Operations *(optional)*
84+
- ✅ Retrieve protocol metadata
85+
- ✅ List available entities
86+
- ✅ Entity schema information
87+
88+
### 4. Error Handling
89+
- ✅ Invalid entity names
90+
- ✅ Invalid IDs
91+
- ✅ Validation errors
92+
- ✅ Protocol-specific error formats
93+
94+
### 5. Batch Operations *(optional)*
95+
- ✅ Batch create
96+
- ✅ Batch update
97+
- ✅ Batch delete
98+
- ✅ Transaction support
99+
100+
### 6. Protocol-Specific Features *(optional)*
101+
102+
#### GraphQL
103+
- ✅ Subscriptions (real-time updates)
104+
- ✅ Federation (subgraph support)
105+
- ✅ DataLoader (N+1 prevention)
106+
107+
#### OData V4
108+
- ✅ $expand (nested entities)
109+
- ✅ $batch (bulk operations)
110+
- ✅ $search (full-text search)
111+
- ✅ ETags (optimistic concurrency)
112+
113+
#### REST
114+
- ✅ OpenAPI/Swagger metadata
115+
- ✅ File uploads
116+
- ✅ Custom endpoints
117+
118+
#### JSON-RPC
119+
- ✅ Batch requests
120+
- ✅ Notification methods
121+
- ✅ Error codes
122+
123+
## Configuration
124+
125+
### Skip Options
126+
127+
Use the `skip` configuration to disable tests for features your protocol doesn't support:
128+
129+
```typescript
130+
{
131+
skip: {
132+
metadata: false, // Skip metadata tests
133+
subscriptions: true, // Skip subscription tests (GraphQL)
134+
batch: true, // Skip batch operation tests
135+
search: true, // Skip full-text search tests
136+
transactions: true, // Skip transaction tests
137+
expand: true, // Skip expand tests (OData)
138+
federation: true // Skip federation tests (GraphQL)
139+
}
140+
}
141+
```
142+
143+
### Performance Benchmarks
144+
145+
Enable performance tracking to measure protocol efficiency:
146+
147+
```typescript
148+
{
149+
performance: {
150+
enabled: true,
151+
thresholds: {
152+
create: 100, // Max 100ms average
153+
read: 50, // Max 50ms average
154+
update: 100, // Max 100ms average
155+
delete: 50, // Max 50ms average
156+
query: 200, // Max 200ms average
157+
batch: 500 // Max 500ms average
158+
}
159+
}
160+
}
161+
```
162+
163+
The TCK will:
164+
1. Measure average, min, and max execution times
165+
2. Report results after all tests complete
166+
3. Warn if averages exceed thresholds
167+
168+
### Hooks
169+
170+
Provide custom setup/teardown logic:
171+
172+
```typescript
173+
{
174+
hooks: {
175+
beforeAll: async () => {
176+
// Setup test server, database, etc.
177+
},
178+
afterAll: async () => {
179+
// Cleanup resources
180+
},
181+
beforeEach: async () => {
182+
// Clear test data between tests
183+
},
184+
afterEach: async () => {
185+
// Post-test cleanup
186+
}
187+
}
188+
}
189+
```
190+
191+
## Protocol Endpoint Interface
192+
193+
Your protocol must implement the `ProtocolEndpoint` interface:
194+
195+
```typescript
196+
interface ProtocolEndpoint {
197+
/**
198+
* Execute a protocol operation
199+
*/
200+
execute(operation: ProtocolOperation): Promise<ProtocolResponse>;
201+
202+
/**
203+
* Get protocol metadata
204+
*/
205+
getMetadata(): Promise<any>;
206+
207+
/**
208+
* Cleanup (optional)
209+
*/
210+
close?(): Promise<void>;
211+
}
212+
213+
interface ProtocolOperation {
214+
type: 'create' | 'read' | 'update' | 'delete' | 'query' | 'batch' | 'subscribe';
215+
entity: string;
216+
data?: any;
217+
id?: string;
218+
filter?: any;
219+
options?: any;
220+
}
221+
222+
interface ProtocolResponse {
223+
success: boolean;
224+
data?: any;
225+
error?: {
226+
code: string;
227+
message: string;
228+
};
229+
metadata?: any;
230+
}
231+
```
232+
233+
## Expected Behavior
234+
235+
1. **Auto-generated IDs**: If no ID is provided in create, generate a unique one
236+
2. **Timestamps**: Automatically add `created_at` and `updated_at` (if supported by engine)
237+
3. **Null Safety**: Return `null` for non-existent entities
238+
4. **Error Handling**: Return structured errors with `code` and `message`
239+
5. **Type Safety**: Preserve data types (numbers, booleans, strings)
240+
241+
## Example: GraphQL Endpoint
242+
243+
```typescript
244+
import { GraphQLPlugin } from '@objectql/protocol-graphql';
245+
import { ProtocolEndpoint } from '@objectql/protocol-tck';
246+
247+
class GraphQLEndpoint implements ProtocolEndpoint {
248+
private client: any;
249+
250+
constructor(plugin: GraphQLPlugin) {
251+
this.client = createGraphQLClient(plugin);
252+
}
253+
254+
async execute(operation) {
255+
if (operation.type === 'create') {
256+
const mutation = `
257+
mutation CreateEntity($data: ${operation.entity}Input!) {
258+
create${operation.entity}(data: $data) {
259+
id
260+
...fields
261+
}
262+
}
263+
`;
264+
const result = await this.client.mutate({ mutation, variables: { data: operation.data } });
265+
return { success: true, data: result.data[`create${operation.entity}`] };
266+
}
267+
// ... implement other operations
268+
}
269+
270+
async getMetadata() {
271+
const query = `{ __schema { types { name } } }`;
272+
const result = await this.client.query({ query });
273+
return result.data;
274+
}
275+
}
276+
```
277+
278+
## License
279+
280+
MIT
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@objectql/protocol-tck",
3+
"version": "4.0.3",
4+
"description": "Technology Compatibility Kit for ObjectQL protocols - Unified test suite",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"scripts": {
8+
"build": "tsc"
9+
},
10+
"keywords": [
11+
"objectql",
12+
"protocol",
13+
"tck",
14+
"test",
15+
"compatibility",
16+
"graphql",
17+
"odata",
18+
"rest"
19+
],
20+
"license": "MIT",
21+
"peerDependencies": {
22+
"jest": "^30.0.0",
23+
"vitest": "^1.0.0"
24+
},
25+
"peerDependenciesMeta": {
26+
"jest": {
27+
"optional": true
28+
},
29+
"vitest": {
30+
"optional": true
31+
}
32+
},
33+
"devDependencies": {
34+
"@types/jest": "^29.0.0",
35+
"typescript": "^5.3.0"
36+
}
37+
}

0 commit comments

Comments
 (0)