diff --git a/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml b/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml index 0b94b409d..d8b5b7ec3 100644 --- a/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml +++ b/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml @@ -202,13 +202,42 @@ onFlowComplete: file: "subflows/get_started_select_school_by_name.yaml" env: SCHOOL_NAME: ${SCHOOL_NAME} +# Test login error when login credential is not valid - Invalid username - tapOn: id: "username" -- inputText: "teacherauser" +- inputText: "teacheruser" - tapOn: id : "password" - inputText: "test123" - tapOn: "Login" +- assertVisible: "Invalid username/password" +- runFlow: + file: "subflows/erase_text.yaml" + env: + TEXT: "teacheruser" + +# Test error when device internet is not connected +- setAirplaneMode: enabled +- extendedWaitUntil: + visible: + id: "internet_disconnected" + timeout: 10000 +- tapOn: + id : "username" +- inputText: "teacherauser" +- tapOn: "Login" +- assertVisible: "Network error: check your connection and try again" + +# Device back to Online mode - Login success +- setAirplaneMode: disabled +- extendedWaitUntil: + visible: + id: "internet_connected" + timeout: 10000 +- assertVisible: + id: "app_title" + text: "Login" +- tapOn: "Login" - assertVisible: id: "nav_home" - tapOn: "Classes" diff --git a/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/App.kt b/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/App.kt index f335d5146..d08eaa5e5 100644 --- a/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/App.kt +++ b/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/App.kt @@ -34,6 +34,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.runtime.collectAsState import androidx.compose.runtime.rememberCoroutineScope import androidx.navigation.compose.rememberNavController +import com.ustadmobile.libcache.connectivitymonitor.ConnectivityMonitor import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -162,8 +163,10 @@ fun App( val coroutineScope = rememberCoroutineScope() val accountManager: RespectAccountManager = koinInject() + val connectivityMonitor: ConnectivityMonitor = koinInject() val biometricAuthUseCase : BiometricAuthUseCase = koinInject() val activeAccount by accountManager.selectedAccountAndPersonFlow.collectAsState(null) + val connectivityState by connectivityMonitor.statusFlow.collectAsState() val topLevelNavItems = if (activeAccount?.isChild == true) { APP_TOP_LEVEL_NAV_ITEMS_FOR_CHILD } else { @@ -209,6 +212,7 @@ fun App( RespectAppBar( compactHeader = (widthClass != SizeClass.EXPANDED), appUiState = appUiStateVal, + isConnectedToInternet = connectivityState.isConnected, navController = navController, topLevelItems = topLevelNavItems, onProfileClick = { diff --git a/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/AppBar.kt b/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/AppBar.kt index 48fc35220..e15e0d1a4 100644 --- a/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/AppBar.kt +++ b/respect-app-compose/src/commonMain/kotlin/world/respect/app/app/AppBar.kt @@ -1,6 +1,7 @@ package world.respect.app.app import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width @@ -65,11 +66,16 @@ import world.respect.shared.viewmodel.app.appstate.AppUiState import world.respect.shared.viewmodel.app.appstate.LoadingUiState +const val INTERNET_CONNECTED_TAG = "internet_connected" + +const val INTERNET_DISCONNECTED_TAG = "internet_disconnected" + @OptIn(ExperimentalMaterial3Api::class) @Composable fun RespectAppBar( compactHeader: Boolean, appUiState: AppUiState, + isConnectedToInternet: Boolean, navController: NavController, onProfileClick: () -> Unit = {}, topLevelItems: List, @@ -131,6 +137,19 @@ fun RespectAppBar( Box( contentAlignment = Alignment.BottomCenter ) { + Spacer( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .testTag( + if (isConnectedToInternet) { + INTERNET_CONNECTED_TAG + } else { + INTERNET_DISCONNECTED_TAG + } + ) + ) + TopAppBar( title = { Text(