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.
This commit is contained in:
1 parent
cb6eda0562
commit
434cba2a69
10 files changed
+671
-338
No files matched your search
@@ -0,0 +1,77 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user