Bug 1876332 - Refactoring out Translations Controller and Interactor
This patch refactors out the translations controller and interactor to transition fully to a redux pattern. Leaving the translations use cases for reference browser usage.fenix/124.1.0
parent
9aaeacc16f
commit
1dbf0145d5
@ -1,84 +0,0 @@
|
||||
/* 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.translations
|
||||
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.engine.translate.DetectedLanguages
|
||||
import mozilla.components.concept.engine.translate.TranslationOptions
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.support.base.log.logger.Logger
|
||||
|
||||
/**
|
||||
* Manages requests to complete operations with other components.
|
||||
*
|
||||
* @param translationUseCase The use case for performing a translation.
|
||||
* @param browserStore The browser store to use for this controller.
|
||||
* @param tabId The tab to perform operations or complete requests for.
|
||||
*/
|
||||
class TranslationsController(
|
||||
private val translationUseCase: SessionUseCases.TranslateUseCase,
|
||||
private val browserStore: BrowserStore,
|
||||
private val tabId: String,
|
||||
|
||||
) {
|
||||
private val logger = Logger("TranslationsController")
|
||||
|
||||
/**
|
||||
* Retrieves detected information about the language on the browser page, the user's preferred
|
||||
* language, and if the detected page language is supported.
|
||||
*
|
||||
* @return The [DetectedLanguages] object that contains page and user preference information.
|
||||
*/
|
||||
fun getDetectedLanguages(): DetectedLanguages? {
|
||||
logger.info("Retrieving translations language support from the browser store.")
|
||||
return browserStore.state.findTab(tabId)?.translationsState?.translationEngineState?.detectedLanguages
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the page on the given [tabId]. Will fallback to default expectations if
|
||||
* [fromLanguage] and [toLanguage] are not provided.
|
||||
*
|
||||
* @param tabId The ID of the tab to translate.
|
||||
* @param fromLanguage The BCP-47 language code to translate from. If null, the default will
|
||||
* be set to the page language.
|
||||
* @param toLanguage The BCP-47 language code to translate to. If null, the default will
|
||||
* be set to the user's preferred language.
|
||||
* @param options Optional options to specify and additional criteria for the translation.
|
||||
*/
|
||||
fun translate(
|
||||
tabId: String?,
|
||||
fromLanguage: String?,
|
||||
toLanguage: String?,
|
||||
options: TranslationOptions?,
|
||||
) {
|
||||
if (fromLanguage != null && toLanguage != null) {
|
||||
logger.info("Requesting a translation.")
|
||||
translationUseCase.invoke(tabId, fromLanguage, toLanguage, options)
|
||||
return
|
||||
}
|
||||
|
||||
// Fallback to find defaults
|
||||
var defaultFromLanguage = fromLanguage
|
||||
var defaultToLanguage = toLanguage
|
||||
val detectedLanguages = getDetectedLanguages()
|
||||
|
||||
if (defaultFromLanguage == null) {
|
||||
defaultFromLanguage = detectedLanguages?.documentLangTag
|
||||
logger.info("Setting translating to use a default 'from' of $defaultFromLanguage.")
|
||||
}
|
||||
|
||||
if (defaultToLanguage == null) {
|
||||
defaultToLanguage = detectedLanguages?.userPreferredLangTag
|
||||
logger.info("Setting translating to use a default 'to' of $defaultToLanguage.")
|
||||
}
|
||||
|
||||
if (defaultFromLanguage != null && defaultToLanguage != null) {
|
||||
logger.info("Requesting a translation based on defaults.")
|
||||
translationUseCase.invoke(tabId, defaultFromLanguage, defaultToLanguage, options)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/* 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.translations
|
||||
|
||||
import mozilla.components.concept.engine.translate.DetectedLanguages
|
||||
import mozilla.components.concept.engine.translate.TranslationOptions
|
||||
import mozilla.components.support.base.log.logger.Logger
|
||||
|
||||
/**
|
||||
* Manages coordinating the functionality interactions for use in the views.
|
||||
*
|
||||
* @param translationsController The translations controller that requests data and
|
||||
* interactions.
|
||||
*/
|
||||
class TranslationsInteractor(
|
||||
private val translationsController: TranslationsController,
|
||||
) {
|
||||
private val logger = Logger("TranslationsInteractor")
|
||||
|
||||
/**
|
||||
* Retrieves the [DetectedLanguages] applicable to the page.
|
||||
*
|
||||
* @return The [DetectedLanguages] object that contains page and user preference information.
|
||||
*/
|
||||
fun detectedLanguages(): DetectedLanguages? {
|
||||
logger.info("Requesting translations language support from the controller.")
|
||||
return translationsController.getDetectedLanguages()
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the page on the given [tabId].
|
||||
* If null is provided for [fromLanguage] or [toLanguage], the engine will attempt to
|
||||
* find a sensible default.
|
||||
*
|
||||
* @param tabId The ID of the tab to translate.
|
||||
* @param fromLanguage The BCP-47 language code to translate from. Usually will be the detected
|
||||
* page language. If set as null, will revert to a default page language, if known.
|
||||
* @param toLanguage The BCP-47 language code to translate to. Usually will be the user's
|
||||
* preferred language. If set as null, will revert to a default of the user's preferred
|
||||
* language, if known.
|
||||
* @param options Optional options to specify and additional criteria for the translation.
|
||||
*/
|
||||
fun onTranslate(
|
||||
tabId: String?,
|
||||
fromLanguage: String?,
|
||||
toLanguage: String?,
|
||||
options: TranslationOptions?,
|
||||
) {
|
||||
logger.info("Requesting a translation from the controller.")
|
||||
translationsController.translate(tabId, fromLanguage, toLanguage, options)
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/* 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.components.translations
|
||||
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.state.state.TranslationsState
|
||||
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.TranslationEngineState
|
||||
import mozilla.components.concept.engine.translate.TranslationOptions
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.support.test.mock
|
||||
import mozilla.components.support.test.whenever
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.translations.TranslationsController
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class TranslationsControllerTest {
|
||||
|
||||
val tab: TabSessionState = spy(
|
||||
createTab(
|
||||
url = "https://www.firefox.com",
|
||||
title = "Firefox",
|
||||
id = "1",
|
||||
),
|
||||
)
|
||||
private val tabs = spy(listOf(tab))
|
||||
private val browserState = spy(BrowserState(tabs = tabs))
|
||||
private val browserStore = spy(BrowserStore(browserState))
|
||||
|
||||
private val translationsUseCase: SessionUseCases.TranslateUseCase = mock()
|
||||
private val translationsController = spy(TranslationsController(translationUseCase = translationsUseCase, browserStore = browserStore, tabId = tab.id))
|
||||
|
||||
@Test
|
||||
fun `Controller translate called the translate use case as expected`() {
|
||||
val from = "en"
|
||||
val to = "es"
|
||||
val options = TranslationOptions(false)
|
||||
translationsController.translate(tab.id, from, to, options)
|
||||
verify(translationsUseCase).invoke(tab.id, from, to, options)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Controller translate called the translate use case as expected when languages were null`() {
|
||||
val mockFrom = "es"
|
||||
val mockTo = "en"
|
||||
val mockDetectedLanguages = DetectedLanguages(
|
||||
documentLangTag = mockFrom,
|
||||
supportedDocumentLang = true,
|
||||
userPreferredLangTag = mockTo,
|
||||
)
|
||||
whenever(translationsController.getDetectedLanguages()).thenReturn(mockDetectedLanguages)
|
||||
|
||||
val from = null
|
||||
val to = null
|
||||
val options = TranslationOptions(false)
|
||||
translationsController.translate(tab.id, from, to, options)
|
||||
|
||||
verify(translationsUseCase).invoke(tab.id, mockFrom, mockTo, options)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Controller detectedLanguages retrieved the languages as expected`() {
|
||||
val mockFrom = "es"
|
||||
val mockTo = "en"
|
||||
val mockDetectedLanguages = DetectedLanguages(
|
||||
documentLangTag = mockFrom,
|
||||
supportedDocumentLang = true,
|
||||
userPreferredLangTag = mockTo,
|
||||
)
|
||||
val mockState = TranslationsState(
|
||||
translationEngineState = TranslationEngineState(mockDetectedLanguages),
|
||||
)
|
||||
|
||||
whenever(browserState.findTab(tab.id)?.translationsState).thenReturn(mockState)
|
||||
|
||||
val test = translationsController.getDetectedLanguages()
|
||||
|
||||
assertNotNull(test)
|
||||
assertTrue(test?.documentLangTag == mockDetectedLanguages.documentLangTag)
|
||||
assertTrue(test?.userPreferredLangTag == mockDetectedLanguages.userPreferredLangTag)
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/* 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.components.translations
|
||||
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
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.TranslationOptions
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.support.test.mock
|
||||
import mozilla.components.support.test.whenever
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.translations.TranslationsController
|
||||
import org.mozilla.fenix.translations.TranslationsInteractor
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class TranslationsInteractorTest {
|
||||
|
||||
val tab: TabSessionState = spy(
|
||||
createTab(
|
||||
url = "https://www.firefox.com",
|
||||
title = "Firefox",
|
||||
id = "1",
|
||||
),
|
||||
)
|
||||
private val tabs = spy(listOf(tab))
|
||||
private val browserState = spy(BrowserState(tabs = tabs))
|
||||
private val browserStore = spy(BrowserStore(browserState))
|
||||
|
||||
private val translationsUseCase: SessionUseCases.TranslateUseCase = mock()
|
||||
private val translationsController = spy(TranslationsController(translationUseCase = translationsUseCase, browserStore = browserStore, tabId = tab.id))
|
||||
private val interactor = TranslationsInteractor(translationsController)
|
||||
|
||||
@Test
|
||||
fun `Interactor onTranslate called the translate controller as expected`() {
|
||||
val from = "en"
|
||||
val to = "es"
|
||||
val options = TranslationOptions(false)
|
||||
interactor.onTranslate(tab.id, from, to, options)
|
||||
verify(translationsController).translate(tab.id, from, to, options)
|
||||
verify(translationsController, never()).getDetectedLanguages()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Interactor onTranslate called the translate controller as expected when languages are null`() {
|
||||
val mockFrom = "es"
|
||||
val mockTo = "en"
|
||||
val mockDetectedLanguages = DetectedLanguages(
|
||||
documentLangTag = mockFrom,
|
||||
supportedDocumentLang = true,
|
||||
userPreferredLangTag = mockTo,
|
||||
)
|
||||
whenever(translationsController.getDetectedLanguages()).thenReturn(mockDetectedLanguages)
|
||||
|
||||
val from = null
|
||||
val to = null
|
||||
val options = TranslationOptions(false)
|
||||
interactor.onTranslate(tab.id, from, to, options)
|
||||
verify(translationsController).translate(tab.id, from, to, options)
|
||||
verify(translationsController).getDetectedLanguages()
|
||||
verify(translationsUseCase).invoke(tab.id, mockFrom, mockTo, options)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Interactor detectedLanguages called the controller to pull detected languages`() {
|
||||
interactor.detectedLanguages()
|
||||
verify(translationsController).getDetectedLanguages()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue