Makelore 2.0 initial clean snapshot

This commit is contained in:
inman
2026-07-29 17:22:35 +08:00
commit b8ca3f8eea
694 changed files with 139782 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import Setup from '@/pages/Setup';
import { useAuthStore } from '@/stores/auth';
import { useOpencodeStore } from '@/stores/opencode';
import { useSettingsStore } from '@/stores/settings';
const { hostApiFetchMock, translateMock } = vi.hoisted(() => ({
hostApiFetchMock: vi.fn(),
translateMock: vi.fn((key: string, options?: { returnObjects?: boolean }) => (
options?.returnObjects ? [`${key}.0`, `${key}.1`, `${key}.2`] : key
)),
}));
vi.mock('@/lib/host-api', () => ({
hostApiFetch: (...args: unknown[]) => hostApiFetchMock(...args),
}));
vi.mock('@/lib/api-client', () => ({
invokeIpc: vi.fn(),
}));
vi.mock('react-i18next', async (importOriginal) => {
const actual = await importOriginal<typeof import('react-i18next')>();
return {
...actual,
useTranslation: () => ({
t: translateMock,
}),
};
});
vi.mock('sonner', () => ({
toast: {
success: vi.fn(),
error: vi.fn(),
},
}));
function renderSetup() {
return render(
<MemoryRouter initialEntries={['/setup']}>
<Setup />
</MemoryRouter>,
);
}
function resetStores() {
useAuthStore.setState({ user: null });
useSettingsStore.setState({
setupComplete: false,
theme: 'system',
language: 'en',
launchAtStartup: false,
telemetryEnabled: false,
proxyEnabled: false,
proxyServer: '',
proxyHttpServer: '',
proxyHttpsServer: '',
proxyAllServer: '',
proxyBypassRules: '',
sidebarCollapsed: false,
devModeUnlocked: false,
});
useOpencodeStore.setState({
status: { state: 'stopped', port: 4096 },
health: null,
healthCheckedAt: null,
runtimeConfigSummary: null,
projects: [],
activeProject: null,
sessions: [],
sessionsByProjectId: {},
selectedSessionId: null,
sessionStatuses: {},
sessionMessages: [],
sessionMessagesBySessionId: {},
streamingMessage: null,
streamingMessagesBySessionId: {},
streamingTools: [],
streamingToolsBySessionId: {},
sendingSessionId: null,
sendingSessionIds: {},
queuedSessionPrompts: {},
sessionDiffs: [],
sessionDiffLoading: false,
sessionDiffError: null,
fileStatuses: [],
fileSearchResults: [],
contentSearchResults: [],
selectedContextFile: null,
fileContextLoading: false,
fileContextError: null,
runtimeAutoStartAttempted: false,
loading: false,
error: null,
});
}
describe('Setup first-run progress flow', () => {
beforeEach(() => {
vi.clearAllMocks();
resetStores();
});
it('greets the authenticated user by the normalized account name', () => {
useAuthStore.setState({
user: { username: 'zhangsan@example.com', userId: 'user-1', tenantId: null, deptId: null, authorities: [] },
});
renderSetup();
expect(screen.getByRole('heading', { name: 'zhangsan欢迎回来' })).toBeInTheDocument();
});
it('renders runtime checks as a quiet progress flow without dependency details', async () => {
hostApiFetchMock.mockResolvedValue({ state: 'stopped', port: 4096 });
renderSetup();
fireEvent.click(screen.getByTestId('setup-next-button'));
expect(await screen.findByTestId('setup-runtime-progress')).toBeInTheDocument();
expect(screen.getByRole('progressbar')).toBeInTheDocument();
expect(screen.queryByText('runtime.nodejs')).not.toBeInTheDocument();
expect(screen.queryByText('runtime.opencode')).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'runtime.viewLogs' })).not.toBeInTheDocument();
});
it('shows only a retry action when runtime checks fail', async () => {
hostApiFetchMock.mockResolvedValue({
state: 'error',
error: 'missing bundled runtime package at /very/noisy/path',
});
renderSetup();
fireEvent.click(screen.getByTestId('setup-next-button'));
expect(await screen.findByTestId('setup-runtime-retry')).toBeInTheDocument();
expect(screen.queryByText(/missing bundled runtime package/)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'runtime.viewLogs' })).not.toBeInTheDocument();
});
it('keeps dependency installation focused on overall progress', async () => {
hostApiFetchMock.mockResolvedValue({ state: 'stopped', port: 4096 });
renderSetup();
fireEvent.click(screen.getByTestId('setup-next-button'));
await waitFor(() => expect(screen.getByTestId('setup-next-button')).toBeEnabled());
fireEvent.click(screen.getByTestId('setup-next-button'));
expect(await screen.findByTestId('setup-installing-progress')).toBeInTheDocument();
expect(screen.queryByText('defaultSkills.python-env.name')).not.toBeInTheDocument();
expect(screen.queryByText('defaultSkills.file-tools.name')).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'installing.skip' })).not.toBeInTheDocument();
});
});