mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Upload tests (#2086)
* Add unit tests for upload flows * Tests for upload model * Test fixes * Remove empty test cases * Changes based on comments
This commit is contained in:
parent
1070137741
commit
f3a90c004c
19 changed files with 533 additions and 252 deletions
|
|
@ -77,6 +77,8 @@ dependencies {
|
|||
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY"
|
||||
testImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY"
|
||||
|
||||
androidTestImplementation "org.mockito:mockito-core:2.10.0"
|
||||
|
||||
//For handling runtime permissions
|
||||
implementation 'com.karumi:dexter:5.0.0'
|
||||
|
||||
|
|
@ -100,6 +102,8 @@ android {
|
|||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.returnDefaultValues = true
|
||||
|
||||
unitTests.all {
|
||||
jvmArgs '-noverify'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ public class CommonsApplication extends Application {
|
|||
ContributionUtils.emptyTemporaryDirectory();
|
||||
|
||||
initAcra();
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (BuildConfig.DEBUG && !isRoboUnitTest()) {
|
||||
Stetho.initializeWithDefaults(this);
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +162,10 @@ public class CommonsApplication extends Application {
|
|||
Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
|
||||
}
|
||||
|
||||
public static boolean isRoboUnitTest() {
|
||||
return "robolectric".equals(Build.FINGERPRINT);
|
||||
}
|
||||
|
||||
private ThreadPoolService getFileLoggingThreadPool() {
|
||||
return new ThreadPoolService.Builder("file-logging-thread")
|
||||
.setPriority(Process.THREAD_PRIORITY_LOWEST)
|
||||
|
|
|
|||
|
|
@ -2,37 +2,31 @@ package fr.free.nrw.commons.upload;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.media.ExifInterface;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import fr.free.nrw.commons.caching.CacheController;
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.mwapi.CategoryApi;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext;
|
||||
|
||||
/**
|
||||
* Processing of the image file that is about to be uploaded via ShareActivity is done here
|
||||
*/
|
||||
@Singleton
|
||||
public class FileProcessor implements SimilarImageDialogFragment.onResponse {
|
||||
|
||||
@Inject
|
||||
|
|
@ -47,24 +41,23 @@ public class FileProcessor implements SimilarImageDialogFragment.onResponse {
|
|||
private String filePath;
|
||||
private ContentResolver contentResolver;
|
||||
private GPSExtractor imageObj;
|
||||
private Context context;
|
||||
private String decimalCoords;
|
||||
private ExifInterface exifInterface;
|
||||
private boolean useExtStorage;
|
||||
private boolean haveCheckedForOtherImages = false;
|
||||
private GPSExtractor tempImageObj;
|
||||
|
||||
FileProcessor(@NonNull String filePath, ContentResolver contentResolver, Context context) {
|
||||
@Inject
|
||||
FileProcessor() {
|
||||
}
|
||||
|
||||
void initFileDetails(@NonNull String filePath, ContentResolver contentResolver) {
|
||||
this.filePath = filePath;
|
||||
this.contentResolver = contentResolver;
|
||||
this.context = context;
|
||||
ApplicationlessInjection.getInstance(context.getApplicationContext()).getCommonsApplicationComponent().inject(this);
|
||||
try {
|
||||
exifInterface=new ExifInterface(filePath);
|
||||
exifInterface = new ExifInterface(filePath);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
useExtStorage = prefs.getBoolean("useExternalStorage", true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,10 +78,6 @@ public class FileProcessor implements SimilarImageDialogFragment.onResponse {
|
|||
return imageObj;
|
||||
}
|
||||
|
||||
String getDecimalCoords() {
|
||||
return decimalCoords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find other images around the same location that were taken within the last 20 sec
|
||||
* @param similarImageInterface
|
||||
|
|
@ -142,7 +131,7 @@ public class FileProcessor implements SimilarImageDialogFragment.onResponse {
|
|||
* Then initiates the calls to MediaWiki API through an instance of CategoryApi.
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
public void useImageCoords() {
|
||||
private void useImageCoords() {
|
||||
if (decimalCoords != null) {
|
||||
Timber.d("Decimal coords of image: %s", decimalCoords);
|
||||
Timber.d("is EXIF data present:" + imageObj.imageCoordsExists + " from findOther image");
|
||||
|
|
|
|||
|
|
@ -234,8 +234,8 @@ public class FileUtils {
|
|||
* @return The value of the _data column, which is typically a file path.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getDataColumn(Context context, Uri uri, String selection,
|
||||
String[] selectionArgs) {
|
||||
private static String getDataColumn(Context context, Uri uri, String selection,
|
||||
String[] selectionArgs) {
|
||||
|
||||
Cursor cursor = null;
|
||||
final String column = MediaStore.Images.ImageColumns.DATA;
|
||||
|
|
@ -311,7 +311,7 @@ public class FileUtils {
|
|||
* @param destination file path copied to
|
||||
* @throws IOException thrown when failing to read source or opening destination file
|
||||
*/
|
||||
public static void copy(@NonNull FileDescriptor source, @NonNull String destination)
|
||||
private static void copy(@NonNull FileDescriptor source, @NonNull String destination)
|
||||
throws IOException {
|
||||
copy(new FileInputStream(source), new FileOutputStream(destination));
|
||||
}
|
||||
|
|
@ -415,7 +415,7 @@ public class FileUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static String getFileExt(String fileName){
|
||||
static String getFileExt(String fileName){
|
||||
//Default file extension
|
||||
String extension=".jpg";
|
||||
|
||||
|
|
@ -426,7 +426,11 @@ public class FileUtils {
|
|||
return extension;
|
||||
}
|
||||
|
||||
public static String getFileExt(Uri uri, ContentResolver contentResolver) {
|
||||
private static String getFileExt(Uri uri, ContentResolver contentResolver) {
|
||||
return getFileExt(getFilename(uri, contentResolver));
|
||||
}
|
||||
|
||||
public static FileInputStream getFileInputStream(String filePath) throws FileNotFoundException {
|
||||
return new FileInputStream(filePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class FileUtilsWrapper {
|
||||
|
||||
@Inject
|
||||
public FileUtilsWrapper() {
|
||||
|
||||
}
|
||||
|
||||
public String createExternalCopyPathAndCopy(Uri uri, ContentResolver contentResolver) throws IOException {
|
||||
return FileUtils.createExternalCopyPathAndCopy(uri, contentResolver);
|
||||
}
|
||||
|
||||
public String createCopyPathAndCopy(Uri uri, Context context) throws IOException {
|
||||
return FileUtils.createCopyPathAndCopy(uri, context);
|
||||
}
|
||||
|
||||
public String getFileExt(String fileName) {
|
||||
return FileUtils.getFileExt(fileName);
|
||||
}
|
||||
|
||||
public String getSHA1(InputStream is) {
|
||||
return FileUtils.getSHA1(is);
|
||||
}
|
||||
|
||||
public FileInputStream getFileInputStream(String filePath) throws FileNotFoundException {
|
||||
return FileUtils.getFileInputStream(filePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,12 +14,12 @@ import timber.log.Timber;
|
|||
* Extracts geolocation to be passed to API for category suggestions. If a picture with geolocation
|
||||
* is uploaded, extract latitude and longitude from EXIF data of image.
|
||||
*/
|
||||
public class GPSExtractor {
|
||||
class GPSExtractor {
|
||||
|
||||
public static final GPSExtractor DUMMY= new GPSExtractor();
|
||||
static final GPSExtractor DUMMY= new GPSExtractor();
|
||||
private double decLatitude;
|
||||
private double decLongitude;
|
||||
public boolean imageCoordsExists;
|
||||
boolean imageCoordsExists;
|
||||
private String latitude;
|
||||
private String longitude;
|
||||
private String latitudeRef;
|
||||
|
|
@ -37,7 +37,7 @@ public class GPSExtractor {
|
|||
* @param fileDescriptor the file descriptor of the image
|
||||
*/
|
||||
@RequiresApi(24)
|
||||
public GPSExtractor(@NonNull FileDescriptor fileDescriptor) {
|
||||
GPSExtractor(@NonNull FileDescriptor fileDescriptor) {
|
||||
try {
|
||||
ExifInterface exif = new ExifInterface(fileDescriptor);
|
||||
processCoords(exif);
|
||||
|
|
@ -51,7 +51,7 @@ public class GPSExtractor {
|
|||
* @param path file path of the image
|
||||
*
|
||||
*/
|
||||
public GPSExtractor(@NonNull String path) {
|
||||
GPSExtractor(@NonNull String path) {
|
||||
try {
|
||||
ExifInterface exif = new ExifInterface(path);
|
||||
processCoords(exif);
|
||||
|
|
@ -65,7 +65,7 @@ public class GPSExtractor {
|
|||
* @param exif exif interface of the image
|
||||
*
|
||||
*/
|
||||
public GPSExtractor(@NonNull ExifInterface exif){
|
||||
GPSExtractor(@NonNull ExifInterface exif){
|
||||
processCoords(exif);
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ public class GPSExtractor {
|
|||
* @return coordinates as string (needs to be passed as a String in API query)
|
||||
*/
|
||||
@Nullable
|
||||
public String getCoords() {
|
||||
String getCoords() {
|
||||
if(decimalCoords!=null){
|
||||
return decimalCoords;
|
||||
}else if (latitude!=null && latitudeRef!=null && longitude!=null && longitudeRef!=null) {
|
||||
|
|
@ -103,11 +103,11 @@ public class GPSExtractor {
|
|||
}
|
||||
}
|
||||
|
||||
public double getDecLatitude() {
|
||||
double getDecLatitude() {
|
||||
return decLatitude;
|
||||
}
|
||||
|
||||
public double getDecLongitude() {
|
||||
double getDecLongitude() {
|
||||
return decLongitude;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class UploadController {
|
|||
}
|
||||
|
||||
private boolean isUploadServiceConnected;
|
||||
private ServiceConnection uploadServiceConnection = new ServiceConnection() {
|
||||
public ServiceConnection uploadServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName componentName, IBinder binder) {
|
||||
uploadService = (UploadService) ((HandlerService.HandlerServiceLocalBinder) binder).getService();
|
||||
|
|
@ -61,6 +61,7 @@ public class UploadController {
|
|||
@Override
|
||||
public void onServiceDisconnected(ComponentName componentName) {
|
||||
// this should never happen
|
||||
isUploadServiceConnected = false;
|
||||
Timber.e(new RuntimeException("UploadService died but the rest of the process did not!"));
|
||||
}
|
||||
};
|
||||
|
|
@ -68,7 +69,7 @@ public class UploadController {
|
|||
/**
|
||||
* Prepares the upload service.
|
||||
*/
|
||||
public void prepareService() {
|
||||
void prepareService() {
|
||||
Intent uploadServiceIntent = new Intent(context, UploadService.class);
|
||||
uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE);
|
||||
context.startService(uploadServiceIntent);
|
||||
|
|
@ -78,7 +79,7 @@ public class UploadController {
|
|||
/**
|
||||
* Disconnects the upload service.
|
||||
*/
|
||||
public void cleanup() {
|
||||
void cleanup() {
|
||||
if (isUploadServiceConnected) {
|
||||
context.unbindService(uploadServiceConnection);
|
||||
}
|
||||
|
|
@ -89,7 +90,7 @@ public class UploadController {
|
|||
*
|
||||
* @param contribution the contribution object
|
||||
*/
|
||||
public void startUpload(Contribution contribution) {
|
||||
void startUpload(Contribution contribution) {
|
||||
startUpload(contribution, c -> {});
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +101,7 @@ public class UploadController {
|
|||
* @param onComplete the progress tracker
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public void startUpload(final Contribution contribution, final ContributionUploadProgress onComplete) {
|
||||
private void startUpload(final Contribution contribution, final ContributionUploadProgress onComplete) {
|
||||
//Set creator, desc, and license
|
||||
if (TextUtils.isEmpty(contribution.getCreator())) {
|
||||
Account currentAccount = sessionManager.getCurrentAccount();
|
||||
|
|
|
|||
|
|
@ -53,16 +53,20 @@ public class UploadModel {
|
|||
private boolean useExtStorage;
|
||||
private Disposable badImageSubscription;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
private SessionManager sessionManager;
|
||||
private Uri currentMediaUri;
|
||||
private FileUtilsWrapper fileUtilsWrapper;
|
||||
private FileProcessor fileProcessor;
|
||||
|
||||
@Inject
|
||||
UploadModel(@Named("licenses") List<String> licenses,
|
||||
@Named("default_preferences") SharedPreferences prefs,
|
||||
@Named("licenses_by_name") Map<String, String> licensesByName,
|
||||
Context context,
|
||||
MediaWikiApi mwApi) {
|
||||
MediaWikiApi mwApi,
|
||||
SessionManager sessionManager,
|
||||
FileUtilsWrapper fileUtilsWrapper,
|
||||
FileProcessor fileProcessor) {
|
||||
this.licenses = licenses;
|
||||
this.prefs = prefs;
|
||||
this.license = Prefs.Licenses.CC_BY_SA_3;
|
||||
|
|
@ -70,6 +74,9 @@ public class UploadModel {
|
|||
this.context = context;
|
||||
this.mwApi = mwApi;
|
||||
this.contentResolver = context.getContentResolver();
|
||||
this.sessionManager = sessionManager;
|
||||
this.fileUtilsWrapper = fileUtilsWrapper;
|
||||
this.fileProcessor = fileProcessor;
|
||||
useExtStorage = this.prefs.getBoolean("useExternalStorage", false);
|
||||
}
|
||||
|
||||
|
|
@ -84,17 +91,17 @@ public class UploadModel {
|
|||
.map(filePath -> {
|
||||
long fileCreatedDate = getFileCreatedDate(currentMediaUri);
|
||||
Uri uri = Uri.fromFile(new File(filePath));
|
||||
FileProcessor fp = new FileProcessor(filePath, context.getContentResolver(), context);
|
||||
UploadItem item = new UploadItem(uri, mimeType, source, fp.processFileCoordinates(similarImageInterface),
|
||||
FileUtils.getFileExt(filePath), null,fileCreatedDate);
|
||||
fileProcessor.initFileDetails(filePath, context.getContentResolver());
|
||||
UploadItem item = new UploadItem(uri, mimeType, source, fileProcessor.processFileCoordinates(similarImageInterface),
|
||||
fileUtilsWrapper.getFileExt(filePath), null,fileCreatedDate);
|
||||
Single.zip(
|
||||
Single.fromCallable(() ->
|
||||
new FileInputStream(filePath))
|
||||
.map(FileUtils::getSHA1)
|
||||
fileUtilsWrapper.getFileInputStream(filePath))
|
||||
.map(fileUtilsWrapper::getSHA1)
|
||||
.map(mwApi::existingFile)
|
||||
.map(b -> b ? ImageUtils.IMAGE_DUPLICATE : ImageUtils.IMAGE_OK),
|
||||
Single.fromCallable(() ->
|
||||
new FileInputStream(filePath))
|
||||
fileUtilsWrapper.getFileInputStream(filePath))
|
||||
.map(file -> BitmapRegionDecoder.newInstance(file, false))
|
||||
.map(ImageUtils::checkIfImageIsTooDark), //Returns IMAGE_DARK or IMAGE_OK
|
||||
(dupe, dark) -> dupe | dark)
|
||||
|
|
@ -113,24 +120,24 @@ public class UploadModel {
|
|||
long fileCreatedDate = getFileCreatedDate(media);
|
||||
String filePath = this.cacheFileUpload(media);
|
||||
Uri uri = Uri.fromFile(new File(filePath));
|
||||
FileProcessor fp = new FileProcessor(filePath, context.getContentResolver(), context);
|
||||
UploadItem item = new UploadItem(uri, mimeType, source, fp.processFileCoordinates(similarImageInterface),
|
||||
FileUtils.getFileExt(filePath), wikidataEntityIdPref,fileCreatedDate);
|
||||
fileProcessor.initFileDetails(filePath, context.getContentResolver());
|
||||
UploadItem item = new UploadItem(uri, mimeType, source, fileProcessor.processFileCoordinates(similarImageInterface),
|
||||
fileUtilsWrapper.getFileExt(filePath), wikidataEntityIdPref,fileCreatedDate);
|
||||
item.title.setTitleText(title);
|
||||
item.descriptions.get(0).setDescriptionText(desc);
|
||||
//TODO figure out if default descriptions in other languages exist
|
||||
item.descriptions.get(0).setLanguageCode("en");
|
||||
Single.zip(
|
||||
Single.fromCallable(() ->
|
||||
new FileInputStream(filePath))
|
||||
.map(FileUtils::getSHA1)
|
||||
fileUtilsWrapper.getFileInputStream(filePath))
|
||||
.map(fileUtilsWrapper::getSHA1)
|
||||
.map(mwApi::existingFile)
|
||||
.map(b -> b ? ImageUtils.IMAGE_DUPLICATE : ImageUtils.IMAGE_OK),
|
||||
Single.fromCallable(() ->
|
||||
new FileInputStream(filePath))
|
||||
fileUtilsWrapper.getFileInputStream(filePath))
|
||||
.map(file -> BitmapRegionDecoder.newInstance(file, false))
|
||||
.map(ImageUtils::checkIfImageIsTooDark), //Returns IMAGE_DARK or IMAGE_OK
|
||||
(dupe, dark) -> dupe | dark).subscribe(item.imageQuality::onNext);
|
||||
(dupe, dark) -> dupe | dark).subscribe(item.imageQuality::onNext, Timber::e);
|
||||
items.add(item);
|
||||
items.get(0).selected = true;
|
||||
items.get(0).first = true;
|
||||
|
|
@ -239,7 +246,7 @@ public class UploadModel {
|
|||
updateItemState();
|
||||
}
|
||||
|
||||
public void setCurrentTitleAndDescriptions(Title title, List<Description> descriptions) {
|
||||
void setCurrentTitleAndDescriptions(Title title, List<Description> descriptions) {
|
||||
setCurrentUploadTitle(title);
|
||||
setCurrentUploadDescriptions(descriptions);
|
||||
}
|
||||
|
|
@ -337,9 +344,9 @@ public class UploadModel {
|
|||
try {
|
||||
String copyPath;
|
||||
if (useExtStorage)
|
||||
copyPath = FileUtils.createExternalCopyPathAndCopy(media, contentResolver);
|
||||
copyPath = fileUtilsWrapper.createExternalCopyPathAndCopy(media, contentResolver);
|
||||
else
|
||||
copyPath = FileUtils.createCopyPathAndCopy(media, context);
|
||||
copyPath = fileUtilsWrapper.createCopyPathAndCopy(media, context);
|
||||
Timber.i("File path is " + copyPath);
|
||||
return copyPath;
|
||||
} catch (IOException e) {
|
||||
|
|
@ -362,6 +369,9 @@ public class UploadModel {
|
|||
badImageSubscription = getCurrentItem().imageQuality.subscribe(consumer, Timber::e);
|
||||
}
|
||||
|
||||
public List<UploadItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
static class UploadItem {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
String notificationProgressTitle;
|
||||
String notificationFinishingTitle;
|
||||
|
||||
public NotificationUpdateProgressListener(String notificationTag, String notificationProgressTitle, String notificationFinishingTitle, Contribution contribution) {
|
||||
NotificationUpdateProgressListener(String notificationTag, String notificationProgressTitle, String notificationFinishingTitle, Contribution contribution) {
|
||||
this.notificationTag = notificationTag;
|
||||
this.notificationProgressTitle = notificationProgressTitle;
|
||||
this.notificationFinishingTitle = notificationFinishingTitle;
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This is a Util class which provides the necessary token to open the Commons License
|
||||
* info in the user language
|
||||
*/
|
||||
public class UrlLicense {
|
||||
public static HashMap<String,String> urlLicense = new HashMap<>();
|
||||
static {
|
||||
urlLicense.put("en", "https://commons.wikimedia.org/wiki/Commons:Licensing");
|
||||
urlLicense.put("ar", "https://commons.wikimedia.org/wiki/Commons:Licensing/ar");
|
||||
urlLicense.put("ast", "https://commons.wikimedia.org/wiki/Commons:Licensing/ast");
|
||||
urlLicense.put("az", "https://commons.wikimedia.org/wiki/Commons:Licensing/az");
|
||||
urlLicense.put("be", "https://commons.wikimedia.org/wiki/Commons:Licensing/be");
|
||||
urlLicense.put("bg", "https://commons.wikimedia.org/wiki/Commons:Licensing/bg");
|
||||
urlLicense.put("bn", "https://commons.wikimedia.org/wiki/Commons:Licensing/bn");
|
||||
urlLicense.put("ca", "https://commons.wikimedia.org/wiki/Commons:Licensing/ca");
|
||||
urlLicense.put("cs", "https://commons.wikimedia.org/wiki/Commons:Licensing/cs");
|
||||
urlLicense.put("da", "https://commons.wikimedia.org/wiki/Commons:Licensing/da");
|
||||
urlLicense.put("de", "https://commons.wikimedia.org/wiki/Commons:Licensing/de");
|
||||
urlLicense.put("el", "https://commons.wikimedia.org/wiki/Commons:Licensing/el");
|
||||
urlLicense.put("eo", "https://commons.wikimedia.org/wiki/Commons:Licensing/eo");
|
||||
urlLicense.put("es", "https://commons.wikimedia.org/wiki/Commons:Licensing/es");
|
||||
urlLicense.put("eu", "https://commons.wikimedia.org/wiki/Commons:Licensing/eu");
|
||||
urlLicense.put("fa", "https://commons.wikimedia.org/wiki/Commons:Licensing/fa");
|
||||
urlLicense.put("fi", "https://commons.wikimedia.org/wiki/Commons:Licensing/fi");
|
||||
urlLicense.put("fr", "https://commons.wikimedia.org/wiki/Commons:Licensing/fr");
|
||||
urlLicense.put("gl", "https://commons.wikimedia.org/wiki/Commons:Licensing/gl");
|
||||
urlLicense.put("gsw", "https://commons.wikimedia.org/wiki/Commons:Licensing/gsw");
|
||||
urlLicense.put("he", "https://commons.wikimedia.org/wiki/Commons:Licensing/he");
|
||||
urlLicense.put("hi", "https://commons.wikimedia.org/wiki/Commons:Licensing/hi");
|
||||
urlLicense.put("hu", "https://commons.wikimedia.org/wiki/Commons:Licensing/hu");
|
||||
urlLicense.put("id", "https://commons.wikimedia.org/wiki/Commons:Licensing/id");
|
||||
urlLicense.put("is", "https://commons.wikimedia.org/wiki/Commons:Licensing/is");
|
||||
urlLicense.put("it", "https://commons.wikimedia.org/wiki/Commons:Licensing/it");
|
||||
urlLicense.put("ja", "https://commons.wikimedia.org/wiki/Commons:Licensing/ja");
|
||||
urlLicense.put("ka", "https://commons.wikimedia.org/wiki/Commons:Licensing/ka");
|
||||
urlLicense.put("km", "https://commons.wikimedia.org/wiki/Commons:Licensing/km");
|
||||
urlLicense.put("ko", "https://commons.wikimedia.org/wiki/Commons:Licensing/ko");
|
||||
urlLicense.put("ku", "https://commons.wikimedia.org/wiki/Commons:Licensing/ku");
|
||||
urlLicense.put("mk", "https://commons.wikimedia.org/wiki/Commons:Licensing/mk");
|
||||
urlLicense.put("mr", "https://commons.wikimedia.org/wiki/Commons:Licensing/mr");
|
||||
urlLicense.put("ms", "https://commons.wikimedia.org/wiki/Commons:Licensing/ms");
|
||||
urlLicense.put("my", "https://commons.wikimedia.org/wiki/Commons:Licensing/my");
|
||||
urlLicense.put("nl", "https://commons.wikimedia.org/wiki/Commons:Licensing/nl");
|
||||
urlLicense.put("oc", "https://commons.wikimedia.org/wiki/Commons:Licensing/oc");
|
||||
urlLicense.put("pl", "https://commons.wikimedia.org/wiki/Commons:Licensing/pl");
|
||||
urlLicense.put("pt", "https://commons.wikimedia.org/wiki/Commons:Licensing/pt");
|
||||
urlLicense.put("pt-br", "https://commons.wikimedia.org/wiki/Commons:Licensing/pt-br");
|
||||
urlLicense.put("ro", "https://commons.wikimedia.org/wiki/Commons:Licensing/ro");
|
||||
urlLicense.put("ru", "https://commons.wikimedia.org/wiki/Commons:Licensing/ru");
|
||||
urlLicense.put("scn", "https://commons.wikimedia.org/wiki/Commons:Licensing/scn");
|
||||
urlLicense.put("sk", "https://commons.wikimedia.org/wiki/Commons:Licensing/sk");
|
||||
urlLicense.put("sl", "https://commons.wikimedia.org/wiki/Commons:Licensing/sl");
|
||||
urlLicense.put("sv", "https://commons.wikimedia.org/wiki/Commons:Licensing/sv");
|
||||
urlLicense.put("tr", "https://commons.wikimedia.org/wiki/Commons:Licensing/tr");
|
||||
urlLicense.put("uk", "https://commons.wikimedia.org/wiki/Commons:Licensing/uk");
|
||||
urlLicense.put("ur", "https://commons.wikimedia.org/wiki/Commons:Licensing/ur");
|
||||
urlLicense.put("vi", "https://commons.wikimedia.org/wiki/Commons:Licensing/vi");
|
||||
urlLicense.put("zh", "https://commons.wikimedia.org/wiki/Commons:Licensing/zh");
|
||||
}
|
||||
public static String getLicenseUrl ( String language){
|
||||
if (urlLicense.containsKey(language)) {
|
||||
return urlLicense.get(language);
|
||||
} else {
|
||||
return urlLicense.get("en");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapRegionDecoder;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.graphics.BitmapCompat;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Contains utility methods for the Zoom function in ShareActivity.
|
||||
*/
|
||||
public class Zoom {
|
||||
|
||||
private View thumbView;
|
||||
private ContentResolver contentResolver;
|
||||
private FrameLayout flContainer;
|
||||
|
||||
Zoom(View thumbView, FrameLayout flContainer, ContentResolver contentResolver) {
|
||||
this.thumbView = thumbView;
|
||||
this.contentResolver = contentResolver;
|
||||
this.flContainer = flContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a scaled bitmap to display the zoomed-in image
|
||||
* @param input the input stream corresponding to the uploaded image
|
||||
* @param imageUri the uploaded image's URI
|
||||
* @return a zoomable bitmap
|
||||
*/
|
||||
Bitmap createScaledImage(InputStream input, Uri imageUri) {
|
||||
|
||||
Bitmap scaled = null;
|
||||
BitmapRegionDecoder decoder = null;
|
||||
Bitmap bitmap = null;
|
||||
|
||||
try {
|
||||
decoder = BitmapRegionDecoder.newInstance(input, false);
|
||||
bitmap = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e);
|
||||
} catch (NullPointerException e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
try {
|
||||
//Compress the Image
|
||||
System.gc();
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
long maxMemory = rt.freeMemory();
|
||||
bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri);
|
||||
int bitmapByteCount = BitmapCompat.getAllocationByteCount(bitmap);
|
||||
long height = bitmap.getHeight();
|
||||
long width = bitmap.getWidth();
|
||||
long calHeight = (long) ((height * maxMemory) / (bitmapByteCount * 1.1));
|
||||
long calWidth = (long) ((width * maxMemory) / (bitmapByteCount * 1.1));
|
||||
scaled = Bitmap.createScaledBitmap(bitmap, (int) Math.min(width, calWidth), (int) Math.min(height, calHeight), true);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e);
|
||||
} catch (NullPointerException e) {
|
||||
Timber.e(e);
|
||||
scaled = bitmap;
|
||||
}
|
||||
return scaled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the starting and ending bounds for the zoomed-in image.
|
||||
* Also set the container view's offset as the origin for the
|
||||
* bounds, since that's the origin for the positioning animation
|
||||
* properties (X, Y).
|
||||
* @param startBounds the global visible rectangle of the thumbnail
|
||||
* @param finalBounds the global visible rectangle of the container view
|
||||
* @param globalOffset the container view's offset
|
||||
* @return scaled start bounds
|
||||
*/
|
||||
float adjustStartEndBounds(Rect startBounds, Rect finalBounds, Point globalOffset) {
|
||||
|
||||
thumbView.getGlobalVisibleRect(startBounds);
|
||||
flContainer.getGlobalVisibleRect(finalBounds, globalOffset);
|
||||
startBounds.offset(-globalOffset.x, -globalOffset.y);
|
||||
finalBounds.offset(-globalOffset.x, -globalOffset.y);
|
||||
|
||||
// Adjust the start bounds to be the same aspect ratio as the final
|
||||
// bounds using the "center crop" technique. This prevents undesirable
|
||||
// stretching during the animation. Also calculate the start scaling
|
||||
// factor (the end scaling factor is always 1.0).
|
||||
float startScale;
|
||||
if ((float) finalBounds.width() / finalBounds.height()
|
||||
> (float) startBounds.width() / startBounds.height()) {
|
||||
// Extend start bounds horizontally
|
||||
startScale = (float) startBounds.height() / finalBounds.height();
|
||||
float startWidth = startScale * finalBounds.width();
|
||||
float deltaWidth = (startWidth - startBounds.width()) / 2;
|
||||
startBounds.left -= deltaWidth;
|
||||
startBounds.right += deltaWidth;
|
||||
} else {
|
||||
// Extend start bounds vertically
|
||||
startScale = (float) startBounds.width() / finalBounds.width();
|
||||
float startHeight = startScale * finalBounds.height();
|
||||
float deltaHeight = (startHeight - startBounds.height()) / 2;
|
||||
startBounds.top -= deltaHeight;
|
||||
startBounds.bottom += deltaHeight;
|
||||
}
|
||||
return startScale;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
package fr.free.nrw.commons.widget;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
|
@ -13,10 +13,7 @@ import android.view.Display;
|
|||
* Created by Ilgaz Er on 8/7/2018.
|
||||
*/
|
||||
public class HeightLimitedRecyclerView extends RecyclerView {
|
||||
|
||||
int height;
|
||||
|
||||
|
||||
public HeightLimitedRecyclerView(Context context) {
|
||||
super(context);
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_expand_less_black_24dp" />
|
||||
|
||||
<fr.free.nrw.commons.upload.HeightLimitedRecyclerView
|
||||
<fr.free.nrw.commons.widget.HeightLimitedRecyclerView
|
||||
android:id="@+id/rv_descriptions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ class TestCommonsApplication : CommonsApplication() {
|
|||
override fun onCreate() {
|
||||
if (mockApplicationComponent == null) {
|
||||
mockApplicationComponent = DaggerCommonsApplicationComponent.builder()
|
||||
.appModule(MockCommonsApplicationModule(this)).build()
|
||||
.appModule(MockCommonsApplicationModule(this))
|
||||
.build()
|
||||
}
|
||||
super.onCreate()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.free.nrw.commons.mwapi
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.preference.PreferenceManager
|
||||
import com.google.gson.Gson
|
||||
|
|
@ -15,9 +16,12 @@ import org.junit.Assert.*
|
|||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.mock
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
import timber.log.Timber
|
||||
import java.io.InputStream
|
||||
import java.net.URLDecoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.SharedPreferences
|
||||
import fr.free.nrw.commons.caching.CacheController
|
||||
import fr.free.nrw.commons.mwapi.CategoryApi
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.anyString
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class FileProcessorTest {
|
||||
|
||||
@Mock
|
||||
internal var cacheController: CacheController? = null
|
||||
@Mock
|
||||
internal var gpsCategoryModel: GpsCategoryModel? = null
|
||||
@Mock
|
||||
internal var apiCall: CategoryApi? = null
|
||||
@Mock
|
||||
@field:[Inject Named("default_preferences")]
|
||||
internal var prefs: SharedPreferences? = null
|
||||
|
||||
@InjectMocks
|
||||
var fileProcessor: FileProcessor? = null
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun processFileCoordinates() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import fr.free.nrw.commons.HandlerService
|
||||
import fr.free.nrw.commons.auth.SessionManager
|
||||
import fr.free.nrw.commons.contributions.Contribution
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class UploadControllerTest {
|
||||
|
||||
@Mock
|
||||
internal var sessionManager: SessionManager? = null
|
||||
@Mock
|
||||
internal var context: Context? = null
|
||||
@Mock
|
||||
internal var prefs: SharedPreferences? = null
|
||||
|
||||
@InjectMocks
|
||||
var uploadController: UploadController? = null
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
val uploadService = mock(UploadService::class.java)
|
||||
val binder = mock(HandlerService.HandlerServiceLocalBinder::class.java)
|
||||
`when`(binder.service).thenReturn(uploadService)
|
||||
uploadController!!.uploadServiceConnection.onServiceConnected(mock(ComponentName::class.java), binder)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prepareService() {
|
||||
uploadController!!.prepareService()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cleanup() {
|
||||
uploadController!!.cleanup()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startUpload() {
|
||||
val contribution = mock(Contribution::class.java)
|
||||
uploadController!!.startUpload(contribution)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.app.Application
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import fr.free.nrw.commons.auth.SessionManager
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers.any
|
||||
import org.mockito.ArgumentMatchers.anyString
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
|
||||
class UploadModelTest {
|
||||
|
||||
@Mock
|
||||
@field:[Inject Named("licenses")]
|
||||
internal var licenses: List<String>? = null
|
||||
@Mock
|
||||
@field:[Inject Named("default_preferences")]
|
||||
internal var prefs: SharedPreferences? = null
|
||||
@Mock
|
||||
@field:[Inject Named("licenses_by_name")]
|
||||
internal var licensesByName: Map<String, String>? = null
|
||||
@Mock
|
||||
internal var context: Context? = null
|
||||
@Mock
|
||||
internal var mwApi: MediaWikiApi? = null
|
||||
@Mock
|
||||
internal var sessionManage: SessionManager? = null
|
||||
@Mock
|
||||
internal var fileUtilsWrapper: FileUtilsWrapper? = null
|
||||
@Mock
|
||||
internal var fileProcessor: FileProcessor? = null
|
||||
|
||||
@InjectMocks
|
||||
var uploadModel: UploadModel? = null
|
||||
|
||||
@Before
|
||||
@Throws(Exception::class)
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
`when`(context!!.applicationContext)
|
||||
.thenReturn(mock(Application::class.java))
|
||||
`when`(fileUtilsWrapper!!.createCopyPathAndCopy(any(Uri::class.java), any(Context::class.java)))
|
||||
.thenReturn("file.jpg")
|
||||
`when`(fileUtilsWrapper!!.createExternalCopyPathAndCopy(any(Uri::class.java), any(ContentResolver::class.java)))
|
||||
.thenReturn("extFile.jpg")
|
||||
`when`(fileUtilsWrapper!!.getFileExt(anyString()))
|
||||
.thenReturn("jpg")
|
||||
`when`(fileUtilsWrapper!!.getSHA1(any(InputStream::class.java)))
|
||||
.thenReturn("sha")
|
||||
`when`(fileUtilsWrapper!!.getFileInputStream(anyString()))
|
||||
.thenReturn(mock(FileInputStream::class.java))
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
@Throws(Exception::class)
|
||||
fun tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receive() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.items.size == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receiveDirect() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.items.size == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyPreviousNotAvailableForDirectUpload() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertFalse(uploadModel!!.isPreviousAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyNextAvailableForDirectUpload() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.isNextAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyPreviousNotAvailable() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertFalse(uploadModel!!.isPreviousAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyNextAvailable() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.isNextAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isSubmitAvailable() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.isNextAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isSubmitAvailableForDirectUpload() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.isNextAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCurrentStepForDirectUpload() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.currentStep == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCurrentStep() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.currentStep == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getStepCount() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.stepCount == 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getStepCountForDirectUpload() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.stepCount == 3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDirectCount() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.count == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCount() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.count == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getUploads() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.uploads.size == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDirectUploads() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.uploads.size == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isTopCardState() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.isTopCardState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isTopCardStateForDirectUpload() {
|
||||
val element = mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
assertTrue(uploadModel!!.isTopCardState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun next() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.currentStep == 1)
|
||||
uploadModel!!.next()
|
||||
assertTrue(uploadModel!!.currentStep == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun previous() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.currentStep == 1)
|
||||
uploadModel!!.next()
|
||||
assertTrue(uploadModel!!.currentStep == 2)
|
||||
uploadModel!!.previous()
|
||||
assertTrue(uploadModel!!.currentStep == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isShowingItem() {
|
||||
val element = mock(Uri::class.java)
|
||||
val element2 = mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadModel!!.receive(uriList, "image/jpeg", "external") { _, _ -> }
|
||||
assertTrue(uploadModel!!.isShowingItem)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun buildContributions() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.net.Uri
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class UploadPresenterTest {
|
||||
|
||||
@Mock
|
||||
internal var uploadModel: UploadModel? = null
|
||||
@Mock
|
||||
internal var uploadController: UploadController? = null
|
||||
@Mock
|
||||
internal var mediaWikiApi: MediaWikiApi? = null
|
||||
|
||||
@InjectMocks
|
||||
var uploadPresenter: UploadPresenter? = null
|
||||
|
||||
@Before
|
||||
@Throws(Exception::class)
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receiveMultipleItems() {
|
||||
val element = Mockito.mock(Uri::class.java)
|
||||
val element2 = Mockito.mock(Uri::class.java)
|
||||
var uriList: List<Uri> = mutableListOf<Uri>(element, element2)
|
||||
uploadPresenter!!.receive(uriList, "image/jpeg", "external")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receiveSingleItem() {
|
||||
val element = Mockito.mock(Uri::class.java)
|
||||
uploadPresenter!!.receive(element, "image/jpeg", "external")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receiveDirect() {
|
||||
val element = Mockito.mock(Uri::class.java)
|
||||
uploadModel!!.receiveDirect(element, "image/jpeg", "external", "Q1", "Test", "Test"
|
||||
) { _, _ -> }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue