Skip to content

Commit ee62bac

Browse files
committed
Make integrations instructions clickable
1 parent 9501c56 commit ee62bac

7 files changed

Lines changed: 323 additions & 27 deletions

File tree

web/app/(console)/integrations/page-content.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ import { readFileSync } from "node:fs";
33
const source = readFileSync("app/(console)/integrations/page.tsx", "utf8");
44

55
assertIncludes("integrations page exposes native Stint CLI recipe", source, "bin/stint config init");
6+
assertIncludes("integrations page makes integration cards selectable", source, "setSelectedIntegration");
7+
assertIncludes("integrations page exposes selected instructions region", source, "integration-instructions");
8+
assertIncludes("integrations page documents WakaTime CLI recipe", source, "wakatime-cli --entity");
9+
assertIncludes("integrations page documents WakaTime CLI offline sync", source, "wakatime-cli --sync-offline-activity");
10+
assertIncludes("integrations page documents Codex recipe", source, "bin/stint --sync-ai-activity --agent codex");
11+
assertIncludes("integrations page documents Codex heartbeat recipe", source, "--ai-agent codex");
12+
assertIncludes("integrations page documents model-aware ingestion recipe", source, "model-aware-ingestion-config");
13+
assertIncludes("integrations page documents model-aware token fields", source, "ai_input_tokens");
14+
assertIncludes("integrations page documents model-aware structured metadata", source, '"metadata": { "source": "custom-client" }');
15+
assertIncludes("integrations page documents integration catalog recipe", source, "integration-catalog-config");
16+
assertIncludes("integrations page makes roadmap items selectable", source, "setSelectedIntegration(item.recipeId)");
617
assertIncludes("integrations page documents api-keys command", source, "bin/stint api-keys");
718
assertIncludes("integrations page documents api-keys create command", source, 'bin/stint api-keys create "Editor key" --scope write_heartbeats --scope read_stats');
819
assertIncludes("integrations page documents api-keys delete command", source, "bin/stint api-keys delete API_KEY_ID");

web/app/(console)/integrations/page.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ assert.match(source, /Create integration key/);
1818
assert.match(source, /setLatestKey/);
1919
assert.match(source, /copyText/);
2020
assert.match(source, /Copy config/);
21+
assert.match(source, /selectedIntegration/);
22+
assert.match(source, /setSelectedIntegration/);
23+
assert.match(source, /aria-pressed/);
24+
assert.match(source, /integration-instructions/);
2125
assert.match(source, /VS Code/);
2226
assert.match(source, /JetBrains/);
2327
assert.match(source, /Vim\/Neovim/);

web/app/(console)/integrations/page.tsx

Lines changed: 167 additions & 26 deletions
Large diffs are not rendered by default.

web/e2e/integrations.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
const recipes = [
4+
{ name: "Stint CLI", expected: "bin/stint config init" },
5+
{ name: "WakaTime CLI", expected: "wakatime-cli --entity" },
6+
{ name: "Codex", expected: "bin/stint --sync-ai-activity --agent codex" },
7+
{ name: "VS Code", expected: "Install the WakaTime extension from the VS Code Marketplace." },
8+
{ name: "JetBrains", expected: "Install the WakaTime plugin from JetBrains Marketplace." },
9+
{ name: "Vim/Neovim", expected: "Install vim-wakatime for Vim or Neovim." },
10+
{ name: "Shell CLI", expected: "curl -X POST" }
11+
];
12+
13+
const roadmapRecipes = [
14+
{ name: "Model-aware ingestion", expected: "ai_input_tokens" },
15+
{ name: "Native Stint CLI", expected: "bin/stint config init" },
16+
{ name: "Integration catalog", expected: "Create integration key" }
17+
];
18+
19+
test("integration names reveal full setup instructions", async ({ page }) => {
20+
await page.route("**/api/v1/meta", async (route) => {
21+
await route.fulfill({
22+
contentType: "application/json",
23+
body: JSON.stringify({ data: { api_url: "http://127.0.0.1:3310/api/v1", base_url: "http://127.0.0.1:3310", hostname: "playwright", ip: "127.0.0.1", version: "test" } })
24+
});
25+
});
26+
await page.route("**/api/v1/api_keys", async (route) => {
27+
await route.fulfill({ contentType: "application/json", body: JSON.stringify({ data: [] }) });
28+
});
29+
await page.route("**/api/v1/editors", async (route) => {
30+
await route.fulfill({ contentType: "application/json", body: JSON.stringify({ data: [] }) });
31+
});
32+
await page.route("**/api/v1/users/current/user_agents", async (route) => {
33+
await route.fulfill({ contentType: "application/json", body: JSON.stringify({ data: [] }) });
34+
});
35+
await page.route("**/api/v1/auth/me", async (route) => {
36+
await route.fulfill({ status: 401, contentType: "application/json", body: JSON.stringify({ error: "unauthorized" }) });
37+
});
38+
39+
await page.goto("/integrations");
40+
41+
const stintCard = page.getByRole("button", { name: "Show Stint CLI integration instructions" });
42+
await expect(stintCard).toContainText("live");
43+
44+
for (const recipe of recipes) {
45+
await page.getByRole("button", { name: `Show ${recipe.name} integration instructions` }).click();
46+
await expect(page.locator("#integration-instructions")).toContainText(recipe.expected);
47+
}
48+
49+
for (const recipe of roadmapRecipes) {
50+
await page.getByRole("button", { name: `Show ${recipe.name} roadmap instructions` }).click();
51+
await expect(page.locator("#integration-instructions")).toContainText(recipe.expected);
52+
}
53+
});

web/package-lock.json

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"build": "next build",
88
"start": "next start",
99
"lint": "eslint .",
10-
"test": "tsc --noEmit -p tsconfig.test.json && node scripts/run-tests.mjs"
10+
"test": "tsc --noEmit -p tsconfig.test.json && node scripts/run-tests.mjs",
11+
"test:browser": "playwright test"
1112
},
1213
"dependencies": {
1314
"@tanstack/react-query": "^5.80.7",
@@ -18,6 +19,7 @@
1819
"recharts": "^3.9.0"
1920
},
2021
"devDependencies": {
22+
"@playwright/test": "^1.51.1",
2123
"@types/node": "^20.19.1",
2224
"@types/react": "^19.2.7",
2325
"@types/react-dom": "^19.2.3",

web/playwright.config.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { defineConfig, devices } from "@playwright/test";
2+
3+
export default defineConfig({
4+
testDir: "./e2e",
5+
timeout: 30_000,
6+
use: {
7+
baseURL: "http://127.0.0.1:3310",
8+
trace: "retain-on-failure"
9+
},
10+
webServer: {
11+
command: "npm run dev -- --hostname 127.0.0.1 --port 3310",
12+
url: "http://127.0.0.1:3310",
13+
reuseExistingServer: !process.env.CI,
14+
timeout: 60_000
15+
},
16+
projects: [
17+
{
18+
name: "chromium",
19+
use: { ...devices["Desktop Chrome"] }
20+
}
21+
]
22+
});

0 commit comments

Comments
 (0)