@o-lang/resolver-tests 1.0.7 → 1.0.9

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/lib/badge.js CHANGED
@@ -2,62 +2,72 @@ const fs = require("fs");
2
2
  const path = require("path");
3
3
  console.log("✅ O-lang badge generator loaded");
4
4
 
5
- // ----------------------
6
- // Resolver-specific badge generator with O-lang tag
7
- // ----------------------
8
5
  function generateBadge({
9
6
  resolverName = "Unknown",
10
7
  version = "",
11
8
  passed = false,
12
- outputDir = process.cwd() // default to where CLI is run
9
+ outputDir = process.cwd()
13
10
  }) {
14
- const color = passed ? "green" : "red";
11
+ // Colors
12
+ const olangColor = "#8A2BE2"; // Purple for "O-lang"
13
+ const statusColor = passed ? "#4CAF50" : "#F44336"; // Green/Red for status
14
+
15
15
  const statusText = passed ? "Certified" : "Failed";
16
16
  const versionText = version ? ` v${version}` : "";
17
17
  const timestamp = new Date().toISOString().split("T")[0]; // YYYY-MM-DD
18
18
 
19
- // O-lang tag (explicit branding)
20
- const badgeText = `O-lang | ${resolverName}${versionText} — ${statusText} (${timestamp})`;
19
+ // Left label: "O-lang"
20
+ const leftLabel = "O-lang";
21
+ // Right message: "resolver-name v1.0 — Certified (2026-01-22)"
22
+ const rightMessage = `${resolverName}${versionText} — ${statusText} (${timestamp})`;
21
23
 
22
- const width = 20 + badgeText.length * 7; // approximate width per character
24
+ // Estimate text widths (approx. 7px per char + padding)
25
+ const leftWidth = 12 + leftLabel.length * 7;
26
+ const rightWidth = 12 + rightMessage.length * 7;
27
+ const totalWidth = leftWidth + rightWidth;
23
28
 
24
29
  const badgeSvg = `
25
- <svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="20">
26
- <rect width="${width}" height="20" fill="${color}" rx="3" ry="3"/>
27
- <text x="${width / 2}" y="14"
30
+ <svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20">
31
+ <!-- Left segment: O-lang (purple) -->
32
+ <rect x="0" y="0" width="${leftWidth}" height="20" fill="${olangColor}" rx="3" ry="3"/>
33
+ <text x="${leftWidth / 2}" y="14"
34
+ fill="#fff"
35
+ font-family="Verdana, DejaVu Sans, sans-serif"
36
+ font-size="11"
37
+ font-weight="bold"
38
+ text-anchor="middle">
39
+ ${leftLabel}
40
+ </text>
41
+
42
+ <!-- Right segment: status info (green/red) -->
43
+ <rect x="${leftWidth}" y="0" width="${rightWidth}" height="20" fill="${statusColor}" rx="3" ry="3"/>
44
+ <text x="${leftWidth + rightWidth / 2}" y="14"
28
45
  fill="#fff"
29
- font-family="Verdana"
30
- font-size="12"
46
+ font-family="Verdana, DejaVu Sans, sans-serif"
47
+ font-size="11"
31
48
  text-anchor="middle">
32
- ${badgeText}
49
+ ${rightMessage}
33
50
  </text>
34
51
  </svg>
35
52
  `.trim();
36
53
 
37
- // ----------------------
38
54
  // Ensure badges folder exists
39
- // ----------------------
40
55
  const badgesDir = path.join(outputDir, "badges");
41
56
  if (!fs.existsSync(badgesDir)) {
42
57
  fs.mkdirSync(badgesDir, { recursive: true });
43
58
  }
44
59
 
45
- // ----------------------
46
60
  // Write badge file
47
- // ----------------------
48
61
  const safeName = resolverName.replace(/[^a-zA-Z0-9_-]/g, "_");
49
62
  const badgePath = path.join(badgesDir, `${safeName}-badge.svg`);
50
63
 
51
64
  fs.writeFileSync(badgePath, badgeSvg, "utf8");
52
-
53
65
  console.log(`🏷 Badge written to ${badgePath}`);
54
66
 
55
67
  return badgePath;
56
68
  }
57
69
 
58
- // ----------------------
59
- // Export
60
- // ----------------------
61
70
  module.exports = {
71
+ generateBadges: generateBadge, // alias for backward compat if needed
62
72
  generateBadge
63
- };
73
+ };
package/lib/runner.js CHANGED
@@ -85,6 +85,7 @@ function checkOutputIsObject(output) {
85
85
  }
86
86
 
87
87
  function checkOutputFieldsMatchContract(output, resolverMeta) {
88
+ if (!output) return false; // 🔒 SAFETY: prevent 'in' operator crash on null/undefined
88
89
  const declaredNames = (resolverMeta.outputs || []).map(o => o.name);
89
90
  return declaredNames.every(name => name in output);
90
91
  }
@@ -171,7 +172,7 @@ function runAssertions(testSpec, target, status = {}) {
171
172
  // ----------------------
172
173
  // Runtime resolver invoker with observation
173
174
  // ----------------------
174
- async function invokeResolverWithObservation(resolver, resolverMeta, testSpec) {
175
+ async function invokeResolverWithObservation(resolver, resolverMeta, testSpec, fixture) {
175
176
  const ctx = {
176
177
  resolver,
177
178
  resolverMeta,
@@ -182,10 +183,9 @@ async function invokeResolverWithObservation(resolver, resolverMeta, testSpec) {
182
183
  retryCount: 0,
183
184
  };
184
185
 
185
- // Use empty input resolver must handle its own validation
186
- const input = {};
186
+ // Use input from test fixture (critical fix!)
187
+ const input = fixture?.invoke || {};
187
188
 
188
- // Run multiple times for determinism test
189
189
  const runs = testSpec.test_id === 'R-011-determinism' ? 3 : 1;
190
190
 
191
191
  for (let i = 0; i < runs; i++) {
@@ -257,7 +257,8 @@ async function runAllTests({ suites, resolver }) {
257
257
  } else if (testSpec.category === "resolver-runtime") {
258
258
  // R-006 → R-012: Observe real resolver behavior
259
259
  try {
260
- const runtimeContext = await invokeResolverWithObservation(resolver, resolverMeta, testSpec);
260
+ // Pass fixture to invoker
261
+ const runtimeContext = await invokeResolverWithObservation(resolver, resolverMeta, testSpec, fixture);
261
262
  const result = runAssertions(testSpec, runtimeContext);
262
263
 
263
264
  if (!result.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o-lang/resolver-tests",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Official O-Lang Resolver Test Harness — locked single entrypoint",
5
5
  "main": "run.js",
6
6
  "type": "commonjs",