mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-11-02 15:53:55 +01:00
Testing, Documentation and Cleanup.
This commit is contained in:
parent
8fe958e3c6
commit
ea94ea782b
5 changed files with 230 additions and 46 deletions
|
|
@ -402,6 +402,7 @@ public class OkHttpJsonApiClient {
|
|||
*
|
||||
* @param placeList A list of Place objects for which to fetch information.
|
||||
* @param language The language code to use for the query.
|
||||
* @param secondaryLanguages The serialized secondary language code(s) to use for fallback queries.
|
||||
* @return A list of Place objects with additional information retrieved from Wikidata, or null
|
||||
* if an error occurs.
|
||||
* @throws IOException If there is an issue with reading the resource file or executing the HTTP
|
||||
|
|
@ -410,25 +411,32 @@ public class OkHttpJsonApiClient {
|
|||
@Nullable
|
||||
public List<Place> getPlaces(
|
||||
final List<Place> placeList, final String language, final String secondaryLanguages) throws IOException {
|
||||
final String wikidataQuery = FileUtils.readFromResource("/queries/query_for_item.rq");
|
||||
final String[] secondaryLanguageArray = secondaryLanguages.split(",\\s*"); // could be used to generate backup SparQL Queries
|
||||
|
||||
// Read the SparQL query template from the resource file
|
||||
final String wikidataQuery = FileUtils.readFromResource("/queries/query_for_item.rq");
|
||||
|
||||
// Split the secondary languages string into an array to use in fallback queries
|
||||
final String[] secondaryLanguageArray = secondaryLanguages.split(",\\s*");
|
||||
|
||||
// Prepare the Wikidata entity IDs (QIDs) for each place in the list
|
||||
String qids = "";
|
||||
for (final Place place : placeList) {
|
||||
qids += "\n" + ("wd:" + place.getWikiDataEntityId());
|
||||
}
|
||||
|
||||
// Build fallback descriptions for secondary languages in case the primary language is unavailable
|
||||
StringBuilder fallBackDescription = new StringBuilder();
|
||||
for (int i = 0; i < secondaryLanguageArray.length; i++) {
|
||||
fallBackDescription.append("OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(i + 1) // Unique identifier for each fallback
|
||||
.append(". FILTER (lang(?itemDescriptionPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(") = \"")
|
||||
.append(secondaryLanguageArray[i])
|
||||
.append(secondaryLanguageArray[i]) // Use the secondary language code
|
||||
.append("\")}\n");
|
||||
}
|
||||
|
||||
// Build fallback labels for secondary languages
|
||||
StringBuilder fallbackLabel = new StringBuilder();
|
||||
for (int i = 0; i < secondaryLanguageArray.length; i++) {
|
||||
fallbackLabel.append("OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_")
|
||||
|
|
@ -440,6 +448,7 @@ public class OkHttpJsonApiClient {
|
|||
.append("\")}\n");
|
||||
}
|
||||
|
||||
// Build fallback class labels for secondary languages
|
||||
StringBuilder fallbackClassLabel = new StringBuilder();
|
||||
for (int i = 0; i < secondaryLanguageArray.length; i++) {
|
||||
fallbackClassLabel.append("OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_")
|
||||
|
|
@ -451,6 +460,7 @@ public class OkHttpJsonApiClient {
|
|||
.append("\")}\n");
|
||||
}
|
||||
|
||||
// Replace placeholders in the query with actual data: QIDs, language codes, and fallback options
|
||||
final String query = wikidataQuery
|
||||
.replace("${ENTITY}", qids)
|
||||
.replace("${LANG}", language)
|
||||
|
|
@ -458,33 +468,41 @@ public class OkHttpJsonApiClient {
|
|||
.replace("${SECONDARYLABEL}", fallbackLabel.toString())
|
||||
.replace("${SECONDARYCLASSLABEL}", fallbackClassLabel.toString());
|
||||
|
||||
// Build the URL for the SparQL query with the formatted query string
|
||||
final HttpUrl.Builder urlBuilder = HttpUrl
|
||||
.parse(sparqlQueryUrl)
|
||||
.newBuilder()
|
||||
.addQueryParameter("query", query)
|
||||
.addQueryParameter("format", "json");
|
||||
.addQueryParameter("format", "json"); // Ensure JSON response
|
||||
|
||||
// Create and send the HTTP request
|
||||
final Request request = new Request.Builder()
|
||||
.url(urlBuilder.build())
|
||||
.build();
|
||||
|
||||
// Execute the request and handle the response
|
||||
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||
if (response.isSuccessful()) {
|
||||
// Parse the JSON response and convert it to a list of NearbyResultItems
|
||||
final String json = response.body().string();
|
||||
final NearbyResponse nearbyResponse = gson.fromJson(json, NearbyResponse.class);
|
||||
final List<NearbyResultItem> bindings = nearbyResponse.getResults().getBindings();
|
||||
|
||||
// Convert each NearbyResultItem into a Place object and return the list of places
|
||||
final List<Place> places = new ArrayList<>();
|
||||
for (final NearbyResultItem item : bindings) {
|
||||
final Place placeFromNearbyItem = Place.from(item);
|
||||
places.add(placeFromNearbyItem);
|
||||
}
|
||||
return places;
|
||||
return places; // Return the list of places with additional information
|
||||
} else {
|
||||
// Handle unsuccessful HTTP response codes
|
||||
throw new IOException("Unexpected response code: " + response.code());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make API Call to get Places
|
||||
*
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ public class NearbyPlaces {
|
|||
*
|
||||
* @param placeList A list of Place objects for which to fetch information.
|
||||
* @param lang The language code to use for the query.
|
||||
* @param lang2 The serialised secondary language code to use for the query.
|
||||
* @return A list of Place objects obtained from the Wikidata query.
|
||||
* @throws Exception If an error occurs during the retrieval process.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -290,6 +290,13 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ListView to display saved languages using the SavedLanguagesAdapter.
|
||||
*
|
||||
* @param savedLanguageListView The ListView that will display the saved languages.
|
||||
* @param savedLanguages A list of saved Language objects to be displayed.
|
||||
* @param selectedLanguages A HashMap containing the selected language IDs and their corresponding names.
|
||||
*/
|
||||
private void updateSavedLanguages(ListView savedLanguageListView, List<Language> savedLanguages, HashMap<Integer, String> selectedLanguages) {
|
||||
// Use SavedLanguagesAdapter to display saved languages
|
||||
SavedLanguagesAdapter savedLanguagesAdapter = new SavedLanguagesAdapter(
|
||||
|
|
@ -302,6 +309,12 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
savedLanguageListView.setAdapter(savedLanguagesAdapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a comma-separated string of language codes into an ArrayList of strings.
|
||||
*
|
||||
* @param languageCodes A string containing language codes separated by commas.
|
||||
* @return An ArrayList of language codes, or an empty ArrayList if the input is null or empty.
|
||||
*/
|
||||
private ArrayList<String> deSerialise(String languageCodes) {
|
||||
// Check if the stored string is empty or null
|
||||
if (languageCodes == null || languageCodes.isEmpty()) {
|
||||
|
|
@ -313,21 +326,21 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
return new ArrayList<>(Arrays.asList(languageArray)); // Convert array to ArrayList and return
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare and Show language selection dialog box
|
||||
* Disable default/already selected language from dialog box
|
||||
* Saves values chosen by user to shared preferences as a serialised string.
|
||||
*/
|
||||
private void prepareSecondaryLanguageDialog() {
|
||||
final String languageCode = getCurrentLanguageCode("descriptionSecondaryLanguagePref");
|
||||
HashMap<Integer, String> selectedLanguages = new HashMap<>();
|
||||
assert languageCode != null;
|
||||
selectedLanguages.put(0, Locale.getDefault().getLanguage());
|
||||
System.out.println(Locale.getDefault().getLanguage());
|
||||
System.out.println(languageCode);
|
||||
|
||||
// Deserializing saved language codes to Language objects
|
||||
ArrayList<Language> savedLanguages = new ArrayList<>();
|
||||
for (String code : deSerialise(languageCode)) {
|
||||
System.out.println(code);
|
||||
if(code.equals(Locale.getDefault().getLanguage())){
|
||||
System.out.println("match");
|
||||
continue;
|
||||
}
|
||||
Locale locale = new Locale(code);
|
||||
|
|
@ -633,42 +646,10 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
separator.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private String reSerialise(ArrayList<String> languageCodes) {
|
||||
// Join the elements of the list into a single string, separated by a comma and a space
|
||||
return String.join(", ", languageCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changing the default app language with selected one and save it to SharedPreferences
|
||||
*/
|
||||
public void setLocale(final Activity activity, String userSelectedValue) {
|
||||
// if (userSelectedValue.equals("")) {
|
||||
// userSelectedValue = Locale.getDefault().getLanguage();
|
||||
// }
|
||||
//
|
||||
// String current = Locale.getDefault().getLanguage();
|
||||
// ArrayList<String> languageCodes = deSerialise(current);
|
||||
// if(appUI) {
|
||||
// languageCodes.set(0, userSelectedValue);
|
||||
// userSelectedValue = reSerialise(languageCodes);
|
||||
// }
|
||||
// else{
|
||||
// ArrayList<String> newLanguageCodes = new ArrayList<>();
|
||||
// ArrayList<String> userSelctedCode = deSerialise(userSelectedValue);
|
||||
//
|
||||
// newLanguageCodes.add(languageCodes.get(0));
|
||||
// for(String code : userSelctedCode){
|
||||
// newLanguageCodes.add(code);
|
||||
// }
|
||||
// userSelectedValue = reSerialise(newLanguageCodes);
|
||||
// }
|
||||
//
|
||||
// System.out.println("Final locale");
|
||||
// System.out.println(userSelectedValue);
|
||||
//
|
||||
// System.out.println("vs");
|
||||
// System.out.println(getCurrentLanguageCode("appUiDefaultLanguagePref"));
|
||||
// System.out.println(getCurrentLanguageCode("descriptionSecondaryLanguagePref"));
|
||||
|
||||
final Locale locale = createLocale(userSelectedValue);
|
||||
Locale.setDefault(locale);
|
||||
|
|
|
|||
74
app/src/test/java/StringBuilderTest.java
Normal file
74
app/src/test/java/StringBuilderTest.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class StringBuilderTest {
|
||||
@Test
|
||||
void testFallbackDescriptionBuilder() {
|
||||
String secondaryLanguages = "en,fr,es"; // Example secondary languages
|
||||
String[] secondaryLanguageArray = secondaryLanguages.split(",\\s*");
|
||||
|
||||
StringBuilder fallBackDescription = new StringBuilder();
|
||||
for (int i = 0; i < secondaryLanguageArray.length; i++) {
|
||||
fallBackDescription.append("OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_")
|
||||
.append(i + 1) // Unique identifier for each fallback
|
||||
.append(". FILTER (lang(?itemDescriptionPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(") = \"")
|
||||
.append(secondaryLanguageArray[i]) // Use the secondary language code
|
||||
.append("\")}\n");
|
||||
}
|
||||
|
||||
String expected = "OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_1. FILTER (lang(?itemDescriptionPreferredLanguage_1) = \"en\")}\n" +
|
||||
"OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_2. FILTER (lang(?itemDescriptionPreferredLanguage_2) = \"fr\")}\n" +
|
||||
"OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_3. FILTER (lang(?itemDescriptionPreferredLanguage_3) = \"es\")}\n";
|
||||
|
||||
assertEquals(expected, fallBackDescription.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFallbackLabelBuilder() {
|
||||
String secondaryLanguages = "en,fr,es"; // Example secondary languages
|
||||
String[] secondaryLanguageArray = secondaryLanguages.split(",\\s*");
|
||||
|
||||
StringBuilder fallbackLabel = new StringBuilder();
|
||||
for (int i = 0; i < secondaryLanguageArray.length; i++) {
|
||||
fallbackLabel.append("OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(". FILTER (lang(?itemLabelPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(") = \"")
|
||||
.append(secondaryLanguageArray[i])
|
||||
.append("\")}\n");
|
||||
}
|
||||
|
||||
String expected = "OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_1. FILTER (lang(?itemLabelPreferredLanguage_1) = \"en\")}\n" +
|
||||
"OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_2. FILTER (lang(?itemLabelPreferredLanguage_2) = \"fr\")}\n" +
|
||||
"OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_3. FILTER (lang(?itemLabelPreferredLanguage_3) = \"es\")}\n";
|
||||
|
||||
assertEquals(expected, fallbackLabel.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFallbackClassLabelBuilder() {
|
||||
String secondaryLanguages = "en,fr,es"; // Example secondary languages
|
||||
String[] secondaryLanguageArray = secondaryLanguages.split(",\\s*");
|
||||
|
||||
StringBuilder fallbackClassLabel = new StringBuilder();
|
||||
for (int i = 0; i < secondaryLanguageArray.length; i++) {
|
||||
fallbackClassLabel.append("OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(". FILTER (lang(?classLabelPreferredLanguage_")
|
||||
.append(i + 1)
|
||||
.append(") = \"")
|
||||
.append(secondaryLanguageArray[i])
|
||||
.append("\")}\n");
|
||||
}
|
||||
|
||||
String expected = "OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_1. FILTER (lang(?classLabelPreferredLanguage_1) = \"en\")}\n" +
|
||||
"OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_2. FILTER (lang(?classLabelPreferredLanguage_2) = \"fr\")}\n" +
|
||||
"OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_3. FILTER (lang(?classLabelPreferredLanguage_3) = \"es\")}\n";
|
||||
|
||||
assertEquals(expected, fallbackClassLabel.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package fr.free.nrw.commons.settings
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Looper
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.recentlanguages.Language
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.Shadows
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.LooperMode
|
||||
import java.lang.reflect.Method
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||
@LooperMode(LooperMode.Mode.PAUSED)
|
||||
class SettingsFragmentSecondaryLanguageTests {
|
||||
|
||||
private lateinit var fragment: SettingsFragment
|
||||
|
||||
private lateinit var recentLanguagesDao: RecentLanguagesDao
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
val activity = Robolectric.buildActivity(SettingsActivity::class.java).create().get()
|
||||
fragment = SettingsFragment()
|
||||
val fragmentManager = activity.supportFragmentManager
|
||||
val fragmentTransaction = fragmentManager.beginTransaction()
|
||||
fragmentTransaction.add(fragment, null)
|
||||
fragmentTransaction.commitNowAllowingStateLoss()
|
||||
// Mock RecentLanguagesDao
|
||||
recentLanguagesDao = Mockito.mock(RecentLanguagesDao::class.java)
|
||||
fragment.recentLanguagesDao = recentLanguagesDao
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun `Test prepareSecondaryLanguageDialog is invoked and dialog is created`() {
|
||||
// Set up the main looper to idle, as necessary in Robolectric tests
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod("prepareSecondaryLanguageDialog")
|
||||
method.isAccessible = true
|
||||
|
||||
method.invoke(fragment)
|
||||
|
||||
// Verify if the dialog was created and is not null
|
||||
val dialogField = SettingsFragment::class.java.getDeclaredField("dialog")
|
||||
dialogField.isAccessible = true
|
||||
val dialog: Dialog? = dialogField.get(fragment) as Dialog?
|
||||
Assert.assertNotNull(dialog)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun `Test prepareSecondaryLanguageDialog adds a language and updates preferences`() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
|
||||
// Mock recent languages and saved languages
|
||||
val savedLanguages = mutableListOf(Language("English", "en"))
|
||||
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod("prepareSecondaryLanguageDialog")
|
||||
method.isAccessible = true
|
||||
|
||||
method.invoke(fragment)
|
||||
|
||||
val dialogField = SettingsFragment::class.java.getDeclaredField("dialog")
|
||||
dialogField.isAccessible = true
|
||||
val dialog: Dialog? = dialogField.get(fragment) as Dialog?
|
||||
|
||||
val newLanguage = Language("German", "de")
|
||||
savedLanguages.add(newLanguage)
|
||||
|
||||
// Verify if the saved languages now include the newly added language
|
||||
Assert.assertTrue(savedLanguages.contains(newLanguage))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun `Test prepareSecondaryLanguageDialog removes a language and updates preferences`() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
|
||||
// Mock recent languages and saved languages
|
||||
val savedLanguages = mutableListOf(Language("English", "en"), Language("French", "fr"))
|
||||
|
||||
val method: Method = SettingsFragment::class.java.getDeclaredMethod("prepareSecondaryLanguageDialog")
|
||||
method.isAccessible = true
|
||||
|
||||
method.invoke(fragment)
|
||||
|
||||
val dialogField = SettingsFragment::class.java.getDeclaredField("dialog")
|
||||
dialogField.isAccessible = true
|
||||
val dialog: Dialog? = dialogField.get(fragment) as Dialog?
|
||||
|
||||
// Simulate removing a language from the saved list (e.g., removing "French")
|
||||
val positionToRemove = 1
|
||||
savedLanguages.removeAt(positionToRemove)
|
||||
|
||||
Assert.assertFalse(savedLanguages.any { it.languageCode == "fr" })
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue