feat: add Makelore Robot hardware module

This commit is contained in:
2026-08-13 23:17:22 +08:00
parent 22add3f01f
commit aba5cae286
25 changed files with 3169 additions and 72 deletions

View File

@@ -62,15 +62,14 @@ describe('AI module navigation', () => {
expect(learningOption).toHaveTextContent('暂未开放');
expect(screen.getByAltText('数学科技宇宙')).toBeInTheDocument();
const robotOption = screen.getByTestId('ai-module-option-robot');
expect(robotOption).toBeDisabled();
expect(robotOption).toHaveClass('module-option-card-disabled');
expect(robotOption).toBeEnabled();
expect(robotOption).toHaveTextContent('Robot 机器');
expect(robotOption).toHaveTextContent('制作你的第一个机器人小伙伴');
expect(robotOption).toHaveTextContent('暂未开放');
expect(robotOption).not.toHaveTextContent('暂未开放');
expect(screen.getByAltText('青少年管理机器人硬件与设备绑定')).toBeInTheDocument();
fireEvent.click(screen.getByTestId('ai-module-option-painting'));
expect(await screen.findByTestId('location-path')).toHaveTextContent('/image-canvas');
fireEvent.click(robotOption);
expect(await screen.findByTestId('location-path')).toHaveTextContent('/ai-hardware');
});
it('routes AI programming from the chooser to the project conversation entry', async () => {
@@ -131,6 +130,7 @@ describe('AI module navigation', () => {
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');
expect(screen.getByTestId('sidebar-module-robot')).not.toHaveAttribute('aria-current');
const learningModule = screen.getByTestId('sidebar-module-learning');
expect(learningModule).toBeDisabled();
expect(learningModule).toHaveTextContent('学习 Learning');
@@ -139,17 +139,28 @@ describe('AI module navigation', () => {
fireEvent.click(learningModule);
expect(screen.getByTestId('location-path')).toHaveTextContent('/image-canvas');
const robotModule = screen.getByTestId('sidebar-module-robot');
expect(robotModule).toBeDisabled();
expect(robotModule).toHaveTextContent('Robot 机器');
expect(robotModule).toHaveTextContent('AI 机器');
fireEvent.click(robotModule);
expect(screen.getByTestId('location-path')).toHaveTextContent('/image-canvas');
fireEvent.click(screen.getByTestId('sidebar-module-programming'));
expect(await screen.findByTestId('location-path')).toHaveTextContent('/opencode-chat');
});
it('marks Robot active on the AI hardware route and switches back to Canvas', async () => {
render(
<MemoryRouter initialEntries={['/ai-hardware']}>
<Routes>
<Route path="*" element={<><ModuleSwitcher sidebarCollapsed={false} /><LocationProbe /></>} />
</Routes>
</MemoryRouter>,
);
expect(screen.getByTestId('sidebar-module-switcher-trigger')).toHaveTextContent('Robot 机器');
fireEvent.click(screen.getByTestId('sidebar-module-switcher-trigger'));
expect(screen.getByTestId('sidebar-module-robot')).toHaveAttribute('aria-current', 'page');
expect(screen.getByTestId('sidebar-module-programming')).not.toHaveAttribute('aria-current');
fireEvent.click(screen.getByTestId('sidebar-module-painting'));
expect(await screen.findByTestId('location-path')).toHaveTextContent('/image-canvas');
});
it('keeps breathing room around the compact module switcher trigger', () => {
render(
<MemoryRouter initialEntries={['/opencode-chat']}>
@@ -160,4 +171,5 @@ describe('AI module navigation', () => {
const trigger = screen.getByTestId('sidebar-module-switcher-trigger');
expect(trigger).toHaveClass('inline-flex', 'w-fit', 'px-2');
});
});