From 98db42147f4cc0311e7c487ebdb6af61082850cd Mon Sep 17 00:00:00 2001 From: "Loren M. Lang" Date: Fri, 28 Jan 2022 02:23:16 -0800 Subject: [PATCH 1/5] Added a test to verify that a chooser is opened for exporting the profile --- .../app/ExampleInstrumentedTest.java | 8 ++-- .../java/org/aprsdroid/app/ProfileTests.java | 46 +++++++++++++++++++ build.gradle | 16 +++++-- 3 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 androidTest/java/org/aprsdroid/app/ProfileTests.java diff --git a/androidTest/java/org/aprsdroid/app/ExampleInstrumentedTest.java b/androidTest/java/org/aprsdroid/app/ExampleInstrumentedTest.java index 85369e0c..e0e19075 100644 --- a/androidTest/java/org/aprsdroid/app/ExampleInstrumentedTest.java +++ b/androidTest/java/org/aprsdroid/app/ExampleInstrumentedTest.java @@ -1,15 +1,15 @@ package org.aprsdroid.app; +import static org.junit.Assert.assertEquals; + import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; import org.junit.Test; import org.junit.runner.RunWith; -import static org.junit.Assert.*; - /** * Instrumented test, which will execute on an Android device. * diff --git a/androidTest/java/org/aprsdroid/app/ProfileTests.java b/androidTest/java/org/aprsdroid/app/ProfileTests.java new file mode 100644 index 00000000..ee1e0a5c --- /dev/null +++ b/androidTest/java/org/aprsdroid/app/ProfileTests.java @@ -0,0 +1,46 @@ +package org.aprsdroid.app; + +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.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.Matchers.allOf; + +import android.app.Instrumentation; +import android.content.Intent; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.intent.Intents; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class ProfileTests { + @Before + public void setUp() { + Intents.init(); + } + + @After + public void tearDown() { + Intents.release(); + } + + @Test + public void testThatExportProfileOpensTheChooser() { + ActivityScenario scenario = ActivityScenario.launch(PrefsAct.class); + Intents.intending(hasAction(Intent.ACTION_CHOOSER)).respondWith(new Instrumentation.ActivityResult(0, null)); + openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().getTargetContext()); + onView(withText(R.string.profile_export)) + .perform(click()); + Intents.intended(hasAction(Intent.ACTION_MAIN)); // Validate the activity launch + Intents.intended(allOf(hasAction(Intent.ACTION_CHOOSER))); + Intents.assertNoUnverifiedIntents(); + } +} diff --git a/build.gradle b/build.gradle index 7f7d6daa..269159d8 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.1' + classpath 'com.android.tools.build:gradle:3.5.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -90,7 +90,7 @@ android { resValue "string", "google_maps_key", mapsApiKey() - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } useLibrary 'org.apache.http.legacy' compileOptions { @@ -167,7 +167,13 @@ dependencies { implementation 'com.squareup.okio:okio:2.1.0' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - testImplementation 'junit:junit:4.12' + + testImplementation 'junit:junit:4.13.1' + testImplementation 'org.hamcrest:hamcrest-core:1.3' + testImplementation 'org.hamcrest:hamcrest-library:1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test:rules:1.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' } From 744526e07bea0c08d20195ef76b5709673b1d67e Mon Sep 17 00:00:00 2001 From: "Loren M. Lang" Date: Sat, 29 Jan 2022 23:33:40 -0800 Subject: [PATCH 2/5] Log any exceptions generated when attempting to export profile --- src/PrefsAct.scala | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/PrefsAct.scala b/src/PrefsAct.scala index f93518d8..5a15d22e 100644 --- a/src/PrefsAct.scala +++ b/src/PrefsAct.scala @@ -9,6 +9,8 @@ import _root_.android.preference.PreferenceActivity import _root_.android.preference.PreferenceManager import _root_.android.view.{Menu, MenuItem} import _root_.android.widget.Toast +import android.util.Log + import java.text.SimpleDateFormat import java.io.{File, PrintWriter} import java.util.Date @@ -16,6 +18,8 @@ import java.util.Date import org.json.JSONObject class PrefsAct extends PreferenceActivity { + val TAG = "APRSdroid.PrefsAct" + lazy val db = StorageDatabase.open(this) lazy val prefs = new PrefsWrapper(this) @@ -33,7 +37,10 @@ class PrefsAct extends PreferenceActivity { UIHelper.shareFile(this, file, filename) } catch { - case e : Exception => Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show() + case e : Exception => { + Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show() + Log.i(TAG, "Caught exception sharing file: " + e, e) + } } } @@ -62,7 +69,7 @@ class PrefsAct extends PreferenceActivity { def resolveContentUri(uri : Uri) = { val Array(storage, path) = uri.getPath().replace("/document/", "").split(":", 2) - android.util.Log.d("PrefsAct", "resolveContentUri s=" + storage + " p=" + path) + android.util.Log.d(TAG, "resolveContentUri s=" + storage + " p=" + path) if (storage == "primary") Environment.getExternalStorageDirectory() + "/" + path else @@ -108,7 +115,7 @@ class PrefsAct extends PreferenceActivity { } override def onActivityResult(reqCode : Int, resultCode : Int, data : Intent) { - android.util.Log.d("PrefsAct", "onActResult: request=" + reqCode + " result=" + resultCode + " " + data) + android.util.Log.d(TAG, "onActResult: request=" + reqCode + " result=" + resultCode + " " + data) if (resultCode == android.app.Activity.RESULT_OK && reqCode == 123456) { parseFilePickerResult(data, "mapfile", R.string.mapfile_error) } else From 95b7259a0b8a2312e661cbccba353104091074c4 Mon Sep 17 00:00:00 2001 From: "Loren M. Lang" Date: Sat, 29 Jan 2022 22:30:55 -0800 Subject: [PATCH 3/5] Don't run tests that require an SD card when it's not present The feature this tests verifies requires an SD card and will fail if it's not available. --- androidTest/java/org/aprsdroid/app/ProfileTests.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/androidTest/java/org/aprsdroid/app/ProfileTests.java b/androidTest/java/org/aprsdroid/app/ProfileTests.java index ee1e0a5c..069774e0 100644 --- a/androidTest/java/org/aprsdroid/app/ProfileTests.java +++ b/androidTest/java/org/aprsdroid/app/ProfileTests.java @@ -6,9 +6,11 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; +import static org.junit.Assume.assumeTrue; import android.app.Instrumentation; import android.content.Intent; +import android.os.Environment; import androidx.test.core.app.ActivityScenario; import androidx.test.espresso.intent.Intents; @@ -34,6 +36,7 @@ public void tearDown() { @Test public void testThatExportProfileOpensTheChooser() { + assumeTrue(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())); ActivityScenario scenario = ActivityScenario.launch(PrefsAct.class); Intents.intending(hasAction(Intent.ACTION_CHOOSER)).respondWith(new Instrumentation.ActivityResult(0, null)); openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().getTargetContext()); From 597618a9cdafb93e285f66d102e24832b4e7fe78 Mon Sep 17 00:00:00 2001 From: "Loren M. Lang" Date: Sat, 29 Jan 2022 00:08:30 -0800 Subject: [PATCH 4/5] Support exporting profiles on pre-19 APIs On pre-19 APIs, the APRSdroid folder is located directly in the top-level of the external storage instead of inside Documents. --- res/xml/file_paths.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/res/xml/file_paths.xml b/res/xml/file_paths.xml index b1b19eb7..a22fa048 100644 --- a/res/xml/file_paths.xml +++ b/res/xml/file_paths.xml @@ -1,3 +1,4 @@ + From 214b77d73f137cc5b9958ffa4b2930d4e192d718 Mon Sep 17 00:00:00 2001 From: "Loren M. Lang" Date: Mon, 31 Jan 2022 22:07:25 -0800 Subject: [PATCH 5/5] Ensure storage permissions are granted for the test --- androidTest/java/org/aprsdroid/app/ProfileTests.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/androidTest/java/org/aprsdroid/app/ProfileTests.java b/androidTest/java/org/aprsdroid/app/ProfileTests.java index 069774e0..2d9efc5d 100644 --- a/androidTest/java/org/aprsdroid/app/ProfileTests.java +++ b/androidTest/java/org/aprsdroid/app/ProfileTests.java @@ -8,6 +8,7 @@ import static org.hamcrest.Matchers.allOf; import static org.junit.Assume.assumeTrue; +import android.Manifest; import android.app.Instrumentation; import android.content.Intent; import android.os.Environment; @@ -16,14 +17,19 @@ import androidx.test.espresso.intent.Intents; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.rule.GrantPermissionRule; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class ProfileTests { + @Rule + public final GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); + @Before public void setUp() { Intents.init();