152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei/*
252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * Copyright (C) 2017 The Android Open Source Project
352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei *
452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * Licensed under the Apache License, Version 2.0 (the "License");
552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * you may not use this file except in compliance with the License.
652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * You may obtain a copy of the License at
752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei *
852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei *      http://www.apache.org/licenses/LICENSE-2.0
952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei *
1052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * Unless required by applicable law or agreed to in writing, software
1152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * distributed under the License is distributed on an "AS IS" BASIS,
1252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * See the License for the specific language governing permissions and
1452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei * limitations under the License.
1552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei */
1652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
1752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleipackage com.android.settings.bluetooth;
1852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
1952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static com.google.common.truth.Truth.assertThat;
2052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
2152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Matchers.any;
2252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Matchers.anyBoolean;
2352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Matchers.anyInt;
2452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Mockito.doNothing;
2552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Mockito.doReturn;
26c11af01481dd7fb4515e681128340724f2008dc0Jack Heimport static org.mockito.Mockito.never;
2752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Mockito.spy;
28c11af01481dd7fb4515e681128340724f2008dc0Jack Heimport static org.mockito.Mockito.times;
2952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport static org.mockito.Mockito.verify;
3052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
3152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport android.bluetooth.BluetoothAdapter;
3252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport android.content.Context;
3352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport android.content.res.Resources;
3452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport android.os.UserManager;
3552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport android.support.v7.preference.PreferenceGroup;
3652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
3752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport com.android.settings.R;
389f1e911759dc6fedaac9fa65afb79f6a93022bf4Andrew Sappersteinimport com.android.settings.testutils.SettingsRobolectricTestRunner;
3952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport com.android.settings.TestConfig;
4052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport com.android.settingslib.bluetooth.BluetoothDeviceFilter;
4152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport com.android.settingslib.bluetooth.LocalBluetoothAdapter;
4252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport com.android.settingslib.bluetooth.LocalBluetoothManager;
4352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport com.android.settingslib.widget.FooterPreference;
4452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
4552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.junit.Before;
4652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.junit.Test;
4752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.junit.runner.RunWith;
4852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.mockito.Answers;
4952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.mockito.Mock;
5052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.mockito.MockitoAnnotations;
5152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.robolectric.RuntimeEnvironment;
5252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleiimport org.robolectric.annotation.Config;
5352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
5452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei@RunWith(SettingsRobolectricTestRunner.class)
5552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
5652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyuleipublic class BluetoothPairingDetailTest {
5752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
5852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Mock
5952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private UserManager mUserManager;
6052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Mock
6152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private Resources mResource;
6252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Mock
6352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private LocalBluetoothAdapter mLocalAdapter;
6452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
6552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private LocalBluetoothManager mLocalManager;
6652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Mock
6752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private PreferenceGroup mPreferenceGroup;
6852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private BluetoothPairingDetail mFragment;
6952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private Context mContext;
7052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private BluetoothProgressCategory mAvailableDevicesCategory;
7152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    private FooterPreference mFooterPreference;
7252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
7352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Before
7452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    public void setUp() {
7552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        MockitoAnnotations.initMocks(this);
7652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
7752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mContext = RuntimeEnvironment.application;
7852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment = spy(new BluetoothPairingDetail());
7952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        doReturn(mContext).when(mFragment).getContext();
8052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        doReturn(mResource).when(mFragment).getResources();
8152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
8252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mAvailableDevicesCategory = spy(new BluetoothProgressCategory(mContext));
8352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFooterPreference = new FooterPreference(mContext);
8452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
8552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mLocalAdapter = mLocalAdapter;
8652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mLocalManager = mLocalManager;
8752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mDeviceListGroup = mPreferenceGroup;
88c86440538fb156718228299bd44698e24995632eAntony Sargent        mFragment.mAlwaysDiscoverable = new AlwaysDiscoverable(mContext, mLocalAdapter);
8952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    }
9052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
9152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Test
9252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    public void testInitPreferencesFromPreferenceScreen_findPreferences() {
9352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        doReturn(mAvailableDevicesCategory).when(mFragment).findPreference(
9452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei                BluetoothPairingDetail.KEY_AVAIL_DEVICES);
9552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        doReturn(mFooterPreference).when(mFragment).findPreference(
9652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei                BluetoothPairingDetail.KEY_FOOTER_PREF);
9752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
9852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.initPreferencesFromPreferenceScreen();
9952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
10052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        assertThat(mFragment.mAvailableDevicesCategory).isEqualTo(mAvailableDevicesCategory);
10152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        assertThat(mFragment.mFooterPreference).isEqualTo(mFooterPreference);
10252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    }
10352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
10452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Test
10552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    public void testStartScanning_startScanAndRemoveDevices() {
10652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory;
10752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mDeviceListGroup = mAvailableDevicesCategory;
10852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
109c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.enableScanning();
11052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
11152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        verify(mLocalAdapter).startScanning(true);
11252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        verify(mAvailableDevicesCategory).removeAll();
11352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    }
11452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
11552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Test
11652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    public void testUpdateContent_stateOn_addDevices() {
11752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory;
11852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.mFooterPreference = mFooterPreference;
11952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        doNothing().when(mFragment).addDeviceCategory(any(), anyInt(), any(), anyBoolean());
12052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
12152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.updateContent(BluetoothAdapter.STATE_ON);
12252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
12352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        verify(mFragment).addDeviceCategory(mAvailableDevicesCategory,
12452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei                R.string.bluetooth_preference_found_devices,
12552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei                BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, false);
12652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        verify(mLocalAdapter).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
12752ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    }
12852ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
12952ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    @Test
13052ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    public void testUpdateContent_stateOff_finish() {
13152ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        mFragment.updateContent(BluetoothAdapter.STATE_OFF);
13252ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
13352ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei        verify(mFragment).finish();
13452ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei    }
13552ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei
136c11af01481dd7fb4515e681128340724f2008dc0Jack He    @Test
137c11af01481dd7fb4515e681128340724f2008dc0Jack He    public void testOnScanningStateChanged_restartScanAfterInitialScanning() {
138c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.mAvailableDevicesCategory = mAvailableDevicesCategory;
139c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.mFooterPreference = mFooterPreference;
140c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.mDeviceListGroup = mAvailableDevicesCategory;
141c11af01481dd7fb4515e681128340724f2008dc0Jack He        doNothing().when(mFragment).addDeviceCategory(any(), anyInt(), any(), anyBoolean());
142c11af01481dd7fb4515e681128340724f2008dc0Jack He
143c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Initial Bluetooth ON will trigger scan enable, list clear and scan start
144c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.updateContent(BluetoothAdapter.STATE_ON);
145c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mFragment).enableScanning();
146c11af01481dd7fb4515e681128340724f2008dc0Jack He        assertThat(mAvailableDevicesCategory.getPreferenceCount()).isEqualTo(0);
147c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter).startScanning(true);
148c11af01481dd7fb4515e681128340724f2008dc0Jack He
149c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Subsequent scan started event will not trigger start/stop nor list clear
150c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.onScanningStateChanged(true);
151c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, times(1)).startScanning(anyBoolean());
152c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mAvailableDevicesCategory, times(1)).setProgress(true);
153c11af01481dd7fb4515e681128340724f2008dc0Jack He
154c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Subsequent scan finished event will trigger scan start without list clean
155c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.onScanningStateChanged(false);
156c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, times(2)).startScanning(true);
157c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mAvailableDevicesCategory, times(2)).setProgress(true);
158c11af01481dd7fb4515e681128340724f2008dc0Jack He
159c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Subsequent scan started event will not trigger any change
160c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.onScanningStateChanged(true);
161c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
162c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mAvailableDevicesCategory, times(3)).setProgress(true);
163c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, never()).stopScanning();
164c11af01481dd7fb4515e681128340724f2008dc0Jack He
165c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Disable scanning will trigger scan stop
166c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.disableScanning();
167c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, times(1)).stopScanning();
168c11af01481dd7fb4515e681128340724f2008dc0Jack He
169c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Subsequent scan start event will not trigger any change besides progress circle
170c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.onScanningStateChanged(true);
171c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mAvailableDevicesCategory, times(4)).setProgress(true);
172c11af01481dd7fb4515e681128340724f2008dc0Jack He
173c11af01481dd7fb4515e681128340724f2008dc0Jack He        // However, subsequent scan finished event won't trigger new scan start and will stop
174c11af01481dd7fb4515e681128340724f2008dc0Jack He        // progress circle from spinning
175c11af01481dd7fb4515e681128340724f2008dc0Jack He        mFragment.onScanningStateChanged(false);
176c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mAvailableDevicesCategory, times(1)).setProgress(false);
177c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, times(2)).startScanning(anyBoolean());
178c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mLocalAdapter, times(1)).stopScanning();
179c11af01481dd7fb4515e681128340724f2008dc0Jack He
180c11af01481dd7fb4515e681128340724f2008dc0Jack He        // Verify that clean up only happen once at initialization
181c11af01481dd7fb4515e681128340724f2008dc0Jack He        verify(mAvailableDevicesCategory, times(1)).removeAll();
182c11af01481dd7fb4515e681128340724f2008dc0Jack He    }
183c11af01481dd7fb4515e681128340724f2008dc0Jack He
184c11af01481dd7fb4515e681128340724f2008dc0Jack He
185c11af01481dd7fb4515e681128340724f2008dc0Jack He
18652ccb49fbe65c8e84a5d4fde1d8028b62a713204jackqdyulei}
187