| ... | @@ -3,10 +3,13 @@ import type { RepositoryIdentity } from "@t3tools/contracts"; | ... | @@ -3,10 +3,13 @@ import type { RepositoryIdentity } from "@t3tools/contracts"; |
| 3 | import * as Deferred from "effect/Deferred"; | 3 | import * as Deferred from "effect/Deferred"; |
| 4 | import * as Effect from "effect/Effect"; | 4 | import * as Effect from "effect/Effect"; |
| 5 | import * as Layer from "effect/Layer"; | 5 | import * as Layer from "effect/Layer"; |
| | 6 | import * as Logger from "effect/Logger"; |
| 6 | import * as PubSub from "effect/PubSub"; | 7 | import * as PubSub from "effect/PubSub"; |
| 7 | import * as Ref from "effect/Ref"; | 8 | import * as Ref from "effect/Ref"; |
| 8 | import { TestClock } from "effect/testing"; | 9 | import { TestClock } from "effect/testing"; |
| 9 | | 10 | |
| | 11 | import * as WorkspacePaths from "../workspace/WorkspacePaths.ts"; |
| | 12 | |
| 10 | import * as ProjectEnrichment from "./ProjectEnrichmentService.ts"; | 13 | import * as ProjectEnrichment from "./ProjectEnrichmentService.ts"; |
| 11 | import * as ProjectFaviconResolver from "./ProjectFaviconResolver.ts"; | 14 | import * as ProjectFaviconResolver from "./ProjectFaviconResolver.ts"; |
| 12 | import * as RepositoryIdentityResolver from "./RepositoryIdentityResolver.ts"; | 15 | import * as RepositoryIdentityResolver from "./RepositoryIdentityResolver.ts"; |
| ... | @@ -95,6 +98,58 @@ it.effect("preserves either enrichment field when the other resolver fails", () | ... | @@ -95,6 +98,58 @@ it.effect("preserves either enrichment field when the other resolver fails", () |
| 95 | }), | 98 | }), |
| 96 | ); | 99 | ); |
| 97 | | 100 | |
| | 101 | it.effect("does not warn about favicons for workspace roots that no longer exist", () => |
| | 102 | Effect.gen(function* () { |
| | 103 | const warnings: Array<unknown> = []; |
| | 104 | const logger = Logger.make(({ message }) => { |
| | 105 | warnings.push(message); |
| | 106 | }); |
| | 107 | const metadataLayer = Layer.merge( |
| | 108 | Layer.succeed(RepositoryIdentityResolver.RepositoryIdentityResolver, { |
| | 109 | resolve: (workspaceRoot) => Effect.succeed(identity(workspaceRoot)), |
| | 110 | }), |
| | 111 | Layer.succeed(ProjectFaviconResolver.ProjectFaviconResolver, { |
| | 112 | resolvePath: (workspaceRoot) => |
| | 113 | Effect.fail( |
| | 114 | workspaceRoot === "/missing" |
| | 115 | ? new ProjectFaviconResolver.ProjectFaviconResolutionError({ |
| | 116 | operation: "normalize-workspace", |
| | 117 | workspaceRoot, |
| | 118 | cause: new WorkspacePaths.WorkspaceRootNotExistsError({ |
| | 119 | workspaceRoot, |
| | 120 | normalizedWorkspaceRoot: workspaceRoot, |
| | 121 | }), |
| | 122 | }) |
| | 123 | : new ProjectFaviconResolver.ProjectFaviconResolutionError({ |
| | 124 | operation: "stat-candidate", |
| | 125 | workspaceRoot, |
| | 126 | cause: "favicon resolver failed", |
| | 127 | }), |
| | 128 | ), |
| | 129 | }), |
| | 130 | ); |
| | 131 | |
| | 132 | yield* Effect.gen(function* () { |
| | 133 | const service = yield* ProjectEnrichment.ProjectEnrichmentService; |
| | 134 | yield* service.request("/missing"); |
| | 135 | yield* service.request("/broken"); |
| | 136 | |
| | 137 | for (let attempt = 0; attempt < 100 && warnings.length === 0; attempt += 1) { |
| | 138 | yield* Effect.yieldNow; |
| | 139 | } |
| | 140 | |
| | 141 | assert.lengthOf(warnings, 1); |
| | 142 | assert.nestedPropertyVal(warnings[0], "[1].workspaceRoot", "/broken"); |
| | 143 | }).pipe( |
| | 144 | Effect.provide( |
| | 145 | layer(metadataLayer, { concurrency: 1 }).pipe( |
| | 146 | Layer.provide(Logger.layer([logger], { mergeWithExisting: false })), |
| | 147 | ), |
| | 148 | ), |
| | 149 | ); |
| | 150 | }), |
| | 151 | ); |
| | 152 | |
| 98 | it.effect("publishes repository completion while favicon enrichment is still pending", () => | 153 | it.effect("publishes repository completion while favicon enrichment is still pending", () => |
| 99 | Effect.gen(function* () { | 154 | Effect.gen(function* () { |
| 100 | const releaseFavicon = yield* Deferred.make<void>(); | 155 | const releaseFavicon = yield* Deferred.make<void>(); |