feat(tree): close rust family shell cutover
This commit is contained in:
@@ -15,6 +15,64 @@ const {
|
||||
renameDocument,
|
||||
} = require("./tree-shell-smoke-helpers");
|
||||
|
||||
const ALLOW_LEGACY_TREE_SHELL_IFRAME_HOST =
|
||||
String(process.env.NEXT_PUBLIC_TREE_SHELL_LEGACY_IFRAME_HOST || "").trim() === "1";
|
||||
|
||||
function treeHostImplementationUsesIframe(implementation) {
|
||||
return (
|
||||
implementation === "mnote_web_iframe_proxy" ||
|
||||
implementation === "rust_inline_compat_host" ||
|
||||
implementation === "rust_runtime_artifact_host"
|
||||
);
|
||||
}
|
||||
|
||||
async function waitForPickerShellReady(page) {
|
||||
await page.waitForFunction(
|
||||
() => {
|
||||
const host = document.querySelector('[data-testid="tree-picker-surface"]');
|
||||
if (!(host instanceof HTMLElement) || host.getClientRects().length === 0) {
|
||||
return false;
|
||||
}
|
||||
const implementation = host.getAttribute("data-tree-host-implementation") || "";
|
||||
if (
|
||||
implementation === "mnote_web_iframe_proxy" ||
|
||||
implementation === "rust_inline_compat_host" ||
|
||||
implementation === "rust_runtime_artifact_host"
|
||||
) {
|
||||
const iframe = host.querySelector('[data-testid="tree-picker-surface-rust-iframe"]');
|
||||
if (!(iframe instanceof HTMLIFrameElement) || iframe.getClientRects().length === 0) {
|
||||
return false;
|
||||
}
|
||||
const doc = iframe.contentDocument;
|
||||
const status = doc?.querySelector("#tree-shell-status")?.textContent ?? "";
|
||||
return Boolean(doc?.querySelector("#tree-shell-state")) && status.includes("就绪");
|
||||
}
|
||||
const domHost = host.querySelector('[data-testid="tree-picker-surface-dom-host"]');
|
||||
return (
|
||||
domHost instanceof HTMLElement &&
|
||||
domHost.getClientRects().length > 0 &&
|
||||
domHost.getAttribute("data-tree-browser-bridge") === "dom_wasm" &&
|
||||
domHost.getAttribute("data-tree-dom-shell-ready") === "true"
|
||||
);
|
||||
},
|
||||
undefined,
|
||||
{ timeout: UI_TIMEOUT_MS },
|
||||
);
|
||||
}
|
||||
|
||||
async function pickerUsesLegacyIframe(pickerSurface) {
|
||||
const implementation = await pickerSurface.getAttribute("data-tree-host-implementation");
|
||||
if (treeHostImplementationUsesIframe(implementation) && !ALLOW_LEGACY_TREE_SHELL_IFRAME_HOST) {
|
||||
throw new Error(
|
||||
`tree-picker-surface 默认主路径不能再使用 legacy iframe host: ${implementation || "unknown"}`,
|
||||
);
|
||||
}
|
||||
return (
|
||||
treeHostImplementationUsesIframe(implementation) &&
|
||||
(await pickerSurface.locator('[data-testid="tree-picker-surface-rust-iframe"]').count()) > 0
|
||||
);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const headless =
|
||||
process.env.MNOTE_SMOKE_HEADLESS === "1"
|
||||
@@ -61,6 +119,10 @@ async function main() {
|
||||
|
||||
const dialog = page.getByRole("dialog");
|
||||
await dialog.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
|
||||
const pickerSurface = dialog.getByTestId("tree-picker-surface");
|
||||
await pickerSurface.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
|
||||
await waitForPickerShellReady(page);
|
||||
const usesLegacyIframe = await pickerUsesLegacyIframe(pickerSurface);
|
||||
const searchInput = dialog.getByPlaceholder("移动到...");
|
||||
const keyboardQuery = `task113-keyboard-${Date.now()}`;
|
||||
|
||||
@@ -92,21 +154,27 @@ async function main() {
|
||||
|
||||
try {
|
||||
await searchInput.fill(keyboardQuery, { timeout: UI_TIMEOUT_MS });
|
||||
await page.waitForFunction(
|
||||
(nodeId) => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement)) {
|
||||
return false;
|
||||
}
|
||||
return Boolean(frame.contentDocument?.querySelector(`.tree-row[data-node-id="${nodeId}"]`));
|
||||
},
|
||||
fixture.targetId,
|
||||
{ timeout: UI_TIMEOUT_MS },
|
||||
);
|
||||
if (usesLegacyIframe) {
|
||||
await page.waitForFunction(
|
||||
(nodeId) => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement)) {
|
||||
return false;
|
||||
}
|
||||
return Boolean(frame.contentDocument?.querySelector(`.tree-row[data-node-id="${nodeId}"]`));
|
||||
},
|
||||
fixture.targetId,
|
||||
{ timeout: UI_TIMEOUT_MS },
|
||||
);
|
||||
} else {
|
||||
await dialog
|
||||
.locator(`[data-testid="tree-picker-row"][data-node-id="${fixture.targetId}"]`)
|
||||
.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
|
||||
}
|
||||
|
||||
await searchInput.focus();
|
||||
await page.waitForFunction(
|
||||
@@ -119,47 +187,61 @@ async function main() {
|
||||
);
|
||||
|
||||
const readFocusedPickerItemKey = async () =>
|
||||
page.evaluate(() => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement)) {
|
||||
return "";
|
||||
}
|
||||
const rootButton = frame.contentDocument?.querySelector(
|
||||
'.tree-row[data-testid="tree-picker-root"][data-focused="true"]',
|
||||
);
|
||||
if (rootButton) {
|
||||
return "__root__";
|
||||
}
|
||||
const row = frame.contentDocument?.querySelector('.tree-row[data-focused="true"]');
|
||||
return row ? row.getAttribute("data-node-id") || "" : "";
|
||||
});
|
||||
usesLegacyIframe
|
||||
? page.evaluate(() => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement) || !frame.contentDocument) {
|
||||
return "";
|
||||
}
|
||||
const rootButton = frame.contentDocument.querySelector(
|
||||
'[data-testid="tree-picker-root"][data-focused="true"]',
|
||||
);
|
||||
if (rootButton) {
|
||||
return "__root__";
|
||||
}
|
||||
const row = frame.contentDocument.querySelector('.tree-row[data-focused="true"]');
|
||||
return row ? row.getAttribute("data-node-id") || "" : "";
|
||||
})
|
||||
: dialog.evaluate((dialogElement) => {
|
||||
const rootButton = dialogElement.querySelector('[data-testid="tree-picker-root"][data-focused="true"]');
|
||||
if (rootButton) {
|
||||
return "__root__";
|
||||
}
|
||||
const row = dialogElement.querySelector('.tree-row[data-focused="true"]');
|
||||
return row ? row.getAttribute("data-node-id") || "" : "";
|
||||
});
|
||||
|
||||
const moveHighlightTo = async (targetNodeId, maxSteps = 4) => {
|
||||
await page.waitForFunction(
|
||||
() => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement)) {
|
||||
return false;
|
||||
}
|
||||
const rootButton = frame.contentDocument?.querySelector(
|
||||
'.tree-row[data-testid="tree-picker-root"][data-focused="true"]',
|
||||
);
|
||||
if (rootButton) {
|
||||
return true;
|
||||
}
|
||||
return Boolean(frame.contentDocument?.querySelector('.tree-row[data-focused="true"]'));
|
||||
},
|
||||
undefined,
|
||||
{ timeout: UI_TIMEOUT_MS },
|
||||
);
|
||||
if (usesLegacyIframe) {
|
||||
await page.waitForFunction(
|
||||
() => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement) || !frame.contentDocument) {
|
||||
return false;
|
||||
}
|
||||
const rootButton = frame.contentDocument.querySelector(
|
||||
'[data-testid="tree-picker-root"][data-focused="true"]',
|
||||
);
|
||||
const row = frame.contentDocument.querySelector('.tree-row[data-focused="true"]');
|
||||
return Boolean(rootButton || row);
|
||||
},
|
||||
undefined,
|
||||
{ timeout: UI_TIMEOUT_MS },
|
||||
);
|
||||
} else {
|
||||
await dialog
|
||||
.locator('[data-testid="tree-picker-root"][data-focused="true"], .tree-row[data-focused="true"]')
|
||||
.first()
|
||||
.waitFor({ state: "attached", timeout: UI_TIMEOUT_MS });
|
||||
}
|
||||
|
||||
for (let index = 0; index < maxSteps; index += 1) {
|
||||
const currentKey = await readFocusedPickerItemKey();
|
||||
@@ -168,19 +250,33 @@ async function main() {
|
||||
}
|
||||
await page.keyboard.press("ArrowDown");
|
||||
await page.waitForFunction(
|
||||
(previousKey) => {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement)) {
|
||||
({ previousKey, legacyIframe }) => {
|
||||
if (legacyIframe) {
|
||||
const frame = Array.from(
|
||||
document.querySelectorAll('[data-testid="tree-picker-surface-rust-iframe"]'),
|
||||
)
|
||||
.reverse()
|
||||
.find((element) => element instanceof HTMLIFrameElement) ?? null;
|
||||
if (!(frame instanceof HTMLIFrameElement) || !frame.contentDocument) {
|
||||
return false;
|
||||
}
|
||||
const rootButton = frame.contentDocument.querySelector(
|
||||
'[data-testid="tree-picker-root"][data-focused="true"]',
|
||||
);
|
||||
const row = frame.contentDocument.querySelector('.tree-row[data-focused="true"]');
|
||||
const currentKey = rootButton
|
||||
? "__root__"
|
||||
: row
|
||||
? row.getAttribute("data-node-id") || ""
|
||||
: "";
|
||||
return currentKey !== previousKey;
|
||||
}
|
||||
const dialogElement = document.querySelector('[role="dialog"]');
|
||||
if (!(dialogElement instanceof HTMLElement)) {
|
||||
return false;
|
||||
}
|
||||
const rootButton = frame.contentDocument?.querySelector(
|
||||
'.tree-row[data-testid="tree-picker-root"][data-focused="true"]',
|
||||
);
|
||||
const row = frame.contentDocument?.querySelector('.tree-row[data-focused="true"]');
|
||||
const rootButton = dialogElement.querySelector('[data-testid="tree-picker-root"][data-focused="true"]');
|
||||
const row = dialogElement.querySelector('.tree-row[data-focused="true"]');
|
||||
const currentKey = rootButton
|
||||
? "__root__"
|
||||
: row
|
||||
@@ -188,7 +284,7 @@ async function main() {
|
||||
: "";
|
||||
return currentKey !== previousKey;
|
||||
},
|
||||
currentKey,
|
||||
{ previousKey: currentKey, legacyIframe: usesLegacyIframe },
|
||||
{ timeout: UI_TIMEOUT_MS },
|
||||
);
|
||||
await page.waitForFunction(
|
||||
|
||||
Reference in New Issue
Block a user