mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-05 15:11:36 +00:00
* refactor(ui): split chat composer * refactor(ui): align composer split ownership * test(ui): clarify custom combobox inventory
66 lines
2.5 KiB
TypeScript
66 lines
2.5 KiB
TypeScript
// @vitest-environment node
|
|
import { readdir, readFile } from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const sourceRoot = path.resolve(import.meta.dirname, "..");
|
|
|
|
async function productionTypeScriptFiles(dir = sourceRoot): Promise<string[]> {
|
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
const files = await Promise.all(
|
|
entries.map(async (entry) => {
|
|
const filePath = path.join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
return productionTypeScriptFiles(filePath);
|
|
}
|
|
if (!entry.name.endsWith(".ts") || entry.name.includes(".test.")) {
|
|
return [];
|
|
}
|
|
return [filePath];
|
|
}),
|
|
);
|
|
return files.flat();
|
|
}
|
|
|
|
async function matchingFiles(pattern: RegExp): Promise<string[]> {
|
|
const matches: string[] = [];
|
|
for (const filePath of await productionTypeScriptFiles()) {
|
|
if (pattern.test(await readFile(filePath, "utf8"))) {
|
|
matches.push(path.relative(sourceRoot, filePath));
|
|
}
|
|
}
|
|
return matches.toSorted();
|
|
}
|
|
|
|
describe("Web Awesome control ownership", () => {
|
|
it("keeps dialogs, menus, and tabs on shared primitives", async () => {
|
|
expect(await matchingFiles(/<dialog\b/u)).toEqual([]);
|
|
expect(
|
|
await matchingFiles(/<[a-z][^>]*\srole=["'](?:menu|menubar|menuitem|tab|tablist)["']/u),
|
|
).toEqual([]);
|
|
expect(
|
|
await matchingFiles(/<details\b[^>]*class=["'][^"']*(?:menu|select|popover|dropdown)/u),
|
|
).toEqual(["pages/chat/components/chat-model-controls.ts"]);
|
|
});
|
|
|
|
it("limits custom comboboxes to dynamic suggestion surfaces", async () => {
|
|
// Web Awesome Core has no combobox; its combobox is a paid Pro component.
|
|
// This inventory tracks literal ARIA roles, not Web Awesome elements that own roles internally.
|
|
expect(await matchingFiles(/<[a-z][^>]*\srole=["'](?:combobox|listbox|option)["']/u)).toEqual([
|
|
"components/command-palette.ts",
|
|
"pages/chat/components/chat-composer-slash-menu.ts",
|
|
"pages/chat/components/chat-model-controls.ts",
|
|
]);
|
|
});
|
|
|
|
it("limits custom dividers to docked multi-pane layouts", async () => {
|
|
// Web Awesome split panel owns exactly two panes; these layouts coordinate
|
|
// sidebar, inspector, and responsive dock state across more than two panes.
|
|
expect(await matchingFiles(/<resizable-divider\b/u)).toEqual([
|
|
"app/app-host.ts",
|
|
"pages/chat/chat-page.ts",
|
|
"pages/chat/components/chat-resizable-divider.ts",
|
|
]);
|
|
});
|
|
});
|