| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.settings.bluetooth; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Matchers.anyBoolean; |
| import static org.mockito.Matchers.anyInt; |
| import static org.mockito.Mockito.doNothing; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.spy; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| |
| import android.bluetooth.BluetoothAdapter; |
| import android.content.Context; |
| import android.content.res.Resources; |
| |
| import androidx.preference.PreferenceGroup; |
| |
| import com.android.settings.R; |
| import com.android.settings.testutils.SettingsRobolectricTestRunner; |
| import com.android.settingslib.bluetooth.BluetoothDeviceFilter; |
| import com.android.settingslib.bluetooth.LocalBluetoothAdapter; |
| import com.android.settingslib.bluetooth.LocalBluetoothManager; |
| import com.android.settingslib.widget.FooterPreference; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.Answers; |
| import org.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| import org.robolectric.RuntimeEnvironment; |
| |
| @RunWith(SettingsRobolectricTestRunner.class) |
| public class BluetoothPairingDetailTest { |
| |
| @Mock |
| private Resources mResource; |
| @Mock |
| private LocalBluetoothAdapter mLocalAdapter; |
| @Mock(answer = Answers.RETURNS_DEEP_STUBS) |
| private LocalBluetoothManager mLocalManager; |
| @Mock |
| private PreferenceGroup mPreferenceGroup; |
| private BluetoothPairingDetail mFragment; |
| private Context mContext; |
| private BluetoothProgressCategory mAvailableDevicesCategory; |
| private FooterPreference mFooterPreference; |
| |
| @Before |
| public void setUp() { |
| MockitoAnnotations.initMocks(this); |
| |
| mContext = RuntimeEnvironment.application; |
| mFragment = spy(new BluetoothPairingDetail()); |
| doReturn(mContext).when(mFragment).getContext(); |
| doReturn(mResource).when(mFragment).getResources(); |
| |
| mAvailableDevicesCategory = spy(new BluetoothProgressCategory(mContext)); |
| mFooterPreference = new FooterPreference(mContext); |
| |
| mFragment.mLocalAdapter = mLocalAdapter; |
| mFragment.mLocalManager = mLocalManager; |
| mFragment.mDeviceListGroup = mPreferenceGroup; |
| mFragment.mAlwaysDiscoverable = new AlwaysDiscoverable(mContext, mLocalAdapter); |
| } |
| |
| @Test |
| public void testInitPreferencesFromPreferenceScreen_findPreferences() { |
| doReturn(mAvailableDevicesCategory).when(mFragment) |
| .findPreference(BluetoothPairingDetail.KEY_AVAIL_DEVICES); |
| doReturn(mFooterPreference).when(mFragment) |
| .findPreference(BluetoothPairingDetail.KEY_FOOTER_PREF); |
| |
| mFragment.initPreferencesFromPreferenceScreen(); |
| |
| assertThat(mFragment.mAvailableDevicesCategory).isEqualTo(mAvailableDevicesCategory); |
| assertThat(mFragment.mFooterPreference).isEqualTo(mFooterPreference); |
| } |
| |
| @Test |
| public void testStartScanning_startScanAndRemoveDevices() { |
| mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory; |
| mFragment.mDeviceListGroup = mAvailableDevicesCategory; |
| |
| mFragment.enableScanning(); |
| |
| verify(mLocalAdapter).startScanning(true); |
| verify(mAvailableDevicesCategory).removeAll(); |
| } |
| |
| @Test |
| public void testUpdateContent_stateOn_addDevices() { |
| mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory; |
| mFragment.mFooterPreference = mFooterPreference; |
| doNothing().when(mFragment).addDeviceCategory(any(), anyInt(), any(), anyBoolean()); |
| |
| mFragment.updateContent(BluetoothAdapter.STATE_ON); |
| |
| verify(mFragment).addDeviceCategory(mAvailableDevicesCategory, |
| R.string.bluetooth_preference_found_media_devices, |
| BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, false); |
| verify(mLocalAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); |
| } |
| |
| @Test |
| public void testUpdateContent_stateOff_finish() { |
| mFragment.updateContent(BluetoothAdapter.STATE_OFF); |
| |
| verify(mFragment).finish(); |
| } |
| |
| @Test |
| public void testUpdateBluetooth_bluetoothOff_turnOnBluetooth() { |
| doReturn(false).when(mLocalAdapter).isEnabled(); |
| |
| mFragment.updateBluetooth(); |
| |
| verify(mLocalAdapter).enable(); |
| } |
| |
| @Test |
| public void testUpdateBluetooth_bluetoothOn_updateState() { |
| doReturn(true).when(mLocalAdapter).isEnabled(); |
| doNothing().when(mFragment).updateContent(anyInt()); |
| |
| mFragment.updateBluetooth(); |
| |
| verify(mFragment).updateContent(anyInt()); |
| } |
| |
| @Test |
| public void testOnScanningStateChanged_restartScanAfterInitialScanning() { |
| mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory; |
| mFragment.mFooterPreference = mFooterPreference; |
| mFragment.mDeviceListGroup = mAvailableDevicesCategory; |
| doNothing().when(mFragment).addDeviceCategory(any(), anyInt(), any(), anyBoolean()); |
| |
| // Initial Bluetooth ON will trigger scan enable, list clear and scan start |
| mFragment.updateContent(BluetoothAdapter.STATE_ON); |
| verify(mFragment).enableScanning(); |
| assertThat(mAvailableDevicesCategory.getPreferenceCount()).isEqualTo(0); |
| verify(mLocalAdapter).startScanning(true); |
| |
| // Subsequent scan started event will not trigger start/stop nor list clear |
| mFragment.onScanningStateChanged(true); |
| verify(mLocalAdapter, times(1)).startScanning(anyBoolean()); |
| verify(mAvailableDevicesCategory, times(1)).setProgress(true); |
| |
| // Subsequent scan finished event will trigger scan start without list clean |
| mFragment.onScanningStateChanged(false); |
| verify(mLocalAdapter, times(2)).startScanning(true); |
| verify(mAvailableDevicesCategory, times(2)).setProgress(true); |
| |
| // Subsequent scan started event will not trigger any change |
| mFragment.onScanningStateChanged(true); |
| verify(mLocalAdapter, times(2)).startScanning(anyBoolean()); |
| verify(mAvailableDevicesCategory, times(3)).setProgress(true); |
| verify(mLocalAdapter, never()).stopScanning(); |
| |
| // Disable scanning will trigger scan stop |
| mFragment.disableScanning(); |
| verify(mLocalAdapter, times(1)).stopScanning(); |
| |
| // Subsequent scan start event will not trigger any change besides progress circle |
| mFragment.onScanningStateChanged(true); |
| verify(mAvailableDevicesCategory, times(4)).setProgress(true); |
| |
| // However, subsequent scan finished event won't trigger new scan start and will stop |
| // progress circle from spinning |
| mFragment.onScanningStateChanged(false); |
| verify(mAvailableDevicesCategory, times(1)).setProgress(false); |
| verify(mLocalAdapter, times(2)).startScanning(anyBoolean()); |
| verify(mLocalAdapter, times(1)).stopScanning(); |
| |
| // Verify that clean up only happen once at initialization |
| verify(mAvailableDevicesCategory, times(1)).removeAll(); |
| } |
| } |