Convert instrumentation tests to Kotlin (#2689)

* Convert SettingsActivityTest to Kotlin

* Convert NavigationBaseActivityTest to Kotlin

* Convert UploadTest to Kotlin
This commit is contained in:
Adam Jones 2019-03-21 04:56:36 +00:00 committed by Vivek Maskara
parent 0612519e1c
commit 268ba07648
5 changed files with 317 additions and 343 deletions

View file

@ -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));
}
}

View file

@ -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))
}
}

View file

@ -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())))
}
}

View file

@ -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);
}
}

View 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")
}
}