// Tests for Web Bluetooth browser compatibility utilities import { detectBrowser, checkWebBluetoothSupport, getUnsupportedBrowserMessage, isWebPlatform, hasWebBluetooth, SUPPORTED_BROWSERS, BROWSER_HELP_URLS, } from '../webBluetooth'; describe('webBluetooth utilities', () => { // Store original navigator and window const originalNavigator = global.navigator; const originalWindow = global.window; afterEach(() => { // Restore originals Object.defineProperty(global, 'navigator', { value: originalNavigator, writable: true, configurable: true, }); Object.defineProperty(global, 'window', { value: originalWindow, writable: true, configurable: true, }); }); describe('detectBrowser', () => { it('should detect Chrome', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', }, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Chrome'); expect(browser.version).toBe('120'); }); it('should detect Safari', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15', }, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Safari'); expect(browser.version).toBe('17'); }); it('should detect Firefox', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0', }, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Firefox'); expect(browser.version).toBe('122'); }); it('should detect Edge', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', }, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Edge'); expect(browser.version).toBe('120'); }); it('should detect Opera', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0', }, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Opera'); expect(browser.version).toBe('106'); }); it('should detect Samsung Internet', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36', }, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Samsung Internet'); expect(browser.version).toBe('23'); }); it('should return Unknown for undefined navigator', () => { Object.defineProperty(global, 'navigator', { value: undefined, writable: true, configurable: true, }); const browser = detectBrowser(); expect(browser.name).toBe('Unknown'); expect(browser.version).toBe('0'); }); }); describe('checkWebBluetoothSupport', () => { it('should return supported for Chrome with Web Bluetooth', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 Chrome/120.0.0.0', bluetooth: {}, }, writable: true, configurable: true, }); Object.defineProperty(global, 'window', { value: { isSecureContext: true }, writable: true, configurable: true, }); const support = checkWebBluetoothSupport(); expect(support.supported).toBe(true); expect(support.browserName).toBe('Chrome'); }); it('should return unsupported for Safari', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X) Safari/605.1.15 Version/17.0', }, writable: true, configurable: true, }); Object.defineProperty(global, 'window', { value: { isSecureContext: true }, writable: true, configurable: true, }); const support = checkWebBluetoothSupport(); expect(support.supported).toBe(false); expect(support.browserName).toBe('Safari'); expect(support.reason).toBe('unsupported_browser'); }); it('should return unsupported for Firefox', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 Firefox/122.0', }, writable: true, configurable: true, }); Object.defineProperty(global, 'window', { value: { isSecureContext: true }, writable: true, configurable: true, }); const support = checkWebBluetoothSupport(); expect(support.supported).toBe(false); expect(support.browserName).toBe('Firefox'); expect(support.reason).toBe('unsupported_browser'); }); it('should return unsupported for insecure context', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 Chrome/120.0.0.0', bluetooth: {}, }, writable: true, configurable: true, }); Object.defineProperty(global, 'window', { value: { isSecureContext: false }, writable: true, configurable: true, }); const support = checkWebBluetoothSupport(); expect(support.supported).toBe(false); expect(support.reason).toBe('insecure_context'); }); it('should return api_unavailable for Chrome without bluetooth API', () => { Object.defineProperty(global, 'navigator', { value: { userAgent: 'Mozilla/5.0 Chrome/120.0.0.0', // No bluetooth property }, writable: true, configurable: true, }); Object.defineProperty(global, 'window', { value: { isSecureContext: true }, writable: true, configurable: true, }); const support = checkWebBluetoothSupport(); expect(support.supported).toBe(false); expect(support.reason).toBe('api_unavailable'); }); }); describe('getUnsupportedBrowserMessage', () => { it('should return correct message for unsupported browser', () => { const support = { supported: false, browserName: 'Safari', browserVersion: '17', reason: 'unsupported_browser' as const, }; const message = getUnsupportedBrowserMessage(support); expect(message.title).toBe('Browser Not Supported'); expect(message.message).toContain('Safari'); expect(message.suggestion).toContain('Chrome'); }); it('should return correct message for insecure context', () => { const support = { supported: false, browserName: 'Chrome', browserVersion: '120', reason: 'insecure_context' as const, }; const message = getUnsupportedBrowserMessage(support); expect(message.title).toBe('Secure Connection Required'); expect(message.message).toContain('HTTPS'); }); it('should return correct message for api unavailable', () => { const support = { supported: false, browserName: 'Chrome', browserVersion: '120', reason: 'api_unavailable' as const, }; const message = getUnsupportedBrowserMessage(support); expect(message.title).toBe('Bluetooth Not Available'); }); }); describe('isWebPlatform', () => { it('should return true when window and document exist', () => { Object.defineProperty(global, 'window', { value: {}, writable: true, configurable: true, }); Object.defineProperty(global, 'document', { value: {}, writable: true, configurable: true, }); expect(isWebPlatform()).toBe(true); }); it('should return false when window is undefined', () => { Object.defineProperty(global, 'window', { value: undefined, writable: true, configurable: true, }); expect(isWebPlatform()).toBe(false); }); }); describe('hasWebBluetooth', () => { it('should return true when navigator.bluetooth exists', () => { Object.defineProperty(global, 'navigator', { value: { bluetooth: {} }, writable: true, configurable: true, }); expect(hasWebBluetooth()).toBe(true); }); it('should return false when navigator.bluetooth does not exist', () => { Object.defineProperty(global, 'navigator', { value: {}, writable: true, configurable: true, }); expect(hasWebBluetooth()).toBe(false); }); }); describe('constants', () => { it('should have supported browsers list', () => { expect(SUPPORTED_BROWSERS).toContain('Chrome'); expect(SUPPORTED_BROWSERS).toContain('Edge'); expect(SUPPORTED_BROWSERS).toContain('Opera'); expect(SUPPORTED_BROWSERS).not.toContain('Safari'); expect(SUPPORTED_BROWSERS).not.toContain('Firefox'); }); it('should have browser help URLs', () => { expect(BROWSER_HELP_URLS.Chrome).toContain('google.com/chrome'); expect(BROWSER_HELP_URLS.Edge).toContain('microsoft.com'); expect(BROWSER_HELP_URLS.Opera).toContain('opera.com'); }); }); });