mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Fixes 4544 : Language selection: history (#4880)
* Xml changes * Content provider created * Database setup done * Database setup revised * Database setup revised * SettingsFragment finished * SettingsFragment finished * UploadMediaDetailFragment updated * UploadMediaDetailFragment updated * Java docs * Test fixed * Test added * Test added * Test updated * More tests added
This commit is contained in:
parent
85bdcd5a7a
commit
4194409cd2
20 changed files with 1312 additions and 9 deletions
|
|
@ -259,6 +259,7 @@ android {
|
|||
buildConfigField "String", "MODIFICATION_AUTHORITY", "\"fr.free.nrw.commons.modifications.contentprovider\""
|
||||
buildConfigField "String", "CATEGORY_AUTHORITY", "\"fr.free.nrw.commons.categories.contentprovider\""
|
||||
buildConfigField "String", "RECENT_SEARCH_AUTHORITY", "\"fr.free.nrw.commons.explore.recentsearches.contentprovider\""
|
||||
buildConfigField "String", "RECENT_LANGUAGE_AUTHORITY", "\"fr.free.nrw.commons.recentlanguages.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.locations.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.items.contentprovider\""
|
||||
|
|
@ -294,6 +295,7 @@ android {
|
|||
buildConfigField "String", "MODIFICATION_AUTHORITY", "\"fr.free.nrw.commons.beta.modifications.contentprovider\""
|
||||
buildConfigField "String", "CATEGORY_AUTHORITY", "\"fr.free.nrw.commons.beta.categories.contentprovider\""
|
||||
buildConfigField "String", "RECENT_SEARCH_AUTHORITY", "\"fr.free.nrw.commons.beta.explore.recentsearches.contentprovider\""
|
||||
buildConfigField "String", "RECENT_LANGUAGE_AUTHORITY", "\"fr.free.nrw.commons.beta.recentlanguages.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.locations.contentprovider\""
|
||||
buildConfigField "String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.items.contentprovider\""
|
||||
|
|
|
|||
|
|
@ -194,6 +194,13 @@
|
|||
android:label="@string/provider_searches"
|
||||
android:syncable="false" />
|
||||
|
||||
<provider
|
||||
android:name=".recentlanguages.RecentLanguagesContentProvider"
|
||||
android:authorities="${applicationId}.recentlanguages.contentprovider"
|
||||
android:exported="false"
|
||||
android:label="@string/provider_recent_languages"
|
||||
android:syncable="false" />
|
||||
|
||||
<provider
|
||||
android:name=".bookmarks.pictures.BookmarkPicturesContentProvider"
|
||||
android:authorities="${applicationId}.bookmarks.contentprovider"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
|
|||
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao;
|
||||
import fr.free.nrw.commons.category.CategoryDao;
|
||||
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
|
||||
|
||||
public class DBOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
|
|
@ -34,6 +35,7 @@ public class DBOpenHelper extends SQLiteOpenHelper {
|
|||
BookmarkLocationsDao.Table.onCreate(sqLiteDatabase);
|
||||
BookmarkItemsDao.Table.onCreate(sqLiteDatabase);
|
||||
RecentSearchesDao.Table.onCreate(sqLiteDatabase);
|
||||
RecentLanguagesDao.Table.onCreate(sqLiteDatabase);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -43,6 +45,7 @@ public class DBOpenHelper extends SQLiteOpenHelper {
|
|||
BookmarkLocationsDao.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
BookmarkItemsDao.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
RecentSearchesDao.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
RecentLanguagesDao.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
deleteTable(sqLiteDatabase,CONTRIBUTIONS_TABLE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,19 @@ public class CommonsApplicationModule {
|
|||
return context.getContentResolver().acquireContentProviderClient(BuildConfig.BOOKMARK_ITEMS_AUTHORITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to provide instance of RecentLanguagesContentProvider
|
||||
* which provides content of recent used languages from database
|
||||
* @param context Context
|
||||
* @return returns RecentLanguagesContentProvider
|
||||
*/
|
||||
@Provides
|
||||
@Named("recent_languages")
|
||||
public ContentProviderClient provideRecentLanguagesContentProviderClient(final Context context) {
|
||||
return context.getContentResolver()
|
||||
.acquireContentProviderClient(BuildConfig.RECENT_LANGUAGE_AUTHORITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a Json store instance(JsonKvStore) which keeps
|
||||
* the provided Gson in it's instance
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsContentProvider;
|
|||
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider;
|
||||
import fr.free.nrw.commons.category.CategoryContentProvider;
|
||||
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesContentProvider;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesContentProvider;
|
||||
|
||||
/**
|
||||
* This Class Represents the Module for dependency injection (using dagger)
|
||||
|
|
@ -31,4 +32,7 @@ public abstract class ContentProviderBuilderModule {
|
|||
|
||||
@ContributesAndroidInjector
|
||||
abstract BookmarkItemsContentProvider bindBookmarkItemContentProvider();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract RecentLanguagesContentProvider bindRecentLanguagesContentProvider();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
package fr.free.nrw.commons.recentlanguages
|
||||
|
||||
data class Language(val languageName: String, val languageCode: String)
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package fr.free.nrw.commons.recentlanguages
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.utils.LangCodeUtils
|
||||
import kotlinx.android.synthetic.main.row_item_languages_spinner.view.*
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import java.util.HashMap
|
||||
|
||||
/**
|
||||
* Array adapter for recent languages
|
||||
*/
|
||||
class RecentLanguagesAdapter constructor(
|
||||
context: Context,
|
||||
var recentLanguages: List<Language>,
|
||||
private val selectedLanguages: HashMap<*, String>
|
||||
) : ArrayAdapter<String?>(context, R.layout.row_item_languages_spinner) {
|
||||
|
||||
/**
|
||||
* Selected language code in UploadMediaDetailAdapter
|
||||
* Used for marking selected ones
|
||||
*/
|
||||
var selectedLangCode = ""
|
||||
|
||||
override fun isEnabled(position: Int) = recentLanguages[position].languageCode.let {
|
||||
it.isNotEmpty() && !selectedLanguages.containsValue(it) && it != selectedLangCode
|
||||
}
|
||||
|
||||
override fun getCount() = recentLanguages.size
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val rowView: View = convertView
|
||||
?: LayoutInflater.from(context)
|
||||
.inflate(R.layout.row_item_languages_spinner, parent, false)
|
||||
val languageCode = recentLanguages[position].languageCode
|
||||
val languageName = recentLanguages[position].languageName
|
||||
rowView.tv_language.let {
|
||||
it.isEnabled = isEnabled(position)
|
||||
if (languageCode.isEmpty()) {
|
||||
it.text = StringUtils.capitalize(languageName)
|
||||
it.textAlignment = View.TEXT_ALIGNMENT_CENTER
|
||||
} else {
|
||||
it.text =
|
||||
"${StringUtils.capitalize(languageName)}" +
|
||||
" [${LangCodeUtils.fixLanguageCode(languageCode)}]"
|
||||
}
|
||||
}
|
||||
return rowView
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides code of a language from recent languages for a specific position
|
||||
*/
|
||||
fun getLanguageCode(position: Int): String {
|
||||
return recentLanguages[position].languageCode
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides name of a language from recent languages for a specific position
|
||||
*/
|
||||
fun getLanguageName(position: Int): String {
|
||||
return recentLanguages[position].languageName
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package fr.free.nrw.commons.recentlanguages;
|
||||
|
||||
import static fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.COLUMN_NAME;
|
||||
import static fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.TABLE_NAME;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.data.DBOpenHelper;
|
||||
import fr.free.nrw.commons.di.CommonsDaggerContentProvider;
|
||||
import javax.inject.Inject;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Content provider of recently used languages
|
||||
*/
|
||||
public class RecentLanguagesContentProvider extends CommonsDaggerContentProvider {
|
||||
|
||||
private static final String BASE_PATH = "recent_languages";
|
||||
public static final Uri BASE_URI =
|
||||
Uri.parse("content://" + BuildConfig.RECENT_LANGUAGE_AUTHORITY + "/" + BASE_PATH);
|
||||
|
||||
|
||||
/**
|
||||
* Append language code to the base uri
|
||||
* @param languageCode Code of a language
|
||||
*/
|
||||
public static Uri uriForCode(final String languageCode) {
|
||||
return Uri.parse(BASE_URI + "/" + languageCode);
|
||||
}
|
||||
|
||||
@Inject
|
||||
DBOpenHelper dbOpenHelper;
|
||||
|
||||
@Override
|
||||
public String getType(@NonNull final Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the SQLite database for the recently used languages
|
||||
* @param uri : contains the uri for recently used languages
|
||||
* @param projection : contains the all fields of the table
|
||||
* @param selection : handles Where
|
||||
* @param selectionArgs : the condition of Where clause
|
||||
* @param sortOrder : ascending or descending
|
||||
*/
|
||||
@Override
|
||||
public Cursor query(@NonNull final Uri uri, final String[] projection, final String selection,
|
||||
final String[] selectionArgs, final String sortOrder) {
|
||||
final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
|
||||
queryBuilder.setTables(TABLE_NAME);
|
||||
final SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
|
||||
final Cursor cursor = queryBuilder.query(db, projection, selection,
|
||||
selectionArgs, null, null, sortOrder);
|
||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the update query of local SQLite Database
|
||||
* @param uri : contains the uri for recently used languages
|
||||
* @param contentValues : new values to be entered to db
|
||||
* @param selection : handles Where
|
||||
* @param selectionArgs : the condition of Where clause
|
||||
*/
|
||||
@Override
|
||||
public int update(@NonNull final Uri uri, final ContentValues contentValues,
|
||||
final String selection, final String[] selectionArgs) {
|
||||
final SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
|
||||
final int rowsUpdated;
|
||||
if (TextUtils.isEmpty(selection)) {
|
||||
final int id = Integer.parseInt(uri.getLastPathSegment());
|
||||
rowsUpdated = sqlDB.update(TABLE_NAME,
|
||||
contentValues,
|
||||
COLUMN_NAME + " = ?",
|
||||
new String[]{String.valueOf(id)});
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Parameter `selection` should be empty when updating an ID");
|
||||
}
|
||||
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return rowsUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the insertion of new recently used languages record to local SQLite Database
|
||||
* @param uri : contains the uri for recently used languages
|
||||
* @param contentValues : new values to be entered to db
|
||||
*/
|
||||
@Override
|
||||
public Uri insert(@NonNull final Uri uri, final ContentValues contentValues) {
|
||||
final SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
|
||||
final long id = sqlDB.insert(TABLE_NAME, null, contentValues);
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return Uri.parse(BASE_URI + "/" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the deletion of new recently used languages record to local SQLite Database
|
||||
* @param uri : contains the uri for recently used languages
|
||||
*/
|
||||
@Override
|
||||
public int delete(@NonNull final Uri uri, final String s, final String[] strings) {
|
||||
final int rows;
|
||||
final SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
|
||||
Timber.d("Deleting recently used language %s", uri.getLastPathSegment());
|
||||
rows = db.delete(
|
||||
TABLE_NAME,
|
||||
"language_code = ?",
|
||||
new String[]{uri.getLastPathSegment()}
|
||||
);
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
package fr.free.nrw.commons.recentlanguages;
|
||||
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.NonNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Handles database operations for recently used languages
|
||||
*/
|
||||
@Singleton
|
||||
public class RecentLanguagesDao {
|
||||
|
||||
private final Provider<ContentProviderClient> clientProvider;
|
||||
|
||||
@Inject
|
||||
public RecentLanguagesDao
|
||||
(@Named("recent_languages") final Provider<ContentProviderClient> clientProvider) {
|
||||
this.clientProvider = clientProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all persisted recently used languages on database
|
||||
* @return list of recently used languages
|
||||
*/
|
||||
public List<Language> getRecentLanguages() {
|
||||
final List<Language> languages = new ArrayList<>();
|
||||
final ContentProviderClient db = clientProvider.get();
|
||||
try (final Cursor cursor = db.query(
|
||||
RecentLanguagesContentProvider.BASE_URI,
|
||||
RecentLanguagesDao.Table.ALL_FIELDS,
|
||||
null,
|
||||
new String[]{},
|
||||
null)) {
|
||||
if(cursor != null && cursor.moveToLast()) {
|
||||
do {
|
||||
languages.add(fromCursor(cursor));
|
||||
} while (cursor.moveToPrevious());
|
||||
}
|
||||
} catch (final RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
db.release();
|
||||
}
|
||||
return languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Language to database
|
||||
* @param language : Language to add
|
||||
*/
|
||||
public void addRecentLanguage(final Language language) {
|
||||
final ContentProviderClient db = clientProvider.get();
|
||||
try {
|
||||
db.insert(RecentLanguagesContentProvider.BASE_URI, toContentValues(language));
|
||||
} catch (final RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
db.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a language from database
|
||||
* @param languageCode : code of the Language to delete
|
||||
*/
|
||||
public void deleteRecentLanguage(final String languageCode) {
|
||||
final ContentProviderClient db = clientProvider.get();
|
||||
try {
|
||||
db.delete(RecentLanguagesContentProvider.uriForCode(languageCode), null, null);
|
||||
} catch (final RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
db.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a language from database based on its name
|
||||
* @param languageCode : code of the Language to find
|
||||
* @return boolean : is language in database ?
|
||||
*/
|
||||
public boolean findRecentLanguage(final String languageCode) {
|
||||
if (languageCode == null) { //Avoiding NPE's
|
||||
return false;
|
||||
}
|
||||
final ContentProviderClient db = clientProvider.get();
|
||||
try (final Cursor cursor = db.query(
|
||||
RecentLanguagesContentProvider.BASE_URI,
|
||||
RecentLanguagesDao.Table.ALL_FIELDS,
|
||||
Table.COLUMN_CODE + "=?",
|
||||
new String[]{languageCode},
|
||||
null
|
||||
)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return true;
|
||||
}
|
||||
} catch (final RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
db.release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* It creates an Recent Language object from data stored in the SQLite DB by using cursor
|
||||
* @param cursor cursor
|
||||
* @return Language object
|
||||
*/
|
||||
@NonNull
|
||||
Language fromCursor(final Cursor cursor) {
|
||||
// Hardcoding column positions!
|
||||
final String languageName = cursor.getString(cursor.getColumnIndex(Table.COLUMN_NAME));
|
||||
final String languageCode = cursor.getString(cursor.getColumnIndex(Table.COLUMN_CODE));
|
||||
return new Language(languageName, languageCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes data from Language and create a content value object
|
||||
* @param recentLanguage recently used language
|
||||
* @return ContentValues
|
||||
*/
|
||||
private ContentValues toContentValues(final Language recentLanguage) {
|
||||
final ContentValues cv = new ContentValues();
|
||||
cv.put(Table.COLUMN_NAME, recentLanguage.getLanguageName());
|
||||
cv.put(Table.COLUMN_CODE, recentLanguage.getLanguageCode());
|
||||
return cv;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class contains the database table architecture for recently used languages,
|
||||
* It also contains queries and logic necessary to the create, update, delete this table.
|
||||
*/
|
||||
public static final class Table {
|
||||
public static final String TABLE_NAME = "recent_languages";
|
||||
static final String COLUMN_NAME = "language_name";
|
||||
static final String COLUMN_CODE = "language_code";
|
||||
|
||||
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
|
||||
public static final String[] ALL_FIELDS = {
|
||||
COLUMN_NAME,
|
||||
COLUMN_CODE
|
||||
};
|
||||
|
||||
static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME;
|
||||
|
||||
static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
|
||||
+ COLUMN_NAME + " STRING,"
|
||||
+ COLUMN_CODE + " STRING PRIMARY KEY"
|
||||
+ ");";
|
||||
|
||||
/**
|
||||
* This method creates a LanguagesTable in SQLiteDatabase
|
||||
* @param db SQLiteDatabase
|
||||
*/
|
||||
public static void onCreate(final SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_TABLE_STATEMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deletes LanguagesTable from SQLiteDatabase
|
||||
* @param db SQLiteDatabase
|
||||
*/
|
||||
public static void onDelete(final SQLiteDatabase db) {
|
||||
db.execSQL(DROP_TABLE_STATEMENT);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called on migrating from a older version to a newer version
|
||||
* @param db SQLiteDatabase
|
||||
* @param from Version from which we are migrating
|
||||
* @param to Version to which we are migrating
|
||||
*/
|
||||
public static void onUpdate(final SQLiteDatabase db, int from, final int to) {
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
if (from < 6) {
|
||||
// doesn't exist yet
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 6) {
|
||||
// table added in version 7
|
||||
onCreate(db);
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 7) {
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
|
@ -18,6 +17,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.MultiSelectListPreference;
|
||||
import androidx.preference.Preference;
|
||||
|
|
@ -39,10 +39,12 @@ import fr.free.nrw.commons.contributions.MainActivity;
|
|||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.logging.CommonsLogSender;
|
||||
import fr.free.nrw.commons.recentlanguages.Language;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
|
||||
import fr.free.nrw.commons.upload.LanguagesAdapter;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -60,10 +62,16 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
@Inject
|
||||
CommonsLogSender commonsLogSender;
|
||||
|
||||
@Inject
|
||||
RecentLanguagesDao recentLanguagesDao;
|
||||
|
||||
private ListPreference themeListPreference;
|
||||
private Preference descriptionLanguageListPreference;
|
||||
private Preference appUiLanguageListPreference;
|
||||
private String keyLanguageListPreference;
|
||||
private TextView recentLanguagesTextView;
|
||||
private View separator;
|
||||
private ListView languageHistoryListView;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
|
|
@ -211,6 +219,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
|
||||
// Gets current language code from shared preferences
|
||||
final String languageCode = getCurrentLanguageCode(keyListPreference);
|
||||
final List<Language> recentLanguages = recentLanguagesDao.getRecentLanguages();
|
||||
HashMap<Integer, String> selectedLanguages = new HashMap<>();
|
||||
|
||||
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||
|
|
@ -246,6 +255,11 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
|
||||
EditText editText = dialog.findViewById(R.id.search_language);
|
||||
ListView listView = dialog.findViewById(R.id.language_list);
|
||||
languageHistoryListView = dialog.findViewById(R.id.language_history_list);
|
||||
recentLanguagesTextView = dialog.findViewById(R.id.recent_searches);
|
||||
separator = dialog.findViewById(R.id.separator);
|
||||
|
||||
setUpRecentLanguagesSection(recentLanguages, selectedLanguages);
|
||||
|
||||
listView.setAdapter(languagesAdapter);
|
||||
|
||||
|
|
@ -253,7 +267,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
|
||||
int i2) {
|
||||
|
||||
hideRecentLanguagesSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -268,12 +282,23 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
});
|
||||
|
||||
languageHistoryListView.setOnItemClickListener((adapterView, view, position, id) -> {
|
||||
onRecentLanguageClicked(keyListPreference, dialog, adapterView, position);
|
||||
});
|
||||
|
||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i,
|
||||
long l) {
|
||||
String languageCode = ((LanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageCode(i);
|
||||
final String languageName = ((LanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageName(i);
|
||||
final boolean isExists = recentLanguagesDao.findRecentLanguage(languageCode);
|
||||
if (isExists) {
|
||||
recentLanguagesDao.deleteRecentLanguage(languageCode);
|
||||
}
|
||||
recentLanguagesDao.addRecentLanguage(new Language(languageName, languageCode));
|
||||
saveLanguageValue(languageCode, keyListPreference);
|
||||
Locale defLocale = new Locale(languageCode);
|
||||
if(keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||
|
|
@ -293,6 +318,75 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
dialogInterface -> languagesAdapter.getFilter().filter(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up recent languages section
|
||||
*
|
||||
* @param recentLanguages recently used languages
|
||||
* @param selectedLanguages selected languages
|
||||
*/
|
||||
private void setUpRecentLanguagesSection(List<Language> recentLanguages,
|
||||
HashMap<Integer, String> selectedLanguages) {
|
||||
if (recentLanguages.isEmpty()) {
|
||||
languageHistoryListView.setVisibility(View.GONE);
|
||||
recentLanguagesTextView.setVisibility(View.GONE);
|
||||
separator.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (recentLanguages.size() > 5) {
|
||||
for (int i = recentLanguages.size()-1; i >=5; i--) {
|
||||
recentLanguagesDao
|
||||
.deleteRecentLanguage(recentLanguages.get(i).getLanguageCode());
|
||||
}
|
||||
}
|
||||
languageHistoryListView.setVisibility(View.VISIBLE);
|
||||
recentLanguagesTextView.setVisibility(View.VISIBLE);
|
||||
separator.setVisibility(View.VISIBLE);
|
||||
final RecentLanguagesAdapter recentLanguagesAdapter
|
||||
= new RecentLanguagesAdapter(
|
||||
getActivity(),
|
||||
recentLanguagesDao.getRecentLanguages(),
|
||||
selectedLanguages);
|
||||
languageHistoryListView.setAdapter(recentLanguagesAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles click event for recent language section
|
||||
*/
|
||||
private void onRecentLanguageClicked(String keyListPreference, Dialog dialog, AdapterView<?> adapterView,
|
||||
int position) {
|
||||
final String recentLanguageCode = ((RecentLanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageCode(position);
|
||||
final String recentLanguageName = ((RecentLanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageName(position);
|
||||
final boolean isExists = recentLanguagesDao.findRecentLanguage(recentLanguageCode);
|
||||
if (isExists) {
|
||||
recentLanguagesDao.deleteRecentLanguage(recentLanguageCode);
|
||||
}
|
||||
recentLanguagesDao.addRecentLanguage(
|
||||
new Language(recentLanguageName, recentLanguageCode));
|
||||
saveLanguageValue(recentLanguageCode, keyListPreference);
|
||||
final Locale defLocale = new Locale(recentLanguageCode);
|
||||
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||
appUiLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||
setLocale(Objects.requireNonNull(getActivity()), recentLanguageCode);
|
||||
getActivity().recreate();
|
||||
final Intent intent = new Intent(getActivity(), MainActivity.class);
|
||||
startActivity(intent);
|
||||
} else {
|
||||
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||
}
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the section of recent languages
|
||||
*/
|
||||
private void hideRecentLanguagesSection() {
|
||||
languageHistoryListView.setVisibility(View.GONE);
|
||||
recentLanguagesTextView.setVisibility(View.GONE);
|
||||
separator.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changing the default app language with selected one and save it to SharedPreferences
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -74,6 +74,13 @@ class LanguagesAdapter constructor(
|
|||
return languageCodesList[position]
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides name of a language from languages for a specific position
|
||||
*/
|
||||
fun getLanguageName(position: Int): String {
|
||||
return languageNamesList[position]
|
||||
}
|
||||
|
||||
fun getIndexOfUserDefaultLocale(context: Context): Int {
|
||||
return language.codes.indexOf(context.locale.language)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
|
|
@ -21,26 +22,39 @@ import butterknife.BindView;
|
|||
import butterknife.ButterKnife;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.MainActivity;
|
||||
import fr.free.nrw.commons.recentlanguages.Language;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
|
||||
import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText;
|
||||
import fr.free.nrw.commons.utils.AbstractTextWatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import javax.inject.Inject;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDetailAdapter.ViewHolder> {
|
||||
|
||||
RecentLanguagesDao recentLanguagesDao;
|
||||
|
||||
private List<UploadMediaDetail> uploadMediaDetails;
|
||||
private Callback callback;
|
||||
private EventListener eventListener;
|
||||
|
||||
private HashMap<Integer, String> selectedLanguages;
|
||||
private final String savedLanguageValue;
|
||||
private TextView recentLanguagesTextView;
|
||||
private View separator;
|
||||
private ListView languageHistoryListView;
|
||||
|
||||
public UploadMediaDetailAdapter(String savedLanguageValue) {
|
||||
public UploadMediaDetailAdapter(String savedLanguageValue, RecentLanguagesDao recentLanguagesDao) {
|
||||
uploadMediaDetails = new ArrayList<>();
|
||||
selectedLanguages = new HashMap<>();
|
||||
this.savedLanguageValue = savedLanguageValue;
|
||||
this.recentLanguagesDao = recentLanguagesDao;
|
||||
}
|
||||
|
||||
public UploadMediaDetailAdapter(final String savedLanguageValue,
|
||||
|
|
@ -183,6 +197,8 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
|||
|
||||
private void initLanguage(int position, UploadMediaDetail description) {
|
||||
|
||||
final List<Language> recentLanguages = recentLanguagesDao.getRecentLanguages();
|
||||
|
||||
LanguagesAdapter languagesAdapter = new LanguagesAdapter(
|
||||
descriptionLanguages.getContext(),
|
||||
selectedLanguages
|
||||
|
|
@ -200,6 +216,10 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
|||
|
||||
EditText editText = dialog.findViewById(R.id.search_language);
|
||||
ListView listView = dialog.findViewById(R.id.language_list);
|
||||
languageHistoryListView = dialog.findViewById(R.id.language_history_list);
|
||||
recentLanguagesTextView = dialog.findViewById(R.id.recent_searches);
|
||||
separator = dialog.findViewById(R.id.separator);
|
||||
setUpRecentLanguagesSection(recentLanguages);
|
||||
|
||||
listView.setAdapter(languagesAdapter);
|
||||
|
||||
|
|
@ -207,7 +227,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
|||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
|
||||
int i2) {
|
||||
|
||||
hideRecentLanguagesSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -222,6 +242,10 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
|||
}
|
||||
});
|
||||
|
||||
languageHistoryListView.setOnItemClickListener((adapterView, view1, position, id) -> {
|
||||
onRecentLanguageClicked(dialog, adapterView, position, description);
|
||||
});
|
||||
|
||||
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i,
|
||||
|
|
@ -230,6 +254,16 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
|||
String languageCode = ((LanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageCode(i);
|
||||
description.setLanguageCode(languageCode);
|
||||
final String languageName
|
||||
= ((LanguagesAdapter) adapterView.getAdapter()).getLanguageName(i);
|
||||
final boolean isExists
|
||||
= recentLanguagesDao.findRecentLanguage(languageCode);
|
||||
if (isExists) {
|
||||
recentLanguagesDao.deleteRecentLanguage(languageCode);
|
||||
}
|
||||
recentLanguagesDao
|
||||
.addRecentLanguage(new Language(languageName, languageCode));
|
||||
|
||||
selectedLanguages.remove(position);
|
||||
selectedLanguages.put(position, languageCode);
|
||||
((LanguagesAdapter) adapterView
|
||||
|
|
@ -300,6 +334,70 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
|||
selectedLanguages.put(position, description.getLanguageCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles click event for recent language section
|
||||
*/
|
||||
private void onRecentLanguageClicked(final Dialog dialog, final AdapterView<?> adapterView,
|
||||
final int position, final UploadMediaDetail description) {
|
||||
description.setSelectedLanguageIndex(position);
|
||||
final String languageCode = ((RecentLanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageCode(position);
|
||||
description.setLanguageCode(languageCode);
|
||||
final String languageName = ((RecentLanguagesAdapter) adapterView.getAdapter())
|
||||
.getLanguageName(position);
|
||||
final boolean isExists = recentLanguagesDao.findRecentLanguage(languageCode);
|
||||
if (isExists) {
|
||||
recentLanguagesDao.deleteRecentLanguage(languageCode);
|
||||
}
|
||||
recentLanguagesDao.addRecentLanguage(new Language(languageName, languageCode));
|
||||
|
||||
selectedLanguages.remove(position);
|
||||
selectedLanguages.put(position, languageCode);
|
||||
((RecentLanguagesAdapter) adapterView
|
||||
.getAdapter()).setSelectedLangCode(languageCode);
|
||||
Timber.d("Description language code is: %s", languageCode);
|
||||
descriptionLanguages.setText(languageCode);
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides recent languages section
|
||||
*/
|
||||
private void hideRecentLanguagesSection() {
|
||||
languageHistoryListView.setVisibility(View.GONE);
|
||||
recentLanguagesTextView.setVisibility(View.GONE);
|
||||
separator.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up recent languages section
|
||||
*
|
||||
* @param recentLanguages recently used languages
|
||||
*/
|
||||
private void setUpRecentLanguagesSection(final List<Language> recentLanguages) {
|
||||
if (recentLanguages.isEmpty()) {
|
||||
languageHistoryListView.setVisibility(View.GONE);
|
||||
recentLanguagesTextView.setVisibility(View.GONE);
|
||||
separator.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (recentLanguages.size() > 5) {
|
||||
for (int i = recentLanguages.size()-1; i >=5; i--) {
|
||||
recentLanguagesDao.deleteRecentLanguage(recentLanguages.get(i)
|
||||
.getLanguageCode());
|
||||
}
|
||||
}
|
||||
languageHistoryListView.setVisibility(View.VISIBLE);
|
||||
recentLanguagesTextView.setVisibility(View.VISIBLE);
|
||||
separator.setVisibility(View.VISIBLE);
|
||||
final RecentLanguagesAdapter recentLanguagesAdapter
|
||||
= new RecentLanguagesAdapter(
|
||||
descriptionLanguages.getContext(),
|
||||
recentLanguagesDao.getRecentLanguages(),
|
||||
selectedLanguages);
|
||||
languageHistoryListView.setAdapter(recentLanguagesAdapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import fr.free.nrw.commons.R;
|
|||
import fr.free.nrw.commons.filepicker.UploadableFile;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import fr.free.nrw.commons.upload.ImageCoordinates;
|
||||
import fr.free.nrw.commons.upload.SimilarImageDialogFragment;
|
||||
|
|
@ -90,6 +91,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
|
|||
@Named("default_preferences")
|
||||
JsonKvStore defaultKvStore;
|
||||
|
||||
@Inject
|
||||
RecentLanguagesDao recentLanguagesDao;
|
||||
|
||||
private UploadableFile uploadableFile;
|
||||
private Place place;
|
||||
|
||||
|
|
@ -201,7 +205,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
|
|||
* init the description recycler veiw and caption recyclerview
|
||||
*/
|
||||
private void initRecyclerView() {
|
||||
uploadMediaDetailAdapter = new UploadMediaDetailAdapter(defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""));
|
||||
uploadMediaDetailAdapter = new UploadMediaDetailAdapter(defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao);
|
||||
uploadMediaDetailAdapter.setCallback(this::showInfoAlert);
|
||||
uploadMediaDetailAdapter.setEventListener(this);
|
||||
rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
|
|
|||
|
|
@ -18,6 +18,49 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"></EditText>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/recent_searches"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recent Searches"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_language"
|
||||
app:layout_constraintEnd_toEndOf="@+id/language_history_list"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ListView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:id="@+id/language_history_list"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/recent_searches"
|
||||
app:layout_constraintBottom_toTopOf="@id/separator"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/black"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/language_history_list" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/all_languages"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="All Languages"
|
||||
app:layout_constraintTop_toBottomOf="@id/separator"
|
||||
app:layout_constraintEnd_toEndOf="@+id/language_history_list"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ListView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
|
@ -26,6 +69,6 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search_language" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/all_languages" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -293,6 +293,7 @@
|
|||
<string name="title_activity_search">Search</string>
|
||||
<string name="search_recent_header">Recent searches:</string>
|
||||
<string name="provider_searches">Recently searched queries</string>
|
||||
<string name="provider_recent_languages">Recent language queries</string>
|
||||
<string name="error_loading_categories">Error occurred while loading categories.</string>
|
||||
<string name="error_loading_depictions">Error occurred while loading depictions.</string>
|
||||
<string name="search_tab_title_media">Media</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
package fr.free.nrw.commons.recentlanguages
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import kotlinx.android.synthetic.main.row_item_languages_spinner.view.*
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.LooperMode
|
||||
import java.lang.reflect.Field
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||
@LooperMode(LooperMode.Mode.PAUSED)
|
||||
class RecentLanguagesAdapterUnitTest {
|
||||
|
||||
private lateinit var adapter: RecentLanguagesAdapter
|
||||
private lateinit var languages: List<Language>
|
||||
|
||||
@Mock
|
||||
private lateinit var context: Context
|
||||
|
||||
@Mock
|
||||
private lateinit var viewGroup: ViewGroup
|
||||
|
||||
@Mock
|
||||
private lateinit var convertView: View
|
||||
|
||||
@Mock
|
||||
private lateinit var textView: TextView
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
languages = listOf(
|
||||
Language("English", "en"),
|
||||
Language("Bengali", "bn")
|
||||
)
|
||||
adapter = RecentLanguagesAdapter(context, languages, hashMapOf(1 to "en"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun checkAdapterNotNull() {
|
||||
Assert.assertNotNull(adapter)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testIsEnabled() {
|
||||
val list = languages
|
||||
val recentLanguagesAdapter: Field =
|
||||
RecentLanguagesAdapter::class.java.getDeclaredField("recentLanguages")
|
||||
recentLanguagesAdapter.isAccessible = true
|
||||
recentLanguagesAdapter.set(adapter, list)
|
||||
Assert.assertEquals(adapter.isEnabled(0), false)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testGetCount() {
|
||||
val list = languages
|
||||
val recentLanguagesAdapter: Field =
|
||||
RecentLanguagesAdapter::class.java.getDeclaredField("recentLanguages")
|
||||
recentLanguagesAdapter.isAccessible = true
|
||||
recentLanguagesAdapter.set(adapter, list)
|
||||
Assert.assertEquals(adapter.count, list.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testGetLanguageName() {
|
||||
val list = languages
|
||||
val recentLanguagesAdapter: Field =
|
||||
RecentLanguagesAdapter::class.java.getDeclaredField("recentLanguages")
|
||||
recentLanguagesAdapter.isAccessible = true
|
||||
recentLanguagesAdapter.set(adapter, list)
|
||||
val languageName = list[0].languageName
|
||||
Assert.assertEquals(adapter.getLanguageName(0), languageName)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testGetView() {
|
||||
val list = languages
|
||||
whenever(convertView.tv_language).thenReturn(textView)
|
||||
val recentLanguagesAdapter: Field =
|
||||
RecentLanguagesAdapter::class.java.getDeclaredField("recentLanguages")
|
||||
recentLanguagesAdapter.isAccessible = true
|
||||
recentLanguagesAdapter.set(adapter, list)
|
||||
Assert.assertEquals(adapter.getView(0, convertView, viewGroup), convertView)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testGetLanguageCode() {
|
||||
val list = languages
|
||||
val recentLanguagesAdapter: Field =
|
||||
RecentLanguagesAdapter::class.java.getDeclaredField("recentLanguages")
|
||||
recentLanguagesAdapter.isAccessible = true
|
||||
recentLanguagesAdapter.set(adapter, list)
|
||||
val languageCode = list[0].languageCode
|
||||
Assert.assertEquals(adapter.getLanguageCode(0), languageCode)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package fr.free.nrw.commons.recentlanguages
|
||||
|
||||
import android.net.Uri
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.data.DBOpenHelper
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.powermock.reflect.Whitebox
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||
class RecentLanguagesContentProviderUnitTest {
|
||||
|
||||
private lateinit var contentProvider: RecentLanguagesContentProvider
|
||||
|
||||
@Mock
|
||||
lateinit var dbOpenHelper: DBOpenHelper
|
||||
|
||||
@Before
|
||||
fun setUp(){
|
||||
MockitoAnnotations.initMocks(this)
|
||||
contentProvider = RecentLanguagesContentProvider()
|
||||
Whitebox.setInternalState(contentProvider, "dbOpenHelper", dbOpenHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testGetType() {
|
||||
contentProvider.getType(mock(Uri::class.java))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
package fr.free.nrw.commons.recentlanguages
|
||||
|
||||
import android.content.ContentProviderClient
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.os.RemoteException
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao.Table.*
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||
class RecentLanguagesDaoUnitTest {
|
||||
|
||||
private val columns = arrayOf(
|
||||
COLUMN_NAME,
|
||||
COLUMN_CODE
|
||||
)
|
||||
|
||||
private val client: ContentProviderClient = mock()
|
||||
private val database: SQLiteDatabase = mock()
|
||||
private val captor = argumentCaptor<ContentValues>()
|
||||
|
||||
private lateinit var testObject: RecentLanguagesDao
|
||||
private lateinit var exampleLanguage: Language
|
||||
|
||||
/**
|
||||
* Set up Test Language and RecentLanguagesDao
|
||||
*/
|
||||
@Before
|
||||
fun setUp() {
|
||||
exampleLanguage = Language("English", "en")
|
||||
testObject = RecentLanguagesDao { client }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTable() {
|
||||
onCreate(database)
|
||||
verify(database).execSQL(CREATE_TABLE_STATEMENT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deleteTable() {
|
||||
onDelete(database)
|
||||
inOrder(database) {
|
||||
verify(database).execSQL(DROP_TABLE_STATEMENT)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createFromCursor() {
|
||||
createCursor(1).let { cursor ->
|
||||
cursor.moveToFirst()
|
||||
testObject.fromCursor(cursor).let {
|
||||
Assert.assertEquals("languageName", it.languageName)
|
||||
Assert.assertEquals("languageCode", it.languageCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetRecentLanguages() {
|
||||
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull()))
|
||||
.thenReturn(createCursor(14))
|
||||
|
||||
val result = testObject.recentLanguages
|
||||
|
||||
Assert.assertEquals(14, (result.size))
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException::class)
|
||||
fun getGetRecentLanguagesTranslatesExceptions() {
|
||||
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenThrow(
|
||||
RemoteException("")
|
||||
)
|
||||
testObject.recentLanguages
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getGetRecentLanguagesReturnsEmptyList_emptyCursor() {
|
||||
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull()))
|
||||
.thenReturn(createCursor(0))
|
||||
Assert.assertTrue(testObject.recentLanguages.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getGetRecentLanguagesReturnsEmptyList_nullCursor() {
|
||||
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenReturn(null)
|
||||
Assert.assertTrue(testObject.recentLanguages.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cursorsAreClosedAfterGetRecentLanguages() {
|
||||
val mockCursor: Cursor = mock()
|
||||
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenReturn(mockCursor)
|
||||
whenever(mockCursor.moveToFirst()).thenReturn(false)
|
||||
|
||||
testObject.recentLanguages
|
||||
|
||||
verify(mockCursor).close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findExistingLanguage() {
|
||||
whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(createCursor(1))
|
||||
Assert.assertTrue(testObject.findRecentLanguage(exampleLanguage.languageCode))
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException::class)
|
||||
fun findLanguageTranslatesExceptions() {
|
||||
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenThrow(
|
||||
RemoteException("")
|
||||
)
|
||||
testObject.findRecentLanguage(exampleLanguage.languageCode)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findNotExistingLanguageReturnsNull_emptyCursor() {
|
||||
whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(createCursor(0))
|
||||
Assert.assertFalse(testObject.findRecentLanguage(exampleLanguage.languageCode))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findNotExistingLanguageReturnsNull_nullCursor() {
|
||||
whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(null)
|
||||
Assert.assertFalse(testObject.findRecentLanguage(exampleLanguage.languageCode))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cursorsAreClosedAfterFindLanguageQuery() {
|
||||
val mockCursor: Cursor = mock()
|
||||
whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(mockCursor)
|
||||
whenever(mockCursor.moveToFirst()).thenReturn(false)
|
||||
|
||||
testObject.findRecentLanguage(exampleLanguage.languageCode)
|
||||
|
||||
verify(mockCursor).close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v1_to_v2() {
|
||||
onUpdate(database, 1, 2)
|
||||
// Table didnt exist before v7
|
||||
verifyZeroInteractions(database)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v2_to_v3() {
|
||||
onUpdate(database, 2, 3)
|
||||
// Table didnt exist before v7
|
||||
verifyZeroInteractions(database)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v3_to_v4() {
|
||||
onUpdate(database, 3, 4)
|
||||
// Table didnt exist before v7
|
||||
verifyZeroInteractions(database)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v4_to_v5() {
|
||||
onUpdate(database, 4, 5)
|
||||
// Table didnt exist before v7
|
||||
verifyZeroInteractions(database)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v5_to_v6() {
|
||||
onUpdate(database, 5, 6)
|
||||
// Table didnt exist before v7
|
||||
verifyZeroInteractions(database)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v6_to_v7() {
|
||||
onUpdate(database, 6, 7)
|
||||
verify(database).execSQL(CREATE_TABLE_STATEMENT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateTableVersionFrom_v7_to_v8() {
|
||||
onUpdate(database, 7, 8)
|
||||
// Table didnt change in version 8
|
||||
verifyZeroInteractions(database)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddNewLanguage() {
|
||||
testObject.addRecentLanguage(exampleLanguage)
|
||||
|
||||
verify(client).insert(eq(RecentLanguagesContentProvider.BASE_URI), captor.capture())
|
||||
captor.firstValue.let { cv ->
|
||||
Assert.assertEquals(2, cv.size())
|
||||
Assert.assertEquals(
|
||||
exampleLanguage.languageName,
|
||||
cv.getAsString(COLUMN_NAME)
|
||||
)
|
||||
Assert.assertEquals(
|
||||
exampleLanguage.languageCode,
|
||||
cv.getAsString(COLUMN_CODE)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeleteLanguage() {
|
||||
testObject.addRecentLanguage(exampleLanguage)
|
||||
testObject.deleteRecentLanguage(exampleLanguage.languageCode)
|
||||
}
|
||||
|
||||
private fun createCursor(rowCount: Int) = MatrixCursor(columns, rowCount).apply {
|
||||
|
||||
for (i in 0 until rowCount) {
|
||||
addRow(listOf("languageName", "languageCode"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,32 @@
|
|||
package fr.free.nrw.commons.settings
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.nhaarman.mockitokotlin2.any
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.recentlanguages.Language
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao
|
||||
import fr.free.nrw.commons.upload.UploadMediaDetailAdapter
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.powermock.reflect.Whitebox
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
|
|
@ -29,6 +45,21 @@ class SettingsFragmentUnitTests {
|
|||
private lateinit var layoutInflater: LayoutInflater
|
||||
private lateinit var context: Context
|
||||
|
||||
@Mock
|
||||
private lateinit var recentLanguagesDao: RecentLanguagesDao
|
||||
|
||||
@Mock
|
||||
private lateinit var recentLanguagesTextView: TextView
|
||||
|
||||
@Mock
|
||||
private lateinit var separator: View
|
||||
|
||||
@Mock
|
||||
private lateinit var languageHistoryListView: ListView
|
||||
|
||||
@Mock
|
||||
private lateinit var adapterView: AdapterView<RecentLanguagesAdapter>
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
|
@ -42,6 +73,13 @@ class SettingsFragmentUnitTests {
|
|||
fragmentTransaction.commitNowAllowingStateLoss()
|
||||
|
||||
layoutInflater = LayoutInflater.from(activity)
|
||||
|
||||
Whitebox.setInternalState(fragment, "recentLanguagesDao", recentLanguagesDao)
|
||||
Whitebox.setInternalState(fragment, "recentLanguagesTextView",
|
||||
recentLanguagesTextView)
|
||||
Whitebox.setInternalState(fragment, "separator", separator)
|
||||
Whitebox.setInternalState(fragment, "languageHistoryListView",
|
||||
languageHistoryListView)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -107,6 +145,41 @@ class SettingsFragmentUnitTests {
|
|||
method.invoke(fragment, "", "appUiDefaultLanguagePref")
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun `Test prepareAppLanguages when recently used languages is empty`() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod(
|
||||
"prepareAppLanguages",
|
||||
String::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(fragment, "appUiDefaultLanguagePref")
|
||||
verify(recentLanguagesDao, times(1)).recentLanguages
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun `Test prepareAppLanguages when recently used languages is not empty`() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
whenever(recentLanguagesDao.recentLanguages)
|
||||
.thenReturn(
|
||||
mutableListOf(Language("English", "en"),
|
||||
Language("English", "en"),
|
||||
Language("English", "en"),
|
||||
Language("English", "en"),
|
||||
Language("English", "en"),
|
||||
Language("English", "en"))
|
||||
)
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod(
|
||||
"prepareAppLanguages",
|
||||
String::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(fragment, "appUiDefaultLanguagePref")
|
||||
verify(recentLanguagesDao, times(2)).recentLanguages
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testSaveLanguageValueCase_descriptionDefaultLanguagePref() {
|
||||
|
|
@ -120,4 +193,77 @@ class SettingsFragmentUnitTests {
|
|||
method.invoke(fragment, "", "descriptionDefaultLanguagePref")
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testHideRecentLanguagesSection() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod(
|
||||
"hideRecentLanguagesSection"
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(fragment)
|
||||
verify(recentLanguagesTextView, times(1)).visibility = any()
|
||||
verify(separator, times(1)).visibility = any()
|
||||
verify(languageHistoryListView, times(1)).visibility = any()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testOnRecentLanguageClicked() {
|
||||
whenever(recentLanguagesDao.findRecentLanguage(any()))
|
||||
.thenReturn(true)
|
||||
whenever(adapterView.adapter)
|
||||
.thenReturn(RecentLanguagesAdapter(context,
|
||||
listOf(Language("English", "en")),
|
||||
hashMapOf<String,String>()
|
||||
)
|
||||
)
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod(
|
||||
"onRecentLanguageClicked",
|
||||
String::class.java,
|
||||
Dialog::class.java,
|
||||
AdapterView::class.java,
|
||||
Int::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(fragment, "test", Mockito.mock(Dialog::class.java), adapterView, 0)
|
||||
verify(recentLanguagesDao, times(1)).findRecentLanguage(any())
|
||||
verify(adapterView, times(2)).adapter
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test setUpRecentLanguagesSection when list is empty`() {
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod(
|
||||
"setUpRecentLanguagesSection",
|
||||
List::class.java,
|
||||
HashMap::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(fragment, emptyList<Language>(), hashMapOf<Int,String>())
|
||||
verify(languageHistoryListView, times(1)).visibility = View.GONE
|
||||
verify(separator, times(1)).visibility = View.GONE
|
||||
verify(recentLanguagesTextView, times(1)).visibility = View.GONE
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test setUpRecentLanguagesSection when list is not empty`() {
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod(
|
||||
"setUpRecentLanguagesSection",
|
||||
List::class.java,
|
||||
HashMap::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(fragment, listOf(
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn")
|
||||
), hashMapOf<Int,String>())
|
||||
verify(languageHistoryListView, times(1)).visibility = View.VISIBLE
|
||||
verify(separator, times(1)).visibility = View.VISIBLE
|
||||
verify(recentLanguagesTextView, times(1)).visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,15 +1,27 @@
|
|||
package fr.free.nrw.commons.upload
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.GridLayout
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import com.nhaarman.mockitokotlin2.any
|
||||
import com.nhaarman.mockitokotlin2.times
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.recentlanguages.Language
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao
|
||||
import fr.free.nrw.commons.settings.SettingsFragment
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.powermock.reflect.Whitebox
|
||||
import org.robolectric.Robolectric
|
||||
|
|
@ -18,6 +30,7 @@ import org.robolectric.RuntimeEnvironment
|
|||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.LooperMode
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||
|
|
@ -36,15 +49,33 @@ class UploadMediaDetailAdapterUnitTest {
|
|||
@Mock
|
||||
private lateinit var eventListener: UploadMediaDetailAdapter.EventListener
|
||||
|
||||
@Mock
|
||||
private lateinit var recentLanguagesDao: RecentLanguagesDao
|
||||
|
||||
@Mock
|
||||
private lateinit var textView: TextView
|
||||
|
||||
@Mock
|
||||
private lateinit var view: View
|
||||
|
||||
@Mock
|
||||
private lateinit var listView: ListView
|
||||
|
||||
@Mock
|
||||
private lateinit var adapterView: AdapterView<RecentLanguagesAdapter>
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
uploadMediaDetails = mutableListOf(uploadMediaDetail, uploadMediaDetail)
|
||||
activity = Robolectric.buildActivity(UploadActivity::class.java).get()
|
||||
adapter = UploadMediaDetailAdapter("")
|
||||
adapter = UploadMediaDetailAdapter("", recentLanguagesDao)
|
||||
context = RuntimeEnvironment.application.applicationContext
|
||||
Whitebox.setInternalState(adapter, "uploadMediaDetails", uploadMediaDetails)
|
||||
Whitebox.setInternalState(adapter, "eventListener", eventListener)
|
||||
Whitebox.setInternalState(adapter, "recentLanguagesTextView", textView)
|
||||
Whitebox.setInternalState(adapter, "separator", view)
|
||||
Whitebox.setInternalState(adapter, "languageHistoryListView", listView)
|
||||
viewHolder = adapter.onCreateViewHolder(GridLayout(activity), 0)
|
||||
}
|
||||
|
||||
|
|
@ -145,4 +176,75 @@ class UploadMediaDetailAdapterUnitTest {
|
|||
verify(uploadMediaDetail).isManuallyAdded
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testHideRecentLanguagesSection() {
|
||||
val method: Method = UploadMediaDetailAdapter.ViewHolder::class.java.getDeclaredMethod(
|
||||
"hideRecentLanguagesSection"
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(viewHolder)
|
||||
verify(listView, times(1)).visibility = View.GONE
|
||||
verify(view, times(1)).visibility = View.GONE
|
||||
verify(textView, times(1)).visibility = View.GONE
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test setUpRecentLanguagesSection when list is empty`() {
|
||||
val method: Method = UploadMediaDetailAdapter.ViewHolder::class.java.getDeclaredMethod(
|
||||
"setUpRecentLanguagesSection",
|
||||
List::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(viewHolder, emptyList<Language>())
|
||||
verify(listView, times(1)).visibility = View.GONE
|
||||
verify(view, times(1)).visibility = View.GONE
|
||||
verify(textView, times(1)).visibility = View.GONE
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test setUpRecentLanguagesSection when list is not empty`() {
|
||||
val method: Method = UploadMediaDetailAdapter.ViewHolder::class.java.getDeclaredMethod(
|
||||
"setUpRecentLanguagesSection",
|
||||
List::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(viewHolder, listOf(
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn"),
|
||||
Language("Bengali", "bn")
|
||||
))
|
||||
verify(listView, times(1)).visibility = View.VISIBLE
|
||||
verify(view, times(1)).visibility = View.VISIBLE
|
||||
verify(textView, times(1)).visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testOnRecentLanguageClicked() {
|
||||
whenever(recentLanguagesDao.findRecentLanguage(any()))
|
||||
.thenReturn(true)
|
||||
whenever(adapterView.adapter)
|
||||
.thenReturn(
|
||||
RecentLanguagesAdapter(context,
|
||||
listOf(Language("English", "en")),
|
||||
hashMapOf<String,String>()
|
||||
)
|
||||
)
|
||||
val method: Method = UploadMediaDetailAdapter.ViewHolder::class.java.getDeclaredMethod(
|
||||
"onRecentLanguageClicked",
|
||||
Dialog::class.java,
|
||||
AdapterView::class.java,
|
||||
Int::class.java,
|
||||
UploadMediaDetail::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(viewHolder, Mockito.mock(Dialog::class.java), adapterView, 0,
|
||||
Mockito.mock(UploadMediaDetail::class.java))
|
||||
verify(recentLanguagesDao, times(1)).findRecentLanguage(any())
|
||||
verify(adapterView, times(3)).adapter
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue