// @vitest-environment jsdom
import { fireEvent, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { APP_NAME } from '../src/app/appMetadata';
import type { GameCreatorDirectActiveTurn } from '../src/app/types';
import { ThemedModal } from '../src/components/modal/ThemedModal';
import { WindowChrome } from '../src/components/WindowChrome';
import { useWindowChrome } from '../src/components/windowChromeContext';
const nativeWindow = vi.hoisted(() => ({
minimize: vi.fn(),
toggleMaximize: vi.fn(),
isMaximized: vi.fn(),
close: vi.fn(),
label: 'client',
}));
vi.mock('@tauri-apps/api/window', () => ({
getCurrentWindow: () => nativeWindow,
}));
function TitleSetter({ value }: { value: string }) {
const { setTitle } = useWindowChrome();
return (
);
}
function ActiveRunsSetter({
activeTurns,
}: {
activeTurns: GameCreatorDirectActiveTurn[];
}) {
const { setActiveProjectRuns } = useWindowChrome();
return (
);
}
describe('WindowChrome', () => {
beforeEach(() => {
nativeWindow.minimize.mockReset();
nativeWindow.toggleMaximize.mockReset();
nativeWindow.isMaximized.mockReset();
nativeWindow.close.mockReset();
delete (window as unknown as Record).__TAURI_INTERNALS__;
});
it('renders the陶泥儿 brand, default title, and controls', async () => {
const user = userEvent.setup();
render(
工作区内容
,
);
expect(screen.getByRole('banner', { name: '窗口标题栏' })).toBeTruthy();
expect(screen.getByLabelText(`${APP_NAME} GameAgent`)).toBeTruthy();
expect(screen.queryByLabelText('本地工作区')).toBeNull();
expect(screen.getByText('创作工作台')).toBeTruthy();
expect(screen.getByText('工作区内容')).toBeTruthy();
expect(screen.queryByRole('menubar')).toBeNull();
await user.click(screen.getByRole('button', { name: '最小化' }));
await user.click(screen.getByRole('button', { name: '最大化' }));
await user.click(screen.getByRole('button', { name: '关闭' }));
});
it('updates the centered title through the shell context', async () => {
const user = userEvent.setup();
render(
,
);
await user.click(screen.getByRole('button', { name: '更新标题' }));
expect(screen.getByText('星尘花园')).toBeTruthy();
expect(screen.getByLabelText('当前工作区:星尘花园')).toBeTruthy();
});
it('restores the default title when a page clears its title', async () => {
const user = userEvent.setup();
function ClearTitle() {
const { setTitle } = useWindowChrome();
return (
);
}
render(
,
);
await user.click(screen.getByRole('button', { name: '清空标题' }));
expect(screen.getByText('创作工作台')).toBeTruthy();
});
it('closes no menus because the title bar has no application menu bar', () => {
render(
,
);
fireEvent.pointerDown(screen.getByRole('button', { name: '页面按钮' }));
expect(screen.queryByRole('menu')).toBeNull();
});
it('renders the latest active project in the title bar and expands the full list', async () => {
const user = userEvent.setup();
render(
,
);
await user.click(screen.getByRole('button', { name: '显示运行项目' }));
expect(
screen.getByRole('button', { name: /正在运行的项目:后开始/ }),
).toBeTruthy();
expect(screen.queryByRole('menu')).toBeNull();
await user.click(
screen.getByRole('button', { name: /正在运行的项目:后开始/ }),
);
expect(screen.getAllByRole('menuitem')).toHaveLength(2);
});
/**
* 回归:发布面板等 ThemedModal 弹窗打开时,标题栏在模态之外,焦点陷阱曾把
* 标题栏上的点击一起拦下 —— 三个窗口按钮看着正常但点不动。
*/
it('keeps the window controls working while a modal covers the workspace', async () => {
const user = userEvent.setup();
nativeWindow.minimize.mockResolvedValue(undefined);
nativeWindow.toggleMaximize.mockResolvedValue(undefined);
nativeWindow.close.mockResolvedValue(undefined);
nativeWindow.isMaximized.mockResolvedValue(false);
(window as unknown as Record).__TAURI_INTERNALS__ = {};
render(
undefined} ariaLabel="测试弹窗">
,
);
await screen.findByRole('dialog', { name: '测试弹窗' });
await user.click(screen.getByRole('button', { name: '最小化' }));
expect(nativeWindow.minimize).toHaveBeenCalledTimes(1);
await user.click(screen.getByRole('button', { name: '最大化' }));
expect(nativeWindow.toggleMaximize).toHaveBeenCalledTimes(1);
await user.click(screen.getByRole('button', { name: '关闭' }));
expect(nativeWindow.close).toHaveBeenCalledTimes(1);
});
});