import { describe, expect, it } from "@effect/vitest";import { type Integration, IntegrationSlug } from "@executor-js/sdk/shared"; import { groupIntegrations, integrationFamily, type IntegrationFamilyGroup,} from "./integration-grouping"; const integration = (slug: string, kind: string, name = slug, family?: string): Integration => ({ slug: IntegrationSlug.make(slug), name, description: name, kind, canRemove: true, canRefresh: true, authMethods: [], ...(family ? { family } : {}),}); describe("groupIntegrations", () => { it("collapses multi-member config families under one umbrella", () => { const items = groupIntegrations([ integration("google_calendar", "openapi", "Google Calendar", "google"), integration("google_gmail", "openapi", "Gmail", "google"), integration("google_drive", "openapi", "Google Drive", "google"), ]); expect(items).toHaveLength(1); const group = items[0] as IntegrationFamilyGroup; expect(group.type).toBe("group"); expect(group.family).toBe("google"); expect(group.label).toBe("Google"); expect(group.members.map((m) => String(m.slug))).toEqual([ "google_calendar", "google_gmail", "google_drive", ]); }); it("groups arbitrary provider families", () => { const items = groupIntegrations([ integration("cloudflare_api", "mcp", "Cloudflare API", "cloudflare"), integration("cloudflare_docs", "mcp", "Cloudflare Docs", "cloudflare"), ]); expect(items).toHaveLength(1); const group = items[0] as IntegrationFamilyGroup; expect(group.type).toBe("group"); expect(group.family).toBe("cloudflare"); expect(group.label).toBe("Cloudflare"); }); it("leaves integrations without config family ungrouped", () => { const items = groupIntegrations([ integration("stripe", "openapi", "Stripe"), integration("sentry", "mcp", "Sentry"), ]); expect(items).toHaveLength(2); expect(items.map((item) => item.type)).toEqual(["single", "single"]); }); it("renders a lone family member flat", () => { const items = groupIntegrations([ integration("google_calendar", "openapi", "Google Calendar", "google"), ]); expect(items).toHaveLength(1); expect(items[0]?.type).toBe("single"); }); it("places each group where its first member appeared", () => { const items = groupIntegrations([ integration("stripe", "openapi", "Stripe"), integration("google_calendar", "openapi", "Google Calendar", "google"), integration("microsoft_mail", "openapi", "Outlook Mail", "microsoft"), integration("google_gmail", "openapi", "Gmail", "google"), integration("microsoft_calendar", "openapi", "Outlook Calendar", "microsoft"), integration("sentry", "mcp", "Sentry"), ]); expect( items.map((item) => (item.type === "group" ? `group:${item.family}` : "single")), ).toEqual(["single", "group:google", "group:microsoft", "single"]); }); it("does not infer a family from integration kind alone", () => { expect( integrationFamily(integration("google_calendar", "google", "Google Calendar")), ).toBeNull(); });});
import { describe, expect, it } from "@effect/vitest";
import { type Integration, IntegrationSlug } from "@executor-js/sdk/shared";
import {
groupIntegrations,
integrationFamily,
type IntegrationFamilyGroup,
} from "./integration-grouping";
const integration = (slug: string, kind: string, name = slug, family?: string): Integration => ({
slug: IntegrationSlug.make(slug),
name,
description: name,
kind,
canRemove: true,
canRefresh: true,
authMethods: [],
...(family ? { family } : {}),
});
describe("groupIntegrations", () => {
it("collapses multi-member config families under one umbrella", () => {
const items = groupIntegrations([
integration("google_calendar", "openapi", "Google Calendar", "google"),
integration("google_gmail", "openapi", "Gmail", "google"),
integration("google_drive", "openapi", "Google Drive", "google"),
]);
expect(items).toHaveLength(1);
const group = items[0] as IntegrationFamilyGroup;
expect(group.type).toBe("group");
expect(group.family).toBe("google");
expect(group.label).toBe("Google");
expect(group.members.map((m) => String(m.slug))).toEqual([
"google_calendar",
"google_gmail",
"google_drive",
]);
});
it("groups arbitrary provider families", () => {
const items = groupIntegrations([
integration("cloudflare_api", "mcp", "Cloudflare API", "cloudflare"),
integration("cloudflare_docs", "mcp", "Cloudflare Docs", "cloudflare"),
]);
expect(items).toHaveLength(1);
const group = items[0] as IntegrationFamilyGroup;
expect(group.type).toBe("group");
expect(group.family).toBe("cloudflare");
expect(group.label).toBe("Cloudflare");
});
it("leaves integrations without config family ungrouped", () => {
const items = groupIntegrations([
integration("stripe", "openapi", "Stripe"),
integration("sentry", "mcp", "Sentry"),
]);
expect(items).toHaveLength(2);
expect(items.map((item) => item.type)).toEqual(["single", "single"]);
});
it("renders a lone family member flat", () => {
const items = groupIntegrations([
integration("google_calendar", "openapi", "Google Calendar", "google"),
]);
expect(items).toHaveLength(1);
expect(items[0]?.type).toBe("single");
});
it("places each group where its first member appeared", () => {
const items = groupIntegrations([
integration("stripe", "openapi", "Stripe"),
integration("google_calendar", "openapi", "Google Calendar", "google"),
integration("microsoft_mail", "openapi", "Outlook Mail", "microsoft"),
integration("google_gmail", "openapi", "Gmail", "google"),
integration("microsoft_calendar", "openapi", "Outlook Calendar", "microsoft"),
integration("sentry", "mcp", "Sentry"),
]);
expect(
items.map((item) => (item.type === "group" ? `group:${item.family}` : "single")),
).toEqual(["single", "group:google", "group:microsoft", "single"]);
});
it("does not infer a family from integration kind alone", () => {
expect(
integrationFamily(integration("google_calendar", "google", "Google Calendar")),
).toBeNull();
});
});