Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.preference:preference:1.2.0'

// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.13.2'
Expand All @@ -111,6 +112,7 @@ dependencies {

// Required for instrumented tests
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.7.0'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test:rules:1.6.1'
}
Expand Down
185 changes: 185 additions & 0 deletions app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package net.osmtracker.activity;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.clearText;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.typeText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.stringContainsInOrder;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.core.app.ActivityScenario;
import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.espresso.matcher.ViewMatchers;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;

import net.osmtracker.OSMTracker;
import net.osmtracker.R;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.util.Arrays;


@RunWith(AndroidJUnit4.class)
public class PreferencesTest {

private Context context;
private ActivityScenario<Preferences> activity;

@Before
public void setup() {
context = InstrumentationRegistry.getInstrumentation().getTargetContext();

// Reset preferences to default before each test to ensure a clean state
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().clear().commit();

// Launch the activity
activity = ActivityScenario.launch(Preferences.class);
}

@After
public void tearDown() {
activity.close();
}

/**
* Test that the Storage Directory preference logic works to rejects empty input.
*/
@Test
public void testStorageDirectoryValidatesNonEmpty() {
String keyTitle = context.getString(R.string.prefs_storage_dir);
String defaultValue = OSMTracker.Preferences.VAL_STORAGE_DIR;

// Looks for storage directory preference
scrollToAndClick(keyTitle);

// Try to save an empty value
onView(withId(android.R.id.edit)).perform(clearText());
onView(withText(android.R.string.ok)).perform(click());

// Open the preference to verify the value in the list remains the default (unchanged)
onView(ViewMatchers.isAssignableFrom(RecyclerView.class))
.check(matches(hasDescendant(withText(defaultValue))));
}

/**
* Test that the Storage Directory preference logic works to automatically append a leading
* slash separator if missing.
*/
@Test
public void testStorageDirectoryValidatesAppendLeadingSlash() {
String keyTitle = context.getString(R.string.prefs_storage_dir);
String expected = File.separator + "my_folder";


// Looks for storage directory preference
scrollToAndClick(keyTitle);

// Try to type a value without a slash
onView(withId(android.R.id.edit)).perform(clearText());
onView(withId(android.R.id.edit))
.perform(typeText("my_folder"));
onView(withText(android.R.string.ok)).perform(click());

// Open the preference to verify the value in the list is the expected
onView(ViewMatchers.isAssignableFrom(RecyclerView.class))
.check(matches(hasDescendant(withText(expected))));
}

/**
* Test Numeric Input logic (GPS Logging Interval): update summary with suffix.
*/
@Test
public void testNumericInputLogic() {
String title = context.getString(R.string.prefs_gps_logging_interval);
String suffix = context.getString(R.string.prefs_gps_logging_interval_seconds);

scrollToAndClick(title);

// Enter a valid number
onView(withId(android.R.id.edit))
.perform(clearText(), typeText("30"));
onView(withText(android.R.string.ok)).perform(click());

// Verify summary format: "30 seconds. <Static Summary>"
onView(ViewMatchers.isAssignableFrom(RecyclerView.class))
.check(matches(hasDescendant(withText(stringContainsInOrder(Arrays.asList("30",
suffix))))));
}

/**
* Test ListPreference custom summary logic (Screen Orientation)
* Should show "Selected Value. \n ..." (don't check for the 2nd line of the summary)
*/
@Test
public void testListPreferenceCustomSummary() {
String title = context.getString(R.string.prefs_ui_orientation);

scrollToAndClick(title);

// Select 1st option from array resource entries
String[] entries = context.getResources()
.getStringArray(R.array.prefs_ui_orientation_options_keys);
onView(withText(entries[0])).perform(click());

// Verify the two-line summary exists
onView(ViewMatchers.isAssignableFrom(RecyclerView.class)).check(matches(hasDescendant(
withText(stringContainsInOrder(Arrays.asList(entries[0], ".\n"))))));
}

/**
* Test Clear OAuth Data logic.
*/
@Test
public void testClearOAuthData() {
String title = context.getString(R.string.prefs_osm_clear_oauth_data);

// Inject a fake token to enable the button
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context)
.edit();
editor.putString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, "fake_token");
editor.commit();

// Relaunch to refresh UI state
ActivityScenario.launch(Preferences.class);


scrollToAndClick(title);

// Click OK on Confirmation Dialog
onView(withText(R.string.prefs_osm_clear_oauth_data_dialog)).check(matches(isDisplayed()));
onView(withText(android.R.string.ok)).perform(click());

// Verify token is gone in prefs
assert(!PreferenceManager.getDefaultSharedPreferences(context)
.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN));
}

// --- Helper Methods ---

/**
* Helper to scroll to a preference in the RecyclerView and click it.
*/
private void scrollToAndClick(String text) {
onView(ViewMatchers.isAssignableFrom(RecyclerView.class))
.perform(RecyclerViewActions.actionOnItem(
hasDescendant(withText(text)),
click()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import net.osmtracker.R;
import net.osmtracker.activity.ButtonsPresets;
import net.osmtracker.activity.Preferences;
import net.osmtracker.db.DataHelper;
import net.osmtracker.util.CustomLayoutsUtils;

import org.junit.After;
Expand Down Expand Up @@ -98,6 +98,6 @@ public void layoutDeletionTest() {
assertFalse(filesAfterDeletion.contains(layoutFileName));

// Check the icons folder was deleted
assertFalse(filesAfterDeletion.contains(layoutName + Preferences.ICONS_DIR_SUFFIX));
assertFalse(filesAfterDeletion.contains(layoutName + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX));
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package net.osmtracker.layouts;

import static androidx.test.espresso.Espresso.onData;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.PreferenceMatchers.withTitleText;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
Expand All @@ -17,11 +14,13 @@

import android.Manifest;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import androidx.lifecycle.Lifecycle;
import androidx.preference.PreferenceManager;
import androidx.test.core.app.ActivityScenario;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.espresso.matcher.ViewMatchers;
import androidx.test.rule.GrantPermissionRule;

import net.osmtracker.OSMTracker;
Expand Down Expand Up @@ -101,7 +100,11 @@ public void navigateToAvailableLayouts() {
// Click on "Settings" in this menu
onView(withText(TestUtils.getStringResource(R.string.menu_settings))).perform(click());
// Click on "Buttons presets" settings
onData(withTitleText(TestUtils.getStringResource(R.string.prefs_ui_buttons_layout))).perform(scrollTo(), click());
onView(ViewMatchers.withId(androidx.preference.R.id.recycler_view))
.perform(RecyclerViewActions.actionOnItem(
ViewMatchers.hasDescendant(withText(R.string.prefs_ui_buttons_layout)),
click()
));
// Wait for "+" to be visible
onView(isRoot()).perform(waitForView(R.id.launch_available, WAIT_VIEW_TIMEOUT));
// Perform a click action on the "+" button
Expand Down
8 changes: 4 additions & 4 deletions app/src/androidTest/java/net/osmtracker/util/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import androidx.preference.PreferenceManager;
import androidx.test.platform.app.InstrumentationRegistry;

import net.osmtracker.OSMTracker;
import net.osmtracker.activity.Preferences;
import net.osmtracker.data.Mocks;
import net.osmtracker.db.DataHelper;

import java.io.File;
import java.io.FileWriter;
Expand Down Expand Up @@ -66,7 +66,7 @@ public static void injectMockLayout(String layoutName, String ISOLangCode) {
writeToFile(newLayout, Mocks.MOCK_LAYOUT_CONTENT);

// Create the icons directory
File iconsDir = createDirectory(layoutsDir, layoutName + Preferences.ICONS_DIR_SUFFIX);
File iconsDir = createDirectory(layoutsDir, layoutName + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX);

// And put some mock files inside
int pngsToCreate = 4;
Expand Down Expand Up @@ -109,7 +109,7 @@ public static File getAppDirectory(){
*/
public static File getLayoutsDirectory(){
String appDirectory = getAppDirectory().getAbsolutePath();
File layoutsDirectory = new File(appDirectory + File.separator + Preferences.LAYOUTS_SUBDIR);
File layoutsDirectory = new File(appDirectory + File.separator + DataHelper.LAYOUTS_SUBDIR);
layoutsDirectory.mkdirs();
return layoutsDirectory;
}
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
android:launchMode="singleTop" />
<activity
android:name=".activity.Preferences"
android:label="@string/prefs" />
android:exported="false"
android:label="@string/prefs"
android:theme="@style/AppTheme" />
<activity
android:name=".activity.WaypointList"
android:label="@string/wplist" />
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/net/osmtracker/activity/About.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import androidx.preference.PreferenceManager;

import java.io.File;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
Expand All @@ -26,6 +25,8 @@
import android.widget.TextView;
import android.widget.Toast;

import androidx.preference.PreferenceManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
Expand Down
Loading