Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
IllegalArgumentException: Failed requirement.
Sentry Issue: [JETPACK-ANDROID-ETT](https://a8c.sentry.io/issues/4644782022/?referrer=github_integration)

```
IllegalArgumentException: Failed requirement.
    at org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.start(SitePreviewViewModel.kt:84)
    at org.wordpress.android.ui.sitecreation.previews.SiteCreationPreviewFragment.init(SiteCreationPreviewFragment.kt:64)
    at org.wordpress.android.ui.sitecreation.previews.SiteCreationPreviewFragment.init(SiteCreationPreviewFragment.kt:64)
    at org.wordpress.android.ui.sitecreation.previews.SiteCreationPreviewFragment.onViewCreated(SiteCreationPreviewFragment.kt:58)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3137)
...
(13 additional frame(s) were not displayed)
```


Discussion hints:
Might want to investigate replacing `require` with a conditional check and gracefully exit rather than exception.
- This crash started to occur when we re-enabled the domain selection step in the site creation flow.
- It occurs mostly on low-memory devices.
- It occurs when the app is in the background. See `{"phase":"IDLE","is_foreground":false}` in logs.
I don't want to blindly prevent the crash, as it might lead to a worse state in the flow. I haven't been able to reproduce the crash, but I believe this crash is not highly critical since the app will be opened with the newly created site after the crash.

If we can find why `siteCreationState.result` is not `Created`, we can fix that root cause. I'm setting the priority to low.

Pull request: Show error when the site is not created correctly
Fixes #19791

## Description
This PR adds a new error UI state to gracefully handle an unexpected error in the site creation preview screen were the site appears not created.

-----

## To Test:
Since I was not able to reproduce the error in real conditions I added a test and faked the state with an
[error.patch](https://github.com/wordpress-mobile/WordPress-Android/files/14837002/error.patch).
1. Start the site creation (e.g. Site Picker and ➕)
2. Proceed to the end (e.g. with a free wordpress.com domain and plan) and expect a success state
3. Apply the patch above
4. Start the site creation
5. Proceed to the end and expect the new error state


|New Error|Success|
|---|---|
|![Screenshot_20240402_160301](https://github.com/wordpress-mobile/WordPress-Android/assets/304044/651e9cc1-b9a2-4524-8bcc-2671562bb9f1)|![Screenshot_20240402_160522](https://github.com/wordpress-mobile/WordPress-Android/assets/304044/5c744760-76b1-4a6a-a12d-e0fd966b8eaa)|

-----

## Regression Notes

1. Potential unintended areas of impact

    - Site creation

2. What I did to test those areas of impact (or what existing automated tests I relied on)

    - Manual testing

3. What automated tests I added (or what prevented me from doing so)

    - Added a new test case

-----

## PR Submission Checklist:

- [x] I have completed the Regression Notes.
- [x] I have considered adding accessibility improvements for my changes.
- [x] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.

-----

## Testing Checklist (strike-out the not-applying and unnecessary ones):

- [ ] WordPress.com sites and self-hosted Jetpack sites.
- [ ] Portrait and landscape orientations.
- [ ] Light and dark modes.
- [ ] Fonts: Larger, smaller and bold text.
- [ ] High contrast.
- [ ] Talkback.
- [ ] Languages with large words or with letters/accents not frequently used in English.
- [ ] Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
- [ ] Large and small screen sizes. (Tablet and smaller phones)
- [ ] Multi-tasking: Split screen and Pop-up view. (Android 10 or higher)


Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModelTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt
index 0ce6f7a2830f..8ab86f82a9d1 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SiteCreationPreviewFragment.kt
@@ -94,6 +94,10 @@ class SiteCreationPreviewFragment : SiteCreationBaseFormFragment(),
                     uiHelpers.updateVisibility(sitePreviewWebError, ui.webViewErrorVisibility)
                     uiHelpers.updateVisibility(sitePreviewWebViewShimmerLayout, ui.shimmerVisibility)
                 }
+                ui.errorTitle?.let { error ->
+                    siteCreationPreviewHeaderItem.sitePreviewTitle.text =
+                        uiHelpers.getTextOfUiString(requireContext(), error)
+                }
             }
         }
     }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt
index bd7061edf214..8383d1625288 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt
@@ -23,6 +23,7 @@ import org.wordpress.android.ui.sitecreation.misc.SiteCreationTracker
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SitePreviewContentUiState
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SitePreviewLoadingShimmerState
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SitePreviewWebErrorUiState
+import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SiteNotCreatedErrorUiState
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.UrlData
 import org.wordpress.android.ui.sitecreation.services.FetchWpComSiteUseCase
 import org.wordpress.android.ui.sitecreation.usecases.isWordPressComSubDomain
@@ -81,7 +82,10 @@ class SitePreviewViewModel @Inject constructor(
 
     fun start(siteCreationState: SiteCreationState) {
         if (isStarted) return else isStarted = true
-        require(siteCreationState.result is Created)
+        if (siteCreationState.result !is Created) {
+            updateUiState(SiteNotCreatedErrorUiState)
+            return
+        }
         siteDesign = siteCreationState.siteDesign
         result = siteCreationState.result
         isFree = requireNotNull(siteCreationState.domain).isFree
@@ -187,6 +191,7 @@ class SitePreviewViewModel @Inject constructor(
         val shimmerVisibility: Boolean = false,
         val subtitle: UiString,
         val caption: UiString?,
+        val errorTitle: UiString? = null,
     ) {
         data class SitePreviewContentUiState(
             val isFree: Boolean,
@@ -210,6 +215,15 @@ class SitePreviewViewModel @Inject constructor(
             caption = getCaption(isFree),
         )
 
+        data object SiteNotCreatedErrorUiState : SitePreviewUiState(
+            urlData = UrlData("", "", 0 to 0, 0 to 0),
+            webViewVisibility = false,
+            webViewErrorVisibility = true,
+            subtitle = UiStringRes(R.string.site_creation_error_generic_title),
+            caption = UiStringRes(R.string.site_creation_error_generic_subtitle),
+            errorTitle = UiStringRes(R.string.error),
+        )
+
         data class SitePreviewLoadingShimmerState(
             val isFree: Boolean,
             override val urlData: UrlData,


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModelTest.kt
index 8d1d17845f05..e5a0051b219f 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModelTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModelTest.kt
@@ -31,6 +31,7 @@ import org.wordpress.android.ui.sitecreation.SITE_CREATION_STATE
 import org.wordpress.android.ui.sitecreation.SITE_MODEL
 import org.wordpress.android.ui.sitecreation.SITE_REMOTE_ID
 import org.wordpress.android.ui.sitecreation.SUB_DOMAIN
+import org.wordpress.android.ui.sitecreation.SiteCreationResult
 import org.wordpress.android.ui.sitecreation.SiteCreationResult.Created
 import org.wordpress.android.ui.sitecreation.SiteCreationState
 import org.wordpress.android.ui.sitecreation.URL
@@ -38,6 +39,7 @@ import org.wordpress.android.ui.sitecreation.misc.SiteCreationTracker
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SitePreviewContentUiState
 import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SitePreviewWebErrorUiState
+import org.wordpress.android.ui.sitecreation.previews.SitePreviewViewModel.SitePreviewUiState.SiteNotCreatedErrorUiState
 import org.wordpress.android.ui.sitecreation.progress.LOADING_STATE_TEXT_ANIMATION_DELAY
 import org.wordpress.android.ui.sitecreation.services.FetchWpComSiteUseCase
 import org.wordpress.android.util.UrlUtilsWrapper
@@ -86,6 +88,12 @@ class SitePreviewViewModelTest : BaseUnitTest() {
         whenever(siteStore.getSiteBySiteId(SITE_REMOTE_ID)).thenReturn(SITE_MODEL)
     }
 
+    @Test
+    fun `on start show error when result is not created`() = testWith(FETCH_SUCCESS) {
+        startViewModel(SITE_CREATION_STATE.copy(result = SiteCreationResult.NotCreated))
+        assertThat(viewModel.uiState.value).isInstanceOf(SiteNotCreatedErrorUiState::class.java)
+    }
+
     @Test
     fun `on start fetches site by remote id when result is created`() = testWith(FETCH_SUCCESS) {
         startViewModel(SITE_CREATION_STATE.copy(result = RESULT_NOT_IN_LOCAL_DB))