@telorun/assert 0.1.12 → 0.3.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 +0 -4
- package/dist/manifest.d.ts +1 -0
- package/dist/manifest.js +26 -7
- package/dist/module-context.js +2 -3
- package/package.json +3 -3
- package/src/manifest.ts +33 -8
- package/src/module-context.ts +2 -3
package/README.md
CHANGED
package/dist/manifest.d.ts
CHANGED
package/dist/manifest.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_MANIFEST_FILENAME, Loader, StaticAnalyzer } from "@telorun/analyzer";
|
|
2
2
|
import * as fs from "fs/promises";
|
|
3
3
|
import * as path from "path";
|
|
4
|
-
class
|
|
4
|
+
class LocalFileSource {
|
|
5
5
|
supports(p) {
|
|
6
6
|
return (p.startsWith("file://") ||
|
|
7
7
|
p.startsWith("/") ||
|
|
@@ -52,7 +52,7 @@ export async function create(manifest, ctx) {
|
|
|
52
52
|
const green = (t) => c("32", t);
|
|
53
53
|
const dim = (t) => c("2", t);
|
|
54
54
|
const name = manifest.metadata.name;
|
|
55
|
-
const loader = new Loader([new
|
|
55
|
+
const loader = new Loader([new LocalFileSource()]);
|
|
56
56
|
const analyzer = new StaticAnalyzer();
|
|
57
57
|
const resolvedUrl = new URL(manifest.source, ctx.moduleContext.source).toString();
|
|
58
58
|
let manifests;
|
|
@@ -87,7 +87,9 @@ export async function create(manifest, ctx) {
|
|
|
87
87
|
}
|
|
88
88
|
const diagnostics = analyzer.analyze(manifests);
|
|
89
89
|
const errors = diagnostics.filter((d) => d.severity === 1); // DiagnosticSeverity.Error = 1
|
|
90
|
+
const warnings = diagnostics.filter((d) => d.severity === 2); // DiagnosticSeverity.Warning = 2
|
|
90
91
|
const expectedErrors = manifest.expect.errors ?? [];
|
|
92
|
+
const expectedWarnings = manifest.expect.warnings ?? [];
|
|
91
93
|
const failures = [];
|
|
92
94
|
const matched = [];
|
|
93
95
|
if (expectedErrors.length === 0) {
|
|
@@ -108,17 +110,34 @@ export async function create(manifest, ctx) {
|
|
|
108
110
|
matched.push(`${expected.code ?? "*"}${expected.message ? ` (${expected.message})` : ""}`);
|
|
109
111
|
}
|
|
110
112
|
else {
|
|
111
|
-
failures.push(`expected ${expected.code ?? "*"}${expected.message ? ` containing "${expected.message}"` : ""} — not found`);
|
|
113
|
+
failures.push(`expected error ${expected.code ?? "*"}${expected.message ? ` containing "${expected.message}"` : ""} — not found`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Warnings are checked only when the caller declares expect.warnings. Unexpected
|
|
118
|
+
// warnings are not failures (unlike errors) — warnings are advisory and may exist
|
|
119
|
+
// on manifests that are otherwise valid. When expect.warnings is present, every
|
|
120
|
+
// listed warning must be found; extras are ignored.
|
|
121
|
+
if (expectedWarnings.length > 0) {
|
|
122
|
+
for (const expected of expectedWarnings) {
|
|
123
|
+
const match = warnings.find((d) => matchesDiagnostic(d, expected));
|
|
124
|
+
if (match) {
|
|
125
|
+
matched.push(`warning ${expected.code ?? "*"}${expected.message ? ` (${expected.message})` : ""}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
failures.push(`expected warning ${expected.code ?? "*"}${expected.message ? ` containing "${expected.message}"` : ""} — not found`);
|
|
112
129
|
}
|
|
113
130
|
}
|
|
114
131
|
}
|
|
115
132
|
const passedLines = matched.map((m) => ` ${green("✓")} ${dim(m)}\n`).join("");
|
|
116
133
|
if (failures.length > 0) {
|
|
117
134
|
const failedLines = failures.map((f) => ` ${red("✗")} ${f}\n`).join("");
|
|
118
|
-
const actualLines = errors.length > 0
|
|
119
|
-
? ` ${dim("actual
|
|
120
|
-
errors
|
|
121
|
-
|
|
135
|
+
const actualLines = errors.length > 0 || warnings.length > 0
|
|
136
|
+
? ` ${dim("actual diagnostics:")}\n` +
|
|
137
|
+
[...errors, ...warnings]
|
|
138
|
+
.map((d) => ` ${dim(`[${d.code}] ${d.message}`)}\n`)
|
|
139
|
+
.join("")
|
|
140
|
+
: ` ${dim("no diagnostics produced")}\n`;
|
|
122
141
|
ctx.stderr.write(bold(red(`Assert.Manifest.${name}: assertion failed`)) + "\n" +
|
|
123
142
|
passedLines + failedLines + actualLines);
|
|
124
143
|
ctx.requestExit(1);
|
package/dist/module-context.js
CHANGED
|
@@ -44,14 +44,13 @@ export async function create(manifest, ctx) {
|
|
|
44
44
|
return {
|
|
45
45
|
run: async () => {
|
|
46
46
|
const { bold, red, green, yellow, dim } = createColors(ctx.stderr);
|
|
47
|
-
const declaringModule = manifest.metadata.module ?? "default";
|
|
48
47
|
const resourcesToCheck = manifest.resources ?? {};
|
|
49
48
|
const failures = [];
|
|
50
49
|
const passed = [];
|
|
51
50
|
const { resources } = ctx.moduleContext;
|
|
52
51
|
for (const [alias, expected] of Object.entries(resourcesToCheck)) {
|
|
53
|
-
if (!ctx.
|
|
54
|
-
failures.push(`Import alias '${alias}' not found in module
|
|
52
|
+
if (!ctx.moduleContext.hasImport(alias)) {
|
|
53
|
+
failures.push(`Import alias '${alias}' not found in declaring module`);
|
|
55
54
|
continue;
|
|
56
55
|
}
|
|
57
56
|
const snap = resources[alias] ?? {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/assert",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Telo Assert module - Assertion resource kinds for Telo manifests.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@sinclair/typebox": "^0.34.48",
|
|
34
|
-
"@telorun/analyzer": "0.
|
|
35
|
-
"@telorun/sdk": "0.
|
|
34
|
+
"@telorun/analyzer": "0.5.0",
|
|
35
|
+
"@telorun/sdk": "0.6.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.0.0",
|
package/src/manifest.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_MANIFEST_FILENAME, Loader, StaticAnalyzer, type AnalysisDiagnostic, type
|
|
1
|
+
import { DEFAULT_MANIFEST_FILENAME, Loader, StaticAnalyzer, type AnalysisDiagnostic, type ManifestSource } from "@telorun/analyzer";
|
|
2
2
|
import type { ResourceContext, Runnable } from "@telorun/sdk";
|
|
3
3
|
import * as fs from "fs/promises";
|
|
4
4
|
import * as path from "path";
|
|
@@ -13,11 +13,12 @@ interface ManifestAssertManifest {
|
|
|
13
13
|
source: string;
|
|
14
14
|
expect: {
|
|
15
15
|
errors?: ExpectError[];
|
|
16
|
+
warnings?: ExpectError[];
|
|
16
17
|
loadError?: string;
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
class
|
|
21
|
+
class LocalFileSource implements ManifestSource {
|
|
21
22
|
supports(p: string): boolean {
|
|
22
23
|
return (
|
|
23
24
|
p.startsWith("file://") ||
|
|
@@ -77,7 +78,7 @@ export async function create(
|
|
|
77
78
|
const dim = (t: string) => c("2", t);
|
|
78
79
|
|
|
79
80
|
const name = manifest.metadata.name;
|
|
80
|
-
const loader = new Loader([new
|
|
81
|
+
const loader = new Loader([new LocalFileSource()]);
|
|
81
82
|
const analyzer = new StaticAnalyzer();
|
|
82
83
|
|
|
83
84
|
const resolvedUrl = new URL(manifest.source, ctx.moduleContext.source).toString();
|
|
@@ -121,7 +122,9 @@ export async function create(
|
|
|
121
122
|
|
|
122
123
|
const diagnostics = analyzer.analyze(manifests);
|
|
123
124
|
const errors = diagnostics.filter((d) => d.severity === 1); // DiagnosticSeverity.Error = 1
|
|
125
|
+
const warnings = diagnostics.filter((d) => d.severity === 2); // DiagnosticSeverity.Warning = 2
|
|
124
126
|
const expectedErrors = manifest.expect.errors ?? [];
|
|
127
|
+
const expectedWarnings = manifest.expect.warnings ?? [];
|
|
125
128
|
const failures: string[] = [];
|
|
126
129
|
const matched: string[] = [];
|
|
127
130
|
|
|
@@ -143,7 +146,26 @@ export async function create(
|
|
|
143
146
|
);
|
|
144
147
|
} else {
|
|
145
148
|
failures.push(
|
|
146
|
-
`expected ${expected.code ?? "*"}${expected.message ? ` containing "${expected.message}"` : ""} — not found`,
|
|
149
|
+
`expected error ${expected.code ?? "*"}${expected.message ? ` containing "${expected.message}"` : ""} — not found`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Warnings are checked only when the caller declares expect.warnings. Unexpected
|
|
156
|
+
// warnings are not failures (unlike errors) — warnings are advisory and may exist
|
|
157
|
+
// on manifests that are otherwise valid. When expect.warnings is present, every
|
|
158
|
+
// listed warning must be found; extras are ignored.
|
|
159
|
+
if (expectedWarnings.length > 0) {
|
|
160
|
+
for (const expected of expectedWarnings) {
|
|
161
|
+
const match = warnings.find((d) => matchesDiagnostic(d, expected));
|
|
162
|
+
if (match) {
|
|
163
|
+
matched.push(
|
|
164
|
+
`warning ${expected.code ?? "*"}${expected.message ? ` (${expected.message})` : ""}`,
|
|
165
|
+
);
|
|
166
|
+
} else {
|
|
167
|
+
failures.push(
|
|
168
|
+
`expected warning ${expected.code ?? "*"}${expected.message ? ` containing "${expected.message}"` : ""} — not found`,
|
|
147
169
|
);
|
|
148
170
|
}
|
|
149
171
|
}
|
|
@@ -152,10 +174,13 @@ export async function create(
|
|
|
152
174
|
const passedLines = matched.map((m) => ` ${green("✓")} ${dim(m)}\n`).join("");
|
|
153
175
|
if (failures.length > 0) {
|
|
154
176
|
const failedLines = failures.map((f) => ` ${red("✗")} ${f}\n`).join("");
|
|
155
|
-
const actualLines =
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
177
|
+
const actualLines =
|
|
178
|
+
errors.length > 0 || warnings.length > 0
|
|
179
|
+
? ` ${dim("actual diagnostics:")}\n` +
|
|
180
|
+
[...errors, ...warnings]
|
|
181
|
+
.map((d) => ` ${dim(`[${d.code}] ${d.message}`)}\n`)
|
|
182
|
+
.join("")
|
|
183
|
+
: ` ${dim("no diagnostics produced")}\n`;
|
|
159
184
|
ctx.stderr.write(
|
|
160
185
|
bold(red(`Assert.Manifest.${name}: assertion failed`)) + "\n" +
|
|
161
186
|
passedLines + failedLines + actualLines,
|
package/src/module-context.ts
CHANGED
|
@@ -50,14 +50,13 @@ export async function create(
|
|
|
50
50
|
return {
|
|
51
51
|
run: async () => {
|
|
52
52
|
const { bold, red, green, yellow, dim } = createColors(ctx.stderr);
|
|
53
|
-
const declaringModule = manifest.metadata.module ?? "default";
|
|
54
53
|
const resourcesToCheck = manifest.resources ?? {};
|
|
55
54
|
const failures: string[] = [];
|
|
56
55
|
const passed: string[] = [];
|
|
57
56
|
const { resources } = ctx.moduleContext;
|
|
58
57
|
for (const [alias, expected] of Object.entries(resourcesToCheck)) {
|
|
59
|
-
if (!
|
|
60
|
-
failures.push(`Import alias '${alias}' not found in module
|
|
58
|
+
if (!ctx.moduleContext.hasImport(alias)) {
|
|
59
|
+
failures.push(`Import alias '${alias}' not found in declaring module`);
|
|
61
60
|
continue;
|
|
62
61
|
}
|
|
63
62
|
|