Skip to content

Commit c062e19

Browse files
committed
Add e2e tests for cloudflare service (basic)
1 parent 6097301 commit c062e19

File tree

11 files changed

+377
-5
lines changed

11 files changed

+377
-5
lines changed

.github/workflows/e2e.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: E2E Tests
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'packages/mcp-server/**'
7+
- 'packages/mcp-cloudflare/**'
8+
- 'packages/e2e/**'
9+
push:
10+
branches: [main]
11+
paths:
12+
- 'packages/mcp-server/**'
13+
- 'packages/mcp-cloudflare/**'
14+
- 'packages/e2e/**'
15+
16+
jobs:
17+
e2e:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Setup Node.js
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: "20"
26+
27+
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda
28+
name: Install pnpm
29+
with:
30+
run_install: false
31+
32+
- name: Get pnpm store directory
33+
shell: bash
34+
run: |
35+
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
36+
37+
- uses: actions/cache@v4
38+
name: Setup pnpm cache
39+
with:
40+
path: ${{ env.STORE_PATH }}
41+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
42+
restore-keys: |
43+
${{ runner.os }}-pnpm-store-
44+
45+
- name: Install dependencies
46+
run: pnpm install --no-frozen-lockfile
47+
48+
- name: Install Playwright Browsers
49+
run: pnpm --filter=@sentry/mcp-cloudflare-e2e install:browsers
50+
51+
- name: Build packages
52+
run: pnpm build
53+
54+
- name: Run E2E tests
55+
run: pnpm test:e2e
56+
57+
- uses: actions/upload-artifact@v4
58+
if: always()
59+
with:
60+
name: playwright-report
61+
path: packages/e2e/playwright-report/
62+
retention-days: 30

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,8 @@ coverage
6060

6161
# Sentry Config File
6262
.env.sentry-build-plugin
63+
64+
# Playwright
65+
playwright-report/
66+
test-results/
67+
playwright/.cache/

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
"start:client": "pnpm run --filter ./packages/mcp-test-client start",
3434
"start:stdio": "pnpm --stream run --filter ./packages/mcp-server start",
3535
"test": "dotenv -e .env -e .env.local -- turbo test",
36-
"test:ci": "CI=true dotenv -e .env -e .env.local -- pnpm --stream -r run test:ci"
36+
"test:ci": "CI=true dotenv -e .env -e .env.local -- pnpm --stream -r run test:ci",
37+
"test:e2e": "pnpm --filter @sentry/mcp-cloudflare-e2e exec playwright test",
38+
"test:e2e:ui": "pnpm --filter @sentry/mcp-cloudflare-e2e test:ui"
3739
},
3840
"dependencies": {
3941
"@biomejs/biome": "^1.9.4",

packages/mcp-cloudflare-e2e/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# @sentry/mcp-cloudflare-e2e
2+
3+
Simple end-to-end tests for the Sentry MCP Cloudflare client.
4+
5+
## Running Tests
6+
7+
```bash
8+
# Run all tests
9+
pnpm test
10+
11+
# Run tests in UI mode
12+
pnpm test:ui
13+
14+
# Run tests in headed mode
15+
pnpm test:headed
16+
17+
# Debug tests
18+
pnpm test:debug
19+
```
20+
21+
## Running from Root
22+
23+
From the project root:
24+
25+
```bash
26+
# Run all e2e tests
27+
pnpm test:e2e
28+
29+
# Open UI mode
30+
pnpm test:e2e:ui
31+
```
32+
33+
## Test Scope
34+
35+
These tests focus on high-level functionality without requiring authentication:
36+
37+
- **Page Loading** - Verifies the application loads without errors
38+
- **Basic Structure** - Checks essential HTML elements exist
39+
- **Responsiveness** - Tests mobile and desktop viewports
40+
- **Meta Tags** - Validates proper HTML meta configuration
41+
- **Title** - Confirms correct page title
42+
43+
## Why Simple Tests?
44+
45+
We intentionally keep these tests simple because:
46+
- OAuth authentication is complex to mock in e2e tests
47+
- Chat functionality requires real Sentry API integration
48+
- Simple tests are more reliable and faster to run
49+
- They catch major regressions without test flakiness
50+
51+
## Configuration
52+
53+
Tests run against:
54+
- Desktop Chrome
55+
- Mobile Safari
56+
57+
The dev server automatically starts on port 5173 before tests run.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@sentry/mcp-cloudflare-e2e",
3+
"version": "0.12.0",
4+
"private": true,
5+
"description": "End-to-end tests for Sentry MCP",
6+
"scripts": {
7+
"test": "playwright test",
8+
"test:headed": "playwright test --headed",
9+
"test:ui": "playwright test --ui",
10+
"test:debug": "playwright test --debug",
11+
"show-report": "playwright show-report",
12+
"install:browsers": "playwright install --with-deps"
13+
},
14+
"devDependencies": {
15+
"@playwright/test": "^1.43.0",
16+
"typescript": "^5.4.5"
17+
}
18+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { defineConfig, devices } from "@playwright/test";
2+
3+
/**
4+
* See https://playwright.dev/docs/test-configuration.
5+
*/
6+
export default defineConfig({
7+
testDir: "./tests",
8+
/* Run tests in files in parallel */
9+
fullyParallel: true,
10+
/* Fail the build on CI if you accidentally left test.only in the source code. */
11+
forbidOnly: !!process.env.CI,
12+
/* Retry on CI only */
13+
retries: process.env.CI ? 2 : 0,
14+
/* Opt out of parallel tests on CI. */
15+
workers: process.env.CI ? 1 : undefined,
16+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
17+
reporter: "html",
18+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
19+
use: {
20+
/* Base URL to use in actions like `await page.goto('/')`. */
21+
baseURL: "http://localhost:5173",
22+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
23+
trace: "on-first-retry",
24+
/* Screenshot on failure */
25+
screenshot: "only-on-failure",
26+
},
27+
28+
/* Configure projects for major browsers */
29+
projects: [
30+
{
31+
name: "Desktop Chrome",
32+
use: { ...devices["Desktop Chrome"] },
33+
},
34+
35+
/* Test against mobile viewports. */
36+
{
37+
name: "Mobile Safari",
38+
use: { ...devices["iPhone 12"] },
39+
},
40+
],
41+
42+
/* Run your local dev server before starting the tests */
43+
webServer: {
44+
command: "pnpm --filter @sentry/mcp-cloudflare dev",
45+
url: "http://localhost:5173",
46+
reuseExistingServer: !process.env.CI,
47+
timeout: 120 * 1000,
48+
},
49+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { test, expect } from "@playwright/test";
2+
3+
test.describe("Simple Application Tests", () => {
4+
test("should load without errors", async ({ page }) => {
5+
await page.goto("/");
6+
7+
// Just check that the page loads without throwing errors
8+
await page.waitForLoadState("networkidle");
9+
10+
// Verify we're on the right page by checking URL
11+
expect(page.url()).toContain("/");
12+
});
13+
14+
test("should have correct title", async ({ page }) => {
15+
await page.goto("/");
16+
17+
// Check page title contains expected text
18+
await expect(page).toHaveTitle(/Sentry MCP/);
19+
});
20+
21+
test("should have basic HTML structure", async ({ page }) => {
22+
await page.goto("/");
23+
24+
// Check basic HTML elements exist (using first() to avoid duplicates)
25+
await expect(page.locator("html")).toBeVisible();
26+
await expect(page.locator("body")).toBeVisible();
27+
await expect(page.locator("#root")).toBeVisible();
28+
});
29+
30+
test("should be responsive", async ({ page }) => {
31+
// Test mobile size
32+
await page.setViewportSize({ width: 375, height: 667 });
33+
await page.goto("/");
34+
await page.waitForLoadState("networkidle");
35+
36+
// Just verify page loads on mobile
37+
await expect(page.locator("body")).toBeVisible();
38+
39+
// Test desktop size
40+
await page.setViewportSize({ width: 1280, height: 720 });
41+
await page.reload();
42+
await page.waitForLoadState("networkidle");
43+
44+
// Just verify page loads on desktop
45+
await expect(page.locator("body")).toBeVisible();
46+
});
47+
48+
test("should have proper meta tags", async ({ page }) => {
49+
await page.goto("/");
50+
51+
// Check viewport meta tag exists
52+
const viewport = page.locator('meta[name="viewport"]');
53+
await expect(viewport).toHaveCount(1);
54+
55+
// Check charset meta tag exists
56+
const charset = page.locator("meta[charset]");
57+
await expect(charset).toHaveCount(1);
58+
});
59+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env node
2+
3+
import fs from "node:fs";
4+
import path from "node:path";
5+
import { fileURLToPath } from "node:url";
6+
import { readFileSync } from "node:fs";
7+
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = path.dirname(__filename);
10+
11+
console.log("Verifying Playwright E2E test setup...\n");
12+
13+
// Check if package.json has Playwright
14+
const packageJson = JSON.parse(
15+
readFileSync(path.join(__dirname, "..", "package.json"), "utf8"),
16+
);
17+
const hasPlaywright =
18+
packageJson.devDependencies["@playwright/test"] &&
19+
packageJson.devDependencies.playwright;
20+
console.log(`✓ Playwright in package.json: ${hasPlaywright ? "Yes" : "No"}`);
21+
22+
// Check test scripts
23+
const hasTestScripts =
24+
packageJson.scripts["test:e2e"] && packageJson.scripts["test:e2e:ui"];
25+
console.log(`✓ Test scripts configured: ${hasTestScripts ? "Yes" : "No"}`);
26+
27+
// Check directory structure
28+
const dirs = ["fixtures", "tests", "utils"];
29+
for (const dir of dirs) {
30+
const exists = fs.existsSync(path.join(__dirname, dir));
31+
console.log(`✓ Directory e2e/${dir}: ${exists ? "Exists" : "Missing"}`);
32+
}
33+
34+
// Check test files
35+
const testFiles = [
36+
"fixtures/test-base.ts",
37+
"fixtures/auth.ts",
38+
"fixtures/chat.ts",
39+
"tests/smoke.spec.ts",
40+
"tests/auth.spec.ts",
41+
"tests/chat.spec.ts",
42+
"tests/mobile.spec.ts",
43+
"utils/mock-api.ts",
44+
];
45+
46+
console.log("\nTest files:");
47+
for (const file of testFiles) {
48+
const exists = fs.existsSync(path.join(__dirname, file));
49+
console.log(` ${exists ? "✓" : "✗"} ${file}`);
50+
}
51+
52+
// Check Playwright config
53+
const configExists = fs.existsSync(
54+
path.join(__dirname, "..", "playwright.config.ts"),
55+
);
56+
console.log(`\n✓ playwright.config.ts: ${configExists ? "Exists" : "Missing"}`);
57+
58+
// Installation status
59+
try {
60+
await import("@playwright/test");
61+
console.log("\n✓ Playwright is installed");
62+
} catch (e) {
63+
console.log("\n✗ Playwright is NOT installed. Run: pnpm install");
64+
}
65+
66+
console.log("\nSetup verification complete!");
67+
console.log("\nNext steps:");
68+
console.log("1. Run: pnpm install");
69+
console.log("2. Run: pnpm exec playwright install --with-deps");
70+
console.log("3. Run: pnpm test:e2e");

packages/mcp-cloudflare/src/client/components/ui/sliding-panel.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,25 @@ export function SlidingPanel({
4747
/>
4848

4949
{/* Panel */}
50-
<div
50+
<dialog
51+
open={isOpen}
5152
className={`fixed inset-y-0 right-0 w-full max-w-2xl bg-slate-950 border-l border-slate-800 z-50 shadow-2xl flex flex-col transition-transform duration-500 ease-in-out ${
5253
isOpen ? "translate-x-0" : "translate-x-full"
5354
} ${className}`}
5455
>
5556
{children}
56-
</div>
57+
</dialog>
5758
</div>
5859

5960
{/* Desktop: Fixed right half */}
60-
<div
61+
<dialog
62+
open={isOpen}
6163
className={`${
6264
isOpen ? "hidden md:flex" : "hidden"
6365
} fixed top-0 right-0 h-screen w-1/2 bg-slate-950 flex-col border-l border-slate-800 transition-opacity duration-300 ${className}`}
6466
>
6567
{children}
66-
</div>
68+
</dialog>
6769
</>
6870
);
6971
}

packages/mcp-cloudflare/vite.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ export default defineConfig({
2323
build: {
2424
sourcemap: true,
2525
},
26+
server: {
27+
port: 5173,
28+
strictPort: true, // Fail if port is in use
29+
},
2630
});

0 commit comments

Comments
 (0)