/*
* Copyright 2017 Gabor Varadi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zhuinden.simplestack;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import com.zhuinden.statebundle.StateBundle;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
/**
* Created by Zhuinden on 2017.02.04..
*/
public class BackstackDelegateTest {
@Mock(extraInterfaces = Bundleable.class)
View view;
@Mock
Context context;
@Mock
Backstack backstack;
@Mock
BackstackManager backstackManager;
@Mock
Bundle savedInstanceState;
@Rule
public MockitoRule rule = MockitoJUnit.rule();
StateChanger stateChanger = new StateChanger() {
@Override
public void handleStateChange(StateChange stateChange, Callback completionCallback) {
completionCallback.stateChangeComplete();
}
};
@Test
public void setNullPersistenceTagShouldThrow() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
try {
backstackDelegate.setPersistenceTag(null);
fail();
} catch(IllegalArgumentException e) {
// OK!
}
}
@Test
public void setSamePersistenceTagTwiceShouldBeOk() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
backstackDelegate.setPersistenceTag(new String("hello"));
backstackDelegate.setPersistenceTag(new String("hello"));
// no exceptions thrown
}
@Test
public void setTwoDifferentPersistenceTagsShouldThrow() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
backstackDelegate.setPersistenceTag(new String("hello"));
try {
backstackDelegate.setPersistenceTag(new String("world"));
fail();
} catch(IllegalStateException e) {
// OK!
}
}
@Test
public void setPersistenceTagAfterOnCreateShouldThrow() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
backstackDelegate.onCreate(null, null, new ArrayList<Object>() {{
add(new TestKey("hello"));
}});
try {
backstackDelegate.setPersistenceTag(new String("world"));
fail();
} catch(IllegalStateException e) {
// OK!
}
}
@Test
public void onCreateRestoresBackstackKeys() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey testKey = new TestKey("hello");
final TestKey restoredKey = new TestKey("world");
ArrayList<Parcelable> restoredKeys = new ArrayList<Parcelable>() {{
add(restoredKey);
}};
StateBundle stateBundle = new StateBundle();
stateBundle.putParcelableArrayList(BackstackManager.getHistoryTag(), restoredKeys);
Mockito.when(savedInstanceState.getParcelable(backstackDelegate.getHistoryTag())).thenReturn(stateBundle);
backstackDelegate.onCreate(savedInstanceState, null, HistoryBuilder.single(testKey));
assertThat(backstackDelegate.getBackstack()).isNotNull();
backstackDelegate.setStateChanger(stateChanger);
assertThat(backstackDelegate.getBackstack().getHistory()).containsExactly(restoredKey);
}
@Test
public void onCreateChoosesInitialKeysIfRestoredHistoryIsEmpty() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey testKey = new TestKey("hello");
ArrayList<Parcelable> restoredKeys = new ArrayList<>();
Mockito.when(savedInstanceState.getParcelableArrayList(backstackDelegate.getHistoryTag())).thenReturn(restoredKeys);
backstackDelegate.onCreate(savedInstanceState, null, HistoryBuilder.single(testKey));
assertThat(backstackDelegate.getBackstack()).isNotNull();
backstackDelegate.setStateChanger(stateChanger);
assertThat(backstackDelegate.getBackstack().getHistory()).containsExactly(testKey);
}
@Test
public void getSavedStateThrowsBeforeOnCreate() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
try {
backstackDelegate.getSavedState(null);
Assert.fail();
} catch(IllegalStateException e) {
// OK
}
}
@Test
public void getSavedStateForNullThrowsException() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey testKey = new TestKey("hello");
backstackDelegate.onCreate(null, null, HistoryBuilder.single(testKey));
try {
backstackDelegate.getSavedState(null);
Assert.fail();
} catch(IllegalArgumentException e) {
// OK
}
}
@Test
public void onCreateInvalidNonConfigurationThrowsException() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
try {
backstackDelegate.onCreate(null, new TestKey("crashpls"), HistoryBuilder.single(new TestKey("hello")));
Assert.fail();
} catch(IllegalArgumentException e) {
// OK
}
}
@Test
public void onCreateRestoresFromNonConfigInstance() {
Mockito.when(backstackManager.getBackstack()).thenReturn(backstack);
BackstackDelegate.NonConfigurationInstance nonConfigurationInstance = new BackstackDelegate.NonConfigurationInstance(
backstackManager);
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey testKey = new TestKey("hello");
backstackDelegate.onCreate(null, nonConfigurationInstance, HistoryBuilder.single(testKey));
assertThat(backstackDelegate.getBackstack()).isSameAs(backstack);
}
@Test
public void testRestoreViewFromState() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey key = new TestKey("hello");
backstackDelegate.onCreate(null, null, HistoryBuilder.single(key));
backstackDelegate.setStateChanger(stateChanger);
Mockito.when(view.getContext()).thenReturn(context);
StateBundle stateBundle = new StateBundle();
Mockito.when(((Bundleable) view).toBundle()).thenReturn(stateBundle);
// noinspection ResourceType
Mockito.when(context.getSystemService(KeyContextWrapper.TAG)).thenReturn(key);
backstackDelegate.persistViewToState(view);
backstackDelegate.restoreViewFromState(view);
((Bundleable) Mockito.verify(view, Mockito.times(1))).fromBundle(stateBundle);
}
@Test
public void onBackPressedGoesBack() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey a = new TestKey("hello");
TestKey b = new TestKey("hello");
backstackDelegate.onCreate(null, null, HistoryBuilder.from(a, b).build());
backstackDelegate.setStateChanger(stateChanger);
assertThat(backstackDelegate.getBackstack().getHistory()).containsExactly(a, b);
backstackDelegate.onBackPressed();
assertThat(backstackDelegate.getBackstack().getHistory()).containsExactly(a);
}
@Test
public void onPostResumeThrowsExceptionIfStateChangerNotSet() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey key = new TestKey("hello");
backstackDelegate.onCreate(null, null, HistoryBuilder.single(key));
// no state changer set
try {
backstackDelegate.onPostResume();
Assert.fail();
} catch(IllegalStateException e) {
// OK
}
}
@Test
public void onPauseRemovesStateChanger() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey key = new TestKey("hello");
backstackDelegate.onCreate(null, null, HistoryBuilder.single(key));
backstackDelegate.setStateChanger(stateChanger);
backstackDelegate.onPause();
assertThat(backstackDelegate.getBackstack().hasStateChanger()).isFalse();
}
@Test
public void onPostResumeReattachesStateChanger() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
TestKey key = new TestKey("hello");
backstackDelegate.onCreate(null, null, HistoryBuilder.single(key));
backstackDelegate.setStateChanger(stateChanger);
backstackDelegate.onPause();
assertThat(backstackDelegate.getBackstack().hasStateChanger()).isFalse();
backstackDelegate.onPostResume();
assertThat(backstackDelegate.getBackstack().hasStateChanger()).isTrue();
}
@Test
public void getBackstackShouldThrowIfOnCreateNotCalled() {
BackstackDelegate backstackDelegate = new BackstackDelegate(null);
try {
backstackDelegate.getBackstack();
Assert.fail();
} catch(IllegalStateException e) {
// OK
}
}
}