aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/androidTest/java/org/wordpress
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/androidTest/java/org/wordpress')
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/DefaultMocksInstrumentationTestCase.java42
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/FactoryUtils.java45
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/PostUploadServiceTest.java101
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/TestUtils.java168
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java29
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/database/CommentTableTest.java61
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/database/WordPressDBTest.java17
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorEmptyMock.java11
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorFactoryTest.java24
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientCustomizableMock.java150
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientEmptyMock.java63
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientFactoryTest.java71
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/SystemServiceFactoryTest.java35
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableJSONMock.java94
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableMockAbstract.java23
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableXMLMock.java90
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientEmptyMock.java43
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCFactoryTest.java75
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/models/BlogTest.java293
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/models/CategoryNodeInstrumentationTest.java34
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/models/PostLocationTest.java115
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/models/PostTest.java55
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/networking/AuthenticatorRequestTest.java61
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/networking/GravatarApiTest.java44
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/networking/WPNetworkImageViewTest.java58
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/networking/XMLRPCTest.java35
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/GCMIntentServiceTest.java66
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotesParseTest.java29
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotificationsUtilsTest.java19
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/ui/plans/RemoteTests.java159
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/ui/posts/PostUtilsTest.java33
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/ui/stats/RemoteTests.java638
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/util/ApiHelperTest.java124
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/util/AutolinkUtilsTest.java79
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/util/HealthCheckTest.java227
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java25
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/util/WPHtmlTest.java38
-rw-r--r--WordPress/src/androidTest/java/org/wordpress/android/util/WPUrlUtilsTest.java272
38 files changed, 3546 insertions, 0 deletions
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/DefaultMocksInstrumentationTestCase.java b/WordPress/src/androidTest/java/org/wordpress/android/DefaultMocksInstrumentationTestCase.java
new file mode 100644
index 000000000..5443c82fa
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/DefaultMocksInstrumentationTestCase.java
@@ -0,0 +1,42 @@
+package org.wordpress.android;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.RenamingDelegatingContext;
+
+import org.wordpress.android.mocks.RestClientFactoryTest;
+import org.wordpress.android.mocks.XMLRPCFactoryTest;
+import org.wordpress.android.util.AppLog;
+
+public class DefaultMocksInstrumentationTestCase extends InstrumentationTestCase {
+ protected Context mTargetContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ FactoryUtils.initWithTestFactories();
+
+ mTargetContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
+ TestUtils.clearApplicationState(mTargetContext);
+
+ // Init contexts
+ XMLRPCFactoryTest.sContext = getInstrumentation().getContext();
+ RestClientFactoryTest.sContext = getInstrumentation().getContext();
+ AppLog.v(AppLog.T.TESTS, "Contexts set");
+
+ // Set mode to Customizable
+ XMLRPCFactoryTest.sMode = XMLRPCFactoryTest.Mode.CUSTOMIZABLE_XML;
+ RestClientFactoryTest.sMode = RestClientFactoryTest.Mode.CUSTOMIZABLE;
+ AppLog.v(AppLog.T.TESTS, "Modes set to customizable");
+
+ // Set default variant
+ RestClientFactoryTest.setPrefixAllInstances("default");
+ XMLRPCFactoryTest.setPrefixAllInstances("default");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ FactoryUtils.clearFactories();
+ super.tearDown();
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/FactoryUtils.java b/WordPress/src/androidTest/java/org/wordpress/android/FactoryUtils.java
new file mode 100644
index 000000000..57dadc937
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/FactoryUtils.java
@@ -0,0 +1,45 @@
+package org.wordpress.android;
+
+import org.wordpress.android.mocks.OAuthAuthenticatorFactoryTest;
+import org.wordpress.android.mocks.RestClientFactoryTest;
+import org.wordpress.android.mocks.SystemServiceFactoryTest;
+import org.wordpress.android.mocks.XMLRPCFactoryTest;
+import org.wordpress.android.networking.OAuthAuthenticatorFactory;
+import org.wordpress.android.networking.RestClientFactory;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+import org.wordpress.android.util.SystemServiceFactory;
+import org.xmlrpc.android.XMLRPCFactory;
+
+import java.lang.reflect.Field;
+
+public class FactoryUtils {
+ public static void clearFactories() {
+ // clear factories
+ forceFactoryInjection(XMLRPCFactory.class, null);
+ forceFactoryInjection(RestClientFactory.class, null);
+ forceFactoryInjection(OAuthAuthenticatorFactory.class, null);
+ forceFactoryInjection(SystemServiceFactory.class, null);
+ AppLog.v(T.TESTS, "Null factories set");
+ }
+
+ public static void initWithTestFactories() {
+ // create test factories
+ forceFactoryInjection(XMLRPCFactory.class, new XMLRPCFactoryTest());
+ forceFactoryInjection(RestClientFactory.class, new RestClientFactoryTest());
+ forceFactoryInjection(OAuthAuthenticatorFactory.class, new OAuthAuthenticatorFactoryTest());
+ forceFactoryInjection(SystemServiceFactory.class, new SystemServiceFactoryTest());
+ AppLog.v(T.TESTS, "Mocks factories instantiated");
+ }
+
+ private static void forceFactoryInjection(Class klass, Object factory) {
+ try {
+ Field field = klass.getDeclaredField("sFactory");
+ field.setAccessible(true);
+ field.set(null, factory);
+ AppLog.v(T.TESTS, "Factory " + klass + " injected");
+ } catch (Exception e) {
+ AppLog.e(T.TESTS, "Can't inject test factory " + klass);
+ }
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/PostUploadServiceTest.java b/WordPress/src/androidTest/java/org/wordpress/android/PostUploadServiceTest.java
new file mode 100644
index 000000000..29c28f9d4
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/PostUploadServiceTest.java
@@ -0,0 +1,101 @@
+package org.wordpress.android;
+
+import android.content.Context;
+import android.content.Intent;
+import android.test.RenamingDelegatingContext;
+import android.test.ServiceTestCase;
+
+import org.wordpress.android.mocks.RestClientFactoryTest;
+import org.wordpress.android.mocks.XMLRPCFactoryTest;
+import org.wordpress.android.ui.posts.services.PostUploadService;
+import org.wordpress.android.util.AppLog;
+
+public class PostUploadServiceTest extends ServiceTestCase<PostUploadService> {
+ protected Context testContext;
+ protected Context targetContext;
+
+ public PostUploadServiceTest() {
+ super(PostUploadService.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ FactoryUtils.initWithTestFactories();
+
+ String namespace = BuildConfig.FLAVOR.equals("wasabi") ? "org.wordpress.android.beta"
+ : "org.wordpress.android";
+ testContext = getContext().createPackageContext(namespace, Context.CONTEXT_IGNORE_SECURITY);
+ targetContext = new RenamingDelegatingContext(getContext(), "test_");
+
+ // Init contexts
+ XMLRPCFactoryTest.sContext = getContext();
+ RestClientFactoryTest.sContext = getContext();
+ AppLog.v(AppLog.T.TESTS, "Contexts set");
+
+ // Set mode to Customizable
+ XMLRPCFactoryTest.sMode = XMLRPCFactoryTest.Mode.CUSTOMIZABLE_XML;
+ RestClientFactoryTest.sMode = RestClientFactoryTest.Mode.CUSTOMIZABLE;
+ AppLog.v(AppLog.T.TESTS, "Modes set to customizable");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ FactoryUtils.clearFactories();
+ super.tearDown();
+ }
+
+ public void testStartable() {
+ Intent startIntent = new Intent();
+ startIntent.setClass(getContext(), PostUploadService.class);
+ startService(startIntent);
+ }
+
+ // test reproducing https://github.com/wordpress-mobile/WordPress-Android/issues/884
+ // Following test is valid but won't be fixed now (it will with the post editor rewrite)
+ /*
+ public void testUploadMalformedPostNullPostId() throws Exception {
+ // init a test db containing a few blogs and posts
+ SQLiteDatabase db = TestUtils.loadDBFromDump(targetContext, testContext, "taliwutt-blogs-sample.sql");
+ WordPressDB wpdb = WordPress.wpDB;
+
+ // callback should be called 3 times
+ final CountDownLatch countDownLatch = new CountDownLatch(3);
+
+ // trick to have a mutable final int
+ final int[] notifyCount = {0};
+ final int[] cancelCount = {0};
+ SystemServiceFactoryTest.sNotificationCallback = new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ if ("notify".equals(invocation.getMethod().getName())) {
+ notifyCount[0] += 1;
+ }
+ if ("cancel".equals(invocation.getMethod().getName())) {
+ cancelCount[0] += 1;
+ }
+ countDownLatch.countDown();
+ return null;
+ }
+ };
+
+ // get an existing uploaded post (defined in the previously loaded db dump)
+ int postId = 27;
+ Post post = wpdb.getPostForLocalTablePostId(postId);
+
+ // fake the remote post id to null
+ post.setRemotePostId(null);
+
+ // push it to the PostUploadService
+ PostUploadService.addPostToUpload(post);
+ startService(new Intent(getContext(), PostUploadService.class));
+
+ // wait for the response
+ countDownLatch.await(15, TimeUnit.SECONDS);
+ assertTrue("NotificationManager.cancel must be called at least once - see #884",
+ cancelCount[0] == 1 && notifyCount[0] == 2);
+ }
+ */
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/TestUtils.java b/WordPress/src/androidTest/java/org/wordpress/android/TestUtils.java
new file mode 100644
index 000000000..0bf1d8563
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/TestUtils.java
@@ -0,0 +1,168 @@
+package org.wordpress.android;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.database.sqlite.SQLiteDatabase;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+
+import org.wordpress.android.util.DateTimeUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+
+import de.greenrobot.event.EventBus;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+public class TestUtils {
+ private static String DATABASE_NAME = "wordpress";
+
+ public static SQLiteDatabase loadDBFromDump(Context targetContext, Context testContext, String filename) {
+ targetContext.deleteDatabase(DATABASE_NAME);
+ WordPress.wpDB = new WordPressDB(targetContext);
+
+ Field dbField;
+ try {
+ dbField = WordPressDB.class.getDeclaredField("db");
+ dbField.setAccessible(true);
+ SQLiteDatabase db = (SQLiteDatabase) dbField.get(WordPress.wpDB);
+ assertNotNull(db);
+
+ // Load file
+ InputStream is = testContext.getAssets().open(filename);
+ InputStreamReader inputStreamReader = new InputStreamReader(is);
+ BufferedReader f = new BufferedReader(inputStreamReader);
+ for (String line = f.readLine(); line != null; line = f.readLine()) {
+ if (TextUtils.isEmpty(line)) {
+ continue;
+ }
+ try {
+ db.execSQL(line);
+ } catch (android.database.sqlite.SQLiteException e) {
+ // ignore import errors
+ }
+ }
+ f.close();
+ return db;
+ } catch (NoSuchFieldException e) {
+ assertTrue(e.toString(), false);
+ } catch (IllegalAccessException e) {
+ assertTrue(e.toString(), false);
+ } catch (IOException e) {
+ assertTrue(e.toString(), false);
+ }
+ return null;
+ }
+
+ public static void resetEventBus() {
+ Field dbField;
+ try {
+ dbField = EventBus.class.getDeclaredField("defaultInstance");
+ dbField.setAccessible(true);
+ dbField.set(EventBus.class, null);
+ } catch (NoSuchFieldException e) {
+ assertTrue(e.toString(), false);
+ } catch (IllegalAccessException e) {
+ assertTrue(e.toString(), false);
+ }
+ }
+
+ public static void clearDefaultSharedPreferences(Context targetContext) {
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(targetContext);
+ Editor editor = settings.edit();
+ editor.clear();
+ editor.commit();
+ }
+
+ public static void dropDB(Context targetContext) {
+ targetContext.deleteDatabase(DATABASE_NAME);
+ }
+
+ public static void clearApplicationState(Context context) {
+ WordPress.currentBlog = null;
+ if (WordPress.getContext() != null) {
+ try {
+ WordPress.WordPressComSignOut(context);
+ } catch (Exception e) {
+ // noop
+ }
+ }
+ TestUtils.clearDefaultSharedPreferences(context);
+ TestUtils.dropDB(context);
+ }
+
+ public static String convertStreamToString(java.io.InputStream is) {
+ java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
+ return s.hasNext() ? s.next() : "";
+ }
+
+ public static Date gsonStringToJavaDate(final String strDate) {
+ try {
+ SimpleDateFormat df = new SimpleDateFormat("MMM dd, yyyy hh:mm:ss a", Locale.ENGLISH);
+ return df.parse(strDate);
+ } catch (ParseException e) {
+ return null;
+ }
+ }
+
+ public static Date parseStringToDate(String value) {
+ // try do parseit as a Date
+ Date newValue = DateTimeUtils.dateFromIso8601(value);
+ if (newValue != null) {
+ return newValue;
+ }
+ newValue = gsonStringToJavaDate(value);
+ if (newValue != null) {
+ return newValue;
+ }
+ return null;
+ }
+
+ public static Object castIt(Object value) {
+ if (value instanceof HashMap) {
+ return injectDateInMap((Map<String, Object>) value);
+ } else if (value instanceof String) {
+ Date newValue = parseStringToDate((String) value);
+ if (newValue != null) {
+ return newValue;
+ } else {
+ return value;
+ }
+ } else if (value instanceof Double) {
+ return (int) Math.round((Double) value);
+ } else if (value instanceof Object[]) {
+ return injectDateInArray((Object[]) value);
+ }
+ return value;
+ }
+
+ public static Object[] injectDateInArray(Object[] array) {
+ HashSet<Object> res = new HashSet<Object>();
+ for (Object value : array) {
+ res.add(castIt(value));
+ }
+ return res.toArray();
+ }
+
+ public static Map<String, Object> injectDateInMap(Map<String, Object> hashMap) {
+ Map<String, Object> res = new HashMap<String, Object>();
+ for (String key : hashMap.keySet()) {
+ Object value = hashMap.get(key);
+ res.put(key, castIt(value));
+ }
+ return res;
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java b/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java
new file mode 100644
index 000000000..ec2fd467d
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/UserAgentTest.java
@@ -0,0 +1,29 @@
+package org.wordpress.android;
+
+import junit.framework.TestCase;
+
+public class UserAgentTest extends TestCase {
+
+ /**
+ * Copy of {@link WordPress#USER_AGENT_APPNAME}.
+ * Copied here in order to be able to catch User-Agent changes and verify that they're intentional.
+ */
+ private static final String USER_AGENT_APPNAME = "wp-android";
+
+ public void testGetDefaultUserAgent() {
+ String defaultUserAgent = WordPress.getDefaultUserAgent();
+ assertNotNull("Default User-Agent must be set", defaultUserAgent);
+ assertTrue("Default User-Agent must not be an empty string", defaultUserAgent.length() > 0);
+ assertFalse("Default User-Agent must not contain app name", defaultUserAgent.contains(USER_AGENT_APPNAME));
+ }
+
+ public void testGetUserAgent() {
+ String userAgent = WordPress.getUserAgent();
+ assertNotNull("User-Agent must be set", userAgent);
+ assertTrue("User-Agent must not be an empty string", userAgent.length() > 0);
+ assertTrue("User-Agent must contain app name substring", userAgent.contains(USER_AGENT_APPNAME));
+
+ String defaultUserAgent = WordPress.getDefaultUserAgent();
+ assertTrue("User-Agent must be derived from default User-Agent", userAgent.contains(defaultUserAgent));
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/database/CommentTableTest.java b/WordPress/src/androidTest/java/org/wordpress/android/database/CommentTableTest.java
new file mode 100644
index 000000000..1f3aaee86
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/database/CommentTableTest.java
@@ -0,0 +1,61 @@
+package org.wordpress.android.database;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.RenamingDelegatingContext;
+
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.datasets.CommentTable;
+import org.wordpress.android.models.Comment;
+
+public class CommentTableTest extends InstrumentationTestCase {
+ protected Context mTargetContext;
+ protected Context mTestContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ // Clean application state
+ mTargetContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
+ mTestContext = getInstrumentation().getContext();
+ TestUtils.clearApplicationState(mTargetContext);
+ TestUtils.resetEventBus();
+ }
+
+ public void testGetCommentEqualTo1024K() {
+ createAndGetComment(1024 * 1024);
+ }
+
+ public void testGetCommentEqualTo2096550() {
+ createAndGetComment(2096550); // 1024 * 1024 * 2 - 603
+ }
+
+ public void testGetCommentEqualTo2096549() {
+ createAndGetComment(2096549); // 1024 * 1024 * 2 - 602
+ }
+
+ public void testGetCommentEqualTo2048K() {
+ createAndGetComment(1024 * 1024 * 2);
+ }
+
+ private void createAndGetComment(int commentLength) {
+ // Load a sample DB and inject it into WordPress.wpdb
+ TestUtils.loadDBFromDump(mTargetContext, mTestContext, "taliwutt-blogs-sample.sql");
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < commentLength; ++i) {
+ sb.append('a');
+ }
+ Comment bigComment = new Comment(0,
+ 1,
+ "author",
+ "0",
+ sb.toString(),
+ "approve",
+ "arst",
+ "http://mop.com",
+ "mop@mop.com",
+ "");
+ CommentTable.addComment(0, bigComment);
+ CommentTable.getCommentsForBlog(0);
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/database/WordPressDBTest.java b/WordPress/src/androidTest/java/org/wordpress/android/database/WordPressDBTest.java
new file mode 100644
index 000000000..0e8b7de50
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/database/WordPressDBTest.java
@@ -0,0 +1,17 @@
+package org.wordpress.android.database;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.RenamingDelegatingContext;
+
+public class WordPressDBTest extends InstrumentationTestCase {
+ protected Context testContext;
+ protected Context targetContext;
+
+ @Override
+ protected void setUp() {
+ // Run tests in an isolated context
+ targetContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
+ testContext = getInstrumentation().getContext();
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorEmptyMock.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorEmptyMock.java
new file mode 100644
index 000000000..2895cf0ed
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorEmptyMock.java
@@ -0,0 +1,11 @@
+package org.wordpress.android.mocks;
+
+import org.wordpress.android.models.AccountHelper;
+import org.wordpress.android.networking.AuthenticatorRequest;
+import org.wordpress.android.networking.OAuthAuthenticator;
+
+public class OAuthAuthenticatorEmptyMock extends OAuthAuthenticator {
+ public void authenticate(AuthenticatorRequest request) {
+ AccountHelper.getDefaultAccount().setAccessToken("dead-parrot");
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorFactoryTest.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorFactoryTest.java
new file mode 100644
index 000000000..d84962500
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/OAuthAuthenticatorFactoryTest.java
@@ -0,0 +1,24 @@
+package org.wordpress.android.mocks;
+
+import android.content.Context;
+
+import org.wordpress.android.networking.OAuthAuthenticator;
+import org.wordpress.android.networking.OAuthAuthenticatorFactoryAbstract;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+
+public class OAuthAuthenticatorFactoryTest implements OAuthAuthenticatorFactoryAbstract {
+ public enum Mode {EMPTY}
+
+ public static Mode sMode = Mode.EMPTY;
+ public static Context sContext;
+
+ public OAuthAuthenticator make() {
+ switch (sMode) {
+ case EMPTY:
+ default:
+ AppLog.v(T.TESTS, "make: OAuthAuthenticatorEmptyMock");
+ return new OAuthAuthenticatorEmptyMock();
+ }
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientCustomizableMock.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientCustomizableMock.java
new file mode 100644
index 000000000..6f066d6d1
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientCustomizableMock.java
@@ -0,0 +1,150 @@
+package org.wordpress.android.mocks;
+
+import android.content.Context;
+
+import com.android.volley.NetworkResponse;
+import com.android.volley.Request.Method;
+import com.android.volley.TimeoutError;
+import com.android.volley.VolleyError;
+import com.wordpress.rest.RestClient;
+import com.wordpress.rest.RestRequest;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class RestClientCustomizableMock extends RestClient {
+ private Context mContext;
+ private String mPrefix;
+
+ public void setContextAndPrefix(Context context, String prefix) {
+ mContext = context;
+ mPrefix = prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ mPrefix = prefix;
+ }
+
+ public void setContext(Context context) {
+ mContext = context;
+ }
+
+ public RestClientCustomizableMock(com.android.volley.RequestQueue queue) {
+ super(queue);
+ }
+
+ public RestClientCustomizableMock(com.android.volley.RequestQueue queue, String token) {
+ super(queue, token, REST_API_ENDPOINT_URL_V1);
+ }
+
+ public String getAbsoluteURL(String url) {
+ return null;
+ }
+
+ public String getAbsoluteURL(String path, java.util.Map<String, String> params) {
+ return null;
+ }
+
+ public RestRequest get(String path, RestRequest.Listener listener, RestRequest.ErrorListener errorListener) {
+ AppLog.v(T.TESTS, this.getClass() + ": get(" + path + ")");
+ return new RestRequest(Method.GET, path, null, listener, errorListener);
+ }
+
+ public RestRequest post(String path, java.util.Map<String, String> body, RestRequest.Listener listener,
+ RestRequest.ErrorListener errorListener) {
+ AppLog.v(T.TESTS, this.getClass() + ": post(" + path + ")");
+ return new RestRequest(Method.POST, path, body, listener, errorListener);
+ }
+
+ private VolleyError forgeVolleyErrorFromFilename(String filename) {
+ String strData = fileToString(filename);
+ byte[] data = new byte[0];
+ if (strData != null) {
+ data = strData.getBytes();
+ }
+ NetworkResponse networkResponse = new NetworkResponse(400, data, null, false);
+ VolleyError ve = new VolleyError(networkResponse);
+ return ve;
+ }
+
+ private TimeoutError forgeVolleyTimeoutError() {
+ TimeoutError te = new TimeoutError();
+ return te;
+ }
+
+ private String fileToString(String filename) {
+ try {
+ InputStream is = mContext.getAssets().open(filename);
+ String data = TestUtils.convertStreamToString(is);
+ AppLog.v(T.TESTS, "file read:" + filename);
+ return data;
+ } catch (IOException e) {
+ AppLog.e(T.TESTS, "can't read file: " + filename + " - " + e.toString());
+ }
+ return null;
+ }
+
+ public RestRequest makeRequest(int method, String url, java.util.Map<String, String> params,
+ RestRequest.Listener listener, RestRequest.ErrorListener errorListener) {
+ AppLog.v(T.TESTS, this.getClass() + ": makeRequest(" + url + ")");
+ RestRequest dummyReturnValue = new RestRequest(method, url, params, listener, errorListener);
+ // URL example: https://public-api.wordpress.com/rest/v1/me
+ // Filename: default-public-api-wordpress-com-rest-v1-me.json
+ String filename = mPrefix + "-" + url.replace("https://", "").replace("/", "-").replace(".", "-").replace("?",
+ "-") + ".json";
+
+ if ("password-invalid".equals(mPrefix) && errorListener != null) {
+ errorListener.onErrorResponse(forgeVolleyErrorFromFilename(filename));
+ return dummyReturnValue;
+ }
+
+ if ("username-exists".equals(mPrefix) && errorListener != null) {
+ errorListener.onErrorResponse(forgeVolleyErrorFromFilename(filename));
+ return dummyReturnValue;
+ }
+
+ if ("timeout".equals(mPrefix) && errorListener != null) {
+ errorListener.onErrorResponse(forgeVolleyTimeoutError());
+ return dummyReturnValue;
+ }
+
+ if ("site-reserved".equals(mPrefix) && errorListener != null) {
+ errorListener.onErrorResponse(forgeVolleyErrorFromFilename(filename));
+ return dummyReturnValue;
+ }
+
+ String data = fileToString(filename);
+ if (data == null) {
+ AppLog.e(T.TESTS, "Can't read file: " + filename);
+ throw new RuntimeException("Can't read file: " + filename);
+ }
+
+ try {
+ JSONObject jsonObj = new JSONObject(data);
+ listener.onResponse(jsonObj);
+ } catch (JSONException je) {
+ AppLog.e(T.TESTS, je.toString());
+ }
+ return dummyReturnValue;
+ }
+
+ public RestRequest send(RestRequest request) {
+ return request;
+ }
+
+ public void setUserAgent(String userAgent) {
+ }
+
+ public void setAccessToken(String token) {
+ }
+
+ public boolean isAuthenticated() {
+ return true;
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientEmptyMock.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientEmptyMock.java
new file mode 100644
index 000000000..b07b1b2a3
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientEmptyMock.java
@@ -0,0 +1,63 @@
+package org.wordpress.android.mocks;
+
+import com.android.volley.Request.Method;
+import com.wordpress.rest.RestClient;
+import com.wordpress.rest.RestRequest;
+
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+
+public class RestClientEmptyMock extends RestClient {
+ public RestClientEmptyMock(com.android.volley.RequestQueue queue) {
+ super(queue);
+ }
+
+ public RestClientEmptyMock(com.android.volley.RequestQueue queue, java.lang.String token) {
+ super(queue, token, REST_API_ENDPOINT_URL_V1);
+ }
+
+ public java.lang.String getAbsoluteURL(java.lang.String url) {
+ return null;
+ }
+
+ public java.lang.String getAbsoluteURL(java.lang.String path,
+ java.util.Map<java.lang.String, java.lang.String> params) {
+ return null;
+ }
+
+ public com.wordpress.rest.RestRequest get(java.lang.String path, com.wordpress.rest.RestRequest.Listener listener,
+ com.wordpress.rest.RestRequest.ErrorListener errorListener) {
+ AppLog.v(T.TESTS, this.getClass() + ": get(" + path + ")");
+ return new RestRequest(Method.GET, path, null, listener, errorListener);
+ }
+
+ public com.wordpress.rest.RestRequest post(java.lang.String path,
+ java.util.Map<java.lang.String, java.lang.String> body,
+ com.wordpress.rest.RestRequest.Listener listener,
+ com.wordpress.rest.RestRequest.ErrorListener errorListener) {
+ AppLog.v(T.TESTS, this.getClass() + ": post(" + path + ")");
+ return new RestRequest(Method.POST, path, body, listener, errorListener);
+ }
+
+ public com.wordpress.rest.RestRequest makeRequest(int method, java.lang.String url,
+ java.util.Map<java.lang.String, java.lang.String> params,
+ com.wordpress.rest.RestRequest.Listener listener,
+ com.wordpress.rest.RestRequest.ErrorListener errorListener) {
+ AppLog.v(T.TESTS, this.getClass() + ": makeRequest(" + url + ")");
+ return new RestRequest(method, url, params, listener, errorListener);
+ }
+
+ public com.wordpress.rest.RestRequest send(com.wordpress.rest.RestRequest request) {
+ return request;
+ }
+
+ public void setUserAgent(java.lang.String userAgent) {
+ }
+
+ public void setAccessToken(java.lang.String token) {
+ }
+
+ public boolean isAuthenticated() {
+ return true;
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientFactoryTest.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientFactoryTest.java
new file mode 100644
index 000000000..f403e5126
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/RestClientFactoryTest.java
@@ -0,0 +1,71 @@
+package org.wordpress.android.mocks;
+
+import android.content.Context;
+
+import com.android.volley.RequestQueue;
+import com.wordpress.rest.RestClient;
+import com.wordpress.rest.RestClient.REST_CLIENT_VERSIONS;
+
+import org.wordpress.android.networking.RestClientFactoryAbstract;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class RestClientFactoryTest implements RestClientFactoryAbstract {
+ public static String sPrefix = "default";
+ public static RestClient.REST_CLIENT_VERSIONS sVersion = REST_CLIENT_VERSIONS.V1;
+ public static Context sContext;
+ // keep a reference to each instances so we can update contexts and prefixes after instantiation
+ public static Set<RestClientCustomizableMock> sInstances = new HashSet<RestClientCustomizableMock>();
+
+ public static void setContextAllInstances(Context context) {
+ sContext = context;
+ if (sMode != Mode.CUSTOMIZABLE) {
+ AppLog.e(T.TESTS, "You try to change context on a non-customizable RestClient mock");
+ }
+ for (RestClientCustomizableMock client : sInstances) {
+ client.setContext(context);
+ }
+ }
+
+ public static void setPrefixAllInstances(String prefix) {
+ sPrefix = prefix;
+ if (sMode != Mode.CUSTOMIZABLE) {
+ AppLog.e(T.TESTS, "You try to change prefix on a non-customizable RestClient mock");
+ }
+ for (RestClientCustomizableMock client : sInstances) {
+ client.setPrefix(prefix);
+ }
+ }
+
+ public static Mode sMode = Mode.EMPTY;
+
+ public RestClient make(RequestQueue queue) {
+ switch (sMode) {
+ case CUSTOMIZABLE:
+ RestClientCustomizableMock client = new RestClientCustomizableMock(queue);
+ if (sContext != null) {
+ client.setContextAndPrefix(sContext, sPrefix);
+ } else {
+ AppLog.e(T.TESTS, "You have to set RestClientFactoryTest.sContext field before running tests");
+ throw new IllegalStateException();
+ }
+ AppLog.v(T.TESTS, "make: RestClientCustomizableMock");
+ sInstances.add(client);
+ return client;
+ case EMPTY:
+ default:
+ AppLog.v(T.TESTS, "make: RestClientEmptyMock");
+ return new RestClientEmptyMock(queue);
+ }
+ }
+
+ public RestClient make(RequestQueue queue, RestClient.REST_CLIENT_VERSIONS version) {
+ sVersion = version;
+ return make(queue);
+ }
+
+ public enum Mode {EMPTY, CUSTOMIZABLE}
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/SystemServiceFactoryTest.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/SystemServiceFactoryTest.java
new file mode 100644
index 000000000..a099de8ef
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/SystemServiceFactoryTest.java
@@ -0,0 +1,35 @@
+package org.wordpress.android.mocks;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+
+import org.mockito.stubbing.Answer;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+import org.wordpress.android.util.SystemServiceFactoryAbstract;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+public class SystemServiceFactoryTest implements SystemServiceFactoryAbstract {
+ public static Answer sNotificationCallback;
+
+ public Object get(Context context, String name) {
+ System.setProperty("dexmaker.dexcache", context.getCacheDir().getPath());
+ if (Context.NOTIFICATION_SERVICE.equals(name)) {
+ NotificationManager notificationManager = mock(NotificationManager.class);
+ if (sNotificationCallback != null) {
+ doAnswer(sNotificationCallback).when(notificationManager).notify(anyInt(), any(Notification.class));
+ doAnswer(sNotificationCallback).when(notificationManager).cancel(anyInt());
+ }
+ return notificationManager;
+ } else {
+ AppLog.e(T.TESTS, "SystemService:" + name + "No supported in SystemServiceFactoryTest");
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableJSONMock.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableJSONMock.java
new file mode 100644
index 000000000..d68746c4a
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableJSONMock.java
@@ -0,0 +1,94 @@
+package org.wordpress.android.mocks;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+import org.xmlrpc.android.LoggedInputStream;
+import org.xmlrpc.android.XMLRPCCallback;
+import org.xmlrpc.android.XMLRPCException;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.HashMap;
+
+public class XMLRPCClientCustomizableJSONMock extends XMLRPCClientCustomizableMockAbstract {
+ private LoggedInputStream mLoggedInputStream;
+
+ public XMLRPCClientCustomizableJSONMock(URI uri, String httpUser, String httpPassword) {
+ }
+
+ public void addQuickPostHeader(String type) {
+ }
+
+ public void setAuthorizationHeader(String authToken) {
+ }
+
+ private Object readFile(String method, String prefix) {
+ // method example: wp.getUsersBlogs
+ // Filename: default-wp.getUsersBlogs.json
+ String filename = prefix + "-" + method + ".json";
+ try {
+ Gson gson = new Gson();
+ mLoggedInputStream = new LoggedInputStream(mContext.getAssets().open(filename));
+ String jsonString = TestUtils.convertStreamToString(mLoggedInputStream);
+ AppLog.i(T.TESTS, "loading: " + filename);
+ try {
+ // Try to load a JSONArray
+ return TestUtils.injectDateInArray(gson.fromJson(jsonString, Object[].class));
+ } catch (Exception e) {
+ // If that fails, try to load a JSONObject
+ Type type = new TypeToken<HashMap<String, Object>>(){}.getType();
+ HashMap<String, Object> map = gson.fromJson(jsonString, type);
+ return TestUtils.injectDateInMap(map);
+ }
+ } catch (IOException e) {
+ AppLog.e(T.TESTS, "can't read file: " + filename);
+ }
+ return null;
+ }
+
+ public Object call(String method, Object[] params) throws XMLRPCException {
+ mLoggedInputStream = null;
+ AppLog.v(T.TESTS, "XMLRPCClientCustomizableJSONMock: call: " + method);
+ if ("login-failure".equals(mPrefix)) {
+ // Wrong login
+ throw new XMLRPCException("code 403");
+ }
+
+ Object retValue = readFile(method, mPrefix);
+ if (retValue == null) {
+ // failback to default
+ AppLog.w(T.TESTS, "failback to default");
+ retValue = readFile(method, "default");
+ }
+ return retValue;
+ }
+
+ public Object call(String method) throws XMLRPCException {
+ return null;
+ }
+
+ public Object call(String method, Object[] params, File tempFile) throws XMLRPCException {
+ return null;
+ }
+
+ public long callAsync(XMLRPCCallback listener, String methodName, Object[] params) {
+ return 0;
+ }
+
+ public long callAsync(XMLRPCCallback listener, String methodName, Object[] params, File tempFile) {
+ return 0;
+ }
+
+ public String getResponse() {
+ if (mLoggedInputStream == null) {
+ return "";
+ }
+ return mLoggedInputStream.getResponseDocument();
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableMockAbstract.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableMockAbstract.java
new file mode 100644
index 000000000..c8690f6b8
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableMockAbstract.java
@@ -0,0 +1,23 @@
+package org.wordpress.android.mocks;
+
+import android.content.Context;
+
+import org.xmlrpc.android.XMLRPCClientInterface;
+
+public abstract class XMLRPCClientCustomizableMockAbstract implements XMLRPCClientInterface {
+ protected Context mContext;
+ protected String mPrefix;
+
+ public void setContextAndPrefix(Context context, String prefix) {
+ mContext = context;
+ mPrefix = prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ mPrefix = prefix;
+ }
+
+ public void setContext(Context context) {
+ mContext = context;
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableXMLMock.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableXMLMock.java
new file mode 100644
index 000000000..57e8291f9
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientCustomizableXMLMock.java
@@ -0,0 +1,90 @@
+package org.wordpress.android.mocks;
+
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlrpc.android.LoggedInputStream;
+import org.xmlrpc.android.XMLRPCCallback;
+import org.xmlrpc.android.XMLRPCClient;
+import org.xmlrpc.android.XMLRPCException;
+import org.xmlrpc.android.XMLRPCFault;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URI;
+
+public class XMLRPCClientCustomizableXMLMock extends XMLRPCClientCustomizableMockAbstract {
+ XMLRPCClient mXmlRpcClient;
+ private LoggedInputStream mLoggedInputStream;
+
+ public XMLRPCClientCustomizableXMLMock(URI uri, String httpUser, String httpPassword) {
+ // Used to test ctor and preparePostMethod
+ mXmlRpcClient = new XMLRPCClient("", "", "");
+ }
+
+ public void addQuickPostHeader(String type) {
+ }
+
+ public void setAuthorizationHeader(String authToken) {
+ }
+
+ private Object readFile(String method, String prefix) throws IOException, XMLRPCException, XmlPullParserException {
+ // method example: wp.getUsersBlogs
+ // Filename: default-wp.getUsersBlogs.xml
+ String filename = prefix + "-" + method + ".xml";
+ try {
+ mLoggedInputStream = new LoggedInputStream(mContext.getAssets().open(filename));
+ return XMLRPCClient.parseXMLRPCResponse(mLoggedInputStream, null);
+ } catch (FileNotFoundException e) {
+ AppLog.e(T.TESTS, "file not found: " + filename);
+ }
+ return null;
+ }
+
+ public Object call(String method, Object[] params) throws XMLRPCException, IOException, XmlPullParserException {
+ mLoggedInputStream = null;
+ try {
+ mXmlRpcClient.preparePostMethod(method, params, null);
+ } catch (IOException e) {
+ // unexpected error, test must fail
+ throw new XMLRPCException("preparePostMethod failed");
+ }
+ AppLog.v(T.TESTS, "XMLRPCClientCustomizableXMLMock call: " + method);
+ if ("login-failure".equals(mPrefix)) {
+ // Wrong login
+ throw new XMLRPCFault("code 403", 403);
+ }
+
+ Object retValue = readFile(method, mPrefix);
+ if (retValue == null) {
+ // failback to default
+ AppLog.w(T.TESTS, "failback to default");
+ retValue = readFile(method, "default");
+ }
+ return retValue;
+ }
+
+ public Object call(String method) throws XMLRPCException {
+ return null;
+ }
+
+ public Object call(String method, Object[] params, File tempFile) throws XMLRPCException {
+ return null;
+ }
+
+ public long callAsync(XMLRPCCallback listener, String methodName, Object[] params) {
+ return 0;
+ }
+
+ public long callAsync(XMLRPCCallback listener, String methodName, Object[] params, File tempFile) {
+ return 0;
+ }
+
+ public String getResponse() {
+ if (mLoggedInputStream == null) {
+ return "";
+ }
+ return mLoggedInputStream.getResponseDocument();
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientEmptyMock.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientEmptyMock.java
new file mode 100644
index 000000000..f995e2446
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCClientEmptyMock.java
@@ -0,0 +1,43 @@
+package org.wordpress.android.mocks;
+
+import org.xmlrpc.android.XMLRPCCallback;
+import org.xmlrpc.android.XMLRPCClientInterface;
+import org.xmlrpc.android.XMLRPCException;
+
+import java.io.File;
+import java.net.URI;
+
+public class XMLRPCClientEmptyMock implements XMLRPCClientInterface {
+ public XMLRPCClientEmptyMock(URI uri, String httpUser, String httpPassword) {
+ }
+
+ public void addQuickPostHeader(String type) {
+ }
+
+ public void setAuthorizationHeader(String authToken) {
+ }
+
+ public Object call(String method, Object[] params) throws XMLRPCException {
+ return null;
+ }
+
+ public Object call(String method) throws XMLRPCException {
+ return null;
+ }
+
+ public Object call(String method, Object[] params, File tempFile) throws XMLRPCException {
+ return null;
+ }
+
+ public long callAsync(XMLRPCCallback listener, String methodName, Object[] params) {
+ return 0;
+ }
+
+ public long callAsync(XMLRPCCallback listener, String methodName, Object[] params, File tempFile) {
+ return 0;
+ }
+
+ public String getResponse() {
+ return null;
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCFactoryTest.java b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCFactoryTest.java
new file mode 100644
index 000000000..60852f11c
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/mocks/XMLRPCFactoryTest.java
@@ -0,0 +1,75 @@
+package org.wordpress.android.mocks;
+
+import android.content.Context;
+
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+import org.xmlrpc.android.XMLRPCClientInterface;
+import org.xmlrpc.android.XMLRPCFactoryAbstract;
+
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+public class XMLRPCFactoryTest implements XMLRPCFactoryAbstract {
+ public static String sPrefix = "default";
+ public static Context sContext;
+ public static Mode sMode = Mode.EMPTY;
+ public static Set<XMLRPCClientCustomizableMockAbstract> sInstances =
+ new HashSet<XMLRPCClientCustomizableMockAbstract>();
+
+ public static void setContextAllInstances(Context context) {
+ sContext = context;
+ if (sMode != Mode.CUSTOMIZABLE_JSON && sMode != Mode.CUSTOMIZABLE_XML) {
+ AppLog.e(T.TESTS, "You tried to change context on a non-customizable XMLRPCClient mock");
+ }
+ for (XMLRPCClientCustomizableMockAbstract client : sInstances) {
+ client.setContext(context);
+ }
+ }
+
+ public static void setPrefixAllInstances(String prefix) {
+ sPrefix = prefix;
+ if (sMode != Mode.CUSTOMIZABLE_JSON && sMode != Mode.CUSTOMIZABLE_XML) {
+ AppLog.e(T.TESTS, "You tried to change prefix on a non-customizable XMLRPCClient mock");
+ }
+ for (XMLRPCClientCustomizableMockAbstract client : sInstances) {
+ client.setPrefix(prefix);
+ }
+ }
+
+ public XMLRPCClientInterface make(URI uri, String httpUser, String httpPassword) {
+ switch (sMode) {
+ case CUSTOMIZABLE_JSON:
+ XMLRPCClientCustomizableJSONMock clientJSONMock = new XMLRPCClientCustomizableJSONMock(uri, httpUser,
+ httpPassword);
+ if (sContext != null) {
+ clientJSONMock.setContextAndPrefix(sContext, sPrefix);
+ } else {
+ AppLog.e(T.TESTS, "You have to set XMLRPCFactoryTest.sContext field before running tests");
+ throw new IllegalStateException();
+ }
+ AppLog.v(T.TESTS, "make: XMLRPCClientCustomizableJSONMock");
+ sInstances.add(clientJSONMock);
+ return clientJSONMock;
+ case CUSTOMIZABLE_XML:
+ XMLRPCClientCustomizableXMLMock clientXMLMock = new XMLRPCClientCustomizableXMLMock(uri, httpUser,
+ httpPassword);
+ if (sContext != null) {
+ clientXMLMock.setContextAndPrefix(sContext, sPrefix);
+ } else {
+ AppLog.e(T.TESTS, "You have to set XMLRPCFactoryTest.sContext field before running tests");
+ throw new IllegalStateException();
+ }
+ AppLog.v(T.TESTS, "make: XMLRPCClientCustomizableXMLMock");
+ sInstances.add(clientXMLMock);
+ return clientXMLMock;
+ case EMPTY:
+ default:
+ AppLog.v(T.TESTS, "make: XMLRPCClientEmptyMock");
+ return new XMLRPCClientEmptyMock(uri, httpUser, httpPassword);
+ }
+ }
+
+ public enum Mode {EMPTY, CUSTOMIZABLE_JSON, CUSTOMIZABLE_XML}
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/models/BlogTest.java b/WordPress/src/androidTest/java/org/wordpress/android/models/BlogTest.java
new file mode 100644
index 000000000..d1e5ba071
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/models/BlogTest.java
@@ -0,0 +1,293 @@
+package org.wordpress.android.models;
+
+import android.test.InstrumentationTestCase;
+
+public class BlogTest extends InstrumentationTestCase {
+ private Blog blog;
+
+ @Override
+ protected void setUp() throws Exception {
+ blog = new Blog("http://www.example.com", "username", "password");
+
+ super.setUp();
+ }
+
+ public void testBlogTestUrlUsernamePassword() {
+ assertEquals("http://www.example.com", blog.getUrl());
+ assertEquals("username", blog.getUsername());
+ assertEquals("password", blog.getPassword());
+ assertEquals(-1, blog.getLocalTableBlogId());
+ }
+
+ public void testGetSetLocalTableBlogId() {
+ assertEquals(-1, blog.getLocalTableBlogId());
+ blog.setLocalTableBlogId(0);
+ assertEquals(0, blog.getLocalTableBlogId());
+ }
+
+ public void testGetSetUrl() {
+ assertEquals("http://www.example.com", blog.getUrl());
+ blog.setUrl(null);
+ assertNull(blog.getUrl());
+ blog.setUrl("http://example.com/two");
+ assertEquals("http://example.com/two", blog.getUrl());
+ }
+
+ public void testGetSetHomeURL() {
+ assertNull(blog.getHomeURL());
+ blog.setHomeURL("http://www.homeurl.com");
+ assertEquals("http://www.homeurl.com", blog.getHomeURL());
+ }
+
+ public void testGetSetBlogName() {
+ assertNull(blog.getBlogName());
+ blog.setBlogName("blogName");
+ assertEquals("blogName", blog.getBlogName());
+ }
+
+ public void testGetSetUsername() {
+ assertEquals("username", blog.getUsername());
+ blog.setUsername(null);
+ // getUsername never returns null
+ assertEquals("", blog.getUsername());
+ }
+
+ public void testGetSetPassword() {
+ assertEquals("password", blog.getPassword());
+ blog.setPassword(null);
+ // getPassword never returns null
+ assertEquals("", blog.getPassword());
+ }
+
+ public void testGetSetImagePlacement() {
+ assertNull(blog.getImagePlacement());
+ blog.setImagePlacement("test");
+ assertEquals("test", blog.getImagePlacement());
+ }
+
+ public void testGetSetFeaturedImageCapable() {
+ assertFalse(blog.isFeaturedImageCapable());
+ blog.setFeaturedImageCapable(true);
+ assertTrue(blog.isFeaturedImageCapable());
+ }
+
+ public void testBsetFeaturedImageCapable() {
+ assertFalse(blog.isFeaturedImageCapable());
+ boolean val = blog.bsetFeaturedImageCapable(false);
+ assertFalse(val);
+ assertFalse(blog.isFeaturedImageCapable());
+ val = blog.bsetFeaturedImageCapable(true);
+ assertTrue(val);
+ assertTrue(blog.isFeaturedImageCapable());
+ val = blog.bsetFeaturedImageCapable(false);
+ assertTrue(val);
+ }
+
+ public void testGetSetFullSizeImage() {
+ assertFalse(blog.isFullSizeImage());
+ blog.setFullSizeImage(true);
+ assertTrue(blog.isFullSizeImage());
+ }
+
+ public void testGetSetMaxImageWidth() {
+ assertEquals("", blog.getMaxImageWidth());
+ blog.setMaxImageWidth("1");
+ assertEquals("1", blog.getMaxImageWidth());
+ }
+
+ public void testGetSetMaxImageWidthId() {
+ assertEquals(0, blog.getMaxImageWidthId());
+ blog.setMaxImageWidthId(1);
+ assertEquals(1, blog.getMaxImageWidthId());
+ }
+
+ public void testGetSetRemoteBlogId() {
+ assertEquals(0, blog.getRemoteBlogId());
+ blog.setRemoteBlogId(1);
+ assertEquals(1, blog.getRemoteBlogId());
+ }
+
+ public void testGetSetDotcom_username() {
+ assertNull(blog.getDotcom_username());
+ blog.setDotcom_username("username");
+ assertEquals("username", blog.getDotcom_username());
+ }
+
+ public void testGetSetDotcom_password() {
+ assertNull(blog.getDotcom_password());
+ blog.setDotcom_password("password");
+ assertEquals("password", blog.getDotcom_password());
+ }
+
+ public void testGetSetApi_key() {
+ assertNull(blog.getApi_key());
+ blog.setApi_key("123");
+ assertEquals("123", blog.getApi_key());
+ }
+
+ public void testGetSetApi_blogid() {
+ assertNull(blog.getApi_blogid());
+ blog.setApi_blogid("123");
+ assertEquals("123", blog.getApi_blogid());
+ }
+
+ public void testGetSetDotcomFlag() {
+ assertFalse(blog.isDotcomFlag());
+ blog.setDotcomFlag(true);
+ assertTrue(blog.isDotcomFlag());
+ }
+
+ public void testGetSetWpVersion() {
+ assertNull(blog.getWpVersion());
+ blog.setWpVersion("123");
+ assertEquals("123", blog.getWpVersion());
+ }
+
+ public void testBsetWpVersion() {
+ assertNull(blog.getWpVersion());
+ boolean val = blog.bsetWpVersion("123");
+ assertTrue(val);
+ assertEquals("123", blog.getWpVersion());
+ val = blog.bsetWpVersion("123");
+ assertFalse(val);
+ }
+
+ public void testGetSetHttpuser() {
+ assertEquals(blog.getHttpuser(), "");
+ blog.setHttpuser("user");
+ assertEquals("user", blog.getHttpuser());
+ }
+
+ public void testGetSetHttppassword() {
+ assertEquals(blog.getHttppassword(), "");
+ blog.setHttppassword("password");
+ assertEquals("password", blog.getHttppassword());
+ }
+
+ public void testGetSetHidden() {
+ assertFalse(blog.isHidden());
+ blog.setHidden(true);
+ assertTrue(blog.isHidden());
+ }
+
+ public void testGetSetPostFormats() {
+ assertNull(blog.getPostFormats());
+ blog.setPostFormats("test");
+ assertEquals("test", blog.getPostFormats());
+ }
+
+ public void testBSetPostFormats() {
+ assertNull(blog.getPostFormats());
+ boolean val = blog.bsetPostFormats("test");
+ assertTrue(val);
+ assertEquals("test", blog.getPostFormats());
+ val = blog.bsetPostFormats("test");
+ assertFalse(val);
+ val = blog.bsetPostFormats("test2");
+ assertTrue(val);
+ }
+
+ public void testGetSetScaledImage() {
+ assertFalse(blog.isScaledImage());
+ blog.setScaledImage(true);
+ assertTrue(blog.isScaledImage());
+ }
+
+ public void testGetSetScaledImageWidth() {
+ assertEquals(0, blog.getScaledImageWidth());
+ blog.setScaledImageWidth(1);
+ assertEquals(1, blog.getScaledImageWidth());
+ }
+
+ public void testGetSetBlogOptions() {
+ assertEquals("{}", blog.getBlogOptions());
+ blog.setBlogOptions("{option:1}");
+ assertEquals("{option:1}", blog.getBlogOptions());
+ }
+
+ public void testBSetBlogOptions() {
+ assertEquals("{}", blog.getBlogOptions());
+ boolean val = blog.bsetBlogOptions("{option:1}");
+ assertTrue(val);
+ val = blog.bsetBlogOptions("{option:1}");
+ assertFalse(val);
+ val = blog.bsetBlogOptions("{option:2}");
+ assertTrue(val);
+ }
+
+ public void testGetSetAdmin() {
+ assertFalse(blog.isAdmin());
+ blog.setAdmin(true);
+ assertTrue(blog.isAdmin());
+ }
+
+ public void testBSetAdmin() {
+ assertFalse(blog.isAdmin());
+ boolean val = blog.bsetAdmin(false);
+ assertFalse(val);
+ val = blog.bsetAdmin(true);
+ assertTrue(val);
+ val = blog.bsetAdmin(true);
+ assertFalse(val);
+ }
+
+ public void testGetSetAdminUrl() {
+ blog.setBlogOptions("{\"admin_url\": {\"value\": \"https://muppets.com/wp-admin/\" } }");
+ assertEquals("https://muppets.com/wp-admin/", blog.getAdminUrl());
+ }
+
+ public void testGetSetPrivate() {
+ assertFalse(blog.isPrivate());
+ blog.setBlogOptions("{ \"blog_public\" : { \"value\" : \"-1\" } }");
+
+ // blog cannot be private if not a wpcom one
+ assertFalse(blog.isPrivate());
+
+ // set the blog as a WPCom one
+ blog.setDotcomFlag(true);
+ // blog should now appear as private
+ assertTrue(blog.isPrivate());
+ }
+
+ public void testGetSetJetpackPowered() {
+ assertFalse(blog.isJetpackPowered());
+ blog.setBlogOptions("{ jetpack_client_id : {} }");
+ assertTrue(blog.isJetpackPowered());
+ }
+
+ public void testIsPhotonCapableJetpack() {
+ assertFalse(blog.isPhotonCapable());
+
+ blog.setBlogOptions("{ jetpack_client_id : {} }");
+ assertTrue(blog.isPhotonCapable());
+ }
+
+ public void testIsPhotonCapableWPComPublic() {
+ assertFalse(blog.isPhotonCapable());
+ assertFalse(blog.isPrivate());
+ blog.setBlogOptions("");
+ blog.setDotcomFlag(true);
+ assertTrue(blog.isPhotonCapable());
+ }
+
+ public void testIsPhotonCapableWPComPrivate() {
+ assertFalse(blog.isPhotonCapable());
+
+ blog.setBlogOptions("{ \"blog_public\" : { \"value\" : \"-1\" } }");
+ assertFalse(blog.isPhotonCapable());
+ }
+
+ public void testGetSetHasValidJetpackCredentials() {
+ assertFalse(blog.hasValidJetpackCredentials());
+ }
+
+ public void testGetSetDotComBlogId() {
+ assertNull(blog.getDotComBlogId());
+ assertFalse(blog.isDotcomFlag());
+ blog.setApi_blogid("1");
+ blog.setRemoteBlogId(2);
+ assertEquals("1", blog.getDotComBlogId());
+ blog.setDotcomFlag(true);
+ assertEquals("2", blog.getDotComBlogId());
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/models/CategoryNodeInstrumentationTest.java b/WordPress/src/androidTest/java/org/wordpress/android/models/CategoryNodeInstrumentationTest.java
new file mode 100644
index 000000000..8eef7cff3
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/models/CategoryNodeInstrumentationTest.java
@@ -0,0 +1,34 @@
+package org.wordpress.android.models;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.InstrumentationTestCase;
+import android.test.RenamingDelegatingContext;
+
+import org.wordpress.android.TestUtils;
+
+public class CategoryNodeInstrumentationTest extends InstrumentationTestCase {
+ protected Context testContext;
+ protected Context targetContext;
+
+ @Override
+ protected void setUp() {
+ // Run tests in an isolated context
+ targetContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
+ testContext = getInstrumentation().getContext();
+ }
+
+ public void testLoadDB_MalformedCategoryParentId() {
+ SQLiteDatabase db = TestUtils.loadDBFromDump(targetContext, testContext,
+ "malformed_category_parent_id.sql");
+
+ // This line failed before #36 was solved
+ CategoryNode node = CategoryNode.createCategoryTreeFromDB(1);
+ }
+
+ public void tearDown() throws Exception {
+ targetContext = null;
+ testContext = null;
+ super.tearDown();
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/models/PostLocationTest.java b/WordPress/src/androidTest/java/org/wordpress/android/models/PostLocationTest.java
new file mode 100644
index 000000000..af8de62ba
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/models/PostLocationTest.java
@@ -0,0 +1,115 @@
+package org.wordpress.android.models;
+
+import android.test.InstrumentationTestCase;
+
+import junit.framework.Assert;
+
+public class PostLocationTest extends InstrumentationTestCase {
+ public static final double MAX_LAT = 90;
+ public static final double MIN_LAT = -90;
+ public static final double MAX_LNG = 180;
+ public static final double MIN_LNG = -180;
+ public static final double INVALID_LAT_MAX = 91;
+ public static final double INVALID_LAT_MIN = -91;
+ public static final double INVALID_LNG_MAX = 181;
+ public static final double INVALID_LNG_MIN = -181;
+ public static final double EQUATOR_LAT = 0;
+ public static final double EQUATOR_LNG = 0;
+
+ public void testInstantiateValidLocation() {
+ PostLocation locationZero = new PostLocation(EQUATOR_LAT, EQUATOR_LNG);
+ assertTrue("ZeroLoc did not instantiate valid location", locationZero.isValid());
+ assertEquals("ZeroLoc did not return correct lat", EQUATOR_LAT, locationZero.getLatitude());
+ assertEquals("ZeroLoc did not return correct lng", EQUATOR_LNG, locationZero.getLongitude());
+
+ PostLocation locationMax = new PostLocation(MAX_LAT, MAX_LNG);
+ assertTrue("MaxLoc did not instantiate valid location", locationMax.isValid());
+ assertEquals("MaxLoc did not return correct lat", MAX_LAT, locationMax.getLatitude());
+ assertEquals("MaxLoc did not return correct lng", MAX_LNG, locationMax.getLongitude());
+
+ PostLocation locationMin = new PostLocation(MIN_LAT, MIN_LNG);
+ assertTrue("MinLoc did not instantiate valid location", locationMin.isValid());
+ assertEquals("MinLoc did not return correct lat", MIN_LAT, locationMin.getLatitude());
+ assertEquals("MinLoc did not return correct lng", MIN_LNG, locationMin.getLongitude());
+
+ double miscLat = 34;
+ double miscLng = -60;
+ PostLocation locationMisc = new PostLocation(miscLat, miscLng);
+ assertTrue("MiscLoc did not instantiate valid location", locationMisc.isValid());
+ assertEquals("MiscLoc did not return correct lat", miscLat, locationMisc.getLatitude());
+ assertEquals("MiscLoc did not return correct lng", miscLng, locationMisc.getLongitude());
+ }
+
+ public void testDefaultLocationInvalid() {
+ PostLocation location = new PostLocation();
+ assertFalse("Empty location should be invalid", location.isValid());
+ }
+
+ public void testInvalidLatitude() {
+ PostLocation maxLoc = null;
+ try {
+ maxLoc = new PostLocation(INVALID_LAT_MAX, 0);
+ Assert.fail("Lat more than max should have failed on instantiation");
+ } catch (IllegalArgumentException e) {
+ assertNull("Invalid instantiation and not null", maxLoc);
+ }
+
+ PostLocation minLoc = null;
+ try {
+ minLoc = new PostLocation(INVALID_LAT_MIN, 0);
+ Assert.fail("Lat less than min should have failed on instantiation");
+ } catch (IllegalArgumentException e) {
+ assertNull("Invalid instantiation and not null", minLoc);
+ }
+
+ PostLocation location = new PostLocation();
+
+ try {
+ location.setLatitude(INVALID_LAT_MAX);
+ Assert.fail("Lat less than min should have failed");
+ } catch (IllegalArgumentException e) {
+ assertFalse("Invalid setLatitude and still valid", location.isValid());
+ }
+
+ try {
+ location.setLatitude(INVALID_LAT_MIN);
+ Assert.fail("Lat less than min should have failed");
+ } catch (IllegalArgumentException e) {
+ assertFalse("Invalid setLatitude and still valid", location.isValid());
+ }
+ }
+
+ public void testInvalidLongitude() {
+ PostLocation maxLoc = null;
+ try {
+ maxLoc = new PostLocation(0, INVALID_LNG_MAX);
+ Assert.fail("Lng more than max should have failed on instantiation");
+ } catch (IllegalArgumentException e) {
+ assertNull("Invalid instantiation and not null", maxLoc);
+ }
+
+ PostLocation minLoc = null;
+ try {
+ minLoc = new PostLocation(0, INVALID_LNG_MIN);
+ Assert.fail("Lng less than min should have failed on instantiation");
+ } catch (IllegalArgumentException e) {
+ assertNull("Invalid instantiation and not null", minLoc);
+ }
+
+ PostLocation location = new PostLocation();
+
+ try {
+ location.setLongitude(INVALID_LNG_MAX);
+ Assert.fail("Lng less than min should have failed");
+ } catch (IllegalArgumentException e) {
+ assertFalse("Invalid setLongitude and still valid", location.isValid());
+ }
+
+ try {
+ location.setLongitude(INVALID_LNG_MIN);
+ Assert.fail("Lat less than min should have failed");
+ } catch (IllegalArgumentException e) {
+ assertFalse("Invalid setLongitude and still valid", location.isValid());
+ }
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/models/PostTest.java b/WordPress/src/androidTest/java/org/wordpress/android/models/PostTest.java
new file mode 100644
index 000000000..09148d07d
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/models/PostTest.java
@@ -0,0 +1,55 @@
+package org.wordpress.android.models;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.InstrumentationTestCase;
+import android.test.RenamingDelegatingContext;
+
+import org.json.JSONObject;
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.WordPress;
+
+public class PostTest extends InstrumentationTestCase {
+ protected Context mTestContext;
+ protected Context mTargetContext;
+
+ @Override
+ protected void setUp() throws Exception {
+
+ mTargetContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
+ mTestContext = getInstrumentation().getContext();
+
+ super.setUp();
+ }
+
+ public void testInvalidPostIdLoad() {
+ SQLiteDatabase db = TestUtils.loadDBFromDump(mTargetContext, mTestContext, "taliwutt-blogs-sample.sql");
+ Post post = WordPress.wpDB.getPostForLocalTablePostId(-1);
+
+ assertNull(post);
+ }
+
+ public void testPostSaveAndLoad() {
+ SQLiteDatabase db = TestUtils.loadDBFromDump(mTargetContext, mTestContext, "taliwutt-blogs-sample.sql");
+ Post post = new Post(1, false);
+ post.setTitle("test-post");
+ WordPress.wpDB.savePost(post);
+
+ Post loadedPost = WordPress.wpDB.getPostForLocalTablePostId(post.getLocalTablePostId());
+
+ assertNotNull(loadedPost);
+ assertEquals(loadedPost.getTitle(), post.getTitle());
+ }
+
+ // reproduce issue #1544
+ public void testGetNullCustomFields() {
+ Post post = new Post(1, false);
+ assertEquals(post.getCustomFields(), null);
+ }
+
+ public void testGetNullCustomField() {
+ Post post = new Post(1, false);
+ JSONObject remoteGeoLatitude = post.getCustomField("geo_latitude");
+ assertEquals(remoteGeoLatitude, null);
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/networking/AuthenticatorRequestTest.java b/WordPress/src/androidTest/java/org/wordpress/android/networking/AuthenticatorRequestTest.java
new file mode 100644
index 000000000..c5936fd61
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/networking/AuthenticatorRequestTest.java
@@ -0,0 +1,61 @@
+package org.wordpress.android.networking;
+
+import android.test.InstrumentationTestCase;
+
+import com.wordpress.rest.RestClient;
+
+import org.wordpress.android.FactoryUtils;
+
+public class AuthenticatorRequestTest extends InstrumentationTestCase {
+ RestClient mRestClient;
+ AuthenticatorRequest mAuthenticatorRequest;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ FactoryUtils.initWithTestFactories();
+ mRestClient = RestClientFactory.instantiate(null);
+ mAuthenticatorRequest = new AuthenticatorRequest(null, null, mRestClient, null);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ FactoryUtils.clearFactories();
+ super.tearDown();
+ }
+
+ public void testExtractSiteIdFromUrl1() {
+ String url = "";
+ assertEquals(null, mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+
+ public void testExtractSiteIdFromUrl2() {
+ String url = null;
+ assertEquals(null, mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+
+ public void testExtractSiteIdFromUrl3() {
+ String url = "https://public-api.wordpress.com/rest/v1/batch/?urls%5B%5D=%2Fsites%2F57991476%2Fstats%2Freferrers%3Fdate%3D2014-05-08&urls%5B%5D=%2Fsites%2F57991476%2Fstats%2Freferrers%3Fdate%3D2014-05-07";
+ assertEquals("57991476", mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+
+ public void testExtractSiteIdFromUrl4() {
+ String url = "https://public-api.wordpress.com/rest/v1/sites/59073674/stats";
+ assertEquals("59073674", mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+
+ public void testExtractSiteIdFromUrl5() {
+ String url = "https://public-api.wordpress.com/rest/v1/sites//stats";
+ assertEquals("", mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+
+ public void testExtractSiteIdFromUrl6() {
+ String url = "https://public-api.wordpress.com/rest/v1/batch/?urls%5B%5D=%2Fsites%2F";
+ assertEquals(null, mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+
+ public void testExtractSiteIdFromUrl7() {
+ String url = "https://public-api.wordpress.com/rest/v1/sites/";
+ assertEquals(null, mAuthenticatorRequest.extractSiteIdFromUrl(mRestClient.getEndpointURL(), url));
+ }
+} \ No newline at end of file
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/networking/GravatarApiTest.java b/WordPress/src/androidTest/java/org/wordpress/android/networking/GravatarApiTest.java
new file mode 100644
index 000000000..dc8ac78c8
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/networking/GravatarApiTest.java
@@ -0,0 +1,44 @@
+package org.wordpress.android.networking;
+
+import android.test.InstrumentationTestCase;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okio.Buffer;
+
+public class GravatarApiTest extends InstrumentationTestCase {
+
+ public void testGravatarUploadRequest() throws IOException {
+ final String fileContent = "abcdefg";
+
+ File tempFile = new File(getInstrumentation().getTargetContext().getCacheDir(), "tempFile.jpg");
+ FileOutputStream fos = new FileOutputStream(tempFile);
+ fos.write(fileContent.getBytes());
+ fos.flush();
+ fos.close();
+
+ final String email = "a@b.com";
+ Request uploadRequest = GravatarApi.prepareGravatarUpload(email, tempFile);
+
+ assertEquals("POST", uploadRequest.method());
+
+ RequestBody requestBody = uploadRequest.body();
+ assertTrue(requestBody.contentType().toString().startsWith("multipart/form-data"));
+
+ final Buffer buffer = new Buffer();
+ requestBody.writeTo(buffer);
+ final String body = buffer.readUtf8();
+
+ assertTrue(body.contains("Content-Disposition: form-data; name=\"account\""));
+ assertTrue(body.contains("Content-Length: " + email.length()));
+ assertTrue(body.contains(email));
+
+ assertTrue(body.contains("Content-Disposition: form-data; name=\"filedata\"; filename=\"" + tempFile.getName() + "\""));
+ assertTrue(body.contains("Content-Type: multipart/form-data"));
+ assertTrue(body.contains(fileContent));
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/networking/WPNetworkImageViewTest.java b/WordPress/src/androidTest/java/org/wordpress/android/networking/WPNetworkImageViewTest.java
new file mode 100644
index 000000000..3e0f0fb50
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/networking/WPNetworkImageViewTest.java
@@ -0,0 +1,58 @@
+package org.wordpress.android.networking;
+
+import android.os.Handler;
+import android.test.InstrumentationTestCase;
+
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.ImageLoader.ImageContainer;
+import com.android.volley.toolbox.ImageLoader.ImageListener;
+
+import org.wordpress.android.WordPress;
+import org.wordpress.android.util.AppLog;
+import org.wordpress.android.util.AppLog.T;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class WPNetworkImageViewTest extends InstrumentationTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // https://github.com/wordpress-mobile/WordPress-Android/issues/1549
+ public void testVolleyImageLoaderGetNullHost() throws InterruptedException {
+ Handler mainLooperHandler = new Handler(WordPress.getContext().getMainLooper());
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ final boolean success[] = new boolean[1];
+ Runnable getImage = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // This call crash on old volley versions
+ WordPress.imageLoader.get("http;///hello/null/host", new ImageListener() {
+ @Override
+ public void onResponse(ImageContainer imageContainer, boolean b) {}
+
+ @Override
+ public void onErrorResponse(VolleyError volleyError) {}
+ }, 1, 1);
+ success[0] = true;
+ } catch (Exception e) {
+ AppLog.e(T.TESTS, e);
+ success[0] = false;
+ } finally {
+ countDownLatch.countDown();
+ }
+ }
+ };
+ mainLooperHandler.post(getImage);
+ countDownLatch.await(1, TimeUnit.SECONDS);
+ assertTrue("Invalid Volley library version", success[0]);
+ }
+} \ No newline at end of file
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/networking/XMLRPCTest.java b/WordPress/src/androidTest/java/org/wordpress/android/networking/XMLRPCTest.java
new file mode 100644
index 000000000..4b5c8256c
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/networking/XMLRPCTest.java
@@ -0,0 +1,35 @@
+package org.wordpress.android.networking;
+
+import org.wordpress.android.DefaultMocksInstrumentationTestCase;
+import org.wordpress.android.mocks.XMLRPCFactoryTest;
+import org.xmlrpc.android.ApiHelper.Method;
+import org.xmlrpc.android.XMLRPCClientInterface;
+import org.xmlrpc.android.XMLRPCFactory;
+
+import java.net.URI;
+
+public class XMLRPCTest extends DefaultMocksInstrumentationTestCase {
+ public void testNumberExceptionWithInvalidDouble() throws Exception {
+ XMLRPCFactoryTest.setPrefixAllInstances("invalid-double-xmlrpc");
+ XMLRPCClientInterface xmlrpcClientInterface = XMLRPCFactory.instantiate(URI.create("http://test.com/ast"), "",
+ "");
+ try {
+ xmlrpcClientInterface.call(Method.GET_MEDIA_LIBRARY, null);
+ } catch (NumberFormatException e) {
+ return;
+ }
+ assertTrue("invalid double format should trigger a NumberException", false);
+ }
+
+ public void testNumberExceptionWithInvalidInteger() throws Exception {
+ XMLRPCFactoryTest.setPrefixAllInstances("invalid-integer-xmlrpc");
+ XMLRPCClientInterface xmlrpcClientInterface = XMLRPCFactory.instantiate(URI.create("http://test.com/ast"), "",
+ "");
+ try {
+ xmlrpcClientInterface.call(Method.GET_MEDIA_LIBRARY, null);
+ } catch (NumberFormatException e) {
+ return;
+ }
+ assertTrue("invalid double format should trigger a NumberException", false);
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/GCMIntentServiceTest.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/GCMIntentServiceTest.java
new file mode 100644
index 000000000..ae2dd501f
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/GCMIntentServiceTest.java
@@ -0,0 +1,66 @@
+package org.wordpress.android.ui.notifications;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.test.RenamingDelegatingContext;
+import android.test.ServiceTestCase;
+
+import org.wordpress.android.FactoryUtils;
+import org.wordpress.android.GCMMessageService;
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.models.AccountHelper;
+
+public class GCMIntentServiceTest extends ServiceTestCase<GCMMessageService> {
+ protected Context mTargetContext;
+
+ public GCMIntentServiceTest() {
+ super(GCMMessageService.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ FactoryUtils.initWithTestFactories();
+
+ mTargetContext = new RenamingDelegatingContext(getContext(), "test_");
+ TestUtils.clearApplicationState(mTargetContext);
+
+ setupService();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ FactoryUtils.clearFactories();
+ super.tearDown();
+ }
+
+ public void testShouldCircularizeNoteIcon() {
+ GCMMessageService intentService = new GCMMessageService();
+
+ String type = "c";
+ assertTrue(intentService.shouldCircularizeNoteIcon(type));
+
+ assertFalse(intentService.shouldCircularizeNoteIcon(null));
+
+ type = "invalidType";
+ assertFalse(intentService.shouldCircularizeNoteIcon(type));
+ }
+
+ public void testOnMessageReceived() throws InterruptedException {
+ org.wordpress.android.models.Account account = AccountHelper.getDefaultAccount();
+ account.setAccessToken("secret token");
+ account.setUserId(1);
+ final Bundle bundle = new Bundle();
+ bundle.putString("user", "1");
+ for (int i = 0; i < 1000; i++) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ getService().onMessageReceived("from", bundle);
+ }
+ }).start();
+ }
+
+ Thread.sleep(10000);
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotesParseTest.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotesParseTest.java
new file mode 100644
index 000000000..0667ce023
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotesParseTest.java
@@ -0,0 +1,29 @@
+package org.wordpress.android.ui.notifications;
+
+import android.text.Spanned;
+
+import junit.framework.TestCase;
+
+import org.wordpress.android.util.HtmlUtils;
+
+public class NotesParseTest extends TestCase {
+ public void testParagraphInListItem1() {
+ String text = "<li><p>Paragraph in li</p></li>";
+ Spanned spanned = HtmlUtils.fromHtml(text);
+ // if this didn't throw a RuntimeException we're ok
+ assertNotNull(spanned);
+ }
+
+ // Trying to reproduce https://github.com/wordpress-mobile/WordPress-Android/issues/900
+ public void testSpanInListItem1() {
+ String text = "<ul><li><span>Current Record: </span><span>20</span></li><li><span>Old Record: </span><span>1</span></li></ul>";
+ Spanned spanned = HtmlUtils.fromHtml(text);
+ assertEquals("Current Record: 20\nOld Record: 1\n", spanned.toString());
+ }
+
+ public void testSpanInListItemFullTest() {
+ String text = "<p>Au Mercredi 18 septembre 2013 vous avez pulvérisé votre précédent record de follows enregistrés en un seul jour, sur votre blog <a href=\"http://taliwutblog.wordpress.com\" title=\"taliwut &amp; blog\" target=\"_blank\" notes-data-click=\"best_period_ever_feat\">taliwut &amp; blog</a>. Super!</p><ul><li><span class=\"wpn-feat-current-record-title\">Current Record: </span><span class=\"wpn-feat-new-record-count\">20</span></li><li><span class=\"wpn-feat-old-record-title\">Old Record: </span><span class=\"wpn-feat-old-record-count\">1</span></li></ul>";
+ Spanned spanned = HtmlUtils.fromHtml(text);
+ assertTrue(spanned.toString().contains("Current Record: 20\nOld Record: 1\n"));
+ }
+} \ No newline at end of file
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotificationsUtilsTest.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotificationsUtilsTest.java
new file mode 100644
index 000000000..daef7f0ba
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotificationsUtilsTest.java
@@ -0,0 +1,19 @@
+package org.wordpress.android.ui.notifications;
+
+import android.test.AndroidTestCase;
+import android.text.SpannableStringBuilder;
+
+import org.wordpress.android.ui.notifications.utils.NotificationsUtils;
+
+public class NotificationsUtilsTest extends AndroidTestCase {
+ public void testSpannableHasCharacterAtIndex() {
+ SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("This is only a test.");
+
+ assertTrue(NotificationsUtils.spannableHasCharacterAtIndex(spannableStringBuilder, 's', 3));
+ assertFalse(NotificationsUtils.spannableHasCharacterAtIndex(spannableStringBuilder, 's', 4));
+
+ // Test with bogus params
+ assertFalse(NotificationsUtils.spannableHasCharacterAtIndex(null, 'b', -1));
+ }
+
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/plans/RemoteTests.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/plans/RemoteTests.java
new file mode 100644
index 000000000..410aebc50
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/plans/RemoteTests.java
@@ -0,0 +1,159 @@
+package org.wordpress.android.ui.plans;
+
+import com.android.volley.Request;
+import com.android.volley.VolleyError;
+import com.wordpress.rest.RestClient;
+import com.wordpress.rest.RestRequest;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.wordpress.android.DefaultMocksInstrumentationTestCase;
+import org.wordpress.android.mocks.RestClientCustomizableMock;
+import org.wordpress.android.mocks.RestClientFactoryTest;
+import org.wordpress.android.networking.RestClientFactory;
+import org.wordpress.android.ui.plans.models.Feature;
+import org.wordpress.android.ui.plans.models.Plan;
+import org.wordpress.android.util.AppLog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RemoteTests extends DefaultMocksInstrumentationTestCase {
+ private RestClientCustomizableMock mRestClientV1_2;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Set the version of the REST client to v1.2
+ RestClientFactoryTest.sVersion = RestClient.REST_CLIENT_VERSIONS.V1_2;
+ mRestClientV1_2 = (RestClientCustomizableMock) RestClientFactory.instantiate(null, RestClient.REST_CLIENT_VERSIONS.V1_2);
+ }
+
+ private RestRequest.ErrorListener errListener = new RestRequest.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError response) {
+ AppLog.e(AppLog.T.PLANS, "The Rest Client returned an error from a mock call: " + response.getMessage());
+ assertFalse(response.getMessage(), true); // force the test to fails in this case
+ }
+ };
+
+ // Just a Utility class that wraps the main logic for the OK listener
+ private abstract class PlansRestRequestAbstractListener implements RestRequest.Listener {
+ @Override
+ public void onResponse(JSONObject response) {
+ boolean parseError = false;
+ try {
+ parseResponse(response);
+ } catch (JSONException e) {
+ parseError = true;
+ AppLog.e(AppLog.T.PLANS, e);
+ }
+ assertFalse(parseError);
+ }
+ abstract void parseResponse(JSONObject response) throws JSONException;
+ }
+
+ public void testSitePlans() throws Exception {
+ PlansRestRequestAbstractListener listener = new PlansRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ List<Plan> plans = new ArrayList<>();
+ JSONArray plansArray = response.getJSONArray("originalResponse");
+ for (int i=0; i < plansArray.length(); i ++) {
+ JSONObject currentPlanJSON = plansArray.getJSONObject(i);
+ Plan currentPlan = new Plan(currentPlanJSON);
+ plans.add(currentPlan);
+ }
+
+ assertEquals(3, plans.size());
+
+ Plan currentPlan = plans.get(0);
+ assertEquals(currentPlan.getDescription(), "Get a free blog and be on your way to publishing your first post in less than five minutes.");
+ assertEquals(currentPlan.getProductID(), 1L);
+ assertEquals(currentPlan.getProductName(), "WordPress.com Free");
+ assertEquals(currentPlan.getBillPeriod(), -1);
+ assertEquals(currentPlan.getRawPrice(), 0);
+ assertEquals(currentPlan.getCost(), 0);
+ assertEquals(currentPlan.isAvailable(), true);
+
+ currentPlan = plans.get(1);
+ assertEquals(currentPlan.isFreeTrial(), false);
+ assertEquals(currentPlan.getBundleSubscriptionID(), "5683566");
+ assertEquals(currentPlan.getExpiry(), "2017-03-07");
+ assertEquals(currentPlan.getUserFacingExpiry(), "2017-03-04");
+ assertEquals(currentPlan.getSubscribedDate(), "2016-03-07 08:56:13");
+
+ currentPlan = plans.get(2);
+ assertEquals(currentPlan.getDescription(), "Everything included with Premium, as well as live chat support, and unlimited access to our premium themes.");
+ assertEquals(currentPlan.getProductID(), 1008L);
+ assertEquals(currentPlan.getProductName(), "WordPress.com Business");
+ assertEquals(currentPlan.getBillPeriod(), 365);
+ assertEquals(currentPlan.getRawPrice(), 199);
+ assertEquals(currentPlan.getCost(), 199);
+ assertEquals(currentPlan.isAvailable(), true);
+ }
+ };
+
+
+ mRestClientV1_2.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.2/sites/123456/plans",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testFeatures() throws Exception {
+ PlansRestRequestAbstractListener listener = new PlansRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ // Parse the response from the server
+ List<Feature> features = new ArrayList<>();
+ JSONArray featuresArray = response.getJSONArray("originalResponse");
+ for (int i = 0; i < featuresArray.length(); i++) {
+ JSONObject currentFeatureJSON = featuresArray.getJSONObject(i);
+ Feature currentFeature = new Feature(currentFeatureJSON);
+ features.add(currentFeature);
+ }
+
+ assertEquals(16, features.size());
+
+ // Test the 1st object in the response
+ Feature currentFeatures = features.get(0);
+ assertEquals("WordPress.com Site", currentFeatures.getTitle());
+ assertEquals("free-blog", currentFeatures.getProductSlug());
+ assertEquals("Your own space to create posts and pages with basic customization.", currentFeatures.getDescription());
+ assertEquals("Your own space to create posts and pages with basic customization.",
+ currentFeatures.getDescriptionForPlan(1L));
+ assertEquals("Your own space to create posts and pages with basic customization.",
+ currentFeatures.getDescriptionForPlan(1003L));
+ assertEquals("Your own space to create posts and pages with basic customization.",
+ currentFeatures.getDescriptionForPlan(1008L));
+
+ assertEquals(false, currentFeatures.isNotPartOfFreeTrial());
+
+ // Test the latest object in the response
+ currentFeatures = features.get(15);
+ assertEquals("Support", currentFeatures.getTitle());
+ assertEquals("support", currentFeatures.getProductSlug());
+ assertEquals("For those times when you can't find an answer on our Support site", currentFeatures.getDescription());
+ assertEquals("Find answers to your questions in our community forum.",
+ currentFeatures.getDescriptionForPlan(1L));
+ assertEquals("Community support",
+ currentFeatures.getTitleForPlan(1L));
+ assertEquals("The kind of support we offer for Jetpack Business.",
+ currentFeatures.getDescriptionForPlan(2001L));
+ assertEquals("Priority security support",
+ currentFeatures.getTitleForPlan(2001L));
+ assertEquals(false, currentFeatures.isNotPartOfFreeTrial());
+ }
+ };
+
+ mRestClientV1_2.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.2/plans/features",
+ null,
+ listener,
+ errListener
+ );
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/posts/PostUtilsTest.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/posts/PostUtilsTest.java
new file mode 100644
index 000000000..d251d9f28
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/posts/PostUtilsTest.java
@@ -0,0 +1,33 @@
+package org.wordpress.android.ui.posts;
+
+import android.test.AndroidTestCase;
+
+public class PostUtilsTest extends AndroidTestCase {
+ public void testCollapseShortcodes() {
+ String postContent = "Text before first gallery [gallery number=\"one\"]"
+ + " text between galleries"
+ + " [gallery number=\"two\"]"
+ + " text after second gallery"
+ + " [unknown shortcode].";
+ String collapsedContent = PostUtils.collapseShortcodes(postContent);
+
+ // make sure [gallery] now exists and [gallery number] does not
+ assertTrue(collapsedContent.contains("[gallery]"));
+ assertFalse(collapsedContent.contains("[gallery number]"));
+
+ // make sure the unknown shortcode is intact
+ assertTrue(collapsedContent.contains("[unknown shortcode]"));
+ }
+
+ public void testShortcodeSpaces() {
+ String postContent = "[ gallery number=\"arst\" /]";
+ String collapsedContent = PostUtils.collapseShortcodes(postContent);
+ assertEquals("[gallery]", collapsedContent);
+ }
+
+ public void testOpeningClosingShortcode() {
+ String postContent = "[recipe difficulty=\"easy\"]Put your recipe here.[/recipe]";
+ String collapsedContent = PostUtils.collapseShortcodes(postContent);
+ assertEquals("[recipe]Put your recipe here.[/recipe]", collapsedContent);
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/stats/RemoteTests.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/stats/RemoteTests.java
new file mode 100644
index 000000000..ff8a9505d
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/stats/RemoteTests.java
@@ -0,0 +1,638 @@
+package org.wordpress.android.ui.stats;
+
+
+import com.android.volley.Request;
+import com.android.volley.VolleyError;
+import com.wordpress.rest.RestClient;
+import com.wordpress.rest.RestRequest;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.wordpress.android.DefaultMocksInstrumentationTestCase;
+import org.wordpress.android.mocks.RestClientCustomizableMock;
+import org.wordpress.android.mocks.RestClientFactoryTest;
+import org.wordpress.android.networking.RestClientFactory;
+import org.wordpress.android.ui.stats.models.AuthorModel;
+import org.wordpress.android.ui.stats.models.ClickGroupModel;
+import org.wordpress.android.ui.stats.models.ClicksModel;
+import org.wordpress.android.ui.stats.models.CommentsModel;
+import org.wordpress.android.ui.stats.models.FollowDataModel;
+import org.wordpress.android.ui.stats.models.FollowerModel;
+import org.wordpress.android.ui.stats.models.FollowersModel;
+import org.wordpress.android.ui.stats.models.GeoviewModel;
+import org.wordpress.android.ui.stats.models.GeoviewsModel;
+import org.wordpress.android.ui.stats.models.InsightsAllTimeModel;
+import org.wordpress.android.ui.stats.models.InsightsPopularModel;
+import org.wordpress.android.ui.stats.models.InsightsTodayModel;
+import org.wordpress.android.ui.stats.models.PostModel;
+import org.wordpress.android.ui.stats.models.PostViewsModel;
+import org.wordpress.android.ui.stats.models.ReferrerGroupModel;
+import org.wordpress.android.ui.stats.models.ReferrerResultModel;
+import org.wordpress.android.ui.stats.models.ReferrersModel;
+import org.wordpress.android.ui.stats.models.SingleItemModel;
+import org.wordpress.android.ui.stats.models.TagsContainerModel;
+import org.wordpress.android.ui.stats.models.TagsModel;
+import org.wordpress.android.ui.stats.models.TopPostsAndPagesModel;
+import org.wordpress.android.ui.stats.models.VideoPlaysModel;
+import org.wordpress.android.ui.stats.models.VisitModel;
+import org.wordpress.android.ui.stats.models.VisitsModel;
+import org.wordpress.android.util.AppLog;
+
+
+public class RemoteTests extends DefaultMocksInstrumentationTestCase {
+
+ private RestClientCustomizableMock mRestClient;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Set the version of the REST client to 1.1
+ RestClientFactoryTest.sVersion = RestClient.REST_CLIENT_VERSIONS.V1_1;
+
+ mRestClient = (RestClientCustomizableMock) RestClientFactory.instantiate(null, RestClient.REST_CLIENT_VERSIONS.V1_1);
+ }
+
+ private RestRequest.ErrorListener errListener = new RestRequest.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError response) {
+ AppLog.e(AppLog.T.STATS, "The Rest Client returned an error from a mock call: " + response.getMessage());
+ assertFalse(response.getMessage(), true); // force the test to fails in this case
+ }
+ };
+
+ // Just a Utility class that wraps the main logic for the OK listener
+ private abstract class StatsRestRequestAbstractListener implements RestRequest.Listener {
+ @Override
+ public void onResponse(JSONObject response) {
+ boolean parseError = false;
+ try {
+ parseResponse(response);
+ } catch (JSONException e) {
+ parseError = true;
+ AppLog.e(AppLog.T.STATS, e);
+ }
+ assertFalse(parseError);
+ }
+ abstract void parseResponse(JSONObject response) throws JSONException;
+ }
+
+ public void testClicks() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ ClicksModel model = new ClicksModel("123456",response);
+ assertEquals(model.getTotalClicks(), 2);
+ assertEquals(model.getOtherClicks(), 0);
+ assertNotNull(model.getClickGroups());
+ assertEquals(model.getClickGroups().size(), 2);
+
+ ClickGroupModel first = model.getClickGroups().get(0);
+ assertEquals(first.getIcon(), "");
+ assertEquals(first.getUrl(), "http://astralbodies.net/blog/2013/10/31/paying-attention-at-automattic/");
+ assertEquals(first.getName(), "astralbodies.net/blog/2013/10/31/paying-attention-at-automattic/");
+ assertEquals(first.getViews(), 1);
+ assertNull(first.getClicks());
+
+ ClickGroupModel second = model.getClickGroups().get(1);
+ assertEquals(second.getIcon(), "");
+ assertEquals(second.getUrl(), "https://devforums.apple.com/thread/86137");
+ assertEquals(second.getName(), "devforums.apple.com/thread/86137");
+ assertEquals(second.getViews(), 1);
+ assertNull(second.getClicks());
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/clicks",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testClicksForMonth() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ ClicksModel model = new ClicksModel("1234567890",response);
+ assertEquals(model.getTotalClicks(), 9);
+ assertEquals(model.getOtherClicks(), 0);
+ assertNotNull(model.getClickGroups());
+ assertEquals(model.getClickGroups().size(), 6);
+
+ ClickGroupModel first = model.getClickGroups().get(0);
+ assertEquals(first.getIcon(), "");
+ assertEquals(first.getUrl(), "http://wp.com/");
+ assertEquals(first.getName(), "wp.com");
+ assertEquals(first.getViews(), 3);
+ assertNull(first.getClicks());
+
+ ClickGroupModel second = model.getClickGroups().get(1);
+ assertEquals(second.getIcon(), "");
+ assertNull(second.getUrl());
+ assertEquals(second.getName(), "blog.wordpress.tv");
+ assertEquals(second.getViews(), 2);
+ assertNotNull(second.getClicks());
+ assertEquals(second.getClicks().size(), 2);
+
+ SingleItemModel firstChild = second.getClicks().get(0);
+ assertNotNull(firstChild);
+ assertEquals(firstChild.getUrl(), "http://blog.wordpress.tv/2014/10/03/build-your-audience-recent-wordcamp-videos-from-experienced-content-creators/");
+ assertEquals(firstChild.getTitle(), "blog.wordpress.tv/2014/10/03/build-your-audience-recent-wordcamp-videos-from-experienced-content-creators/");
+ assertEquals(firstChild.getTotals(), 1);
+ assertEquals(firstChild.getIcon(), "");
+
+
+ SingleItemModel secondChild = second.getClicks().get(1);
+ assertNotNull(secondChild);
+ assertEquals(secondChild.getUrl(), "http://blog.wordpress.tv/2014/10/29/wordcamp-san-francisco-2014-state-of-the-word-keynote/");
+ assertEquals(secondChild.getTitle(), "blog.wordpress.tv/2014/10/29/wordcamp-san-francisco-2014-state-of-the-word-keynote/");
+ assertEquals(secondChild.getTotals(), 1);
+ assertEquals(secondChild.getIcon(), "");
+
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/1234567890/stats/clicks",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testCommentsDay() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ CommentsModel model = new CommentsModel("123456", response);
+ assertEquals(model.getTotalComments(), 177);
+ assertEquals(model.getMonthlyComments(), 2);
+ assertEquals(model.getMostActiveTime(), "08:00");
+ assertEquals(model.getMostActiveDay(), "");
+
+ assertNotNull(model.getAuthors());
+ assertTrue(model.getAuthors().size() == 7);
+ AuthorModel author = model.getAuthors().get(0);
+ assertEquals(author.getName(), "Aaron Douglas");
+ assertEquals(author.getViews(), 20);
+ assertEquals(author.getAvatar(),
+ "https://1.gravatar.com/avatar/db127a496309f2717657d6f6167abd49?s=64&amp;" +
+ "d=https%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D64&amp;r=R"
+ );
+ assertNull(author.getFollowData());
+ assertNull(author.getPosts());
+
+ assertNotNull(model.getPosts());
+ assertTrue(model.getPosts().size() == 11);
+ SingleItemModel mostCommentedPost = model.getPosts().get(0);
+ assertEquals(mostCommentedPost.getItemID(), "67");
+ assertEquals(mostCommentedPost.getTotals(), 29);
+ assertEquals(mostCommentedPost.getTitle(), "Mac Screen Sharing (VNC) & White Screen");
+ assertEquals(mostCommentedPost.getUrl(), "http://astralbodi.es/2010/05/02/mac-screen-sharing-vnc-white-screen/");
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/comments",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testCountryViewsDay() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ GeoviewsModel model = new GeoviewsModel("123456", response);
+ assertEquals(model.getOtherViews(), 17);
+ assertEquals(model.getTotalViews(), 55);
+
+ assertNotNull(model.getCountries());
+ assertEquals(model.getCountries().size(), 10);
+ GeoviewModel first = model.getCountries().get(0);
+ assertEquals(first.getCountryFullName(), "United States");
+ assertEquals(first.getFlagIconURL(), "https://secure.gravatar.com/blavatar/5a83891a81b057fed56930a6aaaf7b3c?s=48");
+ assertEquals(first.getFlatFlagIconURL(), "https://secure.gravatar.com/blavatar/9f4faa5ad0c723474f7a6d810172447c?s=48");
+ assertEquals(first.getViews(), 8);
+ GeoviewModel second = model.getCountries().get(1);
+ assertEquals(second.getCountryFullName(), "Taiwan");
+ assertEquals(second.getFlagIconURL(), "https://secure.gravatar.com/blavatar/f983fff0dda7387746b697cfd865e657?s=48");
+ assertEquals(second.getFlatFlagIconURL(), "https://secure.gravatar.com/blavatar/2c224480a40527ee89d7340d4396e8e6?s=48");
+ assertEquals(second.getViews(), 6);
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/country-views",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testFollowersEmail() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ FollowersModel model = new FollowersModel("123456", response);
+ assertEquals(model.getTotalEmail(), 2931);
+ assertEquals(model.getTotalWPCom(), 7926165);
+ assertEquals(model.getTotal(), 2931);
+ assertEquals(model.getPage(), 1);
+ assertEquals(model.getPages(), 419);
+
+ assertNotNull(model.getFollowers());
+ assertEquals(model.getFollowers().size(), 7);
+ FollowerModel first = model.getFollowers().get(0);
+ assertEquals(first.getAvatar(), "https://2.gravatar.com/avatar/e82142697283897ad7444810e5975895?s=64" +
+ "&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D64&amp;r=G");
+ assertEquals(first.getLabel(), "user1@example.com");
+ assertNull(first.getURL());
+ assertNull(first.getFollowData());
+ assertEquals(first.getDateSubscribed(), "2014-12-16T11:24:41+00:00");
+ FollowerModel last = model.getFollowers().get(6);
+ assertEquals(last.getAvatar(), "https://0.gravatar.com/avatar/3b37f38b63ce4f595cc5cfbaadb10938?s=64" +
+ "&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D64&amp;r=G");
+ assertEquals(last.getLabel(), "user7@example.com");
+ assertNull(last.getURL());
+ assertNull(last.getFollowData());
+ assertEquals(last.getDateSubscribed(), "2014-12-15T15:09:01+00:00");
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/followers",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testFollowersWPCOM() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ FollowersModel model = new FollowersModel("1234567890", response);
+ assertEquals(model.getTotalEmail(), 2930);
+ assertEquals(model.getTotalWPCom(), 7925800);
+ assertEquals(model.getTotal(), 7925800);
+ assertEquals(model.getPage(), 1);
+ assertEquals(model.getPages(), 1132258);
+
+ assertNotNull(model.getFollowers());
+ assertEquals(model.getFollowers().size(), 7);
+ FollowerModel first = model.getFollowers().get(0);
+ assertEquals(first.getAvatar(), "https://0.gravatar.com/avatar/624b89cb0c8b9136f9629dd7bcab0517?s=64" +
+ "&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D64&amp;r=G");
+ assertEquals(first.getLabel(), "ritu929");
+ assertEquals(first.getURL(), "http://ritu9blog.wordpress.com");
+ assertEquals(first.getDateSubscribed(), "2014-12-16T14:53:21+00:00");
+ assertNotNull(first.getFollowData());
+ FollowDataModel followDatamodel = first.getFollowData();
+ assertFalse(followDatamodel.isFollowing());
+ assertEquals(followDatamodel.getType(), "follow");
+
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/1234567890/stats/followers",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testPostDetails() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ PostViewsModel model = new PostViewsModel(response);
+ assertNotNull(model.getOriginalResponse());
+
+ assertEquals(model.getDate(), "2015-03-04");
+ assertEquals(model.getHighestMonth(), 278);
+ assertEquals(model.getHighestDayAverage(), 8);
+ assertEquals(model.getHighestWeekAverage(), 8);
+
+ assertNotNull(model.getDayViews());
+ assertEquals(model.getDayViews()[0].getViews(), 0);
+ assertEquals(model.getDayViews()[0].getPeriod(), "2014-06-04");
+ assertEquals(model.getDayViews()[model.getDayViews().length-1].getViews(), 8);
+ assertEquals(model.getDayViews()[model.getDayViews().length - 1].getPeriod(), "2015-03-04");
+
+ assertNotNull(model.getYears().size());
+ assertEquals(model.getYears().size(), 2);
+ assertEquals(model.getYears().get(0).getTotal(), 1097);
+ assertEquals(model.getYears().get(0).getLabel(), "2014");
+ assertEquals(model.getYears().get(0).getMonths().size(), 7);
+ assertEquals(model.getYears().get(0).getMonths().get(0).getMonth(), "6");
+ assertEquals(model.getYears().get(1).getTotal(), 226);
+ assertEquals(model.getYears().get(1).getLabel(), "2015");
+
+ assertNotNull(model.getWeeks().size());
+ assertEquals(model.getWeeks().size(), 6);
+
+ assertNotNull(model.getAverages());
+ assertEquals(model.getAverages().size(), 2);
+ assertEquals(model.getAverages().get(0).getTotal(), 5);
+ assertEquals(model.getAverages().get(0).getLabel(), "2014");
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/post/123",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testReferrers() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ ReferrersModel model = new ReferrersModel("123456", response);
+ assertEquals(model.getTotalViews(), 2161);
+ assertEquals(model.getOtherViews(), 938);
+ assertNotNull(model.getGroups());
+ assertEquals(model.getGroups().size(), 10);
+
+ // first group in the response
+ ReferrerGroupModel gModel = model.getGroups().get(0);
+ assertEquals(gModel.getName(), "Search Engines");
+ assertEquals(gModel.getGroupId(), "Search Engines");
+ assertEquals(gModel.getIcon(), "https://wordpress.com/i/stats/search-engine.png");
+ assertEquals(gModel.getTotal(), 480);
+ assertNotNull(gModel.getResults());
+ assertEquals(gModel.getResults().size(), 7);
+
+ // 2nd level item
+ ReferrerResultModel refResultModel = gModel.getResults().get(0);
+ assertEquals(refResultModel.getName(), "Google Search");
+ assertEquals(refResultModel.getIcon(), "https://secure.gravatar.com/blavatar/6741a05f4bc6e5b65f504c4f3df388a1?s=48");
+ assertEquals(refResultModel.getViews(), 461);
+ assertNotNull(refResultModel.getChildren());
+ assertNull(refResultModel.getUrl()); //has childs. No URL.
+
+ // 3rd level items
+ SingleItemModel child = refResultModel.getChildren().get(0);
+ assertEquals(child.getUrl(), "http://www.google.com/");
+ assertEquals(child.getTitle(), "google.com");
+ assertEquals(child.getIcon(), "https://secure.gravatar.com/blavatar/ff90821feeb2b02a33a6f9fc8e5f3fcd?s=48");
+ assertEquals(child.getTotals(), 176);
+ child = refResultModel.getChildren().get(10);
+ assertEquals(child.getUrl(), "http://www.google.co.jp");
+ assertEquals(child.getTitle(), "google.co.jp");
+ assertEquals(child.getIcon(), "https://secure.gravatar.com/blavatar/a28b8206a6562f6098688508d4665905?s=48");
+ assertEquals(child.getTotals(), 6);
+
+
+ // 7th group in the response
+ gModel = model.getGroups().get(6);
+ assertEquals(gModel.getName(), "ma.tt");
+ assertEquals(gModel.getGroupId(), "ma.tt");
+ assertEquals(gModel.getIcon(), "https://secure.gravatar.com/blavatar/733a27a6b983dd89d6dd64d0445a3e8e?s=48");
+ assertEquals(gModel.getTotal(), 56);
+ assertNotNull(gModel.getResults());
+ assertEquals(gModel.getResults().size(), 11);
+
+ // 2nd level item
+ refResultModel = gModel.getResults().get(0);
+ assertEquals(refResultModel.getName(), "ma.tt");
+ assertEquals(refResultModel.getUrl(), "http://ma.tt/");
+ assertEquals(refResultModel.getIcon(), "");
+ assertEquals(refResultModel.getViews(), 34); // No childs. Has URL.
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/referrers",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testTagsCategories() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ TagsContainerModel model = new TagsContainerModel("123456", response);
+ assertEquals(model.getDate(), "2014-12-16");
+ assertNotNull(model.getTags());
+ assertEquals(model.getTags().size(), 10);
+
+ TagsModel tag = model.getTags().get(0);
+ assertEquals(tag.getViews(), 461);
+ assertNotNull(tag.getTags());
+ assertEquals(tag.getTags().size(), 1);
+ assertNotNull(tag.getTags());
+ assertEquals(tag.getTags().get(0).getName(), "Uncategorized");
+ assertEquals(tag.getTags().get(0).getType(), "category");
+ assertEquals(tag.getTags().get(0).getLink(), "http://astralbodi.es/category/uncategorized/");
+
+ tag = model.getTags().get(9);
+ assertEquals(tag.getViews(), 41);
+ assertEquals(tag.getTags().get(0).getName(), "networking");
+ assertEquals(tag.getTags().get(0).getType(), "tag");
+ assertEquals(tag.getTags().get(0).getLink(), "http://astralbodi.es/tag/networking/");
+ assertEquals(tag.getTags().get(1).getName(), "unix");
+ assertEquals(tag.getTags().get(1).getType(), "tag");
+ assertEquals(tag.getTags().get(1).getLink(), "http://astralbodi.es/tag/unix/");
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/tags",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testTopPost() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ TopPostsAndPagesModel model = new TopPostsAndPagesModel("123456", response);
+ assertNotNull(model.getTopPostsAndPages());
+ assertEquals(model.getTopPostsAndPages().size(), 10);
+
+ PostModel postModel = model.getTopPostsAndPages().get(0);
+ assertEquals(postModel.getItemID(), "39806");
+ assertEquals(postModel.getTotals(), 2420);
+ assertEquals(postModel.getTitle(), "Home");
+ assertEquals(postModel.getUrl(), "http://automattic.com/home/");
+ assertEquals(postModel.getDate(), StatsUtils.toMs("2011-08-30 21:47:38"));
+ assertEquals(postModel.getPostType(), "page");
+
+ postModel = model.getTopPostsAndPages().get(9);
+ assertEquals(postModel.getItemID(), "39254");
+ assertEquals(postModel.getTotals(), 56);
+ assertEquals(postModel.getTitle(), "Growth Explorer");
+ assertEquals(postModel.getUrl(), "http://automattic.com/work-with-us/growth-explorer/");
+ assertEquals(postModel.getDate(), StatsUtils.toMs("2011-08-25 19:37:27"));
+ assertEquals(postModel.getPostType(), "page");
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/top-posts",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testTopPostEmptyURL() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ TopPostsAndPagesModel model = new TopPostsAndPagesModel("1234567890", response);
+ assertNotNull(model.getTopPostsAndPages());
+ assertEquals(model.getTopPostsAndPages().size(), 10);
+
+ PostModel postModel = model.getTopPostsAndPages().get(0);
+ assertEquals(postModel.getItemID(), "750");
+ assertEquals(postModel.getTotals(), 7);
+ assertEquals(postModel.getTitle(), "Asynchronous unit testing Core Data with Xcode 6");
+ assertEquals(postModel.getUrl(), ""); // This post has no URL?!? Unpublished post that was prev published?
+ assertEquals(postModel.getDate(), StatsUtils.toMs("2014-08-06 14:52:11"));
+ assertEquals(postModel.getPostType(), "post");
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/1234567890/stats/top-posts",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testInsightsAllTime() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ InsightsAllTimeModel model = new InsightsAllTimeModel("12345",response);
+ assertEquals(model.getPosts(), 128);
+ assertEquals(model.getViews(), 56687);
+ assertEquals(model.getVisitors(), 42893);
+ assertEquals(model.getViewsBestDayTotal(), 3485);
+ assertNotNull(model.getViewsBestDay());
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testInsightsToday() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ InsightsTodayModel model = new InsightsTodayModel("123456", response);
+ assertEquals(model.getDate(), "2014-10-28");
+ assertEquals(model.getBlogID(), "123456");
+ assertEquals(model.getViews(), 56);
+ assertEquals(model.getVisitors(), 44);
+ assertEquals(model.getLikes(), 1);
+ assertEquals(model.getReblogs(), 2);
+ assertEquals(model.getComments(), 3);
+ assertEquals(model.getFollowers(), 56);
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/summary",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testInsightsPopular() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ InsightsPopularModel model = new InsightsPopularModel("123456", response);
+ assertEquals(model.getHighestHour(), 9);
+ assertEquals(model.getHighestDayOfWeek(), 5);
+ assertEquals(model.getHighestDayPercent(), 30.532081377152);
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/insights",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testVideoPlaysNoData() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ VideoPlaysModel model = new VideoPlaysModel("123456", response);
+ assertEquals(model.getOtherPlays(), 0);
+ assertEquals(model.getTotalPlays(), 0);
+ assertNotNull(model.getPlays());
+ assertEquals(model.getPlays().size(), 0);
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/video-plays",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testVideoPlays() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ VideoPlaysModel model = new VideoPlaysModel("1234567890", response);
+ assertEquals(model.getOtherPlays(), 0);
+ assertEquals(model.getTotalPlays(), 2);
+ assertNotNull(model.getPlays());
+ assertEquals(model.getPlays().size(), 1);
+ SingleItemModel videoItemModel = model.getPlays().get(0);
+ assertEquals(videoItemModel.getTitle(), "Test Video");
+ assertEquals(videoItemModel.getUrl(), "http://maplebaconyummies.wordpress.com/wp-admin/media.php?action=edit&attachment_id=144");
+ assertEquals(videoItemModel.getItemID(), "144");
+ assertEquals(videoItemModel.getTotals(), 2);
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/1234567890/stats/video-plays",
+ null,
+ listener,
+ errListener
+ );
+ }
+
+ public void testVisits() throws Exception {
+ StatsRestRequestAbstractListener listener = new StatsRestRequestAbstractListener() {
+ @Override
+ void parseResponse(JSONObject response) throws JSONException {
+ VisitsModel model = new VisitsModel("123456", response);
+ assertNotNull(model.getVisits());
+ assertNotNull(model.getUnit());
+ assertNotNull(model.getDate());
+
+ assertEquals(model.getVisits().size(), 30);
+ assertEquals(model.getUnit(), "day");
+
+ VisitModel visitModel = model.getVisits().get(0);
+ assertEquals(visitModel.getViews(), 7808);
+ assertEquals(visitModel.getVisitors(), 4331);
+ assertEquals(visitModel.getLikes(), 0);
+ assertEquals(visitModel.getComments(), 0);
+ assertEquals(visitModel.getPeriod(), "2014-10-08");
+
+ }
+ };
+
+ mRestClient.makeRequest(Request.Method.POST, "https://public-api.wordpress.com/rest/v1.1/sites/123456/stats/visits",
+ null,
+ listener,
+ errListener
+ );
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/util/ApiHelperTest.java b/WordPress/src/androidTest/java/org/wordpress/android/util/ApiHelperTest.java
new file mode 100644
index 000000000..82b3ba214
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/util/ApiHelperTest.java
@@ -0,0 +1,124 @@
+package org.wordpress.android.util;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.test.InstrumentationTestCase;
+import android.test.RenamingDelegatingContext;
+
+import org.wordpress.android.FactoryUtils;
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.mocks.RestClientFactoryTest;
+import org.wordpress.android.mocks.XMLRPCFactoryTest;
+import org.wordpress.android.models.Blog;
+import org.wordpress.android.models.Comment;
+import org.wordpress.android.models.CommentStatus;
+import org.wordpress.android.util.AppLog.T;
+import org.xmlrpc.android.ApiHelper;
+import org.xmlrpc.android.ApiHelper.ErrorType;
+import org.xmlrpc.android.ApiHelper.GenericCallback;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class ApiHelperTest extends InstrumentationTestCase {
+ protected Context mTargetContext;
+
+ @Override
+ protected void setUp() {
+ FactoryUtils.initWithTestFactories();
+
+ // Clean application state
+ mTargetContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
+ TestUtils.clearApplicationState(mTargetContext);
+
+ // Init contexts
+ XMLRPCFactoryTest.sContext = getInstrumentation().getContext();
+ RestClientFactoryTest.sContext = getInstrumentation().getContext();
+ AppLog.v(T.TESTS, "Contexts set");
+
+ // Set mode to Customizable
+ XMLRPCFactoryTest.sMode = XMLRPCFactoryTest.Mode.CUSTOMIZABLE_JSON;
+ RestClientFactoryTest.sMode = RestClientFactoryTest.Mode.CUSTOMIZABLE;
+ AppLog.v(T.TESTS, "Modes set to customizable");
+ }
+
+ @Override
+ protected void tearDown() {
+ FactoryUtils.clearFactories();
+ }
+
+ private void countDownAfterOtherAsyncTasks(final CountDownLatch countDownLatch) {
+ AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {
+ @Override
+ public void run() {
+ countDownLatch.countDown();
+ }
+ });
+ }
+
+ // This test failed before #773 was fixed
+ public void testRefreshBlogContent() throws InterruptedException {
+ XMLRPCFactoryTest.setPrefixAllInstances("malformed-software-version");
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ Blog dummyBlog = new Blog("", "", "");
+ new ApiHelper.RefreshBlogContentTask(dummyBlog, new GenericCallback() {
+ @Override
+ public void onSuccess() {
+ assertTrue(true);
+ // countDown() after the serially invoked (nested) AsyncTask in RefreshBlogContentTask.
+ countDownAfterOtherAsyncTasks(countDownLatch);
+ }
+
+ @Override
+ public void onFailure(ErrorType errorType, String errorMessage, Throwable throwable) {
+ assertTrue(false);
+ // countDown() after the serially invoked (nested) AsyncTask in RefreshBlogContentTask.
+ countDownAfterOtherAsyncTasks(countDownLatch);
+ }
+ }).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, false);
+ countDownLatch.await(5000, TimeUnit.SECONDS);
+ }
+
+ // This test failed before #799 was fixed
+ public void testRefreshBlogContentEmptyResponse() throws InterruptedException {
+ XMLRPCFactoryTest.setPrefixAllInstances("empty");
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ Blog dummyBlog = new Blog("", "", "");
+ new ApiHelper.RefreshBlogContentTask(dummyBlog, new GenericCallback() {
+ @Override
+ public void onSuccess() {
+ assertTrue(false);
+ // countDown() after the serially invoked (nested) AsyncTask in RefreshBlogContentTask.
+ countDownAfterOtherAsyncTasks(countDownLatch);
+ }
+
+ @Override
+ public void onFailure(ErrorType errorType, String errorMessage, Throwable throwable) {
+ assertTrue(true);
+ // countDown() after the serially invoked (nested) AsyncTask in RefreshBlogContentTask.
+ countDownAfterOtherAsyncTasks(countDownLatch);
+ }
+ }).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, false);
+ countDownLatch.await(5000, TimeUnit.SECONDS);
+ }
+
+ public void testSpamSpammedComment() {
+ XMLRPCFactoryTest.sMode = XMLRPCFactoryTest.Mode.CUSTOMIZABLE_XML;
+ XMLRPCFactoryTest.setPrefixAllInstances("comment-already-spammed");
+ Blog dummyBlog = new Blog("", "", "");
+ // contrstust a dummy (albeit invalid) comment object to pass the comment id
+ Comment comment = new Comment(1, 2, null, null, null, null, null, null, null, null);
+
+ assertTrue(ApiHelper.editComment(dummyBlog, comment, CommentStatus.SPAM));
+ }
+
+ public void testGetSpammedCommentStatus() {
+ XMLRPCFactoryTest.sMode = XMLRPCFactoryTest.Mode.CUSTOMIZABLE_XML;
+ XMLRPCFactoryTest.setPrefixAllInstances("comment-already-spammed");
+ Blog dummyBlog = new Blog("", "", "");
+ // contrstust a dummy (albeit invalid) comment object to pass the comment id
+ Comment comment = new Comment(1, 2, null, null, null, null, null, null, null, null);
+
+ assertEquals(CommentStatus.SPAM, ApiHelper.getCommentStatus(dummyBlog, comment));
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/util/AutolinkUtilsTest.java b/WordPress/src/androidTest/java/org/wordpress/android/util/AutolinkUtilsTest.java
new file mode 100644
index 000000000..5341c96bd
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/util/AutolinkUtilsTest.java
@@ -0,0 +1,79 @@
+package org.wordpress.android.util;
+
+import android.test.InstrumentationTestCase;
+
+public class AutolinkUtilsTest extends InstrumentationTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testNullString() {
+ AutolinkUtils.autoCreateLinks(null);
+ }
+
+ public void testEmptyString() {
+ String sourceTest = "";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ assertEquals(sourceTest, output);
+ }
+
+ public void testNonBlacklistedUrl1() {
+ String sourceTest = "http://test.com";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ String expected = "<a href=\"http://test.com\">http://test.com</a>";
+ assertEquals(expected, output);
+ }
+
+ public void testNonBlacklistedUrl2() {
+ String sourceTest = "http://test.com http://test.com";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ String expected = "<a href=\"http://test.com\">http://test.com</a> <a href=\"http://test.com\">http://test.com</a>";
+ assertEquals(expected, output);
+ }
+
+ public void testNonBlacklistedUrl3() {
+ String sourceTest = "http://test.com\nhttp://test.com";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ String expected = "<a href=\"http://test.com\">http://test.com</a>\n<a href=\"http://test.com\">http://test.com</a>";
+ assertEquals(expected, output);
+ }
+
+ public void testBlacklistedUrl1() {
+ String sourceTest = "http://youtube.com/watch?test";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ assertEquals(sourceTest, output);
+ }
+
+ public void testMixedUrls1() {
+ String sourceTest = "hey http://youtube.com/watch?test salut http://test.com hello";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ String expected = "hey http://youtube.com/watch?test salut <a href=\"http://test.com\">http://test.com</a> hello";
+ assertEquals(expected, output);
+ }
+
+ public void testExistingAHref1() {
+ String sourceTest = "<a href=\"http://test.com\">http://test.com</a>";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ assertEquals(sourceTest, output);
+ }
+
+ public void testUndetectable1() {
+ String sourceTest = "testhttp://test.com";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ assertEquals(sourceTest, output);
+ }
+
+ public void testUndetectable2() {
+ String sourceTest = "\"http://test.com\"";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ assertEquals(sourceTest, output);
+ }
+
+ public void testMixedUrls2() {
+ String sourceTest = "http://test.com http://www.youtube.com/watch?test http://test.com http://youtu.be/wat";
+ String output = AutolinkUtils.autoCreateLinks(sourceTest);
+ String expected = "<a href=\"http://test.com\">http://test.com</a> http://www.youtube.com/watch?test <a href=\"http://test.com\">http://test.com</a> http://youtu.be/wat";
+ assertEquals(expected, output);
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/util/HealthCheckTest.java b/WordPress/src/androidTest/java/org/wordpress/android/util/HealthCheckTest.java
new file mode 100644
index 000000000..0e94c079e
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/util/HealthCheckTest.java
@@ -0,0 +1,227 @@
+package org.wordpress.android.util;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.test.InstrumentationTestCase;
+
+import com.squareup.okhttp.Headers;
+import com.squareup.okhttp.mockwebserver.Dispatcher;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import com.squareup.okhttp.mockwebserver.RecordedRequest;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.wordpress.android.TestUtils;
+import org.wordpress.android.WordPress;
+import org.xmlrpc.android.LoggedInputStream;
+import org.xmlrpc.android.XMLRPCUtils;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+public class HealthCheckTest extends InstrumentationTestCase {
+ private static final String sAssetPathBase = "health-check/";
+ private static final String sServerAddressMagicString = "mockserver";
+ private static final String sServerResponsesMagicScheme = "asset:";
+
+ private void setLocale(String language, String country) {
+ Locale locale = new Locale(language, country);
+ Locale.setDefault(locale);
+ Resources res = getInstrumentation().getTargetContext().getResources();
+ Configuration config = res.getConfiguration();
+ config.locale = locale;
+ res.updateConfiguration(config, res.getDisplayMetrics());
+ }
+
+ @Override
+ protected void setUp() {
+ WordPress.setupVolleyQueue();
+
+ // set the app locale to english since the tests only support English for now
+ setLocale("en", "US");
+ }
+
+ @Override
+ protected void tearDown() {
+ }
+
+ private static String stringFromAsset(Context context, String assetFilename) throws IOException {
+ LoggedInputStream mLoggedInputStream = new LoggedInputStream(context.getAssets().open(assetFilename));
+ return TestUtils.convertStreamToString(mLoggedInputStream);
+ }
+
+ private static JSONObject jsonFromAsset(Context context, String assetFilename) throws IOException, JSONException {
+ return new JSONObject(stringFromAsset(context, assetFilename));
+ }
+
+ public void testHealthCheckXplat() throws JSONException, IOException {
+ JSONArray testCases = jsonFromAsset(getInstrumentation().getContext(), sAssetPathBase +
+ "health-check-xplat-testcases.json").getJSONArray("testcases");
+
+ for (int i = 0; i < testCases.length(); i++) {
+ final JSONObject testCase = testCases.getJSONObject(i);
+ final String testCaseComment = testCase.getString("comment");
+
+ final JSONObject testSetup = testCase.getJSONObject("setup");
+ final String realm = testCase.getString("realm");
+
+ switch (realm) {
+ case "URL_CANONICALIZATION":
+ runUrlCanonicalization(testCaseComment, testSetup);
+ break;
+ case "XMLPRC_DISCOVERY":
+ runXmlrpcDiscovery(testCaseComment, testSetup);
+ break;
+ default:
+ // fail the testsuite
+ assertTrue("health-check realm " + realm + " is not supported!", false);
+ break;
+ }
+ }
+ }
+
+ private void runUrlCanonicalization(String testCaseComment, JSONObject testSetup) throws JSONException {
+ final JSONObject input = testSetup.getJSONObject("input");
+
+ final String inputUrl = input.isNull("siteUrl") ? null : input.getString("siteUrl");
+
+ final JSONObject output = testSetup.getJSONObject("output");
+
+ final String outputUrl = output.optString("siteUrl", null);
+ final JSONObject error = output.optJSONObject("error");
+
+ String canonicalizedUrl = null;
+ try {
+ canonicalizedUrl = XMLRPCUtils.sanitizeSiteUrl(inputUrl, true);
+
+ // if we reached this point, it means that no error occurred
+ assertNull(testCaseMessage("Testcase defines an error but no error occurred!", testCaseComment), error);
+ } catch (XMLRPCUtils.XMLRPCUtilsException hce) {
+ assertNotNull(testCaseMessage("Error occurred but testcase does not define an error!", testCaseComment),
+ error);
+
+ assertEquals(testCaseMessage("Error message does not match the defined one!", testCaseComment), error
+ .getString("message"), getInstrumentation().getTargetContext().getString(hce.errorMsgId));
+ }
+
+ assertEquals(testCaseMessage("Canonicalized URL does not match the defined one!", testCaseComment),
+ outputUrl, canonicalizedUrl);
+ }
+
+ private void runXmlrpcDiscovery(String testCaseComment, JSONObject testSetup) throws JSONException, IOException {
+ final MockWebServer server = new MockWebServer();
+
+ testSetup = new JSONObject(replaceServerMagicName(server, testSetup.toString()));
+
+ final JSONObject input = testSetup.getJSONObject("input");
+
+ setupMockHttpServer(server, input);
+
+ final String inputUrl = input.isNull("siteUrl") ? server.url("").toString() : input.getString("siteUrl");
+
+ final JSONObject output = testSetup.getJSONObject("output");
+
+ final String outputUrl = output.optString("xmlrpcEndpoint", null);
+ final JSONObject error = output.optJSONObject("error");
+
+ String xmlrpcUrl = null;
+ try {
+ xmlrpcUrl = XMLRPCUtils.verifyOrDiscoverXmlRpcUrl(inputUrl, input.optString("username", null), input
+ .optString("username", null));
+
+ // if we reached this point, it means that no error occurred
+ assertNull(testCaseMessage("Testcase defines an error but no error occurred!", testCaseComment), error);
+ } catch (XMLRPCUtils.XMLRPCUtilsException hce) {
+ assertNotNull(testCaseMessage("Error occurred but testcase does not define an error!", testCaseComment),
+ error);
+
+ assertEquals(testCaseMessage("Error message does not match the defined one!", testCaseComment), error
+ .getString("message"), getInstrumentation().getTargetContext().getString(hce.errorMsgId));
+ }
+
+ assertEquals(testCaseMessage("XMLRPC URL does not match the defined one!", testCaseComment), outputUrl,
+ xmlrpcUrl);
+
+ server.shutdown();
+ }
+
+ private MockWebServer setupMockHttpServer(MockWebServer server, JSONObject requestResponsesJson) throws
+ JSONException, IOException {
+ final Map<RecordedRequest, MockResponse> mockRequestResponses = new HashMap<>();
+
+ final JSONArray serverMock = requestResponsesJson.getJSONArray("serverMock");
+ for (int i = 0; i < serverMock.length(); i++) {
+ final JSONObject reqRespJson = serverMock.getJSONObject(i);
+
+ final JSONObject reqJson = reqRespJson.getJSONObject("request");
+ Headers reqHeaders = json2Headers(reqJson.optJSONObject("headers"));
+
+ RecordedRequest recordedRequest = new RecordedRequest(reqJson.getString("method") + " " + reqJson
+ .getString("path") + " HTTP/1.1", reqHeaders, null, 0, null, 0, null);
+
+ final JSONObject respJson = reqRespJson.getJSONObject("response");
+ Headers respHeaders = json2Headers(respJson.optJSONObject("headers"));
+
+ String body = respJson.optString("body");
+ if (body.startsWith(sServerResponsesMagicScheme)) {
+ body = stringFromAsset(getInstrumentation().getContext(), sAssetPathBase + body.substring
+ (sServerResponsesMagicScheme.length()));
+ }
+
+ body = replaceServerMagicName(server, body);
+
+ final MockResponse resp = new MockResponse()
+ .setResponseCode(respJson.getInt("statusCode"))
+ .setHeaders(respHeaders)
+ .setBody(body);
+
+ mockRequestResponses.put(recordedRequest, resp);
+ }
+
+ server.setDispatcher(new Dispatcher() {
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+
+ for (Map.Entry<RecordedRequest, MockResponse> reqResp : mockRequestResponses.entrySet()) {
+ final RecordedRequest mockRequest = reqResp.getKey();
+ if (mockRequest.getRequestLine().equals(request.getRequestLine())) {
+ return reqResp.getValue();
+ }
+ }
+ return new MockResponse().setResponseCode(404).setBody("");
+ }
+ });
+
+ return server;
+ }
+
+ private String replaceServerMagicName(MockWebServer server, String str) {
+ return str.replaceAll(sServerAddressMagicString, server.getHostName() + ":" + server.getPort());
+
+ }
+
+ private Headers json2Headers(JSONObject headersJson) throws JSONException {
+ if (headersJson != null) {
+ Headers.Builder headBuilder = new Headers.Builder();
+ Iterator<String> headerKeys = headersJson.keys();
+ while (headerKeys.hasNext()) {
+ final String headerName = headerKeys.next();
+ headBuilder.add(headerName, headersJson.getString(headerName));
+ }
+
+ return headBuilder.build();
+ }
+
+ return new Headers.Builder().build();
+ }
+
+ private String testCaseMessage(String message, String testCaseComment) {
+ return message + " (on testCase: '" + testCaseComment + "')";
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java b/WordPress/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java
new file mode 100644
index 000000000..25398b9d4
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java
@@ -0,0 +1,25 @@
+package org.wordpress.android.util;
+
+import android.test.InstrumentationTestCase;
+
+public class UrlUtilsTest extends InstrumentationTestCase {
+ public void testGetHost1() {
+ assertEquals("a.com", UrlUtils.getHost("http://a.com/test"));
+ }
+
+ public void testGetHost2() {
+ assertEquals("a.com", UrlUtils.getHost("http://a.com#.b.com/test"));
+ }
+
+ public void testGetHost3() {
+ assertEquals("a.com", UrlUtils.getHost("https://a.com"));
+ }
+
+ public void testGetHost4() {
+ assertEquals("a.com", UrlUtils.getHost("https://a.com/test#test"));
+ }
+
+ public void testGetHost5() {
+ assertEquals("", UrlUtils.getHost("a.com"));
+ }
+}
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/util/WPHtmlTest.java b/WordPress/src/androidTest/java/org/wordpress/android/util/WPHtmlTest.java
new file mode 100644
index 000000000..b9ddce162
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/util/WPHtmlTest.java
@@ -0,0 +1,38 @@
+package org.wordpress.android.util;
+
+import android.test.InstrumentationTestCase;
+import android.text.SpannableStringBuilder;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class WPHtmlTest extends InstrumentationTestCase {
+ @Override
+ protected void setUp() {
+ }
+
+ @Override
+ protected void tearDown() {
+ }
+
+ // This test failed before #685 was fixed (throws a InvocationTargetException)
+ public void testStartImg() throws NoSuchMethodException, IllegalAccessException {
+ SpannableStringBuilder text = new SpannableStringBuilder();
+ Attributes attributes = new AttributesImpl();
+
+ HtmlToSpannedConverter converter = new HtmlToSpannedConverter(null, null, null, null, null, null, 0);
+
+ // startImg is private, we use reflection to change accessibility and invoke it from here
+ Method method = HtmlToSpannedConverter.class.getDeclaredMethod("startImg", SpannableStringBuilder.class,
+ Attributes.class, WPHtml.ImageGetter.class);
+ method.setAccessible(true);
+ try {
+ method.invoke(converter, text, attributes, null);
+ } catch (InvocationTargetException e) {
+ assertTrue("startImg failed see #685", false);
+ }
+ }
+} \ No newline at end of file
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/util/WPUrlUtilsTest.java b/WordPress/src/androidTest/java/org/wordpress/android/util/WPUrlUtilsTest.java
new file mode 100644
index 000000000..a250198e3
--- /dev/null
+++ b/WordPress/src/androidTest/java/org/wordpress/android/util/WPUrlUtilsTest.java
@@ -0,0 +1,272 @@
+package org.wordpress.android.util;
+
+import android.test.InstrumentationTestCase;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class WPUrlUtilsTest extends InstrumentationTestCase {
+
+ private static final String wpcomAddress1 = "http://wordpress.com/xmlrpc.php";
+ private static final String wpcomAddress2 = "http://wordpress.com#.b.com/test";
+ private static final String wpcomAddress3 = "http://wordpress.com/xmlrpc.php";
+ private static final String wpcomAddress4 = "https://wordpress.com";
+ private static final String wpcomAddress5 = "https://wordpress.com/test#test";
+ private static final String wpcomAddress6 = "https://developer.wordpress.com";
+ private static final String notWpcomAddress1 = "http://i2.wp.com.eritreo.it#.files.wordpress.com/testpicture.gif?strip=all&quality=100&resize=1024,768";
+ private static final String notWpcomAddress2 = "wordpress.com";
+ private static final String notWpcomAddress3 = "https://thisisnotwordpress.com";
+
+
+ public void testSafeToAddAuthToken1() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(wpcomAddress1));
+ }
+
+ public void testSafeToAddAuthToken2() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(wpcomAddress2));
+ }
+
+ public void testSafeToAddAuthToken3() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(wpcomAddress3));
+ }
+
+ public void testSafeToAddAuthToken4() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(wpcomAddress4));
+ }
+ public void testSafeToAddAuthToken5() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(wpcomAddress5));
+ }
+
+ public void testSafeToAddAuthToken6() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(notWpcomAddress1));
+ }
+
+ public void testSafeToAddAuthToken7() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(notWpcomAddress2));
+ }
+
+ public void testSafeToAddAuthToken8() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(wpcomAddress1)));
+ }
+
+ public void testSafeToAddAuthToken9() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(wpcomAddress2)));
+ }
+
+ public void testSafeToAddAuthToken10() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(wpcomAddress3)));
+ }
+
+ public void testSafeToAddAuthToken11() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(wpcomAddress4)));
+ }
+ public void testSafeToAddAuthToken12() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(wpcomAddress5)));
+ }
+
+ public void testSafeToAddAuthToken13() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(notWpcomAddress1)));
+ }
+
+ public void testSafeToAddAuthToken14() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(notWpcomAddress2)));
+ }
+
+ public void testSafeToAddAuthToken15() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(wpcomAddress1)));
+ }
+
+ public void testSafeToAddAuthToken16() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(wpcomAddress2)));
+ }
+
+ public void testSafeToAddAuthToken17() {
+ // Not HTTPS
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(wpcomAddress3)));
+ }
+
+ public void testSafeToAddAuthToken18() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(wpcomAddress4)));
+ }
+ public void testSafeToAddAuthToken19() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(wpcomAddress5)));
+ }
+
+ public void testSafeToAddAuthToken20() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(notWpcomAddress1)));
+ }
+
+ public void testSafeToAddAuthToken21() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(notWpcomAddress2)));
+ }
+
+ public void testSafeToAddAuthToken22() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(notWpcomAddress3));
+ }
+
+ public void testSafeToAddAuthToken23() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(notWpcomAddress3)));
+ }
+
+ public void testSafeToAddAuthToken24() {
+ // Not wpcom
+ assertFalse(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(notWpcomAddress3)));
+ }
+
+ public void testSafeToAddAuthToken25() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(wpcomAddress6));
+ }
+
+ public void testSafeToAddAuthToken26() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(buildURL(wpcomAddress6)));
+ }
+
+ public void testSafeToAddAuthToken27() {
+ assertTrue(WPUrlUtils.safeToAddWordPressComAuthToken(buildURI(wpcomAddress6)));
+ }
+
+
+ public void testIsWPCOMString1() {
+ assertTrue(WPUrlUtils.isWordPressCom(wpcomAddress1));
+ }
+
+ public void testIsWPCOMString2() {
+ assertTrue(WPUrlUtils.isWordPressCom(wpcomAddress2));
+ }
+
+ public void testIsWPCOMString3() {
+ assertTrue(WPUrlUtils.isWordPressCom(wpcomAddress3));
+ }
+
+ public void testIsWPCOMString4() {
+ assertTrue(WPUrlUtils.isWordPressCom(wpcomAddress4));
+ }
+
+ public void testIsWPCOMString5() {
+ assertTrue(WPUrlUtils.isWordPressCom(wpcomAddress5));
+ }
+
+ public void testIsWPCOMString6() {
+ assertTrue(WPUrlUtils.isWordPressCom(wpcomAddress6));
+ }
+
+ private URL buildURL(String address) {
+ URL url = null;
+ try {
+ url = new URL(address);
+ } catch (MalformedURLException e) {}
+ return url;
+ }
+
+ public void testIsWPCOMURL1() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURL(wpcomAddress1)));
+ }
+
+ public void testIsWPCOMURL2() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURL(wpcomAddress2)));
+ }
+
+ public void testIsWPCOMURL3() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURL(wpcomAddress3)));
+ }
+
+ public void testIsWPCOMURL4() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURL(wpcomAddress4)));
+ }
+
+ public void testIsWPCOMURL5() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURL(wpcomAddress5)));
+ }
+
+ public void testIsWPCOMURL6() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURL(wpcomAddress6)));
+ }
+
+
+ private URI buildURI(String address) {
+ URI uri = null;
+ try {
+ uri = new URI(address);
+ } catch (URISyntaxException e) {}
+ return uri;
+ }
+
+ public void testIsWPCOMURI1() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURI(wpcomAddress1)));
+ }
+
+ public void testIsWPCOMURI2() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURI(wpcomAddress2)));
+ }
+
+ public void testIsWPCOMURI3() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURI(wpcomAddress3)));
+ }
+
+ public void testIsWPCOMURI4() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURI(wpcomAddress4)));
+ }
+
+ public void testIsWPCOMURI5() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURI(wpcomAddress5)));
+ }
+
+ public void testIsWPCOMURI6() {
+ assertTrue(WPUrlUtils.isWordPressCom(buildURI(wpcomAddress6)));
+ }
+
+ public void testIsNOTWPCOM1() {
+ assertFalse(WPUrlUtils.isWordPressCom(notWpcomAddress1));
+ }
+
+ public void testIsNOTWPCOM2() {
+ assertFalse(WPUrlUtils.isWordPressCom(notWpcomAddress2));
+ }
+
+ public void testIsNOTWPCOM3() {
+ assertFalse(WPUrlUtils.isWordPressCom(buildURL(notWpcomAddress1)));
+ }
+
+ public void testIsNOTWPCOM4() {
+ assertFalse(WPUrlUtils.isWordPressCom(buildURL(notWpcomAddress2)));
+ }
+
+ public void testIsNOTWPCOM5() {
+ assertFalse(WPUrlUtils.isWordPressCom(buildURI(notWpcomAddress1)));
+ }
+
+ public void testIsNOTWPCOM6() {
+ assertFalse(WPUrlUtils.isWordPressCom(buildURI(notWpcomAddress2)));
+ }
+
+ public void testIsNOTWPCOM7() {
+ assertFalse(WPUrlUtils.isWordPressCom(notWpcomAddress3));
+ }
+
+ public void testIsNOTWPCOM8() {
+ assertFalse(WPUrlUtils.isWordPressCom(buildURL(notWpcomAddress3)));
+ }
+
+ public void testIsNOTWPCOM9() {
+ assertFalse(WPUrlUtils.isWordPressCom(buildURI(notWpcomAddress3)));
+ }
+
+} \ No newline at end of file