1/*
2 * Copyright (C) 2016 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 androidx.transition;
18
19import static org.hamcrest.CoreMatchers.is;
20import static org.hamcrest.CoreMatchers.notNullValue;
21import static org.hamcrest.MatcherAssert.assertThat;
22import static org.hamcrest.Matchers.sameInstance;
23import static org.mockito.Matchers.any;
24import static org.mockito.Mockito.mock;
25import static org.mockito.Mockito.never;
26import static org.mockito.Mockito.timeout;
27import static org.mockito.Mockito.verify;
28
29import android.support.test.annotation.UiThreadTest;
30import android.support.test.filters.MediumTest;
31import android.view.ViewGroup;
32
33import androidx.transition.test.R;
34
35import org.junit.Before;
36import org.junit.Test;
37
38@MediumTest
39public class TransitionManagerTest extends BaseTest {
40
41    private Scene[] mScenes = new Scene[2];
42
43    @Before
44    public void prepareScenes() {
45        TransitionActivity activity = rule.getActivity();
46        ViewGroup root = activity.getRoot();
47        mScenes[0] = Scene.getSceneForLayout(root, R.layout.support_scene0, activity);
48        mScenes[1] = Scene.getSceneForLayout(root, R.layout.support_scene1, activity);
49    }
50
51    @Test
52    public void testSetup() {
53        assertThat(mScenes[0], is(notNullValue()));
54        assertThat(mScenes[1], is(notNullValue()));
55    }
56
57    @Test
58    @UiThreadTest
59    public void testGo_enterAction() {
60        CheckCalledRunnable runnable = new CheckCalledRunnable();
61        mScenes[0].setEnterAction(runnable);
62        assertThat(runnable.wasCalled(), is(false));
63        TransitionManager.go(mScenes[0]);
64        assertThat(runnable.wasCalled(), is(true));
65    }
66
67    @Test
68    public void testGo_exitAction() throws Throwable {
69        final CheckCalledRunnable enter = new CheckCalledRunnable();
70        final CheckCalledRunnable exit = new CheckCalledRunnable();
71        mScenes[0].setEnterAction(enter);
72        mScenes[0].setExitAction(exit);
73        rule.runOnUiThread(new Runnable() {
74            @Override
75            public void run() {
76                assertThat(enter.wasCalled(), is(false));
77                assertThat(exit.wasCalled(), is(false));
78                TransitionManager.go(mScenes[0]);
79                assertThat(enter.wasCalled(), is(true));
80                assertThat(exit.wasCalled(), is(false));
81            }
82        });
83        // Let the main thread catch up with the scene change
84        rule.runOnUiThread(new Runnable() {
85            @Override
86            public void run() {
87                TransitionManager.go(mScenes[1]);
88                assertThat(exit.wasCalled(), is(true));
89            }
90        });
91    }
92
93    @Test
94    public void testGo_transitionListenerStart() throws Throwable {
95        final SyncTransitionListener listener =
96                new SyncTransitionListener(SyncTransitionListener.EVENT_START);
97        rule.runOnUiThread(new Runnable() {
98            @Override
99            public void run() {
100                Transition transition = new AutoTransition();
101                transition.setDuration(0);
102                assertThat(transition.addListener(listener), is(sameInstance(transition)));
103                TransitionManager.go(mScenes[0], transition);
104            }
105        });
106        assertThat("Timed out waiting for the TransitionListener",
107                listener.await(), is(true));
108    }
109
110    @Test
111    public void testGo_transitionListenerEnd() throws Throwable {
112        final SyncTransitionListener listener =
113                new SyncTransitionListener(SyncTransitionListener.EVENT_END);
114        rule.runOnUiThread(new Runnable() {
115            @Override
116            public void run() {
117                Transition transition = new AutoTransition();
118                transition.setDuration(0);
119                assertThat(transition.addListener(listener), is(sameInstance(transition)));
120                TransitionManager.go(mScenes[0], transition);
121            }
122        });
123        assertThat("Timed out waiting for the TransitionListener",
124                listener.await(), is(true));
125    }
126
127    @Test
128    public void testGo_nullParameter() throws Throwable {
129        final ViewGroup root = rule.getActivity().getRoot();
130        rule.runOnUiThread(new Runnable() {
131            @Override
132            public void run() {
133                TransitionManager.go(mScenes[0], null);
134                assertThat(Scene.getCurrentScene(root), is(mScenes[0]));
135                TransitionManager.go(mScenes[1], null);
136                assertThat(Scene.getCurrentScene(root), is(mScenes[1]));
137            }
138        });
139    }
140
141    @Test
142    public void testEndTransitions() throws Throwable {
143        final ViewGroup root = rule.getActivity().getRoot();
144        final Transition transition = new AutoTransition();
145        // This transition is very long, but will be forced to end as soon as it starts
146        transition.setDuration(30000);
147        final Transition.TransitionListener listener = mock(Transition.TransitionListener.class);
148        transition.addListener(listener);
149        rule.runOnUiThread(new Runnable() {
150            @Override
151            public void run() {
152                TransitionManager.go(mScenes[0], transition);
153            }
154        });
155        verify(listener, timeout(3000)).onTransitionStart(any(Transition.class));
156        rule.runOnUiThread(new Runnable() {
157            @Override
158            public void run() {
159                TransitionManager.endTransitions(root);
160            }
161        });
162        verify(listener, timeout(3000)).onTransitionEnd(any(Transition.class));
163    }
164
165    @Test
166    public void testEndTransitionsBeforeStarted() throws Throwable {
167        final ViewGroup root = rule.getActivity().getRoot();
168        final Transition transition = new AutoTransition();
169        transition.setDuration(0);
170        final Transition.TransitionListener listener = mock(Transition.TransitionListener.class);
171        transition.addListener(listener);
172        rule.runOnUiThread(new Runnable() {
173            @Override
174            public void run() {
175                TransitionManager.go(mScenes[0], transition);
176                // This terminates the transition before it starts
177                TransitionManager.endTransitions(root);
178            }
179        });
180        verify(listener, never()).onTransitionStart(any(Transition.class));
181        verify(listener, never()).onTransitionEnd(any(Transition.class));
182    }
183
184}
185