Skip to content

Commit a639082

Browse files
fix: exclude contract-schema.json from plugin validation tests
The contract schema definition file should not be validated as a plugin contract, as it defines the schema structure rather than implementing it.
1 parent 4e52389 commit a639082

32 files changed

+8003
-2025
lines changed

__tests__/ci/contract-schema-validation.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ describe("Contract Schema Validation", () => {
1919
describe("Plugin Contract Schema Validation", () => {
2020
test("should validate all plugin contract schemas are well-formed", async () => {
2121
const contractFiles = await fs.readdir(contractsDir);
22-
const jsonFiles = contractFiles.filter((file) => file.endsWith(".json"));
22+
const jsonFiles = contractFiles.filter(
23+
(file) => file.endsWith(".json") && file !== "contract-schema.json",
24+
);
2325

2426
expect(jsonFiles.length).toBeGreaterThan(0);
2527

__tests__/contracts/README.md

Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
# Contract Compliance Tests
2+
3+
This directory contains comprehensive contract validation tests for all plugin types in the RAG pipeline utilities.
4+
5+
## Overview
6+
7+
Contract compliance tests ensure that all plugin implementations adhere to their respective contract specifications defined in `/contracts/`. These tests validate:
8+
9+
- **Metadata structure**: Plugin name, version, and type
10+
- **Required methods**: Presence and function type validation
11+
- **Method signatures**: Parameter counts and naming conventions
12+
- **Return types**: Expected return value structures
13+
- **Contract schema**: All contracts must conform to the JSON schema defined in `contracts/contract-schema.json`
14+
15+
## Related Documentation
16+
17+
- **[Contract Schema Guide](../../docs/contract-schema-guide.md)** - Complete guide to contract schema validation, including field requirements, validation rules, and error troubleshooting
18+
- **[Plugin Registry Warnings](../../docs/plugin-registry-contract-warnings.md)** - Documentation about contract warnings in development mode
19+
20+
## Test Structure
21+
22+
```
23+
__tests__/contracts/
24+
├── contract-compliance.test.js # Plugin implementation validation
25+
├── contract-schema-validation.test.js # Contract schema validation (30 tests)
26+
├── invalid-contracts/ # Invalid contract examples
27+
│ ├── empty-methods-array.json
28+
│ ├── invalid-plugin-type.json
29+
│ ├── invalid-version-format.json
30+
│ └── missing-required-field.json
31+
├── mock-plugins/ # Test plugins
32+
│ ├── valid-loader.js
33+
│ ├── valid-embedder.js
34+
│ ├── valid-retriever.js
35+
│ ├── valid-llm.js
36+
│ ├── valid-reranker.js
37+
│ ├── invalid-loader-missing-method.js
38+
│ ├── invalid-loader-missing-metadata.js
39+
│ ├── invalid-loader-wrong-type.js
40+
│ ├── invalid-retriever-missing-method.js
41+
│ └── invalid-embedder-not-function.js
42+
└── README.md # This file
43+
```
44+
45+
## Running Tests
46+
47+
### Run all contract tests
48+
49+
```bash
50+
npm test -- __tests__/contracts/
51+
```
52+
53+
### Run specific test suites
54+
55+
```bash
56+
# Contract compliance tests (plugin implementation validation)
57+
npm test -- __tests__/contracts/contract-compliance.test.js
58+
59+
# Contract schema validation tests (JSON schema validation)
60+
npm test -- __tests__/contracts/contract-schema-validation.test.js
61+
```
62+
63+
### Run with coverage
64+
65+
```bash
66+
npm test -- __tests__/contracts/ --coverage
67+
```
68+
69+
## Test Coverage
70+
71+
The contract compliance test suite includes **45 comprehensive tests** covering:
72+
73+
### Contract Loading (9 tests)
74+
75+
- Loading individual contracts (loader, embedder, retriever, llm, reranker)
76+
- Loading all contracts at once
77+
- Error handling for missing contracts
78+
79+
### Metadata Validation (6 tests)
80+
81+
- Valid metadata structure
82+
- Missing name detection
83+
- Missing version detection
84+
- Type mismatch detection
85+
- Null plugin handling
86+
- Empty string validation
87+
88+
### Required Methods Validation (5 tests)
89+
90+
- Method presence validation
91+
- Missing method detection
92+
- Non-function property detection
93+
- Multiple required methods (retriever)
94+
95+
### Method Signature Validation (4 tests)
96+
97+
- Parameter count validation
98+
- Parameter naming validation
99+
- Missing method handling
100+
101+
### Complete Plugin Validation (10 tests)
102+
103+
- Valid plugin validation for all types (5 tests)
104+
- Invalid plugin rejection for various violations (5 tests)
105+
106+
### Batch Validation (3 tests)
107+
108+
- Multiple plugin validation
109+
- Mixed valid/invalid plugin detection
110+
- Missing contract handling
111+
112+
### Report Formatting (3 tests)
113+
114+
- Passing validation reports
115+
- Failing validation reports
116+
- Warning formatting
117+
118+
### Contract Structure (2 tests)
119+
120+
- Required field validation
121+
- Method-requirement consistency
122+
123+
### Edge Cases (3 tests)
124+
125+
- Extra methods handling
126+
- Extra metadata handling
127+
- Async method validation
128+
129+
## CI Integration
130+
131+
Contract tests are automatically executed in the CI pipeline via GitHub Actions:
132+
133+
- **Workflow**: `.github/workflows/ci.yml`
134+
- **Trigger**: Push to main/develop, pull requests
135+
- **Node versions**: 18, 20, 22
136+
- **Test command**: `npm test`
137+
138+
### CI Failure Conditions
139+
140+
The CI build will **fail** if:
141+
142+
- Any plugin violates its contract specification
143+
- Required methods are missing
144+
- Metadata is incomplete or incorrect
145+
- Method signatures don't match contract expectations
146+
147+
## Creating New Mock Plugins
148+
149+
When adding new plugin types or test cases:
150+
151+
### Valid Plugin Template
152+
153+
```javascript
154+
class ValidPluginName {
155+
constructor() {
156+
this.name = "Plugin Name";
157+
this.version = "1.0.0";
158+
this.type = "plugin-type"; // Must match contract type
159+
}
160+
161+
// Implement all required methods from contract
162+
async requiredMethod(params) {
163+
// Implementation
164+
}
165+
}
166+
167+
module.exports = ValidPluginName;
168+
```
169+
170+
### Invalid Plugin Templates
171+
172+
**Missing Method:**
173+
174+
```javascript
175+
class InvalidPluginMissingMethod {
176+
constructor() {
177+
this.name = "Invalid Plugin";
178+
this.version = "1.0.0";
179+
this.type = "plugin-type";
180+
}
181+
// Missing required method - contract violation
182+
}
183+
```
184+
185+
**Missing Metadata:**
186+
187+
```javascript
188+
class InvalidPluginMissingMetadata {
189+
constructor() {
190+
// Missing name, version, type
191+
}
192+
193+
async requiredMethod(params) {
194+
// Implementation
195+
}
196+
}
197+
```
198+
199+
**Wrong Type:**
200+
201+
```javascript
202+
class InvalidPluginWrongType {
203+
constructor() {
204+
this.name = "Invalid Plugin";
205+
this.version = "1.0.0";
206+
this.type = "wrong-type"; // Doesn't match contract
207+
}
208+
209+
async requiredMethod(params) {
210+
// Implementation
211+
}
212+
}
213+
```
214+
215+
## Contract Validator API
216+
217+
The `ContractValidator` class in `src/utils/contract-validator.js` provides:
218+
219+
### Loading Contracts
220+
221+
```javascript
222+
const validator = new ContractValidator();
223+
224+
// Load single contract
225+
const loaderContract = validator.loadContract("loader");
226+
227+
// Load all contracts
228+
const allContracts = validator.loadAllContracts();
229+
```
230+
231+
### Validating Plugins
232+
233+
```javascript
234+
// Validate single plugin
235+
const result = validator.validatePlugin(myPlugin, contract);
236+
if (!result.valid) {
237+
console.error("Errors:", result.errors);
238+
}
239+
240+
// Validate multiple plugins
241+
const plugins = [plugin1, plugin2, plugin3];
242+
const results = validator.validatePlugins(plugins, allContracts);
243+
```
244+
245+
### Generating Reports
246+
247+
```javascript
248+
const result = validator.validatePlugin(plugin, contract);
249+
const report = validator.formatValidationReport(result, "MyPlugin");
250+
console.log(report);
251+
```
252+
253+
## Adding New Plugin Types
254+
255+
To add a new plugin type:
256+
257+
1. **Create contract**: Add `new-type-contract.json` to `/contracts/`
258+
2. **Create valid plugin**: Add `valid-new-type.js` to mock-plugins/
259+
3. **Create invalid plugins**: Add test cases for common violations
260+
4. **Add tests**: Update contract-compliance.test.js with new test cases
261+
262+
### Example Contract Structure
263+
264+
```json
265+
{
266+
"$schema": "http://json-schema.org/draft-07/schema#",
267+
"type": "new-type",
268+
"version": "1.0.0",
269+
"title": "New Type Contract",
270+
"description": "Contract for new type plugins",
271+
"methods": [
272+
{
273+
"name": "methodName",
274+
"parameters": ["param1", "param2"],
275+
"returns": "returnType"
276+
}
277+
],
278+
"properties": {
279+
"methodName": {
280+
"type": "function",
281+
"description": "Method description",
282+
"parameters": {
283+
/* JSON Schema */
284+
},
285+
"returns": {
286+
/* JSON Schema */
287+
}
288+
}
289+
},
290+
"required": ["methodName"]
291+
}
292+
```
293+
294+
## Debugging Failed Tests
295+
296+
### Common Failure Scenarios
297+
298+
**Missing Method:**
299+
300+
```
301+
✗ Required method "methodName" is missing
302+
```
303+
304+
**Solution**: Implement the missing method on your plugin class
305+
306+
**Type Mismatch:**
307+
308+
```
309+
✗ Plugin type "wrong-type" does not match contract type "expected-type"
310+
```
311+
312+
**Solution**: Ensure `this.type` matches the contract type
313+
314+
**Missing Metadata:**
315+
316+
```
317+
✗ Plugin must have a valid "name" property (non-empty string)
318+
✗ Plugin must have a valid "version" property (non-empty string)
319+
```
320+
321+
**Solution**: Add name and version properties in constructor
322+
323+
**Non-Function Method:**
324+
325+
```
326+
✗ Required property "methodName" must be a function
327+
```
328+
329+
**Solution**: Ensure the property is a function, not a string or object
330+
331+
### Verbose Test Output
332+
333+
For detailed error messages:
334+
335+
```bash
336+
npm test -- __tests__/contracts/ --verbose
337+
```
338+
339+
## Best Practices
340+
341+
1. **Always validate locally** before pushing
342+
2. **Run full test suite** when modifying contracts
343+
3. **Keep mock plugins simple** - focus on contract compliance
344+
4. **Document contract changes** in commit messages
345+
5. **Test both valid and invalid cases** for new plugin types
346+
6. **Use meaningful test names** that describe the validation scenario
347+
348+
## Related Documentation
349+
350+
- [Contract Specifications](/contracts/)
351+
- [Error Context Guide](/docs/error-context-guide.md)
352+
- [Plugin Registry Contract Warnings](/docs/plugin-registry-contract-warnings.md)
353+
- [Contributing Guide](/docs/CONTRIBUTING.md)
354+
355+
## Test Metrics
356+
357+
- **Total Tests**: 45
358+
- **Test Suites**: 1
359+
- **Coverage**: 100% of contract validation logic
360+
- **Execution Time**: ~2 seconds
361+
- **Node Versions Tested**: 18, 20, 22
362+
363+
## Support
364+
365+
For questions or issues related to contract validation:
366+
367+
1. Check existing test cases in `contract-compliance.test.js`
368+
2. Review contract specifications in `/contracts/`
369+
3. See ContractValidator API in `src/utils/contract-validator.js`
370+
4. Open an issue on GitHub if problems persist

0 commit comments

Comments
 (0)