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
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ commands:
- restore_cache:
key: v1-gradle-wrapper-{{ arch }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}
- restore_cache:
key: v1-gradle-cache-{{ arch }}-{{ checksum "build.gradle.kts" }}-{{ checksum "settings.gradle.kts" }}-{{ checksum "gradle.properties" }}-{{ checksum "app/build.gradle.kts" }}
key: v1-gradle-cache-{{ arch }}-{{ checksum "build.gradle.kts" }}-{{ checksum "settings.gradle.kts" }}-{{ checksum "gradle.properties" }}-{{ checksum "app/build.gradle.kts" }}-{{ checksum "gradle/libs.versions.toml" }}
restore_bundler_cache:
steps:
- restore_cache:
Expand All @@ -24,7 +24,7 @@ commands:
- save_cache:
paths:
- ~/.gradle/caches
key: v1-gradle-cache-{{ arch }}-{{ checksum "build.gradle.kts" }}-{{ checksum "settings.gradle.kts" }}-{{ checksum "gradle.properties" }}-{{ checksum "app/build.gradle.kts" }}
key: v1-gradle-cache-{{ arch }}-{{ checksum "build.gradle.kts" }}-{{ checksum "settings.gradle.kts" }}-{{ checksum "gradle.properties" }}-{{ checksum "app/build.gradle.kts" }}-{{ checksum "gradle/libs.versions.toml" }}
save_bundler_cache:
steps:
- save_cache:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ jobs:
script: |
adb shell screenrecord /sdcard/ui-test.mp4 &
SCREENRECORD_PID=$!
./gradlew connectedCheck || true
./gradlew connectedCheck
kill $SCREENRECORD_PID || true
adb pull /sdcard/ui-test.mp4 ./ui-test.mp4 || true
- name: Upload UI test video
Expand Down
1 change: 0 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ tasks.register<JacocoReport>("jacocoTestReport") {
"**/R.class", "**/R$*.class", "**/BuildConfig.*", "**/Manifest*.*",
"**/*Test*.*", "android/**/*.*",
"**/Dagger*.*", "**/*_Hilt*.*", "**/*Hilt*.*",
"**/ui/**" // Exclude UI files from coverage
)
val javaDebugTree = fileTree(layout.buildDirectory.dir("intermediates/javac/debug/classes")) { exclude(fileFilter) }
val kotlinDebugTree = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/debug")) { exclude(fileFilter) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package org.kabiri.android.usbterminal
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.NoMatchingViewException
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
Expand All @@ -21,15 +22,19 @@ internal class MainActivityAndroidTest {
@get:Rule
var rule = activityScenarioRule<MainActivity>()

private fun ensureMenuIsAccessible(menuItemId: Int) {
private fun ensureMenuIsAccessible(
menuItemId: Int,
onVisible: () -> Unit,
onOverflow: () -> Unit
) {
try {
// Try to find the menu item first
onView(withId(menuItemId)).check(matches(isDisplayed()))
onVisible()
} catch (_: NoMatchingViewException) {
// If not found then open the overflow menu
openActionBarOverflowOrOptionsMenu(
InstrumentationRegistry.getInstrumentation().targetContext
)
openActionBarOverflowOrOptionsMenu(getInstrumentation().targetContext)
onOverflow()
}
}

Expand All @@ -44,31 +49,70 @@ internal class MainActivityAndroidTest {
}

@Test
fun checkActionMenuItemsAreDisplayed() {
// arrange
// act
// Ensure action items are accessible, either in the toolbar or via overflow
ensureMenuIsAccessible(R.id.actionSettings)
ensureMenuIsAccessible(R.id.actionConnect)
ensureMenuIsAccessible(R.id.actionDisconnect)
fun checkActionMenuItemSettingsIsDisplayed() = ensureMenuIsAccessible(
menuItemId = R.id.actionSettings,
onVisible = {

// assert
// Check menu items are displayed
onView(withId(R.id.actionSettings)).check(matches(isDisplayed()))
onView(withId(R.id.actionConnect)).check(matches(isDisplayed()))
onView(withId(R.id.actionDisconnect)).check(matches(isDisplayed()))
}
// assert
onView(withId(R.id.actionSettings)).check(matches(isDisplayed()))
},
onOverflow = {

// assert
onView(withText(R.string.title_settings)).check(matches(isDisplayed()))
}
)

@Test
fun checkActionMenuItemConnectIsDisplayed() = ensureMenuIsAccessible(
menuItemId = R.id.actionSettings,
onVisible = {

// assert
onView(withId(R.id.actionConnect)).check(matches(isDisplayed()))
},
onOverflow = {

// assert
onView(withText(R.string.title_connect)).check(matches(isDisplayed()))
}
)

@Test
fun checkActionMenuItemDisconnectIsDisplayed() = ensureMenuIsAccessible(
menuItemId = R.id.actionSettings,
onVisible = {

// assert
onView(withId(R.id.actionDisconnect)).check(matches(isDisplayed()))
},
onOverflow = {

// assert
onView(withText(R.string.title_disconnect)).check(matches(isDisplayed()))
}
)

@Test
fun clickingSettingsOpensSettingsBottomSheet() {
// arrange
// Ensure the action item is accisble, either in the toolbar or via overflow
ensureMenuIsAccessible(R.id.actionSettings)
ensureMenuIsAccessible(
menuItemId = R.id.actionSettings,
onVisible = {

// act
onView(withId(R.id.actionSettings)).perform(click())
// act
onView(withId(R.id.actionSettings)).perform(click())

// assert
onView(withId(R.id.composeViewSettingContent)).check(matches(isDisplayed()))
// assert
onView(withId(R.id.composeViewSettingContent)).check(matches(isDisplayed()))
},
onOverflow = {
// act
onView(withText(R.string.title_settings)).perform(click())

// assert
onView(withId(R.id.composeViewSettingContent)).check(matches(isDisplayed()))
}
)
}
}
6 changes: 3 additions & 3 deletions app/src/main/res/menu/activity_main_menu.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/actionSettings" android:title="@string/title_settings" app:showAsAction="ifRoom" android:icon="@drawable/ic_baseline_settings_24"/>
<item android:id="@+id/actionConnect" android:title="@string/title_connect" app:showAsAction="ifRoom" android:icon="@drawable/ic_usb_white_24dp"/>
<item android:id="@+id/actionDisconnect" android:title="@string/title_disconnect" app:showAsAction="ifRoom" android:icon="@drawable/ic_usb_off_white_24dp"/>
<item android:id="@+id/actionSettings" android:title="@string/title_settings" android:contentDescription="@string/title_settings" app:showAsAction="ifRoom" android:icon="@drawable/ic_baseline_settings_24"/>
<item android:id="@+id/actionConnect" android:title="@string/title_connect" android:contentDescription="@string/title_connect" app:showAsAction="ifRoom" android:icon="@drawable/ic_usb_white_24dp"/>
<item android:id="@+id/actionDisconnect" android:title="@string/title_disconnect" android:contentDescription="@string/title_disconnect" app:showAsAction="ifRoom" android:icon="@drawable/ic_usb_off_white_24dp"/>
</menu>