Files
makelore/tests/unit/update-settings.test.tsx

98 lines
3.6 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { UpdateSettings } from '@/components/settings/UpdateSettings';
import { useUpdateStore } from '@/stores/update';
const actionableMessage =
'\u5f53\u524d\u5e73\u53f0\u7684\u6b63\u5f0f\u66f4\u65b0\u5305\u5c1a\u672a\u53d1\u5e03\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5\u3002';
vi.mock('react-i18next', async (importOriginal) => {
const actual = await importOriginal<typeof import('react-i18next')>();
return {
...actual,
useTranslation: () => ({
t: (key: string) =>
({
'updates.currentVersion': 'Current version',
'updates.status.failed': 'Generic update failure',
'updates.action.retry': 'Retry',
'updates.help': 'Keep Makelore updated',
})[key] ?? key,
}),
};
});
describe('UpdateSettings update errors', () => {
const init = vi.fn().mockResolvedValue(undefined);
const checkForUpdates = vi.fn().mockResolvedValue(undefined);
const clearError = vi.fn();
beforeEach(() => {
vi.clearAllMocks();
useUpdateStore.setState({
status: 'error',
currentVersion: '1.0.0',
updateInfo: null,
progress: null,
error: actionableMessage,
isInitialized: true,
isInitializing: false,
autoInstallCountdown: null,
init,
checkForUpdates,
clearError,
});
});
it('shows a concise updater error only once', () => {
render(<UpdateSettings />);
expect(screen.getAllByText(actionableMessage)).toHaveLength(1);
});
it.each([
'Cannot find channel "latest.yml" update info: HttpError: 404\r\nPlease double check authentication\r\n at ElectronHttpExecutor.handleResponse (app.asar/node_modules/builder-util-runtime/out/httpExecutor.js:121:20)',
'Cannot find channel "latest.yml" update info: HttpError: 404\\r\\nPlease double check authentication\\n at ElectronHttpExecutor.handleResponse (app.asar/node_modules/builder-util-runtime/out/httpExecutor.js:121:20)',
])('does not expose updater stack details for a long technical error', (error) => {
useUpdateStore.setState({ error });
render(<UpdateSettings />);
expect(screen.getByText('Generic update failure')).toBeInTheDocument();
expect(screen.queryByText(/ElectronHttpExecutor|node_modules|Please double check/)).not.toBeInTheDocument();
expect(screen.queryByText('updates.errorDetails')).not.toBeInTheDocument();
});
it.each([
'net::ERR_NAME_NOT_RESOLVED',
'Error: Update check failed',
'Update check temporarily unavailable',
"ENOENT: no such file or directory, open 'C:\\Users\\tester\\AppData\\Local\\Makelore\\latest.yml'",
'ERR_UPDATER_INVALID_RELEASE_FEED',
'{"code":"ERR_UPDATER_INVALID_RELEASE_FEED","message":"Update check failed"}',
])('falls back for a short technical updater diagnostic: %s', (error) => {
useUpdateStore.setState({ error });
render(<UpdateSettings />);
expect(screen.getByText('Generic update failure')).toBeInTheDocument();
expect(screen.queryByText(error)).not.toBeInTheDocument();
});
it('keeps concise actionable Chinese prose', () => {
render(<UpdateSettings />);
expect(screen.getByText(actionableMessage)).toBeInTheDocument();
});
it('initializes on mount and retries through the existing store action', async () => {
render(<UpdateSettings />);
await waitFor(() => expect(init).toHaveBeenCalledTimes(1));
fireEvent.click(screen.getByRole('button', { name: 'Retry' }));
await waitFor(() => expect(checkForUpdates).toHaveBeenCalledTimes(1));
expect(clearError).toHaveBeenCalledTimes(1);
});
});