Skip to content

Commit

Permalink
Add UpcomingReleaseUseCaseAssumptions (#188)
Browse files Browse the repository at this point in the history
  • Loading branch information
illarionov authored Oct 18, 2023
1 parent 09cac97 commit cbc0aa1
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import ru.pixnews.foundation.appconfig.AppConfig
import ru.pixnews.foundation.instrumented.test.base.BaseInstrumentedTest
import ru.pixnews.foundation.instrumented.test.di.ContributesTest
import ru.pixnews.foundation.instrumented.test.di.rule.InjectDependenciesRule
import ru.pixnews.test.assumption.UpcomingReleaseUseCaseAssumptions
import javax.inject.Inject

@ContributesTest
Expand All @@ -39,6 +40,9 @@ class CalendarFeedWidthOnMediumSizeTest : BaseInstrumentedTest() {
private val gameFeed = GameFeedElement(composeTestRule)
private var screenWidth: Dp = (-1).dp

@get:Rule
val upcomingReleaseUseCaseAssumptions = UpcomingReleaseUseCaseAssumptions()

@Inject
lateinit var logger: Logger

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import ru.pixnews.MainActivity
import ru.pixnews.domain.model.datetime.Date
import ru.pixnews.domain.model.game.GameFixtures
import ru.pixnews.domain.model.game.game.beyondGoodEvil2
import ru.pixnews.domain.model.game.game.gta6
import ru.pixnews.domain.model.game.game.hytale
import ru.pixnews.domain.model.game.game.sims5
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingRelease
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.CURRENT_MONTH
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.CURRENT_QUARTER
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.FEW_DAYS
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.NEXT_MONTH
import ru.pixnews.feature.calendar.test.constants.UpcomingReleaseGroupId
Expand All @@ -29,8 +33,10 @@ import ru.pixnews.foundation.appconfig.AppConfig
import ru.pixnews.foundation.instrumented.test.base.BaseInstrumentedTest
import ru.pixnews.foundation.instrumented.test.di.ContributesTest
import ru.pixnews.foundation.instrumented.test.di.rule.InjectDependenciesRule
import ru.pixnews.inject.data.MockObserveUpcomingReleasesByDateUseCase.UpcomingReleasesDateFixtures.CurrentMonth
import ru.pixnews.library.instrumented.test.util.assertVerticalPaddingBetweenAdjacentItems
import ru.pixnews.test.assumption.UpcomingReleaseUseCaseAssumptions
import java.time.Month.AUGUST
import java.time.Month.MAY
import javax.inject.Inject

@ContributesTest
Expand All @@ -43,6 +49,9 @@ class CalendarScreenFeedPaddingsTest : BaseInstrumentedTest() {
private val calendarHeader = CalendarHeaderElement(composeTestRule)
private val gameFeed = GameFeedElement(composeTestRule)

@get:Rule
val upcomingReleaseUseCaseAssumptions = UpcomingReleaseUseCaseAssumptions()

@Inject
lateinit var logger: Logger

Expand Down Expand Up @@ -93,8 +102,17 @@ class CalendarScreenFeedPaddingsTest : BaseInstrumentedTest() {

@Test
fun calendarScreen_adjacent_gameCard_gameSubheader_shouldHaveCorrectPadding() {
val dateToday = Date.YearMonthDay(2023, MAY, 17)
val dateTomorrow = Date.YearMonthDay(2023, MAY, 18)

upcomingReleaseUseCaseAssumptions.assumeUpcomingReleasesSuccessfully(
releases = listOf(
UpcomingRelease(GameFixtures.hytale.copy(releaseDate = dateToday), FEW_DAYS),
UpcomingRelease(GameFixtures.gta6.copy(releaseDate = dateTomorrow), FEW_DAYS),
),
)
val gameId = GameFixtures.hytale.id
val dateSubheader = UpcomingReleaseGroupId.YearMonthDay(FEW_DAYS, CurrentMonth.exactDateTomorrow.date)
val dateSubheader = UpcomingReleaseGroupId.YearMonthDay(FEW_DAYS, dateTomorrow.date)

with(gameFeed) {
scrollToGameCard(gameId)
Expand All @@ -113,6 +131,22 @@ class CalendarScreenFeedPaddingsTest : BaseInstrumentedTest() {
fun calendarScreen_adjacent_gameCard_gameCard_shouldHaveCorrectPadding() {
Assume.assumeTrue("Too far scrolling on small screens", Build.VERSION.SDK_INT > 24)

upcomingReleaseUseCaseAssumptions.assumeUpcomingReleasesSuccessfully(
releases = listOf(
UpcomingRelease(
GameFixtures.sims5.copy(
releaseDate = Date.YearMonthDay(2023, AUGUST, 11),
),
CURRENT_QUARTER,
),
UpcomingRelease(
GameFixtures.beyondGoodEvil2.copy(
releaseDate = Date.YearMonth(2023, AUGUST),
),
CURRENT_QUARTER,
),
),
)
val game1Id = GameFixtures.sims5.id
val game2Id = GameFixtures.beyondGoodEvil2.id
with(gameFeed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import ru.pixnews.library.instrumented.test.rule.SystemNavigationRule
import ru.pixnews.library.instrumented.test.rule.SystemNavigationRule.NavigationMode
import ru.pixnews.library.instrumented.test.rule.SystemNavigationRule.NavigationMode.GESTURAL
import ru.pixnews.library.instrumented.test.rule.SystemNavigationRule.NavigationMode.THREE_BUTTON
import ru.pixnews.test.assumption.UpcomingReleaseUseCaseAssumptions
import javax.inject.Inject
import kotlin.LazyThreadSafetyMode.NONE

Expand All @@ -70,6 +71,9 @@ class CalendarScreenVerticalPaddingsTest(
private var calendarHeader = CalendarHeaderElement(composeTestRule)
private var gameFeed = GameFeedElement(composeTestRule)

@get:Rule
val releasesAssumptions = UpcomingReleaseUseCaseAssumptions()

@Inject
lateinit var logger: Logger

Expand All @@ -83,6 +87,8 @@ class CalendarScreenVerticalPaddingsTest(
screenWidth in testSpec.screenWidthDp,
)

releasesAssumptions.assumeUpcomingGamesResponseDefaultGame()

ViewCompat.getRootWindowInsets(composeTestRule.activity.rootView)!!.also { insets ->
val expectedPadding = testSpec.expectedHorizontalPadding(insets, composeTestRule.density)
leftGuideline = expectedPadding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ru.pixnews.feature.root.TopLevelDestination.CALENDAR
import ru.pixnews.foundation.instrumented.test.base.BaseInstrumentedTest
import ru.pixnews.foundation.instrumented.test.di.ContributesTest
import ru.pixnews.foundation.instrumented.test.di.rule.InjectDependenciesRule
import ru.pixnews.test.assumption.UpcomingReleaseUseCaseAssumptions
import javax.inject.Inject

@ContributesTest
Expand All @@ -26,6 +27,9 @@ class FirstScreenTest : BaseInstrumentedTest() {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()

@get:Rule
val upcomingReleaseUseCaseAssumptions = UpcomingReleaseUseCaseAssumptions()

@Inject
lateinit var logger: Logger
private lateinit var bottomBar: BottomBarElement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,116 +6,40 @@
package ru.pixnews.inject.data

import com.squareup.anvil.annotations.ContributesBinding
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableSet
import com.squareup.anvil.annotations.optional.SingleIn
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import ru.pixnews.domain.model.datetime.Date
import ru.pixnews.domain.model.game.GameField
import ru.pixnews.domain.model.game.GameFixtures
import ru.pixnews.domain.model.game.game.beyondGoodEvil2
import ru.pixnews.domain.model.game.game.gta6
import ru.pixnews.domain.model.game.game.halfLife3
import ru.pixnews.domain.model.game.game.hytale
import ru.pixnews.domain.model.game.game.project007
import ru.pixnews.domain.model.game.game.sims5
import ru.pixnews.domain.model.game.game.slimeRancher2
import ru.pixnews.domain.model.game.game.smalland
import ru.pixnews.domain.model.game.game.starWarsEclipse
import ru.pixnews.domain.model.game.game.theLostWild
import ru.pixnews.feature.calendar.data.domain.upcoming.ObserveUpcomingReleasesByDateUseCase
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingRelease
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.CURRENT_MONTH
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.CURRENT_QUARTER
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.CURRENT_YEAR
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.FEW_DAYS
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.TBD
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleasesResponse
import ru.pixnews.feature.calendar.domain.upcoming.DefaultObserveUpcomingReleasesByDateUseCase
import ru.pixnews.foundation.di.base.scopes.AppScope
import ru.pixnews.library.functional.network.NetworkRequestStatus
import java.time.Month.AUGUST
import java.time.Month.JUNE
import java.time.Month.MAY
import javax.inject.Inject

@ContributesBinding(
boundType = ObserveUpcomingReleasesByDateUseCase::class,
scope = AppScope::class,
replaces = [DefaultObserveUpcomingReleasesByDateUseCase::class],
)
@SingleIn(AppScope::class)
class MockObserveUpcomingReleasesByDateUseCase @Inject constructor() : ObserveUpcomingReleasesByDateUseCase {
@get:Synchronized
@set:Synchronized
internal var createUpcomingReleasesObservableResponse: (
requiredFields: Set<GameField>,
) -> Flow<NetworkRequestStatus<UpcomingReleasesResponse>> = NOT_INITIALIZED

override fun createUpcomingReleasesObservable(
requiredFields: Set<GameField>,
): Flow<NetworkRequestStatus<UpcomingReleasesResponse>> {
return flowOf(
NetworkRequestStatus.completeSuccess(
UpcomingReleasesResponse(
requestTime = currentTime.toInstant(currentTimeZone),
requestedFields = requiredFields.toImmutableSet(),
games = releases,
),
),
)
return createUpcomingReleasesObservableResponse(requiredFields)
}

companion object UpcomingReleasesDateFixtures {
val currentTime = LocalDateTime(2023, 5, 17, 10, 0, 0, 0)
val currentTimeZone = TimeZone.of("UTC+3")

// TODO
val releases = persistentListOf(
// 17 May 2023
UpcomingRelease(
// TODO: loading with debug
game = GameFixtures.slimeRancher2.copy(
releaseDate = CurrentMonth.exactDateToday,
),
group = FEW_DAYS,
),
UpcomingRelease(GameFixtures.hytale.copy(releaseDate = CurrentMonth.exactDateToday), FEW_DAYS),

// 18 May 2023
UpcomingRelease(GameFixtures.gta6.copy(releaseDate = CurrentMonth.exactDateTomorrow), FEW_DAYS),
UpcomingRelease(GameFixtures.theLostWild.copy(releaseDate = CurrentMonth.exactDateTomorrow), FEW_DAYS),

// TBD May 2023
UpcomingRelease(GameFixtures.starWarsEclipse.copy(releaseDate = CurrentMonth.approxDate), CURRENT_MONTH),

// TBD 1 Quarter 2023
UpcomingRelease(GameFixtures.sims5.copy(releaseDate = CurrentQuarter.exactDate), CURRENT_QUARTER),
UpcomingRelease(
GameFixtures.beyondGoodEvil2.copy(releaseDate = CurrentQuarter.approxDateMonth),
CURRENT_QUARTER,
),

// TBD: Current year
UpcomingRelease(GameFixtures.halfLife3.copy(releaseDate = CurrentQuarter.approxDateMonth), CURRENT_YEAR),

// Tbd
UpcomingRelease(GameFixtures.smalland, TBD),
UpcomingRelease(GameFixtures.project007, TBD),
)

object CurrentMonth {
val exactDateToday = Date.YearMonthDay(2023, MAY, 17)
val exactDateTomorrow = Date.YearMonthDay(2023, MAY, 18)
val exactDateLater = Date.YearMonthDay(2023, MAY, 25)
val approxDate = Date.YearMonth(2023, MAY)
}

object NextMonth {
val exactDate = Date.YearMonthDay(2023, JUNE, 10)
val approxDate = Date.YearMonth(2023, JUNE)
}

object CurrentQuarter {
val exactDate = Date.YearMonthDay(2023, AUGUST, 11)
val approxDateMonth = Date.YearMonth(2023, AUGUST)
val approxDateQuarter = Date.YearQuarter(2023, 2)
internal val NOT_INITIALIZED: (
requiredFields: Set<GameField>,
) -> Flow<NetworkRequestStatus<UpcomingReleasesResponse>> = { _ ->
error("MockObserveUpcomingReleasesByDateUseCase not initialized")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2023, the Pixnews project authors and contributors. Please see the AUTHORS file for details.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/

package ru.pixnews.test.assumption

import androidx.annotation.RestrictTo
import androidx.annotation.RestrictTo.Scope.LIBRARY
import com.squareup.anvil.annotations.ContributesTo
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableSet
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.flow.flowOf
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.Month
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import org.junit.rules.ExternalResource
import org.junit.runner.Description
import org.junit.runners.model.Statement
import ru.pixnews.di.root.component.PixnewsRootComponentHolder
import ru.pixnews.domain.model.datetime.Date
import ru.pixnews.domain.model.game.GameFixtures
import ru.pixnews.domain.model.game.game.slimeRancher2
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingRelease
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleaseTimeCategory.FEW_DAYS
import ru.pixnews.feature.calendar.data.domain.upcoming.UpcomingReleasesResponse
import ru.pixnews.foundation.di.base.scopes.AppScope
import ru.pixnews.inject.data.MockObserveUpcomingReleasesByDateUseCase
import ru.pixnews.inject.data.MockObserveUpcomingReleasesByDateUseCase.UpcomingReleasesDateFixtures.NOT_INITIALIZED
import ru.pixnews.library.functional.network.NetworkRequestStatus

class UpcomingReleaseUseCaseAssumptions : ExternalResource() {
private lateinit var mockUseCase: MockObserveUpcomingReleasesByDateUseCase

override fun apply(base: Statement?, description: Description?): Statement {
mockUseCase = (PixnewsRootComponentHolder.appComponent as MockUseCaseHolder).mockUseCase
return super.apply(base, description)
}

override fun before() {
super.before()
assumeUpcomingGamesResponseDefaultGame()
}

override fun after() {
super.after()
resetMockUseCase()
}

fun assumeUpcomingGamesResponseDefaultGame() {
mockUseCase.createUpcomingReleasesObservableResponse = { requiredFields ->
flowOf(
NetworkRequestStatus.completeSuccess(
UpcomingReleasesResponse(
requestTime = DEFAULT_TIME.toInstant(DEFAULT_TIME_ZONE),
requestedFields = requiredFields.toImmutableSet(),
games = persistentListOf(DEFAULT_UPCOMING_RELEASE),
),
),
)
}
}

fun resetMockUseCase() {
mockUseCase.createUpcomingReleasesObservableResponse = NOT_INITIALIZED
}

fun assumeUpcomingGamesResponseEmpty() {
mockUseCase.createUpcomingReleasesObservableResponse = { requiredFields ->
flowOf(
NetworkRequestStatus.completeSuccess(
UpcomingReleasesResponse(
requestTime = Clock.System.now(),
requestedFields = requiredFields.toImmutableSet(),
games = persistentListOf(),
),
),
)
}
}

fun assumeUpcomingReleasesSuccessfully(
releases: List<UpcomingRelease>,
requestTime: Instant = Clock.System.now(),
) {
mockUseCase.createUpcomingReleasesObservableResponse = { requiredFields ->
flowOf(
NetworkRequestStatus.completeSuccess(
UpcomingReleasesResponse(
requestTime = requestTime,
requestedFields = requiredFields.toImmutableSet(),
games = releases.toPersistentList(),
),
),
)
}
}

public companion object {
val DEFAULT_TIME = LocalDateTime(2023, 5, 17, 10, 0, 0, 0)
val DEFAULT_TIME_ZONE = TimeZone.of("UTC+3")
val DEFAULT_UPCOMING_RELEASE = UpcomingRelease(
// TODO: loading with debug
game = GameFixtures.slimeRancher2.copy(
releaseDate = Date.YearMonthDay(2023, Month.MAY, 17),
),
group = FEW_DAYS,
)

@ContributesTo(AppScope::class)
@RestrictTo(LIBRARY)
interface MockUseCaseHolder {
val mockUseCase: MockObserveUpcomingReleasesByDateUseCase
}
}
}
Loading

0 comments on commit cbc0aa1

Please sign in to comment.