Merge branch 'master' into dependency-injection

This commit is contained in:
Paul Hawke 2017-09-13 19:54:43 -05:00
commit 2d91e81121
19 changed files with 288 additions and 168 deletions

View file

@ -84,6 +84,29 @@ android {
}
}
productFlavors {
prod {
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\""
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\""
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\""
buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.org/wiki/\""
buildConfigField "String", "EVENTLOG_URL", "\"https://www.wikimedia.org/beacon/event\""
buildConfigField "String", "EVENTLOG_WIKI", "\"commonswiki\""
}
beta {
// What values do we need to hit the BETA versions of the site / api ?
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\""
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\""
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\""
buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/wiki/\""
buildConfigField "String", "EVENTLOG_URL", "\"https://commons.wikimedia.beta.wmflabs.org/beacon/event\""
buildConfigField "String", "EVENTLOG_WIKI", "\"commonswiki\""
}
}
lintOptions {
disable 'MissingTranslation'
disable 'ExtraTranslation'

View file

@ -1,23 +0,0 @@
package fr.free.nrw.commons;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.is;
// TODO: use Robolectric and make it runnable without a connected device
@RunWith(AndroidJUnit4.class)
public class MediaTest {
@Test public void displayTitleShouldStripExtension() {
Media m = new Media("File:Example.jpg");
Assert.assertThat(m.getDisplayTitle(), is("Example"));
}
@Test public void displayTitleShouldUseSpaceForUnderscore() {
Media m = new Media("File:Example 1_2.jpg");
Assert.assertThat(m.getDisplayTitle(), is("Example 1 2"));
}
}

View file

@ -1,57 +0,0 @@
package fr.free.nrw.commons;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.nearby.NearbyBaseMarker;
import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.nearby.Place;
import static org.hamcrest.CoreMatchers.is;
@RunWith(AndroidJUnit4.class)
public class NearbyControllerTest {
private Context instrumentationContext;
@Before
public void setup() {
instrumentationContext = InstrumentationRegistry.getTargetContext();
}
@Test public void testNullAttractions() {
LatLng location = new LatLng(0, 0, 0);
List<NearbyBaseMarker> options =
NearbyController.loadAttractionsFromLocationToBaseMarkerOptions(
location,
null,
instrumentationContext
);
Assert.assertThat(options.size(), is(0));
}
@Test public void testEmptyList() {
LatLng location = new LatLng(0, 0, 0);
List<Place> emptyList = new ArrayList<>();
List<NearbyBaseMarker> options =
NearbyController.loadAttractionsFromLocationToBaseMarkerOptions(
location,
emptyList,
instrumentationContext
);
Assert.assertThat(options.size(), is(0));
}
}

View file

@ -1,61 +0,0 @@
package fr.free.nrw.commons;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.URLEncoder;
import static org.hamcrest.CoreMatchers.is;
// TODO: use Robolectric and make it runnable without a connected device
@RunWith(AndroidJUnit4.class)
public class PageTitleTest {
@Test public void displayTextShouldNotBeUnderscored() {
Assert.assertThat(new PageTitle("Ex_1 ").getDisplayText(),
is("Ex 1"));
}
@Test public void moreThanTwoColons() {
Assert.assertThat(new PageTitle("File:sample:a.jpg").getPrefixedText(),
is("File:Sample:a.jpg"));
}
@Test public void getTextShouldReturnWithoutNamespace() {
Assert.assertThat(new PageTitle("File:sample.jpg").getText(),
is("Sample.jpg"));
}
@Test public void capitalizeNameAfterNamespace() {
Assert.assertThat(new PageTitle("File:sample.jpg").getPrefixedText(),
is("File:Sample.jpg"));
}
@Test public void prefixedTextShouldBeUnderscored() {
Assert.assertThat(new PageTitle("Ex 1 ").getPrefixedText(),
is("Ex_1"));
}
@Test public void getMobileUriForTest() {
Assert.assertThat(new PageTitle("Test").getMobileUri().toString(),
is("https://commons.m.wikimedia.org/wiki/Test"));
}
@Test public void spaceBecomesUnderscoreInUri() {
Assert.assertThat(new PageTitle("File:Ex 1.jpg").getCanonicalUri().toString(),
is("https://commons.wikimedia.org/wiki/File:Ex_1.jpg"));
}
@Test public void leaveSubpageNamesUncapitalizedInUri() {
Assert.assertThat(new PageTitle("User:Ex/subpage").getCanonicalUri().toString(),
is("https://commons.wikimedia.org/wiki/User:Ex/subpage"));
}
@Test public void unicodeUri() throws Throwable {
Assert.assertThat(new PageTitle("User:例").getCanonicalUri().toString(),
is("https://commons.wikimedia.org/wiki/User:" + URLEncoder.encode("", "utf-8")));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -49,13 +49,6 @@ public class CommonsApplication extends DaggerApplication {
@Inject SessionManager sessionManager;
@Inject DBOpenHelper dbOpenHelper;
public static final String API_URL = "https://commons.wikimedia.org/w/api.php";
public static final String IMAGE_URL_BASE = "https://upload.wikimedia.org/wikipedia/commons";
public static final String HOME_URL = "https://commons.wikimedia.org/wiki/";
public static final String MOBILE_HOME_URL = "https://commons.m.wikimedia.org/wiki/";
public static final String EVENTLOG_URL = "https://www.wikimedia.org/beacon/event";
public static final String EVENTLOG_WIKI = "commonswiki";
public static final Object[] EVENT_UPLOAD_ATTEMPT = {"MobileAppUploadAttempts", 5334329L};
public static final Object[] EVENT_LOGIN_ATTEMPT = {"MobileAppLoginAttempts", 5257721L};
public static final Object[] EVENT_SHARE_ATTEMPT = {"MobileAppShareAttempts", 5346170L};

View file

@ -58,7 +58,7 @@ public class PageTitle {
*/
@NonNull
public Uri getCanonicalUri() {
String uriStr = CommonsApplication.HOME_URL + Uri.encode(getPrefixedText(), ":/");
String uriStr = BuildConfig.HOME_URL + Uri.encode(getPrefixedText(), ":/");
return Uri.parse(uriStr);
}
@ -71,7 +71,7 @@ public class PageTitle {
*/
@NonNull
public Uri getMobileUri() {
String uriStr = CommonsApplication.MOBILE_HOME_URL + Uri.encode(getPrefixedText(), ":/");
String uriStr = BuildConfig.MOBILE_HOME_URL + Uri.encode(getPrefixedText(), ":/");
return Uri.parse(uriStr);
}

View file

@ -11,6 +11,7 @@ import java.util.regex.Pattern;
import fr.free.nrw.commons.settings.Prefs;
public class Utils {
/**
@ -32,7 +33,7 @@ public class Utils {
public static String makeThumbBaseUrl(String filename) {
String name = new PageTitle(filename).getPrefixedText();
String sha = new String(Hex.encodeHex(DigestUtils.md5(name)));
return String.format("%s/%s/%s/%s", CommonsApplication.IMAGE_URL_BASE, sha.substring(0, 1), sha.substring(0, 2), urlEncode(name));
return String.format("%s/%s/%s/%s", BuildConfig.IMAGE_URL_BASE, sha.substring(0, 1), sha.substring(0, 2), urlEncode(name));
}
public static String urlEncode(String url) {

View file

@ -6,6 +6,7 @@ import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.auth.AccountUtil;
import fr.free.nrw.commons.auth.SessionManager;
@ -37,7 +38,7 @@ public class CommonsApplicationModule {
@Provides
@Singleton
public MediaWikiApi provideMediaWikiApi() {
return new ApacheHttpClientMediaWikiApi(CommonsApplication.API_URL);
return new ApacheHttpClientMediaWikiApi(BuildConfig.WIKIMEDIA_API_HOST);
}
@Provides

View file

@ -47,12 +47,12 @@ public class LogBuilder {
try {
fullData.put("schema", schema);
fullData.put("revision", rev);
fullData.put("wiki", CommonsApplication.EVENTLOG_WIKI);
fullData.put("wiki", BuildConfig.EVENTLOG_WIKI);
data.put("device", EventLog.DEVICE);
data.put("platform", "Android/" + Build.VERSION.RELEASE);
data.put("appversion", "Android/" + BuildConfig.VERSION_NAME);
fullData.put("event", data);
return new URL(CommonsApplication.EVENTLOG_URL + "?" + Utils.urlEncode(fullData.toString()) + ";");
return new URL(BuildConfig.EVENTLOG_URL + "?" + Utils.urlEncode(fullData.toString()) + ";");
} catch (MalformedURLException | JSONException e) {
throw new RuntimeException(e);
}

View file

@ -7,7 +7,7 @@ import android.preference.PreferenceManager;
import dagger.android.support.DaggerAppCompatActivity;
import fr.free.nrw.commons.R;
public class BaseActivity extends DaggerAppCompatActivity {
public abstract class BaseActivity extends DaggerAppCompatActivity {
boolean currentTheme;
@Override

View file

@ -20,11 +20,11 @@
<string name="upload_progress_notification_title_finishing">اتمام بارگذاری %1$s</string>
<string name="upload_failed_notification_title">%1$s بارگذاری نشد</string>
<string name="upload_failed_notification_subtitle">برای دیدن انگشت بزنید</string>
<plurals name="uploads_pending_notification_indicator" fuzzy="true">
<item quantity="one">یک پرونده در حال بارگذاری</item>
<plurals name="uploads_pending_notification_indicator">
<item quantity="one">%d پرونده در حال بارگذاری</item>
<item quantity="other">%d پرونده در حال بارگذاری</item>
</plurals>
<string name="title_activity_contributions" fuzzy="true">بارگذاری‌های من</string>
<string name="title_activity_contributions">بارگذاری‌های اخیر من</string>
<string name="contribution_state_queued">در صف</string>
<string name="contribution_state_failed">ناموفق بود</string>
<string name="contribution_state_in_progress">%1$d٪ کامل شد</string>
@ -42,6 +42,7 @@
<string name="login_failed_password">ناتوانی در ورود - لطفاً گذرواژه‌یتان را بررسی کنید</string>
<string name="login_failed_throttled">تلاش ناموفق بیش از حد. لطفاً چند دقیقهٔ دیگر دوباره تلاش کنید</string>
<string name="login_failed_blocked">پوزش، کاربر در ویکی‌انبار بسته شده‌است</string>
<string name="login_failed_2fa_needed">باید تأیید دومرحله‌ای را فعال کنید.</string>
<string name="login_failed_generic">ورود ناموفق بود</string>
<string name="share_upload_button">بارگذاری</string>
<string name="multiple_share_base_title">نام این مجموعه</string>
@ -49,17 +50,21 @@
<string name="menu_upload_single">بارگذاری</string>
<string name="categories_search_text_hint">جستجوی رده‌ها</string>
<string name="menu_save_categories">ذخیره</string>
<plurals name="contributions_subtitle" fuzzy="true">
<item quantity="zero">هنوز بارگذاری نشده است</item>
<item quantity="one">یک بارگذاری شد</item>
<string name="refresh_button">تازه کردن</string>
<string name="gps_disabled">مکان‌یاب در دستگاه شما خاموش است. آیا دوست دارید فعال شود؟</string>
<string name="enable_gps">فعال کردن مکان‌یاب</string>
<string name="contributions_subtitle_zero">هنوز هیچ بارگذاری</string>
<plurals name="contributions_subtitle">
<item quantity="zero">\@string/contributions_subtitle_zero</item>
<item quantity="one">بارگذاری شد</item>
<item quantity="other">%d بارگذاری شد</item>
</plurals>
<plurals name="starting_multiple_uploads" fuzzy="true">
<item quantity="one">شروع بارگذاری پرونده</item>
<plurals name="starting_multiple_uploads">
<item quantity="one">شروع %d بارگذاری پرونده</item>
<item quantity="other">شروع بارگذاری %d پرونده</item>
</plurals>
<plurals name="multiple_uploads_title" fuzzy="true">
<item quantity="one">۱ بارگذاری</item>
<plurals name="multiple_uploads_title">
<item quantity="one">%d بارگذاری</item>
<item quantity="other">%d بارگذاری</item>
</plurals>
<string name="categories_not_found">رده‌ای منطبق با %1$s یافت نشد</string>
@ -68,9 +73,10 @@
<string name="title_activity_settings">تنظیمات</string>
<string name="title_activity_signup">ثبت نام</string>
<string name="menu_about">درباره</string>
<string name="about_license" fuzzy="true">نرم‌افزار متن‌باز آزاد تحت &lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\"&gt;مجوز آپاچی نسخهٔ ۲&lt;/a&gt;\n\nویکی‌انبار و نشانش یک نشان تجاری‌ست و با اجازهٔ بنیاد ویکی‌مدیا استفاده می‌شود. ما زیرمجموعه یا شعبهٔ بنیاد نیستیم.</string>
<string name="about_license">نرم‌افزار متن‌باز آزاد تحت &lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\"&gt;مجوز آپاچی نسخهٔ ۲&lt;/a&gt;\n\n%1$s و نشانش یک نشان تجاری‌ست و با اجازهٔ بنیاد ویکی‌مدیا استفاده می‌شود. ما زیرمجموعه یا شعبهٔ بنیاد نیستیم.</string>
<string name="about_improve">&lt;a href=\"https://github.com/commons-app/apps-android-commons\"&gt;Source&lt;/a&gt; and &lt;a href=\"https://commons-app.github.io/\"&gt;وب‌سایت&lt;/a&gt; در گیت‌هاب. ایجاد یک &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;درخواست در گیت‌هاب&lt;/a&gt; برای گزارش باگ و یا پیشنهاد یک خصوصیت جدید.</string>
<string name="about_privacy_policy">&lt;a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\"&gt;سیاست حفظ حریم خصوصی&lt;/a&gt;</string>
<string name="about_credits">&lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\"&gt;مجوز&lt;/a&gt;</string>
<string name="title_activity_about">درباره</string>
<string name="menu_feedback">ارسال بازخورد (از طریق ایمیل)</string>
<string name="no_email_client">نرم‌افزار ایمیل نصب نیست</string>
@ -80,11 +86,16 @@
<string name="menu_retry_upload">تلاش مجدد</string>
<string name="menu_cancel_upload">لغو</string>
<string name="share_license_summary">این نگاره تحت مجوز %1$s است</string>
<string name="media_upload_policy">با بارگذاری این تصویر، تأیید می‌کنم که این اثر کار خودم است و از محتوای دارای حق تکثیر یا سلفی برای ایجاد آن استفاده نکرده‌ام و شرایط ذکر شده در By submitting this picture, I declare that this is my own work, that it does not contain copyrighted material or selfies, and otherwise adheres to &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;سیاست‌های ویکی‌انبار&lt;/a&gt; را رعایت می‌کند.</string>
<string name="menu_download">دریافت</string>
<string name="preference_license">مجوز</string>
<string name="use_previous">از عنوان/توضیحات پیشین استفاده کنید</string>
<string name="allow_gps">دریافت خودکار موقعیت کنونی</string>
<string name="allow_gps_summary">درحال دریافت موقعیت برای پیشنهاد رده در صورتی که برچسب جغرافیایی وجود نداشته باشد.</string>
<string name="preference_theme">حالت شبانه</string>
<string name="preference_theme_summary">استفاده از حالت تیره</string>
<string name="license_name_cc_by_sa_four">CC Attribution-ShareAlike 4.0</string>
<string name="license_name_cc_by_four">Attribution 4.0</string>
<string name="license_name_cc_by_sa">CC Attribution-ShareAlike 3.0</string>
<string name="license_name_cc_by">CC Attribution 3.0</string>
<string name="license_name_cc0">CC0</string>
@ -127,8 +138,60 @@
<string name="location_permission_rationale">اجازه‌های اختیاری: دریافت موقعیت برای پیشنهاد رده</string>
<string name="ok">تأیید</string>
<string name="title_activity_nearby">مکان‌‌های اطراف</string>
<string name="no_nearby">مکانی در نزدیکی یافت نشد</string>
<string name="warning">هشدار</string>
<string name="file_exists">پرونده در ویکی‌انبار موجود است. آیا مطمئنید که می‌خواهید ادامه دهید؟</string>
<string name="yes">بله</string>
<string name="no">خیر</string>
<string name="media_detail_title">عنوان</string>
<string name="media_detail_media_title">عنوان رسانه</string>
<string name="media_detail_description">توضیح</string>
<string name="media_detail_description_explanation">توضیحات رسانه اینجا می‌روند. امکان دارد طولانی باشد و نیاز به چند خط شدن داشته باشد. امیدواریم خوب دیده شود.</string>
<string name="media_detail_uploaded_date">تاریخ بارگذاری</string>
<string name="media_detail_license">مجوز</string>
<string name="media_detail_coordinates">مختصات‌ها</string>
<string name="media_detail_coordinates_empty">ارائه نشده است</string>
<string name="become_a_tester_title">آزمایشگر نسخهٔ آزمایشی شوید</string>
<string name="become_a_tester_description">به گروه آزمایشی ما در گوگل‌پلی بپیوندید و از خصوصیات جدید و خطاهای رفع‌شده زودتر از دیگران برخوردار شوید.</string>
<string name="use_wikidata">استفاده از ویکی‌داده</string>
<string name="use_wikidata_summary">(هشدار: غیرفعال کردن این ممکن است حجم زیادی از اینترنت تلفن همراه را مصرف کند)</string>
<string name="_2fa_code">کد 2FA</string>
<string name="number_of_uploads">محدودیت بارگذاری اخیر من</string>
<string name="maximum_limit">حداکثر محدودیت</string>
<string name="maximum_limit_alert">عدم توانایی در نمایش بیش از ۵۰۰ مورد</string>
<string name="set_limit">تنظیم محدودیت بارگذاری‌های اخیر</string>
<string name="login_failed_2fa_not_supported">تأیید دومرحله‌ای الان پشتیبانی نمی‌شود.</string>
<string name="logout_verification">آیا واقعاً قصد خروج از سامانه را دارید؟</string>
<string name="commons_logo">نشان ویکی‌انبار</string>
<string name="background_image">تصویر پس‌زمینه</string>
<string name="mediaimage_failed">خطای تصویر رسانه</string>
<string name="no_image_found">تصویری یافت نشد</string>
<string name="upload_image">بارگذاری تصویر</string>
<string name="welcome_image_mount_zao">کوه زائو</string>
<string name="welcome_image_llamas">لاما</string>
<string name="welcome_image_rainbow_bridge">رینبو بریج</string>
<string name="welcome_image_tulip">لاله</string>
<string name="welcome_image_no_selfies">سلفی نه</string>
<string name="welcome_image_proprietary">تصویر اختصاصی</string>
<string name="welcome_image_welcome_wikipedia">به ویکی‌پدیا خوش‌آمدید</string>
<string name="welcome_image_welcome_copyright">حق‌تکثیر خوش‌آمدگویی</string>
<string name="welcome_image_sydney_opera_house">خانه اپرای سیدنی</string>
<string name="cancel">لغو</string>
<string name="navigation_drawer_open">باز کردن</string>
<string name="navigation_drawer_close">بستن</string>
<string name="navigation_item_home">خانه</string>
<string name="navigation_item_upload">بارگذاری</string>
<string name="navigation_item_nearby">در نزدیکی</string>
<string name="navigation_item_about">درباره</string>
<string name="navigation_item_settings">تنظیمات</string>
<string name="navigation_item_feedback">بازخورد</string>
<string name="navigation_item_logout">خروج</string>
<string name="navigation_item_info">آموزش</string>
<string name="nearby_needs_permissions">مکان‌های اطراف بدون اجازه دادن به مکان‌یاب مقدور نیست</string>
<string name="no_description_found">توضیحی یافت نشد</string>
<string name="nearby_info_menu_commons_article">صفحهٔ دروند در ویکی‌انبار</string>
<string name="nearby_info_menu_wikidata_article">آیتم ویکی‌داده</string>
<string name="error_while_cache">خطا در زمان دریافت تصاویر</string>
<string name="title_info">عنوانی توصیفی و یکتا برای پرونده که به عنوان نام پرونده در نظر گرفته خواهد شد. ترجیحاً به زبان ساده باشد، می‌توانید فاصله هم به کار ببرید. پسوند پرونده را ننویسید.</string>
<string name="description_info">لطفاً تصویر را تا حد توان شرح دهید. کجا گرفته شده‌است؟ شامل چه چیزی می‌شود؟ لطفاً اشیا یا افراد را شرح دهید. اطلاعاتی که به راحتی قابل مشاهده هستند را صرفه‌نظر کنید. اگر چیزی در تصویر غیر طبیعی به نظر می‌رسد آن را شرح دهید.</string>
</resources>

View file

@ -41,7 +41,7 @@
<string name="login_failed_username">ناقابلِ داخل ٿيڻ - براءِ مھرباني پنھنجو يُوزرنانءُ چڪاسيو</string>
<string name="login_failed_password">ناقابل داخل ٿيڻ - براءِ مھرباني پنھنجو ڳجھولفظ چڪاسيو</string>
<string name="login_failed_throttled">ھيڪانديون ناڪام ڪوششون. براءِ مھرباني ڪجھ منٽن کانپوءِ ٻيھر ڪوشش ڪريو.</string>
<string name="login_failed_blocked">افسوس، ھي يوزر العام تي بندشيل آھي</string>
<string name="login_failed_blocked">افسوس، ھي واھپ العام تي بندشيل آھي</string>
<string name="login_failed_generic">داخل ٿيڻ ناڪام</string>
<string name="share_upload_button">چاڙھيو</string>
<string name="multiple_share_base_title">ھن سيٽ کي نالو ڏيو</string>

View file

@ -0,0 +1,25 @@
package fr.free.nrw.commons;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MediaTest {
@Test
public void displayTitleShouldStripExtension() {
Media m = new Media("File:Example.jpg");
assertThat(m.getDisplayTitle(), is("Example"));
}
@Test
public void displayTitleShouldUseSpaceForUnderscore() {
Media m = new Media("File:Example 1_2.jpg");
assertThat(m.getDisplayTitle(), is("Example 1 2"));
}
}

View file

@ -0,0 +1,44 @@
package fr.free.nrw.commons;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.nearby.NearbyBaseMarker;
import fr.free.nrw.commons.nearby.Place;
import static fr.free.nrw.commons.nearby.NearbyController.loadAttractionsFromLocationToBaseMarkerOptions;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class NearbyControllerTest {
@Test
public void testNullAttractions() {
LatLng location = new LatLng(0, 0, 0);
List<NearbyBaseMarker> options = loadAttractionsFromLocationToBaseMarkerOptions(
location, null, RuntimeEnvironment.application);
assertThat(options.size(), is(0));
}
@Test
public void testEmptyList() {
LatLng location = new LatLng(0, 0, 0);
List<Place> emptyList = new ArrayList<>();
List<NearbyBaseMarker> options = loadAttractionsFromLocationToBaseMarkerOptions(
location, emptyList, RuntimeEnvironment.application);
assertThat(options.size(), is(0));
}
}

View file

@ -0,0 +1,70 @@
package fr.free.nrw.commons;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.net.URLEncoder;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class PageTitleTest {
@Test
public void displayTextShouldNotBeUnderscored() {
assertThat(new PageTitle("Ex_1 ").getDisplayText(),
is("Ex 1"));
}
@Test
public void moreThanTwoColons() {
assertThat(new PageTitle("File:sample:a.jpg").getPrefixedText(),
is("File:Sample:a.jpg"));
}
@Test
public void getTextShouldReturnWithoutNamespace() {
assertThat(new PageTitle("File:sample.jpg").getText(),
is("Sample.jpg"));
}
@Test
public void capitalizeNameAfterNamespace() {
assertThat(new PageTitle("File:sample.jpg").getPrefixedText(),
is("File:Sample.jpg"));
}
@Test
public void prefixedTextShouldBeUnderscored() {
assertThat(new PageTitle("Ex 1 ").getPrefixedText(),
is("Ex_1"));
}
@Test
public void getMobileUriForTest() {
assertThat(new PageTitle("Test").getMobileUri().toString(),
is(BuildConfig.MOBILE_HOME_URL + "Test"));
}
@Test
public void spaceBecomesUnderscoreInUri() {
assertThat(new PageTitle("File:Ex 1.jpg").getCanonicalUri().toString(),
is(BuildConfig.HOME_URL + "File:Ex_1.jpg"));
}
@Test
public void leaveSubpageNamesUncapitalizedInUri() {
assertThat(new PageTitle("User:Ex/subpage").getCanonicalUri().toString(),
is(BuildConfig.HOME_URL + "User:Ex/subpage"));
}
@Test
public void unicodeUri() throws Throwable {
assertThat(new PageTitle("User:例").getCanonicalUri().toString(),
is(BuildConfig.HOME_URL + "User:" + URLEncoder.encode("", "utf-8")));
}
}

41
dependency-injection.md Normal file
View file

@ -0,0 +1,41 @@
## Overview
At its core, dependency injection is just the principle of `"tell, dont ask"` put into practice; for instance, if a class needs to use the `MediaWikiApi`, it should be handed an instance of the classs rather than reaching out to get it. This has the effect of decoupling code, making it easier to test and reuse.
## Dependency Injection in the Commons app
We use Dagger 2 as our dependency injection engine. Dagger is a fully static, compile-time dependency injection framework for both Java and Android. Dagger aims to address many of the development and performance issues that have plagued reflection-based solutions that came before it, but it does come at something of a cost in complexity.
For more information about Dagger, take a look at the [Dagger user guide](https://google.github.io/dagger/users-guide.html).
## Dagger configuration in the Commons app
The top level `CommonsApplicationComponent` pulls together configuration for injection across the app. The most important files to understand
- if you need to add a new Activity, look at `ActivityBuilderModule` and copy how injection is configured. The `BaseActivity` class will take care of the rest.
- if you are adding a new Fragment, look at `FragmentBuilderModule`
- if you are adding a new ContentProvider, look at `ContentProviderBuilderModule`
- if you are adding a new Service, look at `ServiceBuilderModule`
- other dependencies are configured in `CommonsApplicationModule`
## "Provider" methods
Dagger will resolve the method arguments on provider methods in a module (or the constructor arguments when annotated with `@Inject`) and build the objects accordingly - either by calling another provider method or by looking for a constructor on a class that has the `@Inject` annotation. Dagger takes care of managing singletons, just annotate with the `@Singleton` annotation. For instance,
```java
@Provides
@Singleton
public SessionManager providesSessionManager(MediaWikiApi mediaWikiApi) {
return new SessionManager(application, mediaWikiApi);
}
```
If your code injects an interface (in this case, `MediaWikiApi`) then Dagger needs to know which concrete class to use. This comes by way of a provider method:
```java
@Provides
@Singleton
public MediaWikiApi provideMediaWikiApi() {
return new ApacheHttpClientMediaWikiApi(BuildConfig.WIKIMEDIA_API_HOST);
}
```