mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Upload UI tests (#2626)
* Fix SettingsActivityTest * Add test in SettingsActivity to set recent upload limit to 0 * Add tests to recent upload limit setting * Simplify activity test rule * Add UploadTest * Log the URL where the file should be uploaded * Generate an image file before testing uploads * With runtime permissions * With automatic login * With automatic login * Get test credentials from travis
This commit is contained in:
parent
1040c2d5b1
commit
db5290efcf
3 changed files with 225 additions and 9 deletions
|
|
@ -66,6 +66,7 @@ dependencies {
|
|||
// Android testing
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION"
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.1.1'
|
||||
|
|
@ -193,6 +194,8 @@ android {
|
|||
buildConfigField "String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.locations.contentprovider\""
|
||||
buildConfigField "String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\""
|
||||
buildConfigField "String", "TEST_USERNAME", "\"" + System.getenv("test_user_name") + "\""
|
||||
buildConfigField "String", "TEST_PASSWORD", "\"" + System.getenv("test_user_password") + "\""
|
||||
|
||||
dimension 'tier'
|
||||
}
|
||||
|
|
@ -223,6 +226,8 @@ android {
|
|||
buildConfigField "String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.locations.contentprovider\""
|
||||
buildConfigField "String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\""
|
||||
buildConfigField "String", "TEST_USERNAME", "\"" + System.getenv("test_user_name") + "\""
|
||||
buildConfigField "String", "TEST_PASSWORD", "\"" + System.getenv("test_user_password") + "\""
|
||||
|
||||
dimension 'tier'
|
||||
}
|
||||
|
|
|
|||
211
app/src/androidTest/java/fr/free/nrw/commons/UploadTest.java
Normal file
211
app/src/androidTest/java/fr/free/nrw/commons/UploadTest.java
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,6 @@ import android.app.AlertDialog;
|
|||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
|
@ -20,18 +13,24 @@ import android.view.View;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.auth.AuthenticatedActivity;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.NearbyFragment;
|
||||
import fr.free.nrw.commons.nearby.NearbyNotificationCardView;
|
||||
|
|
@ -464,6 +463,7 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Timber.d(data.toString());
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
controller.handleActivityResult(this, requestCode, resultCode, data);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue