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
1 change: 1 addition & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [**][Payments] Fixed a bug when IPP onboarding was not possible to finish from the app [https://github.com/woocommerce/woocommerce-android/pull/12917]
- [*] Fixed shipping lines being editable at all states [https://github.com/woocommerce/woocommerce-android/pull/12890]
- [*] Fixed a crash that occurred when tapping on the customer shipping address in the order details screen [https://github.com/woocommerce/woocommerce-android/pull/12920]
- [**] Enables creating a new WP.com account during Jetpack activation flow [https://github.com/woocommerce/woocommerce-android/issues/11114]

21.1
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import com.woocommerce.android.analytics.AnalyticsTracker
import com.woocommerce.android.analytics.AnalyticsTrackerWrapper
import com.woocommerce.android.model.JetpackStatus
import com.woocommerce.android.ui.login.WPComLoginRepository
import com.woocommerce.android.util.FeatureFlag
import com.woocommerce.android.util.StringUtils
import com.woocommerce.android.viewmodel.MultiLiveEvent
import com.woocommerce.android.viewmodel.MultiLiveEvent.Event.Exit
Expand All @@ -30,7 +29,8 @@ import javax.inject.Inject
class JetpackActivationWPComEmailViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val wpComLoginRepository: WPComLoginRepository,
private val analyticsTrackerWrapper: AnalyticsTrackerWrapper
private val analyticsTrackerWrapper: AnalyticsTrackerWrapper,
private val stringUtils: StringUtils,
) : ScopedViewModel(savedStateHandle) {
private val navArgs: JetpackActivationWPComEmailFragmentArgs by savedStateHandle.navArgs()

Expand Down Expand Up @@ -106,10 +106,10 @@ class JetpackActivationWPComEmailViewModel @Inject constructor(
when (failure?.type) {
AuthOptionsErrorType.UNKNOWN_USER -> {
when {
!StringUtils.isValidEmail(emailOrUsername) ->
!stringUtils.isValidEmail(emailOrUsername) ->
errorMessage.value = R.string.username_not_registered_wpcom

FeatureFlag.JETPACK_FLOW_ACCOUNT_CREATION.isEnabled() -> {
else -> {
triggerEvent(
ShowMagicLinkScreen(
emailOrUsername,
Expand All @@ -119,8 +119,6 @@ class JetpackActivationWPComEmailViewModel @Inject constructor(
)
isSignup = true
}

else -> errorMessage.value = R.string.email_not_registered_wpcom
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ enum class FeatureFlag {
CUSTOM_FIELDS,
REVAMP_WOO_SHIPPING,
OBJECTIVE_SECTION,
POS_NON_SIMPLE_PRODUCT_TYPES,
JETPACK_FLOW_ACCOUNT_CREATION;
POS_NON_SIMPLE_PRODUCT_TYPES;

fun isEnabled(context: Context? = null): Boolean {
return when (this) {
Expand All @@ -33,8 +32,7 @@ enum class FeatureFlag {
ORDER_CREATION_AUTO_TAX_RATE,
WOO_POS_PAYMENTS_ONBOARDING,
REVAMP_WOO_SHIPPING,
POS_NON_SIMPLE_PRODUCT_TYPES,
JETPACK_FLOW_ACCOUNT_CREATION -> PackageUtils.isDebugBuild()
POS_NON_SIMPLE_PRODUCT_TYPES -> PackageUtils.isDebugBuild()

NEW_SHIPPING_SUPPORT,
INBOX,
Expand Down
1 change: 0 additions & 1 deletion WooCommerce/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3429,7 +3429,6 @@
<string name="login_magic_link_auto_sent">We just sent you a magic link to your e-mail address. Please tap the link in the email to log in.</string>
<string name="login_magic_link_button">Log in with magic link</string>

<string name="email_not_registered_wpcom">Hmm, we can\'t find a WordPress.com account connected to this email address.</string>
<string name="username_not_registered_wpcom">Hmm, we can\'t find a WordPress.com account connected to this username. You can enter an email to create a new account.</string>
<string name="login_magic_links_label">We\'ll email you a link that\'ll log you in instantly, no password needed.</string>
<string name="login_get_link_by_email">Get a login link by email</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package com.woocommerce.android.ui.login.jetpack.wpcom

import com.woocommerce.android.OnChangedException
import com.woocommerce.android.R
import com.woocommerce.android.analytics.AnalyticsTrackerWrapper
import com.woocommerce.android.model.JetpackStatus
import com.woocommerce.android.ui.login.WPComLoginRepository
import com.woocommerce.android.ui.login.jetpack.wpcom.JetpackActivationWPComEmailViewModel.ShowMagicLinkScreen
import com.woocommerce.android.ui.login.jetpack.wpcom.JetpackActivationWPComEmailViewModel.ShowPasswordScreen
import com.woocommerce.android.util.StringUtils
import com.woocommerce.android.util.runAndCaptureValues
import com.woocommerce.android.viewmodel.BaseUnitTest
import com.woocommerce.android.viewmodel.MultiLiveEvent
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.assertj.core.api.Assertions.assertThat
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.wordpress.android.fluxc.store.AccountStore.AuthOptionsError
import org.wordpress.android.fluxc.store.AccountStore.AuthOptionsErrorType
import org.wordpress.android.login.AuthOptions
import kotlin.test.Test
import kotlin.test.assertTrue

@OptIn(ExperimentalCoroutinesApi::class)
class JetpackActivationWPComEmailViewModelTest : BaseUnitTest() {
companion object {
const val WPCOM_EMAIL = "[email protected]"
const val UNKNOWN_EMAIL = "[email protected]"
const val UNKNOWN_USERNAME = "newUser"
val JETPACK_STATUS = JetpackStatus(
isJetpackInstalled = true,
isJetpackConnected = false,
wpComEmail = ""
)
}

private val saveStateHandle = JetpackActivationWPComEmailFragmentArgs(
jetpackStatus = JETPACK_STATUS,
).toSavedStateHandle()
private val wpComLoginRepository: WPComLoginRepository = mock()
private val analyticsTrackerWrapper: AnalyticsTrackerWrapper = mock()
private val stringUtils: StringUtils = mock()
private lateinit var viewModel: JetpackActivationWPComEmailViewModel

fun setup(wpComEmail: String) {
saveStateHandle["email"] = wpComEmail
viewModel = JetpackActivationWPComEmailViewModel(
savedStateHandle = saveStateHandle,
wpComLoginRepository = wpComLoginRepository,
analyticsTrackerWrapper = analyticsTrackerWrapper,
stringUtils = stringUtils
)
}

@Test
fun `when close is clicked, then trigger Exit event and clear access token`() = testBlocking {
setup(WPCOM_EMAIL)
val event = viewModel.event.runAndCaptureValues {
viewModel.onCloseClick()
}.last()

assertTrue(event is MultiLiveEvent.Event.Exit)
verify(wpComLoginRepository).clearAccessToken()
}

@Test
fun `given email is not WPcom, when onContinueClick clicked, then trigger ShowMagicLinkScreen with new wpcom account true`() =
testBlocking {
setup(UNKNOWN_EMAIL)
whenever(stringUtils.isValidEmail(UNKNOWN_EMAIL)).thenReturn(true)
whenever(wpComLoginRepository.fetchAuthOptions(UNKNOWN_EMAIL))
.thenReturn(
Result.failure(OnChangedException(AuthOptionsError(AuthOptionsErrorType.UNKNOWN_USER, "")))
)

val event = viewModel.event.runAndCaptureValues {
viewModel.onContinueClick()
}.last()

assertThat(event).isEqualTo(
ShowMagicLinkScreen(
UNKNOWN_EMAIL,
JETPACK_STATUS,
isNewWpComAccount = true
)
)
}

@Test
fun `given username is not WPcom, when onContinueClick clicked, then show user name not wpcom error`() =
testBlocking {
setup(UNKNOWN_USERNAME)
whenever(stringUtils.isValidEmail(UNKNOWN_USERNAME)).thenReturn(false)
whenever(wpComLoginRepository.fetchAuthOptions(UNKNOWN_USERNAME)).thenReturn(
Result.failure(
OnChangedException(
AuthOptionsError(AuthOptionsErrorType.UNKNOWN_USER, "")
)
)
)

val state = viewModel.viewState.runAndCaptureValues {
viewModel.onContinueClick()
}.last()

assertThat(state.errorMessage).isEqualTo(R.string.username_not_registered_wpcom)
}

@Test
fun `given email not allowed, when onContinueClick clicked, then show user name not wpcom error`() =
testBlocking {
setup(UNKNOWN_USERNAME)
whenever(wpComLoginRepository.fetchAuthOptions(UNKNOWN_USERNAME)).thenReturn(
Result.failure(
OnChangedException(
AuthOptionsError(AuthOptionsErrorType.EMAIL_LOGIN_NOT_ALLOWED, "")
)
)
)

val state = viewModel.viewState.runAndCaptureValues {
viewModel.onContinueClick()
}.last()

assertThat(state.errorMessage).isEqualTo(R.string.error_user_username_instead_of_email)
}

@Test
fun `given email is WPcom user, when onContinueClick clicked, then trigger ShowPasswordScreen`() =
testBlocking {
setup(WPCOM_EMAIL)
whenever(wpComLoginRepository.fetchAuthOptions(WPCOM_EMAIL)).thenReturn(
Result.success(
AuthOptions(
isPasswordless = false,
isEmailVerified = true
)
)
)

val event = viewModel.event.runAndCaptureValues {
viewModel.onContinueClick()
}.last()

assertThat(event).isEqualTo(
ShowPasswordScreen(
WPCOM_EMAIL,
JETPACK_STATUS
)
)
}

@Test
fun `given email is WPcom passwordless user, when onContinueClick clicked, then trigger ShowPasswordScreen`() =
testBlocking {
setup(WPCOM_EMAIL)
whenever(wpComLoginRepository.fetchAuthOptions(WPCOM_EMAIL)).thenReturn(
Result.success(
AuthOptions(
isPasswordless = true,
isEmailVerified = true
)
)
)

val event = viewModel.event.runAndCaptureValues {
viewModel.onContinueClick()
}.last()

assertThat(event).isEqualTo(
ShowMagicLinkScreen(
WPCOM_EMAIL,
JETPACK_STATUS,
isNewWpComAccount = false
)
)
}
}
Loading