Merge branch 'codex/20260929-code-back-entry-33d87a81-code-back-entry' into codex/20260930-code-nav-merge-2f867bc4-code-nav-merge

This commit is contained in:
鲨鱼辣椒
2026-09-30 01:02:20 +08:00
16 changed files with 595 additions and 35 deletions

View File

@@ -50,7 +50,7 @@ async function seedInactiveCodingProjects(resources: { rootDir: string; userData
}
test.describe('Makelore module navigation without setup flow', () => {
test('offers a create CTA and horizontal cards for remembered inactive Code projects', async ({
test('opens remembered Code projects and keeps the module return entry in chat instead of project settings', async ({
electronTestResources,
launchElectronApp,
}) => {
@@ -76,6 +76,125 @@ test.describe('Makelore module navigation without setup flow', () => {
await expect(page.getByTestId('coding-chat-panel')).toBeVisible();
await expect(page.getByTestId('coding-existing-projects')).toHaveCount(0);
await expect(page.getByTestId('sidebar-course-project-project-storybook')).toHaveAttribute('aria-current', 'page');
const sidebar = page.getByTestId('sidebar');
const moduleReturn = page.getByTestId('sidebar-module-switcher-trigger');
await expect(moduleReturn).toBeVisible();
await expect(moduleReturn).toHaveText('');
await expect(moduleReturn).toHaveAttribute('aria-label', '返回首页');
await expect(moduleReturn).toHaveAttribute('title', '返回首页');
await expect(page.getByTestId('sidebar-module-return-icon')).toBeVisible();
const brandBox = await sidebar.locator('.classroom-brand').boundingBox();
const returnBox = await moduleReturn.boundingBox();
const collapseBox = await page.getByRole('button', { name: '折叠侧栏' }).boundingBox();
const sidebarBox = await sidebar.boundingBox();
expect(brandBox).not.toBeNull();
expect(returnBox).not.toBeNull();
expect(collapseBox).not.toBeNull();
expect(returnBox!.y + returnBox!.height).toBeLessThanOrEqual(brandBox!.y);
const headerBox = await page.getByTestId('coding-conversation-header').boundingBox();
const tabsBox = await page.getByRole('tablist', { name: '当前工作' }).boundingBox();
expect(Math.abs(returnBox!.y + returnBox!.height / 2 - headerBox!.y - headerBox!.height / 2)).toBeLessThan(1);
expect(Math.abs(brandBox!.y + brandBox!.height / 2 - tabsBox!.y - tabsBox!.height / 2)).toBeLessThan(1);
expect(brandBox!.y - sidebarBox!.y).toBe(0);
expect(brandBox!.height).toBe(tabsBox!.height);
expect(returnBox!.width).toBe(32);
expect(Math.abs(returnBox!.y + returnBox!.height / 2 - collapseBox!.y - collapseBox!.height / 2)).toBeLessThan(1);
expect(returnBox!.x + returnBox!.width).toBeLessThanOrEqual(collapseBox!.x);
expect(sidebarBox!.x + sidebarBox!.width - collapseBox!.x - collapseBox!.width).toBeLessThanOrEqual(14);
await expect(page.getByTestId('titlebar-sidebar-toggle')).toHaveCount(1);
const community = sidebar.getByRole('button', { name: '作品广场', exact: true });
await expect(community).toHaveCount(1);
const communityBox = await community.boundingBox();
const createBox = await sidebar.getByTestId('sidebar-create-project').boundingBox();
const headingBox = await sidebar.locator('.classroom-projects-heading').boundingBox();
expect(communityBox!.y).toBeGreaterThanOrEqual(brandBox!.y + brandBox!.height);
expect(communityBox!.y - brandBox!.y - brandBox!.height).toBe(10);
expect(createBox!.y - communityBox!.y - communityBox!.height).toBe(10);
expect(createBox!.y - brandBox!.y - brandBox!.height).toBe(61);
expect(communityBox!.height).toBe(createBox!.height);
await expect(community).toHaveCSS('background-color', 'rgb(248, 250, 245)');
const buttonStyles = await page.evaluate(() => {
const styles = (selector: string) => {
const s = getComputedStyle(document.querySelector(selector)!);
return [s.borderRadius, s.borderWidth, s.borderColor, s.boxShadow, s.padding, s.fontSize, s.fontWeight];
};
return { community: styles('[data-testid=sidebar] .community-link'), create: styles('[data-testid=sidebar-create-project]') };
});
expect(buttonStyles.community).toEqual(buttonStyles.create);
expect(headingBox!.y).toBeGreaterThanOrEqual(createBox!.y + createBox!.height);
expect(headingBox!.y - createBox!.y - createBox!.height).toBeLessThanOrEqual(14);
await page.screenshot({ path: test.info().outputPath('chat-code-return-entry.png') });
// Exercise native state events without switching the test app into a macOS Space.
await app.evaluate(({ BrowserWindow }) => BrowserWindow.getAllWindows()[0].emit('enter-full-screen'));
await expect.poll(async () => (await moduleReturn.boundingBox())!.x).toBe(createBox!.x);
const fullscreenReturn = await moduleReturn.boundingBox();
expect(fullscreenReturn!.y).toBe(returnBox!.y);
expect(await page.getByRole('button', { name: '折叠侧栏' }).boundingBox()).toEqual(collapseBox);
expect(await sidebar.locator('.classroom-brand').boundingBox()).toEqual(brandBox);
await page.screenshot({ path: test.info().outputPath('chat-fullscreen-return-aligned.png') });
await app.evaluate(({ BrowserWindow }) => BrowserWindow.getAllWindows()[0].emit('leave-full-screen'));
await expect.poll(async () => (await moduleReturn.boundingBox())!.x).toBe(returnBox!.x);
const sidebarResizer = sidebar.getByRole('separator', { name: '调整左侧功能栏宽度' });
await sidebarResizer.press('Home');
await expect(sidebarResizer).toHaveAttribute('aria-valuenow', '128');
const narrowReturn = await moduleReturn.boundingBox();
const narrowToggle = await page.getByRole('button', { name: '折叠侧栏' }).boundingBox();
expect(narrowReturn!.x + narrowReturn!.width).toBeLessThanOrEqual(narrowToggle!.x);
await expect(moduleReturn).toBeVisible();
await expect(page.getByRole('button', { name: '折叠侧栏' })).toBeVisible();
const narrowHeader = await page.getByTestId('coding-conversation-header').boundingBox();
expect(narrowToggle!.x + narrowToggle!.width).toBeLessThanOrEqual(narrowHeader!.x);
expect(await moduleReturn.evaluate(el => {
const b = el.getBoundingClientRect();
return el.contains(document.elementFromPoint(b.x + b.width / 2, b.y + b.height / 2));
})).toBe(true);
await expect(community).toBeVisible();
expect(await community.evaluate(element => element.scrollWidth <= element.clientWidth)).toBe(true);
await page.screenshot({ path: test.info().outputPath('chat-narrow-navigation-row.png') });
await sidebarResizer.dblclick();
await expect(sidebarResizer).toHaveAttribute('aria-valuenow', '171');
await sidebar.getByRole('button', { name: '项目设置', exact: true }).click();
await expect(page).toHaveURL(/\/project-config$/);
await expect(page.getByTestId('project-configuration-page')).toBeVisible();
await expect(sidebar.getByTestId('sidebar-module-switcher')).toHaveCount(0);
const projectBack = page.getByTestId('project-configuration-back-button');
await expect(projectBack).toBeVisible();
await page.screenshot({ path: test.info().outputPath('project-config-without-module-return.png') });
await projectBack.click();
await expect(page).toHaveURL(/\/chat$/);
await expect(moduleReturn).toBeVisible();
await sidebar.getByRole('button', { name: '项目设置', exact: true }).click();
await page.getByTestId('resource-card-plugins').click();
await expect(page).toHaveURL(/\/project-config\/plugins\?/);
const plugins = page.getByTestId('project-plugins-sheet');
await expect(plugins).toBeVisible();
await expect(sidebar.getByTestId('sidebar-module-switcher')).toHaveCount(0);
await page.screenshot({ path: test.info().outputPath('project-config-plugins-without-module-return.png') });
await plugins.getByRole('button', { name: '关闭', exact: true }).click();
await expect(page).toHaveURL(/\/project-config$/);
await expect(projectBack).toBeVisible();
await sidebar.getByTestId('sidebar-course-project-project-storybook').click();
await expect(page).toHaveURL(/\/chat$/);
const sidebarToggle = page.getByTestId('titlebar-sidebar-toggle');
await sidebarToggle.click();
await page.getByTestId('coding-chat-panel').click({ position: { x: 500, y: 200 } });
await expect(sidebar).toHaveAttribute('aria-hidden', 'true');
const collapsedToggleBox = await sidebarToggle.boundingBox();
await expect(moduleReturn).toBeVisible();
await sidebarToggle.hover();
await expect(sidebar).toHaveAttribute('aria-hidden', 'false');
expect(await sidebarToggle.boundingBox()).toEqual(collapsedToggleBox);
await expect(moduleReturn).toBeVisible();
await page.screenshot({ path: test.info().outputPath('chat-collapsed-hover-code-return.png') });
await moduleReturn.click();
await expect(page).toHaveURL(/\/module-select$/);
await expect(page.getByTestId('ai-module-selection-page')).toBeVisible();
} finally {
await closeElectronApp(app);
}