Loading install-app-lib/installappdemo/src/main/java/foundation/e/apps/installapp/demo/MainActivity.kt +36 −10 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize Loading @@ -20,9 +21,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.layout.layoutId import androidx.compose.ui.unit.dp import androidx.lifecycle.lifecycleScope import foundation.e.apps.installapp.AppInstaller import foundation.e.apps.installapp.AppLoungeConfiguration import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -33,6 +36,7 @@ import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { private val status = MutableStateFlow<String>("Not-connected") private val installStatus = MutableStateFlow<String?>(null) private val appLoungeConfigurationFlow = MutableStateFlow<AppLoungeConfiguration?>(null) private var installJob: Job? = null Loading @@ -43,6 +47,7 @@ class MainActivity : ComponentActivity() { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> InstallAppScreen( modifier = Modifier.padding(innerPadding), appLoungeConfigurationFlow, status, installStatus, ::installApp, Loading @@ -50,6 +55,8 @@ class MainActivity : ComponentActivity() { ) } } getAppLoungeConfiguration() } private fun installApp(packageName: String) { Loading @@ -62,15 +69,22 @@ class MainActivity : ComponentActivity() { } } private fun stopInstallApp() { installJob?.cancel() } private fun getAppLoungeConfiguration() { val appInstaller = AppInstaller(this) lifecycleScope.launch { appLoungeConfigurationFlow.value = appInstaller.getAppLoungeConfiguration() } } } @Composable() fun InstallAppScreen( modifier: Modifier, appLoungeConfigurationFlow: Flow<AppLoungeConfiguration?>, statusFlow: Flow<String>, installStatusFlow: Flow<String?>, installApp: (String) -> Unit, Loading @@ -80,12 +94,28 @@ fun InstallAppScreen( var packageName by remember { mutableStateOf("") } val status by statusFlow.collectAsState("not connected") val installStatus by installStatusFlow.collectAsState(null) val appLoungeConfiguration by appLoungeConfigurationFlow.collectAsState(null) Column( modifier = modifier .fillMaxWidth() .padding(16.dp) .padding(16.dp), verticalArrangement = spacedBy(8.dp) ) { Text("AppLounge configuration") appLoungeConfiguration?.let { Text("GPlayAccountType:") Text( it.gPlayAccountType.name, Modifier.layoutId("GPlayAccountType") ) Text("SearchableSources:") Text( it.searchableSources.joinToString("-"), Modifier.layoutId("SearchableSources"), ) } TextField( value = packageName, onValueChange = { packageName = it }, Loading @@ -94,12 +124,8 @@ fun InstallAppScreen( ) Button( onClick = { installApp(packageName) }, modifier = Modifier .fillMaxWidth() .padding(top = 12.dp) onClick = { installApp(packageName) }, modifier = Modifier.fillMaxWidth().padding(top = 12.dp) ) { Text("Install") } Loading @@ -121,7 +147,7 @@ fun InstallAppScreen( .padding(top = 12.dp) ) { Text("Status: ") Text(status) Text(status, Modifier.layoutId("status")) } installStatus?.let { Row( Loading @@ -130,7 +156,7 @@ fun InstallAppScreen( .padding(top = 12.dp) ) { Text("Install status: ") Text(it) Text(it, Modifier.layoutId("InstallStatus")) } } } Loading maestro/install-app-lib/check_applounge_configuration.yaml 0 → 100644 +12 −0 Original line number Diff line number Diff line # Scenario: install-app-lib show AppLounge configuration # Given InstallAppDemo is installed # When open InstallAppDemo # Then GPlayAccountType shows GPLAY_ACCOUNT_TYPE # And SeachableSrouces shows SEARCHABLE_SOURCES appId: foundation.e.apps.installapp.demo --- - launchApp - assertVisible: ${GPLAY_ACCOUNT_TYPE} - assertVisible: ${SEARCHABLE_SOURCES} maestro/install-app-lib/first_start_google_account.yaml 0 → 100644 +20 −0 Original line number Diff line number Diff line appId: foundation.e.apps --- - launchApp: foundation.e.apps - tapOn: id: foundation.e.apps:id/agreeBT - tapOn: id: foundation.e.apps:id/googleBT - tapOn: PROCEED TO GOOGLE LOGIN - tapOn: Sign in with Google in AppLounge only - tapOn: Email or phone - inputText: ${GOOGLE_ACCOUNT} - tapOn: Next - extendedWaitUntil: visible: Show password timeout: 10000 - inputText: ${GOOGLE_PASSWORD} - tapOn: Next - tapOn: I agree maestro/install-app-lib/run_cleanapk_tests.sh +7 −3 Original line number Diff line number Diff line Loading @@ -14,15 +14,19 @@ adb shell input keyevent 82 adb shell svc wifi enable ## End wake up device. # adb shell pm clear foundation.e.apps # Scenario: Return TODO_error when AppLounge not ready yet maestro test -e GPLAY_ACCOUNT_TYPE=NOT_CONFIGURED -e SEARCHABLE_SOURCES=PLAY_STORE-OPEN_SOURCE-PWA check_applounge_configuration.yaml || exit 1 # Scenario: Return UNAVAILABLE when AppLounge not ready yet maestro test -e PACKAGE_NAME=no.an.existing.packangename -e EXPECTED_STATE=UNAVAILABLE abort_install_apk.yaml || exit 1 # Scenario: Setup AppLounge with anonymous Google account maestro test first_start_nogoogle.yaml || exit 1 # Scenario: AppLounge should be configured with no google now maestro test -e GPLAY_ACCOUNT_TYPE=NO_GOOGLE -e SEARCHABLE_SOURCES=OPEN_SOURCE-PWA check_applounge_configuration.yaml || exit 1 # Scenario: Install FDroid App through install-app-lib adb uninstall com.woefe.shoppinglist maestro test -e PACKAGE_NAME=com.woefe.shoppinglist install_apk.yaml || exit 1 Loading @@ -31,7 +35,7 @@ maestro test -e PACKAGE_NAME=com.woefe.shoppinglist install_apk.yaml || exit 1 maestro test -e PACKAGE_NAME=no.an.existing.packangename -e EXPECTED_STATE=UNAVAILABLE abort_install_apk.yaml || exit 1 # Scenario: Install PWA App through install-app-lib maestro test -e PACKAGE_NAME=dice.richardekwonye.com EXPECTED_STATE=INSTALLED abort_install_apk.yaml || exit 1 maestro test -e PACKAGE_NAME=dice.richardekwonye.com -e EXPECTED_STATE=INSTALLED abort_install_apk.yaml || exit 1 # Scenario: Return error when no network available adb shell svc wifi disable Loading maestro/install-app-lib/run_playstore_tests.sh +10 −3 Original line number Diff line number Diff line #!/bin/bash # Usage: with plugged in device, with AppLounge and applibdemo installed, # $ run_playstore_test GOOGLE_ACCOUNT GOOGLE_PASSWORD cd "$(dirname "$0")" GOOGLE_ACCOUNT=$1 GOOGLE_PASSWORD=$2 # Wake up the device if screen black (not password configured) screen_info=`adb shell dumpsys power | grep mHoldingDisplaySuspendBlocker` if [[ $screen_info == *mHoldingDisplaySuspendBlocker=false* ]] Loading @@ -17,7 +23,9 @@ adb shell svc wifi enable adb shell pm clear foundation.e.apps # Scenario: Setup AppLounge with anonymous Google account maestro test first_start_anonymous.yaml || exit 1 maestro test -e GOOGLE_ACCOUNT=$GOOGLE_ACCOUNT -e GOOGLE_PASSWORD=$GOOGLE_PASSWORD first_start_google_account.yaml || exit 1 maestro test -e GPLAY_ACCOUNT_TYPE=GOOGLE -e SEARCHABLE_SOURCES=PLAY_STORE-OPEN_SOURCE-PWA check_applounge_configuration.yaml || exit 1 # Scenario: Install PlayStore App through install-app-lib adb uninstall com.icedblueberry.shoppinglisteasy Loading @@ -26,6 +34,5 @@ maestro test -e PACKAGE_NAME=com.icedblueberry.shoppinglisteasy install_apk.yaml # Scenario: Return UNAVAILABLE when app unavailable on stores maestro test -e PACKAGE_NAME=no.an.existing.packangename -e EXPECTED_STATE=UNAVAILABLE abort_install_apk.yaml || exit 1 # Scenario: Return error when app not purchased in AppLounge maestro test -e PACKAGE_NAME=nz.co.codepoint.minimetro -e EXPECTED_STATE=PURCHASE_NEEDED abort_install_apk.yaml || exit 1 maestro test -e PACKAGE_NAME=com.MOBGames.PoppyMobileChap1 -e EXPECTED_STATE=PURCHASE_NEEDED abort_install_apk.yaml || exit 1 Loading
install-app-lib/installappdemo/src/main/java/foundation/e/apps/installapp/demo/MainActivity.kt +36 −10 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize Loading @@ -20,9 +21,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.layout.layoutId import androidx.compose.ui.unit.dp import androidx.lifecycle.lifecycleScope import foundation.e.apps.installapp.AppInstaller import foundation.e.apps.installapp.AppLoungeConfiguration import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -33,6 +36,7 @@ import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { private val status = MutableStateFlow<String>("Not-connected") private val installStatus = MutableStateFlow<String?>(null) private val appLoungeConfigurationFlow = MutableStateFlow<AppLoungeConfiguration?>(null) private var installJob: Job? = null Loading @@ -43,6 +47,7 @@ class MainActivity : ComponentActivity() { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> InstallAppScreen( modifier = Modifier.padding(innerPadding), appLoungeConfigurationFlow, status, installStatus, ::installApp, Loading @@ -50,6 +55,8 @@ class MainActivity : ComponentActivity() { ) } } getAppLoungeConfiguration() } private fun installApp(packageName: String) { Loading @@ -62,15 +69,22 @@ class MainActivity : ComponentActivity() { } } private fun stopInstallApp() { installJob?.cancel() } private fun getAppLoungeConfiguration() { val appInstaller = AppInstaller(this) lifecycleScope.launch { appLoungeConfigurationFlow.value = appInstaller.getAppLoungeConfiguration() } } } @Composable() fun InstallAppScreen( modifier: Modifier, appLoungeConfigurationFlow: Flow<AppLoungeConfiguration?>, statusFlow: Flow<String>, installStatusFlow: Flow<String?>, installApp: (String) -> Unit, Loading @@ -80,12 +94,28 @@ fun InstallAppScreen( var packageName by remember { mutableStateOf("") } val status by statusFlow.collectAsState("not connected") val installStatus by installStatusFlow.collectAsState(null) val appLoungeConfiguration by appLoungeConfigurationFlow.collectAsState(null) Column( modifier = modifier .fillMaxWidth() .padding(16.dp) .padding(16.dp), verticalArrangement = spacedBy(8.dp) ) { Text("AppLounge configuration") appLoungeConfiguration?.let { Text("GPlayAccountType:") Text( it.gPlayAccountType.name, Modifier.layoutId("GPlayAccountType") ) Text("SearchableSources:") Text( it.searchableSources.joinToString("-"), Modifier.layoutId("SearchableSources"), ) } TextField( value = packageName, onValueChange = { packageName = it }, Loading @@ -94,12 +124,8 @@ fun InstallAppScreen( ) Button( onClick = { installApp(packageName) }, modifier = Modifier .fillMaxWidth() .padding(top = 12.dp) onClick = { installApp(packageName) }, modifier = Modifier.fillMaxWidth().padding(top = 12.dp) ) { Text("Install") } Loading @@ -121,7 +147,7 @@ fun InstallAppScreen( .padding(top = 12.dp) ) { Text("Status: ") Text(status) Text(status, Modifier.layoutId("status")) } installStatus?.let { Row( Loading @@ -130,7 +156,7 @@ fun InstallAppScreen( .padding(top = 12.dp) ) { Text("Install status: ") Text(it) Text(it, Modifier.layoutId("InstallStatus")) } } } Loading
maestro/install-app-lib/check_applounge_configuration.yaml 0 → 100644 +12 −0 Original line number Diff line number Diff line # Scenario: install-app-lib show AppLounge configuration # Given InstallAppDemo is installed # When open InstallAppDemo # Then GPlayAccountType shows GPLAY_ACCOUNT_TYPE # And SeachableSrouces shows SEARCHABLE_SOURCES appId: foundation.e.apps.installapp.demo --- - launchApp - assertVisible: ${GPLAY_ACCOUNT_TYPE} - assertVisible: ${SEARCHABLE_SOURCES}
maestro/install-app-lib/first_start_google_account.yaml 0 → 100644 +20 −0 Original line number Diff line number Diff line appId: foundation.e.apps --- - launchApp: foundation.e.apps - tapOn: id: foundation.e.apps:id/agreeBT - tapOn: id: foundation.e.apps:id/googleBT - tapOn: PROCEED TO GOOGLE LOGIN - tapOn: Sign in with Google in AppLounge only - tapOn: Email or phone - inputText: ${GOOGLE_ACCOUNT} - tapOn: Next - extendedWaitUntil: visible: Show password timeout: 10000 - inputText: ${GOOGLE_PASSWORD} - tapOn: Next - tapOn: I agree
maestro/install-app-lib/run_cleanapk_tests.sh +7 −3 Original line number Diff line number Diff line Loading @@ -14,15 +14,19 @@ adb shell input keyevent 82 adb shell svc wifi enable ## End wake up device. # adb shell pm clear foundation.e.apps # Scenario: Return TODO_error when AppLounge not ready yet maestro test -e GPLAY_ACCOUNT_TYPE=NOT_CONFIGURED -e SEARCHABLE_SOURCES=PLAY_STORE-OPEN_SOURCE-PWA check_applounge_configuration.yaml || exit 1 # Scenario: Return UNAVAILABLE when AppLounge not ready yet maestro test -e PACKAGE_NAME=no.an.existing.packangename -e EXPECTED_STATE=UNAVAILABLE abort_install_apk.yaml || exit 1 # Scenario: Setup AppLounge with anonymous Google account maestro test first_start_nogoogle.yaml || exit 1 # Scenario: AppLounge should be configured with no google now maestro test -e GPLAY_ACCOUNT_TYPE=NO_GOOGLE -e SEARCHABLE_SOURCES=OPEN_SOURCE-PWA check_applounge_configuration.yaml || exit 1 # Scenario: Install FDroid App through install-app-lib adb uninstall com.woefe.shoppinglist maestro test -e PACKAGE_NAME=com.woefe.shoppinglist install_apk.yaml || exit 1 Loading @@ -31,7 +35,7 @@ maestro test -e PACKAGE_NAME=com.woefe.shoppinglist install_apk.yaml || exit 1 maestro test -e PACKAGE_NAME=no.an.existing.packangename -e EXPECTED_STATE=UNAVAILABLE abort_install_apk.yaml || exit 1 # Scenario: Install PWA App through install-app-lib maestro test -e PACKAGE_NAME=dice.richardekwonye.com EXPECTED_STATE=INSTALLED abort_install_apk.yaml || exit 1 maestro test -e PACKAGE_NAME=dice.richardekwonye.com -e EXPECTED_STATE=INSTALLED abort_install_apk.yaml || exit 1 # Scenario: Return error when no network available adb shell svc wifi disable Loading
maestro/install-app-lib/run_playstore_tests.sh +10 −3 Original line number Diff line number Diff line #!/bin/bash # Usage: with plugged in device, with AppLounge and applibdemo installed, # $ run_playstore_test GOOGLE_ACCOUNT GOOGLE_PASSWORD cd "$(dirname "$0")" GOOGLE_ACCOUNT=$1 GOOGLE_PASSWORD=$2 # Wake up the device if screen black (not password configured) screen_info=`adb shell dumpsys power | grep mHoldingDisplaySuspendBlocker` if [[ $screen_info == *mHoldingDisplaySuspendBlocker=false* ]] Loading @@ -17,7 +23,9 @@ adb shell svc wifi enable adb shell pm clear foundation.e.apps # Scenario: Setup AppLounge with anonymous Google account maestro test first_start_anonymous.yaml || exit 1 maestro test -e GOOGLE_ACCOUNT=$GOOGLE_ACCOUNT -e GOOGLE_PASSWORD=$GOOGLE_PASSWORD first_start_google_account.yaml || exit 1 maestro test -e GPLAY_ACCOUNT_TYPE=GOOGLE -e SEARCHABLE_SOURCES=PLAY_STORE-OPEN_SOURCE-PWA check_applounge_configuration.yaml || exit 1 # Scenario: Install PlayStore App through install-app-lib adb uninstall com.icedblueberry.shoppinglisteasy Loading @@ -26,6 +34,5 @@ maestro test -e PACKAGE_NAME=com.icedblueberry.shoppinglisteasy install_apk.yaml # Scenario: Return UNAVAILABLE when app unavailable on stores maestro test -e PACKAGE_NAME=no.an.existing.packangename -e EXPECTED_STATE=UNAVAILABLE abort_install_apk.yaml || exit 1 # Scenario: Return error when app not purchased in AppLounge maestro test -e PACKAGE_NAME=nz.co.codepoint.minimetro -e EXPECTED_STATE=PURCHASE_NEEDED abort_install_apk.yaml || exit 1 maestro test -e PACKAGE_NAME=com.MOBGames.PoppyMobileChap1 -e EXPECTED_STATE=PURCHASE_NEEDED abort_install_apk.yaml || exit 1