import { describe, expect, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as Schema from "effect/Schema"; import { PluginCommandCatalog, PluginCommandInvokeInput, PluginCommandInvocationError, PluginCommandInvocationResult,} from "./pluginCommands.ts";import { WS_METHODS, WsRpcGroup } from "./rpc.ts"; const decodeCatalog = Schema.decodeUnknownEffect(PluginCommandCatalog);const decodeInvokeInput = Schema.decodeUnknownSync(PluginCommandInvokeInput);const decodeInvocationResult = Schema.decodeUnknownSync(PluginCommandInvocationResult); describe("plugin command contracts", () => { it.effect("decodes a multi-surface command catalog", () => Effect.gen(function* () { const catalog = yield* decodeCatalog({ generation: 3, commands: [ { id: "t3.runtime-status", label: "Check plugin runtime", description: "Verify that the environment plugin runtime is responding.", surfaces: ["web", "desktop", "mobile"], }, ], }); expect(catalog.generation).toBe(3); expect(catalog.commands[0]?.surfaces).toEqual(["web", "desktop", "mobile"]); }), ); it.effect("rejects unknown command surfaces", () => Effect.gen(function* () { const exit = yield* Effect.exit( decodeCatalog({ generation: 1, commands: [{ id: "acme.command", label: "Command", surfaces: ["server"] }], }), ); expect(exit._tag).toBe("Failure"); }), ); it("defines generation-bound invocation schemas", () => { expect( decodeInvokeInput({ generation: 4, id: "acme.command", }), ).toEqual({ generation: 4, id: "acme.command" }); expect( decodeInvocationResult({ message: "Command completed.", tone: "success", }), ).toEqual({ message: "Command completed.", tone: "success" }); }); it("derives invocation failure messages from the command id", () => { const error = new PluginCommandInvocationError({ cause: new Error("handler failed"), id: "acme.command", }); expect(error.message).toBe("Plugin command failed: acme.command"); }); it("registers fixed list, invoke, and subscribe rpc methods", () => { expect(WsRpcGroup.requests.has(WS_METHODS.pluginCommandsList)).toBe(true); expect(WsRpcGroup.requests.has(WS_METHODS.pluginCommandsInvoke)).toBe(true); expect(WsRpcGroup.requests.has(WS_METHODS.subscribePluginCommands)).toBe(true); });});
import { describe, expect, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as Schema from "effect/Schema";
import {
PluginCommandCatalog,
PluginCommandInvokeInput,
PluginCommandInvocationError,
PluginCommandInvocationResult,
} from "./pluginCommands.ts";
import { WS_METHODS, WsRpcGroup } from "./rpc.ts";
const decodeCatalog = Schema.decodeUnknownEffect(PluginCommandCatalog);
const decodeInvokeInput = Schema.decodeUnknownSync(PluginCommandInvokeInput);
const decodeInvocationResult = Schema.decodeUnknownSync(PluginCommandInvocationResult);
describe("plugin command contracts", () => {
it.effect("decodes a multi-surface command catalog", () =>
Effect.gen(function* () {
const catalog = yield* decodeCatalog({
generation: 3,
commands: [
{
id: "t3.runtime-status",
label: "Check plugin runtime",
description: "Verify that the environment plugin runtime is responding.",
surfaces: ["web", "desktop", "mobile"],
},
],
});
expect(catalog.generation).toBe(3);
expect(catalog.commands[0]?.surfaces).toEqual(["web", "desktop", "mobile"]);
}),
);
it.effect("rejects unknown command surfaces", () =>
Effect.gen(function* () {
const exit = yield* Effect.exit(
decodeCatalog({
generation: 1,
commands: [{ id: "acme.command", label: "Command", surfaces: ["server"] }],
}),
);
expect(exit._tag).toBe("Failure");
}),
);
it("defines generation-bound invocation schemas", () => {
expect(
decodeInvokeInput({
generation: 4,
id: "acme.command",
}),
).toEqual({ generation: 4, id: "acme.command" });
expect(
decodeInvocationResult({
message: "Command completed.",
tone: "success",
}),
).toEqual({ message: "Command completed.", tone: "success" });
});
it("derives invocation failure messages from the command id", () => {
const error = new PluginCommandInvocationError({
cause: new Error("handler failed"),
id: "acme.command",
});
expect(error.message).toBe("Plugin command failed: acme.command");
});
it("registers fixed list, invoke, and subscribe rpc methods", () => {
expect(WsRpcGroup.requests.has(WS_METHODS.pluginCommandsList)).toBe(true);
expect(WsRpcGroup.requests.has(WS_METHODS.pluginCommandsInvoke)).toBe(true);
expect(WsRpcGroup.requests.has(WS_METHODS.subscribePluginCommands)).toBe(true);
});
});