1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.bluetooth; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Matchers.anyString; 22 import static org.mockito.Matchers.eq; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 27 import android.app.FragmentManager; 28 import android.app.FragmentTransaction; 29 import android.view.View; 30 import android.widget.Button; 31 32 import com.android.settings.R; 33 import com.android.settings.testutils.SettingsRobolectricTestRunner; 34 import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice; 35 import com.android.settings.widget.ActionButtonPreference; 36 import com.android.settings.widget.ActionButtonPreferenceTest; 37 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.mockito.ArgumentCaptor; 41 import org.robolectric.RuntimeEnvironment; 42 import org.robolectric.annotation.Config; 43 44 @RunWith(SettingsRobolectricTestRunner.class) 45 @Config(shadows = SettingsShadowBluetoothDevice.class) 46 public class BluetoothDetailsButtonsControllerTest extends BluetoothDetailsControllerTestBase { 47 private BluetoothDetailsButtonsController mController; 48 private ActionButtonPreference mButtonsPref; 49 private Button mConnectButton; 50 private Button mForgetButton; 51 52 @Override setUp()53 public void setUp() { 54 super.setUp(); 55 final View buttons = View.inflate( 56 RuntimeEnvironment.application, R.layout.two_action_buttons, null /* parent */); 57 mConnectButton = buttons.findViewById(R.id.button2_positive); 58 mForgetButton = buttons.findViewById(R.id.button1_positive); 59 mController = 60 new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice, mLifecycle); 61 mButtonsPref = ActionButtonPreferenceTest.createMock(); 62 when(mButtonsPref.getKey()).thenReturn(mController.getPreferenceKey()); 63 when(mButtonsPref.setButton2OnClickListener(any(View.OnClickListener.class))) 64 .thenAnswer(invocation -> { 65 final Object[] args = invocation.getArguments(); 66 mConnectButton.setOnClickListener((View.OnClickListener) args[0]); 67 return mButtonsPref; 68 }); 69 when(mButtonsPref.setButton1OnClickListener(any(View.OnClickListener.class))) 70 .thenAnswer(invocation -> { 71 final Object[] args = invocation.getArguments(); 72 mForgetButton.setOnClickListener((View.OnClickListener) args[0]); 73 return mButtonsPref; 74 }); 75 mScreen.addPreference(mButtonsPref); 76 setupDevice(mDeviceConfig); 77 when(mCachedDevice.isBusy()).thenReturn(false); 78 } 79 80 @Test connected()81 public void connected() { 82 showScreen(mController); 83 84 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_disconnect); 85 verify(mButtonsPref).setButton1Text(R.string.forget); 86 } 87 88 @Test clickOnDisconnect()89 public void clickOnDisconnect() { 90 showScreen(mController); 91 mConnectButton.callOnClick(); 92 93 verify(mCachedDevice).disconnect(); 94 } 95 96 @Test clickOnConnect()97 public void clickOnConnect() { 98 when(mCachedDevice.isConnected()).thenReturn(false); 99 showScreen(mController); 100 101 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_connect); 102 103 mConnectButton.callOnClick(); 104 verify(mCachedDevice).connect(eq(true)); 105 } 106 107 @Test becomeDisconnected()108 public void becomeDisconnected() { 109 showScreen(mController); 110 // By default we start out with the device connected. 111 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_disconnect); 112 113 // Now make the device appear to have changed to disconnected. 114 when(mCachedDevice.isConnected()).thenReturn(false); 115 mController.onDeviceAttributesChanged(); 116 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_connect); 117 118 // Click the button and make sure that connect (not disconnect) gets called. 119 mConnectButton.callOnClick(); 120 verify(mCachedDevice).connect(eq(true)); 121 } 122 123 @Test becomeConnected()124 public void becomeConnected() { 125 // Start out with the device disconnected. 126 when(mCachedDevice.isConnected()).thenReturn(false); 127 showScreen(mController); 128 129 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_connect); 130 131 132 // Now make the device appear to have changed to connected. 133 when(mCachedDevice.isConnected()).thenReturn(true); 134 mController.onDeviceAttributesChanged(); 135 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_disconnect); 136 137 // Click the button and make sure that disconnnect (not connect) gets called. 138 mConnectButton.callOnClick(); 139 verify(mCachedDevice).disconnect(); 140 } 141 142 @Test forgetDialog()143 public void forgetDialog() { 144 showScreen(mController); 145 FragmentManager fragmentManager = mock(FragmentManager.class); 146 when(mFragment.getFragmentManager()).thenReturn(fragmentManager); 147 FragmentTransaction ft = mock(FragmentTransaction.class); 148 when(fragmentManager.beginTransaction()).thenReturn(ft); 149 mForgetButton.callOnClick(); 150 151 ArgumentCaptor<ForgetDeviceDialogFragment> dialogCaptor = 152 ArgumentCaptor.forClass(ForgetDeviceDialogFragment.class); 153 verify(ft).add(dialogCaptor.capture(), anyString()); 154 155 ForgetDeviceDialogFragment dialogFragment = dialogCaptor.getValue(); 156 assertThat(dialogFragment).isNotNull(); 157 } 158 159 @Test startsOutBusy()160 public void startsOutBusy() { 161 when(mCachedDevice.isBusy()).thenReturn(true); 162 showScreen(mController); 163 164 verify(mButtonsPref).setButton2Text(R.string.bluetooth_device_context_disconnect); 165 verify(mButtonsPref).setButton2Enabled(false); 166 verify(mButtonsPref).setButton1Text(R.string.forget); 167 168 // Now pretend the device became non-busy. 169 when(mCachedDevice.isBusy()).thenReturn(false); 170 mController.onDeviceAttributesChanged(); 171 172 verify(mButtonsPref).setButton2Enabled(true); 173 } 174 175 @Test becomesBusy()176 public void becomesBusy() { 177 showScreen(mController); 178 verify(mButtonsPref).setButton2Enabled(true); 179 180 // Now pretend the device became busy. 181 when(mCachedDevice.isBusy()).thenReturn(true); 182 mController.onDeviceAttributesChanged(); 183 184 verify(mButtonsPref).setButton2Enabled(false); 185 } 186 } 187