From 84656ce5268a8d29cf5bf5775bf866f03956f8bc Mon Sep 17 00:00:00 2001 From: Remco Janssen Date: Tue, 17 Jul 2018 21:09:44 +0200 Subject: [PATCH] #47: Clearing Loaders onCleared of Play01ViewModel --- .../dartsscorecard/play/Play01ViewModel.kt | 69 ++++++++++--------- .../play/Play01ViewModelUndoTest.kt | 6 ++ .../play/start/MarkGameAsFinishedUsecase.kt | 4 +- .../domain/setup/game/CreateGameUsecase.kt | 4 +- .../start/MarkGameAsFinishedUsecaseTest.kt | 15 +++- .../setup/game/CreateGameUsecaseTest.kt | 15 +++- 6 files changed, 78 insertions(+), 35 deletions(-) diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt index 40790b80..b30d1792 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt @@ -2,6 +2,7 @@ package nl.entreco.dartsscorecard.play import android.databinding.ObservableBoolean import android.databinding.ObservableInt +import android.support.annotation.StringRes import android.view.Menu import android.view.MenuItem import nl.entreco.dartsscorecard.R @@ -11,6 +12,7 @@ import nl.entreco.dartsscorecard.base.DialogHelper import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier import nl.entreco.dartsscorecard.play.score.TeamScoreListener import nl.entreco.dartsscorecard.play.score.UiCallback +import nl.entreco.domain.Analytics import nl.entreco.domain.common.log.Logger import nl.entreco.domain.model.* import nl.entreco.domain.model.players.Player @@ -20,6 +22,7 @@ import nl.entreco.domain.play.mastercaller.MasterCaller import nl.entreco.domain.play.mastercaller.MasterCallerRequest import nl.entreco.domain.play.mastercaller.ToggleSoundUsecase import nl.entreco.domain.play.revanche.RevancheRequest +import nl.entreco.domain.play.revanche.RevancheResponse import nl.entreco.domain.play.revanche.RevancheUsecase import nl.entreco.domain.play.start.MarkGameAsFinishedRequest import nl.entreco.domain.play.start.Play01Request @@ -51,48 +54,47 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use private lateinit var game: Game private lateinit var request: Play01Request private lateinit var teams: Array - private lateinit var load: GameLoadedNotifier - private lateinit var loaders: Array> + private var load: GameLoadedNotifier? = null + private var loaders: Array>? = null fun load(request: Play01Request, load: GameLoadedNotifier, vararg loaders: GameLoadedNotifier) { - this.request = request this.load = load this.loaders = arrayOf(*loaders) this.playGameUsecase.loadGameAndStart(request, { response -> - this.game = response.game - this.teams = response.teams - this.load.onLoaded(response.teams, game.scores, response.settings, this) - this.loaders.forEach { - it.onLoaded(response.teams, game.scores, response, null) - } + onGameOk(request, response, null) }, - { err -> - logger.e("err: $err") - loading.set(false) - errorMsg.set(R.string.err_unable_to_retrieve_game) - }) + onGameFailed(R.string.err_unable_to_retrieve_game)) } override fun onRevanche() { dialogHelper.revanche(request.startIndex, teams) { startIndex -> val nextTeam = (startIndex) % teams.size revancheUsecase.recreateGameAndStart(RevancheRequest(request, teams, nextTeam), - { response -> - this.request = this.request.copy(gameId = response.game.id, startIndex = nextTeam) - this.game = response.game - this.teams = response.teams - this.load.onLoaded(response.teams, game.scores, response.settings, this) - this.loaders.forEach { - val playResponse = Play01Response(response.game, response.settings, response.teams, response.teamIds) - it.onLoaded(response.teams, game.scores, playResponse, null) - } + { revenge -> + onGameOk(this.request.copy(gameId = revenge.game.id, startIndex = nextTeam), null, revenge) }, - { err -> - logger.e("err: $err") - loading.set(false) - errorMsg.set(R.string.err_unable_to_revanche) - }) + onGameFailed(R.string.err_unable_to_revanche)) + } + } + + private fun onGameOk(request: Play01Request, response: Play01Response?, revancheResponse: RevancheResponse?) { + this.request = request + this.game = response?.game ?: revancheResponse!!.game + this.teams = response?.teams ?: revancheResponse!!.teams + val teamIds = response?.teamIds ?: revancheResponse!!.teamIds + val settings = response?.settings ?: revancheResponse!!.settings + this.load?.onLoaded(teams, game.scores, settings, this) + this.loaders?.forEach { + it.onLoaded(teams, game.scores, response ?: Play01Response(game, settings, teams, teamIds), null) + } + } + + private fun onGameFailed(@StringRes error: Int): (Throwable) -> Unit { + return { err -> + logger.e("err: $err") + loading.set(false) + errorMsg.set(error) } } @@ -120,7 +122,7 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use private fun undoSuccess(): (UndoTurnResponse) -> Unit { return { logger.i("Undo done! -> go to Let's Play Darts Function") - load(request, load, *loaders) + load(request, load!!, *loaders!!) } } @@ -187,8 +189,7 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use State.LEG -> adViewModel.provideInterstitial() State.SET -> adViewModel.provideInterstitial() State.MATCH -> adViewModel.provideInterstitial() - else -> { - } + else -> { /* ignore */ } } } @@ -204,4 +205,10 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use item.isChecked = !item.isChecked toggleSoundUsecase.toggle() } + + override fun onCleared() { + load = null + loaders = null + super.onCleared() + } } diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt index 35090570..7345f121 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt @@ -6,6 +6,7 @@ import nl.entreco.dartsscorecard.base.DialogHelper import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier import nl.entreco.domain.common.log.Logger import nl.entreco.domain.model.Game +import nl.entreco.domain.model.players.Team import nl.entreco.domain.play.mastercaller.MasterCaller import nl.entreco.domain.play.mastercaller.ToggleSoundUsecase import nl.entreco.domain.play.revanche.RevancheUsecase @@ -29,6 +30,8 @@ import org.mockito.junit.MockitoJUnitRunner class Play01ViewModelUndoTest { @Mock private lateinit var mockGame: Game + @Mock private lateinit var mockTeam: Team + @Mock private lateinit var mockSettings: ScoreSettings @Mock private lateinit var mockRequest: Play01Request @Mock private lateinit var mockResponse: Play01Response @Mock private lateinit var mockAdProvider: AdViewModel @@ -75,6 +78,9 @@ class Play01ViewModelUndoTest { private fun givenSubject() { whenever(mockGame.id).thenReturn(5) whenever(mockResponse.game).thenReturn(mockGame) + whenever(mockResponse.teams).thenReturn(arrayOf(mockTeam, mockTeam)) + whenever(mockResponse.teamIds).thenReturn("") + whenever(mockResponse.settings).thenReturn(mockSettings) subject = Play01ViewModel(mockPlay01Usecase, mockRevancheUsecase, mockGameListeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger) subject.load(mockRequest, mockLoad, mockLoaders) diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt index 567961c0..1f1eb3ee 100644 --- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt +++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt @@ -1,5 +1,6 @@ package nl.entreco.domain.play.start +import nl.entreco.domain.Analytics import nl.entreco.domain.BaseUsecase import nl.entreco.domain.common.executors.Background import nl.entreco.domain.common.executors.Foreground @@ -9,9 +10,10 @@ import javax.inject.Inject /** * Created by entreco on 09/01/2018. */ -class MarkGameAsFinishedUsecase @Inject constructor(private val gameRepository: GameRepository, bg: Background, fg: Foreground) : BaseUsecase(bg, fg) { +class MarkGameAsFinishedUsecase @Inject constructor(private val gameRepository: GameRepository, private val analytics: Analytics, bg: Background, fg: Foreground) : BaseUsecase(bg, fg) { fun exec(request: MarkGameAsFinishedRequest) { onBackground({ + analytics.trackAchievement("Game Finished") gameRepository.finish(request.gameId, request.winningTeam) }, {}) } diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt index 64d7e6fc..4d68e50c 100644 --- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt +++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt @@ -1,5 +1,6 @@ package nl.entreco.domain.setup.game +import nl.entreco.domain.Analytics import nl.entreco.domain.BaseUsecase import nl.entreco.domain.common.executors.Background import nl.entreco.domain.common.executors.Foreground @@ -9,10 +10,11 @@ import javax.inject.Inject /** * Created by Entreco on 12/12/2017. */ -class CreateGameUsecase @Inject constructor(private val gameRepository: GameRepository, bg: Background, fg: Foreground) : BaseUsecase(bg, fg) { +class CreateGameUsecase @Inject constructor(private val gameRepository: GameRepository, private val analytics: Analytics, bg: Background, fg: Foreground) : BaseUsecase(bg, fg) { fun exec(request: CreateGameRequest, teamIdString: String, done: (CreateGameResponse) -> Unit, fail: (Throwable) -> Unit) { onBackground({ + analytics.trackAchievement("Game Created") val (score, index, legs, sets) = request val id = gameRepository.create(teamIdString, score, index, legs, sets) onUi { done(CreateGameResponse(id, teamIdString, score, index, legs, sets)) } diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecaseTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecaseTest.kt index b6e74c62..95b089dd 100644 --- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecaseTest.kt +++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecaseTest.kt @@ -3,6 +3,7 @@ package nl.entreco.domain.play.start import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.verify import com.nhaarman.mockito_kotlin.whenever +import nl.entreco.domain.Analytics import nl.entreco.domain.common.executors.TestBackground import nl.entreco.domain.common.executors.TestForeground import nl.entreco.domain.repository.GameRepository @@ -17,6 +18,7 @@ import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) class MarkGameAsFinishedUsecaseTest { + @Mock private lateinit var mockAnalytics: Analytics @Mock private lateinit var mockGameRepository: GameRepository private val bg = TestBackground() private val fg = TestForeground() @@ -39,8 +41,15 @@ class MarkGameAsFinishedUsecaseTest { thenGameIsMarkedAsFinished() } + @Test + fun `it should log "game created" when executing usecase`() { + givenSubject() + whenMarkingGameAsFinished(244) + thenSendToAnalytics("Game Finished") + } + private fun givenSubject() { - subject = MarkGameAsFinishedUsecase(mockGameRepository, bg, fg) + subject = MarkGameAsFinishedUsecase(mockGameRepository, mockAnalytics, bg, fg) } private fun whenMarkingGameAsFinished(gameId: Long) { @@ -60,4 +69,8 @@ class MarkGameAsFinishedUsecaseTest { verify(mockGameRepository).finish(givenId, "1") } + private fun thenSendToAnalytics(expected: String) { + verify(mockAnalytics).trackAchievement(expected) + } + } \ No newline at end of file diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/setup/game/CreateGameUsecaseTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/setup/game/CreateGameUsecaseTest.kt index 64f1d10c..582d8dd6 100644 --- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/setup/game/CreateGameUsecaseTest.kt +++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/setup/game/CreateGameUsecaseTest.kt @@ -3,6 +3,7 @@ package nl.entreco.domain.setup.game import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.eq import com.nhaarman.mockito_kotlin.verify +import nl.entreco.domain.Analytics import nl.entreco.domain.common.executors.TestBackground import nl.entreco.domain.common.executors.TestForeground import nl.entreco.domain.repository.GameRepository @@ -19,6 +20,7 @@ import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) class CreateGameUsecaseTest { + @Mock private lateinit var mockAnalytics: Analytics @Mock private lateinit var mockGameRepository: GameRepository @Mock private lateinit var mockOk: (CreateGameResponse) -> Unit @Mock private lateinit var mockFail: (Throwable) -> Unit @@ -43,8 +45,15 @@ class CreateGameUsecaseTest { thenGameIsStarted() } + @Test + fun `it should log "game created" when executing usecase`() { + givenCreateGameUsecase() + whenStartIsCalled() + thenSendToAnalytics("Game Created") + } + private fun givenCreateGameUsecase() { - subject = CreateGameUsecase(mockGameRepository, mockBg, mockFg) + subject = CreateGameUsecase(mockGameRepository, mockAnalytics, mockBg, mockFg) } private fun whenStartIsCalled() { @@ -55,4 +64,8 @@ class CreateGameUsecaseTest { private fun thenGameIsStarted() { verify(mockOk).invoke(any()) } + + private fun thenSendToAnalytics(expected: String) { + verify(mockAnalytics).trackAchievement(expected) + } }