diff --git a/WordPress/src/main/java/org/wordpress/android/models/usecases/GetBloggingPromptUseCase.kt b/WordPress/src/main/java/org/wordpress/android/models/usecases/GetBloggingPromptUseCase.kt deleted file mode 100644 index cc894bedb246..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/models/usecases/GetBloggingPromptUseCase.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.wordpress.android.models.usecases - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import org.wordpress.android.models.bloggingprompts.BloggingPrompt -import javax.inject.Inject - -class GetBloggingPromptUseCase @Inject constructor() { - // TODO fetch from Store when implementation is ready - fun execute(): Flow = flow { - emit( - BloggingPrompt( - text = "This is a blogging prompt!", - numberOfAnswers = 7, - template = "" - ) - ) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingAction.kt index e18295e073fc..402bce02e4f4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingAction.kt @@ -1,7 +1,9 @@ package org.wordpress.android.ui.bloggingprompts.onboarding -import org.wordpress.android.models.bloggingprompts.BloggingPrompt - sealed class BloggingPromptsOnboardingAction { - data class OpenEditor(val bloggingPrompt: BloggingPrompt) : BloggingPromptsOnboardingAction() + object OpenEditor : BloggingPromptsOnboardingAction() + + object OpenSitePicker : BloggingPromptsOnboardingAction() + + object OpenRemindersIntro : BloggingPromptsOnboardingAction() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingDialogFragment.kt index 636262bd2504..878705f59c33 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingDialogFragment.kt @@ -1,24 +1,24 @@ package org.wordpress.android.ui.bloggingprompts.onboarding -import android.app.Dialog import android.content.Context import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment +import androidx.core.text.bold +import androidx.core.text.buildSpannedString import androidx.lifecycle.ViewModelProvider -import com.google.android.material.button.MaterialButton import org.wordpress.android.R import org.wordpress.android.WordPress -import org.wordpress.android.databinding.BloggingPromptsOnboardingDialogFragmentBinding +import org.wordpress.android.databinding.BloggingPromptsOmboardingDialogContentViewBinding import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenEditor +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenRemindersIntro +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenSitePicker +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingUiState.Ready +import org.wordpress.android.ui.featureintroduction.FeatureIntroductionDialogFragment import org.wordpress.android.util.extensions.exhaustive -import org.wordpress.android.util.extensions.setStatusBarAsSurfaceColor import javax.inject.Inject -class BloggingPromptsOnboardingDialogFragment : DialogFragment() { +class BloggingPromptsOnboardingDialogFragment : FeatureIntroductionDialogFragment() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory private lateinit var viewModel: BloggingPromptsOnboardingViewModel @@ -29,28 +29,14 @@ class BloggingPromptsOnboardingDialogFragment : DialogFragment() { fun newInstance(): BloggingPromptsOnboardingDialogFragment = BloggingPromptsOnboardingDialogFragment() } - override fun getTheme(): Int { - return R.style.BloggingPromptsOnboardingDialogFragment - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val dialog = super.onCreateDialog(savedInstanceState) - viewModel = ViewModelProvider(this, viewModelFactory) - .get(BloggingPromptsOnboardingViewModel::class.java) - dialog.setStatusBarAsSurfaceColor() - return dialog - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View = BloggingPromptsOnboardingDialogFragmentBinding.inflate(inflater).root - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val binding = BloggingPromptsOnboardingDialogFragmentBinding.bind(view) - setupTryNow(binding.tryNow) + viewModel = ViewModelProvider(this, viewModelFactory).get(BloggingPromptsOnboardingViewModel::class.java) + setupTryNowButton() + setupRemindMeButton() + setupHeaderTitle() + setupHeaderIcon() + setupUiStateObserver() setupActionObserver() viewModel.start() } @@ -60,15 +46,59 @@ class BloggingPromptsOnboardingDialogFragment : DialogFragment() { (requireActivity().applicationContext as WordPress).component().inject(this) } - private fun setupTryNow(tryNow: MaterialButton) { - tryNow.setOnClickListener { viewModel.onTryNow() } + private fun setupTryNowButton() { + setPrimaryButtonListener { viewModel.onTryNowClick() } + setPrimaryButtonText(R.string.blogging_prompts_onboarding_try_it_now) + } + + private fun setupRemindMeButton() { + setSecondaryButtonListener { viewModel.onRemindMeClick() } + setSecondaryButtonText(R.string.blogging_prompts_onboarding_remind_me) + } + + private fun setupHeaderTitle() { + setHeaderTitle(R.string.blogging_prompts_onboarding_header_title) + } + + private fun setupHeaderIcon() { + setHeaderIcon(R.drawable.ic_outline_lightbulb_orange_gradient_40dp) + } + + private fun setupContent(readyState: Ready) { + val contentBinding = BloggingPromptsOmboardingDialogContentViewBinding.inflate(layoutInflater) + setContent(contentBinding.root) + with(contentBinding) { + contentTop.text = getString(readyState.contentTopRes) + cardCoverView.setOnClickListener { /*do nothing*/ } + promptCard.promptContent.text = getString(readyState.promptRes) + promptCard.numberOfAnswers.text = getString(readyState.answersRes, readyState.answersCount) + contentBottom.text = getString(readyState.contentBottomRes) + contentNote.text = buildSpannedString { + bold { append("${getString(readyState.contentNoteTitle)} ") } + append(getString(readyState.contentNoteContent)) + } + } + } + + private fun setupUiStateObserver() { + viewModel.uiState.observe(this) { uiState -> + when (uiState) { + is Ready -> { + setupContent(uiState) + } + }.exhaustive + } } private fun setupActionObserver() { - viewModel.action.observe(this, { action -> + viewModel.action.observe(this) { action -> when (action) { is OpenEditor -> ActivityLauncher.openEditorInNewStack(activity) + is OpenSitePicker -> { /*TODO*/ + } + is OpenRemindersIntro -> { /*TODO*/ + } }.exhaustive - }) + } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiState.kt index ac86c23e9b81..e8c2a0b36aa0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiState.kt @@ -1,3 +1,15 @@ package org.wordpress.android.ui.bloggingprompts.onboarding -sealed class BloggingPromptsOnboardingUiState +import androidx.annotation.StringRes + +sealed class BloggingPromptsOnboardingUiState { + data class Ready( + @StringRes val promptRes: Int, + @StringRes val answersRes: Int, + val answersCount: Int, + @StringRes val contentTopRes: Int, + @StringRes val contentBottomRes: Int, + @StringRes val contentNoteTitle: Int, + @StringRes val contentNoteContent: Int + ) : BloggingPromptsOnboardingUiState() +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiStateMapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiStateMapper.kt new file mode 100644 index 000000000000..c19b409f443d --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiStateMapper.kt @@ -0,0 +1,19 @@ +package org.wordpress.android.ui.bloggingprompts.onboarding + +import org.wordpress.android.R +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingUiState.Ready +import javax.inject.Inject + +class BloggingPromptsOnboardingUiStateMapper @Inject constructor() { + fun mapReady(): Ready = Ready( + promptRes = R.string.blogging_prompts_onboarding_card_prompt, + answersRes = R.string.my_site_blogging_prompt_card_number_of_answers, + answersCount = ANSWER_COUNT, + contentTopRes = R.string.blogging_prompts_onboarding_content_top, + contentBottomRes = R.string.blogging_prompts_onboarding_content_bottom, + contentNoteTitle = R.string.blogging_prompts_onboarding_content_note_title, + contentNoteContent = R.string.blogging_prompts_onboarding_content_note_content + ) +} + +private const val ANSWER_COUNT = 19 diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModel.kt index 5e306c83631f..8ecae9f3d595 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModel.kt @@ -3,19 +3,16 @@ package org.wordpress.android.ui.bloggingprompts.onboarding import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.flow.single -import kotlinx.coroutines.launch -import org.wordpress.android.models.bloggingprompts.BloggingPrompt -import org.wordpress.android.models.usecases.GetBloggingPromptUseCase +import org.wordpress.android.fluxc.store.SiteStore import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenEditor +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenRemindersIntro +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenSitePicker import javax.inject.Inject class BloggingPromptsOnboardingViewModel @Inject constructor( - private val getBloggingPromptUseCase: GetBloggingPromptUseCase + private val siteStore: SiteStore, + private val uiStateMapper: BloggingPromptsOnboardingUiStateMapper ) : ViewModel() { - private lateinit var bloggingPrompt: BloggingPrompt - private val _uiState = MutableLiveData() val uiState: LiveData = _uiState @@ -23,12 +20,19 @@ class BloggingPromptsOnboardingViewModel @Inject constructor( val action: LiveData = _action fun start() { - viewModelScope.launch { - bloggingPrompt = getBloggingPromptUseCase.execute().single() - } + _uiState.value = uiStateMapper.mapReady() } - fun onTryNow() { - _action.value = OpenEditor(bloggingPrompt) + fun onTryNowClick() { + // TODO send BloggingPrompt with OpenEditor action when prompt store is ready + _action.value = OpenEditor + } + + fun onRemindMeClick() { + if (siteStore.sitesCount > 1) { + _action.value = OpenSitePicker + } else { + _action.value = OpenRemindersIntro + } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/featureintroduction/FeatureIntroductionDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/featureintroduction/FeatureIntroductionDialogFragment.kt new file mode 100644 index 000000000000..c76ac38f2e19 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/featureintroduction/FeatureIntroductionDialogFragment.kt @@ -0,0 +1,79 @@ +package org.wordpress.android.ui.featureintroduction + +import android.app.Dialog +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.core.content.res.ResourcesCompat +import androidx.fragment.app.DialogFragment +import org.wordpress.android.R +import org.wordpress.android.databinding.FeatureIntroductionDialogFragmentBinding +import org.wordpress.android.util.extensions.setStatusBarAsSurfaceColor + +@Suppress("TooManyFunctions") +abstract class FeatureIntroductionDialogFragment : DialogFragment() { + private var _binding: FeatureIntroductionDialogFragmentBinding? = null + private val binding get() = _binding ?: throw NullPointerException("_binding cannot be null") + + override fun getTheme(): Int { + return R.style.FeatureIntroductionDialogFragment + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialog = super.onCreateDialog(savedInstanceState) + dialog.setStatusBarAsSurfaceColor() + return dialog + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View = FeatureIntroductionDialogFragmentBinding.inflate(inflater).root + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + _binding = FeatureIntroductionDialogFragmentBinding.bind(view) + setupCloseButton() + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + fun setPrimaryButtonListener(listener: () -> Unit) { + binding.primaryButton.setOnClickListener { listener() } + } + + fun setPrimaryButtonText(@StringRes textRes: Int) { + binding.primaryButton.text = getString(textRes) + } + + fun setSecondaryButtonListener(listener: () -> Unit) { + binding.secondaryButton.setOnClickListener { listener() } + } + + fun setSecondaryButtonText(@StringRes textRes: Int) { + binding.secondaryButton.text = getString(textRes) + } + + fun setHeaderTitle(@StringRes headerTitleRes: Int) { + binding.headerTitle.text = getString(headerTitleRes) + } + + fun setHeaderIcon(@DrawableRes headerIconRes: Int) { + binding.headerIcon.setImageDrawable(ResourcesCompat.getDrawable(resources, headerIconRes, context?.theme)) + } + + fun setContent(view: View) { + binding.contentContainer.addView(view) + } + + private fun setupCloseButton() { + binding.closeButton.setOnClickListener { dismiss() } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/util/extensions/ViewExtensions.kt b/WordPress/src/main/java/org/wordpress/android/util/extensions/ViewExtensions.kt index 2f4b8d64b1bc..108ba0dcbed1 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/extensions/ViewExtensions.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/extensions/ViewExtensions.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewTreeObserver import android.view.inputmethod.InputMethodManager import androidx.annotation.DimenRes +import androidx.annotation.StringRes import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SimpleItemAnimator @@ -80,3 +81,5 @@ fun View.focusAndShowKeyboard() { fun RecyclerView.disableAnimation() { (itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false } + +fun View.getString(@StringRes stringRes: Int) = context.getString(stringRes) diff --git a/WordPress/src/main/res/color/lightbulb_orange_background.xml b/WordPress/src/main/res/color/lightbulb_orange_background.xml new file mode 100644 index 000000000000..34dcac8c7a12 --- /dev/null +++ b/WordPress/src/main/res/color/lightbulb_orange_background.xml @@ -0,0 +1,6 @@ + + diff --git a/WordPress/src/main/res/drawable/bg_rectangle_black_60_radius_2dp.xml b/WordPress/src/main/res/drawable/bg_rectangle_black_60_radius_2dp.xml new file mode 100644 index 000000000000..9458d24b8ceb --- /dev/null +++ b/WordPress/src/main/res/drawable/bg_rectangle_black_60_radius_2dp.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/WordPress/src/main/res/drawable/ic_outline_lightbulb_orange_gradient_40dp.xml b/WordPress/src/main/res/drawable/ic_outline_lightbulb_orange_gradient_40dp.xml new file mode 100644 index 000000000000..b419eccfb2a4 --- /dev/null +++ b/WordPress/src/main/res/drawable/ic_outline_lightbulb_orange_gradient_40dp.xml @@ -0,0 +1,10 @@ + + + + diff --git a/WordPress/src/main/res/layout/blogging_prompts_omboarding_dialog_content_view.xml b/WordPress/src/main/res/layout/blogging_prompts_omboarding_dialog_content_view.xml new file mode 100644 index 000000000000..6bac234dec46 --- /dev/null +++ b/WordPress/src/main/res/layout/blogging_prompts_omboarding_dialog_content_view.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + diff --git a/WordPress/src/main/res/layout/blogging_prompts_onboarding_dialog_fragment.xml b/WordPress/src/main/res/layout/blogging_prompts_onboarding_dialog_fragment.xml deleted file mode 100644 index 6112b16c97fb..000000000000 --- a/WordPress/src/main/res/layout/blogging_prompts_onboarding_dialog_fragment.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/feature_introduction_dialog_fragment.xml b/WordPress/src/main/res/layout/feature_introduction_dialog_fragment.xml new file mode 100644 index 000000000000..17e67bf8678f --- /dev/null +++ b/WordPress/src/main/res/layout/feature_introduction_dialog_fragment.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index e1b8c67f4eec..f98022e63938 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -3997,6 +3997,12 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> App icon + Introducing Prompts + The best way to become a better writer is to build a writing habit and share with others — that’s where Prompts come in! + We’ll show you a new prompt each day on your dashboard to help get those creative juices flowing! + Note: + You can learn more and set up reminders at any time in My Site > Settings > Blogging Reminders Try it now Remind me + Cast the movie of your life. diff --git a/WordPress/src/main/res/values/styles.xml b/WordPress/src/main/res/values/styles.xml index 0f4b8db08926..4ebf66ccd279 100644 --- a/WordPress/src/main/res/values/styles.xml +++ b/WordPress/src/main/res/values/styles.xml @@ -1410,16 +1410,16 @@ @style/FullScreenDialogFragmentAnimation - - @@ -1729,4 +1729,15 @@ 0dp viewStart + + + diff --git a/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiStateMapperTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiStateMapperTest.kt new file mode 100644 index 000000000000..84b484346a6b --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingUiStateMapperTest.kt @@ -0,0 +1,58 @@ +package org.wordpress.android.ui.bloggingprompts.onboarding + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import org.wordpress.android.R + +class BloggingPromptsOnboardingUiStateMapperTest { + private val classToTest = BloggingPromptsOnboardingUiStateMapper() + + @Test + fun `Should return correct Ready state string resource for promptRes`() { + val actual = classToTest.mapReady().promptRes + val expected = R.string.blogging_prompts_onboarding_card_prompt + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `Should return correct Ready state string resource for answersRes`() { + val actual = classToTest.mapReady().answersRes + val expected = R.string.my_site_blogging_prompt_card_number_of_answers + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `Should return correct Ready state answers count`() { + val actual = classToTest.mapReady().answersCount + val expected = 19 + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `Should return correct Ready state string resource for contentTopRes`() { + val actual = classToTest.mapReady().contentTopRes + val expected = R.string.blogging_prompts_onboarding_content_top + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `Should return correct Ready state string resource for contentBottomRes`() { + val actual = classToTest.mapReady().contentBottomRes + val expected = R.string.blogging_prompts_onboarding_content_bottom + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `Should return correct Ready state string resource for contentNoteTitle`() { + val actual = classToTest.mapReady().contentNoteTitle + val expected = R.string.blogging_prompts_onboarding_content_note_title + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `Should return correct Ready state string resource for contentNoteContent`() { + val actual = classToTest.mapReady().contentNoteContent + val expected = R.string.blogging_prompts_onboarding_content_note_content + assertThat(actual).isEqualTo(expected) + } +} diff --git a/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModelTest.kt index d8bbaae02380..5cd8c8e3bd98 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/bloggingprompts/onboarding/BloggingPromptsOnboardingViewModelTest.kt @@ -4,37 +4,50 @@ import androidx.lifecycle.Observer import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever -import kotlinx.coroutines.flow.flow import org.junit.Before import org.junit.Test import org.wordpress.android.BaseUnitTest -import org.wordpress.android.models.bloggingprompts.BloggingPrompt -import org.wordpress.android.models.usecases.GetBloggingPromptUseCase +import org.wordpress.android.fluxc.store.SiteStore import org.wordpress.android.test import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenEditor +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenRemindersIntro +import org.wordpress.android.ui.bloggingprompts.onboarding.BloggingPromptsOnboardingAction.OpenSitePicker class BloggingPromptsOnboardingViewModelTest : BaseUnitTest() { - private val getBloggingPromptUseCase: GetBloggingPromptUseCase = mock() - private val bloggingPromptsOnboardingViewModel = BloggingPromptsOnboardingViewModel(getBloggingPromptUseCase) + private val uiStateMapper: BloggingPromptsOnboardingUiStateMapper = mock() + private val siteStore: SiteStore = mock() + private val classToTest = BloggingPromptsOnboardingViewModel(siteStore, uiStateMapper) private val actionObserver: Observer = mock() @Before fun setup() { - bloggingPromptsOnboardingViewModel.action.observeForever(actionObserver) + classToTest.action.observeForever(actionObserver) } @Test - fun `Should execute GetBloggingPromptUseCase when start is called`() = test { - bloggingPromptsOnboardingViewModel.start() - verify(getBloggingPromptUseCase).execute() + fun `Should trigger Ready state when start is called`() { + classToTest.start() + verify(uiStateMapper).mapReady() } @Test - fun `Should trigger OpenEditor action when onTryNow is called`() = test { - val bloggingPrompt: BloggingPrompt = mock() - whenever(getBloggingPromptUseCase.execute()).thenReturn(flow { emit(bloggingPrompt) }) - bloggingPromptsOnboardingViewModel.start() - bloggingPromptsOnboardingViewModel.onTryNow() - verify(actionObserver).onChanged(OpenEditor(bloggingPrompt)) + fun `Should trigger OpenEditor action when onTryNow is called`() { + classToTest.start() + classToTest.onTryNowClick() + verify(actionObserver).onChanged(OpenEditor) + } + + @Test + fun `Should trigger OpenSitePicker if Remind Me is clicked and user has more than 1 site`() = test { + whenever(siteStore.sitesCount).thenReturn(2) + classToTest.onRemindMeClick() + verify(actionObserver).onChanged(OpenSitePicker) + } + + @Test + fun `Should trigger OpenRemindersIntro if Remind Me is clicked and user has only 1 site`() = test { + whenever(siteStore.sitesCount).thenReturn(1) + classToTest.onRemindMeClick() + verify(actionObserver).onChanged(OpenRemindersIntro) } }