import { fireEvent, render, screen } from '@testing-library/react'; import { beforeEach, describe, expect, it } from 'vitest'; import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom'; import { ModuleSwitcher } from '@/components/layout/ModuleSwitcher'; import { ModuleSelection } from '@/pages/ModuleSelection'; import { useAuthStore } from '@/stores/auth'; import { useOpencodeStore } from '@/stores/opencode'; function LocationProbe() { const location = useLocation(); return {location.pathname}; } describe('AI module navigation', () => { beforeEach(() => { useAuthStore.setState({ user: { username: 'zhangsan@example.com', userId: 'user-1', tenantId: null, deptId: null, authorities: [] }, }); useOpencodeStore.setState({ activeProject: null }); }); it('shows the two module choices and routes enabled modules from the chooser', async () => { render( } /> } /> , ); expect(screen.getByTestId('ai-module-selection-page')).toBeInTheDocument(); expect(screen.getByRole('heading', { name: '今天,想创造什么?' })).toBeInTheDocument(); expect(screen.getByText('zhangsan,欢迎回来!')).toBeInTheDocument(); expect(screen.queryByText('先选一个入口。进入后,你还可以从左下角随时切换到其他模块。')).not.toBeInTheDocument(); expect(screen.getByTestId('ai-module-option-programming')).toHaveTextContent('Makelore Code'); expect(screen.getByTestId('ai-module-option-programming')).toHaveTextContent('AI 编程'); expect(screen.getByTestId('ai-module-option-programming')).toHaveTextContent('把想法变成可运行的产品、游戏和工具。'); expect(screen.getByTestId('ai-module-option-painting')).toHaveTextContent('Makelore Canvas'); fireEvent.click(screen.getByTestId('ai-module-option-painting')); expect(await screen.findByTestId('location-path')).toHaveTextContent('/image-canvas'); }); it('routes AI programming from the chooser to the project conversation entry', async () => { render( } /> } /> , ); fireEvent.click(screen.getByTestId('ai-module-option-programming')); expect(await screen.findByTestId('location-path')).toHaveTextContent('/opencode-chat'); }); it('keeps the current module active and switches from the Sidebar entry', async () => { render( } /> , ); expect(screen.getByTestId('sidebar-module-switcher-trigger')).toHaveAttribute('aria-expanded', 'false'); expect(screen.queryByTestId('sidebar-module-painting')).not.toBeInTheDocument(); fireEvent.click(screen.getByTestId('sidebar-module-switcher-trigger')); expect(screen.getByTestId('sidebar-module-switcher-menu')).toBeInTheDocument(); expect(screen.getByTestId('sidebar-module-painting')).toHaveAttribute('aria-current', 'page'); expect(screen.getByTestId('sidebar-module-programming')).not.toHaveAttribute('aria-current'); fireEvent.click(screen.getByTestId('sidebar-module-programming')); expect(await screen.findByTestId('location-path')).toHaveTextContent('/opencode-chat'); }); });