|
1 | 1 | import * as NodeFileSystem from "@effect/platform-node-shared/NodeFileSystem" |
2 | | -import { describe } from "@effect/vitest" |
| 2 | +import { assert, describe, it } from "@effect/vitest" |
| 3 | +import * as Deferred from "effect/Deferred" |
| 4 | +import * as Effect from "effect/Effect" |
| 5 | +import * as Fiber from "effect/Fiber" |
| 6 | +import * as FileSystem from "effect/FileSystem" |
| 7 | +import * as Stream from "effect/Stream" |
| 8 | +import * as TestClock from "effect/testing/TestClock" |
3 | 9 | import { testLayer } from "../../effect/test/FileSystem.test-utils.ts" |
4 | 10 |
|
5 | | -describe("FileSystem", () => testLayer(NodeFileSystem.layer)) |
| 11 | +const startWatch = <E, R>( |
| 12 | + fs: FileSystem.FileSystem, |
| 13 | + root: string, |
| 14 | + watch: () => Stream.Stream<FileSystem.WatchEvent, E, R> |
| 15 | +) => |
| 16 | + Effect.gen(function*() { |
| 17 | + const ready = yield* Deferred.make<void>() |
| 18 | + const readyName = ".watch-ready" |
| 19 | + const fiber = yield* watch().pipe( |
| 20 | + Stream.tap((event) => |
| 21 | + event.path === readyName |
| 22 | + ? Deferred.succeed(ready, undefined) |
| 23 | + : Effect.void |
| 24 | + ), |
| 25 | + Stream.filter((event) => event.path !== readyName), |
| 26 | + Stream.runHead, |
| 27 | + Effect.flatMap(Effect.fromOption), |
| 28 | + Effect.forkChild |
| 29 | + ) |
| 30 | + const signalFiber = yield* Effect.sleep("10 millis").pipe( |
| 31 | + TestClock.withLive, |
| 32 | + Effect.andThen(fs.writeFileString(`${root}/${readyName}`, "")), |
| 33 | + Effect.forever, |
| 34 | + Effect.forkChild |
| 35 | + ) |
| 36 | + yield* Deferred.await(ready).pipe( |
| 37 | + Effect.raceFirst(Fiber.join(fiber).pipe(Effect.asVoid)), |
| 38 | + Effect.ensuring(Fiber.interrupt(signalFiber)) |
| 39 | + ) |
| 40 | + return fiber |
| 41 | + }) |
| 42 | + |
| 43 | +describe("FileSystem", () => { |
| 44 | + testLayer(NodeFileSystem.layer) |
| 45 | + |
| 46 | + it.effect("watch does not report nested changes when recursive is false", () => |
| 47 | + Effect.gen(function*() { |
| 48 | + const fs = yield* FileSystem.FileSystem |
| 49 | + const root = yield* fs.makeTempDirectoryScoped() |
| 50 | + const nested = `${root}/nested` |
| 51 | + yield* fs.makeDirectory(nested) |
| 52 | + |
| 53 | + const fiber = yield* startWatch(fs, root, () => fs.watch(root, { recursive: false })) |
| 54 | + |
| 55 | + yield* fs.writeFileString(`${nested}/nested.txt`, "") |
| 56 | + yield* fs.writeFileString(`${root}/direct.txt`, "") |
| 57 | + |
| 58 | + const event = yield* Fiber.join(fiber) |
| 59 | + assert.strictEqual(event.path, "direct.txt") |
| 60 | + }).pipe( |
| 61 | + Effect.scoped, |
| 62 | + Effect.provide(NodeFileSystem.layer) |
| 63 | + )) |
| 64 | + |
| 65 | + it.effect("watch is non-recursive when options are omitted", () => |
| 66 | + Effect.gen(function*() { |
| 67 | + const fs = yield* FileSystem.FileSystem |
| 68 | + const root = yield* fs.makeTempDirectoryScoped() |
| 69 | + const nested = `${root}/nested` |
| 70 | + yield* fs.makeDirectory(nested) |
| 71 | + |
| 72 | + const fiber = yield* startWatch(fs, root, () => fs.watch(root)) |
| 73 | + |
| 74 | + yield* fs.writeFileString(`${nested}/nested.txt`, "") |
| 75 | + yield* fs.writeFileString(`${root}/direct.txt`, "") |
| 76 | + |
| 77 | + const event = yield* Fiber.join(fiber) |
| 78 | + assert.strictEqual(event.path, "direct.txt") |
| 79 | + }).pipe( |
| 80 | + Effect.scoped, |
| 81 | + Effect.provide(NodeFileSystem.layer) |
| 82 | + )) |
| 83 | + |
| 84 | + it.effect("watch reports nested changes when recursive is true", () => |
| 85 | + Effect.gen(function*() { |
| 86 | + const fs = yield* FileSystem.FileSystem |
| 87 | + const root = yield* fs.makeTempDirectoryScoped() |
| 88 | + const nested = `${root}/nested` |
| 89 | + yield* fs.makeDirectory(nested) |
| 90 | + |
| 91 | + const fiber = yield* startWatch(fs, root, () => fs.watch(root, { recursive: true })) |
| 92 | + |
| 93 | + yield* fs.writeFileString(`${nested}/nested.txt`, "") |
| 94 | + |
| 95 | + const event = yield* Fiber.join(fiber) |
| 96 | + assert(event.path.endsWith("nested.txt")) |
| 97 | + }).pipe( |
| 98 | + Effect.scoped, |
| 99 | + Effect.provide(NodeFileSystem.layer) |
| 100 | + )) |
| 101 | +}) |
0 commit comments