Showing the changes to apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts (1 of 62 files). Show all
Unified · Split
| @@ -54,6 +54,64 @@ const writeTextFile = Effect.fn("writeTextFile")(function* ( · 53 unmodified lines | |||
| 54 | }); | 54 | }); |
| 55 | 55 | ||
| 56 | it.layer(TestLayer)("WorkspaceFileSystemLive", (it) => { | 56 | it.layer(TestLayer)("WorkspaceFileSystemLive", (it) => { |
| 57 | describe("readFile", () => { | ||
| 58 | it.effect("reads UTF-8 files relative to the workspace root", () => | ||
| 59 | Effect.gen(function* () { | ||
| 60 | const workspaceFileSystem = yield* WorkspaceFileSystem; | ||
| 61 | const cwd = yield* makeTempDir; | ||
| 62 | yield* writeTextFile(cwd, "src/index.ts", "export const answer = 42;\n"); | ||
| 63 | |||
| 64 | const result = yield* workspaceFileSystem.readFile({ | ||
| 65 | cwd, | ||
| 66 | relativePath: "src/index.ts", | ||
| 67 | }); | ||
| 68 | |||
| 69 | expect(result).toEqual({ | ||
| 70 | relativePath: "src/index.ts", | ||
| 71 | contents: "export const answer = 42;\n", | ||
| 72 | byteLength: 26, | ||
| 73 | truncated: false, | ||
| 74 | }); | ||
| 75 | }), | ||
| 76 | ); | ||
| 77 | |||
| 78 | it.effect("rejects reads outside the workspace root", () => | ||
| 79 | Effect.gen(function* () { | ||
| 80 | const workspaceFileSystem = yield* WorkspaceFileSystem; | ||
| 81 | const cwd = yield* makeTempDir; | ||
| 82 | |||
| 83 | const error = yield* workspaceFileSystem | ||
| 84 | .readFile({ cwd, relativePath: "../escape.md" }) | ||
| 85 | .pipe(Effect.flip); | ||
| 86 | |||
| 87 | expect(error.message).toContain( | ||
| 88 | "Workspace file path must be relative to the project root: ../escape.md", | ||
| 89 | ); | ||
| 90 | }), | ||
| 91 | ); | ||
| 92 | |||
| 93 | it.effect("rejects symlinks that resolve outside the workspace root", () => | ||
| 94 | Effect.gen(function* () { | ||
| 95 | const workspaceFileSystem = yield* WorkspaceFileSystem; | ||
| 96 | const fileSystem = yield* FileSystem.FileSystem; | ||
| 97 | const path = yield* Path.Path; | ||
| 98 | const cwd = yield* makeTempDir; | ||
| 99 | const outsideDir = yield* makeTempDir; | ||
| 100 | yield* writeTextFile(outsideDir, "secret.txt", "outside\n"); | ||
| 101 | yield* fileSystem.symlink( | ||
| 102 | path.join(outsideDir, "secret.txt"), | ||
| 103 | path.join(cwd, "linked-secret.txt"), | ||
| 104 | ); | ||
| 105 | |||
| 106 | const error = yield* workspaceFileSystem | ||
| 107 | .readFile({ cwd, relativePath: "linked-secret.txt" }) | ||
| 108 | .pipe(Effect.flip); | ||
| 109 | |||
| 110 | expect(error.message).toContain("resolves outside the project root"); | ||
| 111 | }), | ||
| 112 | ); | ||
| 113 | }); | ||
| 114 | |||
| 57 | describe("writeFile", () => { | 115 | describe("writeFile", () => { |
| 58 | it.effect("writes files relative to the workspace root", () => | 116 | it.effect("writes files relative to the workspace root", () => |
| 59 | Effect.gen(function* () { | 117 | Effect.gen(function* () { |