@opensip-cli/external-tool-adapter 0.1.15
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/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +33 -0
- package/dist/__tests__/acceptance-harness.test.d.ts +2 -0
- package/dist/__tests__/acceptance-harness.test.d.ts.map +1 -0
- package/dist/__tests__/acceptance-harness.test.js +106 -0
- package/dist/__tests__/acceptance-harness.test.js.map +1 -0
- package/dist/__tests__/artifact-path.test.d.ts +2 -0
- package/dist/__tests__/artifact-path.test.d.ts.map +1 -0
- package/dist/__tests__/artifact-path.test.js +19 -0
- package/dist/__tests__/artifact-path.test.js.map +1 -0
- package/dist/__tests__/binary-resolver.test.d.ts +2 -0
- package/dist/__tests__/binary-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/binary-resolver.test.js +64 -0
- package/dist/__tests__/binary-resolver.test.js.map +1 -0
- package/dist/__tests__/define-external-tool-adapter.test.d.ts +2 -0
- package/dist/__tests__/define-external-tool-adapter.test.d.ts.map +1 -0
- package/dist/__tests__/define-external-tool-adapter.test.js +165 -0
- package/dist/__tests__/define-external-tool-adapter.test.js.map +1 -0
- package/dist/__tests__/doctor-command.test.d.ts +2 -0
- package/dist/__tests__/doctor-command.test.d.ts.map +1 -0
- package/dist/__tests__/doctor-command.test.js +124 -0
- package/dist/__tests__/doctor-command.test.js.map +1 -0
- package/dist/__tests__/exit-model.test.d.ts +2 -0
- package/dist/__tests__/exit-model.test.d.ts.map +1 -0
- package/dist/__tests__/exit-model.test.js +30 -0
- package/dist/__tests__/exit-model.test.js.map +1 -0
- package/dist/__tests__/fingerprint.test.d.ts +2 -0
- package/dist/__tests__/fingerprint.test.d.ts.map +1 -0
- package/dist/__tests__/fingerprint.test.js +39 -0
- package/dist/__tests__/fingerprint.test.js.map +1 -0
- package/dist/__tests__/gate-render.test.d.ts +2 -0
- package/dist/__tests__/gate-render.test.d.ts.map +1 -0
- package/dist/__tests__/gate-render.test.js +82 -0
- package/dist/__tests__/gate-render.test.js.map +1 -0
- package/dist/__tests__/ingest-json.test.d.ts +2 -0
- package/dist/__tests__/ingest-json.test.d.ts.map +1 -0
- package/dist/__tests__/ingest-json.test.js +53 -0
- package/dist/__tests__/ingest-json.test.js.map +1 -0
- package/dist/__tests__/ingest-sarif.test.d.ts +2 -0
- package/dist/__tests__/ingest-sarif.test.d.ts.map +1 -0
- package/dist/__tests__/ingest-sarif.test.js +283 -0
- package/dist/__tests__/ingest-sarif.test.js.map +1 -0
- package/dist/__tests__/manifest-commands.test.d.ts +2 -0
- package/dist/__tests__/manifest-commands.test.d.ts.map +1 -0
- package/dist/__tests__/manifest-commands.test.js +67 -0
- package/dist/__tests__/manifest-commands.test.js.map +1 -0
- package/dist/__tests__/provenance.test.d.ts +2 -0
- package/dist/__tests__/provenance.test.d.ts.map +1 -0
- package/dist/__tests__/provenance.test.js +48 -0
- package/dist/__tests__/provenance.test.js.map +1 -0
- package/dist/__tests__/redact.test.d.ts +2 -0
- package/dist/__tests__/redact.test.d.ts.map +1 -0
- package/dist/__tests__/redact.test.js +37 -0
- package/dist/__tests__/redact.test.js.map +1 -0
- package/dist/__tests__/run-loop-artifact.test.d.ts +21 -0
- package/dist/__tests__/run-loop-artifact.test.d.ts.map +1 -0
- package/dist/__tests__/run-loop-artifact.test.js +186 -0
- package/dist/__tests__/run-loop-artifact.test.js.map +1 -0
- package/dist/__tests__/run-loop-exit.test.d.ts +21 -0
- package/dist/__tests__/run-loop-exit.test.d.ts.map +1 -0
- package/dist/__tests__/run-loop-exit.test.js +123 -0
- package/dist/__tests__/run-loop-exit.test.js.map +1 -0
- package/dist/__tests__/run-loop-gate.test.d.ts +10 -0
- package/dist/__tests__/run-loop-gate.test.d.ts.map +1 -0
- package/dist/__tests__/run-loop-gate.test.js +159 -0
- package/dist/__tests__/run-loop-gate.test.js.map +1 -0
- package/dist/__tests__/session-payload.test.d.ts +12 -0
- package/dist/__tests__/session-payload.test.d.ts.map +1 -0
- package/dist/__tests__/session-payload.test.js +131 -0
- package/dist/__tests__/session-payload.test.js.map +1 -0
- package/dist/__tests__/severity-map.test.d.ts +2 -0
- package/dist/__tests__/severity-map.test.d.ts.map +1 -0
- package/dist/__tests__/severity-map.test.js +57 -0
- package/dist/__tests__/severity-map.test.js.map +1 -0
- package/dist/acceptance-harness.d.ts +48 -0
- package/dist/acceptance-harness.d.ts.map +1 -0
- package/dist/acceptance-harness.js +78 -0
- package/dist/acceptance-harness.js.map +1 -0
- package/dist/adapter-config.d.ts +58 -0
- package/dist/adapter-config.d.ts.map +1 -0
- package/dist/adapter-config.js +73 -0
- package/dist/adapter-config.js.map +1 -0
- package/dist/adapter-manifest.d.ts +57 -0
- package/dist/adapter-manifest.d.ts.map +1 -0
- package/dist/adapter-manifest.js +68 -0
- package/dist/adapter-manifest.js.map +1 -0
- package/dist/artifact-path.d.ts +26 -0
- package/dist/artifact-path.d.ts.map +1 -0
- package/dist/artifact-path.js +22 -0
- package/dist/artifact-path.js.map +1 -0
- package/dist/binary-resolver.d.ts +51 -0
- package/dist/binary-resolver.d.ts.map +1 -0
- package/dist/binary-resolver.js +66 -0
- package/dist/binary-resolver.js.map +1 -0
- package/dist/define-external-tool-adapter.d.ts +25 -0
- package/dist/define-external-tool-adapter.d.ts.map +1 -0
- package/dist/define-external-tool-adapter.js +149 -0
- package/dist/define-external-tool-adapter.js.map +1 -0
- package/dist/doctor-command.d.ts +81 -0
- package/dist/doctor-command.d.ts.map +1 -0
- package/dist/doctor-command.js +160 -0
- package/dist/doctor-command.js.map +1 -0
- package/dist/exit-model.d.ts +33 -0
- package/dist/exit-model.d.ts.map +1 -0
- package/dist/exit-model.js +35 -0
- package/dist/exit-model.js.map +1 -0
- package/dist/fingerprint.d.ts +26 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +32 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/gate-render.d.ts +18 -0
- package/dist/gate-render.d.ts.map +1 -0
- package/dist/gate-render.js +25 -0
- package/dist/gate-render.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest-json.d.ts +32 -0
- package/dist/ingest-json.d.ts.map +1 -0
- package/dist/ingest-json.js +66 -0
- package/dist/ingest-json.js.map +1 -0
- package/dist/ingest-sarif.d.ts +113 -0
- package/dist/ingest-sarif.d.ts.map +1 -0
- package/dist/ingest-sarif.js +158 -0
- package/dist/ingest-sarif.js.map +1 -0
- package/dist/manifest-commands.d.ts +23 -0
- package/dist/manifest-commands.d.ts.map +1 -0
- package/dist/manifest-commands.js +47 -0
- package/dist/manifest-commands.js.map +1 -0
- package/dist/process-exec.d.ts +51 -0
- package/dist/process-exec.d.ts.map +1 -0
- package/dist/process-exec.js +99 -0
- package/dist/process-exec.js.map +1 -0
- package/dist/provenance.d.ts +19 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +31 -0
- package/dist/provenance.js.map +1 -0
- package/dist/redact.d.ts +24 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +38 -0
- package/dist/redact.js.map +1 -0
- package/dist/run-context.d.ts +24 -0
- package/dist/run-context.d.ts.map +1 -0
- package/dist/run-context.js +36 -0
- package/dist/run-context.js.map +1 -0
- package/dist/run-loop.d.ts +64 -0
- package/dist/run-loop.d.ts.map +1 -0
- package/dist/run-loop.js +320 -0
- package/dist/run-loop.js.map +1 -0
- package/dist/scan-emit.d.ts +81 -0
- package/dist/scan-emit.d.ts.map +1 -0
- package/dist/scan-emit.js +125 -0
- package/dist/scan-emit.js.map +1 -0
- package/dist/session-payload.d.ts +81 -0
- package/dist/session-payload.d.ts.map +1 -0
- package/dist/session-payload.js +86 -0
- package/dist/session-payload.js.map +1 -0
- package/dist/severity-map.d.ts +43 -0
- package/dist/severity-map.d.ts.map +1 -0
- package/dist/severity-map.js +84 -0
- package/dist/severity-map.js.map +1 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/version-command.d.ts +36 -0
- package/dist/version-command.d.ts.map +1 -0
- package/dist/version-command.js +74 -0
- package/dist/version-command.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createSignal, ValidationError } from '@opensip-cli/core';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { deriveAdapterConfigManifest, deriveAdapterManifestRequires } from '../adapter-manifest.js';
|
|
4
|
+
import { defineExternalToolAdapter } from '../define-external-tool-adapter.js';
|
|
5
|
+
import { messageHashFingerprintStrategy } from '../fingerprint.js';
|
|
6
|
+
const baseSpec = {
|
|
7
|
+
identity: { name: 'examplescan', aliases: ['ex'] },
|
|
8
|
+
metadata: {
|
|
9
|
+
id: 'c0ffee00-1234-4abc-8def-0123456789ab',
|
|
10
|
+
description: 'Example scanner',
|
|
11
|
+
version: '1.2.3',
|
|
12
|
+
adapterPackage: '@opensip-cli/tool-example',
|
|
13
|
+
},
|
|
14
|
+
binary: { command: 'examplescan', versionArgs: ['version'], minVersion: '1.0.0' },
|
|
15
|
+
network: 'local-only',
|
|
16
|
+
commands: [
|
|
17
|
+
{
|
|
18
|
+
name: 'scan',
|
|
19
|
+
args: (ctx) => ['scan', ctx.projectRoot],
|
|
20
|
+
output: { kind: 'sarif', path: 'example.sarif' },
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
describe('defineExternalToolAdapter', () => {
|
|
25
|
+
it('returns an ordinary Tool with identity + metadata derived', () => {
|
|
26
|
+
const tool = defineExternalToolAdapter(baseSpec);
|
|
27
|
+
expect(tool.identity.name).toBe('examplescan');
|
|
28
|
+
expect(tool.metadata).toMatchObject({
|
|
29
|
+
id: 'c0ffee00-1234-4abc-8def-0123456789ab',
|
|
30
|
+
name: 'examplescan',
|
|
31
|
+
version: '1.2.3',
|
|
32
|
+
description: 'Example scanner',
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it('mounts the scan primary + nested doctor + version (3 specs)', () => {
|
|
36
|
+
const tool = defineExternalToolAdapter(baseSpec);
|
|
37
|
+
const specs = tool.commandSpecs ?? [];
|
|
38
|
+
expect(specs.map((s) => s.name)).toEqual(['examplescan', 'doctor', 'version']);
|
|
39
|
+
const [primary, doctor, version] = specs;
|
|
40
|
+
expect(primary).toMatchObject({
|
|
41
|
+
name: 'examplescan',
|
|
42
|
+
scope: 'project',
|
|
43
|
+
output: 'raw-stream',
|
|
44
|
+
rawStreamReason: 'runtime-render-dispatch',
|
|
45
|
+
});
|
|
46
|
+
expect(primary.aliases).toEqual(['ex']);
|
|
47
|
+
expect(doctor).toMatchObject({
|
|
48
|
+
name: 'doctor',
|
|
49
|
+
parent: 'examplescan',
|
|
50
|
+
scope: 'none',
|
|
51
|
+
output: 'raw-stream',
|
|
52
|
+
rawStreamReason: 'diagnostic-gate',
|
|
53
|
+
});
|
|
54
|
+
expect(version).toMatchObject({
|
|
55
|
+
name: 'version',
|
|
56
|
+
parent: 'examplescan',
|
|
57
|
+
scope: 'none',
|
|
58
|
+
output: 'raw-stream',
|
|
59
|
+
rawStreamReason: 'diagnostic-gate',
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
it('mounts additional scanner commands as nested verbs', () => {
|
|
63
|
+
const tool = defineExternalToolAdapter({
|
|
64
|
+
...baseSpec,
|
|
65
|
+
commands: [
|
|
66
|
+
baseSpec.commands[0],
|
|
67
|
+
{ name: 'config', args: () => ['config'], output: { kind: 'sarif' } },
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
expect((tool.commandSpecs ?? []).map((s) => s.name)).toEqual([
|
|
71
|
+
'examplescan',
|
|
72
|
+
'config',
|
|
73
|
+
'doctor',
|
|
74
|
+
'version',
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
it('declares the message-hash fingerprint strategy by default (worker-side stamping)', () => {
|
|
78
|
+
const tool = defineExternalToolAdapter(baseSpec);
|
|
79
|
+
expect(tool.extensionPoints?.fingerprintStrategy).toBe(messageHashFingerprintStrategy);
|
|
80
|
+
});
|
|
81
|
+
it('forwards an optional config contribution', () => {
|
|
82
|
+
const tool = defineExternalToolAdapter({ ...baseSpec, config: { schema: { marker: true } } });
|
|
83
|
+
expect(tool.extensionPoints?.config).toMatchObject({
|
|
84
|
+
namespace: 'examplescan',
|
|
85
|
+
schema: { marker: true },
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
// A4 / R6 (ADR-0090 §4.3): an adapter that declares NO `config` must still CLAIM
|
|
89
|
+
// its namespace by default — otherwise `scope.toolConfig[<tool>]` is always
|
|
90
|
+
// undefined (binary pin dead, verdict keys non-configurable, and an operator's
|
|
91
|
+
// `<tool>:` block bricks the project via the ADR-0043 unclaimed-namespace gate).
|
|
92
|
+
describe('default config namespace claim (A4 / R6)', () => {
|
|
93
|
+
it('claims the namespace on the runtime when config is omitted', () => {
|
|
94
|
+
const tool = defineExternalToolAdapter(baseSpec);
|
|
95
|
+
const config = tool.extensionPoints?.config;
|
|
96
|
+
expect(config?.namespace).toBe('examplescan');
|
|
97
|
+
// The runtime schema is the worker deep-pass Zod (exposes safeParse).
|
|
98
|
+
expect(typeof (config?.schema).safeParse).toBe('function');
|
|
99
|
+
});
|
|
100
|
+
it('the runtime schema accepts the binary pin AND the reserved verdict keys', () => {
|
|
101
|
+
const tool = defineExternalToolAdapter(baseSpec);
|
|
102
|
+
const schema = tool.extensionPoints?.config?.schema;
|
|
103
|
+
expect(schema.safeParse({
|
|
104
|
+
binaries: { examplescan: { path: '/opt/examplescan' } },
|
|
105
|
+
failOnWarnings: 2,
|
|
106
|
+
failOnDegraded: false,
|
|
107
|
+
}).success).toBe(true);
|
|
108
|
+
// A typo inside the block is rejected by the deep pass (strict).
|
|
109
|
+
expect(schema.safeParse({ binares: {} }).success).toBe(false);
|
|
110
|
+
});
|
|
111
|
+
it('emits a coarse static config descriptor (the installed-path namespace claim)', () => {
|
|
112
|
+
const tool = defineExternalToolAdapter(baseSpec);
|
|
113
|
+
const descriptor = deriveAdapterConfigManifest(tool);
|
|
114
|
+
expect(descriptor?.namespace).toBe('examplescan');
|
|
115
|
+
expect(descriptor?.schema.properties?.binaries).toEqual({ type: 'object' });
|
|
116
|
+
});
|
|
117
|
+
it('emits NO static descriptor for a custom config (validation defers to the worker)', () => {
|
|
118
|
+
const tool = defineExternalToolAdapter({ ...baseSpec, config: { schema: { marker: true } } });
|
|
119
|
+
expect(deriveAdapterConfigManifest(tool)).toBeUndefined();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
// A13 (ADR-0092 §4.8): `requires` is DERIVED from the network posture — the
|
|
123
|
+
// documented forward-map, not a hand-typed list. `network` rides only on a
|
|
124
|
+
// non-local-only posture, so a future flip to `networked` is a visible drift.
|
|
125
|
+
describe('network posture → requires derivation (A13)', () => {
|
|
126
|
+
it('a local-only adapter derives [subprocess, filesystem] (no network)', () => {
|
|
127
|
+
const requires = deriveAdapterManifestRequires(defineExternalToolAdapter(baseSpec));
|
|
128
|
+
expect(requires.map((r) => r.resource)).toEqual(['subprocess', 'filesystem']);
|
|
129
|
+
});
|
|
130
|
+
it('a networked adapter derives an added network requirement', () => {
|
|
131
|
+
const tool = defineExternalToolAdapter({ ...baseSpec, network: 'networked' });
|
|
132
|
+
const requires = deriveAdapterManifestRequires(tool);
|
|
133
|
+
expect(requires.map((r) => r.resource)).toEqual(['subprocess', 'filesystem', 'network']);
|
|
134
|
+
expect(requires.find((r) => r.resource === 'network')?.reason).toContain('networked');
|
|
135
|
+
});
|
|
136
|
+
it('an auth-required adapter also derives a network requirement', () => {
|
|
137
|
+
const tool = defineExternalToolAdapter({ ...baseSpec, network: 'auth-required' });
|
|
138
|
+
expect(deriveAdapterManifestRequires(tool).some((r) => r.resource === 'network')).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
it('rejects a non-SARIF command with no parse', () => {
|
|
142
|
+
expect(() => defineExternalToolAdapter({
|
|
143
|
+
...baseSpec,
|
|
144
|
+
commands: [{ name: 'scan', args: () => [], output: { kind: 'json', path: 'x.json' } }],
|
|
145
|
+
})).toThrow(ValidationError);
|
|
146
|
+
});
|
|
147
|
+
it('accepts a JSON command WITH a parse', () => {
|
|
148
|
+
const tool = defineExternalToolAdapter({
|
|
149
|
+
...baseSpec,
|
|
150
|
+
commands: [
|
|
151
|
+
{
|
|
152
|
+
name: 'scan',
|
|
153
|
+
args: () => [],
|
|
154
|
+
output: { kind: 'json', path: 'x.json' },
|
|
155
|
+
parse: () => [createSignal({ source: 'x', severity: 'low', ruleId: 'r', message: 'm' })],
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
expect(tool.commandSpecs).toBeDefined();
|
|
160
|
+
});
|
|
161
|
+
it('rejects an empty command list', () => {
|
|
162
|
+
expect(() => defineExternalToolAdapter({ ...baseSpec, commands: [] })).toThrow(ValidationError);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=define-external-tool-adapter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-external-tool-adapter.test.js","sourceRoot":"","sources":["../../src/__tests__/define-external-tool-adapter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-command.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/doctor-command.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { defaultAdapterConfigSchema } from '../adapter-config.js';
|
|
3
|
+
import { compareVersion, doctorReportLines, probeAdapter } from '../doctor-command.js';
|
|
4
|
+
import { probeVersionReport } from '../version-command.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build the `gitleaks` namespace config block the way PRODUCTION does — by parsing
|
|
7
|
+
* it through the adapter's own (default) namespace schema. This is the same Zod the
|
|
8
|
+
* worker deep pass runs and the same shape the composer projects onto
|
|
9
|
+
* `scope.toolConfig.gitleaks`, so a test that feeds the parsed result to
|
|
10
|
+
* `probeAdapter` exercises a genuinely reachable config — not a hand-built shape the
|
|
11
|
+
* resolver could never deliver (the A4 "production-unreachable" hole).
|
|
12
|
+
*/
|
|
13
|
+
function producibleConfig(raw) {
|
|
14
|
+
const parsed = defaultAdapterConfigSchema().safeParse(raw);
|
|
15
|
+
if (!parsed.success)
|
|
16
|
+
throw new Error('config block is not producible by the adapter schema');
|
|
17
|
+
return parsed.data;
|
|
18
|
+
}
|
|
19
|
+
function deps(over = {}) {
|
|
20
|
+
return {
|
|
21
|
+
binaryDeps: { existsSync: () => true, which: () => '/usr/bin/gitleaks' },
|
|
22
|
+
probeVersion: () => '8.18.0',
|
|
23
|
+
env: {},
|
|
24
|
+
...over,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
describe('compareVersion', () => {
|
|
28
|
+
it('classifies ok / too-old / unknown / not-applicable', () => {
|
|
29
|
+
expect(compareVersion('8.18.0', '8.0.0')).toBe('ok');
|
|
30
|
+
expect(compareVersion('8.18.0', '8.18.0')).toBe('ok');
|
|
31
|
+
expect(compareVersion('7.9.9', '8.0.0')).toBe('too-old');
|
|
32
|
+
expect(compareVersion(undefined, '8.0.0')).toBe('unknown');
|
|
33
|
+
expect(compareVersion('not-a-version!', '8.0.0')).toBe('unknown');
|
|
34
|
+
expect(compareVersion('8.0.0', undefined)).toBe('not-applicable');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('probeAdapter', () => {
|
|
38
|
+
const binary = {
|
|
39
|
+
command: 'gitleaks',
|
|
40
|
+
versionArgs: ['version'],
|
|
41
|
+
minVersion: '8.0.0',
|
|
42
|
+
installHint: 'brew install gitleaks',
|
|
43
|
+
};
|
|
44
|
+
it('reports ready when the binary is found and recent enough', () => {
|
|
45
|
+
const report = probeAdapter({ tool: 'gitleaks', network: 'local-only', binary, config: {} }, deps());
|
|
46
|
+
expect(report.binary.found).toBe(true);
|
|
47
|
+
expect(report.binary.layer).toBe('path');
|
|
48
|
+
expect(report.version).toMatchObject({ detected: '8.18.0', minVersion: '8.0.0', status: 'ok' });
|
|
49
|
+
expect(report.ready).toBe(true);
|
|
50
|
+
expect(report.installHint).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
it('reports not-ready + an install hint when the binary is missing', () => {
|
|
53
|
+
const report = probeAdapter({ tool: 'gitleaks', network: 'local-only', binary, config: {} }, deps({ binaryDeps: { existsSync: () => false, which: () => undefined } }));
|
|
54
|
+
expect(report.binary.found).toBe(false);
|
|
55
|
+
expect(report.ready).toBe(false);
|
|
56
|
+
expect(report.installHint).toBe('brew install gitleaks');
|
|
57
|
+
});
|
|
58
|
+
it('reports not-ready when the version is too old', () => {
|
|
59
|
+
const report = probeAdapter({ tool: 'gitleaks', network: 'local-only', binary, config: {} }, deps({ probeVersion: () => '7.0.0' }));
|
|
60
|
+
expect(report.version.status).toBe('too-old');
|
|
61
|
+
expect(report.ready).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it('honors a config-file pin (from a producible namespace block)', () => {
|
|
64
|
+
const report = probeAdapter({
|
|
65
|
+
tool: 'gitleaks',
|
|
66
|
+
network: 'local-only',
|
|
67
|
+
binary,
|
|
68
|
+
// The pin is validated through the adapter's own schema first, so this is
|
|
69
|
+
// exactly the shape the composer projects onto scope.toolConfig.gitleaks —
|
|
70
|
+
// not a production-unreachable hand-built object (A4).
|
|
71
|
+
config: producibleConfig({ binaries: { gitleaks: { path: '/opt/gitleaks' } } }),
|
|
72
|
+
}, deps());
|
|
73
|
+
expect(report.binary.path).toBe('/opt/gitleaks');
|
|
74
|
+
expect(report.binary.layer).toBe('config');
|
|
75
|
+
});
|
|
76
|
+
it('surfaces credential presence (presence only) for an auth-required posture', () => {
|
|
77
|
+
const present = probeAdapter({
|
|
78
|
+
tool: 'snyk',
|
|
79
|
+
network: 'auth-required',
|
|
80
|
+
binary: { command: 'snyk', versionArgs: ['--version'] },
|
|
81
|
+
config: {},
|
|
82
|
+
}, deps({ env: { OPENSIP_SNYK_TOKEN: 'secret-value' } }));
|
|
83
|
+
expect(present.credentialEnv).toEqual({ name: 'OPENSIP_SNYK_TOKEN', present: true });
|
|
84
|
+
expect(present.ready).toBe(true);
|
|
85
|
+
const missing = probeAdapter({
|
|
86
|
+
tool: 'snyk',
|
|
87
|
+
network: 'auth-required',
|
|
88
|
+
binary: { command: 'snyk', versionArgs: ['--version'] },
|
|
89
|
+
config: {},
|
|
90
|
+
}, deps());
|
|
91
|
+
expect(missing.credentialEnv?.present).toBe(false);
|
|
92
|
+
expect(missing.ready).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('doctorReportLines', () => {
|
|
96
|
+
it('renders a found+ready report', () => {
|
|
97
|
+
const lines = doctorReportLines(probeAdapter({
|
|
98
|
+
tool: 'gitleaks',
|
|
99
|
+
network: 'local-only',
|
|
100
|
+
binary: { command: 'gitleaks', versionArgs: ['version'], minVersion: '8.0.0' },
|
|
101
|
+
config: {},
|
|
102
|
+
}, deps()));
|
|
103
|
+
expect(lines.join('\n')).toContain('ready: yes');
|
|
104
|
+
expect(lines.join('\n')).toContain('network: local-only');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('probeVersionReport', () => {
|
|
108
|
+
it('returns the resolved path + version', () => {
|
|
109
|
+
const report = probeVersionReport({ tool: 'gitleaks', binary: { command: 'gitleaks', versionArgs: ['version'] }, config: {} }, deps());
|
|
110
|
+
expect(report).toMatchObject({
|
|
111
|
+
tool: 'gitleaks',
|
|
112
|
+
found: true,
|
|
113
|
+
path: '/usr/bin/gitleaks',
|
|
114
|
+
version: '8.18.0',
|
|
115
|
+
layer: 'path',
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
it('reports not-found cleanly', () => {
|
|
119
|
+
const report = probeVersionReport({ tool: 'gitleaks', binary: { command: 'gitleaks', versionArgs: ['version'] }, config: {} }, deps({ binaryDeps: { existsSync: () => false, which: () => undefined } }));
|
|
120
|
+
expect(report).toMatchObject({ found: false, command: 'gitleaks' });
|
|
121
|
+
expect(report.version).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=doctor-command.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-command.test.js","sourceRoot":"","sources":["../../src/__tests__/doctor-command.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-model.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/exit-model.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { DEFAULT_EXIT_MODEL, interpretExit } from '../exit-model.js';
|
|
3
|
+
const GITLEAKS = { ok: [0], findings: [1], errorFrom: 2 };
|
|
4
|
+
const TRIVY = { ok: [0], findings: [], errorFrom: 1 };
|
|
5
|
+
describe('interpretExit', () => {
|
|
6
|
+
it('classifies ok / findings / fault for the default model', () => {
|
|
7
|
+
expect(interpretExit(0, DEFAULT_EXIT_MODEL)).toBe('ok');
|
|
8
|
+
expect(interpretExit(1, DEFAULT_EXIT_MODEL)).toBe('findings');
|
|
9
|
+
expect(interpretExit(2, DEFAULT_EXIT_MODEL)).toBe('fault');
|
|
10
|
+
expect(interpretExit(127, DEFAULT_EXIT_MODEL)).toBe('fault');
|
|
11
|
+
});
|
|
12
|
+
it('gitleaks disambiguation: exit 1 + invalid artifact ⇒ fault, valid ⇒ findings', () => {
|
|
13
|
+
expect(interpretExit(1, GITLEAKS, { artifactValid: true })).toBe('findings');
|
|
14
|
+
expect(interpretExit(1, GITLEAKS, { artifactValid: false })).toBe('fault');
|
|
15
|
+
// undefined artifactValid is treated as valid (stdout scanners).
|
|
16
|
+
expect(interpretExit(1, GITLEAKS)).toBe('findings');
|
|
17
|
+
});
|
|
18
|
+
it('trivy model: 0 is ok, any nonzero is a fault (no exit-code findings)', () => {
|
|
19
|
+
expect(interpretExit(0, TRIVY)).toBe('ok');
|
|
20
|
+
expect(interpretExit(1, TRIVY)).toBe('fault');
|
|
21
|
+
expect(interpretExit(5, TRIVY)).toBe('fault');
|
|
22
|
+
});
|
|
23
|
+
it('prefers ok when a code appears in both ok and findings', () => {
|
|
24
|
+
expect(interpretExit(0, { ok: [0], findings: [0] })).toBe('ok');
|
|
25
|
+
});
|
|
26
|
+
it('an unmodeled nonzero with no errorFrom is still a fault', () => {
|
|
27
|
+
expect(interpretExit(3, { ok: [0], findings: [1] })).toBe('fault');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=exit-model.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-model.test.js","sourceRoot":"","sources":["../../src/__tests__/exit-model.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAIrE,MAAM,QAAQ,GAAqB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;AAC5E,MAAM,KAAK,GAAqB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;AAExE,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9D,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7E,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3E,iEAAiE;QACjE,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/fingerprint.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createSignal, defaultFingerprintStrategy } from '@opensip-cli/core';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { messageHashFingerprintStrategy, resolveFingerprintStrategy } from '../fingerprint.js';
|
|
5
|
+
describe('messageHashFingerprintStrategy', () => {
|
|
6
|
+
it('is sha256(filePath\\nruleId\\nmessage) — line-shift tolerant', () => {
|
|
7
|
+
const signal = createSignal({
|
|
8
|
+
source: 'osv-scanner',
|
|
9
|
+
severity: 'high',
|
|
10
|
+
ruleId: 'GHSA-1',
|
|
11
|
+
message: 'Prototype pollution',
|
|
12
|
+
code: { file: 'package-lock.json', line: 42 },
|
|
13
|
+
});
|
|
14
|
+
const expected = createHash('sha256')
|
|
15
|
+
.update(`package-lock.json\nGHSA-1\nPrototype pollution`)
|
|
16
|
+
.digest('hex');
|
|
17
|
+
expect(messageHashFingerprintStrategy.fingerprint(signal)).toBe(expected);
|
|
18
|
+
});
|
|
19
|
+
it('ignores line/column so a shift does not re-key the baseline', () => {
|
|
20
|
+
const base = {
|
|
21
|
+
source: 'g',
|
|
22
|
+
severity: 'high',
|
|
23
|
+
ruleId: 'R',
|
|
24
|
+
message: 'm',
|
|
25
|
+
code: { file: 'a.txt' },
|
|
26
|
+
};
|
|
27
|
+
const at10 = messageHashFingerprintStrategy.fingerprint(createSignal({ ...base, code: { file: 'a.txt', line: 10 } }));
|
|
28
|
+
const at99 = messageHashFingerprintStrategy.fingerprint(createSignal({ ...base, code: { file: 'a.txt', line: 99 } }));
|
|
29
|
+
expect(at10).toBe(at99);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('resolveFingerprintStrategy', () => {
|
|
33
|
+
it('defaults to message-hash and maps rule-location to the host default', () => {
|
|
34
|
+
expect(resolveFingerprintStrategy(undefined)).toBe(messageHashFingerprintStrategy);
|
|
35
|
+
expect(resolveFingerprintStrategy('message-hash')).toBe(messageHashFingerprintStrategy);
|
|
36
|
+
expect(resolveFingerprintStrategy('rule-location')).toBe(defaultFingerprintStrategy);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=fingerprint.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.test.js","sourceRoot":"","sources":["../../src/__tests__/fingerprint.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAE/F,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,MAAM,GAAG,YAAY,CAAC;YAC1B,MAAM,EAAE,aAAa;YACrB,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,qBAAqB;YAC9B,IAAI,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,EAAE,EAAE;SAC9C,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;aAClC,MAAM,CAAC,gDAAgD,CAAC;aACxD,MAAM,CAAC,KAAK,CAAC,CAAC;QACjB,MAAM,CAAC,8BAA8B,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,GAAG;YACX,QAAQ,EAAE,MAAe;YACzB,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,GAAG;YACZ,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;SACxB,CAAC;QACF,MAAM,IAAI,GAAG,8BAA8B,CAAC,WAAW,CACrD,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAC7D,CAAC;QACF,MAAM,IAAI,GAAG,8BAA8B,CAAC,WAAW,CACrD,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAC7D,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,CAAC,0BAA0B,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACnF,MAAM,CAAC,0BAA0B,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACxF,MAAM,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-render.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/gate-render.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createSignal } from '@opensip-cli/core';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { renderGateCompareLines, renderGateSaveLines } from '../gate-render.js';
|
|
4
|
+
function sig(over = {}) {
|
|
5
|
+
return createSignal({
|
|
6
|
+
source: 'examplescan',
|
|
7
|
+
severity: 'high',
|
|
8
|
+
ruleId: 'secret',
|
|
9
|
+
message: 'A secret',
|
|
10
|
+
code: { file: 'src/a.ts', line: 3 },
|
|
11
|
+
...over,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function result(over = {}) {
|
|
15
|
+
return { added: [], resolved: [], unchanged: [], degraded: false, ...over };
|
|
16
|
+
}
|
|
17
|
+
describe('renderGateSaveLines', () => {
|
|
18
|
+
it('reports the tool + finding count', () => {
|
|
19
|
+
expect(renderGateSaveLines('examplescan', 3)).toEqual([
|
|
20
|
+
'examplescan: baseline saved (project SQLite store)',
|
|
21
|
+
' 3 finding(s) recorded',
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe('renderGateCompareLines', () => {
|
|
26
|
+
it('renders STABLE when there is no change', () => {
|
|
27
|
+
const lines = renderGateCompareLines('examplescan', result({ unchanged: [sig()] }));
|
|
28
|
+
expect(lines[0]).toBe('examplescan gate compare');
|
|
29
|
+
expect(lines.at(-1)).toBe('✓ STABLE — no change');
|
|
30
|
+
expect(lines.join('\n')).toContain('Unchanged (1):');
|
|
31
|
+
});
|
|
32
|
+
it('renders DEGRADED with the net-new finding + message when added is non-empty', () => {
|
|
33
|
+
const added = sig({
|
|
34
|
+
ruleId: 'aws-key',
|
|
35
|
+
message: 'AWS Access Key',
|
|
36
|
+
code: { file: 'p.env', line: 9 },
|
|
37
|
+
});
|
|
38
|
+
const lines = renderGateCompareLines('examplescan', result({ added: [added], degraded: true }));
|
|
39
|
+
const text = lines.join('\n');
|
|
40
|
+
expect(text).toContain('Added (1):');
|
|
41
|
+
expect(text).toContain('aws-key');
|
|
42
|
+
expect(text).toContain('p.env:9');
|
|
43
|
+
expect(text).toContain('AWS Access Key');
|
|
44
|
+
expect(lines.at(-1)).toBe('✗ DEGRADED — 1 new finding');
|
|
45
|
+
});
|
|
46
|
+
it('pluralizes the DEGRADED footer for multiple new findings', () => {
|
|
47
|
+
const lines = renderGateCompareLines('examplescan', result({ added: [sig({ ruleId: 'a' }), sig({ ruleId: 'b' })], degraded: true }));
|
|
48
|
+
expect(lines.at(-1)).toBe('✗ DEGRADED — 2 new findings');
|
|
49
|
+
});
|
|
50
|
+
it('renders IMPROVED when findings resolved and none added', () => {
|
|
51
|
+
const lines = renderGateCompareLines('examplescan', result({ resolved: [sig(), sig({ ruleId: 'b' })] }));
|
|
52
|
+
expect(lines.join('\n')).toContain('Resolved (2):');
|
|
53
|
+
expect(lines.at(-1)).toBe('✓ IMPROVED — 2 findings resolved, none added');
|
|
54
|
+
});
|
|
55
|
+
it('samples the unchanged bucket to the first five with an overflow note', () => {
|
|
56
|
+
const unchanged = Array.from({ length: 7 }, (_, i) => sig({ ruleId: `r${i}`, code: { file: `f${i}.ts`, line: i } }));
|
|
57
|
+
const text = renderGateCompareLines('examplescan', result({ unchanged })).join('\n');
|
|
58
|
+
expect(text).toContain('Unchanged (7):');
|
|
59
|
+
expect(text).toContain('... and 2 more');
|
|
60
|
+
});
|
|
61
|
+
it('renders a no-location placeholder for a signal with no file', () => {
|
|
62
|
+
const noFile = sig({ code: { file: '' } });
|
|
63
|
+
const text = renderGateCompareLines('examplescan', result({ added: [noFile], degraded: true })).join('\n');
|
|
64
|
+
expect(text).toContain('(no location)');
|
|
65
|
+
});
|
|
66
|
+
it('orders same-rule findings by file then line, and truncates a long message', () => {
|
|
67
|
+
const longMsg = 'x'.repeat(200);
|
|
68
|
+
const added = [
|
|
69
|
+
sig({ ruleId: 'dup', message: longMsg, code: { file: 'b.ts', line: 9 } }),
|
|
70
|
+
sig({ ruleId: 'dup', message: longMsg, code: { file: 'a.ts', line: 2 } }),
|
|
71
|
+
sig({ ruleId: 'dup', message: longMsg, code: { file: 'a.ts', line: 1 } }),
|
|
72
|
+
];
|
|
73
|
+
const lines = renderGateCompareLines('examplescan', result({ added, degraded: true }));
|
|
74
|
+
const locOrder = lines.filter((l) => l.includes('dup')).map((l) => l.split(/\s+/).at(-1));
|
|
75
|
+
expect(locOrder).toEqual(['a.ts:1', 'a.ts:2', 'b.ts:9']);
|
|
76
|
+
// The 200-char message is truncated with an ellipsis to <= 120 chars.
|
|
77
|
+
const msgLine = lines.find((l) => l.trimStart().startsWith('x'));
|
|
78
|
+
expect(msgLine?.trim().length).toBeLessThanOrEqual(120);
|
|
79
|
+
expect(msgLine).toContain('…');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=gate-render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-render.test.js","sourceRoot":"","sources":["../../src/__tests__/gate-render.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-json.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ingest-json.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { asArray, asObject, getNumber, getString, navigate, safeParseJson, } from '../ingest-json.js';
|
|
3
|
+
describe('safeParseJson', () => {
|
|
4
|
+
it('returns ok for valid JSON', () => {
|
|
5
|
+
expect(safeParseJson('{"a":1}')).toEqual({ ok: true, value: { a: 1 } });
|
|
6
|
+
expect(safeParseJson('[]')).toEqual({ ok: true, value: [] });
|
|
7
|
+
});
|
|
8
|
+
it('returns an error Result for malformed JSON instead of throwing', () => {
|
|
9
|
+
const result = safeParseJson('{not json');
|
|
10
|
+
expect(result.ok).toBe(false);
|
|
11
|
+
if (!result.ok)
|
|
12
|
+
expect(typeof result.error).toBe('string');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe('asObject / asArray', () => {
|
|
16
|
+
it('narrows plain objects but not arrays or null', () => {
|
|
17
|
+
expect(asObject({ a: 1 })).toEqual({ a: 1 });
|
|
18
|
+
expect(asObject([])).toBeUndefined();
|
|
19
|
+
expect(asObject(null)).toBeUndefined();
|
|
20
|
+
expect(asObject('x')).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
it('narrows arrays only', () => {
|
|
23
|
+
expect(asArray([1, 2])).toEqual([1, 2]);
|
|
24
|
+
expect(asArray({})).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('getString / getNumber', () => {
|
|
28
|
+
it('reads typed properties', () => {
|
|
29
|
+
expect(getString({ k: 'v' }, 'k')).toBe('v');
|
|
30
|
+
expect(getString({ k: 1 }, 'k')).toBeUndefined();
|
|
31
|
+
expect(getString(undefined, 'k')).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
it('coerces numeric strings for numbers', () => {
|
|
34
|
+
expect(getNumber({ k: 3 }, 'k')).toBe(3);
|
|
35
|
+
expect(getNumber({ k: '7.5' }, 'k')).toBe(7.5);
|
|
36
|
+
expect(getNumber({ k: 'nope' }, 'k')).toBeUndefined();
|
|
37
|
+
expect(getNumber({ k: Number.NaN }, 'k')).toBeUndefined();
|
|
38
|
+
expect(getNumber({}, 'k')).toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('navigate', () => {
|
|
42
|
+
const doc = { results: [{ packages: [{ id: 'GHSA-1' }] }] };
|
|
43
|
+
it('descends objects and array indices', () => {
|
|
44
|
+
expect(navigate(doc, ['results', '0', 'packages', '0', 'id'])).toBe('GHSA-1');
|
|
45
|
+
});
|
|
46
|
+
it('returns undefined on a missing or wrong-typed step', () => {
|
|
47
|
+
expect(navigate(doc, ['results', '9', 'id'])).toBeUndefined();
|
|
48
|
+
expect(navigate(doc, ['missing'])).toBeUndefined();
|
|
49
|
+
expect(navigate(null, ['x'])).toBeUndefined();
|
|
50
|
+
expect(navigate(doc, ['results', 'notanindex'])).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=ingest-json.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-json.test.js","sourceRoot":"","sources":["../../src/__tests__/ingest-json.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-sarif.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ingest-sarif.test.ts"],"names":[],"mappings":""}
|