mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-26 16:06:16 +00:00
Channels: add contract surface coverage
This commit is contained in:
73
src/channels/plugins/contracts/registry.contract.test.ts
Normal file
73
src/channels/plugins/contracts/registry.contract.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
actionContractRegistry,
|
||||
pluginContractRegistry,
|
||||
setupContractRegistry,
|
||||
statusContractRegistry,
|
||||
surfaceContractRegistry,
|
||||
type ChannelPluginSurface,
|
||||
} from "./registry.js";
|
||||
|
||||
const orderedSurfaceKeys = [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
] as const satisfies readonly ChannelPluginSurface[];
|
||||
|
||||
describe("channel contract registry", () => {
|
||||
it("does not duplicate channel plugin ids", () => {
|
||||
const ids = pluginContractRegistry.map((entry) => entry.id);
|
||||
expect(ids).toEqual([...new Set(ids)]);
|
||||
});
|
||||
|
||||
it("keeps the surface registry aligned with the plugin registry", () => {
|
||||
expect(surfaceContractRegistry.map((entry) => entry.id).toSorted()).toEqual(
|
||||
pluginContractRegistry.map((entry) => entry.id).toSorted(),
|
||||
);
|
||||
});
|
||||
|
||||
it("declares the actual owned channel plugin surfaces explicitly", () => {
|
||||
for (const entry of surfaceContractRegistry) {
|
||||
const actual = orderedSurfaceKeys.filter((surface) => Boolean(entry.plugin[surface]));
|
||||
expect([...entry.surfaces].toSorted()).toEqual(actual.toSorted());
|
||||
}
|
||||
});
|
||||
|
||||
it("only installs deep action coverage for plugins that declare actions", () => {
|
||||
const actionSurfaceIds = new Set(
|
||||
surfaceContractRegistry
|
||||
.filter((entry) => entry.surfaces.includes("actions"))
|
||||
.map((entry) => entry.id),
|
||||
);
|
||||
for (const entry of actionContractRegistry) {
|
||||
expect(actionSurfaceIds.has(entry.id)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("only installs deep setup coverage for plugins that declare setup", () => {
|
||||
const setupSurfaceIds = new Set(
|
||||
surfaceContractRegistry
|
||||
.filter((entry) => entry.surfaces.includes("setup"))
|
||||
.map((entry) => entry.id),
|
||||
);
|
||||
for (const entry of setupContractRegistry) {
|
||||
expect(setupSurfaceIds.has(entry.id)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("only installs deep status coverage for plugins that declare status", () => {
|
||||
const statusSurfaceIds = new Set(
|
||||
surfaceContractRegistry
|
||||
.filter((entry) => entry.surfaces.includes("status"))
|
||||
.map((entry) => entry.id),
|
||||
);
|
||||
for (const entry of statusContractRegistry) {
|
||||
expect(statusSurfaceIds.has(entry.id)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -57,6 +57,33 @@ type StatusContractEntry = {
|
||||
}>;
|
||||
};
|
||||
|
||||
export type ChannelPluginSurface =
|
||||
| "actions"
|
||||
| "setup"
|
||||
| "status"
|
||||
| "outbound"
|
||||
| "messaging"
|
||||
| "threading"
|
||||
| "directory"
|
||||
| "gateway";
|
||||
|
||||
type SurfaceContractEntry = {
|
||||
id: string;
|
||||
plugin: Pick<
|
||||
ChannelPlugin,
|
||||
| "id"
|
||||
| "actions"
|
||||
| "setup"
|
||||
| "status"
|
||||
| "outbound"
|
||||
| "messaging"
|
||||
| "threading"
|
||||
| "directory"
|
||||
| "gateway"
|
||||
>;
|
||||
surfaces: readonly ChannelPluginSurface[];
|
||||
};
|
||||
|
||||
const telegramListActionsMock = vi.fn();
|
||||
const telegramGetCapabilitiesMock = vi.fn();
|
||||
const discordListActionsMock = vi.fn();
|
||||
@@ -461,3 +488,187 @@ export const statusContractRegistry: StatusContractEntry[] = [
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const surfaceContractRegistry: SurfaceContractEntry[] = [
|
||||
{
|
||||
id: "bluebubbles",
|
||||
plugin: bluebubblesPlugin,
|
||||
surfaces: ["actions", "setup", "status", "outbound", "messaging", "threading", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "discord",
|
||||
plugin: discordPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "feishu",
|
||||
plugin: feishuPlugin,
|
||||
surfaces: ["actions", "setup", "status", "outbound", "messaging", "directory", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "googlechat",
|
||||
plugin: googlechatPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "imessage",
|
||||
plugin: imessagePlugin,
|
||||
surfaces: ["setup", "status", "outbound", "messaging", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "irc",
|
||||
plugin: ircPlugin,
|
||||
surfaces: ["setup", "status", "outbound", "messaging", "directory", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "line",
|
||||
plugin: linePlugin,
|
||||
surfaces: ["setup", "status", "outbound", "messaging", "directory", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "matrix",
|
||||
plugin: matrixPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "mattermost",
|
||||
plugin: mattermostPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "msteams",
|
||||
plugin: msteamsPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "nextcloud-talk",
|
||||
plugin: nextcloudTalkPlugin,
|
||||
surfaces: ["setup", "status", "outbound", "messaging", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "nostr",
|
||||
plugin: nostrPlugin,
|
||||
surfaces: ["setup", "status", "outbound", "messaging", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "signal",
|
||||
plugin: signalPlugin,
|
||||
surfaces: ["actions", "setup", "status", "outbound", "messaging", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "slack",
|
||||
plugin: slackPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "synology-chat",
|
||||
plugin: synologyChatPlugin,
|
||||
surfaces: ["setup", "outbound", "messaging", "directory", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "telegram",
|
||||
plugin: telegramPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "tlon",
|
||||
plugin: tlonPlugin,
|
||||
surfaces: ["setup", "status", "outbound", "messaging", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "whatsapp",
|
||||
plugin: whatsappPlugin,
|
||||
surfaces: ["actions", "setup", "status", "outbound", "messaging", "directory", "gateway"],
|
||||
},
|
||||
{
|
||||
id: "zalo",
|
||||
plugin: zaloPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "zalouser",
|
||||
plugin: zalouserPlugin,
|
||||
surfaces: [
|
||||
"actions",
|
||||
"setup",
|
||||
"status",
|
||||
"outbound",
|
||||
"messaging",
|
||||
"threading",
|
||||
"directory",
|
||||
"gateway",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
14
src/channels/plugins/contracts/surface.contract.test.ts
Normal file
14
src/channels/plugins/contracts/surface.contract.test.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { describe } from "vitest";
|
||||
import { surfaceContractRegistry } from "./registry.js";
|
||||
import { installChannelSurfaceContractSuite } from "./suites.js";
|
||||
|
||||
for (const entry of surfaceContractRegistry) {
|
||||
for (const surface of entry.surfaces) {
|
||||
describe(`${entry.id} ${surface} surface contract`, () => {
|
||||
installChannelSurfaceContractSuite({
|
||||
plugin: entry.plugin,
|
||||
surface,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user