diff --git a/.gitignore b/.gitignore index 6ce556395..c63eadaa4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ sdk client/playwright-report/ client/results.json client/test-results/ +client/e2e/test-results/ mcp.json diff --git a/client/e2e/cli-arguments.spec.ts b/client/e2e/cli-arguments.spec.ts index a4dcdcce2..7711ea77c 100644 --- a/client/e2e/cli-arguments.spec.ts +++ b/client/e2e/cli-arguments.spec.ts @@ -1,14 +1,17 @@ import { test, expect } from "@playwright/test"; +// Adjust the URL if your dev server runs on a different port +const APP_URL = "http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=abc123"; + // These tests verify that CLI arguments correctly set URL parameters // The CLI should parse config files and pass transport/serverUrl as URL params -test.describe("CLI Arguments @cli", () => { +test.describe("CLI Arguments", () => { test("should pass transport parameter from command line", async ({ page, }) => { // Simulate: npx . --transport sse --server-url http://localhost:3000/sse await page.goto( - "http://localhost:6274/?transport=sse&serverUrl=http://localhost:3000/sse", + `${APP_URL}&transport=sse&serverUrl=http://localhost:3000/sse`, ); // Wait for the Transport Type dropdown to be visible @@ -29,7 +32,7 @@ test.describe("CLI Arguments @cli", () => { }) => { // Simulate config with streamable-http transport await page.goto( - "http://localhost:6274/?transport=streamable-http&serverUrl=http://localhost:3000/mcp", + `${APP_URL}&transport=streamable-http&serverUrl=http://localhost:3000/mcp`, ); // Wait for the Transport Type dropdown to be visible @@ -49,7 +52,7 @@ test.describe("CLI Arguments @cli", () => { page, }) => { // Simulate stdio config (no transport param needed) - await page.goto("http://localhost:6274/"); + await page.goto(APP_URL); // Wait for the Transport Type dropdown to be visible const selectTrigger = page.getByLabel("Transport Type"); @@ -63,3 +66,28 @@ test.describe("CLI Arguments @cli", () => { await expect(page.locator("#arguments-input")).toBeVisible(); }); }); + +test.describe("CLI npx (npm exec) start up", { tag: "@cli" }, () => { + test("CLI arguments should populate form fields", async ({ page }) => { + const cliTestScenario = process.env.CLI_TEST_SCENARIO; + + // Skip this test if not running a CLI test scenario + if ( + !cliTestScenario || + (cliTestScenario !== "inline" && cliTestScenario !== "file") + ) { + test.skip(); + return; + } + + await page.goto(APP_URL); + + const commandInput = page.getByRole("textbox", { name: "Command" }); + const argsInput = page.getByRole("textbox", { name: "Arguments" }); + + await expect(commandInput).toHaveValue("npm"); + await expect(argsInput).toHaveValue( + "--silent --prefix /path/to/mcp/servers/src/everything run start", + ); + }); +}); diff --git a/client/e2e/fixtures/everything-server.json b/client/e2e/fixtures/everything-server.json new file mode 100644 index 000000000..41ca3c669 --- /dev/null +++ b/client/e2e/fixtures/everything-server.json @@ -0,0 +1,18 @@ +{ + "mcpServers": { + "everything": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "/path/to/mcp/servers/src/everything", + "run", + "start" + ], + "env": { + "FOO": "bar", + "BAZ": "bat" + } + } + } +} diff --git a/client/e2e/startup-state.spec.ts b/client/e2e/startup-state.spec.ts index 414ebd3e6..e5e10b674 100644 --- a/client/e2e/startup-state.spec.ts +++ b/client/e2e/startup-state.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from "@playwright/test"; // Adjust the URL if your dev server runs on a different port -const APP_URL = "http://localhost:6274/"; +const APP_URL = "http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=abc123"; test.describe("Startup State", () => { test("should not navigate to a tab when Inspector first opens", async ({ diff --git a/client/e2e/transport-type-dropdown.spec.ts b/client/e2e/transport-type-dropdown.spec.ts index e4ac8fbb4..f4e242c51 100644 --- a/client/e2e/transport-type-dropdown.spec.ts +++ b/client/e2e/transport-type-dropdown.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from "@playwright/test"; // Adjust the URL if your dev server runs on a different port -const APP_URL = "http://localhost:6274/"; +const APP_URL = "http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=abc123"; test.describe("Transport Type Dropdown", () => { test("should have options for STDIO, SSE, and Streamable HTTP", async ({ diff --git a/client/package.json b/client/package.json index d1c6d7751..d6fe85d2e 100644 --- a/client/package.json +++ b/client/package.json @@ -21,7 +21,9 @@ "preview": "vite preview --port 6274", "test": "jest --config jest.config.cjs", "test:watch": "jest --config jest.config.cjs --watch", - "test:e2e": "playwright test e2e && npm run cleanup:e2e", + "test:e2e": "playwright test --grep-invert @cli e2e && npm run test:e2e:cli-file && npm run test:e2e:cli-inline && npm run cleanup:e2e", + "test:e2e:cli-file": "CLI_TEST_SCENARIO=file playwright test --grep @cli e2e", + "test:e2e:cli-inline": "CLI_TEST_SCENARIO=inline playwright test --grep @cli e2e", "cleanup:e2e": "node e2e/global-teardown.js" }, "dependencies": { diff --git a/client/playwright.config.ts b/client/playwright.config.ts index 570dd054e..e4b50d120 100644 --- a/client/playwright.config.ts +++ b/client/playwright.config.ts @@ -1,5 +1,20 @@ import { defineConfig, devices } from "@playwright/test"; +const getWebServerCommand = () => { + /** + * The content of the fixture configuration file matches the inline arguments such + * that the same set of tests (tagged `@cli`) can run in both scenarios. + */ + switch (process.env.CLI_TEST_SCENARIO) { + case "file": + return "npx . --config client/e2e/fixtures/everything-server.json --server everything"; + case "inline": + return "npx . -e FOO=bar -e BAZ=bat npm --silent --prefix /path/to/mcp/servers/src/everything run start"; + default: + return "npm run dev"; + } +}; + /** * @see https://playwright.dev/docs/test-configuration */ @@ -7,9 +22,13 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: { cwd: "..", - command: "npm run dev", - url: "http://localhost:6274", + command: getWebServerCommand(), + url: "http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=abc123", reuseExistingServer: !process.env.CI, + env: { + MCP_AUTO_OPEN_ENABLED: "false", + MCP_PROXY_AUTH_TOKEN: "abc123", + }, }, testDir: "./e2e", @@ -22,7 +41,11 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + + /* Reporter to use. See https://playwright.dev/docs/test-reporters + * Use `--reporter [type]` to override for more information while debugging tests. + * e.g., `npx playwright test --reporter list [args]` + */ reporter: process.env.CI ? [ ["html", { outputFolder: "playwright-report" }], @@ -30,10 +53,11 @@ export default defineConfig({ ["line"], ] : [["line"]], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: "http://localhost:6274", + baseURL: "http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=abc123", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", @@ -43,6 +67,9 @@ export default defineConfig({ /* Record video on failure */ video: "retain-on-failure", + + /* Useful for local debugging */ + // headless: false, }, /* Configure projects for major browsers */ diff --git a/package.json b/package.json index bd494090a..41d1b89e5 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "start-client": "cd client && npm run preview", "test": "npm run prettier-check && cd client && npm test", "test-cli": "cd cli && npm run test", - "test:e2e": "MCP_AUTO_OPEN_ENABLED=false npm run test:e2e --workspace=client", + "test:e2e": "npm run test:e2e --workspace=client", "prettier-fix": "prettier --write .", "prettier-check": "prettier --check .", "lint": "prettier --check . && cd client && npm run lint",