|
1 | 1 | import { NodeServices } from "@effect/platform-node"; |
2 | | -import { Effect } from "effect"; |
| 2 | +import { describe, expect, layer } from "@effect/vitest"; |
| 3 | +import { Effect, Layer } from "effect"; |
3 | 4 | import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; |
4 | 5 | import { tmpdir } from "node:os"; |
5 | 6 | import { join } from "node:path"; |
6 | | -import { afterEach, describe, expect, it } from "vitest"; |
7 | | -import { executeHooks, type HookInput } from "../src/services/hooks.ts"; |
8 | | - |
9 | | -const runEffect = <A>(effect: Effect.Effect<A, unknown, any>) => |
10 | | - Effect.runPromise(Effect.provide(effect, NodeServices.layer) as Effect.Effect<A, unknown, never>); |
| 7 | +import { afterEach } from "vitest"; |
| 8 | +import { HookService, HookServiceLive, type HookInput } from "../src/services/hooks.ts"; |
11 | 9 |
|
12 | 10 | const hookInput: HookInput = { |
13 | 11 | diff: "", |
@@ -35,26 +33,36 @@ afterEach(() => { |
35 | 33 | } |
36 | 34 | }); |
37 | 35 |
|
38 | | -describe("executeHooks", () => { |
39 | | - it("fails when a configured shell hook is missing", async () => { |
40 | | - const dir = mkdtempSync(join(tmpdir(), "git-agent-hooks-")); |
41 | | - tempDirs.push(dir); |
42 | | - const hookPath = join(dir, "missing-hook.sh"); |
| 36 | +describe("HookService", () => { |
| 37 | + layer(HookServiceLive.pipe(Layer.provide(NodeServices.layer)))((it) => { |
| 38 | + it.effect( |
| 39 | + "fails when a configured shell hook is missing", |
| 40 | + Effect.fn(function* () { |
| 41 | + const dir = mkdtempSync(join(tmpdir(), "git-agent-hooks-")); |
| 42 | + tempDirs.push(dir); |
| 43 | + const hookPath = join(dir, "missing-hook.sh"); |
| 44 | + const hookService = yield* HookService; |
43 | 45 |
|
44 | | - await expect(runEffect(executeHooks([hookPath], hookInput))).rejects.toMatchObject({ |
45 | | - message: expect.stringContaining(`failed to read hook "${hookPath}"`), |
46 | | - }); |
47 | | - }); |
| 46 | + const error = yield* Effect.flip(hookService.execute([hookPath], hookInput)); |
| 47 | + |
| 48 | + expect(error.message).toContain(`failed to read hook "${hookPath}"`); |
| 49 | + }), |
| 50 | + ); |
| 51 | + |
| 52 | + it.effect( |
| 53 | + "fails for non-executable hook files", |
| 54 | + Effect.fn(function* () { |
| 55 | + const dir = mkdtempSync(join(tmpdir(), "git-agent-hooks-")); |
| 56 | + tempDirs.push(dir); |
| 57 | + const hookPath = join(dir, "hook.sh"); |
| 58 | + writeFileSync(hookPath, "#!/bin/sh\nexit 0\n"); |
| 59 | + chmodSync(hookPath, 0o644); |
| 60 | + const hookService = yield* HookService; |
48 | 61 |
|
49 | | - it("fails for non-executable hook files", async () => { |
50 | | - const dir = mkdtempSync(join(tmpdir(), "git-agent-hooks-")); |
51 | | - tempDirs.push(dir); |
52 | | - const hookPath = join(dir, "hook.sh"); |
53 | | - writeFileSync(hookPath, "#!/bin/sh\nexit 0\n"); |
54 | | - chmodSync(hookPath, 0o644); |
| 62 | + const error = yield* Effect.flip(hookService.execute([hookPath], hookInput)); |
55 | 63 |
|
56 | | - await expect(runEffect(executeHooks([hookPath], hookInput))).rejects.toMatchObject({ |
57 | | - message: `hook is not executable: ${hookPath}`, |
58 | | - }); |
| 64 | + expect(error.message).toBe(`hook is not executable: ${hookPath}`); |
| 65 | + }), |
| 66 | + ); |
59 | 67 | }); |
60 | 68 | }); |
0 commit comments