mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Convert instrumentation tests to Kotlin (#2689)
* Convert SettingsActivityTest to Kotlin * Convert NavigationBaseActivityTest to Kotlin * Convert UploadTest to Kotlin
This commit is contained in:
parent
0612519e1c
commit
268ba07648
5 changed files with 317 additions and 343 deletions
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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())))
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
194
app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt
Normal file
194
app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt
Normal file
|
|
@ -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<View>(withId(R.id.fab_plus), isDisplayed()))
|
||||
.perform(click())
|
||||
|
||||
// Click gallery
|
||||
onView(allOf<View>(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<View>(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")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue