Skip to content

Commit 1546229

Browse files
committed
CU-868f46emq Working on getting Bluetooth on Android working.
1 parent 8042e72 commit 1546229

File tree

6 files changed

+639
-23
lines changed

6 files changed

+639
-23
lines changed
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// This is a simplified test that focuses on the logic without UI rendering
2+
import { bluetoothAudioService } from '@/services/bluetooth-audio.service';
3+
4+
// Mock the bluetooth audio service
5+
jest.mock('@/services/bluetooth-audio.service', () => ({
6+
bluetoothAudioService: {
7+
startScanning: jest.fn(),
8+
stopScanning: jest.fn(),
9+
connectToDevice: jest.fn(),
10+
disconnectDevice: jest.fn(),
11+
},
12+
}));
13+
14+
// Mock the hook
15+
const mockSetPreferredDevice = jest.fn();
16+
jest.mock('@/lib/hooks/use-preferred-bluetooth-device', () => ({
17+
usePreferredBluetoothDevice: () => ({
18+
preferredDevice: null,
19+
setPreferredDevice: mockSetPreferredDevice,
20+
}),
21+
}));
22+
23+
describe('BluetoothDeviceSelectionBottomSheet Device Selection Logic', () => {
24+
beforeEach(() => {
25+
jest.clearAllMocks();
26+
});
27+
28+
describe('handleDeviceSelect function behavior', () => {
29+
it('should clear preferred device first, then disconnect, then set new device and connect', async () => {
30+
// Simulate the handleDeviceSelect logic directly
31+
const mockDevice = {
32+
id: 'test-device-1',
33+
name: 'Test Headset',
34+
rssi: -50,
35+
isConnected: false,
36+
hasAudioCapability: true,
37+
supportsMicrophoneControl: true,
38+
device: {} as any,
39+
};
40+
41+
const mockConnectedDevice = {
42+
id: 'current-device',
43+
name: 'Current Device',
44+
rssi: -40,
45+
isConnected: true,
46+
hasAudioCapability: true,
47+
supportsMicrophoneControl: true,
48+
device: {} as any,
49+
};
50+
51+
// Simulate the handleDeviceSelect function logic
52+
await mockSetPreferredDevice(null);
53+
54+
if (mockConnectedDevice) {
55+
await bluetoothAudioService.disconnectDevice();
56+
}
57+
58+
const selectedDevice = {
59+
id: mockDevice.id,
60+
name: mockDevice.name || 'Unknown Device',
61+
};
62+
63+
await mockSetPreferredDevice(selectedDevice);
64+
await bluetoothAudioService.connectToDevice(mockDevice.id);
65+
66+
// Verify the order of operations
67+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(1, null);
68+
expect(bluetoothAudioService.disconnectDevice).toHaveBeenCalled();
69+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(2, {
70+
id: 'test-device-1',
71+
name: 'Test Headset',
72+
});
73+
expect(bluetoothAudioService.connectToDevice).toHaveBeenCalledWith('test-device-1');
74+
});
75+
76+
it('should handle disconnect failure gracefully and continue with new connection', async () => {
77+
// Make disconnect fail
78+
(bluetoothAudioService.disconnectDevice as jest.Mock).mockRejectedValue(new Error('Disconnect failed'));
79+
80+
const mockDevice = {
81+
id: 'test-device-1',
82+
name: 'Test Headset',
83+
rssi: -50,
84+
isConnected: false,
85+
hasAudioCapability: true,
86+
supportsMicrophoneControl: true,
87+
device: {} as any,
88+
};
89+
90+
const mockConnectedDevice = {
91+
id: 'current-device',
92+
name: 'Current Device',
93+
rssi: -40,
94+
isConnected: true,
95+
hasAudioCapability: true,
96+
supportsMicrophoneControl: true,
97+
device: {} as any,
98+
};
99+
100+
// Simulate the handleDeviceSelect function logic with error handling
101+
try {
102+
await mockSetPreferredDevice(null);
103+
104+
if (mockConnectedDevice) {
105+
try {
106+
await bluetoothAudioService.disconnectDevice();
107+
} catch (disconnectError) {
108+
// Should continue even if disconnect fails
109+
}
110+
}
111+
112+
const selectedDevice = {
113+
id: mockDevice.id,
114+
name: mockDevice.name || 'Unknown Device',
115+
};
116+
117+
await mockSetPreferredDevice(selectedDevice);
118+
await bluetoothAudioService.connectToDevice(mockDevice.id);
119+
} catch (error) {
120+
// Should not throw
121+
}
122+
123+
// Verify operations still executed despite disconnect failure
124+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(1, null);
125+
expect(bluetoothAudioService.disconnectDevice).toHaveBeenCalled();
126+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(2, {
127+
id: 'test-device-1',
128+
name: 'Test Headset',
129+
});
130+
expect(bluetoothAudioService.connectToDevice).toHaveBeenCalledWith('test-device-1');
131+
});
132+
133+
it('should skip disconnect when no device is currently connected', async () => {
134+
const mockDevice = {
135+
id: 'test-device-1',
136+
name: 'Test Headset',
137+
rssi: -50,
138+
isConnected: false,
139+
hasAudioCapability: true,
140+
supportsMicrophoneControl: true,
141+
device: {} as any,
142+
};
143+
144+
const mockConnectedDevice = null;
145+
146+
// Simulate the handleDeviceSelect function logic
147+
await mockSetPreferredDevice(null);
148+
149+
if (mockConnectedDevice) {
150+
await bluetoothAudioService.disconnectDevice();
151+
}
152+
153+
const selectedDevice = {
154+
id: mockDevice.id,
155+
name: mockDevice.name || 'Unknown Device',
156+
};
157+
158+
await mockSetPreferredDevice(selectedDevice);
159+
await bluetoothAudioService.connectToDevice(mockDevice.id);
160+
161+
// Verify disconnect was not called since no device was connected
162+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(1, null);
163+
expect(bluetoothAudioService.disconnectDevice).not.toHaveBeenCalled();
164+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(2, {
165+
id: 'test-device-1',
166+
name: 'Test Headset',
167+
});
168+
expect(bluetoothAudioService.connectToDevice).toHaveBeenCalledWith('test-device-1');
169+
});
170+
171+
it('should handle connection failure gracefully', async () => {
172+
// Make connect fail
173+
(bluetoothAudioService.connectToDevice as jest.Mock).mockRejectedValue(new Error('Connection failed'));
174+
175+
const mockDevice = {
176+
id: 'test-device-1',
177+
name: 'Test Headset',
178+
rssi: -50,
179+
isConnected: false,
180+
hasAudioCapability: true,
181+
supportsMicrophoneControl: true,
182+
device: {} as any,
183+
};
184+
185+
const mockConnectedDevice = null;
186+
187+
// Simulate the handleDeviceSelect function logic with error handling
188+
try {
189+
await mockSetPreferredDevice(null);
190+
191+
if (mockConnectedDevice) {
192+
try {
193+
await bluetoothAudioService.disconnectDevice();
194+
} catch (disconnectError) {
195+
// Continue even if disconnect fails
196+
}
197+
}
198+
199+
const selectedDevice = {
200+
id: mockDevice.id,
201+
name: mockDevice.name || 'Unknown Device',
202+
};
203+
204+
await mockSetPreferredDevice(selectedDevice);
205+
206+
try {
207+
await bluetoothAudioService.connectToDevice(mockDevice.id);
208+
} catch (connectionError) {
209+
// Should not prevent setting the preferred device
210+
}
211+
} catch (error) {
212+
// Should not throw
213+
}
214+
215+
// Verify preferred device was still set despite connection failure
216+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(1, null);
217+
expect(mockSetPreferredDevice).toHaveBeenNthCalledWith(2, {
218+
id: 'test-device-1',
219+
name: 'Test Headset',
220+
});
221+
expect(bluetoothAudioService.connectToDevice).toHaveBeenCalledWith('test-device-1');
222+
});
223+
});
224+
});

0 commit comments

Comments
 (0)