1306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli/* 2306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * Copyright (C) 2017 The Android Open Source Project 3306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * 4306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * Licensed under the Apache License, Version 2.0 (the "License"); 5306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * you may not use this file except in compliance with the License. 6306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * You may obtain a copy of the License at 7306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * 8306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * http://www.apache.org/licenses/LICENSE-2.0 9306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * 10306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * Unless required by applicable law or agreed to in writing, software 11306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * distributed under the License is distributed on an "AS IS" BASIS, 12306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * See the License for the specific language governing permissions and 14306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * limitations under the License. 15306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli */ 16306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.widget; 18306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 19306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport static org.junit.Assert.assertEquals; 20306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport static org.junit.Assert.assertFalse; 21306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport static org.junit.Assert.assertTrue; 22306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 23306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.content.Context; 24306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.support.test.InstrumentationRegistry; 25306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.support.test.filters.SmallTest; 26306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.support.test.runner.AndroidJUnit4; 27306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.text.InputType; 28306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.view.ContextThemeWrapper; 29306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport android.widget.FrameLayout; 30306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 31d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Guimport androidx.core.os.BuildCompat; 328619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.test.R; 338619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas 34306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport org.junit.Before; 35306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport org.junit.Test; 36306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangliimport org.junit.runner.RunWith; 37306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 38d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Guimport java.util.Arrays; 39d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 40306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli@SmallTest 41306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli@RunWith(AndroidJUnit4.class) 42306fba1d4665743f6b4f6e609fb2565e25c14c71jingjianglipublic class GuidedActionStylistTest { 43306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli private static final int DEFAULT_MAX_LINES = 0; 44306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 45306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Simulate Android Context 46306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli private Context mContext; 47306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 48306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // The GuidedActionStylist for testing purpose 49306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli private GuidedActionsStylist mGuidedActionsStylist; 50306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 51306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Mocked view holder, required by the parameter of onBindViewHolder method 52306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli private GuidedActionsStylist.ViewHolder mViewHolder; 53306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 54306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Mocked action object, required by the parameter of onBindViewHolder method 55306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli private GuidedAction mGuidedAction; 56306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 57306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli @Before 58306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli public void setUp() throws Exception { 59306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 60306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Get context from instrumentation registry firstly 61306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 62306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 63306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Then apply the theme on the context 64306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mContext = new ContextThemeWrapper(mContext, 65306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli R.style.Widget_Leanback_GuidedSubActionsListStyle); 66306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 67306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Prepare GuidedActionStylist object 68306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mGuidedActionsStylist = new GuidedActionsStylist(); 69306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 70306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 71306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli @Override 72306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli public void run() { 73306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Create view holder object programmatically 74306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mViewHolder = mGuidedActionsStylist.onCreateViewHolder(new FrameLayout(mContext)); 75306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli } 76306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli }); 77306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli } 78306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 79306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli /** 80306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * Test cases when multilineDescription is set to true 81306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli */ 82306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli @Test 83306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli public void testWhenMultiLineDescriptionSetToTrue() { 84306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 85306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Create a action and set multilineDescription to true 86306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mGuidedAction = new GuidedAction.Builder(mContext).multilineDescription(true).build(); 87306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 88306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Execute onBindViewHolder method so we can monitor the internal state 89306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mGuidedActionsStylist.onBindViewHolder(mViewHolder, mGuidedAction); 90306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 91306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // double check if multilineDescription option has been enabled 92306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli assertTrue(mGuidedAction.hasMultilineDescription()); 93306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 94306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // currently the title view and description view using the same flag. So when we execute 95306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // multilineDescription(true) method, the multi line mode should be enabled both for title 96306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // view and description view. 97306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Test cases should be updated when we change this behavior 98306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli assertTrue((mViewHolder.mTitleView.getInputType() & InputType.TYPE_TEXT_FLAG_MULTI_LINE) 99306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli == InputType.TYPE_TEXT_FLAG_MULTI_LINE); 100306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli assertTrue((mViewHolder.mDescriptionView.getInputType() 101306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == InputType.TYPE_TEXT_FLAG_MULTI_LINE); 102306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli } 103306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 104306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli /** 105306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli * Test cases when multilineDescription is set to false 106306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli */ 107306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli @Test 108306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli public void testWhenMultiLineDescriptionSetToFalse() { 109306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 110306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Create a action and set multilineDescription to false 111306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mGuidedAction = new GuidedAction.Builder(mContext).multilineDescription(false).build(); 112306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 113306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Execute onBindViewHolder method so we can monitor the internal state 114306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli mGuidedActionsStylist.onBindViewHolder(mViewHolder, mGuidedAction); 115306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 116306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // double check if multilineDescription option has been disabled 117306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli assertFalse(mGuidedAction.hasMultilineDescription()); 118306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli 119306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // currently the title view and description view using the same flag. So when we execute 120306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // multilineDescription(true) method, the multi line mode should be disabled both for title 121306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // view and description view. 122306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli // Test cases should be updated when we change this behavior 123306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli assertEquals(mViewHolder.mTitleView.getMaxLines(), DEFAULT_MAX_LINES); 124306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli assertEquals(mViewHolder.mDescriptionView.getMaxLines(), DEFAULT_MAX_LINES); 125306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli } 126d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 127d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu @Test 128d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu public void testAutofillHintsOnTitle() { 129d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu if (!BuildCompat.isAtLeastP()) { 130d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu return; 131d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu } 132d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu String[] hints = new String[]{"hint1", "hint2"}; 133d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu mGuidedAction = new GuidedAction.Builder(mContext) 134d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .editable(true) 135d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .autofillHints(hints) 136d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .build(); 137d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 138d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu assertTrue(BuildCompat.isAtLeastP()); 139d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu // Execute onBindViewHolder method so we can monitor the internal state 140d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu mGuidedActionsStylist.onBindViewHolder(mViewHolder, mGuidedAction); 141d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 142d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu assertTrue(Arrays.equals(mViewHolder.mTitleView.getAutofillHints(), hints)); 143d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 144d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu } 145d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 146d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu @Test 147d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu public void testAutofillHintsOnNonEditableViews() { 148d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu if (!BuildCompat.isAtLeastP()) { 149d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu return; 150d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu } 151d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu String[] hints = new String[]{"hint1", "hint2"}; 152d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu mGuidedAction = new GuidedAction.Builder(mContext) 153d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .editable(false) 154d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .autofillHints(hints) 155d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .build(); 156d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 157d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu // Execute onBindViewHolder method so we can monitor the internal state 158d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu mGuidedActionsStylist.onBindViewHolder(mViewHolder, mGuidedAction); 159d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 160d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu String[] viewHints = mViewHolder.mTitleView.getAutofillHints(); 161d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu assertTrue(viewHints == null || viewHints.length == 0); 162d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 163d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu viewHints = mViewHolder.mDescriptionView.getAutofillHints(); 164d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu assertTrue(viewHints == null || viewHints.length == 0); 165d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu } 166d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 167d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu @Test 168d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu public void testAutofillHintsOnDescription() { 169d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu if (!BuildCompat.isAtLeastP()) { 170d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu return; 171d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu } 172d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu String[] hints = new String[]{"hint1", "hint2"}; 173d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu mGuidedAction = new GuidedAction.Builder(mContext) 174d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .editable(false) 175d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .descriptionEditable(true) 176d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .autofillHints(hints) 177d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu .build(); 178d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 179d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu // Execute onBindViewHolder method so we can monitor the internal state 180d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu mGuidedActionsStylist.onBindViewHolder(mViewHolder, mGuidedAction); 181d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 182d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu assertTrue(Arrays.equals(mViewHolder.mDescriptionView.getAutofillHints(), hints)); 183d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 184d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu } 185d1d1d1a4a5a12a5e4541ccc37ce48cd130b2bc5dDake Gu 186306fba1d4665743f6b4f6e609fb2565e25c14c71jingjiangli} 187