Files
LocalMind/__tests__/utils.test.ts
T
evandro 434cba2a69 refactor(settings): split SettingsScreen into section components and pure helpers
SettingsScreen CC 23 -> below 10. Form parsing, change detection and the dark-theme check moved to utils/ with unit tests; the dark switch now reads the OS scheme instead of comparing the background colour. Adds characterization tests for the screen.
2026-10-10 04:18:40 -03:00

78 lines
3.1 KiB
TypeScript

import { ChatMessage } from '../store/useAppStore';
import { findLastAssistantId, shouldShowTypingIndicator } from '../utils/chatSelectors';
import { buildServerConfig, isConfigChanged } from '../utils/serverConfig';
import { isDarkTheme } from '../utils/theme';
const msg = (id: string, role: ChatMessage['role'], content = 'x'): ChatMessage => ({
id,
role,
content,
timestamp: 0,
});
describe('findLastAssistantId', () => {
it('returns the most recent assistant message', () => {
expect(findLastAssistantId([msg('1', 'assistant'), msg('2', 'user'), msg('3', 'assistant')])).toBe('3');
});
it('returns null when there is no assistant message', () => {
expect(findLastAssistantId([msg('1', 'user')])).toBeNull();
expect(findLastAssistantId([])).toBeNull();
});
});
describe('shouldShowTypingIndicator', () => {
it('is true only while streaming an assistant message with no text yet', () => {
expect(shouldShowTypingIndicator([msg('1', 'user'), msg('2', 'assistant', '')], true)).toBe(true);
});
it('is false when not streaming, when text arrived, when the last message is the user, or when empty', () => {
expect(shouldShowTypingIndicator([msg('2', 'assistant', '')], false)).toBe(false);
expect(shouldShowTypingIndicator([msg('2', 'assistant', 'hi')], true)).toBe(false);
expect(shouldShowTypingIndicator([msg('1', 'user', '')], true)).toBe(false);
expect(shouldShowTypingIndicator([], true)).toBe(false);
});
});
describe('buildServerConfig', () => {
it('trims the host and API key and parses the port', () => {
expect(buildServerConfig({ host: ' 10.0.0.1 ', port: '8080', apiKey: ' k ' })).toEqual({
host: '10.0.0.1',
port: 8080,
apiKey: 'k',
});
});
it('uses the defaults for blank host, invalid port and blank key', () => {
expect(buildServerConfig({ host: '', port: 'abc', apiKey: ' ' })).toEqual({
host: 'localhost',
port: 1234,
apiKey: undefined,
});
});
});
describe('isConfigChanged', () => {
const saved = { host: 'lan', port: 1234, apiKey: 'k' };
it('is false when the form matches the saved config', () => {
expect(isConfigChanged({ host: 'lan', port: '1234', apiKey: 'k' }, saved)).toBe(false);
expect(isConfigChanged({ host: 'lan', port: '1234', apiKey: '' }, { host: 'lan', port: 1234 })).toBe(false);
});
it('is true when any single field differs', () => {
expect(isConfigChanged({ host: 'other', port: '1234', apiKey: 'k' }, saved)).toBe(true);
expect(isConfigChanged({ host: 'lan', port: '99', apiKey: 'k' }, saved)).toBe(true);
expect(isConfigChanged({ host: 'lan', port: '1234', apiKey: '' }, saved)).toBe(true);
});
});
describe('isDarkTheme', () => {
it('honours an explicit preference and falls back to the system scheme', () => {
expect(isDarkTheme('dark', 'light')).toBe(true);
expect(isDarkTheme('light', 'dark')).toBe(false);
expect(isDarkTheme('system', 'dark')).toBe(true);
expect(isDarkTheme('system', 'light')).toBe(false);
});
});