1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v7.widget;
18
19import org.junit.Before;
20import org.junit.Test;
21import org.junit.runner.RunWith;
22
23import android.support.test.InstrumentationRegistry;
24import android.support.test.runner.AndroidJUnit4;
25import android.test.AndroidTestCase;
26import android.test.mock.MockContext;
27import android.test.suitebuilder.annotation.SmallTest;
28import android.view.View;
29import android.view.ViewGroup;
30
31import java.util.ArrayList;
32import java.util.List;
33
34@RunWith(AndroidJUnit4.class)
35@SmallTest
36public class ChildHelperTest extends AndroidTestCase {
37    LoggingCallback  mLoggingCallback;
38    ChildHelper mChildHelper;
39
40    @Before
41    public void prepare() throws Exception {
42        setUp();
43        setContext(InstrumentationRegistry.getContext());
44        mLoggingCallback = new LoggingCallback();
45        mChildHelper = new ChildHelper(mLoggingCallback);
46    }
47
48    private RecyclerView.ViewHolder vh() {
49        View view = new View(mContext);
50        RecyclerViewBasicTest.MockViewHolder mockViewHolder
51                = new RecyclerViewBasicTest.MockViewHolder(view);
52        RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(0 , 0);
53        lp.mViewHolder = mockViewHolder;
54        view.setLayoutParams(lp);
55        return mockViewHolder;
56    }
57
58    @Test
59    public void addChild() {
60        RecyclerView.ViewHolder vh = vh();
61        mChildHelper.addView(vh.itemView, false);
62        assertEquals(1, mLoggingCallback.getChildCount());
63        assertFalse(mChildHelper.isHidden(vh.itemView));
64        assertEquals(0, mLoggingCallback.mOnEnteredHiddenState.size());
65    }
66
67    @Test
68    public void addChildHidden() {
69        RecyclerView.ViewHolder vh = vh();
70        mChildHelper.addView(vh.itemView, true);
71        assertEquals(1, mLoggingCallback.getChildCount());
72        assertTrue(mChildHelper.isHidden(vh.itemView));
73        assertTrue(mLoggingCallback.mOnEnteredHiddenState.contains(vh.itemView));
74    }
75
76    @Test
77    public void addChildAndHide() {
78        RecyclerView.ViewHolder vh = vh();
79        mChildHelper.addView(vh.itemView, false);
80        mChildHelper.hide(vh.itemView);
81        assertTrue(mChildHelper.isHidden(vh.itemView));
82        mChildHelper.unhide(vh.itemView);
83        assertFalse(mChildHelper.isHidden(vh.itemView));
84    }
85
86    @Test
87    public void findHiddenNonRemoved() {
88        RecyclerView.ViewHolder vh = vh();
89        vh.mPosition = 12;
90        mChildHelper.addView(vh.itemView, true);
91        assertSame(vh.itemView,
92                mChildHelper.findHiddenNonRemovedView(12, RecyclerView.INVALID_TYPE));
93    }
94
95    @Test
96    public void findHiddenRemoved() {
97        RecyclerView.ViewHolder vh = vh();
98        vh.mPosition = 12;
99        vh.addFlags(RecyclerView.ViewHolder.FLAG_REMOVED);
100        mChildHelper.addView(vh.itemView, true);
101        assertNull(mChildHelper.findHiddenNonRemovedView(12, RecyclerView.INVALID_TYPE));
102    }
103
104    private static class LoggingCallback implements ChildHelper.Callback {
105        List<View> mViews = new ArrayList<>();
106        List<View> mDetached = new ArrayList<>();
107        List<View> mOnEnteredHiddenState = new ArrayList<>();
108        List<View> mOnExitedHiddenState = new ArrayList<>();
109        @Override
110        public int getChildCount() {
111            return mViews.size();
112        }
113
114        @Override
115        public void addView(View child, int index) {
116            mViews.add(index, child);
117        }
118
119        @Override
120        public int indexOfChild(View view) {
121            return mViews.indexOf(view);
122        }
123
124        private boolean validateIndex(int index) {
125            return index < getChildCount() && index >= 0;
126        }
127
128        @Override
129        public void removeViewAt(int index) {
130            if (validateIndex(index)) {
131                mViews.remove(index);
132            }
133        }
134
135        @Override
136        public View getChildAt(int offset) {
137            if (validateIndex(offset)) {
138                return mViews.remove(offset);
139            }
140            return null;
141        }
142
143        @Override
144        public void removeAllViews() {
145            mViews.clear();
146        }
147
148        @Override
149        public RecyclerView.ViewHolder getChildViewHolder(View view) {
150            return RecyclerView.getChildViewHolderInt(view);
151        }
152
153        @Override
154        public void attachViewToParent(View child, int index, ViewGroup.LayoutParams layoutParams) {
155            assertTrue(mDetached.remove(child));
156            addView(child, index);
157        }
158
159        @Override
160        public void detachViewFromParent(int offset) {
161            mDetached.add(getChildAt(offset));
162        }
163
164        @Override
165        public void onEnteredHiddenState(View child) {
166            mOnEnteredHiddenState.add(child);
167        }
168
169        @Override
170        public void onLeftHiddenState(View child) {
171            mOnExitedHiddenState.add(child);
172        }
173    }
174}
175