diff --git a/News-Android-App/build.gradle b/News-Android-App/build.gradle index e47c0ff0..f4231746 100644 --- a/News-Android-App/build.gradle +++ b/News-Android-App/build.gradle @@ -94,6 +94,13 @@ dependencies { testCompile 'org.robolectric:robolectric:3.0-rc3' testCompile 'junit:junit:4.1' + testCompile("org.mockito:mockito-core:1.10.19") { + exclude group: 'org.hamcrest' + } + testCompile 'com.google.dexmaker:dexmaker:1.2' + testCompile 'com.google.dexmaker:dexmaker-mockito:1.2' + + androidTestCompile 'com.squareup.okhttp:mockwebserver:2.5.0' androidTestCompile "com.android.support:support-annotations:${SUPPORT_VERSION}" @@ -112,5 +119,10 @@ dependencies { compile 'com.nbsp:library:1.02' - //androidTestCompile 'tools:fastlane:screengrab:0.3.0' + androidTestCompile 'tools.fastlane:screengrab:0.3.1' + androidTestCompile("org.mockito:mockito-core:1.10.19") { + exclude group: 'org.hamcrest' + } + androidTestCompile 'com.google.dexmaker:dexmaker:1.2' + androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' } diff --git a/News-Android-App/src/androidTest/java/ScreenshotTest.java b/News-Android-App/src/androidTest/java/ScreenshotTest.java deleted file mode 100644 index 4631c1cf..00000000 --- a/News-Android-App/src/androidTest/java/ScreenshotTest.java +++ /dev/null @@ -1,37 +0,0 @@ -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import de.luhmer.owncloudnewsreader.NewsReaderListActivity; -import de.luhmer.owncloudnewsreader.R; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.matcher.ViewMatchers.withId; - -/** - * Created by David on 06.03.2016. - */ -@RunWith(AndroidJUnit4.class) -public class ScreenshotTest { - - /* - @ClassRule - public static final LocalTestRule localTestRule = new LocalTestRule(); - - @Rule - public ActivityTestRule mActivityRule = new ActivityTestRule<>(NewsReaderListActivity.class); - - - @Test - public void changeText_sameActivity() { - Screengrab - } - */ - -} diff --git a/News-Android-App/src/androidTest/java/screengrab/ScreenshotTest.java b/News-Android-App/src/androidTest/java/screengrab/ScreenshotTest.java new file mode 100644 index 00000000..08f0869e --- /dev/null +++ b/News-Android-App/src/androidTest/java/screengrab/ScreenshotTest.java @@ -0,0 +1,209 @@ +package screengrab; + +import android.app.Instrumentation; +import android.content.SharedPreferences; +import android.graphics.Point; +import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.support.v4.content.SharedPreferencesCompat; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.test.UiThreadTest; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import de.luhmer.owncloudnewsreader.NewsReaderDetailFragment; +import de.luhmer.owncloudnewsreader.NewsReaderListActivity; +import de.luhmer.owncloudnewsreader.NewsReaderListFragment; +import de.luhmer.owncloudnewsreader.R; + +import de.luhmer.owncloudnewsreader.SettingsActivity; +import de.luhmer.owncloudnewsreader.adapter.NewsListRecyclerAdapter; +import de.luhmer.owncloudnewsreader.adapter.ViewHolder; +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.model.PodcastItem; +import de.luhmer.owncloudnewsreader.model.UserInfo; +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.locale.LocaleTestRule; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Created by David on 06.03.2016. + */ +@RunWith(AndroidJUnit4.class) +public class ScreenshotTest { + @ClassRule + public static final LocaleTestRule localTestRule = new LocaleTestRule(); + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(NewsReaderListActivity.class); + + + private MenuItem menuItem; + private NewsReaderListActivity activity; + private NewsReaderListFragment nrlf; + private NewsReaderDetailFragment nrdf; + private int itemPos = 5; + + @Before + public void setup() { + menuItem = Mockito.mock(MenuItem.class); + activity = mActivityRule.getActivity(); + nrlf = mActivityRule.getActivity().getSlidingListFragment(); + nrdf = mActivityRule.getActivity().getNewsReaderDetailFragment(); + + + SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(mActivityRule.getActivity()); + + UserInfo userInfo = new UserInfo.Builder() + .setUserId("1") + .setDisplayName("David") + .setAvatar(null) + .build(); + + try { + mPrefs.edit().putString("USER_INFO", NewsReaderListFragment.toString(userInfo)).commit(); + mPrefs.edit().putBoolean(SettingsActivity.CB_SKIP_DETAILVIEW_AND_OPEN_BROWSER_DIRECTLY_STRING, false).commit(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + + + @Test + public void testTakeScreenshots() { + Screengrab.screenshot("startup"); + Mockito.when(menuItem.getItemId()).thenReturn(android.R.id.home); + activity.runOnUiThread(new Runnable() { + public void run() { + //Set url to mock + nrlf.bindUserInfoToUI(true); + + mActivityRule.getActivity().onOptionsItemSelected(menuItem); //Open Drawer + + nrlf.getListView().expandGroup(2); + } + }); + + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Screengrab.screenshot("slider_open"); + + + + + activity.runOnUiThread(new Runnable() { + public void run() { + activity.onOptionsItemSelected(menuItem); //Close Drawer + + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + activity.onClick(null, itemPos); //Select item + + } + }); + + try { + Thread.sleep(8000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Screengrab.screenshot("detail_activity"); + + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + NewsListRecyclerAdapter na = (NewsListRecyclerAdapter) nrdf.getRecyclerView().getAdapter(); + ViewHolder vh = (ViewHolder) nrdf.getRecyclerView().getChildViewHolder(nrdf.getRecyclerView().getLayoutManager().findViewByPosition(itemPos)); + na.ChangeReadStateOfItem(vh, false); + } + }); + } + + + @Test + public void testPodcast() { + activity.runOnUiThread(new Runnable() { + public void run() { + //Set url to mock + nrlf.bindUserInfoToUI(true); + + mActivityRule.getActivity().onOptionsItemSelected(menuItem); //Open Drawer + + nrlf.getListView().expandGroup(2); + + nrlf.onChildClickListener.onChildClick(null, null, 2, 2, 0); //Click on Android Central Podcast + } + }); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Screengrab.screenshot("podcast_list"); + + activity.runOnUiThread(new Runnable() { + public void run() { + ViewHolder vh = (ViewHolder) nrdf.getRecyclerView().getChildViewHolder(nrdf.getRecyclerView().getLayoutManager().findViewByPosition(1)); + + PodcastItem podcastItem = DatabaseConnectionOrm.ParsePodcastItemFromRssItem(activity, vh.getRssItem()); + activity.openMediaItem(podcastItem); + } + }); + + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Screengrab.screenshot("podcast_running"); + + + activity.runOnUiThread(new Runnable() { + public void run() { + activity.pausePodcast(); + } + }); + + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java index 05c2b5ec..034ceefb 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java @@ -42,6 +42,7 @@ import android.os.RemoteException; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; import android.support.design.widget.Snackbar; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; @@ -845,11 +846,13 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements } } - protected NewsReaderListFragment getSlidingListFragment() { + @VisibleForTesting + public NewsReaderListFragment getSlidingListFragment() { return ((NewsReaderListFragment) getSupportFragmentManager().findFragmentById(R.id.left_drawer)); } - protected NewsReaderDetailFragment getNewsReaderDetailFragment() { + @VisibleForTesting + public NewsReaderDetailFragment getNewsReaderDetailFragment() { return (NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java index 16cc648c..a800cadb 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListFragment.java @@ -24,13 +24,13 @@ package de.luhmer.owncloudnewsreader; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; -import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; import android.util.Base64; import android.util.Log; import android.util.TypedValue; @@ -65,6 +65,7 @@ import de.luhmer.owncloudnewsreader.helper.AsyncTaskHelper; import de.luhmer.owncloudnewsreader.helper.ThemeChooser; import de.luhmer.owncloudnewsreader.interfaces.ExpListTextClicked; import de.luhmer.owncloudnewsreader.model.FolderSubscribtionItem; +import de.luhmer.owncloudnewsreader.model.UserInfo; import de.luhmer.owncloudnewsreader.reader.HttpJsonRequest; import de.luhmer.owncloudnewsreader.reader.owncloud.API; import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloudReaderMethods; @@ -212,7 +213,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM }; - OnChildClickListener onChildClickListener = new OnChildClickListener() { + public OnChildClickListener onChildClickListener = new OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, @@ -248,7 +249,9 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM - + public ExpandableListView getListView() { + return eListView; + } protected void showTapLogoToSyncShowcaseView() { @@ -279,7 +282,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM return null; //API NOT SUPPORTED! - UserInfo ui = new UserInfo(); + UserInfo.Builder ui = new UserInfo.Builder(); InputStream inputStream = HttpJsonRequest.getInstance().PerformJsonRequest(api.getUserUrl()); JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8")); @@ -289,10 +292,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM while(reader.hasNext() && (currentName = reader.nextName()) != null) { switch(currentName) { case "userId": - ui.mUserId = reader.nextString(); + ui.setUserId(reader.nextString()); break; case "displayName": - ui.mDisplayName = reader.nextString(); + ui.setDisplayName(reader.nextString()); break; case "avatar": com.google.gson.stream.JsonToken jt = reader.peek(); @@ -307,7 +310,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM if (currentName.equals("data")) { String encodedImage = reader.nextString(); byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT); - ui.mAvatar = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); + ui.setAvatar(BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length)); Log.v(TAG, encodedImage); } else { reader.skipValue(); @@ -323,7 +326,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM } reader.close(); - return ui; + return ui.build(); } catch (Exception e) { if(e.getMessage().equals("Method Not Allowed")) { //Remove if old version is used SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); @@ -351,6 +354,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM } protected void bindUserInfoToUI() { + bindUserInfoToUI(false); + } + + public void bindUserInfoToUI(boolean testMode) { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); String mUsername = mPrefs.getString(SettingsActivity.EDT_USERNAME_STRING, null); String mOc_root_path = mPrefs.getString(SettingsActivity.EDT_OWNCLOUDROOTPATH_STRING, getString(R.string.app_name)); @@ -358,6 +365,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM userTextView.setText(mUsername); urlTextView.setText(mOc_root_path); + if(testMode) { //Hide real url in test mode + urlTextView.setText("https://example.com/owncloud"); + } + String uInfo = mPrefs.getString("USER_INFO", null); if(uInfo == null) return; @@ -380,14 +391,8 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM } - private class UserInfo implements Serializable { - private String mUserId; - private String mDisplayName; - private Bitmap mAvatar; - } - /** Read the object from Base64 string. */ - private static Object fromString(String s) throws IOException, + public static Object fromString(String s) throws IOException, ClassNotFoundException { byte [] data = Base64.decode(s, Base64.DEFAULT); ObjectInputStream ois = new ObjectInputStream( @@ -398,7 +403,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM } /** Write the object to a Base64 string. */ - private static String toString(Serializable o) throws IOException { + public static String toString(Serializable o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( baos ); oos.writeObject(o); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragmentActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragmentActivity.java index d888e057..e48c76b5 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragmentActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/PodcastFragmentActivity.java @@ -12,6 +12,7 @@ import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.support.annotation.VisibleForTesting; import android.support.v4.view.GravityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; @@ -482,7 +483,8 @@ public class PodcastFragmentActivity extends AppCompatActivity implements IPlayP return px; } - protected void openMediaItem(MediaItem mediaItem) { + @VisibleForTesting + public void openMediaItem(MediaItem mediaItem) { Intent intent = new Intent(this, PodcastPlaybackService.class); if(mediaItem instanceof TTSItem) intent.putExtra(PodcastPlaybackService.TTS_ITEM, mediaItem); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/UserInfo.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/UserInfo.java new file mode 100644 index 00000000..3fd2ce8a --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/model/UserInfo.java @@ -0,0 +1,46 @@ +package de.luhmer.owncloudnewsreader.model; + +import android.graphics.Bitmap; + +import java.io.Serializable; + +/** + * Created by dluhmer on 19.03.16. + */ +public class UserInfo implements Serializable { + + public static class Builder { + private String userId; + private String displayName; + private Bitmap avatar; + + public Builder setUserId(String userId) { + this.userId = userId; + return this; + } + + public Builder setDisplayName(String displayName) { + this.displayName = displayName; + return this; + } + + public Builder setAvatar(Bitmap avatar) { + this.avatar = avatar; + return this; + } + + public UserInfo build() { + return new UserInfo(userId, displayName, avatar); + } + } + + private UserInfo(String userId, String displayName, Bitmap avatar) { + this.mUserId = userId; + this.mDisplayName = displayName; + this.mAvatar = avatar; + } + + public final String mUserId; + public final String mDisplayName; + public final Bitmap mAvatar; +} diff --git a/Screengrabfile b/Screengrabfile new file mode 100644 index 00000000..45eebd82 --- /dev/null +++ b/Screengrabfile @@ -0,0 +1,16 @@ +# remove the leading '#' to uncomment lines + +app_package_name 'de.luhmer.owncloudnewsreader' + use_tests_in_packages ['screengrab'] +# use_tests_in_classes ['ScreenshotTest'] + +app_apk_path 'News-Android-App/build/outputs/apk/News-Android-App-debug-unaligned.apk' +tests_apk_path 'News-Android-App/build/outputs/apk/News-Android-App-debug-androidTest-unaligned.apk' + +locales ['en-US', 'fr-FR', 'it-IT'] + +# clear all previously generated screenshots in your local output directory before creating new ones +clear_previous_screenshots true + +# For more information about all available options run +# screengrab --help diff --git a/executeScreengrab.sh b/executeScreengrab.sh new file mode 100644 index 00000000..35df2292 --- /dev/null +++ b/executeScreengrab.sh @@ -0,0 +1,3 @@ +# export PATH=$PATH:/Users/dluhmer/Library/Android/sdk/platform-tools/ +./gradlew assembleDebug assembleAndroidTest +screengrab diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 84968ffd..88690854 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Dec 07 11:51:22 CET 2014 +#Sat Mar 19 10:26:26 CET 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip diff --git a/gradlew b/gradlew old mode 100644 new mode 100755