Files
openwork/apps/app/tests/connect-capability-inventory.test.ts

439 lines
14 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { createDenClient } from "../src/app/lib/den";
import {
listAssignedConnectCapabilities,
} from "../src/react-app/domains/session/surface/connect-capability-inventory";
describe("assigned OpenWork Connect capability inventory", () => {
test("keeps assigned Workflows returned by Den", async () => {
const originalFetch = globalThis.fetch;
const fetchMock: typeof fetch = async () => new Response(JSON.stringify({
items: [{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "script_1",
objectType: "workflow",
}],
}), {
headers: { "Content-Type": "application/json" },
status: 200,
});
Object.defineProperty(globalThis, "fetch", { configurable: true, value: fetchMock });
try {
const capabilities = await createDenClient({ baseUrl: "http://den.local", token: "token" })
.listAssignedMarketplaceCapabilities("organization_1");
expect(capabilities).toEqual([{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "script_1",
objectType: "workflow",
}]);
} finally {
Object.defineProperty(globalThis, "fetch", { configurable: true, value: originalFetch });
}
});
test("normalizes legacy script inventory objects to Workflows", async () => {
const originalFetch = globalThis.fetch;
const fetchMock: typeof fetch = async () => new Response(JSON.stringify({
items: [{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "script_1",
objectType: "script",
}],
}), {
headers: { "Content-Type": "application/json" },
status: 200,
});
Object.defineProperty(globalThis, "fetch", { configurable: true, value: fetchMock });
try {
const capabilities = await createDenClient({ baseUrl: "http://den.local", token: "token" })
.listAssignedMarketplaceCapabilities("organization_1");
expect(capabilities).toEqual([{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "script_1",
objectType: "workflow",
}]);
} finally {
Object.defineProperty(globalThis, "fetch", { configurable: true, value: originalFetch });
}
});
test("returns active marketplace skills and MCPs with Connect provenance", async () => {
const inventory = await listAssignedConnectCapabilities({
organizationId: "org_1",
client: {
listAssignedMarketplaceCapabilities: async () => [
{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "skill_1",
objectType: "skill",
},
{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "mcp_1",
objectType: "mcp",
},
],
listOrgMarketplaces: async () => [
{
id: "marketplace_1",
name: "Team tools",
description: null,
status: "active",
pluginCount: 1,
updatedAt: null,
},
],
getOrgMarketplaceResolved: async () => ({
marketplace: {
id: "marketplace_1",
name: "Team tools",
description: null,
status: "active",
pluginCount: 1,
updatedAt: null,
},
plugins: [
{
id: "plugin_1",
name: "Support kit",
description: null,
status: "active",
memberCount: 2,
updatedAt: null,
componentCounts: { skill: 1, mcp: 1 },
cloudReadiness: {
state: "ready",
hasInstructional: true,
connections: [
{
id: "connection_1",
name: "Support search",
url: "https://support.example.test/mcp",
configObjectId: "mcp_1",
serverName: "support",
credentialMode: "shared",
connectedForMe: true,
},
],
},
},
],
}),
getOrgPluginResolved: async (_organizationId, plugin) => ({
plugin,
memberships: [
{
id: "membership_skill",
pluginId: plugin.id,
configObjectId: "skill_1",
configObject: {
id: "skill_1",
objectType: "skill",
title: "Escalate ticket",
description: "Prepare a support escalation.",
currentFileName: "SKILL.md",
currentFileExtension: "md",
currentRelativePath: "skills/escalate-ticket/SKILL.md",
status: "active",
updatedAt: null,
latestVersion: {
id: "version_skill",
rawSourceText: "# Escalate ticket",
normalizedPayloadJson: null,
sourceRevisionRef: null,
createdAt: null,
},
},
},
{
id: "membership_mcp",
pluginId: plugin.id,
configObjectId: "mcp_1",
configObject: {
id: "mcp_1",
objectType: "mcp",
title: "Support MCP",
description: null,
currentFileName: "support.json",
currentFileExtension: "json",
currentRelativePath: "mcp/support.json",
status: "active",
updatedAt: null,
latestVersion: {
id: "version_mcp",
rawSourceText: null,
normalizedPayloadJson: {
mcpServers: {
support: {
url: "https://support.example.test/mcp",
headers: { Authorization: "Bearer ${SUPPORT_TOKEN}" },
},
},
},
sourceRevisionRef: null,
createdAt: null,
},
},
},
],
}),
},
});
expect(inventory.skills).toEqual([
expect.objectContaining({
name: "Escalate ticket",
trigger: "escalate-ticket",
origin: "openwork-connect",
marketplaceName: "Team tools",
pluginName: "Support kit",
connectCapabilityName: "plugin:plugin_1:skill_1",
}),
]);
expect(inventory.mcpServers).toEqual([
expect.objectContaining({
name: "Support MCP",
origin: "openwork-connect",
marketplaceName: "Team tools",
pluginName: "Support kit",
config: {
type: "remote",
url: "https://support.example.test/mcp",
},
}),
]);
expect(inventory.mcpStatuses[inventory.mcpServers[0]?.id ?? ""]).toEqual({ status: "connected" });
expect(inventory.plugins).toEqual([
expect.objectContaining({
pluginId: "plugin_1",
name: "Support kit",
marketplaceName: "Team tools",
}),
]);
expect(inventory.plugins[0]?.files.map((file) => file.objectType)).toEqual(["skill", "mcp"]);
});
test("only uses marketplaces visible to the member and ignores inactive objects", async () => {
let resolvedMarketplaceIds: string[] = [];
const inventory = await listAssignedConnectCapabilities({
organizationId: "org_1",
client: {
listAssignedMarketplaceCapabilities: async () => [
{
marketplaceId: "marketplace_active",
pluginId: "plugin_1",
configObjectId: "skill_inactive",
objectType: "skill",
},
],
listOrgMarketplaces: async () => [
{
id: "marketplace_active",
name: "Assigned",
description: null,
status: "active",
pluginCount: 1,
updatedAt: null,
},
{
id: "marketplace_archived",
name: "Archived",
description: null,
status: "archived",
pluginCount: 1,
updatedAt: null,
},
],
getOrgMarketplaceResolved: async (_organizationId, marketplaceId) => {
resolvedMarketplaceIds.push(marketplaceId);
return {
marketplace: {
id: marketplaceId,
name: "Assigned",
description: null,
status: "active",
pluginCount: 1,
updatedAt: null,
},
plugins: [
{
id: "plugin_1",
name: "Assigned plugin",
description: null,
status: "active",
memberCount: 1,
updatedAt: null,
componentCounts: { skill: 1 },
},
],
};
},
getOrgPluginResolved: async (_organizationId, plugin) => ({
plugin,
memberships: [
{
id: "membership_1",
pluginId: plugin.id,
configObjectId: "skill_inactive",
configObject: {
id: "skill_inactive",
objectType: "skill",
title: "Old skill",
description: null,
currentFileName: null,
currentFileExtension: null,
currentRelativePath: null,
status: "archived",
updatedAt: null,
latestVersion: null,
},
},
],
}),
},
});
expect(resolvedMarketplaceIds).toEqual(["marketplace_active"]);
expect(inventory.skills).toEqual([]);
expect(inventory.mcpServers).toEqual([]);
});
test("derives the trigger from Windows-style skill paths and omits it when the path is not a SKILL.md", async () => {
const marketplace = {
id: "marketplace_1",
name: "Team tools",
description: null,
status: "active" as const,
pluginCount: 1,
updatedAt: null,
};
const makeSkill = (id: string, title: string, currentRelativePath: string | null) => ({
id: `membership_${id}`,
pluginId: "plugin_1",
configObjectId: id,
configObject: {
id,
objectType: "skill" as const,
title,
description: null,
currentFileName: null,
currentFileExtension: null,
currentRelativePath,
status: "active" as const,
updatedAt: null,
latestVersion: null,
},
});
const inventory = await listAssignedConnectCapabilities({
organizationId: "org_1",
client: {
listAssignedMarketplaceCapabilities: async () => [
{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "skill_win",
objectType: "skill",
},
{
marketplaceId: "marketplace_1",
pluginId: "plugin_1",
configObjectId: "skill_nomatch",
objectType: "skill",
},
],
listOrgMarketplaces: async () => [marketplace],
getOrgMarketplaceResolved: async () => ({
marketplace,
plugins: [
{
id: "plugin_1",
name: "Support kit",
description: null,
status: "active",
memberCount: 2,
updatedAt: null,
componentCounts: { skill: 2 },
},
],
}),
getOrgPluginResolved: async (_organizationId, plugin) => ({
plugin,
memberships: [
makeSkill("skill_win", "Windows skill", "skills\\escalate-ticket\\SKILL.md"),
makeSkill("skill_nomatch", "Loose skill", "docs/escalate-ticket/README.md"),
],
}),
},
});
const byName = Object.fromEntries(inventory.skills.map((skill) => [skill.name, skill]));
expect(byName["Windows skill"]?.trigger).toBe("escalate-ticket");
expect(byName["Loose skill"]?.trigger).toBeUndefined();
});
test("includes plugins from My Library even when no marketplace is assigned", async () => {
const inventory = await listAssignedConnectCapabilities({
organizationId: "org_1",
client: {
listAssignedMarketplaceCapabilities: async () => [],
listMeLibraryPlugins: async () => [
{ id: "plugin_mine", name: "Briefing kit", description: "My plugin" },
],
listOrgMarketplaces: async () => [],
getOrgMarketplaceResolved: async () => {
throw new Error("marketplace resolve should not run");
},
getOrgPluginResolved: async (_organizationId, plugin) => ({
plugin,
memberships: [
{
id: "membership_skill",
pluginId: plugin.id,
configObjectId: "skill_mine",
configObject: {
id: "skill_mine",
objectType: "skill",
title: "Customer briefing",
description: null,
currentFileName: "SKILL.md",
currentFileExtension: "md",
currentRelativePath: "skills/customer-briefing/SKILL.md",
status: "active",
updatedAt: null,
latestVersion: {
id: "version_skill",
rawSourceText: "# Brief",
normalizedPayloadJson: null,
sourceRevisionRef: null,
createdAt: null,
},
},
},
],
}),
},
});
expect(inventory.plugins).toEqual([
expect.objectContaining({
pluginId: "plugin_mine",
name: "Briefing kit",
marketplaceName: "Library",
}),
]);
expect(inventory.skills.map((skill) => skill.name)).toEqual(["Customer briefing"]);
});
});