import { normalizeCameraUrl, readWeekCamera } from './week-camera'; describe('week camera settings', () => { it('accepts a room scene link without a view ID', () => { const url = new URL(normalizeCameraUrl('https://vdo.ninja/?scene=0&room=Alex_12345&password=xxxx')); expect(url.searchParams.get('scene')).toBe('0'); expect(url.searchParams.get('room')).toBe('Alex_12345'); expect(url.searchParams.get('password')).toBe('xxxx'); expect(url.searchParams.has('view')).toBe(false); }); it('keeps only viewing parameters', () => { const url = new URL(normalizeCameraUrl('https://vdo.ninja/?room=track&view=camera&push=bad&director=bad&password=secret')); expect(url.searchParams.get('room')).toBe('track'); expect(url.searchParams.get('view')).toBe('camera'); expect(url.searchParams.has('scene')).toBe(true); expect(url.searchParams.has('push')).toBe(false); expect(url.searchParams.has('director')).toBe(false); expect(url.searchParams.get('password')).toBe('secret'); }); it.each(['http://vdo.ninja/?room=x&view=y', 'https://example.com/?room=x&view=y', 'https://vdo.ninja/?room=x', 'javascript:alert(1)', 'https://vdo.ninja:8443/?room=x&view=y'])('rejects unsafe or incomplete URL %s', (url) => { expect(() => normalizeCameraUrl(url)).toThrow(); }); it('supports unset camera settings and preserves password whitespace', () => { expect(normalizeCameraUrl(' ')).toBe(''); expect(readWeekCamera(null)).toEqual({ url: '' }); const legacy = readWeekCamera({ cameraViewUrl: 'https://vdo.ninja/?room=x&view=y', cameraPassword: ' a&b ' }); expect(new URL(legacy.url).searchParams.get('password')).toBe(' a&b '); }); it('preserves encoded passwords and prefers the link over legacy settings', () => { const url = normalizeCameraUrl('https://vdo.ninja/?room=x&view=y&password=%20a%26b%2B%23%20'); expect(new URL(url).searchParams.get('password')).toBe(' a&b+# '); expect(readWeekCamera({ cameraViewUrl: url, cameraPassword: 'old' })).toEqual({ url }); }); });