import * as NodeServices from "@effect/platform-node/NodeServices";import { it, describe, expect } from "@effect/vitest";import { Effect, FileSystem, Layer, Path } from "effect"; import { ProjectFaviconResolver } from "../Services/ProjectFaviconResolver.ts";import { ProjectFaviconResolverLive } from "./ProjectFaviconResolver.ts"; const TestLayer = Layer.empty.pipe( Layer.provideMerge(ProjectFaviconResolverLive), Layer.provideMerge(NodeServices.layer),); const makeTempDir = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; return yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3code-project-favicon-", });}); const writeTextFile = Effect.fn("writeTextFile")(function* ( cwd: string, relativePath: string, contents: string,) { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const absolutePath = path.join(cwd, relativePath); yield* fileSystem .makeDirectory(path.dirname(absolutePath), { recursive: true }) .pipe(Effect.orDie); yield* fileSystem.writeFileString(absolutePath, contents).pipe(Effect.orDie);}); it.layer(TestLayer)("ProjectFaviconResolverLive", (it) => { describe("resolvePath", () => { it.effect("prefers well-known favicon files", () => Effect.gen(function* () { const resolver = yield* ProjectFaviconResolver; const cwd = yield* makeTempDir; yield* writeTextFile(cwd, "favicon.svg", "<svg>favicon</svg>"); const resolved = yield* resolver.resolvePath(cwd); expect(resolved).not.toBeNull(); expect(resolved).toContain("favicon.svg"); }), ); it.effect("resolves icon hrefs from project source files", () => Effect.gen(function* () { const resolver = yield* ProjectFaviconResolver; const cwd = yield* makeTempDir; yield* writeTextFile(cwd, "index.html", '<link rel="icon" href="/brand/logo.svg">'); yield* writeTextFile(cwd, "public/brand/logo.svg", "<svg>brand</svg>"); const resolved = yield* resolver.resolvePath(cwd); expect(resolved).not.toBeNull(); expect(resolved).toContain("public/brand/logo.svg"); }), ); it.effect("returns null when no icon is present", () => Effect.gen(function* () { const resolver = yield* ProjectFaviconResolver; const cwd = yield* makeTempDir; const resolved = yield* resolver.resolvePath(cwd); expect(resolved).toBeNull(); }), ); });});
import * as NodeServices from "@effect/platform-node/NodeServices";
import { it, describe, expect } from "@effect/vitest";
import { Effect, FileSystem, Layer, Path } from "effect";
import { ProjectFaviconResolver } from "../Services/ProjectFaviconResolver.ts";
import { ProjectFaviconResolverLive } from "./ProjectFaviconResolver.ts";
const TestLayer = Layer.empty.pipe(
Layer.provideMerge(ProjectFaviconResolverLive),
Layer.provideMerge(NodeServices.layer),
);
const makeTempDir = Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
return yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3code-project-favicon-",
});
});
const writeTextFile = Effect.fn("writeTextFile")(function* (
cwd: string,
relativePath: string,
contents: string,
) {
const fileSystem = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const absolutePath = path.join(cwd, relativePath);
yield* fileSystem
.makeDirectory(path.dirname(absolutePath), { recursive: true })
.pipe(Effect.orDie);
yield* fileSystem.writeFileString(absolutePath, contents).pipe(Effect.orDie);
});
it.layer(TestLayer)("ProjectFaviconResolverLive", (it) => {
describe("resolvePath", () => {
it.effect("prefers well-known favicon files", () =>
Effect.gen(function* () {
const resolver = yield* ProjectFaviconResolver;
const cwd = yield* makeTempDir;
yield* writeTextFile(cwd, "favicon.svg", "<svg>favicon</svg>");
const resolved = yield* resolver.resolvePath(cwd);
expect(resolved).not.toBeNull();
expect(resolved).toContain("favicon.svg");
}),
);
it.effect("resolves icon hrefs from project source files", () =>
Effect.gen(function* () {
const resolver = yield* ProjectFaviconResolver;
const cwd = yield* makeTempDir;
yield* writeTextFile(cwd, "index.html", '<link rel="icon" href="/brand/logo.svg">');
yield* writeTextFile(cwd, "public/brand/logo.svg", "<svg>brand</svg>");
const resolved = yield* resolver.resolvePath(cwd);
expect(resolved).not.toBeNull();
expect(resolved).toContain("public/brand/logo.svg");
}),
);
it.effect("returns null when no icon is present", () =>
Effect.gen(function* () {
const resolver = yield* ProjectFaviconResolver;
const cwd = yield* makeTempDir;
const resolved = yield* resolver.resolvePath(cwd);
expect(resolved).toBeNull();
}),
);
});
});