From 268ba07648b996552a93b29f8df1578f44139c12 Mon Sep 17 00:00:00 2001 From: Adam Jones Date: Thu, 21 Mar 2019 04:56:36 +0000 Subject: [PATCH] Convert instrumentation tests to Kotlin (#2689) * Convert SettingsActivityTest to Kotlin * Convert NavigationBaseActivityTest to Kotlin * Convert UploadTest to Kotlin --- .../commons/NavigationBaseActivityTest.java | 67 ------ .../nrw/commons/NavigationBaseActivityTest.kt | 65 ++++++ ...ivityTest.java => SettingsActivityTest.kt} | 123 +++++----- .../java/fr/free/nrw/commons/UploadTest.java | 211 ------------------ .../java/fr/free/nrw/commons/UploadTest.kt | 194 ++++++++++++++++ 5 files changed, 317 insertions(+), 343 deletions(-) delete mode 100644 app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.java create mode 100644 app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.kt rename app/src/androidTest/java/fr/free/nrw/commons/{SettingsActivityTest.java => SettingsActivityTest.kt} (53%) delete mode 100644 app/src/androidTest/java/fr/free/nrw/commons/UploadTest.java create mode 100644 app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt diff --git a/app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.java b/app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.java deleted file mode 100644 index cef134b69..000000000 --- a/app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import androidx.test.espresso.contrib.DrawerActions; -import androidx.test.espresso.contrib.NavigationViewActions; -import androidx.test.filters.LargeTest; -import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -@LargeTest -@RunWith(AndroidJUnit4.class) -public class NavigationBaseActivityTest { - @Rule - public ActivityTestRule activityRule = new ActivityTestRule<>(AboutActivity.class); - - /** - * Goes through all the activities in the app and checks we don't crash - * NB: This is not realistic if we're not logged in; we can access 'home', 'notifications', 'settings' and 'achievements' which we wouldn't otherwise be able to. - */ - @Test - public void goThroughNavigationBaseActivityActivities() { - // Home - openNavigationDrawerAndNavigateTo(R.id.action_home); - - // Explore - openNavigationDrawerAndNavigateTo(R.id.action_explore); - - // Bookmarks - openNavigationDrawerAndNavigateTo(R.id.action_bookmarks); - - // About - openNavigationDrawerAndNavigateTo(R.id.action_about); - - // Settings - openNavigationDrawerAndNavigateTo(R.id.action_settings); - - // Achievements - openNavigationDrawerAndNavigateTo(R.id.action_login); - } - - /** - * Clicks 'Explore' in the navigation drawer twice, then clicks 'home' - * Testing to avoid regression of #2200 - */ - @Test - public void doubleNavigateToExploreThenReturnHome() { - // Explore - openNavigationDrawerAndNavigateTo(R.id.action_explore); - - // Explore - openNavigationDrawerAndNavigateTo(R.id.action_explore); - - // Home - openNavigationDrawerAndNavigateTo(R.id.action_home); - } - - public void openNavigationDrawerAndNavigateTo(int menuItemId) { - onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); - onView(withId(R.id.navigation_view)).perform(NavigationViewActions.navigateTo(menuItemId)); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.kt new file mode 100644 index 000000000..2054ed9f3 --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/NavigationBaseActivityTest.kt @@ -0,0 +1,65 @@ +package fr.free.nrw.commons + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.contrib.DrawerActions +import androidx.test.espresso.contrib.NavigationViewActions +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.filters.LargeTest +import androidx.test.rule.ActivityTestRule +import androidx.test.runner.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@LargeTest +@RunWith(AndroidJUnit4::class) +class NavigationBaseActivityTest { + @get:Rule + var activityRule: ActivityTestRule<*> = ActivityTestRule(AboutActivity::class.java) + + /** + * Goes through all the activities in the app and checks we don't crash + * NB: This is not realistic if we're not logged in; we can access 'home', 'notifications', 'settings' and 'achievements' which we wouldn't otherwise be able to. + */ + @Test + fun goThroughNavigationBaseActivityActivities() { + // Home + openNavigationDrawerAndNavigateTo(R.id.action_home) + + // Explore + openNavigationDrawerAndNavigateTo(R.id.action_explore) + + // Bookmarks + openNavigationDrawerAndNavigateTo(R.id.action_bookmarks) + + // About + openNavigationDrawerAndNavigateTo(R.id.action_about) + + // Settings + openNavigationDrawerAndNavigateTo(R.id.action_settings) + + // Achievements + openNavigationDrawerAndNavigateTo(R.id.action_login) + } + + /** + * Clicks 'Explore' in the navigation drawer twice, then clicks 'home' + * Testing to avoid regression of #2200 + */ + @Test + fun doubleNavigateToExploreThenReturnHome() { + // Explore + openNavigationDrawerAndNavigateTo(R.id.action_explore) + + // Explore + openNavigationDrawerAndNavigateTo(R.id.action_explore) + + // Home + openNavigationDrawerAndNavigateTo(R.id.action_home) + } + + private fun openNavigationDrawerAndNavigateTo(menuItemId: Int) { + onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()) + onView(withId(R.id.navigation_view)).perform(NavigationViewActions.navigateTo(menuItemId)) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt similarity index 53% rename from app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java rename to app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt index 299c42c97..5400d972e 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java +++ b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt @@ -1,160 +1,153 @@ -package fr.free.nrw.commons; +package fr.free.nrw.commons -import android.content.Context; - -import com.google.gson.Gson; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import androidx.test.InstrumentationRegistry; -import androidx.test.espresso.Espresso; -import androidx.test.espresso.matcher.PreferenceMatchers; -import androidx.test.filters.LargeTest; -import androidx.test.rule.ActivityTestRule; -import androidx.test.runner.AndroidJUnit4; -import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.settings.Prefs; -import fr.free.nrw.commons.settings.SettingsActivity; - -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.replaceText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertEquals; +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.PreferenceMatchers +import androidx.test.espresso.matcher.ViewMatchers.* +import androidx.test.filters.LargeTest +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ActivityTestRule +import androidx.test.runner.AndroidJUnit4 +import com.google.gson.Gson +import fr.free.nrw.commons.kvstore.JsonKvStore +import fr.free.nrw.commons.settings.Prefs +import fr.free.nrw.commons.settings.SettingsActivity +import org.hamcrest.Matchers.allOf +import org.hamcrest.core.IsNot.not +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith @LargeTest -@RunWith(AndroidJUnit4.class) -public class SettingsActivityTest { - JsonKvStore defaultKvStore; +@RunWith(AndroidJUnit4::class) +class SettingsActivityTest { + private lateinit var defaultKvStore: JsonKvStore - @Rule - public ActivityTestRule activityRule = new ActivityTestRule<>(SettingsActivity.class); + @get:Rule + var activityRule: ActivityTestRule<*> = ActivityTestRule(SettingsActivity::class.java) @Before - public void setup() { - Context context = InstrumentationRegistry.getTargetContext(); - String storeName = context.getPackageName() + "_preferences"; - defaultKvStore = new JsonKvStore(context, storeName, new Gson()); + fun setup() { + val context = InstrumentationRegistry.getInstrumentation().targetContext + val storeName = context.packageName + "_preferences" + defaultKvStore = JsonKvStore(context, storeName, Gson()) } @Test - public void setRecentUploadLimitTo123() { + fun setRecentUploadLimitTo123() { // Open "Use external storage" preference Espresso.onData(PreferenceMatchers.withKey("uploads")) .inAdapterView(withId(android.R.id.list)) - .perform(click()); + .perform(click()) // Try setting it to 123 Espresso.onView(withId(android.R.id.edit)) - .perform(replaceText("123")); + .perform(replaceText("123")) // Click "OK" Espresso.onView(allOf(withId(android.R.id.button1), withText("OK"))) - .perform(click()); + .perform(click()) // Check setting set to 123 in SharedPreferences assertEquals( 123, - defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0) - ); + defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0).toLong() + ) // Check displaying 123 in summary text Espresso.onData(PreferenceMatchers.withKey("uploads")) .inAdapterView(withId(android.R.id.list)) .onChildView(withId(android.R.id.summary)) - .check(matches(withText("123"))); + .check(matches(withText("123"))) } @Test - public void setRecentUploadLimitTo0() { + fun setRecentUploadLimitTo0() { // Open "Use external storage" preference Espresso.onData(PreferenceMatchers.withKey("uploads")) .inAdapterView(withId(android.R.id.list)) - .perform(click()); + .perform(click()) // Try setting it to 0 Espresso.onView(withId(android.R.id.edit)) - .perform(replaceText("0")); + .perform(replaceText("0")) // Click "OK" Espresso.onView(allOf(withId(android.R.id.button1), withText("OK"))) - .perform(click()); + .perform(click()) // Check setting set to 100 in SharedPreferences assertEquals( 100, - defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0) - ); + defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0).toLong() + ) // Check displaying 100 in summary text Espresso.onData(PreferenceMatchers.withKey("uploads")) .inAdapterView(withId(android.R.id.list)) .onChildView(withId(android.R.id.summary)) - .check(matches(withText("100"))); + .check(matches(withText("100"))) } @Test - public void setRecentUploadLimitTo700() { + fun setRecentUploadLimitTo700() { // Open "Use external storage" preference Espresso.onData(PreferenceMatchers.withKey("uploads")) .inAdapterView(withId(android.R.id.list)) - .perform(click()); + .perform(click()) // Try setting it to 700 Espresso.onView(withId(android.R.id.edit)) - .perform(replaceText("700")); + .perform(replaceText("700")) // Click "OK" Espresso.onView(allOf(withId(android.R.id.button1), withText("OK"))) - .perform(click()); + .perform(click()) // Check setting set to 500 in SharedPreferences assertEquals( 500, - defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0) - ); + defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0).toLong() + ) // Check displaying 100 in summary text Espresso.onData(PreferenceMatchers.withKey("uploads")) .inAdapterView(withId(android.R.id.list)) .onChildView(withId(android.R.id.summary)) - .check(matches(withText("500"))); + .check(matches(withText("500"))) } @Test - public void useAuthorNameTogglesOn() { + fun useAuthorNameTogglesOn() { // Turn on "Use external storage" preference if currently off if (!defaultKvStore.getBoolean("useAuthorName", true)) { Espresso.onData(PreferenceMatchers.withKey("useAuthorName")) .inAdapterView(withId(android.R.id.list)) - .perform(click()); + .perform(click()) } // Check authorName preference is enabled Espresso.onData(PreferenceMatchers.withKey("authorName")) .inAdapterView(withId(android.R.id.list)) - .check(matches(isEnabled())); + .check(matches(isEnabled())) } @Test - public void useAuthorNameTogglesOff() { + fun useAuthorNameTogglesOff() { // Turn off "Use external storage" preference if currently on if (defaultKvStore.getBoolean("useAuthorName", false)) { Espresso.onData(PreferenceMatchers.withKey("useAuthorName")) .inAdapterView(withId(android.R.id.list)) - .perform(click()); + .perform(click()) } // Check authorName preference is enabled Espresso.onData(PreferenceMatchers.withKey("authorName")) .inAdapterView(withId(android.R.id.list)) - .check(matches(not(isEnabled()))); + .check(matches(not(isEnabled()))) } } diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.java b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.java deleted file mode 100644 index 9b29931a3..000000000 --- a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.java +++ /dev/null @@ -1,211 +0,0 @@ -package fr.free.nrw.commons; - -import android.Manifest; -import android.app.Activity; -import android.app.Instrumentation.ActivityResult; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Environment; -import android.view.autofill.AutofillManager; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Random; - -import androidx.test.espresso.NoMatchingViewException; -import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.filters.LargeTest; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; -import androidx.test.rule.GrantPermissionRule; -import androidx.test.runner.AndroidJUnit4; -import fr.free.nrw.commons.auth.LoginActivity; -import fr.free.nrw.commons.utils.ConfigUtils; -import timber.log.Timber; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.clearText; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.replaceText; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intended; -import static androidx.test.espresso.intent.Intents.intending; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasType; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withParent; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.core.AllOf.allOf; - -@LargeTest -@RunWith(AndroidJUnit4.class) -public class UploadTest { - @Rule - public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE, - Manifest.permission.ACCESS_FINE_LOCATION); - - @Rule - public ActivityTestRule activityRule = new IntentsTestRule<>(LoginActivity.class); - - @Before - public void setup() { - - saveToInternalStorage(); - } - - private void saveToInternalStorage() { - Bitmap bitmapImage = getRandomBitmap(); - Context applicationContext = InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext(); - ContextWrapper cw = new ContextWrapper(applicationContext); - // path to /data/data/yourapp/app_data/imageDir - File mypath = new File(Environment.getExternalStorageDirectory(), "image.jpg"); - - Timber.d("Filepath: %s", mypath.getPath()); - - Timber.d("Absolute Filepath: %s", mypath.getAbsolutePath()); - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(mypath); - // Use the compress method on the BitMap object to write image to the OutputStream - bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, fos); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (fos != null) { - fos.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - private Bitmap getRandomBitmap() { - Random random = new Random(); - Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); - bitmap.eraseColor(random.nextInt(255)); - return bitmap; - } - - private void getToMainActivity() { - try { - //Skip tutorial - onView(withId(R.id.finishTutorialButton)) - .perform(click()); - - //Perform Login - onView(withId(R.id.loginUsername)) - .perform(clearText(), typeText(BuildConfig.TEST_USERNAME)); - onView(withId(R.id.loginPassword)) - .perform(clearText(), typeText(BuildConfig.TEST_PASSWORD)); - onView(withId(R.id.loginButton)) - .perform(click()); - } catch (NoMatchingViewException ignored) { - } - } - - @Test - public void uploadTest() { - if (!ConfigUtils.isBetaFlavour()) { - throw new Error("This test should only be run in Beta!"); - } - - getToMainActivity(); - - // Uri to return by our mock gallery selector - // Requires file 'image.jpg' to be placed at root of file structure - Uri imageUri = Uri.parse("file://mnt/sdcard/image.jpg"); - - // Build a result to return from the Camera app - Intent intent = new Intent(); - intent.setData(imageUri); - ActivityResult result = new ActivityResult(Activity.RESULT_OK, intent); - - // Stub out the File picker. When an intent is sent to the File picker, this tells - // Espresso to respond with the ActivityResult we just created - intending(allOf(hasAction(Intent.ACTION_GET_CONTENT), hasType("image/*"))).respondWith(result); - - // Open FAB - onView(allOf(withId(R.id.fab_plus), isDisplayed())) - .perform(click()); - - // Click gallery - onView(allOf(withId(R.id.fab_gallery), isDisplayed())) - .perform(click()); - - // Validate that an intent to get an image is sent - intended(allOf(hasAction(Intent.ACTION_GET_CONTENT), hasType("image/*"))); - - // Create filename with the current time (to prevent overwrites) - SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd-hhmmss"); - String commonsFileName = "MobileTest " + dateFormat.format(new Date()); - - // Try to dismiss the error, if there is one (probably about duplicate files on Commons) - try { - onView(withText("Yes")) - .check(matches(isDisplayed())) - .perform(click()); - } catch (NoMatchingViewException ignored) {} - - onView(allOf(withId(R.id.description_item_edit_text), withParent(withParent(withId(R.id.image_title_container))))) - .perform(replaceText(commonsFileName)); - - onView(withId(R.id.bottom_card_next)) - .perform(click()); - - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - onView(withId(R.id.category_search)) - .perform(replaceText("Uploaded with Mobile/Android Tests")); - - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - onView(withParent(withId(R.id.categories))) - .perform(click()); - - onView(withId(R.id.category_next)) - .perform(click()); - - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - onView(withId(R.id.submit)) - .perform(click()); - - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - String fileUrl = "https://commons.wikimedia.beta.wmflabs.org/wiki/File:" + - commonsFileName.replace(' ', '_') + ".jpg"; - Timber.i("File should be uploaded to " + fileUrl); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt new file mode 100644 index 000000000..1de33c077 --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt @@ -0,0 +1,194 @@ +package fr.free.nrw.commons + +import android.Manifest +import android.app.Activity +import android.app.Instrumentation.ActivityResult +import android.content.Intent +import android.graphics.Bitmap +import android.net.Uri +import android.os.Environment +import android.view.View +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.NoMatchingViewException +import androidx.test.espresso.action.ViewActions.* +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.intent.Intents.intended +import androidx.test.espresso.intent.Intents.intending +import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction +import androidx.test.espresso.intent.matcher.IntentMatchers.hasType +import androidx.test.espresso.intent.rule.IntentsTestRule +import androidx.test.espresso.matcher.ViewMatchers.* +import androidx.test.filters.LargeTest +import androidx.test.rule.ActivityTestRule +import androidx.test.rule.GrantPermissionRule +import androidx.test.runner.AndroidJUnit4 +import fr.free.nrw.commons.auth.LoginActivity +import fr.free.nrw.commons.utils.ConfigUtils +import org.hamcrest.core.AllOf.allOf +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import timber.log.Timber +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.text.SimpleDateFormat +import java.util.* + +@LargeTest +@RunWith(AndroidJUnit4::class) +class UploadTest { + @get:Rule + var permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.ACCESS_FINE_LOCATION) + + @get:Rule + var activityRule: ActivityTestRule<*> = IntentsTestRule(LoginActivity::class.java) + + private val randomBitmap: Bitmap + get() { + val random = Random() + val bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888) + bitmap.eraseColor(random.nextInt(255)) + return bitmap + } + + @Before + fun setup() { + saveToInternalStorage() + } + + private fun saveToInternalStorage() { + val bitmapImage = randomBitmap + + // path to /data/data/yourapp/app_data/imageDir + val mypath = File(Environment.getExternalStorageDirectory(), "image.jpg") + + Timber.d("Filepath: %s", mypath.path) + + Timber.d("Absolute Filepath: %s", mypath.absolutePath) + + var fos: FileOutputStream? = null + try { + fos = FileOutputStream(mypath) + // Use the compress method on the BitMap object to write image to the OutputStream + bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, fos) + } catch (e: Exception) { + e.printStackTrace() + } finally { + try { + fos?.close() + } catch (e: IOException) { + e.printStackTrace() + } + + } + } + + private fun getToMainActivity() { + try { + //Skip tutorial + onView(withId(R.id.finishTutorialButton)) + .perform(click()) + + //Perform Login + onView(withId(R.id.loginUsername)) + .perform(clearText(), typeText(BuildConfig.TEST_USERNAME)) + onView(withId(R.id.loginPassword)) + .perform(clearText(), typeText(BuildConfig.TEST_PASSWORD)) + onView(withId(R.id.loginButton)) + .perform(click()) + } catch (ignored: NoMatchingViewException) {} + } + + @Test + fun uploadTest() { + if (!ConfigUtils.isBetaFlavour()) { + throw Error("This test should only be run in Beta!") + } + + getToMainActivity() + + // Uri to return by our mock gallery selector + // Requires file 'image.jpg' to be placed at root of file structure + val imageUri = Uri.parse("file://mnt/sdcard/image.jpg") + + // Build a result to return from the Camera app + val intent = Intent() + intent.data = imageUri + val result = ActivityResult(Activity.RESULT_OK, intent) + + // Stub out the File picker. When an intent is sent to the File picker, this tells + // Espresso to respond with the ActivityResult we just created + intending(allOf(hasAction(Intent.ACTION_GET_CONTENT), hasType("image/*"))).respondWith(result) + + // Open FAB + onView(allOf(withId(R.id.fab_plus), isDisplayed())) + .perform(click()) + + // Click gallery + onView(allOf(withId(R.id.fab_gallery), isDisplayed())) + .perform(click()) + + // Validate that an intent to get an image is sent + intended(allOf(hasAction(Intent.ACTION_GET_CONTENT), hasType("image/*"))) + + // Create filename with the current time (to prevent overwrites) + val dateFormat = SimpleDateFormat("yyMMdd-hhmmss") + val commonsFileName = "MobileTest " + dateFormat.format(Date()) + + // Try to dismiss the error, if there is one (probably about duplicate files on Commons) + try { + onView(withText("Yes")) + .check(matches(isDisplayed())) + .perform(click()) + } catch (ignored: NoMatchingViewException) {} + + onView(allOf(withId(R.id.description_item_edit_text), withParent(withParent(withId(R.id.image_title_container))))) + .perform(replaceText(commonsFileName)) + + onView(withId(R.id.bottom_card_next)) + .perform(click()) + + try { + Thread.sleep(500) + } catch (e: InterruptedException) { + e.printStackTrace() + } + + onView(withId(R.id.category_search)) + .perform(replaceText("Uploaded with Mobile/Android Tests")) + + try { + Thread.sleep(3000) + } catch (e: InterruptedException) { + e.printStackTrace() + } + + onView(withParent(withId(R.id.categories))) + .perform(click()) + + onView(withId(R.id.category_next)) + .perform(click()) + + try { + Thread.sleep(500) + } catch (e: InterruptedException) { + e.printStackTrace() + } + + onView(withId(R.id.submit)) + .perform(click()) + + try { + Thread.sleep(10000) + } catch (e: InterruptedException) { + e.printStackTrace() + } + + val fileUrl = "https://commons.wikimedia.beta.wmflabs.org/wiki/File:" + + commonsFileName.replace(' ', '_') + ".jpg" + Timber.i("File should be uploaded to $fileUrl") + } +} \ No newline at end of file