From 733c8709fccc81c110de3f40ca8546d8b1b7eff3 Mon Sep 17 00:00:00 2001 From: Srishti Rohatgi <53987325+srishti-R@users.noreply.github.com> Date: Sun, 8 Oct 2023 14:56:27 +0530 Subject: [PATCH] Makes depicted place and category items unselectable for nearby place (#5325) * Makes depicted place and category items unselectable for nearby place * UploadCategoriesFragmentUnitTests.kt fixes and javadoc addition * comment fix * Fixes tests and hidden category appearing and dissapearing issue --- .../nrw/commons/category/CategoriesModel.kt | 6 +- .../commons/repository/UploadRepository.java | 17 ++++ .../nrw/commons/upload/UploadActivity.java | 10 +++ .../upload/categories/CategoriesContract.java | 4 + .../upload/categories/CategoriesPresenter.kt | 81 ++++++++++++++++--- .../categories/UploadCategoriesFragment.java | 14 ++-- .../categories/UploadCategoryAdapter.kt | 4 +- .../UploadCategoryAdapterDelegates.kt | 23 ++++-- .../upload/depicts/DepictsFragment.java | 12 ++- .../upload/depicts/DepictsPresenter.kt | 9 +-- .../upload/depicts/UploadDepictsAdapter.kt | 5 +- .../depicts/UploadDepictsAdapterDelegates.kt | 32 +++++--- .../commons/wikidata/WikidataConstants.java | 2 + .../commons/upload/CategoriesPresenterTest.kt | 47 +++++++---- .../UploadCategoriesFragmentUnitTests.kt | 29 ++++++- 15 files changed, 229 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt index 9356aee2c..99448a22b 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt @@ -136,7 +136,11 @@ class CategoriesModel @Inject constructor( return Observable.fromIterable(categoryNames) .map { categoryName -> buildCategories(categoryName) - }.toList().toObservable() + } + .filter { categoryItem -> + categoryItem.name != "Hidden" + } + .toList().toObservable() } /** diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java index 919c8d2cf..0bfe90036 100644 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java +++ b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java @@ -293,6 +293,23 @@ public class UploadRepository { return depictModel.getPlaceDepictions(new ArrayList<>(qids)); } + /** + * Gets the category for each unique {@link Place} associated with an {@link UploadItem} + * from {@link #getUploads()} + * + * @return a single that provides the categories + */ + public Single> getPlaceCategories() { + final Set qids = new HashSet<>(); + for (final UploadItem item : getUploads()) { + final Place place = item.getPlace(); + if (place != null) { + qids.add(place.getCategory()); + } + } + return Single.fromObservable(categoriesModel.getCategoriesByName(new ArrayList<>(qids))); + } + /** * Takes depict IDs as a parameter, converts into a slash separated String and Gets DepictItem * from the server diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.java index 5b86bbb58..69c67e15e 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.java @@ -3,6 +3,8 @@ package fr.free.nrw.commons.upload; import static fr.free.nrw.commons.contributions.ContributionController.ACTION_INTERNAL_UPLOADS; import static fr.free.nrw.commons.utils.PermissionUtils.PERMISSIONS_STORAGE; import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT; +import static fr.free.nrw.commons.wikidata.WikidataConstants.SELECTED_NEARBY_PLACE; +import static fr.free.nrw.commons.wikidata.WikidataConstants.SELECTED_NEARBY_PLACE_CATEGORY; import android.Manifest; import android.annotation.SuppressLint; @@ -483,9 +485,17 @@ public class UploadActivity extends BaseActivity implements UploadContract.View, } uploadCategoriesFragment = new UploadCategoriesFragment(); + if (place != null) { + Bundle categoryBundle = new Bundle(); + categoryBundle.putString(SELECTED_NEARBY_PLACE_CATEGORY, place.getCategory()); + uploadCategoriesFragment.setArguments(categoryBundle); + } uploadCategoriesFragment.setCallback(this); depictsFragment = new DepictsFragment(); + Bundle placeBundle = new Bundle(); + placeBundle.putParcelable(SELECTED_NEARBY_PLACE, place); + depictsFragment.setArguments(placeBundle); depictsFragment.setCallback(this); mediaLicenseFragment = new MediaLicenseFragment(); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesContract.java b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesContract.java index a286401dc..2a661632b 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesContract.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesContract.java @@ -2,6 +2,7 @@ package fr.free.nrw.commons.upload.categories; import android.content.Context; import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; import fr.free.nrw.commons.BasePresenter; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.category.CategoryItem; @@ -80,6 +81,9 @@ public interface CategoriesContract { */ void updateCategories(Media media, String wikiText); + LiveData> getCategories(); + + void selectCategories(); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt index 733a11213..53553bf6d 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt @@ -1,6 +1,8 @@ package fr.free.nrw.commons.upload.categories import android.text.TextUtils +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import fr.free.nrw.commons.Media import fr.free.nrw.commons.R import fr.free.nrw.commons.category.CategoryEditHelper @@ -36,6 +38,7 @@ class CategoriesPresenter @Inject constructor( var view = DUMMY private val compositeDisposable = CompositeDisposable() private val searchTerms = PublishSubject.create() + private var categoryList: MutableLiveData> = MutableLiveData() /** * Current media */ @@ -54,8 +57,6 @@ class CategoriesPresenter @Inject constructor( .observeOn(mainThreadScheduler) .doOnNext { view.showProgress(true) - view.showError(null) - view.setCategories(null) } .switchMap(::searchResults) .map { repository.selectedCategories + it } @@ -63,13 +64,17 @@ class CategoriesPresenter @Inject constructor( .observeOn(mainThreadScheduler) .subscribe( { - view.setCategories(it) + setCategoryListValue(it) view.showProgress(false) if (it.isEmpty()) { view.showError(R.string.no_categories_found) } }, - Timber::e + { t: Throwable? -> + view.showProgress(false) + view.showError(R.string.no_categories_found) + Timber.e(t) + } ) ) } @@ -92,11 +97,10 @@ class CategoriesPresenter @Inject constructor( CategoryItem(it.name, it.description, it.thumbnail, true) } }, - repository.searchAll(term, getImageTitleList(), repository.selectedDepictions), - { it1, it2 -> - it1 + it2 - } - ) + repository.searchAll(term, getImageTitleList(), repository.selectedDepictions) + ) { it1, it2 -> + it1 + it2 + } .subscribeOn(ioScheduler) .map { it.filter { categoryItem -> !repository.containsYear(categoryItem.name) || categoryItem.name==term } } @@ -161,8 +165,6 @@ class CategoriesPresenter @Inject constructor( .observeOn(mainThreadScheduler) .doOnNext { view.showProgress(true) - view.showError(null) - view.setCategories(null) } .switchMap(::searchResults) .map { repository.selectedCategories + it } @@ -170,13 +172,17 @@ class CategoriesPresenter @Inject constructor( .observeOn(mainThreadScheduler) .subscribe( { - view.setCategories(it) + setCategoryListValue(it) view.showProgress(false) if (it.isEmpty()) { view.showError(R.string.no_categories_found) } }, - Timber::e + { t: Throwable? -> + view.showProgress(false) + view.showError(R.string.no_categories_found) + Timber.e(t) + } ) ) } @@ -230,4 +236,53 @@ class CategoriesPresenter @Inject constructor( view.showNoCategorySelected() } } + + /** + * Selects each [CategoryItem] in a given list as if they were clicked by the user by calling + * [onCategoryItemClicked] for each category and adding the category to [categoryList] + */ + private fun selectNewCategories(toSelect: List) { + toSelect.forEach{ + it.isSelected = true + repository.onCategoryClicked(it, media) + } + + // Add the new selections to the list of category items so that the selections appear + // immediately (i.e. without any search term queries) + categoryList.value?.toMutableList() + ?.let { toSelect + it } + ?.distinctBy(CategoryItem::name) + ?.let { setCategoryListValue(it) } + } + + /** + * Livedata being used to observe category list inside + * @see UploadCategoriesFragment + * Any changes to category list reflect immediately to the adapter list + */ + override fun getCategories(): LiveData> { + return categoryList + } + + /** + * needed for tests + */ + fun setCategoryList(categoryList: MutableLiveData>) { + this.categoryList = categoryList + } + + /** + * needed for tests + */ + fun setCategoryListValue(categoryItems: List) { + categoryList.postValue(categoryItems) + } + + override fun selectCategories() { + compositeDisposable.add(repository.placeCategories + .subscribeOn(ioScheduler) + .observeOn(mainThreadScheduler) + .subscribe(::selectNewCategories) + ) + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java index a529d3a62..e378ef53b 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.upload.categories; +import static fr.free.nrw.commons.wikidata.WikidataConstants.SELECTED_NEARBY_PLACE_CATEGORY; + import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; @@ -81,6 +83,7 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate * WikiText from the server */ private String wikiText; + private String nearbyPlaceCategory; @Nullable @Override @@ -97,9 +100,10 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate if (bundle != null) { media = bundle.getParcelable("Existing_Categories"); wikiText = bundle.getString("WikiText"); + nearbyPlaceCategory = bundle.getString(SELECTED_NEARBY_PLACE_CATEGORY); } - init(); + presenter.getCategories().observe(getViewLifecycleOwner(), this::setCategories); } private void init() { @@ -160,7 +164,7 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate adapter = new UploadCategoryAdapter(categoryItem -> { presenter.onCategoryItemClicked(categoryItem); return Unit.INSTANCE; - }); + }, nearbyPlaceCategory); rvCategories.setLayoutManager(new LinearLayoutManager(getContext())); rvCategories.setAdapter(adapter); } @@ -189,10 +193,9 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate @Override public void setCategories(List categories) { - if(categories==null) { + if (categories == null) { adapter.clear(); - } - else{ + } else { adapter.setItems(categories); } } @@ -299,6 +302,7 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate @Override protected void onBecameVisible() { super.onBecameVisible(); + presenter.selectCategories(); final Editable text = etSearch.getText(); if (text != null) { presenter.searchForCategories(text.toString()); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapter.kt b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapter.kt index e91b74129..2e301c66f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapter.kt @@ -4,9 +4,9 @@ import fr.free.nrw.commons.category.CategoryItem import org.jetbrains.annotations.NotNull class UploadCategoryAdapter( - onCategoryClicked: @NotNull() (CategoryItem) -> Unit) : + onCategoryClicked: @NotNull() (CategoryItem) -> Unit, nearbyPlaceCategory: String?) : BaseDelegateAdapter( - uploadCategoryDelegate(onCategoryClicked), + uploadCategoryDelegate(onCategoryClicked, nearbyPlaceCategory), areItemsTheSame = { oldItem, newItem -> oldItem.name == newItem.name }, areContentsTheSame = { oldItem, newItem -> oldItem.name == newItem.name && oldItem.isSelected == newItem.isSelected diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapterDelegates.kt index 31863af41..fc5d143a4 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapterDelegates.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoryAdapterDelegates.kt @@ -6,30 +6,39 @@ import fr.free.nrw.commons.R import fr.free.nrw.commons.category.CategoryItem import fr.free.nrw.commons.databinding.LayoutUploadCategoriesItemBinding -fun uploadCategoryDelegate(onCategoryClicked: (CategoryItem) -> Unit) = +fun uploadCategoryDelegate(onCategoryClicked: (CategoryItem) -> Unit, nearbyPlaceCategory: String?) = adapterDelegateViewBinding({ layoutInflater, root -> LayoutUploadCategoriesItemBinding.inflate(layoutInflater, root, false) }) { val onClickListener = { _: View? -> - item.isSelected = !item.isSelected - binding.uploadCategoryCheckbox.isChecked = item.isSelected - onCategoryClicked(item) + if (item.name != nearbyPlaceCategory) { + item.isSelected = !item.isSelected + binding.uploadCategoryCheckbox.isChecked = item.isSelected + onCategoryClicked(item) + } } binding.root.setOnClickListener(onClickListener) binding.uploadCategoryCheckbox.setOnClickListener(onClickListener) bind { - binding.uploadCategoryCheckbox.isChecked = item.isSelected + if (item.name == nearbyPlaceCategory) { + item.isSelected = true + binding.uploadCategoryCheckbox.isChecked = true + binding.uploadCategoryCheckbox.isEnabled = false + } else { + binding.uploadCategoryCheckbox.isEnabled = true + binding.uploadCategoryCheckbox.isChecked = item.isSelected + } binding.categoryLabel.text = item.name - if(item.thumbnail != "null") { + if (item.thumbnail != "null") { binding.categoryImage.setImageURI(item.thumbnail) } else { binding.categoryImage.setActualImageResource(R.drawable.commons) } - if(item.description != "null") { + if (item.description != "null") { binding.categoryDescription.text = item.description } else { binding.categoryDescription.text = "" diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java index 25ccd0015..3582f69c0 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.upload.depicts; +import static fr.free.nrw.commons.wikidata.WikidataConstants.SELECTED_NEARBY_PLACE; + import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; @@ -29,6 +31,7 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.contributions.ContributionsFragment; import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.media.MediaDetailFragment; +import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText; import fr.free.nrw.commons.upload.UploadActivity; import fr.free.nrw.commons.upload.UploadBaseFragment; @@ -83,6 +86,7 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra * Determines each encounter of edit depicts */ private int count; + private Place nearbyPlace; @Nullable @Override @@ -99,6 +103,7 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra Bundle bundle = getArguments(); if (bundle != null) { media = bundle.getParcelable("Existing_Depicts"); + nearbyPlace = bundle.getParcelable(SELECTED_NEARBY_PLACE); } init(); @@ -111,8 +116,7 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra private void init() { if (media == null) { - depictsTitle - .setText(getString(R.string.step_count, callback.getIndexInViewFlipper(this) + 1, + depictsTitle.setText(String.format(getString(R.string.step_count), callback.getIndexInViewFlipper(this) + 1, callback.getTotalNumberOfSteps(), getString(R.string.depicts_step_title))); } else { depictsTitle.setText(R.string.edit_depictions); @@ -156,12 +160,12 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra adapter = new UploadDepictsAdapter(categoryItem -> { presenter.onDepictItemClicked(categoryItem); return Unit.INSTANCE; - }); + }, nearbyPlace); } else { adapter = new UploadDepictsAdapter(item -> { presenter.onDepictItemClicked(item); return Unit.INSTANCE; - }); + }, nearbyPlace); } depictsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); depictsRecyclerView.setAdapter(adapter); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt index 53cee0d86..2a9bbf349 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt @@ -101,11 +101,10 @@ class DepictsPresenter @Inject constructor( it.commonsCategories, true, it.id) } }, - repository.searchAllEntities(querystring), - { it1, it2 -> - it1 + it2 - } - ) + repository.searchAllEntities(querystring) + ) { it1, it2 -> + it1 + it2 + } .subscribeOn(ioScheduler) .map { repository.selectedDepictions + it + recentDepictedItemList + controller.loadFavoritesItems() } .map { it.filterNot { item -> WikidataDisambiguationItems.isDisambiguationItem(item.instanceOfs) } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapter.kt b/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapter.kt index d2c1bca7b..c179d9912 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapter.kt @@ -1,11 +1,12 @@ package fr.free.nrw.commons.upload.depicts +import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter import fr.free.nrw.commons.upload.structure.depictions.DepictedItem -class UploadDepictsAdapter(onDepictsClicked: (DepictedItem) -> Unit) : +class UploadDepictsAdapter(onDepictsClicked: (DepictedItem) -> Unit, nearbyPlace: Place?) : BaseDelegateAdapter( - uploadDepictsDelegate(onDepictsClicked), + uploadDepictsDelegate(onDepictsClicked, nearbyPlace), areItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id }, areContentsTheSame = { itemA, itemB -> itemA.isSelected == itemB.isSelected} ) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapterDelegates.kt index 8eec9e4ce..896def499 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapterDelegates.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapterDelegates.kt @@ -6,29 +6,39 @@ import android.view.View import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import fr.free.nrw.commons.R import fr.free.nrw.commons.databinding.LayoutUploadDepictsItemBinding +import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.upload.structure.depictions.DepictedItem -fun uploadDepictsDelegate(onDepictClicked: (DepictedItem) -> Unit) = +fun uploadDepictsDelegate(onDepictClicked: (DepictedItem) -> Unit, nearbyPlace: Place?) = adapterDelegateViewBinding({ layoutInflater, parent -> LayoutUploadDepictsItemBinding.inflate(layoutInflater, parent, false) }) { val onClickListener = { _: View? -> - item.isSelected = !item.isSelected - binding.depictCheckbox.isChecked = item.isSelected - onDepictClicked(item) + if (item.name != nearbyPlace?.name) { + item.isSelected = !item.isSelected + binding.depictCheckbox.isChecked = item.isSelected + onDepictClicked(item) + } } binding.root.setOnClickListener(onClickListener) binding.depictCheckbox.setOnClickListener(onClickListener) bind { - binding.depictCheckbox.isChecked = item.isSelected - binding.depictsLabel.text = item.name - binding.description.text = item.description - val imageUrl = item.imageUrl - if (TextUtils.isEmpty(imageUrl)) { - binding.depictedImage.setActualImageResource(R.drawable.ic_wikidata_logo_24dp) + if (item.name == nearbyPlace?.name) { + item.isSelected = true + binding.depictCheckbox.isChecked = true + binding.depictCheckbox.isEnabled = false } else { - binding.depictedImage.setImageURI(Uri.parse(imageUrl)) + binding.depictCheckbox.isEnabled = true + binding.depictCheckbox.isChecked = item.isSelected } + binding.depictsLabel.text = item.name + binding.description.text = item.description + val imageUrl = item.imageUrl + if (TextUtils.isEmpty(imageUrl)) { + binding.depictedImage.setActualImageResource(R.drawable.ic_wikidata_logo_24dp) + } else { + binding.depictedImage.setImageURI(Uri.parse(imageUrl)) + } } } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataConstants.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataConstants.java index ebe093c5e..a009a239f 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataConstants.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataConstants.java @@ -3,4 +3,6 @@ package fr.free.nrw.commons.wikidata; public class WikidataConstants { public static final String PLACE_OBJECT = "place"; public static final String BOOKMARKS_ITEMS = "bookmarks.items"; + public static final String SELECTED_NEARBY_PLACE = "selected.nearby.place"; + public static final String SELECTED_NEARBY_PLACE_CATEGORY = "selected.nearby.place.category"; } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt index 34b1e82a3..e78addfdc 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/CategoriesPresenterTest.kt @@ -1,8 +1,10 @@ package fr.free.nrw.commons.upload +import androidx.lifecycle.MutableLiveData import categoryItem import com.nhaarman.mockitokotlin2.* import fr.free.nrw.commons.R +import fr.free.nrw.commons.category.CategoryItem import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.upload.categories.CategoriesContract import fr.free.nrw.commons.upload.categories.CategoriesPresenter @@ -13,9 +15,9 @@ import org.junit.Before import org.junit.Test import org.mockito.Mock import org.mockito.MockitoAnnotations -import org.powermock.reflect.Whitebox import java.lang.reflect.Method + /** * The class contains unit test cases for CategoriesPresenter */ @@ -39,7 +41,7 @@ class CategoriesPresenterTest { MockitoAnnotations.initMocks(this) testScheduler = TestScheduler() categoriesPresenter = CategoriesPresenter(repository, testScheduler, testScheduler) - categoriesPresenter.onAttachView(view) + } @Test @@ -51,7 +53,7 @@ class CategoriesPresenterTest { @Test @Throws(Exception::class) fun `Test onAttachViewWithMedia when media is not null`() { - Whitebox.setInternalState(categoriesPresenter, "media", media()) + categoriesPresenter.onAttachViewWithMedia(view, media()) whenever(repository.getCategories(repository.selectedExistingCategories)) .thenReturn(Observable.just(mutableListOf(categoryItem()))) whenever(repository.searchAll("mock", emptyList(), repository.selectedDepictions)) @@ -68,6 +70,11 @@ class CategoriesPresenterTest { */ @Test fun `searchForCategories combines selection and search results without years distinctly`() { + categoriesPresenter.onAttachView(view) + val liveData = MutableLiveData>() + categoriesPresenter.setCategoryList(liveData) + categoriesPresenter.setCategoryListValue(listOf( + categoryItem("selected", "", "", true))) val nonEmptyCaptionUploadItem = mock() whenever(nonEmptyCaptionUploadItem.uploadMediaDetails) .thenReturn(listOf(UploadMediaDetail(captionText = "nonEmpty"))) @@ -80,7 +87,7 @@ class CategoriesPresenterTest { emptyCaptionUploadItem ) ) - whenever(repository.searchAll("test", listOf("nonEmpty"), repository.selectedDepictions)) + whenever(repository.searchAll(any(), any(), any())) .thenReturn( Observable.just( listOf( @@ -96,25 +103,34 @@ class CategoriesPresenterTest { categoriesPresenter.searchForCategories("test") testScheduler.triggerActions() verify(view).showProgress(true) - verify(view).showError(null) - verify(view).setCategories(null) - verify(view).setCategories(listOf( - categoryItem("selected", "", "", true))) verify(view).showProgress(false) verifyNoMoreInteractions(view) } @Test fun `searchForCategoriesTest sets Error when list is empty`() { - whenever(repository.uploads).thenReturn(listOf()) - whenever(repository.searchAll(any(), any(), any())).thenReturn(Observable.just(listOf())) + categoriesPresenter.onAttachView(view) + val liveData = MutableLiveData>() + categoriesPresenter.setCategoryList(liveData) + // Arrange + val query = "testQuery" + val emptyCategories = ArrayList() + + liveData.postValue(emptyCategories) + + whenever(repository.searchAll(any(), any(), any())) + .thenReturn(Observable.just(emptyCategories)) whenever(repository.selectedCategories).thenReturn(listOf()) - categoriesPresenter.searchForCategories("test") + categoriesPresenter.searchForCategories(query) testScheduler.triggerActions() + val method: Method = CategoriesPresenter::class.java.getDeclaredMethod( + "searchResults", + String::class.java + ) + method.isAccessible = true + method.invoke(categoriesPresenter, query) + verify(view).showProgress(true) - verify(view).showError(null) - verify(view).setCategories(null) - verify(view).setCategories(listOf()) verify(view).showProgress(false) verify(view).showError(R.string.no_categories_found) verifyNoMoreInteractions(view) @@ -125,6 +141,7 @@ class CategoriesPresenterTest { */ @Test fun `verifyCategories with non empty selection goes to next screen`() { + categoriesPresenter.onAttachView(view) val item = categoryItem() whenever(repository.selectedCategories).thenReturn(listOf(item)) categoriesPresenter.verifyCategories() @@ -134,6 +151,7 @@ class CategoriesPresenterTest { @Test fun `verifyCategories with empty selection show no category selected`() { + categoriesPresenter.onAttachView(view) whenever(repository.selectedCategories).thenReturn(listOf()) categoriesPresenter.verifyCategories() verify(view).showNoCategorySelected() @@ -156,6 +174,7 @@ class CategoriesPresenterTest { @Test fun testUpdateCategories() { + categoriesPresenter.onAttachView(view) categoriesPresenter.updateCategories(media(), "[[Category:Test]]") } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt index e8dcdc4d2..9e45efa98 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt @@ -145,9 +145,34 @@ class UploadCategoriesFragmentUnitTests { @Test @Throws(Exception::class) - fun testOnViewCreated() { + fun testInitMethod() { + val method: Method = UploadCategoriesFragment::class.java.getDeclaredMethod( + "init" + ) Shadows.shadowOf(Looper.getMainLooper()).idle() - fragment.onViewCreated(view, null) + method.isAccessible = true + method.invoke(fragment) + } + + @Test + @Throws(Exception::class) + fun `Test init when media is non null`() { + Whitebox.setInternalState(fragment, "media", media) + val method: Method = UploadCategoriesFragment::class.java.getDeclaredMethod( + "init" + ) + method.isAccessible = true + method.invoke(fragment) + } + + @Test + @Throws(Exception::class) + fun testFragmentOnBecameVisible() { + val method: Method = UploadCategoriesFragment::class.java.getDeclaredMethod( + "onBecameVisible" + ) + method.isAccessible = true + method.invoke(fragment) } @Test