Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
language: android

addons:
artifacts: true

android:
components:
# Uncomment the lines below if you want to
Expand Down Expand Up @@ -28,7 +32,7 @@ android:
#- adb shell input keyevent 82 &

# Don't do connectedCheck to skip instrumentTest on Travis
script: "./gradlew build"
script: "./gradlew build --info"

jdk:
- oraclejdk8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ protected void prepareDependencies(MvcComponent testComponent) throws Exception

@After
public void tearDown() throws Exception {
navigationManager.navigate(this).back(null);
navigationManager.navigate(this).back();
try {
Mvc.graph().getRootComponent().getCache().clear();
Mvc.graph().getRootComponent().detach(component);
Expand Down
9 changes: 9 additions & 0 deletions samples/simple-mvp/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ dependencies {

compile 'com.jakewharton:butterknife:8.2.1'
apt 'com.jakewharton:butterknife-compiler:8.2.1'

// Testing-only dependencies
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile "com.android.support:support-annotations:$rootProject.supportLibVersion"
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
}

android {
Expand All @@ -48,6 +55,8 @@ android {
versionName "1.0.0"

multiDexEnabled false

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

sourceSets {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.shipdream.lib.android.mvc.samples.simple.mvp.view;

import android.content.Intent;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;

import com.shipdream.lib.android.mvc.Mvc;
import com.shipdream.lib.android.mvc.MvcComponent;
import com.shipdream.lib.android.mvc.NavigationManager;
import com.shipdream.lib.android.mvc.samples.simple.mvp.MainActivity;
import com.shipdream.lib.android.mvc.samples.simple.mvp.R;
import com.shipdream.lib.android.mvc.samples.simple.mvp.controller.CounterDetailController;
import com.shipdream.lib.android.mvc.samples.simple.mvp.dto.IpPayload;
import com.shipdream.lib.android.mvc.samples.simple.mvp.factory.ServiceFactory;
import com.shipdream.lib.android.mvc.samples.simple.mvp.http.IpService;
import com.shipdream.lib.poke.Provides;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;

import javax.inject.Inject;

import retrofit2.Call;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class TestDetailScreen {
private MvcComponent testComponent;
private Call<IpPayload> ipServiceCallMock;
@Inject
private NavigationManager navigationManager;

@Rule
public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(
MainActivity.class,
false, // initialTouchMode
false); // launchActivity. False to set intent per test);

@Before
public void prepareInjection() throws Exception {
testComponent = new MvcComponent("TestComponent");
testComponent.register(new Object(){
/**
* Prepare objects to mock http calls
* @return
* @throws IOException
*/
@Provides
public ServiceFactory serviceFactory() throws IOException {
ipServiceCallMock = mock(Call.class);

IpService ipServiceMock = mock(IpService.class);
when(ipServiceMock.getIp(anyString())).thenReturn(ipServiceCallMock);

ServiceFactory serviceFactoryMock = mock(ServiceFactory.class);
when(serviceFactoryMock.createService(IpService.class)).thenReturn(ipServiceMock);
return serviceFactoryMock;
}
});

boolean overriding = true;
Mvc.graph().getRootComponent().attach(testComponent, overriding);

Mvc.graph().inject(this);

rule.launchActivity(new Intent());

navigationManager.navigate(this).to(CounterDetailController.class);
}

@After
public void tearDown() throws Exception {
//Important!!!
//To clear fragment manager's back stack
navigationManager.navigate(this).back(null);
navigationManager.navigate(this).back();

//Remove overriding component
Mvc.graph().getRootComponent().detach(testComponent);
}

@Test
public void should_be_able_to_increment_and_decrement_count() {
//Initial value is 0
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("0")));

//Click increment and check text view value
onView(withId(R.id.screen_detail_buttonIncrement)).perform(click());
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("1")));

//Click decrement and check text view value
onView(withId(R.id.screen_detail_buttonDecrement)).perform(click());
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("0")));
}

@Test
public void should_be_able_to_increment_and_decrement_count2() {
//Initial value is 0
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("0")));

//Click increment and check text view value
onView(withId(R.id.screen_detail_buttonIncrement)).perform(click());
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("1")));

//Click decrement and check text view value
onView(withId(R.id.screen_detail_buttonDecrement)).perform(click());
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("0")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* Copyright 2016 Kejun Xia
*
* 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.shipdream.lib.android.mvc.samples.simple.mvp.view;

import android.content.Intent;
import android.support.test.espresso.matcher.ViewMatchers;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;

import com.shipdream.lib.android.mvc.Mvc;
import com.shipdream.lib.android.mvc.MvcComponent;
import com.shipdream.lib.android.mvc.NavigationManager;
import com.shipdream.lib.android.mvc.samples.simple.mvp.MainActivity;
import com.shipdream.lib.android.mvc.samples.simple.mvp.R;
import com.shipdream.lib.android.mvc.samples.simple.mvp.dto.IpPayload;
import com.shipdream.lib.android.mvc.samples.simple.mvp.factory.ServiceFactory;
import com.shipdream.lib.android.mvc.samples.simple.mvp.http.IpService;
import com.shipdream.lib.poke.Provides;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;

import javax.inject.Inject;

import retrofit2.Call;
import retrofit2.Response;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class TestMasterScreen {
private MvcComponent testComponent;
private Call<IpPayload> ipServiceCallMock;
@Inject
private NavigationManager navigationManager;

@Rule
public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(
MainActivity.class,
false, // initialTouchMode
false); // launchActivity. False to set intent per test);

@Before
public void prepareInjection() throws Exception {
testComponent = new MvcComponent("TestComponent");
testComponent.register(new Object(){
/**
* Prepare objects to mock http calls
* @return
* @throws IOException
*/
@Provides
public ServiceFactory serviceFactory() throws IOException {
ipServiceCallMock = mock(Call.class);

IpService ipServiceMock = mock(IpService.class);
when(ipServiceMock.getIp(anyString())).thenReturn(ipServiceCallMock);

ServiceFactory serviceFactoryMock = mock(ServiceFactory.class);
when(serviceFactoryMock.createService(IpService.class)).thenReturn(ipServiceMock);
return serviceFactoryMock;
}
});

boolean overriding = true;
Mvc.graph().getRootComponent().attach(testComponent, overriding);
Mvc.graph().inject(this);

rule.launchActivity(new Intent());
}

@After
public void tearDown() throws Exception {
//Important!!!
//To clear fragment manager's back stack
navigationManager.navigate(this).back(null);
navigationManager.navigate(this).back();

//Remove overriding component
Mvc.graph().getRootComponent().detach(testComponent);
}

@Test
public void should_be_able_to_increment_and_decrement_count() {
//Initial value is 0
onView(withId(R.id.screen_master_counterDisplay)).check(matches(withText("0")));

//Click increment and check text view value
onView(withId(R.id.screen_master_buttonIncrement)).perform(click());
onView(withId(R.id.screen_master_counterDisplay)).check(matches(withText("1")));

//Click decrement and check text view value
onView(withId(R.id.screen_master_buttonDecrement)).perform(click());
onView(withId(R.id.screen_master_counterDisplay)).check(matches(withText("0")));
}

@Test
public void should_carry_count_to_detail_screen() {
//Initial value is 0
onView(withId(R.id.screen_master_counterDisplay)).check(matches(withText("0")));

//Click increment and check text view value
onView(withId(R.id.screen_master_buttonIncrement)).perform(click());
onView(withId(R.id.screen_master_counterDisplay)).check(matches(withText("1")));

//Navigate to detail screen
onView(withId(R.id.fragment_master_buttonShowDetailScreen)).perform(click());

//Check count on detail screen
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("1")));

//Click decrement and check text view value
onView(withId(R.id.screen_detail_buttonIncrement)).perform(click());
onView(withId(R.id.screen_detail_counterDisplay)).check(matches(withText("2")));

navigationManager.navigate(this).back();
onView(withId(R.id.screen_master_counterDisplay)).check(matches(withText("2")));
}

@Test
public void should_be_able_to_get_ip() throws Exception{
//Pre check
onView(withId(R.id.fragment_master_ipValue)).check(
matches(withEffectiveVisibility(ViewMatchers.Visibility.INVISIBLE)));

final String fakeIpResult = "abc.123.456.xyz";
IpPayload payload = mock(IpPayload.class);
when(payload.getIp()).thenReturn(fakeIpResult);
when(ipServiceCallMock.execute()).thenReturn(Response.success(payload));

//Action
onView(withId(R.id.fragment_master_ipRefresh)).perform(click());

//Check value
onView(withId(R.id.fragment_master_ipValue)).check(matches(withText(fakeIpResult)));
}

@Test
public void should_be_able_to_show_network_error_when_getting_ip_failed() throws Exception{
//Pre check
onView(withId(R.id.fragment_master_ipValue)).check(
matches(withEffectiveVisibility(ViewMatchers.Visibility.INVISIBLE)));

//Prepare
//Throw an IOException to simulate an network error
IOException ioExceptionMock = mock(IOException.class);
when(ipServiceCallMock.execute()).thenThrow(ioExceptionMock);

//Action
onView(withId(R.id.fragment_master_ipRefresh)).perform(click());

//Check value
onView(withText(R.string.network_error_to_get_ip)).inRoot(
withDecorView(not(is(rule.getActivity().getWindow().getDecorView()))))
.check(matches(isDisplayed()));
}
}
Loading