Bug 1875817 - Translations Integration Toolbar Showing
parent
936bb85d6c
commit
ddb15214df
@ -0,0 +1,72 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.browser
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TranslationsState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.translate.Language
|
||||
import mozilla.components.concept.engine.translate.initialFromLanguage
|
||||
import mozilla.components.concept.engine.translate.initialToLanguage
|
||||
import mozilla.components.lib.state.helpers.AbstractBinding
|
||||
|
||||
/**
|
||||
* A binding for observing [TranslationsState] changes
|
||||
* from the [BrowserStore] and updating the translations action button.
|
||||
*
|
||||
* @param browserStore [BrowserStore] observed for any changes related to [TranslationsState].
|
||||
* @param sessionId Current open tab session id.
|
||||
* @param onStateUpdated Invoked when the translations action button should be updated with the new translations state.
|
||||
*/
|
||||
class TranslationsBinding(
|
||||
private val browserStore: BrowserStore,
|
||||
private val sessionId: String,
|
||||
private val onStateUpdated: (
|
||||
isVisible: Boolean,
|
||||
isTranslated: Boolean,
|
||||
fromSelectedLanguage: Language?,
|
||||
toSelectedLanguage: Language?,
|
||||
) -> Unit,
|
||||
) : AbstractBinding<BrowserState>(browserStore) {
|
||||
|
||||
override suspend fun onState(flow: Flow<BrowserState>) {
|
||||
flow.mapNotNull { state -> state.findTab(sessionId) }.distinctUntilChangedBy {
|
||||
it.translationsState
|
||||
}.collect { sessionState ->
|
||||
val translationsState = sessionState.translationsState
|
||||
|
||||
if (translationsState.isTranslated) {
|
||||
val fromSelected = translationsState.translationEngineState?.initialFromLanguage(
|
||||
translationsState.supportedLanguages?.fromLanguages,
|
||||
)
|
||||
val toSelected = translationsState.translationEngineState?.initialToLanguage(
|
||||
translationsState.supportedLanguages?.toLanguages,
|
||||
)
|
||||
|
||||
if (fromSelected != null && toSelected != null) {
|
||||
onStateUpdated(
|
||||
true,
|
||||
true,
|
||||
fromSelected,
|
||||
toSelected,
|
||||
)
|
||||
}
|
||||
} else if (translationsState.isExpectedTranslate) {
|
||||
onStateUpdated(
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
} else {
|
||||
onStateUpdated(false, false, null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.browser
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import mozilla.components.browser.state.action.TranslationsAction
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.translate.DetectedLanguages
|
||||
import mozilla.components.concept.engine.translate.Language
|
||||
import mozilla.components.concept.engine.translate.TranslationEngineState
|
||||
import mozilla.components.concept.engine.translate.TranslationOperation
|
||||
import mozilla.components.concept.engine.translate.TranslationPair
|
||||
import mozilla.components.concept.engine.translate.TranslationSupport
|
||||
import mozilla.components.support.test.ext.joinBlocking
|
||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||
import mozilla.components.support.test.rule.runTestOnMain
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.verify
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TranslationsBindingTest {
|
||||
@get:Rule
|
||||
val coroutineRule = MainCoroutineRule()
|
||||
|
||||
lateinit var browserStore: BrowserStore
|
||||
|
||||
private val tabId = "1"
|
||||
private val tab = createTab(url = tabId, id = tabId)
|
||||
private val onIconChanged: (
|
||||
isVisible: Boolean,
|
||||
isTranslated: Boolean,
|
||||
fromSelectedLanguage: Language?,
|
||||
toSelectedLanguage: Language?,
|
||||
) -> Unit = spy()
|
||||
|
||||
@Test
|
||||
fun `GIVEN translationState WHEN translation status isTranslated THEN invoke onIconChanged callback`() =
|
||||
runTestOnMain {
|
||||
val englishLanguage = Language("en", "English")
|
||||
val spanishLanguage = Language("es", "Spanish")
|
||||
|
||||
browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = listOf(tab),
|
||||
selectedTabId = tabId,
|
||||
),
|
||||
)
|
||||
|
||||
val binding = TranslationsBinding(
|
||||
browserStore = browserStore,
|
||||
sessionId = tabId,
|
||||
onStateUpdated = onIconChanged,
|
||||
)
|
||||
binding.start()
|
||||
|
||||
val detectedLanguages = DetectedLanguages(
|
||||
documentLangTag = englishLanguage.code,
|
||||
supportedDocumentLang = true,
|
||||
userPreferredLangTag = spanishLanguage.code,
|
||||
)
|
||||
|
||||
val translationEngineState = TranslationEngineState(
|
||||
detectedLanguages = detectedLanguages,
|
||||
error = null,
|
||||
isEngineReady = true,
|
||||
requestedTranslationPair = TranslationPair(
|
||||
fromLanguage = englishLanguage.code,
|
||||
toLanguage = spanishLanguage.code,
|
||||
),
|
||||
)
|
||||
|
||||
val supportLanguages = TranslationSupport(
|
||||
fromLanguages = listOf(englishLanguage),
|
||||
toLanguages = listOf(spanishLanguage),
|
||||
)
|
||||
|
||||
browserStore.dispatch(
|
||||
TranslationsAction.SetSupportedLanguagesAction(
|
||||
tabId = tab.id,
|
||||
supportedLanguages = supportLanguages,
|
||||
),
|
||||
).joinBlocking()
|
||||
|
||||
browserStore.dispatch(
|
||||
TranslationsAction.TranslateStateChangeAction(
|
||||
tabId = tabId,
|
||||
translationEngineState = translationEngineState,
|
||||
),
|
||||
).joinBlocking()
|
||||
|
||||
browserStore.dispatch(
|
||||
TranslationsAction.TranslateSuccessAction(
|
||||
tabId = tab.id,
|
||||
operation = TranslationOperation.TRANSLATE,
|
||||
),
|
||||
).joinBlocking()
|
||||
|
||||
verify(onIconChanged).invoke(
|
||||
true,
|
||||
true,
|
||||
englishLanguage,
|
||||
spanishLanguage,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN translationState WHEN translation status isExpectedTranslate THEN invoke onIconChanged callback`() =
|
||||
runTestOnMain {
|
||||
browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = listOf(tab),
|
||||
selectedTabId = tabId,
|
||||
),
|
||||
)
|
||||
|
||||
val binding = TranslationsBinding(
|
||||
browserStore = browserStore,
|
||||
sessionId = tabId,
|
||||
onStateUpdated = onIconChanged,
|
||||
)
|
||||
binding.start()
|
||||
|
||||
browserStore.dispatch(
|
||||
TranslationsAction.TranslateExpectedAction(
|
||||
tabId = tabId,
|
||||
),
|
||||
).joinBlocking()
|
||||
|
||||
verify(onIconChanged).invoke(
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN translationState WHEN translation status is not isExpectedTranslate or isTranslated THEN invoke onIconChanged callback`() =
|
||||
runTestOnMain {
|
||||
browserStore = BrowserStore(
|
||||
BrowserState(
|
||||
tabs = listOf(tab),
|
||||
selectedTabId = tabId,
|
||||
),
|
||||
)
|
||||
|
||||
val binding = TranslationsBinding(
|
||||
browserStore = browserStore,
|
||||
sessionId = tabId,
|
||||
onStateUpdated = onIconChanged,
|
||||
)
|
||||
binding.start()
|
||||
|
||||
verify(onIconChanged).invoke(
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue