wjttc 1.0.2 → 1.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/README.md CHANGED
@@ -9,12 +9,23 @@
9
9
 
10
10
  ---
11
11
 
12
+ ## What is WJTTC?
13
+
14
+ WJTTC is the **WolfeJam Technical Testing Certification**. wolfejam is the dev who created the [IANA-registered .faf format](https://www.iana.org/assignments/media-types/application/vnd.faf+yaml) for AI context - the first and only MCP of its kind. He achieved this largely due to his obsession with technical details and testing.
15
+
16
+ WJTTC is the rollout of his self-certification secrets to help grade other MCP servers for free, with a view to improving MCP server quality system-wide.
17
+
18
+ **Score your Server for free. Full leaderboard going live soon - what will your server score?**
19
+
20
+ ---
21
+
12
22
  ## What is Big Orange?
13
23
 
14
- The 🍊 **Big Orange** is a super-score - recognition that an MCP server is above and beyond the standard.
24
+ The 🍊 **Big Orange** is a super-score - recognition that the Server Owner(s) have gone above and beyond the 100% pass rate.
15
25
 
16
- - **100%** = Pass all 46 tests across ALL 7 tiers
26
+ - **100%** = Pass all 49 scored tests across ALL 9 tiers (Tiers 1-8)
17
27
  - **+5%** = Awarded for documentation and professional polish
28
+ - **Tier 9** = TAF Receipt Validation (informational only, doesn't affect score)
18
29
 
19
30
  The 🍊, much like a Michelin Star for a restaurant, is awarded for excellence and well-deserved for Best-of-Class MCP servers.
20
31
 
@@ -26,16 +37,16 @@ The 🍊, much like a Michelin Star for a restaurant, is awarded for excellence
26
37
 
27
38
  ## Certification Tiers
28
39
 
29
- | Tier | Score | Badge | Meaning |
30
- |------|-------|-------|---------|
31
- | Big Orange | 105% | 🍊 | *The Michelin Star - Perfection + Excellence* |
32
- | Trophy | 100% | 🏆 | Perfect MCP compliance |
33
- | Gold | 99%+ | 🥇 | Exceptional |
34
- | Silver | 95%+ | 🥈 | Top tier - Excellent |
35
- | Bronze | 85%+ | 🥉 | Strong - Production ready |
36
- | Green | 70%+ | 🟢 | Good - Solid foundation |
37
- | Yellow | 55%+ | 🟡 | Caution - Needs improvement |
38
- | Red | <55% | 🔴 | Critical - Major work needed |
40
+ | Badge | Tier | Score | Meaning |
41
+ |-------|------|-------|---------|
42
+ | 🍊 | Big Orange | 105% | The Michelin Star of MCP servers |
43
+ | 🏆 | Trophy | 100% | Perfect - 100% pass rate |
44
+ | 🥇 | Gold | 99%+ | Exceptional |
45
+ | 🥈 | Silver | 95%+ | Excellent, room for polish |
46
+ | 🥉 | Bronze | 85%+ | Production ready (minimum recommended) |
47
+ | 🟢 | Green | 70%+ | Solid foundation |
48
+ | 🟡 | Yellow | 55%+ | Needs improvement |
49
+ | 🔴 | Red | <55% | Critical issues |
39
50
 
40
51
  ---
41
52
 
@@ -48,7 +59,7 @@ npx wjttc certify --mcp "npx your-mcp-server"
48
59
  # Example output:
49
60
  # 🍊 CERTIFICATION: BIG-ORANGE
50
61
  # Score: 105/100
51
- # Tests: 46/46 passed
62
+ # Tests: 49/49 passed (+ 3 validation checks)
52
63
  ```
53
64
 
54
65
  ---
@@ -65,7 +76,7 @@ npx wjttc certify --mcp "npx your-mcp-server"
65
76
 
66
77
  ## Test System
67
78
 
68
- **46 tests across 7 tiers:**
79
+ **52 tests across 9 tiers** (49 scored + 3 validation checks):
69
80
 
70
81
  | Tier | Name | Weight | Tests |
71
82
  |------|------|--------|-------|
@@ -76,6 +87,10 @@ npx wjttc certify --mcp "npx your-mcp-server"
76
87
  | 5 | Security Validation | 15% | 3 |
77
88
  | 6 | Performance Benchmarks | 15% | 6 |
78
89
  | 7 | Integration Readiness | 10% | 5 |
90
+ | 8 | FAF Documentation | 5% | 3 |
91
+ | 9 | TAF Receipt Validation | Informational | 3 |
92
+
93
+ **Note:** Tier 9 validates `.taf` receipt files but doesn't affect the 0-100% score. It provides proof of testing history over time.
79
94
 
80
95
  ---
81
96
 
@@ -0,0 +1,6 @@
1
+ /**
2
+ * WJTTC Badge Generator Tests
3
+ * Testing the testing tool - F1 grade
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=badge.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/badge.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /**
3
+ * WJTTC Badge Generator Tests
4
+ * Testing the testing tool - F1 grade
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const badge_1 = require("../badge");
8
+ describe('BadgeGenerator', () => {
9
+ describe('generate()', () => {
10
+ it('should generate valid badge JSON for big-orange tier', () => {
11
+ const badge = badge_1.BadgeGenerator.generate({ score: 105, tier: 'big-orange' });
12
+ expect(badge.schemaVersion).toBe(1);
13
+ expect(badge.label).toBe('WJTTC');
14
+ expect(badge.message).toContain('big-orange');
15
+ expect(badge.message).toContain('105%');
16
+ expect(badge.color).toBe('FF8C00');
17
+ });
18
+ it('should generate valid badge JSON for trophy tier', () => {
19
+ const badge = badge_1.BadgeGenerator.generate({ score: 100, tier: 'trophy' });
20
+ expect(badge.message).toContain('trophy');
21
+ expect(badge.message).toContain('100%');
22
+ expect(badge.color).toBe('FFD700');
23
+ });
24
+ it('should generate valid badge JSON for silver tier', () => {
25
+ const badge = badge_1.BadgeGenerator.generate({ score: 95, tier: 'silver' });
26
+ expect(badge.message).toContain('silver');
27
+ expect(badge.message).toContain('95%');
28
+ expect(badge.color).toBe('C0C0C0');
29
+ });
30
+ it('should generate valid badge JSON for bronze tier', () => {
31
+ const badge = badge_1.BadgeGenerator.generate({ score: 85, tier: 'bronze' });
32
+ expect(badge.message).toContain('bronze');
33
+ expect(badge.color).toBe('CD7F32');
34
+ });
35
+ it('should generate valid badge JSON for red tier', () => {
36
+ const badge = badge_1.BadgeGenerator.generate({ score: 40, tier: 'red' });
37
+ expect(badge.message).toContain('red');
38
+ expect(badge.color).toBe('D50000');
39
+ });
40
+ it('should include correct emoji for each tier', () => {
41
+ const tiers = ['big-orange', 'trophy', 'gold', 'silver', 'bronze', 'green', 'yellow', 'red', 'white'];
42
+ const emojis = ['🍊', '🏆', '🥇', '🥈', '🥉', '🟢', '🟡', '🔴', '🤍'];
43
+ tiers.forEach((tier, index) => {
44
+ const badge = badge_1.BadgeGenerator.generate({ score: 100, tier });
45
+ expect(badge.message).toContain(emojis[index]);
46
+ });
47
+ });
48
+ });
49
+ describe('generateUrl()', () => {
50
+ it('should generate a valid shields.io URL', () => {
51
+ const url = badge_1.BadgeGenerator.generateUrl({ score: 95, tier: 'silver' });
52
+ expect(url).toContain('https://img.shields.io/endpoint');
53
+ expect(url).toContain('data:application/json');
54
+ });
55
+ it('should include encoded badge data in URL', () => {
56
+ const url = badge_1.BadgeGenerator.generateUrl({ score: 105, tier: 'big-orange' });
57
+ expect(url).toContain('WJTTC');
58
+ expect(url).toContain('FF8C00');
59
+ });
60
+ });
61
+ describe('generateMarkdown()', () => {
62
+ it('should generate valid markdown without repo URL', () => {
63
+ const md = badge_1.BadgeGenerator.generateMarkdown({ score: 95, tier: 'silver' });
64
+ expect(md).toMatch(/^!\[WJTTC silver\]\(https:\/\/img\.shields\.io/);
65
+ });
66
+ it('should generate linked markdown with repo URL', () => {
67
+ const md = badge_1.BadgeGenerator.generateMarkdown({ score: 105, tier: 'big-orange' }, 'https://github.com/example/repo');
68
+ expect(md).toMatch(/^\[!\[WJTTC big-orange\]/);
69
+ expect(md).toContain('https://github.com/example/repo');
70
+ });
71
+ });
72
+ describe('generateHtml()', () => {
73
+ it('should generate valid HTML img tag without repo URL', () => {
74
+ const html = badge_1.BadgeGenerator.generateHtml({ score: 85, tier: 'bronze' });
75
+ expect(html).toMatch(/^<img src="https:\/\/img\.shields\.io/);
76
+ expect(html).toContain('alt="WJTTC bronze"');
77
+ });
78
+ it('should generate linked HTML with repo URL', () => {
79
+ const html = badge_1.BadgeGenerator.generateHtml({ score: 100, tier: 'trophy' }, 'https://github.com/example/repo');
80
+ expect(html).toMatch(/^<a href="https:\/\/github\.com\/example\/repo">/);
81
+ expect(html).toContain('<img');
82
+ expect(html).toContain('</a>');
83
+ });
84
+ });
85
+ });
86
+ //# sourceMappingURL=badge.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.test.js","sourceRoot":"","sources":["../../src/__tests__/badge.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * WJTTC Certifier Tests
3
+ * Comprehensive tests for the core certification engine
4
+ * "Testing the tester" - F1 Championship Grade
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=certifier.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certifier.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/certifier.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,451 @@
1
+ "use strict";
2
+ /**
3
+ * WJTTC Certifier Tests
4
+ * Comprehensive tests for the core certification engine
5
+ * "Testing the tester" - F1 Championship Grade
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
9
+ // TIER SYSTEM CONSTANTS (extracted for testing)
10
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11
+ const TIER_NAMES = {
12
+ 1: 'Protocol Compliance',
13
+ 2: 'Capability Negotiation',
14
+ 3: 'Tool Integrity',
15
+ 4: 'Resource Management',
16
+ 5: 'Security Validation',
17
+ 6: 'Performance Benchmarks',
18
+ 7: 'Integration Readiness',
19
+ };
20
+ const TIER_WEIGHTS = {
21
+ 1: 20,
22
+ 2: 10,
23
+ 3: 20,
24
+ 4: 10,
25
+ 5: 15,
26
+ 6: 15,
27
+ 7: 10,
28
+ };
29
+ const TIER_TEST_COUNTS = {
30
+ 1: 12,
31
+ 2: 8,
32
+ 3: 6,
33
+ 4: 6,
34
+ 5: 3,
35
+ 6: 6,
36
+ 7: 5,
37
+ };
38
+ // Score tier boundaries
39
+ const TIER_BOUNDARIES = [
40
+ { min: 105, max: 105, tier: 'big-orange' },
41
+ { min: 100, max: 104, tier: 'trophy' },
42
+ { min: 99, max: 99, tier: 'gold' },
43
+ { min: 95, max: 98, tier: 'silver' },
44
+ { min: 85, max: 94, tier: 'bronze' },
45
+ { min: 70, max: 84, tier: 'green' },
46
+ { min: 55, max: 69, tier: 'yellow' },
47
+ { min: 0, max: 54, tier: 'red' },
48
+ ];
49
+ // Helper to determine tier from score
50
+ function getTierFromScore(score) {
51
+ if (score >= 105)
52
+ return 'big-orange';
53
+ if (score >= 100)
54
+ return 'trophy';
55
+ if (score >= 99)
56
+ return 'gold';
57
+ if (score >= 95)
58
+ return 'silver';
59
+ if (score >= 85)
60
+ return 'bronze';
61
+ if (score >= 70)
62
+ return 'green';
63
+ if (score >= 55)
64
+ return 'yellow';
65
+ return 'red';
66
+ }
67
+ // Helper to calculate weighted score (mirrors certifier logic)
68
+ function calculateWeightedScore(tierResults) {
69
+ let weightedScore = 0;
70
+ let totalWeight = 0;
71
+ for (const result of tierResults) {
72
+ const weight = TIER_WEIGHTS[result.tier] || 10;
73
+ const tierScore = result.totalTests > 0
74
+ ? (result.passedTests / result.totalTests) * 100
75
+ : 0;
76
+ weightedScore += tierScore * weight;
77
+ totalWeight += weight;
78
+ }
79
+ return totalWeight > 0 ? Math.round(weightedScore / totalWeight) : 0;
80
+ }
81
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
82
+ // TIER SYSTEM TESTS
83
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
84
+ describe('Tier System', () => {
85
+ describe('Tier Names', () => {
86
+ it('should have exactly 7 tiers', () => {
87
+ expect(Object.keys(TIER_NAMES)).toHaveLength(7);
88
+ });
89
+ it('should have tier 1 as Protocol Compliance', () => {
90
+ expect(TIER_NAMES[1]).toBe('Protocol Compliance');
91
+ });
92
+ it('should have tier 2 as Capability Negotiation', () => {
93
+ expect(TIER_NAMES[2]).toBe('Capability Negotiation');
94
+ });
95
+ it('should have tier 3 as Tool Integrity', () => {
96
+ expect(TIER_NAMES[3]).toBe('Tool Integrity');
97
+ });
98
+ it('should have tier 4 as Resource Management', () => {
99
+ expect(TIER_NAMES[4]).toBe('Resource Management');
100
+ });
101
+ it('should have tier 5 as Security Validation', () => {
102
+ expect(TIER_NAMES[5]).toBe('Security Validation');
103
+ });
104
+ it('should have tier 6 as Performance Benchmarks', () => {
105
+ expect(TIER_NAMES[6]).toBe('Performance Benchmarks');
106
+ });
107
+ it('should have tier 7 as Integration Readiness', () => {
108
+ expect(TIER_NAMES[7]).toBe('Integration Readiness');
109
+ });
110
+ });
111
+ describe('Tier Weights', () => {
112
+ it('should have exactly 7 tier weights', () => {
113
+ expect(Object.keys(TIER_WEIGHTS)).toHaveLength(7);
114
+ });
115
+ it('should have weights that sum to 100', () => {
116
+ const totalWeight = Object.values(TIER_WEIGHTS).reduce((a, b) => a + b, 0);
117
+ expect(totalWeight).toBe(100);
118
+ });
119
+ it('should have Protocol Compliance (T1) weighted at 20%', () => {
120
+ expect(TIER_WEIGHTS[1]).toBe(20);
121
+ });
122
+ it('should have Capability Negotiation (T2) weighted at 10%', () => {
123
+ expect(TIER_WEIGHTS[2]).toBe(10);
124
+ });
125
+ it('should have Tool Integrity (T3) weighted at 20%', () => {
126
+ expect(TIER_WEIGHTS[3]).toBe(20);
127
+ });
128
+ it('should have Resource Management (T4) weighted at 10%', () => {
129
+ expect(TIER_WEIGHTS[4]).toBe(10);
130
+ });
131
+ it('should have Security Validation (T5) weighted at 15%', () => {
132
+ expect(TIER_WEIGHTS[5]).toBe(15);
133
+ });
134
+ it('should have Performance Benchmarks (T6) weighted at 15%', () => {
135
+ expect(TIER_WEIGHTS[6]).toBe(15);
136
+ });
137
+ it('should have Integration Readiness (T7) weighted at 10%', () => {
138
+ expect(TIER_WEIGHTS[7]).toBe(10);
139
+ });
140
+ });
141
+ describe('Test Counts', () => {
142
+ it('should have 46 total tests across all tiers', () => {
143
+ const totalTests = Object.values(TIER_TEST_COUNTS).reduce((a, b) => a + b, 0);
144
+ expect(totalTests).toBe(46);
145
+ });
146
+ it('should have 12 tests in Tier 1', () => {
147
+ expect(TIER_TEST_COUNTS[1]).toBe(12);
148
+ });
149
+ it('should have 8 tests in Tier 2', () => {
150
+ expect(TIER_TEST_COUNTS[2]).toBe(8);
151
+ });
152
+ it('should have 6 tests in Tier 3', () => {
153
+ expect(TIER_TEST_COUNTS[3]).toBe(6);
154
+ });
155
+ it('should have 6 tests in Tier 4', () => {
156
+ expect(TIER_TEST_COUNTS[4]).toBe(6);
157
+ });
158
+ it('should have 3 tests in Tier 5', () => {
159
+ expect(TIER_TEST_COUNTS[5]).toBe(3);
160
+ });
161
+ it('should have 6 tests in Tier 6', () => {
162
+ expect(TIER_TEST_COUNTS[6]).toBe(6);
163
+ });
164
+ it('should have 5 tests in Tier 7', () => {
165
+ expect(TIER_TEST_COUNTS[7]).toBe(5);
166
+ });
167
+ });
168
+ });
169
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
170
+ // SCORE CALCULATION TESTS
171
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
172
+ describe('Score Calculation', () => {
173
+ describe('Weighted Score Algorithm', () => {
174
+ it('should return 100 when all tests pass', () => {
175
+ const allPassing = Object.entries(TIER_TEST_COUNTS).map(([tier, count]) => ({
176
+ tier: parseInt(tier),
177
+ passedTests: count,
178
+ totalTests: count,
179
+ }));
180
+ const score = calculateWeightedScore(allPassing);
181
+ expect(score).toBe(100);
182
+ });
183
+ it('should return 0 when no tests pass', () => {
184
+ const nonePassing = Object.entries(TIER_TEST_COUNTS).map(([tier, count]) => ({
185
+ tier: parseInt(tier),
186
+ passedTests: 0,
187
+ totalTests: count,
188
+ }));
189
+ const score = calculateWeightedScore(nonePassing);
190
+ expect(score).toBe(0);
191
+ });
192
+ it('should return 50 when half tests pass in each tier', () => {
193
+ const halfPassing = Object.entries(TIER_TEST_COUNTS).map(([tier, count]) => ({
194
+ tier: parseInt(tier),
195
+ passedTests: Math.floor(count / 2),
196
+ totalTests: count,
197
+ }));
198
+ const score = calculateWeightedScore(halfPassing);
199
+ expect(score).toBeGreaterThanOrEqual(45);
200
+ expect(score).toBeLessThanOrEqual(55);
201
+ });
202
+ it('should weight Tier 1 and Tier 3 more heavily (20% each)', () => {
203
+ // Only Tier 1 passing = 20% of 100 = 20
204
+ const onlyTier1 = [
205
+ { tier: 1, passedTests: TIER_TEST_COUNTS[1], totalTests: TIER_TEST_COUNTS[1] },
206
+ { tier: 2, passedTests: 0, totalTests: TIER_TEST_COUNTS[2] },
207
+ { tier: 3, passedTests: 0, totalTests: TIER_TEST_COUNTS[3] },
208
+ { tier: 4, passedTests: 0, totalTests: TIER_TEST_COUNTS[4] },
209
+ { tier: 5, passedTests: 0, totalTests: TIER_TEST_COUNTS[5] },
210
+ { tier: 6, passedTests: 0, totalTests: TIER_TEST_COUNTS[6] },
211
+ { tier: 7, passedTests: 0, totalTests: TIER_TEST_COUNTS[7] },
212
+ ];
213
+ const score = calculateWeightedScore(onlyTier1);
214
+ expect(score).toBe(20);
215
+ });
216
+ it('should correctly calculate partial tier scores', () => {
217
+ // Tier 1: 10/12 passed, weight 20%
218
+ // Score contribution: (10/12) * 100 * 20 / 100 = 16.67
219
+ const partialTier1 = [
220
+ { tier: 1, passedTests: 10, totalTests: 12 },
221
+ { tier: 2, passedTests: 0, totalTests: 8 },
222
+ { tier: 3, passedTests: 0, totalTests: 6 },
223
+ { tier: 4, passedTests: 0, totalTests: 6 },
224
+ { tier: 5, passedTests: 0, totalTests: 3 },
225
+ { tier: 6, passedTests: 0, totalTests: 6 },
226
+ { tier: 7, passedTests: 0, totalTests: 5 },
227
+ ];
228
+ const score = calculateWeightedScore(partialTier1);
229
+ expect(score).toBe(17); // Rounded
230
+ });
231
+ });
232
+ describe('Tier Level Determination', () => {
233
+ it('should return big-orange for score of 105', () => {
234
+ expect(getTierFromScore(105)).toBe('big-orange');
235
+ });
236
+ it('should return trophy for score of 100', () => {
237
+ expect(getTierFromScore(100)).toBe('trophy');
238
+ });
239
+ it('should return gold for score of 99', () => {
240
+ expect(getTierFromScore(99)).toBe('gold');
241
+ });
242
+ it('should return silver for score of 95-98', () => {
243
+ expect(getTierFromScore(95)).toBe('silver');
244
+ expect(getTierFromScore(96)).toBe('silver');
245
+ expect(getTierFromScore(97)).toBe('silver');
246
+ expect(getTierFromScore(98)).toBe('silver');
247
+ });
248
+ it('should return bronze for score of 85-94', () => {
249
+ expect(getTierFromScore(85)).toBe('bronze');
250
+ expect(getTierFromScore(90)).toBe('bronze');
251
+ expect(getTierFromScore(94)).toBe('bronze');
252
+ });
253
+ it('should return green for score of 70-84', () => {
254
+ expect(getTierFromScore(70)).toBe('green');
255
+ expect(getTierFromScore(77)).toBe('green');
256
+ expect(getTierFromScore(84)).toBe('green');
257
+ });
258
+ it('should return yellow for score of 55-69', () => {
259
+ expect(getTierFromScore(55)).toBe('yellow');
260
+ expect(getTierFromScore(62)).toBe('yellow');
261
+ expect(getTierFromScore(69)).toBe('yellow');
262
+ });
263
+ it('should return red for score below 55', () => {
264
+ expect(getTierFromScore(54)).toBe('red');
265
+ expect(getTierFromScore(30)).toBe('red');
266
+ expect(getTierFromScore(0)).toBe('red');
267
+ });
268
+ });
269
+ describe('Tier Boundary Edge Cases', () => {
270
+ it('should handle boundary between trophy (100) and gold (99)', () => {
271
+ expect(getTierFromScore(100)).toBe('trophy');
272
+ expect(getTierFromScore(99)).toBe('gold');
273
+ });
274
+ it('should handle boundary between gold (99) and silver (98)', () => {
275
+ expect(getTierFromScore(99)).toBe('gold');
276
+ expect(getTierFromScore(98)).toBe('silver');
277
+ });
278
+ it('should handle boundary between silver (95) and bronze (94)', () => {
279
+ expect(getTierFromScore(95)).toBe('silver');
280
+ expect(getTierFromScore(94)).toBe('bronze');
281
+ });
282
+ it('should handle boundary between bronze (85) and green (84)', () => {
283
+ expect(getTierFromScore(85)).toBe('bronze');
284
+ expect(getTierFromScore(84)).toBe('green');
285
+ });
286
+ it('should handle boundary between green (70) and yellow (69)', () => {
287
+ expect(getTierFromScore(70)).toBe('green');
288
+ expect(getTierFromScore(69)).toBe('yellow');
289
+ });
290
+ it('should handle boundary between yellow (55) and red (54)', () => {
291
+ expect(getTierFromScore(55)).toBe('yellow');
292
+ expect(getTierFromScore(54)).toBe('red');
293
+ });
294
+ });
295
+ });
296
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
297
+ // BIG ORANGE TESTS - THE MICHELIN STAR
298
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
299
+ describe('Big Orange (105%) - The Michelin Star', () => {
300
+ it('should be 5% above perfect score', () => {
301
+ expect(105 - 100).toBe(5);
302
+ });
303
+ it('should only be achievable with 100% pass rate', () => {
304
+ // Big Orange requires ALL tests passing, then bonus
305
+ const almostPerfect = Object.entries(TIER_TEST_COUNTS).map(([tier, count]) => ({
306
+ tier: parseInt(tier),
307
+ passedTests: tier === '1' ? count - 1 : count, // Miss 1 test in tier 1
308
+ totalTests: count,
309
+ }));
310
+ const score = calculateWeightedScore(almostPerfect);
311
+ expect(score).toBeLessThan(100);
312
+ expect(getTierFromScore(score)).not.toBe('big-orange');
313
+ });
314
+ it('should represent excellence beyond standard compliance', () => {
315
+ // This is documented behavior - 105% = 100% tests + 5% documentation/polish bonus
316
+ expect(getTierFromScore(105)).toBe('big-orange');
317
+ expect(getTierFromScore(104)).not.toBe('big-orange');
318
+ });
319
+ });
320
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
321
+ // TYPE DEFINITIONS TESTS
322
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
323
+ describe('Type Definitions', () => {
324
+ describe('TierLevel Type', () => {
325
+ const validTiers = [
326
+ 'big-orange',
327
+ 'trophy',
328
+ 'gold',
329
+ 'silver',
330
+ 'bronze',
331
+ 'green',
332
+ 'yellow',
333
+ 'red',
334
+ 'white',
335
+ ];
336
+ it('should include all 9 tier levels', () => {
337
+ expect(validTiers).toHaveLength(9);
338
+ });
339
+ it('should include big-orange as highest tier', () => {
340
+ expect(validTiers).toContain('big-orange');
341
+ });
342
+ it('should include white as lowest/empty tier', () => {
343
+ expect(validTiers).toContain('white');
344
+ });
345
+ it('should include all medal tiers (gold, silver, bronze)', () => {
346
+ expect(validTiers).toContain('gold');
347
+ expect(validTiers).toContain('silver');
348
+ expect(validTiers).toContain('bronze');
349
+ });
350
+ it('should include traffic light tiers (green, yellow, red)', () => {
351
+ expect(validTiers).toContain('green');
352
+ expect(validTiers).toContain('yellow');
353
+ expect(validTiers).toContain('red');
354
+ });
355
+ });
356
+ });
357
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
358
+ // CERTIFICATION RESULT STRUCTURE TESTS
359
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
360
+ describe('Certification Result Structure', () => {
361
+ // Mock result structure for testing
362
+ const mockResult = {
363
+ score: 95,
364
+ totalTests: 46,
365
+ passedTests: 44,
366
+ failedTests: 2,
367
+ tierResults: [
368
+ { tier: 1, name: 'Protocol Compliance', passed: true, passedTests: 12, totalTests: 12, failedTests: [], duration: 100 },
369
+ { tier: 2, name: 'Capability Negotiation', passed: true, passedTests: 8, totalTests: 8, failedTests: [], duration: 50 },
370
+ { tier: 3, name: 'Tool Integrity', passed: false, passedTests: 5, totalTests: 6, failedTests: ['Test failed'], duration: 200 },
371
+ ],
372
+ timestamp: '2025-12-02T00:00:00.000Z',
373
+ };
374
+ it('should have required score field', () => {
375
+ expect(mockResult).toHaveProperty('score');
376
+ expect(typeof mockResult.score).toBe('number');
377
+ });
378
+ it('should have required totalTests field', () => {
379
+ expect(mockResult).toHaveProperty('totalTests');
380
+ expect(typeof mockResult.totalTests).toBe('number');
381
+ });
382
+ it('should have required passedTests field', () => {
383
+ expect(mockResult).toHaveProperty('passedTests');
384
+ expect(typeof mockResult.passedTests).toBe('number');
385
+ });
386
+ it('should have required failedTests field', () => {
387
+ expect(mockResult).toHaveProperty('failedTests');
388
+ expect(typeof mockResult.failedTests).toBe('number');
389
+ });
390
+ it('should have required tierResults array', () => {
391
+ expect(mockResult).toHaveProperty('tierResults');
392
+ expect(Array.isArray(mockResult.tierResults)).toBe(true);
393
+ });
394
+ it('should have required timestamp field', () => {
395
+ expect(mockResult).toHaveProperty('timestamp');
396
+ expect(typeof mockResult.timestamp).toBe('string');
397
+ });
398
+ it('should have passedTests + failedTests equal totalTests', () => {
399
+ expect(mockResult.passedTests + mockResult.failedTests).toBe(mockResult.totalTests);
400
+ });
401
+ });
402
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
403
+ // TIER RESULT STRUCTURE TESTS
404
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
405
+ describe('Tier Result Structure', () => {
406
+ const mockTierResult = {
407
+ tier: 1,
408
+ name: 'Protocol Compliance',
409
+ passed: true,
410
+ passedTests: 12,
411
+ totalTests: 12,
412
+ failedTests: [],
413
+ duration: 100,
414
+ };
415
+ it('should have tier number', () => {
416
+ expect(mockTierResult).toHaveProperty('tier');
417
+ expect(typeof mockTierResult.tier).toBe('number');
418
+ });
419
+ it('should have tier name', () => {
420
+ expect(mockTierResult).toHaveProperty('name');
421
+ expect(typeof mockTierResult.name).toBe('string');
422
+ });
423
+ it('should have passed boolean', () => {
424
+ expect(mockTierResult).toHaveProperty('passed');
425
+ expect(typeof mockTierResult.passed).toBe('boolean');
426
+ });
427
+ it('should have passedTests count', () => {
428
+ expect(mockTierResult).toHaveProperty('passedTests');
429
+ expect(typeof mockTierResult.passedTests).toBe('number');
430
+ });
431
+ it('should have totalTests count', () => {
432
+ expect(mockTierResult).toHaveProperty('totalTests');
433
+ expect(typeof mockTierResult.totalTests).toBe('number');
434
+ });
435
+ it('should have failedTests array', () => {
436
+ expect(mockTierResult).toHaveProperty('failedTests');
437
+ expect(Array.isArray(mockTierResult.failedTests)).toBe(true);
438
+ });
439
+ it('should have duration in ms', () => {
440
+ expect(mockTierResult).toHaveProperty('duration');
441
+ expect(typeof mockTierResult.duration).toBe('number');
442
+ });
443
+ it('should have passed=true when passedTests equals totalTests', () => {
444
+ expect(mockTierResult.passedTests).toBe(mockTierResult.totalTests);
445
+ expect(mockTierResult.passed).toBe(true);
446
+ });
447
+ it('should have empty failedTests array when all pass', () => {
448
+ expect(mockTierResult.failedTests).toHaveLength(0);
449
+ });
450
+ });
451
+ //# sourceMappingURL=certifier.test.js.map