源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
import { expect } from "vitest";
|
||||
import { createOrgConnection, evalIn, waitFor } from "@openwork/behaviors";
|
||||
import { app, eventually, faultProxy, mcpMock, needs, server, test, unmetNeeds } from "@openwork/testkit";
|
||||
import type { TestNeeds } from "@openwork/testkit";
|
||||
|
||||
const requirements: TestNeeds = {
|
||||
optIn: ["OPENWORK_EVAL_E2E_TESTS"],
|
||||
};
|
||||
const missingRequirements = unmetNeeds(requirements, process.env);
|
||||
const title = missingRequirements.length > 0
|
||||
? `Library Advanced settings refresh skipped — needs: ${missingRequirements.join(", ")}`
|
||||
: "Library keeps Advanced settings expanded through server inventory refresh";
|
||||
const orgConnectionsPath = "/api/den/v1/mcp-connections";
|
||||
const capabilitiesPath = "/api/den/v1/resources/marketplace-capabilities";
|
||||
|
||||
test(title, async ({ evidence, place }) => {
|
||||
needs(requirements);
|
||||
await using den = await server({
|
||||
place,
|
||||
org: {
|
||||
name: `Library Advanced refresh ${Date.now()}`,
|
||||
admin: { name: "Library Refresh Admin" },
|
||||
},
|
||||
mocks: { connector: mcpMock() },
|
||||
});
|
||||
await using proxy = await faultProxy(den.ref, {
|
||||
place,
|
||||
sandbox: den.placement?.kind === "daytona" ? den.placement.sandboxId : undefined,
|
||||
});
|
||||
await using desktop = await app({ den: { ...den, ref: proxy.ref }, as: "admin", place });
|
||||
const settingsHash = `#/workspace/${desktop.workspaceId}/settings/extensions`;
|
||||
const committedSettingsRoute = `(() => {
|
||||
const target = ${JSON.stringify(settingsHash)};
|
||||
const committed = window.location.hash === target
|
||||
&& !document.querySelector("[data-extensions-main-surface]")
|
||||
&& [...document.querySelectorAll("button")]
|
||||
.some((button) => button.textContent?.trim() === "Back to app")
|
||||
&& [...document.querySelectorAll("h1, h2")]
|
||||
.some((heading) => heading.textContent?.trim() === "Library")
|
||||
&& [...document.querySelectorAll("button")]
|
||||
.some((button) => (button.textContent ?? "").includes("Advanced settings"));
|
||||
if (!committed && window.location.hash !== target) window.location.hash = target;
|
||||
return committed;
|
||||
})()`;
|
||||
|
||||
await waitFor(desktop, committedSettingsRoute, {
|
||||
timeoutMs: 90_000,
|
||||
label: "committed Settings Library route",
|
||||
});
|
||||
|
||||
const initialRequests = await eventually(
|
||||
() => proxy.requestLog(),
|
||||
{
|
||||
within: 60_000,
|
||||
intervalMs: 500,
|
||||
label: "initial server inventory requests",
|
||||
until: (requests) => [orgConnectionsPath, capabilitiesPath].every((path) =>
|
||||
requests.some((request) => request.method === "GET"
|
||||
&& request.path.startsWith(path)
|
||||
&& request.status === 200)),
|
||||
},
|
||||
);
|
||||
const initialOrgConnectionRequests = initialRequests.filter((request) => request.method === "GET"
|
||||
&& request.path.startsWith(orgConnectionsPath)).length;
|
||||
const initialCapabilityRequests = initialRequests.filter((request) => request.method === "GET"
|
||||
&& request.path.startsWith(capabilitiesPath)).length;
|
||||
expect(initialOrgConnectionRequests).toBeGreaterThan(0);
|
||||
expect(initialCapabilityRequests).toBeGreaterThan(0);
|
||||
await waitFor(desktop, committedSettingsRoute, {
|
||||
timeoutMs: 30_000,
|
||||
label: "stable Settings Library route before expanding Advanced settings",
|
||||
});
|
||||
|
||||
const expanded = await evalIn(desktop, `(() => {
|
||||
const button = [...document.querySelectorAll("button")]
|
||||
.find((entry) => (entry.textContent ?? "").includes("Advanced settings"));
|
||||
if (!(button instanceof HTMLButtonElement)) return false;
|
||||
button.scrollIntoView({ block: "center" });
|
||||
button.click();
|
||||
return true;
|
||||
})()`);
|
||||
expect(expanded).toBe(true);
|
||||
await waitFor(desktop, `[...document.querySelectorAll("button")]
|
||||
.some((button) => button.textContent?.trim() === "Add workspace MCP")`, {
|
||||
timeoutMs: 10_000,
|
||||
label: "expanded Add workspace MCP action",
|
||||
});
|
||||
const probeInstalled = await evalIn(desktop, `(() => {
|
||||
const visible = () => {
|
||||
const button = [...document.querySelectorAll("button")]
|
||||
.find((entry) => entry.textContent?.trim() === "Add workspace MCP");
|
||||
if (!(button instanceof HTMLButtonElement)) return false;
|
||||
const rect = button.getBoundingClientRect();
|
||||
return rect.width > 0 && rect.height > 0 && getComputedStyle(button).visibility !== "hidden";
|
||||
};
|
||||
const probe = { everMissing: !visible(), samples: 1 };
|
||||
const observer = new MutationObserver(() => {
|
||||
probe.samples += 1;
|
||||
if (!visible()) probe.everMissing = true;
|
||||
});
|
||||
observer.observe(document.body, { subtree: true, childList: true, attributes: true });
|
||||
window.__openworkAdvancedRefreshProbe = { observer, probe, visible };
|
||||
return visible();
|
||||
})()`);
|
||||
expect(probeInstalled).toBe(true);
|
||||
|
||||
const connectionName = `Advanced refresh connection ${Date.now()}`;
|
||||
await createOrgConnection(den.admin, {
|
||||
name: connectionName,
|
||||
url: den.mocks.connector.mcpUrl,
|
||||
authType: "oauth",
|
||||
credentialMode: "per_member",
|
||||
access: { orgWide: true },
|
||||
});
|
||||
await Promise.all([
|
||||
proxy.faults.latency(orgConnectionsPath, 3_000, { times: 1 }),
|
||||
proxy.faults.latency(capabilitiesPath, 3_000, { times: 1 }),
|
||||
]);
|
||||
const refreshClicked = await evalIn(desktop, `(() => {
|
||||
const button = [...document.querySelectorAll("button")]
|
||||
.find((entry) => entry.textContent?.trim() === "Refresh" && !entry.disabled);
|
||||
if (!(button instanceof HTMLButtonElement)) return false;
|
||||
button.click();
|
||||
return true;
|
||||
})()`);
|
||||
expect(refreshClicked).toBe(true);
|
||||
|
||||
const refreshedRequests = await eventually(
|
||||
() => proxy.requestLog(),
|
||||
{
|
||||
within: 60_000,
|
||||
intervalMs: 500,
|
||||
label: "delayed successful server inventory refresh requests",
|
||||
until: (requests) => {
|
||||
const orgRequests = requests.filter((request) => request.method === "GET"
|
||||
&& request.path.startsWith(orgConnectionsPath));
|
||||
const capabilityRequests = requests.filter((request) => request.method === "GET"
|
||||
&& request.path.startsWith(capabilitiesPath));
|
||||
return orgRequests.length > initialOrgConnectionRequests
|
||||
&& capabilityRequests.length > initialCapabilityRequests
|
||||
&& orgRequests.at(-1)?.status === 200
|
||||
&& orgRequests.at(-1)?.faulted === true
|
||||
&& capabilityRequests.at(-1)?.status === 200
|
||||
&& capabilityRequests.at(-1)?.faulted === true;
|
||||
},
|
||||
},
|
||||
);
|
||||
const refreshedOrgConnectionRequest = refreshedRequests.filter((request) => request.method === "GET"
|
||||
&& request.path.startsWith(orgConnectionsPath)).at(-1);
|
||||
const refreshedCapabilityRequest = refreshedRequests.filter((request) => request.method === "GET"
|
||||
&& request.path.startsWith(capabilitiesPath)).at(-1);
|
||||
expect(refreshedOrgConnectionRequest).toMatchObject({ status: 200, faulted: true });
|
||||
expect(refreshedCapabilityRequest).toMatchObject({ status: 200, faulted: true });
|
||||
|
||||
await waitFor(desktop, `document.body.innerText.includes(${JSON.stringify(connectionName)})`, {
|
||||
timeoutMs: 30_000,
|
||||
label: "new organization connection rendered from refreshed inventory",
|
||||
});
|
||||
const stayedExpanded = await evalIn(desktop, `(() => {
|
||||
const current = window.__openworkAdvancedRefreshProbe;
|
||||
if (!current) return false;
|
||||
current.observer.disconnect();
|
||||
return current.probe.samples > 1 && !current.probe.everMissing && current.visible();
|
||||
})()`);
|
||||
expect(stayedExpanded).toBe(true);
|
||||
evidence.recordAssertionEvidence(
|
||||
"Advanced settings stays expanded through real server inventory refreshes",
|
||||
`Refresh completed delayed HTTP 200 requests for ${refreshedOrgConnectionRequest?.path} and ${refreshedCapabilityRequest?.path}, rendered ${connectionName}, and Add workspace MCP never disappeared.`,
|
||||
refreshedOrgConnectionRequest?.status === 200
|
||||
&& refreshedOrgConnectionRequest.faulted
|
||||
&& refreshedCapabilityRequest?.status === 200
|
||||
&& refreshedCapabilityRequest.faulted
|
||||
&& stayedExpanded === true,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user