@o-lang/resolver-tests 1.0.0 → 1.0.2
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/R-001-allowlist/test.json +2 -2
- package/R-002-io-contract/test.json +2 -2
- package/R-003-failure-modes/test.json +4 -10
- package/R-004-invalid-syntax/test.json +2 -2
- package/R-005-resolver-metadata-contract/test.json +2 -2
- package/badges/notify-telegram-badge.svg +10 -0
- package/badges/unknown-resolver-badge.svg +10 -0
- package/certified.svg +6 -0
- package/conformance.json +10 -0
- package/lib/badge.js +57 -21
- package/lib/runner.js +4 -3
- package/package.json +1 -1
- package/run.js +19 -9
- package/badges/certified.svg +0 -18
- package/lib/O--Lang v1-Conformant-success.svg +0 -1
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"fixtures": {
|
|
12
12
|
"inputs": [
|
|
13
13
|
{
|
|
14
|
-
"workflow": "
|
|
14
|
+
"workflow": "workflow.ol",
|
|
15
15
|
"values": {
|
|
16
16
|
"userInput": "42"
|
|
17
17
|
}
|
|
@@ -73,4 +73,4 @@
|
|
|
73
73
|
"description": "No warnings for valid I/O contracts"
|
|
74
74
|
}
|
|
75
75
|
]
|
|
76
|
-
}
|
|
76
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"fixtures": {
|
|
12
12
|
"inputs": [
|
|
13
13
|
{
|
|
14
|
-
"workflow": "
|
|
14
|
+
"workflow": "workflow.ol",
|
|
15
15
|
"values": {
|
|
16
16
|
"userInput": "someInput"
|
|
17
17
|
}
|
|
@@ -61,14 +61,8 @@
|
|
|
61
61
|
"type": "step_failure_policies",
|
|
62
62
|
"stepIndex": 1,
|
|
63
63
|
"expected": {
|
|
64
|
-
"TIMEOUT": {
|
|
65
|
-
|
|
66
|
-
"count": 2
|
|
67
|
-
},
|
|
68
|
-
"NETWORK_ERROR": {
|
|
69
|
-
"action": "fail",
|
|
70
|
-
"count": 0
|
|
71
|
-
}
|
|
64
|
+
"TIMEOUT": { "action": "retry", "count": 2 },
|
|
65
|
+
"NETWORK_ERROR": { "action": "fail", "count": 0 }
|
|
72
66
|
},
|
|
73
67
|
"severity": "fatal",
|
|
74
68
|
"description": "Failure modes and retry counts must be parsed"
|
|
@@ -81,4 +75,4 @@
|
|
|
81
75
|
"description": "No warnings for valid failure mode syntax"
|
|
82
76
|
}
|
|
83
77
|
]
|
|
84
|
-
}
|
|
78
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"fixtures": {
|
|
12
12
|
"inputs": [
|
|
13
13
|
{
|
|
14
|
-
"resolver_contract": "
|
|
14
|
+
"resolver_contract": "resolver.js"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
},
|
|
@@ -57,4 +57,4 @@
|
|
|
57
57
|
"description": "Failure modes should be declared for production resolvers"
|
|
58
58
|
}
|
|
59
59
|
]
|
|
60
|
-
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="412" height="20">
|
|
2
|
+
<rect width="412" height="20" fill="green" rx="3" ry="3"/>
|
|
3
|
+
<text x="206" y="14"
|
|
4
|
+
fill="#fff"
|
|
5
|
+
font-family="Verdana"
|
|
6
|
+
font-size="12"
|
|
7
|
+
text-anchor="middle">
|
|
8
|
+
O-lang | notify-telegram v1.0.3 — Certified (2026-01-20)
|
|
9
|
+
</text>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="370" height="20">
|
|
2
|
+
<rect width="370" height="20" fill="green" rx="3" ry="3"/>
|
|
3
|
+
<text x="185" y="14"
|
|
4
|
+
fill="#fff"
|
|
5
|
+
font-family="Verdana"
|
|
6
|
+
font-size="12"
|
|
7
|
+
text-anchor="middle">
|
|
8
|
+
O-lang | unknown-resolver — Certified (2026-01-20)
|
|
9
|
+
</text>
|
|
10
|
+
</svg>
|
package/certified.svg
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="28">
|
|
2
|
+
<rect rx="4" width="160" height="28" fill="#2d2d2d"/>
|
|
3
|
+
<rect rx="4" x="80" width="80" height="28" fill="#4cbb17"/>
|
|
4
|
+
<text x="40" y="18" fill="#fff" font-size="13" font-family="Arial" text-anchor="middle">O-lang</text>
|
|
5
|
+
<text x="120" y="18" fill="#fff" font-size="13" font-family="Arial" text-anchor="middle">CERTIFIED</text>
|
|
6
|
+
</svg>
|
package/conformance.json
ADDED
package/lib/badge.js
CHANGED
|
@@ -1,27 +1,63 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const path = require("path");
|
|
3
|
+
console.log("✅ O-lang badge generator loaded");
|
|
4
|
+
|
|
5
|
+
// ----------------------
|
|
6
|
+
// Resolver-specific badge generator with O-lang tag
|
|
7
|
+
// ----------------------
|
|
8
|
+
function generateBadge({
|
|
9
|
+
resolverName = "Unknown",
|
|
10
|
+
version = "",
|
|
11
|
+
passed = false,
|
|
12
|
+
outputDir = process.cwd() // default to where CLI is run
|
|
13
|
+
}) {
|
|
14
|
+
const color = passed ? "green" : "red";
|
|
15
|
+
const statusText = passed ? "Certified" : "Failed";
|
|
16
|
+
const versionText = version ? ` v${version}` : "";
|
|
17
|
+
const timestamp = new Date().toISOString().split("T")[0]; // YYYY-MM-DD
|
|
18
|
+
|
|
19
|
+
// O-lang tag (explicit branding)
|
|
20
|
+
const badgeText = `O-lang | ${resolverName}${versionText} — ${statusText} (${timestamp})`;
|
|
21
|
+
|
|
22
|
+
const width = 20 + badgeText.length * 7; // approximate width per character
|
|
23
|
+
|
|
24
|
+
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"
|
|
28
|
+
fill="#fff"
|
|
29
|
+
font-family="Verdana"
|
|
30
|
+
font-size="12"
|
|
31
|
+
text-anchor="middle">
|
|
32
|
+
${badgeText}
|
|
33
|
+
</text>
|
|
34
|
+
</svg>
|
|
35
|
+
`.trim();
|
|
36
|
+
|
|
37
|
+
// ----------------------
|
|
38
|
+
// Ensure badges folder exists
|
|
39
|
+
// ----------------------
|
|
40
|
+
const badgesDir = path.join(outputDir, "badges");
|
|
41
|
+
if (!fs.existsSync(badgesDir)) {
|
|
42
|
+
fs.mkdirSync(badgesDir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ----------------------
|
|
46
|
+
// Write badge file
|
|
47
|
+
// ----------------------
|
|
48
|
+
const safeName = resolverName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
49
|
+
const badgePath = path.join(badgesDir, `${safeName}-badge.svg`);
|
|
50
|
+
|
|
51
|
+
fs.writeFileSync(badgePath, badgeSvg, "utf8");
|
|
52
|
+
|
|
53
|
+
console.log(`🏷 Badge written to ${badgePath}`);
|
|
3
54
|
|
|
4
|
-
function generateBadge({ passed, outputDir }) {
|
|
5
|
-
const badgePath = path.join(outputDir, "certified.svg");
|
|
6
|
-
|
|
7
|
-
const svg = passed
|
|
8
|
-
? `
|
|
9
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="28">
|
|
10
|
-
<rect rx="4" width="160" height="28" fill="#2d2d2d"/>
|
|
11
|
-
<rect rx="4" x="80" width="80" height="28" fill="#4cbb17"/>
|
|
12
|
-
<text x="40" y="18" fill="#fff" font-size="13" font-family="Arial" text-anchor="middle">O-lang</text>
|
|
13
|
-
<text x="120" y="18" fill="#fff" font-size="13" font-family="Arial" text-anchor="middle">CERTIFIED</text>
|
|
14
|
-
</svg>`
|
|
15
|
-
: `
|
|
16
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="28">
|
|
17
|
-
<rect rx="4" width="160" height="28" fill="#2d2d2d"/>
|
|
18
|
-
<rect rx="4" x="80" width="80" height="28" fill="#bb2124"/>
|
|
19
|
-
<text x="40" y="18" fill="#fff" font-size="13" font-family="Arial" text-anchor="middle">O-lang</text>
|
|
20
|
-
<text x="120" y="18" fill="#fff" font-size="13" font-family="Arial" text-anchor="middle">FAILED</text>
|
|
21
|
-
</svg>`;
|
|
22
|
-
|
|
23
|
-
fs.writeFileSync(badgePath, svg.trim());
|
|
24
55
|
return badgePath;
|
|
25
56
|
}
|
|
26
57
|
|
|
27
|
-
|
|
58
|
+
// ----------------------
|
|
59
|
+
// Export
|
|
60
|
+
// ----------------------
|
|
61
|
+
module.exports = {
|
|
62
|
+
generateBadge
|
|
63
|
+
};
|
package/lib/runner.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// lib/runner.js
|
|
2
1
|
const path = require("path");
|
|
3
2
|
const fs = require("fs");
|
|
4
3
|
|
|
@@ -254,9 +253,11 @@ function runAssertions(testSpec, target, status = {}) {
|
|
|
254
253
|
// ----------------------
|
|
255
254
|
async function runAllTests({ suites, resolver }) {
|
|
256
255
|
let failed = 0;
|
|
256
|
+
// Resolve test suites from the package root (where R-001-..., R-005-... live)
|
|
257
|
+
const PACKAGE_ROOT = path.join(__dirname, '..');
|
|
257
258
|
|
|
258
259
|
for (const suite of suites) {
|
|
259
|
-
const suiteDir = path.join(
|
|
260
|
+
const suiteDir = path.join(PACKAGE_ROOT, suite);
|
|
260
261
|
const testSpecPath = path.join(suiteDir, "test.json");
|
|
261
262
|
|
|
262
263
|
if (!fs.existsSync(testSpecPath)) {
|
|
@@ -334,4 +335,4 @@ async function runAllTests({ suites, resolver }) {
|
|
|
334
335
|
module.exports = {
|
|
335
336
|
runAssertions,
|
|
336
337
|
runAllTests,
|
|
337
|
-
};
|
|
338
|
+
};
|
package/package.json
CHANGED
package/run.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
console.log("🚀 Starting O-lang resolver test runner...");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
|
|
@@ -75,7 +75,6 @@ const { generateBadge } = require("./lib/badge");
|
|
|
75
75
|
"R-001-allowlist",
|
|
76
76
|
"R-002-io-contract",
|
|
77
77
|
"R-003-failure-modes",
|
|
78
|
-
"R-004-invalid-syntax",
|
|
79
78
|
"R-005-resolver-metadata-contract"
|
|
80
79
|
];
|
|
81
80
|
|
|
@@ -88,7 +87,7 @@ const { generateBadge } = require("./lib/badge");
|
|
|
88
87
|
// Generate conformance report
|
|
89
88
|
// ----------------------
|
|
90
89
|
const conformanceReport = {
|
|
91
|
-
resolver: resolver?.resolverName || "unknown",
|
|
90
|
+
resolver: resolver?.resolverDeclaration?.resolverName || resolver?.resolverName || "unknown",
|
|
92
91
|
timestamp: new Date().toISOString(),
|
|
93
92
|
results: suites.map(suite => ({
|
|
94
93
|
suite,
|
|
@@ -102,12 +101,23 @@ const { generateBadge } = require("./lib/badge");
|
|
|
102
101
|
);
|
|
103
102
|
|
|
104
103
|
// ----------------------
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
// Generate certification badge
|
|
105
|
+
// ----------------------
|
|
106
|
+
const meta = resolver.resolverDeclaration || resolver;
|
|
107
|
+
|
|
108
|
+
console.log("🏷 Badge metadata being sent:", {
|
|
109
|
+
resolverName: meta.resolverName,
|
|
110
|
+
version: meta.version,
|
|
111
|
+
passed: result.failed === 0,
|
|
112
|
+
outputDir: process.cwd()
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
generateBadge({
|
|
116
|
+
resolverName: meta.resolverName || "unknown-resolver",
|
|
117
|
+
version: meta.version || "",
|
|
118
|
+
passed: result.failed === 0,
|
|
119
|
+
outputDir: process.cwd()
|
|
120
|
+
});
|
|
111
121
|
|
|
112
122
|
// ----------------------
|
|
113
123
|
// Output handling
|
package/badges/certified.svg
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='20'>
|
|
2
|
-
<linearGradient id='b' x2='0' y2='100%'>
|
|
3
|
-
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
|
4
|
-
<stop offset='1' stop-opacity='.1'/>
|
|
5
|
-
</linearGradient>
|
|
6
|
-
<mask id='a'>
|
|
7
|
-
<rect width='120' height='20' rx='3' fill='#fff'/>
|
|
8
|
-
</mask>
|
|
9
|
-
<g mask='url(#a)'>
|
|
10
|
-
<rect width='70' height='20' fill='#555'/>
|
|
11
|
-
<rect x='70' width='50' height='20' fill='red'/>
|
|
12
|
-
<rect width='120' height='20' fill='url(#b)'/>
|
|
13
|
-
</g>
|
|
14
|
-
<g fill='#fff' text-anchor='middle' font-family='Verdana' font-size='11'>
|
|
15
|
-
<text x='35' y='14'>Certified</text>
|
|
16
|
-
<text x='95' y='14'>fail</text>
|
|
17
|
-
</g>
|
|
18
|
-
</svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="159" height="20" role="img" aria-label="O-Lang v1: Conformant"><title>O-Lang v1: Conformant</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="159" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="84" height="20" fill="#555"/><rect x="84" width="75" height="20" fill="#4c1"/><rect width="159" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="515" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="570">O-Lang v1</text><text x="515" y="140" transform="scale(.1)" fill="#fff" textLength="570">O-Lang v1</text><text aria-hidden="true" x="1205" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="650">Conformant</text><text x="1205" y="140" transform="scale(.1)" fill="#fff" textLength="650">Conformant</text></g></svg>
|