Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Integrations are a directory of connectors, for a workspace and for each person | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import { connectorsFor } from "@g1t/contracts/connectors"; | |
| 5 | ||
| 6 | import { | |
| 7 | arrange, | |
| 8 | askHref, | |
| 9 | categoriesWith, | |
| 10 | categoryCounts, | |
| 11 | categoryFilter, | |
| 12 | groupByCategory, | |
| 13 | matchesQuery, | |
| 14 | monogram, | |
| 15 | tileColor, | |
| 16 | } from "./connectors.ts"; | |
| 17 | ||
| 18 | const workspace = connectorsFor("workspace"); | |
| 19 | const personal = connectorsFor("personal"); | |
| 20 | const none = new Set<string>(); | |
| 21 | ||
| 22 | test("the two contexts list different connectors", () => { | |
| 23 | const ids = (views: typeof workspace) => new Set(views.map((view) => view.id)); | |
| 24 | assert.ok(ids(personal).has("google-calendar")); | |
| 25 | assert.ok(!ids(workspace).has("google-calendar"), "a calendar is your own"); | |
| 26 | assert.ok(ids(workspace).has("sentry")); | |
| 27 | assert.ok(!ids(personal).has("sentry"), "alerts are the workspace's"); | |
| 28 | assert.ok(ids(workspace).has("github") && ids(personal).has("github"), "GitHub is both"); | |
| 29 | }); | |
| 30 | ||
| 31 | test("a category shows only its own connectors, sorted into connected, available and soon", () => { | |
| 32 | const found = arrange(workspace, { category: "monitoring", query: "", connected: new Set(["sentry"]) }); | |
| 33 | assert.deepEqual(found.connected.map((view) => view.id), ["sentry"]); | |
| 34 | assert.ok(found.available.some((view) => view.id === "datadog")); | |
| 35 | assert.ok(!found.available.some((view) => view.id === "sentry"), "connected is not also available"); | |
| 36 | assert.ok(found.soon.some((view) => view.id === "pagerduty")); | |
| 37 | for (const view of [...found.connected, ...found.available, ...found.soon]) assert.equal(view.category, "monitoring"); | |
| 38 | }); | |
| 39 | ||
| 40 | test("all shows everything once", () => { | |
| 41 | const found = arrange(workspace, { category: "all", query: "", connected: none }); | |
| 42 | assert.equal(found.available.length + found.soon.length, workspace.length); | |
| 43 | }); | |
| 44 | ||
| 45 | test("search finds by name, description, tag and keyword, across every category", () => { | |
| 46 | const found = arrange(workspace, { category: "design", query: "sentry", connected: none }); | |
| The Integrations directory shows each tool's own mark, and only what g1t sets up end to end can be set up: cards draw the brand's icon from Simple Icons where it has one (GitHub, Linear, Jira, Sentry, Datadog, Anthropic, Gemini and some sixty more), in the brand's colour washed toward the text colour, and in the text colour itself when the brand's is black or nearly (GitHub, Notion, Vercel), so each reads in the dark theme and the light one; outgoing webhooks take the webhook mark, and the rest keep their letters, which now count letters and digits alone, so "GitHub (MCP)" is GM and no longer "G(". The search's magnifying glass no longer sits on the placeholder: the field is the input group used elsewhere, with the icon as its addon (the older Input it used dropped the padding it was given). Every connector backed only by an MCP server (GitHub (MCP), Linear (MCP), Notion, Atlassian, Sentry (MCP), Cloudflare, Vercel, Stripe, Figma and the rest) is Soon, since Customize, where they were connected, went with the hosted agents and their Set up led nowhere; they sort after what works, with Ask for this in place of Set up, and the rail cannot pin them. Available stays GitHub, webhooks, Linear, Jira, Sentry, Datadog, the alerts webhook and the AI providers for a workspace, and GitHub sign-in and MCP clients for you, as the docs' Available today already said; a test holds the catalog to that list. | 47 | assert.deepEqual(found.available.map((view) => view.id), ["sentry"], "a search is not held to the category"); |
| 48 | assert.deepEqual(found.soon.map((view) => view.id), ["sentry-mcp"], "what is coming sorts after what works"); | |
| Integrations are a directory of connectors, for a workspace and for each person | 49 | assert.ok(matchesQuery(personal.find((view) => view.id === "google-calendar")!, "in a meeting")); |
| 50 | assert.ok(matchesQuery(workspace.find((view) => view.id === "anthropic")!, "claude")); | |
| 51 | assert.ok(matchesQuery(workspace.find((view) => view.id === "incident-io")!, "incidentio")); | |
| 52 | assert.ok(matchesQuery(workspace.find((view) => view.id === "pagerduty")!, "opens ISSUES")); | |
| 53 | assert.ok(!matchesQuery(workspace.find((view) => view.id === "figma")!, "kubernetes")); | |
| 54 | }); | |
| 55 | ||
| 56 | test("the navigation counts each category and leaves out empty ones", () => { | |
| 57 | const counts = categoryCounts(workspace); | |
| 58 | assert.equal(counts.all, workspace.length); | |
| 59 | assert.ok(counts.ai >= 14); | |
| 60 | const mine = categoriesWith(personal).map((category) => category.id); | |
| 61 | assert.ok(mine.includes("calendar")); | |
| 62 | const groups = groupByCategory(personal); | |
| 63 | assert.equal(groups.reduce((sum, group) => sum + group.views.length, 0), personal.length); | |
| 64 | }); | |
| 65 | ||
| 66 | test("an unknown category is all of them", () => { | |
| 67 | assert.equal(categoryFilter("ai"), "ai"); | |
| 68 | assert.equal(categoryFilter("nope"), "all"); | |
| 69 | assert.equal(categoryFilter(null), "all"); | |
| 70 | }); | |
| 71 | ||
| 72 | test("a tile has the connector's letters and a steady colour", () => { | |
| 73 | assert.equal(monogram("PagerDuty"), "PD"); | |
| 74 | assert.equal(monogram("Google Calendar"), "GC"); | |
| 75 | assert.equal(monogram("Sentry"), "S"); | |
| 76 | assert.equal(monogram("incident.io"), "II"); | |
| 77 | assert.equal(monogram("1Password"), "1P"); | |
| The Integrations directory shows each tool's own mark, and only what g1t sets up end to end can be set up: cards draw the brand's icon from Simple Icons where it has one (GitHub, Linear, Jira, Sentry, Datadog, Anthropic, Gemini and some sixty more), in the brand's colour washed toward the text colour, and in the text colour itself when the brand's is black or nearly (GitHub, Notion, Vercel), so each reads in the dark theme and the light one; outgoing webhooks take the webhook mark, and the rest keep their letters, which now count letters and digits alone, so "GitHub (MCP)" is GM and no longer "G(". The search's magnifying glass no longer sits on the placeholder: the field is the input group used elsewhere, with the icon as its addon (the older Input it used dropped the padding it was given). Every connector backed only by an MCP server (GitHub (MCP), Linear (MCP), Notion, Atlassian, Sentry (MCP), Cloudflare, Vercel, Stripe, Figma and the rest) is Soon, since Customize, where they were connected, went with the hosted agents and their Set up led nowhere; they sort after what works, with Ask for this in place of Set up, and the rail cannot pin them. Available stays GitHub, webhooks, Linear, Jira, Sentry, Datadog, the alerts webhook and the AI providers for a workspace, and GitHub sign-in and MCP clients for you, as the docs' Available today already said; a test holds the catalog to that list. | 78 | assert.equal(monogram("GitHub (MCP)"), "GM", "punctuation is not a letter"); |
| 79 | assert.equal(monogram("Linear (MCP)"), "LM"); | |
| 80 | assert.equal(monogram("Atlassian (Jira and Confluence)"), "AJ"); | |
| Integrations are a directory of connectors, for a workspace and for each person | 81 | assert.equal(tileColor("figma"), tileColor("figma")); |
| 82 | }); | |
| 83 | ||
| 84 | test("asking for a connector names it and who it is for", () => { | |
| 85 | const href = askHref({ connector: { id: "slack", name: "Slack" }, scope: "workspace", workspace: "acme", address: "hey@example.com" }); | |
| 86 | assert.ok(href.startsWith("mailto:hey@example.com?subject=Integration%20request%3A%20Slack")); | |
| 87 | assert.ok(decodeURIComponent(href).includes("For the workspace: acme")); | |
| 88 | const mine = askHref({ connector: { id: "google-calendar", name: "Google Calendar" }, scope: "personal", workspace: null, address: "hey@example.com" }); | |
| 89 | assert.ok(decodeURIComponent(mine).includes("For my own account.")); | |
| 90 | }); |