guardrail-core 1.0.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/dist/__tests__/autopilot.test.d.ts +7 -0
- package/dist/__tests__/autopilot.test.d.ts.map +1 -0
- package/dist/__tests__/autopilot.test.js +156 -0
- package/dist/__tests__/tier-config.test.d.ts +9 -0
- package/dist/__tests__/tier-config.test.d.ts.map +1 -0
- package/dist/__tests__/tier-config.test.js +230 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash-inline.test.js +62 -0
- package/dist/__tests__/utils/hash.test.d.ts +3 -0
- package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash.test.js +95 -0
- package/dist/__tests__/utils/simple.test.d.ts +1 -0
- package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/simple.test.js +10 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils-simple.test.js +6 -0
- package/dist/__tests__/utils/utils.test.d.ts +15 -0
- package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils.test.js +172 -0
- package/dist/autopilot/autopilot-runner.d.ts +33 -0
- package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
- package/dist/autopilot/autopilot-runner.js +479 -0
- package/dist/autopilot/index.d.ts +6 -0
- package/dist/autopilot/index.d.ts.map +1 -0
- package/dist/autopilot/index.js +25 -0
- package/dist/autopilot/types.d.ts +102 -0
- package/dist/autopilot/types.d.ts.map +1 -0
- package/dist/autopilot/types.js +18 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +22 -0
- package/dist/cache/redis-cache.d.ts +145 -0
- package/dist/cache/redis-cache.d.ts.map +1 -0
- package/dist/cache/redis-cache.js +459 -0
- package/dist/ci/github-actions.d.ts +77 -0
- package/dist/ci/github-actions.d.ts.map +1 -0
- package/dist/ci/github-actions.js +277 -0
- package/dist/ci/index.d.ts +12 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +27 -0
- package/dist/ci/pre-commit.d.ts +65 -0
- package/dist/ci/pre-commit.d.ts.map +1 -0
- package/dist/ci/pre-commit.js +286 -0
- package/dist/entitlements.d.ts +149 -0
- package/dist/entitlements.d.ts.map +1 -0
- package/dist/entitlements.js +464 -0
- package/dist/env.d.ts +113 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +204 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
- package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
- package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
- package/dist/fix-packs/generate-fix-packs.js +505 -0
- package/dist/fix-packs/index.d.ts +8 -0
- package/dist/fix-packs/index.d.ts.map +1 -0
- package/dist/fix-packs/index.js +23 -0
- package/dist/fix-packs/types.d.ts +113 -0
- package/dist/fix-packs/types.d.ts.map +1 -0
- package/dist/fix-packs/types.js +71 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/metrics/prometheus.d.ts +99 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +306 -0
- package/dist/quota-ledger.d.ts +119 -0
- package/dist/quota-ledger.d.ts.map +1 -0
- package/dist/quota-ledger.js +462 -0
- package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
- package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/rbac/__tests__/permissions.test.js +350 -0
- package/dist/rbac/index.d.ts +9 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +32 -0
- package/dist/rbac/permissions.d.ts +71 -0
- package/dist/rbac/permissions.d.ts.map +1 -0
- package/dist/rbac/permissions.js +247 -0
- package/dist/rbac/types.d.ts +69 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +213 -0
- package/dist/tier-config.d.ts +203 -0
- package/dist/tier-config.d.ts.map +1 -0
- package/dist/tier-config.js +675 -0
- package/dist/types.d.ts +365 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +127 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
- package/dist/verified-autofix/format-validator.d.ts +101 -0
- package/dist/verified-autofix/format-validator.d.ts.map +1 -0
- package/dist/verified-autofix/format-validator.js +446 -0
- package/dist/verified-autofix/index.d.ts +14 -0
- package/dist/verified-autofix/index.d.ts.map +1 -0
- package/dist/verified-autofix/index.js +39 -0
- package/dist/verified-autofix/pipeline.d.ts +68 -0
- package/dist/verified-autofix/pipeline.d.ts.map +1 -0
- package/dist/verified-autofix/pipeline.js +330 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
- package/dist/verified-autofix/repo-fingerprint.js +396 -0
- package/dist/verified-autofix/workspace.d.ts +83 -0
- package/dist/verified-autofix/workspace.d.ts.map +1 -0
- package/dist/verified-autofix/workspace.js +454 -0
- package/dist/verified-autofix.d.ts +182 -0
- package/dist/verified-autofix.d.ts.map +1 -0
- package/dist/verified-autofix.js +1021 -0
- package/dist/visualization/dependency-graph.d.ts +79 -0
- package/dist/visualization/dependency-graph.d.ts.map +1 -0
- package/dist/visualization/dependency-graph.js +399 -0
- package/dist/visualization/index.d.ts +5 -0
- package/dist/visualization/index.d.ts.map +1 -0
- package/dist/visualization/index.js +20 -0
- package/package.json +29 -0
- package/src/__tests__/autopilot.test.ts +196 -0
- package/src/__tests__/tier-config.test.ts +289 -0
- package/src/__tests__/utils/hash-inline.test.ts +76 -0
- package/src/__tests__/utils/hash.test.ts +119 -0
- package/src/__tests__/utils/simple.test.ts +10 -0
- package/src/__tests__/utils/utils-simple.test.ts +5 -0
- package/src/__tests__/utils/utils.test.ts +203 -0
- package/src/autopilot/autopilot-runner.ts +503 -0
- package/src/autopilot/index.ts +6 -0
- package/src/autopilot/types.ts +119 -0
- package/src/cache/index.ts +7 -0
- package/src/cache/redis-cache.d.ts +155 -0
- package/src/cache/redis-cache.d.ts.map +1 -0
- package/src/cache/redis-cache.ts +517 -0
- package/src/ci/github-actions.ts +335 -0
- package/src/ci/index.ts +12 -0
- package/src/ci/pre-commit.ts +338 -0
- package/src/db/usage-schema.prisma +114 -0
- package/src/entitlements.ts +570 -0
- package/src/env.d.ts +68 -0
- package/src/env.d.ts.map +1 -0
- package/src/env.ts +247 -0
- package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
- package/src/fix-packs/generate-fix-packs.ts +577 -0
- package/src/fix-packs/index.ts +8 -0
- package/src/fix-packs/types.ts +206 -0
- package/src/index.d.ts +7 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +12 -0
- package/src/metrics/prometheus.d.ts +104 -0
- package/src/metrics/prometheus.d.ts.map +1 -0
- package/src/metrics/prometheus.ts +446 -0
- package/src/quota-ledger.ts +548 -0
- package/src/rbac/__tests__/permissions.test.ts +446 -0
- package/src/rbac/index.ts +46 -0
- package/src/rbac/permissions.ts +301 -0
- package/src/rbac/types.ts +298 -0
- package/src/tier-config.json +157 -0
- package/src/tier-config.ts +815 -0
- package/src/types.d.ts +365 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +441 -0
- package/src/utils.d.ts +36 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.ts +140 -0
- package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
- package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
- package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
- package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
- package/src/verified-autofix/format-validator.ts +517 -0
- package/src/verified-autofix/index.ts +63 -0
- package/src/verified-autofix/pipeline.ts +403 -0
- package/src/verified-autofix/repo-fingerprint.ts +459 -0
- package/src/verified-autofix/workspace.ts +531 -0
- package/src/verified-autofix.ts +1187 -0
- package/src/visualization/dependency-graph.d.ts +85 -0
- package/src/visualization/dependency-graph.d.ts.map +1 -0
- package/src/visualization/dependency-graph.ts +495 -0
- package/src/visualization/index.ts +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autopilot.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/autopilot.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Autopilot Tests
|
|
4
|
+
*
|
|
5
|
+
* Tests for the Autopilot batch remediation feature.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const autopilot_runner_1 = require("../autopilot/autopilot-runner");
|
|
9
|
+
const types_1 = require("../autopilot/types");
|
|
10
|
+
describe('AutopilotRunner', () => {
|
|
11
|
+
let runner;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
runner = new autopilot_runner_1.AutopilotRunner();
|
|
14
|
+
process.env['GUARDRAIL_SKIP_ENTITLEMENTS'] = '1';
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
delete process.env['GUARDRAIL_SKIP_ENTITLEMENTS'];
|
|
18
|
+
});
|
|
19
|
+
describe('groupIntoFixPacks', () => {
|
|
20
|
+
it('should group findings by category', () => {
|
|
21
|
+
const findings = [
|
|
22
|
+
{ id: '1', category: 'type-errors', severity: 'high', file: 'a.ts', line: 1, message: 'err', fixable: true },
|
|
23
|
+
{ id: '2', category: 'type-errors', severity: 'high', file: 'b.ts', line: 2, message: 'err', fixable: true },
|
|
24
|
+
{ id: '3', category: 'quality', severity: 'low', file: 'c.ts', line: 3, message: 'console.log', fixable: true },
|
|
25
|
+
];
|
|
26
|
+
const packs = runner.groupIntoFixPacks(findings);
|
|
27
|
+
expect(packs).toHaveLength(2);
|
|
28
|
+
const typeErrorsPack = packs.find(p => p.category === 'type-errors');
|
|
29
|
+
const qualityPack = packs.find(p => p.category === 'quality');
|
|
30
|
+
expect(typeErrorsPack).toBeDefined();
|
|
31
|
+
expect(qualityPack).toBeDefined();
|
|
32
|
+
expect(typeErrorsPack.findings).toHaveLength(2);
|
|
33
|
+
expect(qualityPack.findings).toHaveLength(1);
|
|
34
|
+
});
|
|
35
|
+
it('should exclude non-fixable findings', () => {
|
|
36
|
+
const findings = [
|
|
37
|
+
{ id: '1', category: 'quality', severity: 'low', file: 'a.ts', line: 1, message: 'TODO', fixable: false },
|
|
38
|
+
{ id: '2', category: 'quality', severity: 'low', file: 'b.ts', line: 2, message: 'console.log', fixable: true },
|
|
39
|
+
];
|
|
40
|
+
const packs = runner.groupIntoFixPacks(findings);
|
|
41
|
+
expect(packs).toHaveLength(1);
|
|
42
|
+
expect(packs[0].findings).toHaveLength(1);
|
|
43
|
+
expect(packs[0].findings[0].id).toBe('2');
|
|
44
|
+
});
|
|
45
|
+
it('should respect maxFixes limit', () => {
|
|
46
|
+
const findings = Array.from({ length: 20 }, (_, i) => ({
|
|
47
|
+
id: String(i),
|
|
48
|
+
category: 'type-errors',
|
|
49
|
+
severity: 'high',
|
|
50
|
+
file: `file${i}.ts`,
|
|
51
|
+
line: i,
|
|
52
|
+
message: 'error',
|
|
53
|
+
fixable: true,
|
|
54
|
+
}));
|
|
55
|
+
const packs = runner.groupIntoFixPacks(findings, 5);
|
|
56
|
+
expect(packs).toHaveLength(1);
|
|
57
|
+
expect(packs[0].findings).toHaveLength(5);
|
|
58
|
+
});
|
|
59
|
+
it('should sort packs by priority', () => {
|
|
60
|
+
const findings = [
|
|
61
|
+
{ id: '1', category: 'quality', severity: 'low', file: 'a.ts', line: 1, message: 'q', fixable: true },
|
|
62
|
+
{ id: '2', category: 'security', severity: 'critical', file: 'b.ts', line: 2, message: 's', fixable: true },
|
|
63
|
+
{ id: '3', category: 'type-errors', severity: 'high', file: 'c.ts', line: 3, message: 't', fixable: true },
|
|
64
|
+
];
|
|
65
|
+
const packs = runner.groupIntoFixPacks(findings);
|
|
66
|
+
expect(packs[0].category).toBe('security');
|
|
67
|
+
expect(packs[1].category).toBe('type-errors');
|
|
68
|
+
expect(packs[2].category).toBe('quality');
|
|
69
|
+
});
|
|
70
|
+
it('should calculate risk based on severity', () => {
|
|
71
|
+
const lowSeverityFindings = [
|
|
72
|
+
{ id: '1', category: 'quality', severity: 'low', file: 'a.ts', line: 1, message: 'q', fixable: true },
|
|
73
|
+
];
|
|
74
|
+
const highSeverityFindings = [
|
|
75
|
+
{ id: '2', category: 'security', severity: 'critical', file: 'b.ts', line: 2, message: 's', fixable: true },
|
|
76
|
+
];
|
|
77
|
+
const lowPacks = runner.groupIntoFixPacks(lowSeverityFindings);
|
|
78
|
+
const highPacks = runner.groupIntoFixPacks(highSeverityFindings);
|
|
79
|
+
expect(lowPacks[0].estimatedRisk).toBe('low');
|
|
80
|
+
expect(highPacks[0].estimatedRisk).toBe('medium');
|
|
81
|
+
});
|
|
82
|
+
it('should collect impacted files without duplicates', () => {
|
|
83
|
+
const findings = [
|
|
84
|
+
{ id: '1', category: 'type-errors', severity: 'high', file: 'a.ts', line: 1, message: 'err', fixable: true },
|
|
85
|
+
{ id: '2', category: 'type-errors', severity: 'high', file: 'a.ts', line: 2, message: 'err', fixable: true },
|
|
86
|
+
{ id: '3', category: 'type-errors', severity: 'high', file: 'b.ts', line: 1, message: 'err', fixable: true },
|
|
87
|
+
];
|
|
88
|
+
const packs = runner.groupIntoFixPacks(findings);
|
|
89
|
+
expect(packs[0].impactedFiles).toHaveLength(2);
|
|
90
|
+
expect(packs[0].impactedFiles).toContain('a.ts');
|
|
91
|
+
expect(packs[0].impactedFiles).toContain('b.ts');
|
|
92
|
+
});
|
|
93
|
+
it('should return empty array when no fixable findings', () => {
|
|
94
|
+
const findings = [
|
|
95
|
+
{ id: '1', category: 'quality', severity: 'low', file: 'a.ts', line: 1, message: 'TODO', fixable: false },
|
|
96
|
+
];
|
|
97
|
+
const packs = runner.groupIntoFixPacks(findings);
|
|
98
|
+
expect(packs).toHaveLength(0);
|
|
99
|
+
});
|
|
100
|
+
it('should assign correct priority from FIX_PACK_PRIORITY', () => {
|
|
101
|
+
const findings = [
|
|
102
|
+
{ id: '1', category: 'security', severity: 'high', file: 'a.ts', line: 1, message: 's', fixable: true },
|
|
103
|
+
];
|
|
104
|
+
const packs = runner.groupIntoFixPacks(findings);
|
|
105
|
+
expect(packs[0].priority).toBe(types_1.AUTOPILOT_FIX_PACK_PRIORITY['security']);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('FIX_PACK_PRIORITY', () => {
|
|
109
|
+
it('should have security as highest priority', () => {
|
|
110
|
+
expect(types_1.AUTOPILOT_FIX_PACK_PRIORITY['security']).toBe(1);
|
|
111
|
+
});
|
|
112
|
+
it('should have quality as lowest priority', () => {
|
|
113
|
+
expect(types_1.AUTOPILOT_FIX_PACK_PRIORITY['quality']).toBe(7);
|
|
114
|
+
});
|
|
115
|
+
it('should have all categories defined', () => {
|
|
116
|
+
const categories = [
|
|
117
|
+
'security',
|
|
118
|
+
'build-blockers',
|
|
119
|
+
'type-errors',
|
|
120
|
+
'test-failures',
|
|
121
|
+
'route-integrity',
|
|
122
|
+
'placeholders',
|
|
123
|
+
'quality',
|
|
124
|
+
];
|
|
125
|
+
for (const category of categories) {
|
|
126
|
+
expect(types_1.AUTOPILOT_FIX_PACK_PRIORITY[category]).toBeDefined();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe('Autopilot Entitlement Gating', () => {
|
|
132
|
+
it('should require autopilot feature to be enabled', async () => {
|
|
133
|
+
const runner = new autopilot_runner_1.AutopilotRunner();
|
|
134
|
+
// Without GUARDRAIL_SKIP_ENTITLEMENTS, it should check entitlements
|
|
135
|
+
// In test environment without proper setup, it should fail gracefully
|
|
136
|
+
// This test verifies the entitlement check is wired up
|
|
137
|
+
delete process.env['GUARDRAIL_SKIP_ENTITLEMENTS'];
|
|
138
|
+
// The run method should attempt to check entitlements
|
|
139
|
+
// We expect it to either succeed (if entitlements pass) or fail with entitlement error
|
|
140
|
+
try {
|
|
141
|
+
await runner.run({
|
|
142
|
+
projectPath: process.cwd(),
|
|
143
|
+
mode: 'plan',
|
|
144
|
+
});
|
|
145
|
+
// If we get here, entitlements passed (e.g., in CI with proper config)
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
// Expected to fail with entitlement-related error in test environment
|
|
149
|
+
expect(error.message.includes('autopilot') ||
|
|
150
|
+
error.message.includes('tier') ||
|
|
151
|
+
error.message.includes('feature') ||
|
|
152
|
+
error.message.includes('FEATURE_NOT_AVAILABLE') ||
|
|
153
|
+
error.code === 'FEATURE_NOT_AVAILABLE').toBe(true);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier Configuration Drift Prevention Tests
|
|
3
|
+
*
|
|
4
|
+
* These tests ensure that tier definitions remain consistent across
|
|
5
|
+
* all parts of the codebase. If a tier is added/removed in one place
|
|
6
|
+
* but not others, these tests will fail.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=tier-config.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier-config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tier-config.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tier Configuration Drift Prevention Tests
|
|
4
|
+
*
|
|
5
|
+
* These tests ensure that tier definitions remain consistent across
|
|
6
|
+
* all parts of the codebase. If a tier is added/removed in one place
|
|
7
|
+
* but not others, these tests will fail.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const tier_config_1 = require("../tier-config");
|
|
11
|
+
describe('Tier Configuration', () => {
|
|
12
|
+
describe('Tier Enum Consistency', () => {
|
|
13
|
+
it('should have exactly 6 tiers', () => {
|
|
14
|
+
expect(tier_config_1.TIERS).toHaveLength(6);
|
|
15
|
+
});
|
|
16
|
+
it('should include all required tiers', () => {
|
|
17
|
+
const requiredTiers = ['free', 'starter', 'pro', 'compliance', 'enterprise', 'unlimited'];
|
|
18
|
+
for (const tier of requiredTiers) {
|
|
19
|
+
expect(tier_config_1.TIERS).toContain(tier);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
it('should have TIER_CONFIG for every tier in TIERS', () => {
|
|
23
|
+
for (const tier of tier_config_1.TIERS) {
|
|
24
|
+
expect(tier_config_1.TIER_CONFIG[tier]).toBeDefined();
|
|
25
|
+
expect(tier_config_1.TIER_CONFIG[tier].id).toBe(tier);
|
|
26
|
+
expect(tier_config_1.TIER_CONFIG[tier].name).toBeTruthy();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
it('should have TIER_ORDER match TIERS', () => {
|
|
30
|
+
expect(tier_config_1.TIER_ORDER).toHaveLength(tier_config_1.TIERS.length);
|
|
31
|
+
for (const tier of tier_config_1.TIERS) {
|
|
32
|
+
expect(tier_config_1.TIER_ORDER).toContain(tier);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
it('should have purchasable tiers be a subset of all tiers', () => {
|
|
36
|
+
for (const tier of tier_config_1.PURCHASABLE_TIERS) {
|
|
37
|
+
expect(tier_config_1.TIERS).toContain(tier);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it('should not include free or unlimited in purchasable tiers', () => {
|
|
41
|
+
expect(tier_config_1.PURCHASABLE_TIERS).not.toContain('free');
|
|
42
|
+
expect(tier_config_1.PURCHASABLE_TIERS).not.toContain('unlimited');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('Tier Configuration Completeness', () => {
|
|
46
|
+
it('should have all required fields for each tier', () => {
|
|
47
|
+
for (const tier of tier_config_1.TIERS) {
|
|
48
|
+
const config = tier_config_1.TIER_CONFIG[tier];
|
|
49
|
+
// Required fields
|
|
50
|
+
expect(config.id).toBe(tier);
|
|
51
|
+
expect(typeof config.name).toBe('string');
|
|
52
|
+
expect(typeof config.price).toBe('number');
|
|
53
|
+
expect(typeof config.annualPrice).toBe('number');
|
|
54
|
+
expect(typeof config.description).toBe('string');
|
|
55
|
+
expect(Array.isArray(config.features)).toBe(true);
|
|
56
|
+
// Limits
|
|
57
|
+
expect(typeof config.limits.scansPerMonth).toBe('number');
|
|
58
|
+
expect(typeof config.limits.realityRunsPerMonth).toBe('number');
|
|
59
|
+
expect(typeof config.limits.aiAgentRunsPerMonth).toBe('number');
|
|
60
|
+
expect(typeof config.limits.projects).toBe('number');
|
|
61
|
+
expect(typeof config.limits.teamMembers).toBe('number');
|
|
62
|
+
expect(typeof config.limits.complianceFrameworks).toBe('number');
|
|
63
|
+
// Rate limits
|
|
64
|
+
expect(typeof config.rateLimit.requestsPerMinute).toBe('number');
|
|
65
|
+
expect(typeof config.rateLimit.burstLimit).toBe('number');
|
|
66
|
+
expect(typeof config.rateLimit.windowMs).toBe('number');
|
|
67
|
+
// Upsell
|
|
68
|
+
expect(typeof config.upsell.message).toBe('string');
|
|
69
|
+
expect(tier_config_1.TIERS).toContain(config.upsell.nextTier);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
it('should have features be valid Feature types', () => {
|
|
73
|
+
for (const tier of tier_config_1.TIERS) {
|
|
74
|
+
const config = tier_config_1.TIER_CONFIG[tier];
|
|
75
|
+
for (const feature of config.features) {
|
|
76
|
+
expect(tier_config_1.FEATURES).toContain(feature);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
it('should have increasing limits as tiers increase', () => {
|
|
81
|
+
const orderedTiers = ['free', 'starter', 'pro', 'compliance', 'enterprise'];
|
|
82
|
+
for (let i = 1; i < orderedTiers.length; i++) {
|
|
83
|
+
const prevTierKey = orderedTiers[i - 1];
|
|
84
|
+
const currTierKey = orderedTiers[i];
|
|
85
|
+
const prevTier = tier_config_1.TIER_CONFIG[prevTierKey];
|
|
86
|
+
const currTier = tier_config_1.TIER_CONFIG[currTierKey];
|
|
87
|
+
// Scans should increase or stay unlimited
|
|
88
|
+
if (prevTier.limits.scansPerMonth !== -1) {
|
|
89
|
+
expect(currTier.limits.scansPerMonth).toBeGreaterThanOrEqual(prevTier.limits.scansPerMonth);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
it('should have increasing rate limits as tiers increase', () => {
|
|
94
|
+
const orderedTiers = ['free', 'starter', 'pro', 'compliance', 'enterprise'];
|
|
95
|
+
for (let i = 1; i < orderedTiers.length; i++) {
|
|
96
|
+
const prevTierKey = orderedTiers[i - 1];
|
|
97
|
+
const currTierKey = orderedTiers[i];
|
|
98
|
+
const prevTier = tier_config_1.TIER_CONFIG[prevTierKey];
|
|
99
|
+
const currTier = tier_config_1.TIER_CONFIG[currTierKey];
|
|
100
|
+
expect(currTier.rateLimit.requestsPerMinute).toBeGreaterThanOrEqual(prevTier.rateLimit.requestsPerMinute);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
describe('Pricing Consistency', () => {
|
|
105
|
+
it('should have free tier at $0', () => {
|
|
106
|
+
expect(tier_config_1.TIER_CONFIG.free.price).toBe(0);
|
|
107
|
+
expect(tier_config_1.TIER_CONFIG.free.annualPrice).toBe(0);
|
|
108
|
+
});
|
|
109
|
+
it('should have starter at $29/mo', () => {
|
|
110
|
+
expect(tier_config_1.TIER_CONFIG.starter.price).toBe(29);
|
|
111
|
+
});
|
|
112
|
+
it('should have pro at $99/mo', () => {
|
|
113
|
+
expect(tier_config_1.TIER_CONFIG.pro.price).toBe(99);
|
|
114
|
+
});
|
|
115
|
+
it('should have compliance at $199/mo', () => {
|
|
116
|
+
expect(tier_config_1.TIER_CONFIG.compliance.price).toBe(199);
|
|
117
|
+
});
|
|
118
|
+
it('should have annual pricing be exactly 20% off monthly*12', () => {
|
|
119
|
+
// IMPORTANT: This test ensures the "Save 20%" marketing claim is accurate.
|
|
120
|
+
// If this test fails, either:
|
|
121
|
+
// 1. Update annual prices to be exactly 20% off (monthly * 12 * 0.8)
|
|
122
|
+
// 2. Update the "Save 20%" copy in the UI to match the actual discount
|
|
123
|
+
const EXPECTED_DISCOUNT = 0.20; // 20% off
|
|
124
|
+
const TOLERANCE = 0.005; // Allow 0.5% tolerance for rounding
|
|
125
|
+
for (const tier of tier_config_1.PURCHASABLE_TIERS) {
|
|
126
|
+
const config = tier_config_1.TIER_CONFIG[tier];
|
|
127
|
+
if (config.price > 0) {
|
|
128
|
+
const monthlyTotal = config.price * 12;
|
|
129
|
+
const expectedAnnual = monthlyTotal * (1 - EXPECTED_DISCOUNT);
|
|
130
|
+
const actualDiscount = (monthlyTotal - config.annualPrice) / monthlyTotal;
|
|
131
|
+
// Assert the discount is within tolerance of 20%
|
|
132
|
+
expect(actualDiscount).toBeGreaterThanOrEqual(EXPECTED_DISCOUNT - TOLERANCE);
|
|
133
|
+
expect(actualDiscount).toBeLessThanOrEqual(EXPECTED_DISCOUNT + TOLERANCE);
|
|
134
|
+
// Also verify the annual price is close to expected (within $2 for rounding)
|
|
135
|
+
expect(config.annualPrice).toBeGreaterThanOrEqual(expectedAnnual - 2);
|
|
136
|
+
expect(config.annualPrice).toBeLessThanOrEqual(expectedAnnual + 2);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('Helper Functions', () => {
|
|
142
|
+
it('isValidTier should validate tier strings', () => {
|
|
143
|
+
expect((0, tier_config_1.isValidTier)('free')).toBe(true);
|
|
144
|
+
expect((0, tier_config_1.isValidTier)('starter')).toBe(true);
|
|
145
|
+
expect((0, tier_config_1.isValidTier)('pro')).toBe(true);
|
|
146
|
+
expect((0, tier_config_1.isValidTier)('compliance')).toBe(true);
|
|
147
|
+
expect((0, tier_config_1.isValidTier)('enterprise')).toBe(true);
|
|
148
|
+
expect((0, tier_config_1.isValidTier)('unlimited')).toBe(true);
|
|
149
|
+
expect((0, tier_config_1.isValidTier)('invalid')).toBe(false);
|
|
150
|
+
expect((0, tier_config_1.isValidTier)('team')).toBe(false); // Legacy tier should not be valid
|
|
151
|
+
});
|
|
152
|
+
it('getTierConfig should return correct config', () => {
|
|
153
|
+
expect((0, tier_config_1.getTierConfig)('pro').name).toBe('Pro');
|
|
154
|
+
expect((0, tier_config_1.getTierConfig)('compliance').name).toBe('Compliance');
|
|
155
|
+
});
|
|
156
|
+
it('compareTiers should correctly order tiers', () => {
|
|
157
|
+
expect((0, tier_config_1.compareTiers)('free', 'pro')).toBeLessThan(0);
|
|
158
|
+
expect((0, tier_config_1.compareTiers)('pro', 'free')).toBeGreaterThan(0);
|
|
159
|
+
expect((0, tier_config_1.compareTiers)('pro', 'pro')).toBe(0);
|
|
160
|
+
expect((0, tier_config_1.compareTiers)('starter', 'compliance')).toBeLessThan(0);
|
|
161
|
+
});
|
|
162
|
+
it('isTierHigher should correctly compare tiers', () => {
|
|
163
|
+
expect((0, tier_config_1.isTierHigher)('pro', 'free')).toBe(true);
|
|
164
|
+
expect((0, tier_config_1.isTierHigher)('free', 'pro')).toBe(false);
|
|
165
|
+
expect((0, tier_config_1.isTierHigher)('compliance', 'starter')).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
it('getMinimumTierForFeature should find correct tier', () => {
|
|
168
|
+
expect((0, tier_config_1.getMinimumTierForFeature)('scan')).toBe('free');
|
|
169
|
+
expect((0, tier_config_1.getMinimumTierForFeature)('reality')).toBe('starter');
|
|
170
|
+
expect((0, tier_config_1.getMinimumTierForFeature)('ai-agent')).toBe('pro');
|
|
171
|
+
expect((0, tier_config_1.getMinimumTierForFeature)('compliance:soc2')).toBe('compliance');
|
|
172
|
+
});
|
|
173
|
+
it('tierHasFeature should check features correctly', () => {
|
|
174
|
+
expect((0, tier_config_1.tierHasFeature)('free', 'scan')).toBe(true);
|
|
175
|
+
expect((0, tier_config_1.tierHasFeature)('free', 'reality')).toBe(false);
|
|
176
|
+
expect((0, tier_config_1.tierHasFeature)('starter', 'reality')).toBe(true);
|
|
177
|
+
expect((0, tier_config_1.tierHasFeature)('unlimited', 'compliance:soc2')).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
describe('Pricing Page Integration', () => {
|
|
181
|
+
it('getPricingPageTiers should return 4 tiers for display', () => {
|
|
182
|
+
const pricingTiers = (0, tier_config_1.getPricingPageTiers)();
|
|
183
|
+
expect(pricingTiers).toHaveLength(4);
|
|
184
|
+
});
|
|
185
|
+
it('getPricingPageTiers should include free, starter, pro, compliance', () => {
|
|
186
|
+
const pricingTiers = (0, tier_config_1.getPricingPageTiers)();
|
|
187
|
+
const tierIds = pricingTiers.map(t => t.id);
|
|
188
|
+
expect(tierIds).toContain('free');
|
|
189
|
+
expect(tierIds).toContain('starter');
|
|
190
|
+
expect(tierIds).toContain('pro');
|
|
191
|
+
expect(tierIds).toContain('compliance');
|
|
192
|
+
});
|
|
193
|
+
it('getPricingPageTiers should mark pro as popular', () => {
|
|
194
|
+
const pricingTiers = (0, tier_config_1.getPricingPageTiers)();
|
|
195
|
+
const proTier = pricingTiers.find(t => t.id === 'pro');
|
|
196
|
+
expect(proTier?.popular).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
it('getPricingPageTiers prices should match TIER_CONFIG', () => {
|
|
199
|
+
const pricingTiers = (0, tier_config_1.getPricingPageTiers)();
|
|
200
|
+
for (const tier of pricingTiers) {
|
|
201
|
+
const config = tier_config_1.TIER_CONFIG[tier.id];
|
|
202
|
+
expect(tier.price).toBe(config.price);
|
|
203
|
+
expect(tier.annual).toBe(config.annualPrice);
|
|
204
|
+
expect(tier.name).toBe(config.name);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
describe('Rate Limiter Integration', () => {
|
|
209
|
+
it('getRateLimiterTiers should return config for all tiers', () => {
|
|
210
|
+
const rateLimiterTiers = (0, tier_config_1.getRateLimiterTiers)();
|
|
211
|
+
for (const tier of tier_config_1.TIERS) {
|
|
212
|
+
expect(rateLimiterTiers[tier]).toBeDefined();
|
|
213
|
+
expect(rateLimiterTiers[tier].name).toBe(tier_config_1.TIER_CONFIG[tier].name);
|
|
214
|
+
expect(rateLimiterTiers[tier].baseLimit).toBe(tier_config_1.TIER_CONFIG[tier].rateLimit.requestsPerMinute);
|
|
215
|
+
expect(rateLimiterTiers[tier].burstLimit).toBe(tier_config_1.TIER_CONFIG[tier].rateLimit.burstLimit);
|
|
216
|
+
expect(rateLimiterTiers[tier].windowMs).toBe(tier_config_1.TIER_CONFIG[tier].rateLimit.windowMs);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
describe('No Legacy Tiers', () => {
|
|
221
|
+
it('should not have "team" tier (replaced by compliance)', () => {
|
|
222
|
+
expect(tier_config_1.TIERS).not.toContain('team');
|
|
223
|
+
expect(tier_config_1.TIER_CONFIG).not.toHaveProperty('team');
|
|
224
|
+
});
|
|
225
|
+
it('should not have "basic" tier', () => {
|
|
226
|
+
expect(tier_config_1.TIERS).not.toContain('basic');
|
|
227
|
+
expect(tier_config_1.TIER_CONFIG).not.toHaveProperty('basic');
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-inline.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/hash-inline.test.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,MAAM,KAAyB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
|
+
const crypto = require('node:crypto');
|
|
5
|
+
// Inline hash function for testing
|
|
6
|
+
function calculateHash(content) {
|
|
7
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
8
|
+
}
|
|
9
|
+
describe('Hash Utils', () => {
|
|
10
|
+
describe('calculateHash', () => {
|
|
11
|
+
it('should generate consistent hash for same input', () => {
|
|
12
|
+
const input = 'test-input';
|
|
13
|
+
const hash1 = calculateHash(input);
|
|
14
|
+
const hash2 = calculateHash(input);
|
|
15
|
+
expect(hash1).toBe(hash2);
|
|
16
|
+
expect(hash1).toMatch(/^[a-f0-9]{64}$/);
|
|
17
|
+
});
|
|
18
|
+
it('should generate different hashes for different inputs', () => {
|
|
19
|
+
const hash1 = calculateHash('input1');
|
|
20
|
+
const hash2 = calculateHash('input2');
|
|
21
|
+
expect(hash1).not.toBe(hash2);
|
|
22
|
+
});
|
|
23
|
+
it('should handle empty string', () => {
|
|
24
|
+
const hash = calculateHash('');
|
|
25
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
26
|
+
});
|
|
27
|
+
it('should handle special characters', () => {
|
|
28
|
+
const input = 'test with spaces and symbols !@#$%^&*()';
|
|
29
|
+
const hash = calculateHash(input);
|
|
30
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
31
|
+
});
|
|
32
|
+
it('should handle unicode characters', () => {
|
|
33
|
+
const input = '测试中文 🚀 emoji';
|
|
34
|
+
const hash = calculateHash(input);
|
|
35
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
36
|
+
});
|
|
37
|
+
it('should handle very long strings', () => {
|
|
38
|
+
const input = 'a'.repeat(10000);
|
|
39
|
+
const hash = calculateHash(input);
|
|
40
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('Security Properties', () => {
|
|
44
|
+
it('should generate different hashes for similar inputs', () => {
|
|
45
|
+
const hash1 = calculateHash('password');
|
|
46
|
+
const hash2 = calculateHash('password ');
|
|
47
|
+
expect(hash1).not.toBe(hash2);
|
|
48
|
+
});
|
|
49
|
+
it('should be case-sensitive', () => {
|
|
50
|
+
const hash1 = calculateHash('Test');
|
|
51
|
+
const hash2 = calculateHash('test');
|
|
52
|
+
expect(hash1).not.toBe(hash2);
|
|
53
|
+
});
|
|
54
|
+
it('should produce fixed-length hashes', () => {
|
|
55
|
+
const inputs = ['a', 'abc', 'a long string with many characters'];
|
|
56
|
+
const hashes = inputs.map(calculateHash);
|
|
57
|
+
hashes.forEach(hash => {
|
|
58
|
+
expect(hash.length).toBe(64);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/hash.test.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,MAAM,KAAyB,CAAC;AAQtC,iBAAS,UAAU,CAAC,KAAK,KAAA,EAAE,IAAI,KAAA,WAI9B"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
|
+
const crypto = require('node:crypto');
|
|
5
|
+
// Hash function for testing
|
|
6
|
+
function calculateHash(content) {
|
|
7
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
8
|
+
}
|
|
9
|
+
// Helper function to verify hash
|
|
10
|
+
function verifyHash(input, hash) {
|
|
11
|
+
if (!input || !hash)
|
|
12
|
+
return false;
|
|
13
|
+
const calculatedHash = crypto.createHash('sha256').update(input).digest('hex');
|
|
14
|
+
return calculatedHash === hash;
|
|
15
|
+
}
|
|
16
|
+
describe('Hash Utils', () => {
|
|
17
|
+
describe('calculateHash', () => {
|
|
18
|
+
it('should generate consistent hash for same input', () => {
|
|
19
|
+
const input = 'test-input';
|
|
20
|
+
const hash1 = calculateHash(input);
|
|
21
|
+
const hash2 = calculateHash(input);
|
|
22
|
+
expect(hash1).toBe(hash2);
|
|
23
|
+
expect(hash1).toMatch(/^[a-f0-9]{64}$/);
|
|
24
|
+
});
|
|
25
|
+
it('should generate different hashes for different inputs', () => {
|
|
26
|
+
const hash1 = calculateHash('input1');
|
|
27
|
+
const hash2 = calculateHash('input2');
|
|
28
|
+
expect(hash1).not.toBe(hash2);
|
|
29
|
+
});
|
|
30
|
+
it('should handle empty string', () => {
|
|
31
|
+
const hash = calculateHash('');
|
|
32
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
33
|
+
});
|
|
34
|
+
it('should handle special characters', () => {
|
|
35
|
+
const input = 'test with spaces and symbols !@#$%^&*()';
|
|
36
|
+
const hash = calculateHash(input);
|
|
37
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
38
|
+
});
|
|
39
|
+
it('should handle unicode characters', () => {
|
|
40
|
+
const input = '测试中文 🚀 emoji';
|
|
41
|
+
const hash = calculateHash(input);
|
|
42
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
43
|
+
});
|
|
44
|
+
it('should handle very long strings', () => {
|
|
45
|
+
const input = 'a'.repeat(10000);
|
|
46
|
+
const hash = calculateHash(input);
|
|
47
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('verifyHash', () => {
|
|
51
|
+
it('should verify correct hash', () => {
|
|
52
|
+
const input = 'test-input';
|
|
53
|
+
const hash = calculateHash(input);
|
|
54
|
+
expect(verifyHash(input, hash)).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
it('should reject incorrect hash', () => {
|
|
57
|
+
const input = 'test-input';
|
|
58
|
+
const wrongHash = calculateHash('different-input');
|
|
59
|
+
expect(verifyHash(input, wrongHash)).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
it('should reject empty hash', () => {
|
|
62
|
+
const input = 'test-input';
|
|
63
|
+
expect(verifyHash(input, '')).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
it('should reject invalid hash format', () => {
|
|
66
|
+
const input = 'test-input';
|
|
67
|
+
const invalidHash = 'invalid-hash';
|
|
68
|
+
expect(verifyHash(input, invalidHash)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
it('should handle null/undefined inputs', () => {
|
|
71
|
+
const hash = calculateHash('test');
|
|
72
|
+
expect(verifyHash(null, hash)).toBe(false);
|
|
73
|
+
expect(verifyHash(undefined, hash)).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('Security Properties', () => {
|
|
77
|
+
it('should generate different hashes for similar inputs', () => {
|
|
78
|
+
const hash1 = calculateHash('password');
|
|
79
|
+
const hash2 = calculateHash('password ');
|
|
80
|
+
expect(hash1).not.toBe(hash2);
|
|
81
|
+
});
|
|
82
|
+
it('should be case-sensitive', () => {
|
|
83
|
+
const hash1 = calculateHash('Test');
|
|
84
|
+
const hash2 = calculateHash('test');
|
|
85
|
+
expect(hash1).not.toBe(hash2);
|
|
86
|
+
});
|
|
87
|
+
it('should produce fixed-length hashes', () => {
|
|
88
|
+
const inputs = ['a', 'abc', 'a long string with many characters'];
|
|
89
|
+
const hashes = inputs.map(calculateHash);
|
|
90
|
+
hashes.forEach(hash => {
|
|
91
|
+
expect(hash.length).toBe(64);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=simple.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/simple.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=utils-simple.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-simple.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/utils-simple.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare const crypto: any;
|
|
2
|
+
declare function generateCorrelationId(): string;
|
|
3
|
+
declare function generateTaskId(): string;
|
|
4
|
+
declare function calculateEntropy(str: any): number;
|
|
5
|
+
declare function maskSensitiveValue(value: any): string;
|
|
6
|
+
declare function isPathAllowed(path: any, allowedPaths: any, deniedPaths: any): boolean;
|
|
7
|
+
declare function isDomainAllowed(url: any, allowedDomains: any, deniedDomains: any): boolean;
|
|
8
|
+
declare function sanitizeError(error: any): {
|
|
9
|
+
message: string;
|
|
10
|
+
code: any;
|
|
11
|
+
} | {
|
|
12
|
+
message: string;
|
|
13
|
+
code?: undefined;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=utils.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/utils.test.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,MAAM,KAAyB,CAAC;AAGtC,iBAAS,qBAAqB,WAE7B;AAED,iBAAS,cAAc,WAEtB;AAMD,iBAAS,gBAAgB,CAAC,GAAG,KAAA,UAqB5B;AAED,iBAAS,kBAAkB,CAAC,KAAK,KAAA,UAKhC;AAED,iBAAS,aAAa,CAAC,IAAI,KAAA,EAAE,YAAY,KAAA,EAAE,WAAW,KAAA,WAuBrD;AAED,iBAAS,eAAe,CAAC,GAAG,KAAA,EAAE,cAAc,KAAA,EAAE,aAAa,KAAA,WA4B1D;AAED,iBAAS,aAAa,CAAC,KAAK,KAAA;;;;;;EAQ3B"}
|