1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.LOLLIPOP; 4 import static com.google.common.truth.Truth.assertThat; 5 import static org.junit.Assert.assertEquals; 6 import static org.junit.Assert.assertFalse; 7 import static org.junit.Assert.assertNotNull; 8 import static org.junit.Assert.assertNull; 9 import static org.junit.Assert.assertTrue; 10 import static org.robolectric.RuntimeEnvironment.application; 11 import static org.robolectric.Shadows.shadowOf; 12 13 import android.app.Activity; 14 import android.app.AlertDialog; 15 import android.app.Application; 16 import android.app.Dialog; 17 import android.content.ContextWrapper; 18 import android.content.DialogInterface; 19 import android.view.View; 20 import android.widget.ArrayAdapter; 21 import android.widget.EditText; 22 import androidx.test.core.app.ApplicationProvider; 23 import androidx.test.ext.junit.runners.AndroidJUnit4; 24 import java.util.ArrayList; 25 import java.util.List; 26 import org.junit.Before; 27 import org.junit.Test; 28 import org.junit.runner.RunWith; 29 import org.robolectric.R; 30 import org.robolectric.Robolectric; 31 import org.robolectric.android.CustomView; 32 import org.robolectric.annotation.Config; 33 34 @RunWith(AndroidJUnit4.class) 35 public class ShadowAlertDialogTest { 36 37 private Application context; 38 39 @Before setUp()40 public void setUp() throws Exception { 41 context = ApplicationProvider.getApplicationContext(); 42 } 43 44 @Test testBuilder()45 public void testBuilder() throws Exception { 46 AlertDialog.Builder builder = new AlertDialog.Builder(application); 47 builder.setTitle("title").setMessage("message"); 48 builder.setCancelable(true); 49 AlertDialog alert = builder.create(); 50 alert.show(); 51 52 assertThat(alert.isShowing()).isTrue(); 53 54 ShadowAlertDialog shadowAlertDialog = shadowOf(alert); 55 assertEquals("title", shadowAlertDialog.getTitle()); 56 assertThat(shadowAlertDialog.getMessage()).isEqualTo("message"); 57 assertThat(shadowAlertDialog.isCancelable()).isTrue(); 58 assertThat(shadowOf(ShadowAlertDialog.getLatestAlertDialog())).isSameAs(shadowAlertDialog); 59 assertThat(ShadowAlertDialog.getLatestAlertDialog()).isSameAs(alert); 60 } 61 62 @Test nullTitleAndMessageAreOkay()63 public void nullTitleAndMessageAreOkay() throws Exception { 64 AlertDialog.Builder builder = new AlertDialog.Builder(application) // 65 .setTitle(null) // 66 .setMessage(null); 67 ShadowAlertDialog shadowAlertDialog = shadowOf(builder.create()); 68 assertThat(shadowAlertDialog.getTitle().toString()).isEqualTo(""); 69 assertThat(shadowAlertDialog.getMessage()).isEqualTo(""); 70 } 71 72 @Test getLatestAlertDialog_shouldReturnARealAlertDialog()73 public void getLatestAlertDialog_shouldReturnARealAlertDialog() throws Exception { 74 assertThat(ShadowAlertDialog.getLatestAlertDialog()).isNull(); 75 76 AlertDialog dialog = new AlertDialog.Builder(application).show(); 77 assertThat(ShadowAlertDialog.getLatestAlertDialog()).isSameAs(dialog); 78 } 79 80 @Test shouldOnlyCreateRequestedButtons()81 public void shouldOnlyCreateRequestedButtons() throws Exception { 82 AlertDialog.Builder builder = new AlertDialog.Builder(application); 83 builder.setPositiveButton("OK", null); 84 AlertDialog dialog = builder.create(); 85 dialog.show(); 86 assertThat(dialog.getButton(AlertDialog.BUTTON_POSITIVE).getVisibility()) 87 .isEqualTo(View.VISIBLE); 88 assertThat(dialog.getButton(AlertDialog.BUTTON_NEGATIVE).getVisibility()).isEqualTo(View.GONE); 89 } 90 91 @Test shouldAllowNullButtonListeners()92 public void shouldAllowNullButtonListeners() throws Exception { 93 AlertDialog.Builder builder = new AlertDialog.Builder(application); 94 builder.setPositiveButton("OK", null); 95 AlertDialog dialog = builder.create(); 96 dialog.show(); 97 ShadowView.clickOn(dialog.getButton(AlertDialog.BUTTON_POSITIVE)); 98 } 99 100 @Test testSetMessageAfterCreation()101 public void testSetMessageAfterCreation() { 102 AlertDialog.Builder builder = new AlertDialog.Builder(application); 103 builder.setTitle("title").setMessage("message"); 104 AlertDialog alert = builder.create(); 105 106 ShadowAlertDialog shadowAlertDialog = shadowOf(alert); 107 assertThat(shadowAlertDialog.getMessage()).isEqualTo("message"); 108 109 alert.setMessage("new message"); 110 assertThat(shadowAlertDialog.getMessage()).isEqualTo("new message"); 111 112 alert.setMessage(null); 113 assertThat(shadowAlertDialog.getMessage()).isEqualTo(""); 114 } 115 116 @Test shouldSetMessageFromResourceId()117 public void shouldSetMessageFromResourceId() throws Exception { 118 AlertDialog.Builder builder = new AlertDialog.Builder(application); 119 builder.setTitle("title").setMessage(R.string.hello); 120 121 AlertDialog alert = builder.create(); 122 ShadowAlertDialog shadowAlertDialog = shadowOf(alert); 123 assertThat(shadowAlertDialog.getMessage()).isEqualTo("Hello"); 124 } 125 126 @Test shouldSetView()127 public void shouldSetView() throws Exception { 128 AlertDialog.Builder builder = new AlertDialog.Builder(application); 129 EditText view = new EditText(application); 130 builder.setView(view); 131 132 AlertDialog alert = builder.create(); 133 assertThat(shadowOf(alert).getView()).isEqualTo(view); 134 } 135 136 @Test 137 @Config(minSdk = LOLLIPOP) shouldSetView_withLayoutId()138 public void shouldSetView_withLayoutId() throws Exception { 139 AlertDialog.Builder builder = new AlertDialog.Builder(application); 140 builder.setView(R.layout.custom_layout); 141 142 AlertDialog alert = builder.create(); 143 View view = shadowOf(alert).getView(); 144 assertThat(view.getClass()).isEqualTo(CustomView.class); 145 } 146 147 @Test shouldSetCustomTitleView()148 public void shouldSetCustomTitleView() throws Exception { 149 AlertDialog.Builder builder = new AlertDialog.Builder(application); 150 View view = new View(application); 151 assertThat(builder.setCustomTitle(view)).isSameAs(builder); 152 153 AlertDialog alert = builder.create(); 154 assertThat(shadowOf(alert).getCustomTitleView()).isEqualTo(view); 155 } 156 157 @Test clickingPositiveButtonDismissesDialog()158 public void clickingPositiveButtonDismissesDialog() throws Exception { 159 AlertDialog alertDialog = new AlertDialog.Builder(application) 160 .setPositiveButton("Positive", null).create(); 161 alertDialog.show(); 162 163 assertTrue(alertDialog.isShowing()); 164 alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); 165 assertFalse(alertDialog.isShowing()); 166 } 167 168 @Test clickingNeutralButtonDismissesDialog()169 public void clickingNeutralButtonDismissesDialog() throws Exception { 170 AlertDialog alertDialog = new AlertDialog.Builder(application) 171 .setNeutralButton("Neutral", new DialogInterface.OnClickListener() { 172 @Override 173 public void onClick(DialogInterface dialog, int which) { 174 } 175 }).create(); 176 alertDialog.show(); 177 178 assertTrue(alertDialog.isShowing()); 179 alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).performClick(); 180 assertFalse(alertDialog.isShowing()); 181 } 182 183 @Test clickingNegativeButtonDismissesDialog()184 public void clickingNegativeButtonDismissesDialog() throws Exception { 185 AlertDialog alertDialog = new AlertDialog.Builder(application) 186 .setNegativeButton("Negative", new DialogInterface.OnClickListener() { 187 @Override 188 public void onClick(DialogInterface dialog, int which) { 189 } 190 }).create(); 191 alertDialog.show(); 192 193 assertTrue(alertDialog.isShowing()); 194 alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).performClick(); 195 assertFalse(alertDialog.isShowing()); 196 } 197 198 @Test testBuilderWithItemArrayViaResourceId()199 public void testBuilderWithItemArrayViaResourceId() throws Exception { 200 AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(context)); 201 202 builder.setTitle("title"); 203 builder.setItems(R.array.alertDialogTestItems, new TestDialogOnClickListener()); 204 AlertDialog alert = builder.create(); 205 alert.show(); 206 207 assertThat(alert.isShowing()).isTrue(); 208 209 ShadowAlertDialog shadowAlertDialog = shadowOf(alert); 210 assertThat(shadowAlertDialog.getTitle().toString()).isEqualTo("title"); 211 assertThat(shadowAlertDialog.getItems().length).isEqualTo(2); 212 assertThat(shadowAlertDialog.getItems()[0]).isEqualTo("Aloha"); 213 assertThat(shadowOf(ShadowAlertDialog.getLatestAlertDialog())).isSameAs(shadowAlertDialog); 214 assertThat(ShadowAlertDialog.getLatestAlertDialog()).isSameAs(alert); 215 } 216 217 @Test testBuilderWithAdapter()218 public void testBuilderWithAdapter() throws Exception { 219 List<Integer> list = new ArrayList<>(); 220 list.add(99); 221 list.add(88); 222 list.add(77); 223 ArrayAdapter<Integer> adapter = new ArrayAdapter<>(context, R.layout.main, R.id.title, list); 224 225 AlertDialog.Builder builder = new AlertDialog.Builder(application); 226 builder.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() { 227 @Override 228 public void onClick(DialogInterface dialog, int item) { 229 dialog.dismiss(); 230 } 231 }); 232 AlertDialog alert = builder.create(); 233 alert.show(); 234 235 assertTrue(alert.isShowing()); 236 ShadowAlertDialog shadowAlertDialog = shadowOf(alert); 237 assertThat(shadowAlertDialog.getAdapter().getCount()).isEqualTo(3); 238 assertThat(shadowAlertDialog.getAdapter().getItem(0)).isEqualTo(99); 239 } 240 241 @Test show_setsLatestAlertDialogAndLatestDialog()242 public void show_setsLatestAlertDialogAndLatestDialog() { 243 AlertDialog alertDialog = new AlertDialog.Builder(context).create(); 244 assertNull(ShadowDialog.getLatestDialog()); 245 assertNull(ShadowAlertDialog.getLatestAlertDialog()); 246 247 alertDialog.show(); 248 249 assertEquals(alertDialog, ShadowDialog.getLatestDialog()); 250 assertEquals(alertDialog, ShadowAlertDialog.getLatestAlertDialog()); 251 } 252 253 @Test shouldCallTheClickListenerOfTheCheckedAdapterInASingleChoiceDialog()254 public void shouldCallTheClickListenerOfTheCheckedAdapterInASingleChoiceDialog() 255 throws Exception { 256 AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(context)); 257 258 TestDialogOnClickListener listener = new TestDialogOnClickListener(); 259 List<Integer> list = new ArrayList<>(); 260 list.add(1); 261 list.add(2); 262 list.add(3); 263 ArrayAdapter<Integer> arrayAdapter = 264 new ArrayAdapter<>(context, R.layout.main, R.id.title, list); 265 builder.setSingleChoiceItems(arrayAdapter, 1, listener); 266 267 AlertDialog alert = builder.create(); 268 alert.show(); 269 270 ShadowAlertDialog shadowAlertDialog = shadowOf(alert); 271 shadowAlertDialog.clickOnItem(0); 272 assertThat(listener.transcript).containsExactly("clicked on 0"); 273 listener.transcript.clear(); 274 275 shadowAlertDialog.clickOnItem(1); 276 assertThat(listener.transcript).containsExactly("clicked on 1"); 277 278 } 279 280 @Test shouldDelegateToDialogFindViewByIdIfViewIsNull()281 public void shouldDelegateToDialogFindViewByIdIfViewIsNull() { 282 AlertDialog dialog = new AlertDialog(context) {}; 283 284 assertThat((View) dialog.findViewById(99)).isNull(); 285 286 dialog.setContentView(R.layout.main); 287 assertNotNull(dialog.findViewById(R.id.title)); 288 } 289 290 @Test shouldNotExplodeWhenNestingAlerts()291 public void shouldNotExplodeWhenNestingAlerts() throws Exception { 292 final Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 293 final AlertDialog nestedDialog = new AlertDialog.Builder(activity) 294 .setTitle("Dialog 2") 295 .setMessage("Another dialog") 296 .setPositiveButton("OK", null) 297 .create(); 298 299 final AlertDialog dialog = new AlertDialog.Builder(activity) 300 .setTitle("Dialog 1") 301 .setMessage("A dialog") 302 .setPositiveButton("Button 1", new DialogInterface.OnClickListener() { 303 @Override 304 public void onClick(DialogInterface dialog, int which) { 305 nestedDialog.show(); 306 } 307 }).create(); 308 309 dialog.show(); 310 assertThat(ShadowDialog.getLatestDialog()).isEqualTo(dialog); 311 312 dialog.getButton(Dialog.BUTTON_POSITIVE).performClick(); 313 assertThat(ShadowDialog.getLatestDialog()).isEqualTo(nestedDialog); 314 } 315 316 @Test alertControllerShouldStoreCorrectIconIdFromBuilder()317 public void alertControllerShouldStoreCorrectIconIdFromBuilder() { 318 AlertDialog.Builder builder = new AlertDialog.Builder(application); 319 builder.setIcon(R.drawable.an_image); 320 321 AlertDialog alertDialog = builder.create(); 322 assertThat(shadowOf(alertDialog).getIconId()).isEqualTo(R.drawable.an_image); 323 } 324 325 private static class TestDialogOnClickListener implements DialogInterface.OnClickListener { 326 327 private final ArrayList<String> transcript = new ArrayList<>(); 328 329 @Override onClick(DialogInterface dialog, int item)330 public void onClick(DialogInterface dialog, int item) { 331 transcript.add("clicked on " + item); 332 } 333 } 334 } 335