Skip to content

Commit 011edfe

Browse files
committed
fix(phone): stop reporting expected phone-parse failures as notifiable Bugsnag warnings
PhoneUtils.makeE164 reported NumberParseException via ErrorUtils.handleError when a user's entered number failed to parse for the selected region — an expected condition mid-onboarding phone verification, surfaced in production Bugsnag as a notifiable warning. Swallow NumberParseException/NumberFormatException silently and return "", matching the sibling toE164/parseInternationalNumber/isPhoneNumberValid methods. Genuinely unexpected exceptions are still routed through ErrorUtils.handleError. Adds PhoneUtilsTest coverage for cleanNumber: valid national/plus-prefixed numbers format to E164, expected parse failures are swallowed without reporting, and unexpected failures are still reported. Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 963e9fe commit 011edfe

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/PhoneUtils.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ class PhoneUtils @Inject constructor(
105105
return try {
106106
val p = phoneNumberUtil.parse(this, (locale ?: Locale.getDefault()).country)
107107
phoneNumberUtil.format(p, PhoneNumberUtil.PhoneNumberFormat.E164)
108-
} catch(e: Exception) {
108+
} catch (e: NumberParseException) {
109+
// Expected when the entered value isn't a valid number for the region
110+
// (e.g. an incomplete number mid-onboarding). Not notifiable.
111+
""
112+
} catch (e: NumberFormatException) {
113+
""
114+
} catch (e: Exception) {
109115
ErrorUtils.handleError(e)
110116
""
111117
}

apps/flipcash/shared/phone/src/test/kotlin/com/flipcash/app/phone/PhoneUtilsTest.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.flipcash.app.phone
22

33
import com.getcode.opencode.exchange.Exchange
4+
import com.getcode.utils.ErrorUtils
45
import io.michaelrocks.libphonenumber.android.PhoneNumberUtil
56
import io.mockk.every
67
import io.mockk.mockk
8+
import io.mockk.mockkObject
79
import io.mockk.mockkStatic
10+
import io.mockk.unmockkObject
811
import io.mockk.unmockkStatic
12+
import io.mockk.verify
913
import org.junit.After
1014
import org.junit.Before
1115
import org.junit.Test
@@ -211,6 +215,67 @@ class PhoneUtilsTest {
211215

212216
// endregion
213217

218+
// region cleanNumber
219+
220+
private val usLocale = CountryLocale(
221+
name = "United States",
222+
phoneCode = 1,
223+
countryCode = "US",
224+
resId = null,
225+
)
226+
227+
@Test
228+
fun `cleanNumber returns E164 for a valid national number`() {
229+
val mockNumber = mockk<io.michaelrocks.libphonenumber.android.Phonenumber.PhoneNumber>(relaxed = true)
230+
every { mockPhoneNumberUtil.parse("12025551234", "US") } returns mockNumber
231+
every { mockPhoneNumberUtil.format(mockNumber, PhoneNumberUtil.PhoneNumberFormat.E164) } returns "+12025551234"
232+
233+
assertEquals("+12025551234", phoneUtils.cleanNumber("2025551234", usLocale))
234+
}
235+
236+
@Test
237+
fun `cleanNumber returns E164 for a number already prefixed with plus`() {
238+
val mockNumber = mockk<io.michaelrocks.libphonenumber.android.Phonenumber.PhoneNumber>(relaxed = true)
239+
every { mockPhoneNumberUtil.parse("+12025551234", "US") } returns mockNumber
240+
every { mockPhoneNumberUtil.format(mockNumber, PhoneNumberUtil.PhoneNumberFormat.E164) } returns "+12025551234"
241+
242+
assertEquals("+12025551234", phoneUtils.cleanNumber("+12025551234", usLocale))
243+
}
244+
245+
@Test
246+
fun `cleanNumber swallows expected parse failure without reporting`() {
247+
mockkObject(ErrorUtils)
248+
try {
249+
every { mockPhoneNumberUtil.parse("1123", "US") } throws
250+
io.michaelrocks.libphonenumber.android.NumberParseException(
251+
io.michaelrocks.libphonenumber.android.NumberParseException.ErrorType.NOT_A_NUMBER,
252+
"incomplete number",
253+
)
254+
255+
// An incomplete number mid-onboarding is expected, not a notifiable error.
256+
assertEquals("", phoneUtils.cleanNumber("123", usLocale))
257+
verify(exactly = 0) { ErrorUtils.handleError(any()) }
258+
} finally {
259+
unmockkObject(ErrorUtils)
260+
}
261+
}
262+
263+
@Test
264+
fun `cleanNumber still reports unexpected failures`() {
265+
mockkObject(ErrorUtils)
266+
try {
267+
every { mockPhoneNumberUtil.parse("12025551234", "US") } throws
268+
IllegalStateException("unexpected")
269+
270+
assertEquals("", phoneUtils.cleanNumber("2025551234", usLocale))
271+
verify(exactly = 1) { ErrorUtils.handleError(any()) }
272+
} finally {
273+
unmockkObject(ErrorUtils)
274+
}
275+
}
276+
277+
// endregion
278+
214279
// region formatNumber
215280

216281
@Test

0 commit comments

Comments
 (0)