1package com.xtremelabs.robolectric.shadows;
2
3import static com.xtremelabs.robolectric.Robolectric.shadowOf;
4import static junit.framework.Assert.assertFalse;
5import static junit.framework.Assert.assertNull;
6import static org.hamcrest.CoreMatchers.*;
7import static org.junit.Assert.*;
8
9import java.util.ArrayList;
10import java.util.List;
11
12import org.junit.Test;
13import org.junit.runner.RunWith;
14
15import android.app.Activity;
16import android.app.AlertDialog;
17import android.content.ContextWrapper;
18import android.content.DialogInterface;
19import android.view.View;
20import android.widget.ArrayAdapter;
21import android.widget.Button;
22import android.widget.EditText;
23
24import com.xtremelabs.robolectric.R;
25import com.xtremelabs.robolectric.Robolectric;
26import com.xtremelabs.robolectric.WithTestDefaultsRunner;
27
28@RunWith(WithTestDefaultsRunner.class)
29public class AlertDialogTest {
30
31    @Test
32    public void testBuilder() throws Exception {
33        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(null));
34        builder.setTitle("title").setMessage("message");
35        builder.setCancelable(true);
36        AlertDialog alert = builder.create();
37        alert.show();
38
39        assertThat(alert.isShowing(), equalTo(true));
40
41        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
42        assertEquals("title", shadowAlertDialog.getTitle());
43        assertThat(shadowAlertDialog.getMessage(), equalTo("message"));
44        assertThat(shadowAlertDialog.isCancelable(), equalTo(true));
45        assertThat(shadowOf(ShadowAlertDialog.getLatestAlertDialog()), sameInstance(shadowAlertDialog));
46        assertThat(ShadowAlertDialog.getLatestAlertDialog(), sameInstance(alert));
47    }
48
49    @Test
50    public void getLatestAlertDialog_shouldReturnARealAlertDialog() throws Exception {
51        assertThat(ShadowAlertDialog.getLatestAlertDialog(), nullValue());
52
53        AlertDialog dialog = new AlertDialog.Builder(new ContextWrapper(null)).show();
54        assertThat(ShadowAlertDialog.getLatestAlertDialog(), sameInstance(dialog));
55    }
56
57    @Test
58    public void shouldOnlyCreateRequestedButtons() throws Exception {
59        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(null));
60        builder.setPositiveButton("OK", null);
61        AlertDialog dialog = builder.create();
62        dialog.show();
63        assertThat(shadowOf(dialog).getButton(AlertDialog.BUTTON_POSITIVE), not(nullValue()));
64        assertThat(shadowOf(dialog).getButton(AlertDialog.BUTTON_NEGATIVE), nullValue());
65    }
66
67    @Test
68    public void shouldAllowNullButtonListeners() throws Exception {
69        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(null));
70        builder.setPositiveButton("OK", null);
71        AlertDialog dialog = builder.create();
72        dialog.show();
73        Robolectric.clickOn(dialog.getButton(AlertDialog.BUTTON_POSITIVE));
74    }
75
76    @Test
77    public void testSetMessageAfterCreation() {
78        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(null));
79        builder.setTitle("title").setMessage("message");
80        AlertDialog alert = builder.create();
81
82        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
83        assertThat(shadowAlertDialog.getMessage(), equalTo("message"));
84
85        shadowAlertDialog.setMessage("new message");
86        assertThat(shadowAlertDialog.getMessage(), equalTo("new message"));
87
88        shadowAlertDialog.setMessage(null);
89        assertThat(shadowAlertDialog.getMessage(), nullValue());
90    }
91
92    @Test
93    public void shouldSetMessageFromResourceId() throws Exception {
94        AlertDialog.Builder builder = new AlertDialog.Builder(new Activity());
95        builder.setTitle("title").setMessage(R.string.hello);
96
97        AlertDialog alert = builder.create();
98        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
99        assertThat(shadowAlertDialog.getMessage(), equalTo("Hello"));
100    }
101
102    @Test
103    public void shouldSetView() throws Exception {
104        ContextWrapper context = new ContextWrapper(null);
105        AlertDialog.Builder builder = new AlertDialog.Builder(context);
106        EditText view = new EditText(context);
107        builder.setView(view);
108
109        AlertDialog alert = builder.create();
110        assertThat(shadowOf(alert).getView(), equalTo((View) view));
111    }
112
113    @Test
114    public void shouldSetCustomTitleView() throws Exception {
115        ContextWrapper context = new ContextWrapper(null);
116        AlertDialog.Builder builder = new AlertDialog.Builder(context);
117        View view = new View(context);
118        assertThat(builder.setCustomTitle(view), sameInstance(builder));
119
120        AlertDialog alert = builder.create();
121        assertThat(shadowOf(alert).getCustomTitleView(), equalTo((View) view));
122    }
123
124    @Test
125    public void shouldSetThePositiveButtonAfterCreation() throws Exception {
126        final AlertDialog alertDialog = new AlertDialog.Builder(new ContextWrapper(null))
127            .setPositiveButton("Positive", null).create();
128
129        TestDialogOnClickListener listener = new TestDialogOnClickListener();
130        alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "More Positive", listener);
131
132        final Button positiveButton = shadowOf(alertDialog).getButton(AlertDialog.BUTTON_POSITIVE);
133        positiveButton.performClick();
134
135        assertThat(positiveButton.getText().toString(), equalTo("More Positive"));
136        assertThat(listener.clickedItem, equalTo(AlertDialog.BUTTON_POSITIVE));
137    }
138
139    @Test
140    public void shouldSetTheNegativeButtonAfterCreation() throws Exception {
141        final AlertDialog alertDialog = new AlertDialog.Builder(new ContextWrapper(null))
142            .setNegativeButton("Negative", null).create();
143
144        TestDialogOnClickListener listener = new TestDialogOnClickListener();
145        alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "More Negative", listener);
146
147        final Button negativeButton = shadowOf(alertDialog).getButton(AlertDialog.BUTTON_NEGATIVE);
148        negativeButton.performClick();
149
150        assertThat(negativeButton.getText().toString(), equalTo("More Negative"));
151        assertThat(listener.clickedItem, equalTo(AlertDialog.BUTTON_NEGATIVE));
152    }
153
154    @Test
155    public void shouldSetTheNeutralButtonAfterCreation() throws Exception {
156        final AlertDialog alertDialog = new AlertDialog.Builder(new ContextWrapper(null))
157            .setNegativeButton("Neutral", null).create();
158
159        TestDialogOnClickListener listener = new TestDialogOnClickListener();
160        alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Still Neutral", listener);
161
162        final Button neutralButton = shadowOf(alertDialog).getButton(AlertDialog.BUTTON_NEUTRAL);
163        neutralButton.performClick();
164
165        assertThat(neutralButton.getText().toString(), equalTo("Still Neutral"));
166        assertThat(listener.clickedItem, equalTo(AlertDialog.BUTTON_NEUTRAL));
167    }
168
169    @Test
170    public void clickingPositiveButtonDismissesDialog() throws Exception {
171        AlertDialog alertDialog = new AlertDialog.Builder(new ContextWrapper(null))
172                .setPositiveButton("Positive", null).create();
173        alertDialog.show();
174
175        assertTrue(alertDialog.isShowing());
176        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick();
177        assertFalse(alertDialog.isShowing());
178    }
179
180    @Test
181    public void clickingNeutralButtonDismissesDialog() throws Exception {
182        AlertDialog alertDialog = new AlertDialog.Builder(new ContextWrapper(null))
183                .setNeutralButton("Neutral", new DialogInterface.OnClickListener() {
184                    @Override
185                    public void onClick(DialogInterface dialog, int which) {
186                    }
187                }).create();
188        alertDialog.show();
189
190        assertTrue(alertDialog.isShowing());
191        alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).performClick();
192        assertFalse(alertDialog.isShowing());
193    }
194
195    @Test
196    public void clickingNegativeButtonDismissesDialog() throws Exception {
197        AlertDialog alertDialog = new AlertDialog.Builder(new ContextWrapper(null))
198                .setNegativeButton("Negative", new DialogInterface.OnClickListener() {
199                    @Override
200                    public void onClick(DialogInterface dialog, int which) {
201                    }
202                }).create();
203        alertDialog.show();
204
205        assertTrue(alertDialog.isShowing());
206        alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).performClick();
207        assertFalse(alertDialog.isShowing());
208    }
209
210    @Test
211    public void testBuilderWithItemArrayViaResourceId() throws Exception {
212        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(Robolectric.application));
213
214        builder.setTitle("title");
215        builder.setItems(R.array.alertDialogTestItems, new TestDialogOnClickListener());
216        AlertDialog alert = builder.create();
217        alert.show();
218
219        assertThat(alert.isShowing(), equalTo(true));
220
221        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
222        assertThat(shadowAlertDialog.getTitle().toString(), equalTo("title"));
223        assertThat(shadowAlertDialog.getItems().length, equalTo(2));
224        assertEquals(shadowAlertDialog.getItems()[0], "Aloha");
225        assertThat(shadowOf(ShadowAlertDialog.getLatestAlertDialog()), sameInstance(shadowAlertDialog));
226        assertThat(ShadowAlertDialog.getLatestAlertDialog(), sameInstance(alert));
227    }
228
229
230//    @Test
231//    public void testBuilderWithItemArrayCanPerformClickOnItem() throws Exception {
232//        TestDialogOnClickListener listener = new TestDialogOnClickListener();
233//        AlertDialog alert = new AlertDialog.Builder(new ContextWrapper(Robolectric.application))
234//                .setItems(R.array.alertDialogTestItems, listener)
235//                .create();
236//
237//        alert.show();
238//        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
239//        shadowAlertDialog.clickOnItem(1);
240//
241//
242//    }
243
244    @Test
245    public void testBuilderWithAdapter() throws Exception {
246        List<Integer> list = new ArrayList<Integer>();
247        list.add(99);
248        list.add(88);
249        list.add(77);
250        ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(Robolectric.application, R.layout.main, R.id.title, list);
251
252        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(null));
253        builder.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
254            @Override
255            public void onClick(DialogInterface dialog, int item) {
256                dialog.dismiss();
257            }
258        });
259        AlertDialog alert = builder.create();
260        alert.show();
261
262        assertTrue(alert.isShowing());
263        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
264        assertEquals(shadowAlertDialog.getAdapter().getCount(), 3);
265        assertEquals(shadowAlertDialog.getAdapter().getItem(0), 99);
266    }
267
268    @Test
269    public void show_setsLatestAlertDialogAndLatestDialog() {
270        AlertDialog alertDialog = new AlertDialog.Builder(Robolectric.application).create();
271        assertNull(ShadowDialog.getLatestDialog());
272        assertNull(ShadowAlertDialog.getLatestAlertDialog());
273
274        alertDialog.show();
275
276        assertEquals(alertDialog, ShadowDialog.getLatestDialog());
277        assertEquals(alertDialog, ShadowAlertDialog.getLatestAlertDialog());
278    }
279
280    @Test
281    public void shouldReturnTheIndexOfTheCheckedItemInASingleChoiceDialog() throws Exception {
282        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(Robolectric.application));
283
284        builder.setSingleChoiceItems(new String[]{"foo", "bar"}, 1, new DialogInterface.OnClickListener() {
285            public void onClick(DialogInterface dialog, int item) {
286
287            }
288        });
289        AlertDialog alert = builder.create();
290        alert.show();
291
292        assertThat(alert.isShowing(), equalTo(true));
293
294        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
295        assertEquals(shadowAlertDialog.getCheckedItemIndex(), 1);
296        assertEquals(shadowAlertDialog.getItems()[0], "foo");
297        assertThat(shadowAlertDialog.getItems().length, equalTo(2));
298        assertThat(ShadowAlertDialog.getLatestAlertDialog(), sameInstance(alert));
299    }
300
301    @Test
302    public void shouldCallTheClickListenerOfTheCheckedItemInASingleChoiceDialog() throws Exception {
303        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(Robolectric.application));
304
305        TestDialogOnClickListener listener = new TestDialogOnClickListener();
306        builder.setSingleChoiceItems(new String[]{"foo", "bar"}, 1, listener);
307
308        AlertDialog alert = builder.create();
309        alert.show();
310
311        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
312        shadowAlertDialog.clickOnItem(0);
313        assertThat(listener.clickedItem, equalTo(0));
314        assertThat(shadowAlertDialog.getCheckedItemIndex(), equalTo(0));
315
316        shadowAlertDialog.clickOnItem(1);
317        assertThat(listener.clickedItem, equalTo(1));
318        assertThat(shadowAlertDialog.getCheckedItemIndex(), equalTo(1));
319
320    }
321
322    @Test
323    public void shouldCallTheClickListenerOfTheCheckedAdapterInASingleChoiceDialog() throws Exception {
324        AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(Robolectric.application));
325
326        TestDialogOnClickListener listener = new TestDialogOnClickListener();
327        List<Integer> list = new ArrayList<Integer>();
328        list.add(1);
329        list.add(2);
330        list.add(3);
331        ArrayAdapter<Integer> arrayAdapter = new ArrayAdapter<Integer>(Robolectric.application, R.layout.main, R.id.title, list);
332        builder.setSingleChoiceItems(arrayAdapter, 1, listener);
333
334        AlertDialog alert = builder.create();
335        alert.show();
336
337        ShadowAlertDialog shadowAlertDialog = shadowOf(alert);
338        shadowAlertDialog.clickOnItem(0);
339        assertThat(listener.clickedItem, equalTo(0));
340        assertThat(shadowAlertDialog.getCheckedItemIndex(), equalTo(0));
341
342        shadowAlertDialog.clickOnItem(1);
343        assertThat(listener.clickedItem, equalTo(1));
344        assertThat(shadowAlertDialog.getCheckedItemIndex(), equalTo(1));
345
346    }
347
348    @Test
349    public void shouldFindViewsByIdIfAViewIsSet() throws Exception {
350        ContextWrapper context = new ContextWrapper(null);
351        AlertDialog dialog = new AlertDialog.Builder(context).create();
352
353        assertThat(dialog.findViewById(99), nullValue());
354
355        View view = new View(context);
356        view.setId(99);
357        dialog.setView(view);
358        assertThat(dialog.findViewById(99), sameInstance(view));
359
360        assertThat(dialog.findViewById(66), nullValue());
361    }
362
363    @Test
364    public void shouldDelegateToDialogFindViewByIdIfViewIsNull() {
365        AlertDialog dialog = new AlertDialog(Robolectric.application) {
366        };
367
368        assertThat(dialog.findViewById(99), nullValue());
369
370        dialog.setContentView(R.layout.main);
371        assertNotNull(dialog.findViewById(R.id.title));
372    }
373
374
375    private static class TestDialogOnClickListener implements DialogInterface.OnClickListener {
376        private DialogInterface dialog;
377        private int clickedItem;
378
379        public void onClick(DialogInterface dialog, int item) {
380            this.dialog = dialog;
381            this.clickedItem = item;
382        }
383    }
384}
385