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