Commit f0bfeb3e authored by Tiger Oakes's avatar Tiger Oakes
Browse files

Use interface for PromptDialogFragment

parent 04ffc01c
......@@ -37,7 +37,7 @@ internal class ConfirmDialogFragment : PromptDialogFragment() {
}
private fun onPositiveClickAction() {
feature?.onConfirm(sessionId)
feature?.onConfirm(sessionId, null)
}
companion object {
......
......@@ -15,7 +15,7 @@ internal const val KEY_MESSAGE = "KEY_MESSAGE"
*/
internal abstract class PromptDialogFragment : DialogFragment() {
var feature: PromptFeature? = null
var feature: Prompter? = null
internal val sessionId: String by lazy { requireNotNull(arguments).getString(KEY_SESSION_ID)!! }
......@@ -25,3 +25,31 @@ internal abstract class PromptDialogFragment : DialogFragment() {
val safeArguments get() = requireNotNull(arguments)
}
internal interface Prompter {
/**
* Invoked when a dialog is dismissed. This consumes the [PromptFeature]
* value from the session indicated by [sessionId].
*
* @param sessionId this is the id of the session which requested the prompt.
*/
fun onCancel(sessionId: String)
/**
* Invoked when the user confirms the action on the dialog. This consumes
* the [PromptFeature] value from the session indicated by [sessionId].
*
* @param sessionId that requested to show the dialog.
* @param value an optional value provided by the dialog as a result of confirming the action.
*/
fun onConfirm(sessionId: String, value: Any?)
/**
* Invoked when the user is requesting to clear the selected value from the dialog.
* This consumes the [PromptFeature] value from the session indicated by [sessionId].
*
* @param sessionId that requested to show the dialog.
*/
fun onClear(sessionId: String)
}
......@@ -71,14 +71,14 @@ internal const val FRAGMENT_TAG = "mozac_feature_prompt_dialog"
* need to be requested before a prompt (e.g. a file picker) can be displayed.
* Once the request is completed, [onPermissionsResult] needs to be invoked.
*/
@Suppress("TooManyFunctions")
@Suppress("TooManyFunctions", "LargeClass")
class PromptFeature internal constructor(
private val container: PromptContainer,
private val store: BrowserStore,
private var customTabId: String? = null,
private val fragmentManager: FragmentManager,
onNeedToRequestPermissions: OnNeedToRequestPermissions
) : LifecycleAwareFeature, PermissionsFeature {
) : LifecycleAwareFeature, PermissionsFeature, Prompter {
private var scope: CoroutineScope? = null
private var activePromptRequest: PromptRequest? = null
......@@ -212,7 +212,7 @@ class PromptFeature internal constructor(
*
* @param sessionId this is the id of the session which requested the prompt.
*/
internal fun onCancel(sessionId: String) {
override fun onCancel(sessionId: String) {
store.consumePromptFrom(sessionId) {
when (it) {
is PromptRequest.Dismissible -> it.onDismiss()
......@@ -229,7 +229,7 @@ class PromptFeature internal constructor(
* @param value an optional value provided by the dialog as a result of confirming the action.
*/
@Suppress("UNCHECKED_CAST", "ComplexMethod")
internal fun onConfirm(sessionId: String, value: Any? = null) {
override fun onConfirm(sessionId: String, value: Any?) {
store.consumePromptFrom(sessionId) {
when (it) {
is TimeSelection -> it.onConfirm(value as Date)
......@@ -278,7 +278,7 @@ class PromptFeature internal constructor(
*
* @param sessionId that requested to show the dialog.
*/
internal fun onClear(sessionId: String) {
override fun onClear(sessionId: String) {
store.consumePromptFrom(sessionId) {
when (it) {
is TimeSelection -> it.onClear()
......
......@@ -9,24 +9,33 @@ import android.widget.CheckBox
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.ext.appCompatContext
import mozilla.components.feature.prompts.R.id
import mozilla.components.support.test.mock
import mozilla.ext.appCompatContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
class AlertDialogFragmentTest {
@Mock private lateinit var mockFeature: Prompter
@Before
fun setup() {
initMocks(this)
}
@Test
fun `build dialog`() {
val fragment = spy(
AlertDialogFragment.newInstance("sessionId", "title", "message", true)
)
......@@ -53,7 +62,6 @@ class AlertDialogFragmentTest {
@Test
fun `Alert with hasShownManyDialogs equals false should not have a checkbox`() {
val fragment = spy(
AlertDialogFragment.newInstance("sessionId", "title", "message", false)
)
......@@ -93,9 +101,6 @@ class AlertDialogFragmentTest {
@Test
fun `After checking no more dialogs checkbox feature onNoMoreDialogsChecked must be called`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
AlertDialogFragment.newInstance("sessionId", "title", "message", true)
)
......@@ -119,9 +124,6 @@ class AlertDialogFragmentTest {
@Test
fun `touching outside of the dialog must notify the feature onCancel`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
AlertDialogFragment.newInstance("sessionId", "title", "message", true)
)
......
......@@ -10,19 +10,29 @@ import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.ext.appCompatContext
import mozilla.components.feature.prompts.R.id
import mozilla.components.support.test.mock
import mozilla.ext.appCompatContext
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
class AuthenticationDialogFragmentTest {
@Mock private lateinit var mockFeature: Prompter
@Before
fun setup() {
initMocks(this)
}
@Test
fun `build dialog`() {
......@@ -33,7 +43,7 @@ class AuthenticationDialogFragmentTest {
"message",
"username",
"password",
false
onlyShowPassword = false
)
)
......@@ -120,9 +130,6 @@ class AuthenticationDialogFragmentTest {
@Test
fun `Clicking on positive button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
AuthenticationDialogFragment.newInstance(
"sessionId",
......@@ -149,9 +156,6 @@ class AuthenticationDialogFragmentTest {
@Test
fun `touching outside of the dialog must notify the feature onCancel`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
AuthenticationDialogFragment.newInstance(
"sessionId",
......@@ -171,4 +175,4 @@ class AuthenticationDialogFragmentTest {
verify(mockFeature).onCancel("sessionId")
}
}
\ No newline at end of file
}
......@@ -27,24 +27,36 @@ import mozilla.components.feature.prompts.ChoiceDialogFragment.Companion.MENU_CH
import mozilla.components.feature.prompts.ChoiceDialogFragment.Companion.MULTIPLE_CHOICE_DIALOG_TYPE
import mozilla.components.feature.prompts.ChoiceDialogFragment.Companion.SINGLE_CHOICE_DIALOG_TYPE
import mozilla.components.feature.prompts.ChoiceDialogFragment.Companion.newInstance
import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
import mozilla.ext.appCompatContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doNothing
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
class ChoiceDialogFragmentTest {
@Mock private lateinit var mockFeature: Prompter
private val item = Choice(id = "", label = "item1")
private val subItem = Choice(id = "", label = "sub-item1")
private val separator = Choice(id = "", label = "item1", isASeparator = true)
@Before
fun setup() {
initMocks(this)
}
@Test
fun `Build single choice dialog`() {
......@@ -94,7 +106,7 @@ class ChoiceDialogFragmentTest {
@Test
fun `Will show a single choice item`() {
val choices = arrayOf(Choice(id = "", label = "item1"))
val choices = arrayOf(item)
val fragment = spy(newInstance(choices, "sessionId", SINGLE_CHOICE_DIALOG_TYPE))
......@@ -112,7 +124,7 @@ class ChoiceDialogFragmentTest {
@Test
fun `Will show a menu choice item`() {
val choices = arrayOf(Choice(id = "", label = "item1"))
val choices = arrayOf(item)
val fragment = spy(newInstance(choices, "sessionId", MENU_CHOICE_DIALOG_TYPE))
......@@ -130,7 +142,7 @@ class ChoiceDialogFragmentTest {
@Test
fun `Will show a menu choice separator item`() {
val choices = arrayOf(Choice(id = "", label = "item1", isASeparator = true))
val choices = arrayOf(separator)
val fragment = spy(newInstance(choices, "sessionId", MENU_CHOICE_DIALOG_TYPE))
......@@ -147,7 +159,7 @@ class ChoiceDialogFragmentTest {
@Test(expected = Exception::class)
fun `Will throw an exception to try to create a invalid choice type item`() {
val choices = arrayOf(Choice(id = "", label = "item1", isASeparator = true))
val choices = arrayOf(separator)
val fragment = spy(newInstance(choices, "sessionId", MENU_CHOICE_DIALOG_TYPE))
......@@ -161,11 +173,11 @@ class ChoiceDialogFragmentTest {
fun `Will adapter will return correct view type `() {
val choices = arrayOf(
Choice(id = "", label = "item1"),
Choice(id = "", label = "item1", children = arrayOf()),
Choice(id = "", label = "menu", children = arrayOf()),
Choice(id = "", label = "separator", children = arrayOf(), isASeparator = true),
Choice(id = "", label = "multiple choice")
item,
Choice(id = "", label = "item1", children = arrayOf()),
Choice(id = "", label = "menu", children = arrayOf()),
Choice(id = "", label = "separator", children = arrayOf(), isASeparator = true),
Choice(id = "", label = "multiple choice")
)
var fragment = spy(newInstance(choices, "sessionId", SINGLE_CHOICE_DIALOG_TYPE))
......@@ -262,9 +274,7 @@ class ChoiceDialogFragmentTest {
@Test
fun `Clicking on single choice item notifies the feature`() {
val mockFeature: PromptFeature = mock()
val choices = arrayOf(Choice(id = "", label = "item1"))
val choices = arrayOf(item)
val fragment = spy(newInstance(choices, "sessionId", SINGLE_CHOICE_DIALOG_TYPE))
......@@ -292,9 +302,7 @@ class ChoiceDialogFragmentTest {
@Test
fun `Clicking on menu choice item notifies the feature`() {
val mockFeature: PromptFeature = mock()
val choices = arrayOf(Choice(id = "", label = "item1"))
val choices = arrayOf(item)
val fragment = spy(newInstance(choices, "sessionId", MENU_CHOICE_DIALOG_TYPE))
......@@ -322,9 +330,8 @@ class ChoiceDialogFragmentTest {
@Test
fun `Clicking on multiple choice item notifies the feature`() {
val mockFeature: PromptFeature = mock()
val choices =
arrayOf(Choice(id = "", label = "item1", children = arrayOf(Choice(id = "", label = "sub-item1"))))
arrayOf(Choice(id = "", label = "item1", children = arrayOf(subItem)))
val fragment = spy(newInstance(choices, "sessionId", MULTIPLE_CHOICE_DIALOG_TYPE))
fragment.feature = mockFeature
......@@ -358,9 +365,8 @@ class ChoiceDialogFragmentTest {
@Test
fun `Clicking on selected multiple choice item will notify feature`() {
val mockFeature: PromptFeature = mock()
val choices =
arrayOf(Choice(id = "", label = "item1", selected = true))
arrayOf(item.copy(selected = true))
val fragment = spy(newInstance(choices, "sessionId", MULTIPLE_CHOICE_DIALOG_TYPE))
fragment.feature = mockFeature
......@@ -392,7 +398,6 @@ class ChoiceDialogFragmentTest {
@Test
fun `single choice item with multiple sub-menu groups`() {
val mockFeature: PromptFeature = mock()
val choices = arrayOf(
Choice(
id = "group1",
......
......@@ -14,15 +14,25 @@ import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
import mozilla.ext.appCompatContext
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
class ColorPickerDialogFragmentTest {
@Mock private lateinit var mockFeature: Prompter
@Before
fun setup() {
initMocks(this)
}
@Test
fun `build dialog`() {
......@@ -43,8 +53,6 @@ class ColorPickerDialogFragmentTest {
@Test
fun `clicking on positive button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
ColorPickerDialogFragment.newInstance("sessionId", "#e66465")
)
......@@ -67,8 +75,6 @@ class ColorPickerDialogFragmentTest {
@Test
fun `clicking on negative button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
ColorPickerDialogFragment.newInstance("sessionId", "#e66465")
)
......@@ -89,8 +95,6 @@ class ColorPickerDialogFragmentTest {
@Test
fun `touching outside of the dialog must notify the feature onCancel`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
ColorPickerDialogFragment.newInstance("sessionId", "#e66465")
)
......
......@@ -9,21 +9,26 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.ext.appCompatContext
import mozilla.components.support.test.mock
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
class ConfirmDialogFragmentTest {
@Test
fun `build dialog`() {
@Mock private lateinit var mockFeature: Prompter
private lateinit var fragment: ConfirmDialogFragment
val fragment = spy(
@Before
fun setup() {
initMocks(this)
fragment = spy(
ConfirmDialogFragment.newInstance(
"sessionId",
"title",
......@@ -32,6 +37,10 @@ class ConfirmDialogFragmentTest {
"negativeLabel"
)
)
}
@Test
fun `build dialog`() {
doReturn(appCompatContext).`when`(fragment).requireContext()
......@@ -57,18 +66,6 @@ class ConfirmDialogFragmentTest {
@Test
fun `clicking on positive button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
ConfirmDialogFragment.newInstance(
"sessionId",
"title",
"message",
"positiveLabel",
"negativeLabel"
)
)
fragment.feature = mockFeature
doReturn(appCompatContext).`when`(fragment).requireContext()
......@@ -79,24 +76,12 @@ class ConfirmDialogFragmentTest {
val positiveButton = (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE)
positiveButton.performClick()
verify(mockFeature).onConfirm("sessionId")
verify(mockFeature).onConfirm("sessionId", null)
}
@Test
fun `clicking on negative button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
ConfirmDialogFragment.newInstance(
"sessionId",
"title",
"message",
"positiveLabel",
"negativeLabel"
)
)
fragment.feature = mockFeature
doReturn(appCompatContext).`when`(fragment).requireContext()
......
......@@ -10,21 +10,31 @@ import android.widget.CheckBox
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.ext.appCompatContext
import mozilla.components.feature.prompts.R.id
import mozilla.components.support.test.mock
import mozilla.ext.appCompatContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@RunWith(AndroidJUnit4::class)
class MultiButtonDialogFragmentTest {
@Mock private lateinit var mockFeature: Prompter
@Before
fun setup() {
initMocks(this)
}
@Test
fun `Build dialog`() {
......@@ -96,8 +106,6 @@ class MultiButtonDialogFragmentTest {
@Test
fun `Clicking on a positive button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
MultiButtonDialogFragment.newInstance(
"sessionId",
......@@ -124,8 +132,6 @@ class MultiButtonDialogFragmentTest {
@Test
fun `Clicking on a negative button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
MultiButtonDialogFragment.newInstance(
"sessionId",
......@@ -152,8 +158,6 @@ class MultiButtonDialogFragmentTest {
@Test
fun `Clicking on a neutral button notifies the feature`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
MultiButtonDialogFragment.newInstance(
"sessionId",
......@@ -180,8 +184,6 @@ class MultiButtonDialogFragmentTest {
@Test
fun `After checking no more dialogs checkbox onConfirm must be called with NoMoreDialogs equals true`() {
val mockFeature: PromptFeature = mock()
val fragment = spy(
MultiButtonDialogFragment.newInstance(