import { describe, expect, it } from "vitest"; import { createToolcraftModuleDefinition } from "./contract/module-definition"; import type { ToolcraftModuleRecord } from "./contract/module-protocol"; import { snapshotToolcraftModuleData } from "./contract/module-data"; import { resolveToolcraftModuleDependencies } from "./resolution/resolve-module-dependencies"; function moduleDefinition(input: Pick & Partial) { return createToolcraftModuleDefinition({ contributions: [], defaultProviders: [], portRequirements: [], provides: [], requires: [], ...input, }, snapshotToolcraftModuleData); } const capabilityId = "extension.storage"; const consumer = (id: string, ...providerIds: string[]) => moduleDefinition({ id, requires: [capabilityId], defaultProviders: providerIds.map(providerId => ({ capabilityId, providerId })), }); const provider = (id: string) => moduleDefinition({ id, provides: [capabilityId] }); describe("default provider ambiguity", () => { it.each([false, true])("rejects duplicate selected catalog ids independently of catalog order (reverse=%s)", reverse => { const catalog = [ { id: "storage-default", capabilityId, definition: provider("local-storage") }, { id: "storage-default", capabilityId, definition: provider("remote-storage") }, ]; if (reverse) catalog.reverse(); expect(() => resolveToolcraftModuleDependencies([consumer("notes", "storage-default")], catalog)) .toThrow('Default provider "storage-default" is registered more than once'); }); it("rejects several defaults for one unsatisfied requirement rather than choosing alphabetically", () => { const catalog = [ { id: "a", capabilityId, definition: provider("local-storage") }, { id: "b", capabilityId, definition: provider("remote-storage") }, ]; expect(() => resolveToolcraftModuleDependencies([consumer("notes", "b", "a")], catalog)) .toThrow('Module "notes" declares multiple default providers for "extension.storage": a, b'); }); it("does not silently merge different default definitions under the same module id", () => { const local = provider("storage"); const remote = moduleDefinition({ id: "storage", provides: [capabilityId, "storage.remote"] }); const catalog = [ { id: "local", capabilityId, definition: local }, { id: "remote", capabilityId, definition: remote }, ]; expect(() => resolveToolcraftModuleDependencies([consumer("notes", "local"), consumer("palette", "remote")], catalog)) .toThrow('Conflicting default definitions for module "storage"'); }); it("coalesces several references to the same opaque default definition", () => { const storage = provider("storage"); const catalog = [ { id: "local", capabilityId, definition: storage }, { id: "shared", capabilityId, definition: storage }, ]; const result = resolveToolcraftModuleDependencies([consumer("notes", "local"), consumer("palette", "shared")], catalog); expect(result.definitions.filter(definition => definition.id === "storage")).toEqual([storage]); expect(result.modules.find(module => module.id === "storage")?.requestedBy).toEqual(["notes", "palette"]); }); });