@markjaquith/agency 0.5.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/LICENSE +21 -0
- package/README.md +109 -0
- package/cli.ts +569 -0
- package/index.ts +1 -0
- package/package.json +65 -0
- package/src/commands/base.test.ts +198 -0
- package/src/commands/base.ts +198 -0
- package/src/commands/clean.test.ts +299 -0
- package/src/commands/clean.ts +320 -0
- package/src/commands/emit.test.ts +412 -0
- package/src/commands/emit.ts +521 -0
- package/src/commands/emitted.test.ts +226 -0
- package/src/commands/emitted.ts +57 -0
- package/src/commands/init.test.ts +311 -0
- package/src/commands/init.ts +140 -0
- package/src/commands/merge.test.ts +365 -0
- package/src/commands/merge.ts +253 -0
- package/src/commands/pull.test.ts +385 -0
- package/src/commands/pull.ts +205 -0
- package/src/commands/push.test.ts +394 -0
- package/src/commands/push.ts +346 -0
- package/src/commands/save.test.ts +247 -0
- package/src/commands/save.ts +162 -0
- package/src/commands/source.test.ts +195 -0
- package/src/commands/source.ts +72 -0
- package/src/commands/status.test.ts +489 -0
- package/src/commands/status.ts +258 -0
- package/src/commands/switch.test.ts +194 -0
- package/src/commands/switch.ts +84 -0
- package/src/commands/task-branching.test.ts +334 -0
- package/src/commands/task-edit.test.ts +141 -0
- package/src/commands/task-main.test.ts +872 -0
- package/src/commands/task.ts +712 -0
- package/src/commands/tasks.test.ts +335 -0
- package/src/commands/tasks.ts +155 -0
- package/src/commands/template-delete.test.ts +178 -0
- package/src/commands/template-delete.ts +98 -0
- package/src/commands/template-list.test.ts +135 -0
- package/src/commands/template-list.ts +87 -0
- package/src/commands/template-view.test.ts +158 -0
- package/src/commands/template-view.ts +86 -0
- package/src/commands/template.test.ts +32 -0
- package/src/commands/template.ts +96 -0
- package/src/commands/use.test.ts +87 -0
- package/src/commands/use.ts +97 -0
- package/src/commands/work.test.ts +462 -0
- package/src/commands/work.ts +193 -0
- package/src/errors.ts +17 -0
- package/src/schemas.ts +33 -0
- package/src/services/AgencyMetadataService.ts +287 -0
- package/src/services/ClaudeService.test.ts +184 -0
- package/src/services/ClaudeService.ts +91 -0
- package/src/services/ConfigService.ts +115 -0
- package/src/services/FileSystemService.ts +222 -0
- package/src/services/GitService.ts +751 -0
- package/src/services/OpencodeService.ts +263 -0
- package/src/services/PromptService.ts +183 -0
- package/src/services/TemplateService.ts +75 -0
- package/src/test-utils.ts +362 -0
- package/src/types/native-exec.d.ts +8 -0
- package/src/types.ts +216 -0
- package/src/utils/colors.ts +178 -0
- package/src/utils/command.ts +17 -0
- package/src/utils/effect.ts +281 -0
- package/src/utils/exec.ts +48 -0
- package/src/utils/paths.ts +51 -0
- package/src/utils/pr-branch.test.ts +372 -0
- package/src/utils/pr-branch.ts +473 -0
- package/src/utils/process.ts +110 -0
- package/src/utils/spinner.ts +82 -0
- package/templates/AGENCY.md +20 -0
- package/templates/AGENTS.md +11 -0
- package/templates/CLAUDE.md +3 -0
- package/templates/TASK.md +5 -0
- package/templates/opencode.json +4 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import { test, expect, describe, beforeEach, afterEach } from "bun:test"
|
|
2
|
+
import { join } from "path"
|
|
3
|
+
import { emit } from "../commands/emit"
|
|
4
|
+
import { task } from "../commands/task"
|
|
5
|
+
import {
|
|
6
|
+
createTempDir,
|
|
7
|
+
cleanupTempDir,
|
|
8
|
+
initGitRepo,
|
|
9
|
+
initAgency,
|
|
10
|
+
fileExists,
|
|
11
|
+
getGitOutput,
|
|
12
|
+
getCurrentBranch,
|
|
13
|
+
createCommit,
|
|
14
|
+
checkoutBranch,
|
|
15
|
+
createBranch,
|
|
16
|
+
addAndCommit,
|
|
17
|
+
setupRemote,
|
|
18
|
+
renameBranch,
|
|
19
|
+
runTestEffect,
|
|
20
|
+
} from "../test-utils"
|
|
21
|
+
|
|
22
|
+
// Cache the git-filter-repo availability check (it doesn't change during test run)
|
|
23
|
+
let hasGitFilterRepoCache: boolean | null = null
|
|
24
|
+
async function checkGitFilterRepo(): Promise<boolean> {
|
|
25
|
+
if (hasGitFilterRepoCache === null) {
|
|
26
|
+
const proc = Bun.spawn(["which", "git-filter-repo"], {
|
|
27
|
+
stdout: "pipe",
|
|
28
|
+
stderr: "pipe",
|
|
29
|
+
})
|
|
30
|
+
await proc.exited
|
|
31
|
+
hasGitFilterRepoCache = proc.exitCode === 0
|
|
32
|
+
}
|
|
33
|
+
return hasGitFilterRepoCache
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("emit command", () => {
|
|
37
|
+
let tempDir: string
|
|
38
|
+
let originalCwd: string
|
|
39
|
+
let hasGitFilterRepo: boolean
|
|
40
|
+
|
|
41
|
+
beforeEach(async () => {
|
|
42
|
+
tempDir = await createTempDir()
|
|
43
|
+
originalCwd = process.cwd()
|
|
44
|
+
process.chdir(tempDir)
|
|
45
|
+
|
|
46
|
+
// Set config path to non-existent file to use defaults
|
|
47
|
+
process.env.AGENCY_CONFIG_PATH = join(tempDir, "non-existent-config.json")
|
|
48
|
+
// Set config dir to temp dir to avoid picking up user's config files
|
|
49
|
+
process.env.AGENCY_CONFIG_DIR = await createTempDir()
|
|
50
|
+
|
|
51
|
+
// Check if git-filter-repo is available (cached)
|
|
52
|
+
hasGitFilterRepo = await checkGitFilterRepo()
|
|
53
|
+
|
|
54
|
+
// Initialize git repo with main branch (already includes initial commit)
|
|
55
|
+
await initGitRepo(tempDir)
|
|
56
|
+
|
|
57
|
+
// Create a source branch (with agency/ prefix)
|
|
58
|
+
await createBranch(tempDir, "agency/test-feature")
|
|
59
|
+
|
|
60
|
+
// Initialize AGENTS.md and commit in one go
|
|
61
|
+
await initAgency(tempDir, "test")
|
|
62
|
+
|
|
63
|
+
await runTestEffect(task({ silent: true }))
|
|
64
|
+
await addAndCommit(tempDir, "AGENTS.md", "Add AGENTS.md")
|
|
65
|
+
|
|
66
|
+
// Set up origin/main for git-filter-repo
|
|
67
|
+
await setupRemote(tempDir, "origin", tempDir)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
afterEach(async () => {
|
|
71
|
+
process.chdir(originalCwd)
|
|
72
|
+
delete process.env.AGENCY_CONFIG_PATH
|
|
73
|
+
if (process.env.AGENCY_CONFIG_DIR) {
|
|
74
|
+
await cleanupTempDir(process.env.AGENCY_CONFIG_DIR)
|
|
75
|
+
delete process.env.AGENCY_CONFIG_DIR
|
|
76
|
+
}
|
|
77
|
+
await cleanupTempDir(tempDir)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
describe("basic functionality", () => {
|
|
81
|
+
test("throws error when git-filter-repo is not installed", async () => {
|
|
82
|
+
if (hasGitFilterRepo) {
|
|
83
|
+
// Skip this test if git-filter-repo IS installed
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await createBranch(tempDir, "agency/feature")
|
|
88
|
+
await createCommit(tempDir, "Feature commit")
|
|
89
|
+
|
|
90
|
+
expect(runTestEffect(emit({ silent: true }))).rejects.toThrow(
|
|
91
|
+
"git-filter-repo is not installed",
|
|
92
|
+
)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test("creates emit branch with default name", async () => {
|
|
96
|
+
// Go back to main and create a fresh source branch (no inherited agency.json)
|
|
97
|
+
await checkoutBranch(tempDir, "main")
|
|
98
|
+
await createBranch(tempDir, "agency/feature")
|
|
99
|
+
// Create agency.json for this branch
|
|
100
|
+
await Bun.write(
|
|
101
|
+
join(tempDir, "agency.json"),
|
|
102
|
+
JSON.stringify({
|
|
103
|
+
version: 1,
|
|
104
|
+
injectedFiles: ["AGENTS.md"],
|
|
105
|
+
template: "test",
|
|
106
|
+
createdAt: new Date().toISOString(),
|
|
107
|
+
}),
|
|
108
|
+
)
|
|
109
|
+
await addAndCommit(tempDir, "agency.json", "Feature commit")
|
|
110
|
+
|
|
111
|
+
// Create emit branch (skip filter for speed)
|
|
112
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
113
|
+
|
|
114
|
+
// Check that emit branch exists (default pattern is %branch%, so emit is just "feature")
|
|
115
|
+
const branches = await getGitOutput(tempDir, [
|
|
116
|
+
"branch",
|
|
117
|
+
"--list",
|
|
118
|
+
"feature",
|
|
119
|
+
])
|
|
120
|
+
expect(branches.trim()).toContain("feature")
|
|
121
|
+
|
|
122
|
+
// Check we're still on the source branch
|
|
123
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
124
|
+
expect(currentBranch).toBe("agency/feature")
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test("creates emit branch with custom name", async () => {
|
|
128
|
+
await createBranch(tempDir, "agency/feature")
|
|
129
|
+
await createCommit(tempDir, "Feature commit")
|
|
130
|
+
|
|
131
|
+
// Skip filter for speed - we're just testing branch creation
|
|
132
|
+
await runTestEffect(
|
|
133
|
+
emit({ branch: "custom-pr", silent: true, skipFilter: true }),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
const branches = await getGitOutput(tempDir, [
|
|
137
|
+
"branch",
|
|
138
|
+
"--list",
|
|
139
|
+
"custom-pr",
|
|
140
|
+
])
|
|
141
|
+
expect(branches.trim()).toContain("custom-pr")
|
|
142
|
+
|
|
143
|
+
// Check we're still on the source branch
|
|
144
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
145
|
+
expect(currentBranch).toBe("agency/feature")
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test("completes emit workflow successfully", async () => {
|
|
149
|
+
await createBranch(tempDir, "agency/feature")
|
|
150
|
+
await createCommit(tempDir, "Feature commit")
|
|
151
|
+
|
|
152
|
+
// Should complete without throwing (skip filter for speed)
|
|
153
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
154
|
+
|
|
155
|
+
// Should still be on source branch
|
|
156
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
157
|
+
expect(currentBranch).toBe("agency/feature")
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
test("preserves files on source branch after emit", async () => {
|
|
161
|
+
await createBranch(tempDir, "agency/feature")
|
|
162
|
+
await createCommit(tempDir, "Feature commit")
|
|
163
|
+
|
|
164
|
+
// Skip filter for speed - we're testing source branch preservation
|
|
165
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
166
|
+
|
|
167
|
+
// Should still be on source branch
|
|
168
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
169
|
+
expect(currentBranch).toBe("agency/feature")
|
|
170
|
+
|
|
171
|
+
// Check that test file still exists on source branch
|
|
172
|
+
expect(await fileExists(join(tempDir, "test.txt"))).toBe(true)
|
|
173
|
+
|
|
174
|
+
const files = await getGitOutput(tempDir, ["ls-files"])
|
|
175
|
+
expect(files).toContain("test.txt")
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test("original branch remains untouched", async () => {
|
|
179
|
+
await createBranch(tempDir, "agency/feature")
|
|
180
|
+
await createCommit(tempDir, "Feature commit")
|
|
181
|
+
|
|
182
|
+
// Create emit branch (skip filter for speed)
|
|
183
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
184
|
+
|
|
185
|
+
// Should still be on feature branch
|
|
186
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
187
|
+
expect(currentBranch).toBe("agency/feature")
|
|
188
|
+
|
|
189
|
+
// Check that AGENTS.md still exist on original branch
|
|
190
|
+
const files = await getGitOutput(tempDir, ["ls-files"])
|
|
191
|
+
expect(files).toContain("AGENTS.md")
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
test("works correctly when run multiple times (recreates emit branch)", async () => {
|
|
195
|
+
await createBranch(tempDir, "agency/feature")
|
|
196
|
+
|
|
197
|
+
// Modify AGENTS.md on feature branch
|
|
198
|
+
await Bun.write(
|
|
199
|
+
join(tempDir, "AGENTS.md"),
|
|
200
|
+
"# Modified by feature branch\n",
|
|
201
|
+
)
|
|
202
|
+
await addAndCommit(tempDir, "AGENTS.md", "Modify AGENTS.md")
|
|
203
|
+
|
|
204
|
+
// Run emit command first time (skip filter for speed)
|
|
205
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
206
|
+
|
|
207
|
+
// Switch back to feature branch
|
|
208
|
+
await checkoutBranch(tempDir, "agency/feature")
|
|
209
|
+
|
|
210
|
+
// Make another commit
|
|
211
|
+
await createCommit(tempDir, "Another feature commit")
|
|
212
|
+
|
|
213
|
+
// Run emit command second time (skip filter for speed)
|
|
214
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
215
|
+
|
|
216
|
+
// Should complete successfully without interactive prompts and stay on source branch
|
|
217
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
218
|
+
expect(currentBranch).toBe("agency/feature")
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test("accepts explicit base branch argument", async () => {
|
|
222
|
+
await createBranch(tempDir, "agency/feature")
|
|
223
|
+
await createCommit(tempDir, "Feature commit")
|
|
224
|
+
|
|
225
|
+
// Create emit branch with explicit base branch (skip filter for speed)
|
|
226
|
+
await runTestEffect(
|
|
227
|
+
emit({ baseBranch: "main", silent: true, skipFilter: true }),
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
// Should stay on source branch
|
|
231
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
232
|
+
expect(currentBranch).toBe("agency/feature")
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
test("throws error if provided base branch does not exist", async () => {
|
|
236
|
+
await createBranch(tempDir, "agency/feature")
|
|
237
|
+
await createCommit(tempDir, "Feature commit")
|
|
238
|
+
|
|
239
|
+
// This should fail even with skipFilter since base branch validation happens first
|
|
240
|
+
expect(
|
|
241
|
+
runTestEffect(
|
|
242
|
+
emit({ baseBranch: "nonexistent", silent: true, skipFilter: true }),
|
|
243
|
+
),
|
|
244
|
+
).rejects.toThrow("does not exist")
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
// Integration tests that actually run git-filter-repo to verify filtering behavior
|
|
249
|
+
// These are slower but ensure the filtering logic works correctly
|
|
250
|
+
describe("filtering integration (requires git-filter-repo)", () => {
|
|
251
|
+
test("filters AGENTS.md from emit branch", async () => {
|
|
252
|
+
if (!hasGitFilterRepo) {
|
|
253
|
+
console.log("Skipping test: git-filter-repo not installed")
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Go back to main and create a fresh source branch
|
|
258
|
+
await checkoutBranch(tempDir, "main")
|
|
259
|
+
await createBranch(tempDir, "agency/feature")
|
|
260
|
+
// Create agency.json with AGENTS.md as managed file
|
|
261
|
+
await Bun.write(
|
|
262
|
+
join(tempDir, "agency.json"),
|
|
263
|
+
JSON.stringify({
|
|
264
|
+
version: 1,
|
|
265
|
+
injectedFiles: ["AGENTS.md"],
|
|
266
|
+
template: "test",
|
|
267
|
+
createdAt: new Date().toISOString(),
|
|
268
|
+
}),
|
|
269
|
+
)
|
|
270
|
+
await Bun.write(join(tempDir, "AGENTS.md"), "# Test AGENTS\n")
|
|
271
|
+
await addAndCommit(tempDir, "agency.json AGENTS.md", "Add agency files")
|
|
272
|
+
// Also create a test.txt file via createCommit
|
|
273
|
+
await createCommit(tempDir, "Feature commit")
|
|
274
|
+
|
|
275
|
+
// Create emit branch (this runs git-filter-repo)
|
|
276
|
+
await runTestEffect(emit({ silent: true }))
|
|
277
|
+
|
|
278
|
+
// Should still be on feature branch
|
|
279
|
+
const currentBranch = await getCurrentBranch(tempDir)
|
|
280
|
+
expect(currentBranch).toBe("agency/feature")
|
|
281
|
+
|
|
282
|
+
// Switch to emit branch to verify files
|
|
283
|
+
await checkoutBranch(tempDir, "feature")
|
|
284
|
+
|
|
285
|
+
// AGENTS.md should be filtered out
|
|
286
|
+
const files = await getGitOutput(tempDir, ["ls-files"])
|
|
287
|
+
expect(files).not.toContain("AGENTS.md")
|
|
288
|
+
expect(files).not.toContain("AGENCY.md")
|
|
289
|
+
|
|
290
|
+
// But test.txt should still exist
|
|
291
|
+
expect(files).toContain("test.txt")
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
test("handles emit branch recreation after source branch rebase", async () => {
|
|
295
|
+
if (!hasGitFilterRepo) {
|
|
296
|
+
console.log("Skipping test: git-filter-repo not installed")
|
|
297
|
+
return
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// We're on test-feature which has AGENTS.md
|
|
301
|
+
// Add a feature-specific file to avoid conflicts
|
|
302
|
+
await Bun.write(join(tempDir, "feature.txt"), "feature content\n")
|
|
303
|
+
await addAndCommit(tempDir, "feature.txt", "Add feature file")
|
|
304
|
+
|
|
305
|
+
// Store merge-base before advancing main
|
|
306
|
+
const initialMergeBase = await getGitOutput(tempDir, [
|
|
307
|
+
"merge-base",
|
|
308
|
+
"agency/test-feature",
|
|
309
|
+
"main",
|
|
310
|
+
])
|
|
311
|
+
|
|
312
|
+
// Create initial emit branch
|
|
313
|
+
await runTestEffect(emit({ silent: true, baseBranch: "main" }))
|
|
314
|
+
|
|
315
|
+
// Should still be on test-feature branch
|
|
316
|
+
let currentBranch = await getCurrentBranch(tempDir)
|
|
317
|
+
expect(currentBranch).toBe("agency/test-feature")
|
|
318
|
+
|
|
319
|
+
// Switch to emit branch to verify AGENTS.md is filtered
|
|
320
|
+
await checkoutBranch(tempDir, "test-feature")
|
|
321
|
+
|
|
322
|
+
let files = await getGitOutput(tempDir, ["ls-files"])
|
|
323
|
+
expect(files).not.toContain("AGENTS.md")
|
|
324
|
+
expect(files).toContain("feature.txt")
|
|
325
|
+
|
|
326
|
+
// Switch back to source branch
|
|
327
|
+
await checkoutBranch(tempDir, "agency/test-feature")
|
|
328
|
+
|
|
329
|
+
// Simulate advancing main branch with a different file
|
|
330
|
+
await checkoutBranch(tempDir, "main")
|
|
331
|
+
await Bun.write(join(tempDir, "main-file.txt"), "main content\n")
|
|
332
|
+
await addAndCommit(tempDir, "main-file.txt", "Main branch advancement")
|
|
333
|
+
|
|
334
|
+
// Rebase test-feature onto new main
|
|
335
|
+
await checkoutBranch(tempDir, "agency/test-feature")
|
|
336
|
+
const rebaseProc = Bun.spawn(["git", "rebase", "main"], {
|
|
337
|
+
cwd: tempDir,
|
|
338
|
+
stdout: "pipe",
|
|
339
|
+
stderr: "pipe",
|
|
340
|
+
})
|
|
341
|
+
await rebaseProc.exited
|
|
342
|
+
if (rebaseProc.exitCode !== 0) {
|
|
343
|
+
const stderr = await new Response(rebaseProc.stderr).text()
|
|
344
|
+
throw new Error(`Rebase failed: ${stderr}`)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Verify merge-base has changed after rebase
|
|
348
|
+
const newMergeBase = await getGitOutput(tempDir, [
|
|
349
|
+
"merge-base",
|
|
350
|
+
"agency/test-feature",
|
|
351
|
+
"main",
|
|
352
|
+
])
|
|
353
|
+
expect(newMergeBase.trim()).not.toBe(initialMergeBase.trim())
|
|
354
|
+
|
|
355
|
+
// Recreate emit branch after rebase (this is where the bug would manifest)
|
|
356
|
+
await runTestEffect(emit({ silent: true, baseBranch: "main" }))
|
|
357
|
+
|
|
358
|
+
// Should still be on test-feature branch
|
|
359
|
+
currentBranch = await getCurrentBranch(tempDir)
|
|
360
|
+
expect(currentBranch).toBe("agency/test-feature")
|
|
361
|
+
|
|
362
|
+
// Switch to emit branch to verify files
|
|
363
|
+
await checkoutBranch(tempDir, "test-feature")
|
|
364
|
+
|
|
365
|
+
// Verify AGENTS.md is still filtered and no extraneous changes
|
|
366
|
+
files = await getGitOutput(tempDir, ["ls-files"])
|
|
367
|
+
expect(files).not.toContain("AGENTS.md")
|
|
368
|
+
expect(files).toContain("feature.txt")
|
|
369
|
+
expect(files).toContain("main-file.txt") // Should have main's file after rebase
|
|
370
|
+
|
|
371
|
+
// Verify that our feature commits exist but AGENTS.md commit is filtered
|
|
372
|
+
const logOutput = await getGitOutput(tempDir, [
|
|
373
|
+
"log",
|
|
374
|
+
"--oneline",
|
|
375
|
+
"main..test-feature",
|
|
376
|
+
])
|
|
377
|
+
expect(logOutput).toContain("Add feature file")
|
|
378
|
+
expect(logOutput).not.toContain("Add AGENTS.md")
|
|
379
|
+
})
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
describe("error handling", () => {
|
|
383
|
+
test("throws error when not in a git repository", async () => {
|
|
384
|
+
const nonGitDir = await createTempDir()
|
|
385
|
+
process.chdir(nonGitDir)
|
|
386
|
+
|
|
387
|
+
expect(runTestEffect(emit({ silent: true }))).rejects.toThrow(
|
|
388
|
+
"Not in a git repository",
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
await cleanupTempDir(nonGitDir)
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
describe("silent mode", () => {
|
|
396
|
+
test("silent flag suppresses output", async () => {
|
|
397
|
+
await createBranch(tempDir, "agency/feature")
|
|
398
|
+
await createCommit(tempDir, "Feature commit")
|
|
399
|
+
|
|
400
|
+
const logs: string[] = []
|
|
401
|
+
const originalLog = console.log
|
|
402
|
+
console.log = (...args: any[]) => logs.push(args.join(" "))
|
|
403
|
+
|
|
404
|
+
// Skip filter for speed
|
|
405
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
406
|
+
|
|
407
|
+
console.log = originalLog
|
|
408
|
+
|
|
409
|
+
expect(logs.length).toBe(0)
|
|
410
|
+
})
|
|
411
|
+
})
|
|
412
|
+
})
|