mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
Each of these specs declared the service it exercises and then, as its first action, signed in through the dashboard's OIDC button. In a round that ships no identity provider that button does not exist, so the spec spent its whole timeout waiting for it and reported the missing login rather than anything about MCP. The junit already said as much, carrying the SSO_SERVICE_ENABLED flag as the skip reason on the neighbouring tests. Nine specs in the directory sign in that way; two already declared sso. The other seven now do too, through the same gate they already imported. Signing in as the deployed identity instead was not open to us: that helper authenticates as the administrator whatever username it is handed, which contradicts the non-member spec asserting the very endpoint the administrator is asserted to reach. Nor can a native member stand in, because the account is created by the OIDC login itself, so a round without one has no members to grant anything to. This buys the honest label at a price worth naming: a round that ships seaweedfs without sso now reports green with no seaweedfs coverage, where it used to report red for the wrong reason. Covering that needs a sign-in the suite does not have yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
88 lines
3.2 KiB
JavaScript
88 lines
3.2 KiB
JavaScript
const { test, expect } = require("@playwright/test");
|
|
const { resolveTimeout } = require("./timeouts");
|
|
const { skipUnlessServiceEnabled } = require("./service-gating");
|
|
|
|
exports.register = function (shared) {
|
|
test("administrator: every registered MCP server answers Open WebUI's client", async ({
|
|
page,
|
|
}) => {
|
|
skipUnlessServiceEnabled("mcp");
|
|
skipUnlessServiceEnabled("sso");
|
|
|
|
const expected = (shared.env.mcpExpectedServers || "")
|
|
.split(",")
|
|
.map((s) => s.trim())
|
|
.filter(Boolean);
|
|
expect(
|
|
expected.length,
|
|
"the deploy must have discovered at least one MCP server when the mcp service is enabled"
|
|
).toBeGreaterThan(0);
|
|
|
|
test.setTimeout(resolveTimeout(60_000 + expected.length * 20_000));
|
|
|
|
await shared.signInViaDashboardOidc(
|
|
page,
|
|
shared.env.adminUsername,
|
|
shared.env.adminPassword,
|
|
"administrator"
|
|
);
|
|
|
|
const token = await page.evaluate(() => window.localStorage.getItem("token"));
|
|
expect(token, "OpenWebUI must store a session token after login").toBeTruthy();
|
|
const headers = { Authorization: `Bearer ${token}` };
|
|
const base = shared.env.openwebuiBaseUrl.replace(/\/+$/, "");
|
|
|
|
const readProbes = JSON.parse(shared.env.mcpExpectedTools || "{}");
|
|
|
|
const config = await page.request.get(`${base}/api/v1/configs/tool_servers`, {
|
|
headers,
|
|
});
|
|
expect(
|
|
config.ok(),
|
|
`the admin tool-server config must answer the authenticated session (HTTP ${config.status()})`
|
|
).toBeTruthy();
|
|
const connections = (await config.json())?.TOOL_SERVER_CONNECTIONS ?? [];
|
|
|
|
const verifiable = expected.filter((id) => {
|
|
const connection = connections.find(
|
|
(c) => c?.type === "mcp" && String(c?.info?.id ?? "") === id
|
|
);
|
|
expect(connection, `${id} must be a configured MCP tool server`).toBeTruthy();
|
|
return connection.auth_type === "bearer";
|
|
});
|
|
expect(
|
|
verifiable.length,
|
|
`none of ${JSON.stringify(expected)} authenticates with a deployment bearer; only a bearer connection carries its credential in the row, a system_oauth one resolves the caller's own upstream token and the administrator holds none, so there is nothing here this spec can verify against the bridge`
|
|
).toBeGreaterThan(0);
|
|
|
|
for (const id of verifiable) {
|
|
const connection = connections.find(
|
|
(c) => c?.type === "mcp" && String(c?.info?.id ?? "") === id
|
|
);
|
|
|
|
const verify = await page.request.post(
|
|
`${base}/api/v1/configs/tool_servers/verify`,
|
|
{ headers, data: connection }
|
|
);
|
|
expect(
|
|
verify.ok(),
|
|
`${id} did not answer Open WebUI's MCP client (HTTP ${verify.status()}); the endpoint is down, the deployed bearer is refused, or the transport disagrees`
|
|
).toBeTruthy();
|
|
|
|
const specs = (await verify.json())?.specs ?? [];
|
|
expect(
|
|
specs.length,
|
|
`${id} completed the handshake but served no tool; a client would be configured against an empty surface`
|
|
).toBeGreaterThan(0);
|
|
|
|
const probe = readProbes[id];
|
|
if (probe) {
|
|
expect(
|
|
specs.map((s) => String(s?.name ?? "")),
|
|
`${id} does not serve ${probe}, the read probe its meta/mcp.yml declares`
|
|
).toContain(probe);
|
|
}
|
|
}
|
|
});
|
|
};
|