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,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace Tests - Temp Workspace Manager
|
|
3
|
+
*
|
|
4
|
+
* Tests for isolated workspace verification:
|
|
5
|
+
* - Workspace creation (copy and worktree)
|
|
6
|
+
* - Diff application via git apply
|
|
7
|
+
* - Verification command execution
|
|
8
|
+
* - Top 3 failure context extraction
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import * as os from 'os';
|
|
14
|
+
import { execSync } from 'child_process';
|
|
15
|
+
import { TempWorkspace } from '../workspace';
|
|
16
|
+
import type { ParsedHunk } from '../format-validator';
|
|
17
|
+
import type { RepoFingerprint } from '../repo-fingerprint';
|
|
18
|
+
|
|
19
|
+
describe('TempWorkspace', () => {
|
|
20
|
+
let tempDir: string;
|
|
21
|
+
let workspace: TempWorkspace;
|
|
22
|
+
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'workspace-test-'));
|
|
25
|
+
workspace = new TempWorkspace();
|
|
26
|
+
|
|
27
|
+
// Create minimal project structure
|
|
28
|
+
await fs.promises.writeFile(
|
|
29
|
+
path.join(tempDir, 'package.json'),
|
|
30
|
+
JSON.stringify({
|
|
31
|
+
name: 'test-project',
|
|
32
|
+
version: '1.0.0',
|
|
33
|
+
scripts: {
|
|
34
|
+
build: 'echo "build complete"',
|
|
35
|
+
test: 'echo "tests passed"',
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Create a source file
|
|
41
|
+
await fs.promises.mkdir(path.join(tempDir, 'src'), { recursive: true });
|
|
42
|
+
await fs.promises.writeFile(
|
|
43
|
+
path.join(tempDir, 'src', 'index.ts'),
|
|
44
|
+
'export const version = "1.0.0";\n'
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterEach(async () => {
|
|
49
|
+
await workspace.cleanupAll();
|
|
50
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('create', () => {
|
|
54
|
+
it('creates workspace via copy when not a git repo', async () => {
|
|
55
|
+
const info = await workspace.create({
|
|
56
|
+
projectPath: tempDir,
|
|
57
|
+
useWorktree: true, // Will fall back to copy since no .git
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(info.type).toBe('copy');
|
|
61
|
+
expect(fs.existsSync(info.path)).toBe(true);
|
|
62
|
+
expect(fs.existsSync(path.join(info.path, 'package.json'))).toBe(true);
|
|
63
|
+
expect(fs.existsSync(path.join(info.path, 'src', 'index.ts'))).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('excludes node_modules from copy', async () => {
|
|
67
|
+
// Create fake node_modules
|
|
68
|
+
await fs.promises.mkdir(path.join(tempDir, 'node_modules', 'lodash'), { recursive: true });
|
|
69
|
+
await fs.promises.writeFile(
|
|
70
|
+
path.join(tempDir, 'node_modules', 'lodash', 'index.js'),
|
|
71
|
+
'module.exports = {};'
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const info = await workspace.create({
|
|
75
|
+
projectPath: tempDir,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(fs.existsSync(path.join(info.path, 'node_modules'))).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('excludes .git from copy', async () => {
|
|
82
|
+
// Create fake .git
|
|
83
|
+
await fs.promises.mkdir(path.join(tempDir, '.git'), { recursive: true });
|
|
84
|
+
await fs.promises.writeFile(path.join(tempDir, '.git', 'config'), '');
|
|
85
|
+
|
|
86
|
+
const info = await workspace.create({
|
|
87
|
+
projectPath: tempDir,
|
|
88
|
+
useWorktree: false, // Force copy mode
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(fs.existsSync(path.join(info.path, '.git'))).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('applyDiff', () => {
|
|
96
|
+
it('applies simple hunk to file', async () => {
|
|
97
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
98
|
+
|
|
99
|
+
const hunks: ParsedHunk[] = [{
|
|
100
|
+
file: 'src/index.ts',
|
|
101
|
+
oldStart: 1,
|
|
102
|
+
oldLines: 1,
|
|
103
|
+
newStart: 1,
|
|
104
|
+
newLines: 2,
|
|
105
|
+
content: `@@ -1,1 +1,2 @@
|
|
106
|
+
export const version = "1.0.0";
|
|
107
|
+
+export const name = "test";`,
|
|
108
|
+
}];
|
|
109
|
+
|
|
110
|
+
const diff = `--- a/src/index.ts
|
|
111
|
+
+++ b/src/index.ts
|
|
112
|
+
@@ -1,1 +1,2 @@
|
|
113
|
+
export const version = "1.0.0";
|
|
114
|
+
+export const name = "test";`;
|
|
115
|
+
|
|
116
|
+
const result = await workspace.applyDiff(info.path, diff, hunks);
|
|
117
|
+
|
|
118
|
+
expect(result.success).toBe(true);
|
|
119
|
+
expect(result.applied).toBe(1);
|
|
120
|
+
expect(result.errors).toHaveLength(0);
|
|
121
|
+
|
|
122
|
+
// Verify file was modified
|
|
123
|
+
const content = await fs.promises.readFile(
|
|
124
|
+
path.join(info.path, 'src', 'index.ts'),
|
|
125
|
+
'utf8'
|
|
126
|
+
);
|
|
127
|
+
expect(content).toContain('export const name = "test"');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('creates new file from diff', async () => {
|
|
131
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
132
|
+
|
|
133
|
+
const hunks: ParsedHunk[] = [{
|
|
134
|
+
file: 'src/utils.ts',
|
|
135
|
+
oldStart: 0,
|
|
136
|
+
oldLines: 0,
|
|
137
|
+
newStart: 1,
|
|
138
|
+
newLines: 1,
|
|
139
|
+
content: `@@ -0,0 +1,1 @@
|
|
140
|
+
+export const add = (a: number, b: number) => a + b;`,
|
|
141
|
+
}];
|
|
142
|
+
|
|
143
|
+
const diff = `--- /dev/null
|
|
144
|
+
+++ b/src/utils.ts
|
|
145
|
+
@@ -0,0 +1,1 @@
|
|
146
|
+
+export const add = (a: number, b: number) => a + b;`;
|
|
147
|
+
|
|
148
|
+
const result = await workspace.applyDiff(info.path, diff, hunks);
|
|
149
|
+
|
|
150
|
+
expect(result.applied).toBeGreaterThan(0);
|
|
151
|
+
expect(fs.existsSync(path.join(info.path, 'src', 'utils.ts'))).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe('verify', () => {
|
|
156
|
+
it('runs verification commands based on fingerprint', async () => {
|
|
157
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
158
|
+
|
|
159
|
+
const fingerprint: RepoFingerprint = {
|
|
160
|
+
packageManager: 'npm',
|
|
161
|
+
buildTool: 'none',
|
|
162
|
+
framework: 'none',
|
|
163
|
+
testRunner: 'none',
|
|
164
|
+
hasTypeScript: false,
|
|
165
|
+
hasESLint: false,
|
|
166
|
+
hasPrettier: false,
|
|
167
|
+
hasBuildScript: true,
|
|
168
|
+
hasTestScript: true,
|
|
169
|
+
isMonorepo: false,
|
|
170
|
+
workspaces: [],
|
|
171
|
+
dependencies: {},
|
|
172
|
+
devDependencies: {},
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const result = await workspace.verify(info.path, fingerprint, {
|
|
176
|
+
skipTests: true,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Build should pass (echo command)
|
|
180
|
+
expect(result.passed).toBe(true);
|
|
181
|
+
expect(result.checks.length).toBeGreaterThan(0);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('extracts top 3 failure context on error', async () => {
|
|
185
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
186
|
+
|
|
187
|
+
// Create a failing build script
|
|
188
|
+
await fs.promises.writeFile(
|
|
189
|
+
path.join(info.path, 'package.json'),
|
|
190
|
+
JSON.stringify({
|
|
191
|
+
name: 'test',
|
|
192
|
+
scripts: {
|
|
193
|
+
build: 'echo "error TS2322: Type mismatch" && echo "error TS2345: Wrong arg" && echo "error TS2339: Missing prop" && exit 1',
|
|
194
|
+
},
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const fingerprint: RepoFingerprint = {
|
|
199
|
+
packageManager: 'npm',
|
|
200
|
+
buildTool: 'none',
|
|
201
|
+
framework: 'none',
|
|
202
|
+
testRunner: 'none',
|
|
203
|
+
hasTypeScript: false,
|
|
204
|
+
hasESLint: false,
|
|
205
|
+
hasPrettier: false,
|
|
206
|
+
hasBuildScript: true,
|
|
207
|
+
hasTestScript: false,
|
|
208
|
+
isMonorepo: false,
|
|
209
|
+
workspaces: [],
|
|
210
|
+
dependencies: {},
|
|
211
|
+
devDependencies: {},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const result = await workspace.verify(info.path, fingerprint, {
|
|
215
|
+
skipTests: true,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(result.passed).toBe(false);
|
|
219
|
+
expect(result.failureContext.length).toBeLessThanOrEqual(3);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe('copyBack', () => {
|
|
224
|
+
it('copies modified files back to project', async () => {
|
|
225
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
226
|
+
|
|
227
|
+
// Modify file in workspace
|
|
228
|
+
await fs.promises.writeFile(
|
|
229
|
+
path.join(info.path, 'src', 'index.ts'),
|
|
230
|
+
'export const version = "2.0.0";\n'
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
await workspace.copyBack(info.path, tempDir, ['src/index.ts']);
|
|
234
|
+
|
|
235
|
+
// Verify original project was updated
|
|
236
|
+
const content = await fs.promises.readFile(
|
|
237
|
+
path.join(tempDir, 'src', 'index.ts'),
|
|
238
|
+
'utf8'
|
|
239
|
+
);
|
|
240
|
+
expect(content).toBe('export const version = "2.0.0";\n');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('creates backup before overwriting', async () => {
|
|
244
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
245
|
+
|
|
246
|
+
// Modify file in workspace
|
|
247
|
+
await fs.promises.writeFile(
|
|
248
|
+
path.join(info.path, 'src', 'index.ts'),
|
|
249
|
+
'export const version = "2.0.0";\n'
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
await workspace.copyBack(info.path, tempDir, ['src/index.ts']);
|
|
253
|
+
|
|
254
|
+
// Backup should exist
|
|
255
|
+
const backupPath = path.join(tempDir, 'src', 'index.ts.guardrail-backup');
|
|
256
|
+
expect(fs.existsSync(backupPath)).toBe(true);
|
|
257
|
+
|
|
258
|
+
const backupContent = await fs.promises.readFile(backupPath, 'utf8');
|
|
259
|
+
expect(backupContent).toBe('export const version = "1.0.0";\n');
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe('cleanup', () => {
|
|
264
|
+
it('removes workspace directory', async () => {
|
|
265
|
+
const info = await workspace.create({ projectPath: tempDir });
|
|
266
|
+
const workspacePath = info.path;
|
|
267
|
+
|
|
268
|
+
expect(fs.existsSync(workspacePath)).toBe(true);
|
|
269
|
+
|
|
270
|
+
await workspace.cleanup(info.id);
|
|
271
|
+
|
|
272
|
+
expect(fs.existsSync(workspacePath)).toBe(false);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe('TempWorkspace with git repo', () => {
|
|
278
|
+
let tempDir: string;
|
|
279
|
+
let workspace: TempWorkspace;
|
|
280
|
+
let isGitAvailable: boolean;
|
|
281
|
+
|
|
282
|
+
beforeAll(() => {
|
|
283
|
+
// Check if git is available
|
|
284
|
+
try {
|
|
285
|
+
execSync('git --version', { stdio: 'pipe' });
|
|
286
|
+
isGitAvailable = true;
|
|
287
|
+
} catch {
|
|
288
|
+
isGitAvailable = false;
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
beforeEach(async () => {
|
|
293
|
+
if (!isGitAvailable) return;
|
|
294
|
+
|
|
295
|
+
tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'workspace-git-test-'));
|
|
296
|
+
workspace = new TempWorkspace();
|
|
297
|
+
|
|
298
|
+
// Initialize git repo
|
|
299
|
+
execSync('git init', { cwd: tempDir, stdio: 'pipe' });
|
|
300
|
+
execSync('git config user.email "test@test.com"', { cwd: tempDir, stdio: 'pipe' });
|
|
301
|
+
execSync('git config user.name "Test"', { cwd: tempDir, stdio: 'pipe' });
|
|
302
|
+
|
|
303
|
+
// Create and commit a file
|
|
304
|
+
await fs.promises.writeFile(
|
|
305
|
+
path.join(tempDir, 'file.ts'),
|
|
306
|
+
'const x = 1;\n'
|
|
307
|
+
);
|
|
308
|
+
execSync('git add .', { cwd: tempDir, stdio: 'pipe' });
|
|
309
|
+
execSync('git commit -m "initial"', { cwd: tempDir, stdio: 'pipe' });
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
afterEach(async () => {
|
|
313
|
+
if (!isGitAvailable) return;
|
|
314
|
+
|
|
315
|
+
await workspace.cleanupAll();
|
|
316
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('uses git worktree when available', async () => {
|
|
320
|
+
if (!isGitAvailable) {
|
|
321
|
+
console.log('Skipping git worktree test - git not available');
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const info = await workspace.create({
|
|
326
|
+
projectPath: tempDir,
|
|
327
|
+
useWorktree: true,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
expect(info.type).toBe('worktree');
|
|
331
|
+
expect(fs.existsSync(path.join(info.path, 'file.ts'))).toBe(true);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('applies diff with git apply', async () => {
|
|
335
|
+
if (!isGitAvailable) {
|
|
336
|
+
console.log('Skipping git apply test - git not available');
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const info = await workspace.create({
|
|
341
|
+
projectPath: tempDir,
|
|
342
|
+
useWorktree: true,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const diff = `--- a/file.ts
|
|
346
|
+
+++ b/file.ts
|
|
347
|
+
@@ -1 +1,2 @@
|
|
348
|
+
const x = 1;
|
|
349
|
+
+const y = 2;
|
|
350
|
+
`;
|
|
351
|
+
|
|
352
|
+
const hunks: ParsedHunk[] = [{
|
|
353
|
+
file: 'file.ts',
|
|
354
|
+
oldStart: 1,
|
|
355
|
+
oldLines: 1,
|
|
356
|
+
newStart: 1,
|
|
357
|
+
newLines: 2,
|
|
358
|
+
content: `@@ -1 +1,2 @@
|
|
359
|
+
const x = 1;
|
|
360
|
+
+const y = 2;`,
|
|
361
|
+
}];
|
|
362
|
+
|
|
363
|
+
const result = await workspace.applyDiff(info.path, diff, hunks);
|
|
364
|
+
|
|
365
|
+
expect(result.success).toBe(true);
|
|
366
|
+
|
|
367
|
+
const content = await fs.promises.readFile(
|
|
368
|
+
path.join(info.path, 'file.ts'),
|
|
369
|
+
'utf8'
|
|
370
|
+
);
|
|
371
|
+
expect(content).toContain('const y = 2');
|
|
372
|
+
});
|
|
373
|
+
});
|