Home | History | Annotate | Download | only in res
      1 package com.xtremelabs.robolectric.res;
      2 
      3 import android.app.Activity;
      4 import android.content.Context;
      5 import android.os.Build;
      6 import android.os.Bundle;
      7 import android.view.View;
      8 import android.view.ViewGroup;
      9 import android.webkit.WebView;
     10 import android.widget.*;
     11 import com.google.android.maps.MapView;
     12 import com.xtremelabs.robolectric.R;
     13 import com.xtremelabs.robolectric.Robolectric;
     14 import com.xtremelabs.robolectric.WithTestDefaultsRunner;
     15 import com.xtremelabs.robolectric.shadows.ShadowImageView;
     16 import com.xtremelabs.robolectric.shadows.ShadowTextView;
     17 import com.xtremelabs.robolectric.util.CustomView;
     18 import com.xtremelabs.robolectric.util.CustomView2;
     19 import com.xtremelabs.robolectric.util.I18nException;
     20 import com.xtremelabs.robolectric.util.TestUtil;
     21 import org.junit.Before;
     22 import org.junit.Test;
     23 import org.junit.runner.RunWith;
     24 
     25 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
     26 import static com.xtremelabs.robolectric.util.TestUtil.*;
     27 import static org.hamcrest.CoreMatchers.*;
     28 import static org.junit.Assert.*;
     29 
     30 @RunWith(WithTestDefaultsRunner.class)
     31 public class ViewLoaderTest {
     32     private ViewLoader viewLoader;
     33     private Context context;
     34 
     35     @Before
     36     public void setUp() throws Exception {
     37         Robolectric.bindDefaultShadowClasses();
     38 
     39         ResourceExtractor resourceExtractor = new ResourceExtractor();
     40         resourceExtractor.addLocalRClass(R.class);
     41         resourceExtractor.addSystemRClass(android.R.class);
     42 
     43         StringResourceLoader stringResourceLoader = new StringResourceLoader(resourceExtractor);
     44         new DocumentLoader(stringResourceLoader).loadResourceXmlDir(resourceFile("res", "values"));
     45         new DocumentLoader(stringResourceLoader).loadSystemResourceXmlDir(getSystemResourceDir("values"));
     46 
     47         viewLoader =  new ViewLoader(resourceExtractor, new AttrResourceLoader(resourceExtractor));
     48         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout"));
     49         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout-land"));
     50         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout-large-v16"));
     51         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout-v11"));
     52         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout-xlarge"));
     53         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout-xlarge-v11"));
     54         new DocumentLoader(viewLoader).loadSystemResourceXmlDir(getSystemResourceDir("layout"));
     55 
     56         context = new Activity();
     57     }
     58 
     59     @Test
     60     public void testCreatesCorrectClasses() throws Exception {
     61         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/media");
     62         TestUtil.assertInstanceOf(LinearLayout.class, view);
     63 
     64         assertSame(context, view.getContext());
     65     }
     66 
     67     @Test
     68     public void testChoosesLayoutBasedOnDefaultScreenSize() throws Exception {
     69         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
     70         TextView textView = (TextView) view.findViewById(android.R.id.text1);
     71         assertThat(textView.getText().toString(), equalTo("default"));
     72     }
     73 
     74     @Test
     75     public void testChoosesLayoutBasedOnSearchPath_choosesFirstFileFoundOnPath() throws Exception {
     76         viewLoader.setLayoutQualifierSearchPath("xlarge", "land");
     77         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
     78         TextView textView = (TextView) view.findViewById(android.R.id.text1);
     79         assertThat(textView.getText().toString(), equalTo("xlarge"));
     80     }
     81 
     82     @Test
     83     public void testChoosesLayoutBasedOnSearchPath_respectsOrderOfPath() throws Exception {
     84         viewLoader.setLayoutQualifierSearchPath("does-not-exist", "land", "xlarge");
     85         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
     86         TextView textView = (TextView) view.findViewById(android.R.id.text1);
     87         assertThat(textView.getText().toString(), equalTo("land"));
     88     }
     89 
     90     @Test
     91     public void testChoosesLayoutBasedOnDefaultVersion() throws Exception {
     92         Robolectric.Reflection.setFinalStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.FROYO);
     93         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
     94         TextView textView = (TextView) view.findViewById(android.R.id.text1);
     95         assertThat(textView.getText().toString(), equalTo("default"));
     96     }
     97 
     98     @Test
     99     public void testChoosesLayoutBasedOnNewestVersion() throws Exception {
    100         Robolectric.Reflection.setFinalStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.JELLY_BEAN);
    101         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
    102         TextView textView = (TextView) view.findViewById(android.R.id.text1);
    103         assertThat(textView.getText().toString(), equalTo("v11"));
    104     }
    105 
    106     @Test
    107     public void testChoosesLayoutBasedOnSearchPath_choosesFirstFileFoundOnPathWithVersionNumber() throws Exception {
    108         viewLoader.setLayoutQualifierSearchPath("xlarge", "large");
    109         Robolectric.Reflection.setFinalStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.HONEYCOMB);
    110         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
    111         TextView textView = (TextView) view.findViewById(android.R.id.text1);
    112         assertThat(textView.getText().toString(), equalTo("xlarge-v11"));
    113     }
    114 
    115     @Test
    116     public void testChoosesLayoutBasedOnSearchPath_choosesBestFileFoundOnPathWithVersionNumber() throws Exception {
    117         viewLoader.setLayoutQualifierSearchPath("xlarge", "large");
    118         Robolectric.Reflection.setFinalStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.JELLY_BEAN);
    119         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/different_screen_sizes");
    120         TextView textView = (TextView) view.findViewById(android.R.id.text1);
    121         assertThat(textView.getText().toString(), equalTo("xlarge-v11"));
    122     }
    123 
    124     @Test
    125     public void testWebView() throws Exception {
    126         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/webview_holder");
    127         WebView webView = (WebView) view.findViewById(R.id.web_view);
    128 
    129         webView.loadUrl("www.example.com");
    130 
    131         assertThat(shadowOf(webView).getLastLoadedUrl(), equalTo("www.example.com"));
    132     }
    133 
    134     @Test
    135     public void testAddsChildren() throws Exception {
    136         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/media");
    137         assertTrue(view.getChildCount() > 0);
    138 
    139         assertSame(context, view.getChildAt(0).getContext());
    140     }
    141 
    142     @Test
    143     public void testFindsChildrenById() throws Exception {
    144         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/media");
    145         TestUtil.assertInstanceOf(TextView.class, mediaView.findViewById(R.id.title));
    146 
    147         ViewGroup mainView = (ViewGroup) viewLoader.inflateView(context, "layout/main");
    148         assertInstanceOf(View.class, mainView.findViewById(R.id.title));
    149     }
    150 
    151     @Test
    152     public void testInflatingConflictingSystemAndLocalViewsWorks() throws Exception {
    153         ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/activity_list_item");
    154         assertInstanceOf(ImageView.class, view.findViewById(R.id.icon));
    155 
    156         view = (ViewGroup) viewLoader.inflateView(context, "android:layout/activity_list_item");
    157         assertInstanceOf(ImageView.class, view.findViewById(android.R.id.icon));
    158     }
    159 
    160     @Test
    161     public void testInclude() throws Exception {
    162         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/media");
    163         assertInstanceOf(TextView.class, mediaView.findViewById(R.id.include_id));
    164     }
    165 
    166     @Test
    167     public void testIncludeShouldRetainAttributes() throws Exception {
    168         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/media");
    169         assertThat(mediaView.findViewById(R.id.include_id).getVisibility(), is(View.GONE));
    170     }
    171 
    172     @Test
    173     public void shouldOverwriteIdOnIncludedNonMerge() throws Exception {
    174         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/media");
    175         assertNull(mediaView.findViewById(R.id.snippet_text));
    176     }
    177 
    178     @Test
    179     public void shouldRetainIdOnIncludedMergeWhenIncludeSpecifiesNoId() throws Exception {
    180         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/override_include");
    181         assertInstanceOf(TextView.class, mediaView.findViewById(R.id.inner_text));
    182     }
    183 
    184     @Test
    185     public void shouldRetainIdOnIncludedNonMergeWhenIncludeSpecifiesNoId() throws Exception {
    186         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/override_include");
    187         assertInstanceOf(TextView.class, mediaView.findViewById(R.id.snippet_text));
    188     }
    189 
    190     @Test
    191     public void testIncludedIdShouldNotBeFoundWhenIncludedIsMerge() throws Exception {
    192         ViewGroup overrideIncludeView = (ViewGroup) viewLoader.inflateView(context, "layout/outer");
    193         assertInstanceOf(LinearLayout.class, overrideIncludeView.findViewById(R.id.outer_merge));
    194         assertInstanceOf(TextView.class, overrideIncludeView.findViewById(R.id.inner_text));
    195         assertNull(overrideIncludeView.findViewById(R.id.include_id));
    196         assertEquals(1, overrideIncludeView.getChildCount());
    197     }
    198 
    199     @Test
    200     public void testIncludeShouldOverrideAttributesOfIncludedRootNode() throws Exception {
    201         ViewGroup overrideIncludeView = (ViewGroup) viewLoader.inflateView(context, "layout/override_include");
    202         assertThat(overrideIncludeView.findViewById(R.id.snippet_text).getVisibility(), is(View.INVISIBLE));
    203     }
    204 
    205     @Test
    206     public void shouldNotCountRequestFocusElementAsChild() throws Exception {
    207         ViewGroup viewGroup = (ViewGroup) viewLoader.inflateView(context, "layout/request_focus");
    208         ViewGroup frameLayout = (ViewGroup) viewGroup.getChildAt(1);
    209         assertEquals(0, frameLayout.getChildCount());
    210     }
    211 
    212     @Test
    213     public void shouldGiveFocusToElementContainingRequestFocusElement() throws Exception {
    214         ViewGroup viewGroup = (ViewGroup) viewLoader.inflateView(context, "layout/request_focus");
    215         EditText editText = (EditText) viewGroup.findViewById(R.id.edit_text);
    216         assertFalse(editText.isFocused());
    217     }
    218 
    219     @Test
    220     public void shouldGiveFocusToFirstFocusableElement_butThisMightBeTheWrongBehavior() throws Exception {
    221         ViewGroup viewGroup = (ViewGroup) viewLoader.inflateView(context, "layout/request_focus_with_two_edit_texts");
    222         assertTrue(viewGroup.findViewById(R.id.edit_text).isFocused());
    223         assertFalse(viewGroup.findViewById(R.id.edit_text2).isFocused());
    224     }
    225 
    226     @Test
    227     public void testMerge() throws Exception {
    228         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/outer");
    229         TestUtil.assertInstanceOf(TextView.class, mediaView.findViewById(R.id.inner_text));
    230     }
    231 
    232     @Test
    233     public void mergeIncludesShouldNotCreateAncestryLoops() throws Exception {
    234         ViewGroup mediaView = (ViewGroup) viewLoader.inflateView(context, "layout/outer");
    235         mediaView.hasFocus();
    236     }
    237 
    238     @Test
    239     public void testViewGroupsLooksAtItsOwnId() throws Exception {
    240         TextView mediaView = (TextView) viewLoader.inflateView(context, "layout/snippet");
    241         assertSame(mediaView, mediaView.findViewById(R.id.snippet_text));
    242     }
    243 
    244     @Test
    245     public void shouldConstructCustomViewsWithAttributesConstructor() throws Exception {
    246         CustomView view = (CustomView) viewLoader.inflateView(context, "layout/custom_layout");
    247         assertThat(view.attributeResourceValue, equalTo(R.string.hello));
    248     }
    249 
    250     @Test
    251     public void testViewVisibilityIsSet() throws Exception {
    252         View mediaView = viewLoader.inflateView(context, "layout/media");
    253         assertThat(mediaView.findViewById(R.id.title).getVisibility(), equalTo(View.VISIBLE));
    254         assertThat(mediaView.findViewById(R.id.subtitle).getVisibility(), equalTo(View.GONE));
    255     }
    256 
    257     @Test
    258     public void testTextViewTextIsSet() throws Exception {
    259         View mediaView = viewLoader.inflateView(context, "layout/main");
    260         assertThat(((TextView) mediaView.findViewById(R.id.title)).getText().toString(), equalTo("Main Layout"));
    261         assertThat(((TextView) mediaView.findViewById(R.id.subtitle)).getText().toString(), equalTo("Hello"));
    262     }
    263 
    264     @Test
    265     public void testTextViewCompoundDrawablesAreSet() throws Exception {
    266         View mediaView = viewLoader.inflateView(context, "layout/main");
    267         ShadowTextView shadowTextView = shadowOf((TextView) mediaView.findViewById(R.id.title));
    268 
    269         assertThat(shadowTextView.getCompoundDrawablesImpl().getTop(), equalTo(R.drawable.an_image));
    270         assertThat(shadowTextView.getCompoundDrawablesImpl().getRight(), equalTo(R.drawable.an_other_image));
    271         assertThat(shadowTextView.getCompoundDrawablesImpl().getBottom(), equalTo(R.drawable.third_image));
    272         assertThat(shadowTextView.getCompoundDrawablesImpl().getLeft(), equalTo(R.drawable.fourth_image));
    273     }
    274 
    275     @Test
    276     public void testCheckBoxCheckedIsSet() throws Exception {
    277         View mediaView = viewLoader.inflateView(context, "layout/main");
    278         assertThat(((CheckBox) mediaView.findViewById(R.id.true_checkbox)).isChecked(), equalTo(true));
    279         assertThat(((CheckBox) mediaView.findViewById(R.id.false_checkbox)).isChecked(), equalTo(false));
    280         assertThat(((CheckBox) mediaView.findViewById(R.id.default_checkbox)).isChecked(), equalTo(false));
    281     }
    282 
    283     @Test
    284     public void testImageViewSrcIsSet() throws Exception {
    285         View mediaView = viewLoader.inflateView(context, "layout/main");
    286         assertThat(((ShadowImageView) shadowOf(mediaView.findViewById(R.id.image))).getResourceId(), equalTo(R.drawable.an_image));
    287     }
    288 
    289     @Test
    290     public void shouldInflateMergeLayoutIntoParent() throws Exception {
    291         View innerMerge = viewLoader.inflateView(context, R.layout.inner_merge, new LinearLayout(null));
    292         assertNotNull(innerMerge);
    293     }
    294 
    295     @Test
    296     public void testMapView() throws Exception {
    297         RelativeLayout mainView = (RelativeLayout) viewLoader.inflateView(context, "layout/mapview");
    298         TestUtil.assertInstanceOf(MapView.class, mainView.findViewById(R.id.map_view));
    299     }
    300 
    301     @Test
    302     public void testViewEnabled() throws Exception {
    303         View mediaView = viewLoader.inflateView(context, "layout/main");
    304         assertThat(mediaView.findViewById(R.id.time).isEnabled(), equalTo(false));
    305     }
    306 
    307     @Test
    308     public void testContentDescriptionIsSet() throws Exception {
    309         View mediaView = viewLoader.inflateView(context, "layout/main");
    310         assertThat(mediaView.findViewById(R.id.time).getContentDescription().toString(), equalTo("Howdy"));
    311     }
    312 
    313     @Test
    314     public void testViewBackgroundIdIsSet() throws Exception {
    315         View mediaView = viewLoader.inflateView(context, "layout/main");
    316         ImageView imageView = (ImageView) mediaView.findViewById(R.id.image);
    317         ShadowImageView shadowImageView = Robolectric.shadowOf(imageView);
    318 
    319         assertThat(shadowImageView.getBackgroundResourceId(), equalTo(R.drawable.image_background));
    320     }
    321 
    322     @Test
    323     public void testOnClickAttribute() throws Exception {
    324         ClickActivity activity = new ClickActivity();
    325         activity.onCreate(null);
    326 
    327         assertThat(activity.clicked, equalTo(false));
    328 
    329         Button button = (Button)activity.findViewById(R.id.button);
    330         button.performClick();
    331 
    332         assertThat(activity.clicked, equalTo(true));
    333     }
    334 
    335     @Test
    336     public void testInvalidOnClickAttribute() throws Exception {
    337         Activity activity = new Activity();
    338         activity.setContentView(R.layout.with_invalid_onclick);
    339 
    340         Button button =
    341             (Button)activity.findViewById(R.id.invalid_onclick_button);
    342 
    343         IllegalStateException exception = null;
    344         try {
    345             button.performClick();
    346         } catch (IllegalStateException e) {
    347             exception = e;
    348         } finally {
    349             assertNotNull(exception);
    350             assertThat("The error message should contain the id name of the "
    351                        + "faulty button",
    352                        exception.getMessage(),
    353                        containsString("invalid_onclick_button"));
    354         }
    355     }
    356 
    357     @Test
    358     public void shouldInvokeOnFinishInflate() throws Exception {
    359         CustomView2 outerCustomView = (CustomView2) viewLoader.inflateView(context, "layout/custom_layout2");
    360         CustomView2 innerCustomView = (CustomView2) outerCustomView.getChildAt(0);
    361         assertThat(outerCustomView.childCountAfterInflate, equalTo(1));
    362         assertThat(innerCustomView.childCountAfterInflate, equalTo(3));
    363     }
    364 
    365     @Test
    366     public void testIncludesLinearLayoutsOnlyOnce() throws Exception {
    367         ViewGroup parentView = (ViewGroup) viewLoader.inflateView(context, "layout/included_layout_parent");
    368         assertEquals(1, parentView.getChildCount());
    369     }
    370 
    371     @Test(expected=I18nException.class)
    372     public void shouldThrowI18nExceptionOnLayoutWithBareStrings() throws Exception {
    373     	viewLoader.setStrictI18n(true);
    374         new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout"));
    375         new DocumentLoader(viewLoader).loadSystemResourceXmlDir(getSystemResourceDir("layout"));
    376 
    377     	viewLoader.inflateView(context,"layout/text_views");
    378     }
    379 
    380     public static class ClickActivity extends Activity {
    381         public boolean clicked = false;
    382 
    383         @Override protected void onCreate(Bundle savedInstanceState) {
    384             super.onCreate(savedInstanceState);
    385             setContentView(R.layout.main);
    386         }
    387 
    388         public void onButtonClick(View v) {
    389             clicked = true;
    390         }
    391     }
    392 }
    393