fix(agents): open cards from home and align sidebar navigation
This commit is contained in:
1 parent
e5d79bf37a
commit
5e99804bc2
13 files changed
+460
-27
No files matched your search
@@ -0,0 +1,123 @@
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
import { createServer, type ViteDevServer } from 'vite';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
let server: ViteDevServer;
|
||||
let baseUrl: string;
|
||||
test.use({ headless: true, channel: process.env.MAKELORE_LAYOUT_BROWSER_CHANNEL, video: 'off' });
|
||||
|
||||
// Exercise actual navigation controls and persisted layout state without
|
||||
// starting Electron or connecting to an account or any cloud service.
|
||||
test.beforeAll(async () => {
|
||||
const entry = resolve('tests/e2e/__cloud-agent-navigation-layout-harness.tsx');
|
||||
server = await createServer({
|
||||
configFile: false,
|
||||
cacheDir: 'node_modules/.vite-cloud-agent-navigation-layout',
|
||||
resolve: { alias: { '@': resolve('src') } },
|
||||
esbuild: { jsx: 'automatic' },
|
||||
server: { host: '127.0.0.1', port: 0 },
|
||||
plugins: [{
|
||||
name: 'isolated-cloud-agent-navigation-layout', enforce: 'pre',
|
||||
resolveId(id) { if (id === '/__cloud-agent-navigation-layout-harness.tsx') return entry; },
|
||||
load(id) {
|
||||
if (id === entry) return `
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom';
|
||||
import { TitleBar } from '/src/components/layout/TitleBar.tsx';
|
||||
import { useSettingsStore } from '/src/stores/settings.ts';
|
||||
import '/src/styles/globals.css';
|
||||
function AgentFrame() {
|
||||
const collapsed = useSettingsStore(state => state.sidebarCollapsed);
|
||||
const location = useLocation();
|
||||
return <div className="flex h-screen min-w-0 flex-col">
|
||||
<TitleBar integrated showModuleReturn pageTitle="我的智能体" />
|
||||
<div className="flex min-h-0 flex-1">
|
||||
{!collapsed && <aside aria-label="智能体侧栏" className="w-64 shrink-0" />}
|
||||
<main className="min-w-0 flex-1"><output data-testid="fixture-location">{location.pathname}</output></main>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
createRoot(document.getElementById('root')).render(<MemoryRouter initialEntries={['/cloud-agents?view=mine']}>
|
||||
<Routes><Route path="/cloud-agents" element={<AgentFrame />} /><Route path="/module-select" element={<main>首页模块卡片</main>} /></Routes>
|
||||
</MemoryRouter>);
|
||||
`;
|
||||
if (id.endsWith('/src/stores/coding-workspace.ts')) return 'export function useCodingWorkspaceStore(select) { return select({ activeProject: null }); }';
|
||||
if (id.endsWith('/src/stores/user-sync.ts')) return 'export const useUserSyncStore = { getState: () => ({ pushPreferences: async () => undefined }) };';
|
||||
},
|
||||
configureServer(vite) {
|
||||
vite.middlewares.use((req, res, next) => {
|
||||
if (req.url !== '/' && !req.url?.startsWith('/?')) return next();
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.end('<!doctype html><html><head><meta charset="utf-8"></head><body><div id="root"></div><script type="module" src="/__cloud-agent-navigation-layout-harness.tsx"></script></body></html>');
|
||||
});
|
||||
},
|
||||
}],
|
||||
});
|
||||
await server.listen();
|
||||
baseUrl = server.resolvedUrls!.local[0];
|
||||
});
|
||||
test.afterAll(async () => { await server?.close(); });
|
||||
|
||||
async function expectNavigationRow(page: Page, width: number) {
|
||||
const back = page.getByRole('button', { name: '返回首页', exact: true });
|
||||
const toggle = page.getByTestId('titlebar-sidebar-toggle');
|
||||
await expect(back).toHaveCount(1);
|
||||
await expect(back).toBeVisible();
|
||||
await expect(toggle).toBeVisible();
|
||||
const a = (await back.boundingBox())!;
|
||||
const b = (await toggle.boundingBox())!;
|
||||
expect(Math.abs((a.y + a.height / 2) - (b.y + b.height / 2))).toBeLessThanOrEqual(1);
|
||||
expect(a.x + a.width).toBeLessThanOrEqual(b.x);
|
||||
for (const box of [a, b]) {
|
||||
expect(box.x).toBeGreaterThanOrEqual(0);
|
||||
expect(box.x + box.width).toBeLessThanOrEqual(width);
|
||||
expect(box.y).toBeGreaterThanOrEqual(0);
|
||||
expect(box.width).toBeGreaterThanOrEqual(32);
|
||||
expect(box.height).toBeGreaterThanOrEqual(32);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
for (const platform of ['darwin', 'win32', 'linux']) {
|
||||
for (const width of [375, 1024]) {
|
||||
test(`${platform} Agent return and sidebar toggle share one usable row at ${width}px`, async ({ page }) => {
|
||||
const pageErrors: string[] = [];
|
||||
page.on('pageerror', error => pageErrors.push(error.message));
|
||||
await page.setViewportSize({ width, height: 760 });
|
||||
await page.addInitScript(platform => {
|
||||
Object.defineProperty(window, 'electron', { value: { platform, ipcRenderer: {
|
||||
invoke: async (channel: string) => {
|
||||
if (channel === 'window:isMaximized' || channel === 'window:isFullScreen') return false;
|
||||
throw new Error('Unexpected fixture IPC ' + channel);
|
||||
},
|
||||
on: () => () => {},
|
||||
} } });
|
||||
}, platform);
|
||||
await page.goto(baseUrl);
|
||||
await expect(page.getByTestId('fixture-location')).toHaveText('/cloud-agents');
|
||||
const expandedToggle = await expectNavigationRow(page, width);
|
||||
await expect(page.getByTestId('titlebar-sidebar-toggle')).toHaveAttribute('aria-label', '折叠侧栏');
|
||||
|
||||
// 375px stresses application controls; Windows' native desktop frame has
|
||||
// a larger minimum width, so validate its chrome separation at 1024px.
|
||||
if (platform !== 'win32' || width === 1024) {
|
||||
const logo = (await page.getByTestId('titlebar-logo').boundingBox())!;
|
||||
expect(expandedToggle.x + expandedToggle.width).toBeLessThanOrEqual(logo.x);
|
||||
}
|
||||
await page.getByTestId('titlebar-sidebar-toggle').click();
|
||||
await expect(page.getByRole('complementary', { name: '智能体侧栏' })).toHaveCount(0);
|
||||
await expect(page.getByTestId('titlebar-sidebar-toggle')).toHaveAttribute('aria-label', '展开侧栏');
|
||||
const collapsedToggle = await expectNavigationRow(page, width);
|
||||
const collapsedLogo = (await page.getByTestId('titlebar-logo').boundingBox())!;
|
||||
expect(collapsedToggle.x + collapsedToggle.width).toBeLessThanOrEqual(collapsedLogo.x);
|
||||
|
||||
await page.getByTestId('titlebar-sidebar-toggle').click();
|
||||
await expect(page.getByRole('complementary', { name: '智能体侧栏' })).toBeVisible();
|
||||
await expectNavigationRow(page, width);
|
||||
await page.getByTestId('titlebar-sidebar-toggle').click();
|
||||
await page.getByRole('button', { name: '返回首页', exact: true }).click();
|
||||
await expect(page.getByText('首页模块卡片')).toBeVisible();
|
||||
expect(pageErrors).toEqual([]);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user