Skip to content

Commit afdeaae

Browse files
authored
Fixes: #3179 Make category search non case-sensitive (#3326)
* CategoryClient: fix category search case-sensitivity by converting to lower case as MW api is inherently case-sensitive, the results obtained will be same * CategoryItem: reverting javadoc changes * CategoriesModel: make category search case-insensitive * CategoryItem: fix whitespaces * Add tests for case-insensitivity * CategoryClientTest: add more test cases * CategoryClientTest: fix travis ci test * CategoriesModelTest: changes mage to CategoriesModel and tested
1 parent 0affe71 commit afdeaae

File tree

5 files changed

+58
-39
lines changed

5 files changed

+58
-39
lines changed

app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,9 @@ public Observable<CategoryItem> searchAll(String term, List<String> imageTitleLi
123123
}
124124

125125
//otherwise, search API for matching categories
126+
//term passed as lower case to make search case-insensitive(taking only lower case for everything)
126127
return categoryClient
127-
.searchCategoriesForPrefix(term, SEARCH_CATS_LIMIT)
128+
.searchCategoriesForPrefix(term.toLowerCase(), SEARCH_CATS_LIMIT)
128129
.map(name -> new CategoryItem(name, false));
129130
}
130131

@@ -183,11 +184,12 @@ private Observable<CategoryItem> titleCategories(List<String> titleList) {
183184

184185
/**
185186
* Return category for single title
187+
* title is converted to lower case to make search case-insensitive
186188
* @param title
187189
* @return
188190
*/
189191
private Observable<CategoryItem> getTitleCategories(String title) {
190-
return categoryClient.searchCategories(title, SEARCH_CATS_LIMIT)
192+
return categoryClient.searchCategories(title.toLowerCase(), SEARCH_CATS_LIMIT)
191193
.map(name -> new CategoryItem(name, false));
192194
}
193195

app/src/main/java/fr/free/nrw/commons/category/CategoryClient.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public Observable<String> searchCategories(String filter, int itemLimit) {
5555

5656
/**
5757
* Searches for categories starting with the specified string.
58-
*
58+
*
5959
* @param prefix The prefix to be searched
6060
* @param itemLimit How many results are returned
6161
* @param offset Starts returning items from the nth result. If offset is 9, the response starts with the 9th item of the search result

app/src/main/java/fr/free/nrw/commons/category/CategoryItem.java

+1-36
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
import android.os.Parcel;
44
import android.os.Parcelable;
55

6-
/**
7-
* Represents a Category Item.
8-
* Implemented as Parcelable so that its object could be parsed between activity components.
9-
*/
106
public class CategoryItem implements Parcelable {
117
private final String name;
128
private boolean selected;
@@ -28,53 +24,28 @@ public CategoryItem(String name, boolean selected) {
2824
this.selected = selected;
2925
}
3026

31-
/**
32-
* Reads from the received Parcel
33-
* @param in
34-
*/
3527
private CategoryItem(Parcel in) {
3628
name = in.readString();
3729
selected = in.readInt() == 1;
3830
}
3931

40-
/**
41-
* Gets Name
42-
* @return
43-
*/
4432
public String getName() {
4533
return name;
4634
}
4735

48-
/**
49-
* Checks if that Category Item has been selected.
50-
* @return
51-
*/
5236
public boolean isSelected() {
5337
return selected;
5438
}
5539

56-
/**
57-
* Selects the Category Item.
58-
* @param selected
59-
*/
6040
public void setSelected(boolean selected) {
6141
this.selected = selected;
6242
}
6343

64-
/**
65-
* Used by Parcelable
66-
* @return
67-
*/
6844
@Override
6945
public int describeContents() {
7046
return 0;
7147
}
7248

73-
/**
74-
* Writes to the received Parcel
75-
* @param parcel
76-
* @param flags
77-
*/
7849
@Override
7950
public void writeToParcel(Parcel parcel, int flags) {
8051
parcel.writeString(name);
@@ -96,19 +67,13 @@ public boolean equals(Object o) {
9667

9768
}
9869

99-
/**
100-
* Returns hash code for current object
101-
*/
10270
@Override
10371
public int hashCode() {
10472
return name.hashCode();
10573
}
10674

107-
/**
108-
* Return String form of current object
109-
*/
11075
@Override
11176
public String toString() {
11277
return "CategoryItem: '" + name + '\'';
11378
}
114-
}
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package fr.free.nrw.commons.category
2+
3+
import io.reactivex.Observable
4+
import junit.framework.Assert.*
5+
import org.junit.Before
6+
import org.junit.Test
7+
import org.mockito.*
8+
import org.wikipedia.dataclient.mwapi.MwQueryPage
9+
import org.wikipedia.dataclient.mwapi.MwQueryResponse
10+
import org.wikipedia.dataclient.mwapi.MwQueryResult
11+
12+
//class for testing CategoriesModel class
13+
class CategoriesModelTest {
14+
@Mock
15+
internal var categoryInterface: CategoryInterface? = null
16+
17+
@Mock
18+
internal var categoryItem: CategoryItem? = null
19+
20+
@InjectMocks
21+
var categoryClient: CategoryClient? = null
22+
23+
@Before
24+
@Throws(Exception::class)
25+
fun setUp() {
26+
MockitoAnnotations.initMocks(this)
27+
}
28+
29+
// Test Case for verifying that Categories search (MW api calls) are case-insensitive
30+
@Test
31+
fun searchAllFoundCaseTest() {
32+
val mwQueryPage = Mockito.mock(MwQueryPage::class.java)
33+
Mockito.`when`(mwQueryPage.title()).thenReturn("Category:Test")
34+
val mwQueryResult = Mockito.mock(MwQueryResult::class.java)
35+
Mockito.`when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage))
36+
val mockResponse = Mockito.mock(MwQueryResponse::class.java)
37+
Mockito.`when`(mockResponse.query()).thenReturn(mwQueryResult)
38+
val categoriesModel: CategoriesModel = CategoriesModel(categoryClient,null,null)
39+
40+
Mockito.`when`(categoryInterface!!.searchCategoriesForPrefix(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()))
41+
.thenReturn(Observable.just(mockResponse))
42+
43+
// Checking if both return "Test"
44+
val actualCategoryName = categoriesModel!!.searchAll("tes",null).blockingFirst()
45+
assertEquals("Test", actualCategoryName.getName())
46+
47+
val actualCategoryNameCaps = categoriesModel!!.searchAll("Tes",null).blockingFirst()
48+
assertEquals("Test", actualCategoryNameCaps.getName())
49+
}
50+
}

app/src/test/kotlin/fr/free/nrw/commons/category/CategoryClientTest.kt

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class CategoryClientTest {
5858
{ fail("SearchCategories returned element when it shouldn't have.") },
5959
{ s -> throw s })
6060
}
61+
6162
@Test
6263
fun searchCategoriesForPrefixFound() {
6364
val mwQueryPage = Mockito.mock(MwQueryPage::class.java)
@@ -92,6 +93,7 @@ class CategoryClientTest {
9293
{ fail("SearchCategories returned element when it shouldn't have.") },
9394
{ s -> throw s })
9495
}
96+
9597
@Test
9698
fun getParentCategoryListFound() {
9799
val mwQueryPage = Mockito.mock(MwQueryPage::class.java)

0 commit comments

Comments
 (0)