import { describe, expect, test } from 'bun:test'; import { getDesktopRecoveryConfig } from './desktopRecoveryConfig'; describe('getDesktopRecoveryConfig', () => { // --------------------------------------------------------------------------- // 1. local-unavailable: both actions visible + retry labeled "Retry Local" // --------------------------------------------------------------------------- test('local-unavailable exposes both actions and Retry Local', () => { const config = getDesktopRecoveryConfig('local-unavailable'); expect(config.title).toBe('Local OpenCode Unavailable'); expect(config.iconKey).toBe('local'); expect(config.showRetry).toBe(true); expect(config.retryLabel).toBe('Retry Local'); expect(config.showUseLocal).toBe(true); expect(config.showUseRemote).toBe(true); // local-unavailable uses setup-oriented label since local needs installing expect(config.useLocalLabel).toBe('Set Up Local'); expect(config.useRemoteLabel).toBe('Use Remote'); }); // --------------------------------------------------------------------------- // 2. remote-unreachable: both actions + retry // --------------------------------------------------------------------------- test('remote-unreachable exposes both actions + retry', () => { const config = getDesktopRecoveryConfig( 'remote-unreachable', 'My Server', 'https://example.com:4096', ); expect(config.title).toBe('Remote Server Unreachable'); expect(config.iconKey).toBe('remote'); expect(config.showRetry).toBe(true); expect(config.retryLabel).toBe('Retry Connection'); expect(config.showUseLocal).toBe(true); expect(config.showUseRemote).toBe(true); // remote variants keep standard "Use Local" expect(config.useLocalLabel).toBe('Use Local'); expect(config.useRemoteLabel).toBe('Use Remote'); }); // --------------------------------------------------------------------------- // 3. remote-wrong-service: both actions, NO retry // --------------------------------------------------------------------------- test('remote-wrong-service exposes both actions and no retry', () => { const config = getDesktopRecoveryConfig( 'remote-wrong-service', 'Bad Host', 'https://wrong.example.com', ); expect(config.title).toBe('Incompatible Server'); expect(config.iconKey).toBe('remote'); expect(config.showRetry).toBe(false); expect(config.retryLabel).toBe(undefined); expect(config.showUseLocal).toBe(true); expect(config.showUseRemote).toBe(true); expect(config.useLocalLabel).toBe('Use Local'); expect(config.useRemoteLabel).toBe('Use Remote'); }); test('remote-incompatible exposes retry and both actions', () => { const config = getDesktopRecoveryConfig('remote-incompatible', 'Old Server', 'https://old.example'); expect(config.showRetry).toBe(true); expect(config.showUseLocal).toBe(true); expect(config.showUseRemote).toBe(true); expect(config.titleKey).toBe('onboarding.desktopRecovery.remoteIncompatible.title'); }); // --------------------------------------------------------------------------- // 4. missing-default-host: chooser-with-context (both actions, no retry) // --------------------------------------------------------------------------- test('missing-default-host behaves like chooser-with-context', () => { const config = getDesktopRecoveryConfig('missing-default-host'); expect(config.title).toBe('No Default Connection'); expect(config.iconKey).toBe('local'); expect(config.showRetry).toBe(false); expect(config.retryLabel).toBe(undefined); expect(config.showUseLocal).toBe(true); expect(config.showUseRemote).toBe(true); expect(config.useLocalLabel).toBe('Use Local'); expect(config.useRemoteLabel).toBe('Use Remote'); }); // --------------------------------------------------------------------------- // 5. descriptions redact sensitive query params for remote variants // --------------------------------------------------------------------------- test('remote-unreachable description redacts sensitive query params in URL', () => { const sensitiveUrl = 'https://example.com:4096?token=super-secret&auth=abc123'; const config = getDesktopRecoveryConfig( 'remote-unreachable', undefined, sensitiveUrl, ); // Secrets must never appear in the description expect(config.description).not.toContain('super-secret'); expect(config.description).not.toContain('abc123'); // Redaction marker is present expect(config.description).toContain('REDACTED'); expect(config.description).toContain('example.com'); }); test('remote-wrong-service description redacts sensitive query params in URL', () => { const sensitiveUrl = 'https://wrong.example.com?api_key=sk-12345&secret=mysecret'; const config = getDesktopRecoveryConfig( 'remote-wrong-service', undefined, sensitiveUrl, ); // Secrets must never appear in the description expect(config.description).not.toContain('sk-12345'); expect(config.description).not.toContain('mysecret'); // Redaction marker is present expect(config.description).toContain('REDACTED'); expect(config.description).toContain('wrong.example.com'); }); test('local-unavailable description does not reference host URL', () => { const config = getDesktopRecoveryConfig( 'local-unavailable', 'Some Host', 'https://example.com?token=secret', ); // local-unavailable ignores hostUrl in its description expect(config.description).not.toContain('example.com'); expect(config.description).not.toContain('secret'); }); test('missing-default-host description does not reference host URL', () => { const config = getDesktopRecoveryConfig( 'missing-default-host', 'Some Host', 'https://example.com?token=secret', ); expect(config.description).not.toContain('example.com'); expect(config.description).not.toContain('secret'); }); // --------------------------------------------------------------------------- // 6. URL-like hostLabel is also redacted (sensitive data leak prevention) // --------------------------------------------------------------------------- test('remote-unreachable redacts URL-like hostLabel containing sensitive query params', () => { const urlAsLabel = 'https://example.com:4096?token=super-secret&auth=abc123'; const config = getDesktopRecoveryConfig( 'remote-unreachable', urlAsLabel, 'https://fallback.example.com', ); // Secrets in hostLabel must never appear in the description expect(config.description).not.toContain('super-secret'); expect(config.description).not.toContain('abc123'); // Redaction marker is present expect(config.description).toContain('REDACTED'); expect(config.description).toContain('example.com'); }); test('remote-wrong-service redacts URL-like hostLabel containing sensitive query params', () => { const urlAsLabel = 'https://wrong.example.com?api_key=sk-12345&secret=mysecret'; const config = getDesktopRecoveryConfig( 'remote-wrong-service', urlAsLabel, 'https://fallback.example.com', ); // Secrets in hostLabel must never appear in the description expect(config.description).not.toContain('sk-12345'); expect(config.description).not.toContain('mysecret'); // Redaction marker is present expect(config.description).toContain('REDACTED'); expect(config.description).toContain('wrong.example.com'); }); test('remote-unreachable redacts embedded credentials in URL-like hostLabel', () => { const urlWithCreds = 'https://admin:s3cret@example.com:4096'; const config = getDesktopRecoveryConfig( 'remote-unreachable', urlWithCreds, 'https://fallback.example.com', ); // Username/password must never appear in the description expect(config.description).not.toContain('admin'); expect(config.description).not.toContain('s3cret'); // Hostname should still be visible expect(config.description).toContain('example.com'); }); test('remote-wrong-service redacts embedded credentials in URL-like hostLabel', () => { const urlWithCreds = 'https://user:pass123@wrong.example.com'; const config = getDesktopRecoveryConfig( 'remote-wrong-service', urlWithCreds, 'https://fallback.example.com', ); expect(config.description).not.toContain('user'); expect(config.description).not.toContain('pass123'); expect(config.description).toContain('wrong.example.com'); }); test('non-URL hostLabel is used as-is without redaction', () => { const config = getDesktopRecoveryConfig( 'remote-unreachable', 'My Server', 'https://example.com?token=secret', ); // Plain label should appear verbatim expect(config.description).toContain('My Server'); // hostUrl secrets should not leak (already tested above, but sanity check) expect(config.description).not.toContain('secret'); }); // --------------------------------------------------------------------------- // Fallback descriptions when no host info is provided // --------------------------------------------------------------------------- test('remote-unreachable falls back to generic text when no host info', () => { const config = getDesktopRecoveryConfig('remote-unreachable'); expect(config.description).toContain('the remote server'); expect(config.description).not.toContain('undefined'); }); test('remote-wrong-service falls back to generic text when no host info', () => { const config = getDesktopRecoveryConfig('remote-wrong-service'); expect(config.description).toContain('unknown'); }); // --------------------------------------------------------------------------- // Whitespace-only hostLabel is treated as absent // --------------------------------------------------------------------------- test('whitespace-only hostLabel falls back to hostUrl', () => { const config = getDesktopRecoveryConfig( 'remote-unreachable', ' ', 'https://fallback.example.com?token=secret', ); // hostLabel is whitespace-only → should use redacted hostUrl instead expect(config.description).not.toContain('secret'); expect(config.description).toContain('fallback.example.com'); expect(config.description).toContain('REDACTED'); }); });