Skip to content

Commit

Permalink
Configure supervisor contact (#3404)
Browse files Browse the repository at this point in the history
* Change the contact number to be configurable

* Update changes to strings.xml and test

* Run spotless

* Add changes to LoginScreen and tests

* Remove unused string

* Fix failing tests

* Add ignore test case

* Update

* Fix failing CI

* Update missing tests

* Fix failing test

* Remove unused imports

* Fix loginscreen test

* Add phone number formatting

* Fix failing test

* Run CI test

* Fix codes

* Add changes to the login screen

* Updates

* Fix hardcoded country code

* Fix failing tests

* Refactor super contact number dialer

Signed-off-by: Elly Kitoto <[email protected]>

* Fix launching dial pad

Signed-off-by: Elly Kitoto <[email protected]>

* Fix failing unit tests

Signed-off-by: Elly Kitoto <[email protected]>

---------

Signed-off-by: Elly Kitoto <[email protected]>
Co-authored-by: Peter Lubell-Doughtie <[email protected]>
Co-authored-by: Sebastian <[email protected]>
Co-authored-by: Benjamin Mwalimu <[email protected]>
Co-authored-by: Elly Kitoto <[email protected]>
  • Loading branch information
5 people authored Sep 5, 2024
1 parent bad449e commit 3a93d7d
Show file tree
Hide file tree
Showing 20 changed files with 395 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ data class LoginConfig(
val logoHeight: Int = 120,
val logoWidth: Int = 140,
val showAppTitle: Boolean = true,
val supervisorContactNumber: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.smartregister.fhircore.engine.util.extension

import android.content.Context
import android.telephony.PhoneNumberUtils
import java.text.MessageFormat
import java.text.SimpleDateFormat
import java.util.Date
Expand Down Expand Up @@ -123,3 +125,14 @@ fun String.lastOffset() = this.uppercase() + "_" + SharedPreferenceKey.LAST_OFFS

fun String.spaceByUppercase() =
this.split(Regex("(?=\\p{Upper})")).joinToString(separator = " ").trim()

fun String?.formatPhoneNumber(context: Context): String? {
if (this == null) return null
return try {
PhoneNumberUtils.formatNumber(this, context.resources.configuration.locales.get(0).country)
?: this
} catch (formatException: NumberFormatException) {
Timber.e(formatException, "Error formatting phone number: $this")
this
}
}
1 change: 0 additions & 1 deletion android/engine/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@
<string name="incorrect_pin_please_retry">Code PIN incorrect, veuillez réessayer</string>
<string name="pin_menu_login">Connexion</string>
<string name="forgot_pin">Code PIN oublié ?</string>
<string name="please_contact_supervisor">Veuillez contacter votre superviseur.</string>
<string name="logging_out">Déconnexion. Veuillez patienter...</string>
<string name="session_expired">Session expirée, veuillez vous connecter à nouveau</string>
<string name="sex">Sexe</string>
Expand Down
1 change: 0 additions & 1 deletion android/engine/src/main/res/values-in/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
<string name="incorrect_pin_please_retry">PIN salah, mohon coba lagi</string>
<string name="pin_menu_login">Masuk</string>
<string name="forgot_pin">Lupa PIN?</string>
<string name="please_contact_supervisor">Silakan hubungi supervisor Anda.</string>
<string name="percentage" translatable="false">%</string>
<string name="logging_out">Sedang keluar (log out). Mohon tunggu…</string>
<string name="session_expired">Sesi telah kedaluwarsa dan harus login lagi</string>
Expand Down
1 change: 0 additions & 1 deletion android/engine/src/main/res/values-sw/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@
<string name="incorrect_pin_please_retry">PIN isiyo sahihi, jaribu tena</string>
<string name="pin_menu_login">Ingia</string>
<string name="forgot_pin">Umesahau PIN?</string>
<string name="please_contact_supervisor">Tafadhali wasiliana na msimamizi wako.</string>
<string name="logging_out">Tafadhali subiri... Inatoka kwenye mfumo</string>
<string name="session_expired">Muda wa kipindi chako umeisha. Tafadhali ingia tena.</string>
<string name="sex">Jinsia</string>
Expand Down
6 changes: 3 additions & 3 deletions android/engine/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
<string name="forgot_password">Forgot Password</string>
<string name="forgot_password_title">Forgot Password!</string>
<string name="more">More</string>
<string name="call_supervisor">Please call your supervisor at %1$s</string>
<string name="call_supervisor">Please contact your supervisor.</string>
<string name="cancel" tools:ignore="ButtonCase">CANCEL</string>
<string name="dial_number">DIAL NUMBER</string>
<string name="register">Register</string>
Expand Down Expand Up @@ -113,7 +113,6 @@
<string name="incorrect_pin_please_retry">Incorrect PIN, please try again</string>
<string name="pin_menu_login">Login</string>
<string name="forgot_pin">Forgot PIN?</string>
<string name="please_contact_supervisor">Please contact your supervisor.</string>
<string name="percentage" translatable="false">%</string>
<string name="logging_out">Logging out. Please wait…</string>
<string name="session_expired">Session has been expired and must login again</string>
Expand Down Expand Up @@ -190,10 +189,11 @@
<string name="no_data">No data set</string>
<string name="sync_complete">Sync complete</string>
<string name="sync_error">Sync error</string>
<string name="minutes_remaining">Calculating minutes remaining...</string>
<string name="minutes_remaining">Calculating minutes remaining</string>
<string name="sync_up_inprogress"> %1$d%% Syncing up…</string>
<string name="sync_down_inprogress"> %1$d%% Syncing down…</string>
<string name="default_html_title">file</string>
<string name="retry">RETRY</string>
<string name="unsynced_data_present">There\'s some un-synced data</string>
<string name="missing_supervisor_contact">Supervisor contact missing or the provided phone number is invalid</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import androidx.test.platform.app.InstrumentationRegistry
import junit.framework.TestCase.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Rule
import org.junit.Test
Expand Down Expand Up @@ -60,7 +62,7 @@ class LoginScreenTest {
ApplicationConfiguration(
appTitle = "My app",
appId = "app/debug",
loginConfig = LoginConfig(showLogo = true),
loginConfig = LoginConfig(showLogo = true, supervisorContactNumber = "123-456-7890"),
)

private val context = InstrumentationRegistry.getInstrumentation().targetContext
Expand Down Expand Up @@ -91,10 +93,87 @@ class LoginScreenTest {

@Test
fun testForgotPasswordDialog() {
composeRule.setContent { ForgotPasswordDialog(forgotPassword = {}, onDismissDialog = {}) }
composeRule.setContent {
ForgotPasswordDialog(
forgotPassword = {},
supervisorContactNumber = applicationConfiguration.loginConfig.supervisorContactNumber,
onDismissDialog = {},
)
}
composeRule.onNodeWithTag(PASSWORD_FORGOT_DIALOG).assertExists()
}

@Test
fun testForgotPasswordDialog_DisplayedCorrectly() {
composeRule.setContent {
ForgotPasswordDialog(
supervisorContactNumber = applicationConfiguration.loginConfig.supervisorContactNumber,
forgotPassword = {},
onDismissDialog = {},
)
}
assertDialogContent()
}

private fun assertDialogContent() {
composeRule.onNodeWithTag(PASSWORD_FORGOT_DIALOG).assertExists().assertIsDisplayed()
composeRule
.onNodeWithText(context.getString(R.string.forgot_password_title))
.assertIsDisplayed()
composeRule.onNodeWithText(context.getString(R.string.call_supervisor)).assertIsDisplayed()
composeRule
.onNodeWithText(applicationConfiguration.loginConfig.supervisorContactNumber.toString())
.assertIsDisplayed()
composeRule.onNodeWithText(context.getString(R.string.cancel)).assertIsDisplayed()
composeRule.onNodeWithText(context.getString(R.string.dial_number)).assertIsDisplayed()
}

@Test
fun testForgotPasswordDialog_CancelButton_Click() {
var dismissDialogClicked = false

composeRule.setContent {
ForgotPasswordDialog(
supervisorContactNumber = applicationConfiguration.loginConfig.supervisorContactNumber,
forgotPassword = {},
onDismissDialog = { dismissDialogClicked = true },
)
}
val cancelText = context.getString(R.string.cancel)
composeRule.onNodeWithText(cancelText).performClick()
assertTrue(dismissDialogClicked)
}

@Test
fun testForgotPasswordDialog_DisplaysCorrectContactNumber() {
composeRule.setContent {
ForgotPasswordDialog(
supervisorContactNumber = applicationConfiguration.loginConfig.supervisorContactNumber,
forgotPassword = {},
onDismissDialog = {},
)
}
val contactNumber = applicationConfiguration.loginConfig.supervisorContactNumber
composeRule.onNodeWithText(contactNumber.toString()).assertIsDisplayed()
}

@Test
fun testForgotPasswordDialog_DialNumberButton_Click() {
var forgotPasswordClicked = false
var dismissDialogClicked = false
composeRule.setContent {
ForgotPasswordDialog(
supervisorContactNumber = applicationConfiguration.loginConfig.supervisorContactNumber,
forgotPassword = { forgotPasswordClicked = true },
onDismissDialog = { dismissDialogClicked = true },
)
}
val dialNumber = context.getString(R.string.dial_number)
composeRule.onNodeWithText(dialNumber).performClick()
assert(dismissDialogClicked)
assert(forgotPasswordClicked)
}

@Test
fun testOnDoneKeyboardActionPerformsLoginButtonClicked() {
listenerObjectSpy.attemptRemoteLogin()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,56 @@ import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.smartregister.fhircore.engine.configuration.app.ApplicationConfiguration
import org.smartregister.fhircore.engine.configuration.app.LoginConfig
import org.smartregister.fhircore.engine.ui.components.PIN_CELL_TEST_TAG
import org.smartregister.fhircore.quest.ui.pin.CIRCULAR_PROGRESS_INDICATOR
import org.smartregister.fhircore.quest.ui.pin.ForgotPinDialog
import org.smartregister.fhircore.quest.ui.pin.PIN_LOGO_IMAGE
import org.smartregister.fhircore.quest.ui.pin.PinLoginPage
import org.smartregister.fhircore.quest.ui.pin.PinUiState

class PinLoginScreenKtTest {
@get:Rule(order = 1) val composeRule = createComposeRule()

private val applicationConfiguration =
ApplicationConfiguration(
appTitle = "My app",
appId = "app/debug",
loginConfig = LoginConfig(showLogo = true, supervisorContactNumber = "123-456-7890"),
)

@Test
fun testForgotPasswordDialog_DisplaysCorrectContactNumber() {
// Set the content for the test
composeRule.setContent {
ForgotPinDialog(
supervisorContactNumber = applicationConfiguration.loginConfig.supervisorContactNumber,
forgotPin = {},
onDismissDialog = {},
)
}

// Retrieve the contact number from the context
val contactNumber = applicationConfiguration.loginConfig.supervisorContactNumber

// Assert that the contact number is displayed correctly in the dialog
composeRule.onNodeWithText(contactNumber.toString()).assertIsDisplayed()
}

@Test
fun testThatPinSetupPageIsLaunched() {
composeRule.setContent {
PinLoginPage(
applicationConfiguration =
ApplicationConfiguration(
appId = "appId",
configType = "application",
appTitle = "FHIRCore App",
),
onSetPin = {},
showProgressBar = false,
showError = false,
Expand Down Expand Up @@ -67,10 +102,17 @@ class PinLoginScreenKtTest {
.assertIsDisplayed()
}

@Ignore("This test is currently ignored")
@Test
fun testThatEnterPinPageIsLaunched() {
composeRule.setContent {
PinLoginPage(
applicationConfiguration =
ApplicationConfiguration(
appId = "appId",
configType = "application",
appTitle = "FHIRCore App",
),
onSetPin = {},
showProgressBar = false,
showError = false,
Expand All @@ -88,16 +130,17 @@ class PinLoginScreenKtTest {
onPinEntered = { _: CharArray, _: (Boolean) -> Unit -> },
)
}

composeRule.onNodeWithText("MOH eCBIS", ignoreCase = true).assertExists().assertIsDisplayed()
composeRule
.onNodeWithText("Enter PIN for ecbis", ignoreCase = true)
.assertExists()
.assertIsDisplayed()
composeRule.onAllNodesWithTag(PIN_CELL_TEST_TAG).assertCountEquals(4)
val forgotPinNode = composeRule.onNodeWithText("Forgot PIN?", ignoreCase = true)

val forgotPinNode = composeRule.onNodeWithTag("FORGOT_PIN_TEXT")
forgotPinNode.assertExists().assertIsDisplayed().assertHasClickAction()

// Clicking forgot pin should launch dialog
forgotPinNode.performClick()
composeRule.onNodeWithText("CANCEL").assertIsDisplayed().assertHasClickAction()
composeRule.onNodeWithText("DIAL NUMBER").assertIsDisplayed().assertHasClickAction()
Expand All @@ -108,6 +151,12 @@ class PinLoginScreenKtTest {
val errorMessage = "Incorrect PIN. Please try again."
composeRule.setContent {
PinLoginPage(
applicationConfiguration =
ApplicationConfiguration(
appId = "appId",
configType = "application",
appTitle = "FHIRCore App",
),
onSetPin = {},
showProgressBar = false,
showError = true,
Expand All @@ -132,6 +181,12 @@ class PinLoginScreenKtTest {
fun testThatPinSetupPageShowsCircularProgressIndicator() {
composeRule.setContent {
PinLoginPage(
applicationConfiguration =
ApplicationConfiguration(
appId = "appId",
configType = "application",
appTitle = "FHIRCore App",
),
onSetPin = {},
showProgressBar = true,
showError = false,
Expand Down Expand Up @@ -160,6 +215,12 @@ class PinLoginScreenKtTest {
val pinStateMessage = "Provider will use this PIN to login"
composeRule.setContent {
PinLoginPage(
applicationConfiguration =
ApplicationConfiguration(
appId = "appId",
configType = "application",
appTitle = "FHIRCore App",
),
onSetPin = {},
showProgressBar = false,
showError = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
],
"loginConfig": {
"showLogo": true,
"enablePin": true
"enablePin": true,
"supervisorContactNumber": "1234567890"
},
"deviceToDeviceSync": {
"resourcesToSync": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ open class LoginActivity : BaseMultiLanguageActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.applyWindowInsetListener()

loginViewModel.launchDialPad.observe(
this,
) { phone ->
if (!phone.isNullOrBlank()) {
startActivity(Intent(Intent.ACTION_DIAL).apply { data = Uri.parse("tel:$phone") })
}
}
// Cancel sync background job to get new auth token; login required, refresh token expired
val cancelBackgroundSync =
intent.extras?.getBoolean(TokenAuthenticator.CANCEL_BACKGROUND_SYNC, false) ?: false
Expand Down Expand Up @@ -87,7 +93,7 @@ open class LoginActivity : BaseMultiLanguageActivity() {
} else loginActivity.navigateToHome()
}
}
launchDialPad.observe(loginActivity) { if (!it.isNullOrEmpty()) launchDialPad(it) }
launchDialPad.observe(loginActivity) { if (!it.isNullOrBlank()) launchDialPad(it) }
}
}

Expand Down Expand Up @@ -126,7 +132,7 @@ open class LoginActivity : BaseMultiLanguageActivity() {
)
}

private fun launchDialPad(phone: String) {
startActivity(Intent(Intent.ACTION_DIAL).apply { data = Uri.parse(phone) })
fun launchDialPad(phone: String) {
startActivity(Intent(Intent.ACTION_DIAL).apply { data = Uri.parse("tel:$phone") })
}
}
Loading

0 comments on commit 3a93d7d

Please sign in to comment.