Skip to content

Commit 3947fa6

Browse files
Integration tests for command line arguments
Use different server startup commands in Playwright to allow tests that command line arguments initialize form inputs as intended. A full integration test is used because the Inspector comprises multiple components (package bin entry point, start command, webClient, server), making benefit to test-effort higher, and less dependent on implementation details. The webServer start command uses the package entry point to ensure tests follow the exact user experience provided by: `npx @m/inspector [...]` Playwright's `webServer.command` cannot be [re]configured after it has started, so multiple Playwright invocations are necessary. To do this, use an environment variable and a command-generating function (instead of multiple config files). Test tagging (`@cli`) is used to select which tests execute, while keeping the entire test suite together. Future: Playwright has a feature under consideration to permit a web server per project, which might simplify the config: microsoft/playwright#22496
1 parent 82a9dcf commit 3947fa6

File tree

4 files changed

+76
-2
lines changed

4 files changed

+76
-2
lines changed

client/e2e/cli-arguments.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { test, expect } from "@playwright/test";
2+
3+
// Adjust the URL if your dev server runs on a different port
4+
const APP_URL = "http://localhost:6274/";
5+
6+
test.describe("CLI npx (npm exec) start up", { tag: "@cli" }, () => {
7+
test("CLI arguments should populate form fields", async ({ page }) => {
8+
const cliTestScenario = process.env.CLI_TEST_SCENARIO;
9+
10+
// Skip this test if not running a CLI test scenario
11+
if (
12+
!cliTestScenario ||
13+
(cliTestScenario !== "inline" && cliTestScenario !== "file")
14+
) {
15+
test.skip();
16+
return;
17+
}
18+
19+
await page.goto(APP_URL);
20+
21+
const commandInput = page.getByRole("textbox", { name: "Command" });
22+
const argsInput = page.getByRole("textbox", { name: "Arguments" });
23+
24+
await expect(commandInput).toHaveValue("uv");
25+
await expect(argsInput).toHaveValue("run main.py");
26+
27+
// Click to expand environment variables section
28+
const envButton = page.getByRole("button", {
29+
name: /Environment Variables/i,
30+
});
31+
await envButton.click();
32+
33+
// Check that environment variables are populated (sorted alphabetically)
34+
const keyInputs = page.locator('input[placeholder="Key"]');
35+
const valueInputs = page.locator('input[placeholder="Value"]');
36+
37+
await expect(keyInputs.first()).toHaveValue("BAZ");
38+
await expect(valueInputs.first()).toHaveValue("bat");
39+
});
40+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"mcpServers": {
3+
"test-server": {
4+
"command": "uv",
5+
"args": ["run", "main.py"],
6+
"env": {
7+
"FOO": "bar",
8+
"BAZ": "bat"
9+
}
10+
}
11+
}
12+
}

client/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
"preview": "vite preview --port 6274",
2222
"test": "jest --config jest.config.cjs",
2323
"test:watch": "jest --config jest.config.cjs --watch",
24-
"test:e2e": "playwright test e2e && npm run cleanup:e2e",
24+
"test:e2e": "playwright test --grep-invert @cli e2e && npm run test:e2e:cli-file && npm run test:e2e:cli-inline && npm run cleanup:e2e",
25+
"test:e2e:cli-file": "CLI_TEST_SCENARIO=file playwright test --grep @cli e2e",
26+
"test:e2e:cli-inline": "CLI_TEST_SCENARIO=inline playwright test --grep @cli e2e",
2527
"cleanup:e2e": "node e2e/global-teardown.js"
2628
},
2729
"dependencies": {

client/playwright.config.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
import { defineConfig, devices } from "@playwright/test";
22

3+
const getWebServerCommand = () => {
4+
/**
5+
* The content of the fixture configuration file matches the inline arguments such
6+
* that the same set of tests (tagged `@cli`) can run in both scenarios.
7+
*/
8+
switch (process.env.CLI_TEST_SCENARIO) {
9+
case "inline":
10+
return "npx . -e FOO=bar -e BAZ=bat uv run main.py";
11+
case "file":
12+
return "npx . --config client/e2e/fixtures/test-cli-config.json --server test-server";
13+
/* FIXME: With and without a mock localStorage
14+
* case "none":
15+
* return "npx . ";
16+
*/
17+
default:
18+
return "npm run dev";
19+
}
20+
};
21+
322
/**
423
* @see https://playwright.dev/docs/test-configuration
524
*/
625
export default defineConfig({
726
/* Run your local dev server before starting the tests */
827
webServer: {
928
cwd: "..",
10-
command: "npm run dev",
29+
command: getWebServerCommand(),
1130
url: "http://localhost:6274",
1231
reuseExistingServer: !process.env.CI,
1332
env: {
1433
MCP_AUTO_OPEN_ENABLED: "false",
34+
DANGEROUSLY_OMIT_AUTH: "true",
1535
},
1636
},
1737

0 commit comments

Comments
 (0)