Fix CI build after KMP migration and Compose Multiplatform 1.7.3 upgrade

- Remove demo/prod flavor references from CI workflow (flavors were
  removed during KMP migration)
- Replace tasks.create with tasks.register in convention plugins to fix
  EagerGradleConfiguration lint error
- Remove HiltTestApplication references from screenshot and UI tests
  (Hilt was replaced by Koin)
- Add Compose plugins to core:screenshot-testing for inline method
  resolution
- Add androidx.navigation.testing dependency to feature:topic and
  feature:interests for SavedStateHandle.toRoute
- Fix ViewModel tests in commonTest by setting up Dispatchers.Main
  (bookmarks, settings)
- Uncomment TopicRoute in TopicViewModelTest SavedStateHandle setup
- Replace NavDestination.id with type-safe popUpTo<ForYouBaseRoute> in
  NiaAppState (id property removed in KMP navigation)
- Rename badging golden file from prodRelease to release
- Update dependency guard baselines
- Update AGENTS.md with corrected task names
pull/2064/head
Mercury Li 3 weeks ago
parent 172a6db1a5
commit b60153218c

@ -76,7 +76,7 @@ jobs:
- name: Run all local screenshot tests (Roborazzi)
id: screenshotsverify
continue-on-error: true
run: ./gradlew verifyRoborazziDemoDebug
run: ./gradlew verifyRoborazziDebug
- name: Prevent pushing new screenshots if this is a fork
id: checkfork_screenshots
@ -92,7 +92,7 @@ jobs:
id: screenshotsrecord
if: steps.screenshotsverify.outcome == 'failure' && github.event_name == 'pull_request'
run: |
./gradlew recordRoborazziDemoDebug
./gradlew recordRoborazziDebug
- name: Push new screenshots if available
uses: stefanzweifel/git-auto-commit-action@v5
@ -104,7 +104,7 @@ jobs:
# Run local tests after screenshot tests to avoid wrong UP-TO-DATE. TODO: Ignore screenshots.
- name: Run local tests
run: ./gradlew testDemoDebug :lint:test
run: ./gradlew testDebugUnitTest :lint:test
- name: Build all build type and flavor permutations
run: ./gradlew :app:assemble
@ -130,7 +130,7 @@ jobs:
path: '**/build/outputs/roborazzi/*_compare.png'
- name: Check lint
run: ./gradlew :app:lintProdRelease :app-nia-catalog:lintRelease :lint:lint
run: ./gradlew :app:lintRelease :app-nia-catalog:lintRelease :lint:lint
- name: Upload lint reports (HTML)
if: ${{ !cancelled() }}
@ -146,7 +146,7 @@ jobs:
sarif_file: './'
- name: Check badging
run: ./gradlew :app:checkProdReleaseBadging
run: ./gradlew :app:checkReleaseBadging
androidTest:
runs-on: ubuntu-latest
@ -199,17 +199,16 @@ jobs:
disable-animations: true
disk-size: 6000M
heap-size: 600M
script: ./gradlew connectedDemoDebugAndroidTest --daemon
script: ./gradlew connectedDebugAndroidTest --daemon
- name: Run local tests (including Roborazzi) for the combined coverage report (only API 30)
if: matrix.api-level == 30
# There is no need to verify Roborazzi tests to generate coverage.
run: ./gradlew testDemoDebugUnitTest -Proborazzi.test.verify=false # Add Prod if we ever add JVM tests for prod
run: ./gradlew testDebugUnitTest -Proborazzi.test.verify=false
# Add `createProdDebugUnitTestCoverageReport` if we ever add JVM tests for prod
- name: Generate coverage reports for Debug variants (only API 30)
if: matrix.api-level == 30
run: ./gradlew createDemoDebugCombinedCoverageReport
run: ./gradlew createDebugCombinedCoverageReport
- name: Upload test reports
if: ${{ !cancelled() }}

@ -20,21 +20,21 @@ Now in Android (KMP edition) — a Kotlin Multiplatform fork of Google's Now in
# Run desktop app
# Gradle run config task: desktopRun -DmainClass=MainKt --quiet
# Unit tests (only demoDebug variant has test coverage)
./gradlew testDemoDebug # all module tests
./gradlew :feature:foryou:testDemoDebug # single module test
# Unit tests
./gradlew testDebugUnitTest # all module tests
./gradlew :feature:foryou:testDebugUnitTest # single module test
./gradlew :lint:test # lint rule tests
# Instrumented tests (requires a connected Android emulator)
./gradlew connectedDemoDebugAndroidTest
./gradlew connectedDebugAndroidTest
# Screenshot tests (Roborazzi — CI only, do NOT run locally)
# CI records/verifies screenshots and auto-commits updates via PR
# ./gradlew verifyRoborazziDemoDebug # verify against baselines (CI only)
# ./gradlew recordRoborazziDemoDebug # record new baselines (CI only)
# ./gradlew verifyRoborazziDebug # verify against baselines (CI only)
# ./gradlew recordRoborazziDebug # record new baselines (CI only)
# Lint
./gradlew :app:lintProdRelease :app-nia-catalog:lintRelease :lint:lint
./gradlew :app:lintRelease :app-nia-catalog:lintRelease :lint:lint
# Dependency guard
./gradlew dependencyGuard # check
@ -44,7 +44,7 @@ Now in Android (KMP edition) — a Kotlin Multiplatform fork of Google's Now in
./gradlew :build-logic:convention:check
# Badging check
./gradlew :app:checkProdReleaseBadging
./gradlew :app:checkReleaseBadging
```
## Architecture
@ -86,7 +86,7 @@ All modules use convention plugins from `build-logic/convention/` (plugin IDs pr
### Build Variants
Two flavor dimensions: `demo` (local static data) and `prod` (requires backend server, not public). Use `demoDebug` for development.
Two build types: `debug` and `release`. No flavor dimensions (demo/prod flavors were removed during KMP migration).
### KMP Source Set Layout

@ -2,8 +2,8 @@ androidx.activity:activity-compose:1.9.3
androidx.activity:activity-ktx:1.9.3
androidx.activity:activity:1.9.3
androidx.annotation:annotation-experimental:1.4.1
androidx.annotation:annotation-jvm:1.9.0
androidx.annotation:annotation:1.9.0
androidx.annotation:annotation-jvm:1.9.1
androidx.annotation:annotation:1.9.1
androidx.appcompat:appcompat-resources:1.7.0
androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0
@ -11,48 +11,48 @@ androidx.autofill:autofill:1.0.0
androidx.collection:collection-jvm:1.4.4
androidx.collection:collection-ktx:1.4.4
androidx.collection:collection:1.4.4
androidx.compose.animation:animation-android:1.7.4
androidx.compose.animation:animation-core-android:1.7.4
androidx.compose.animation:animation-core:1.7.4
androidx.compose.animation:animation:1.7.4
androidx.compose.foundation:foundation-android:1.7.4
androidx.compose.foundation:foundation-layout-android:1.7.4
androidx.compose.foundation:foundation-layout:1.7.4
androidx.compose.foundation:foundation:1.7.4
androidx.compose.animation:animation-android:1.7.6
androidx.compose.animation:animation-core-android:1.7.6
androidx.compose.animation:animation-core:1.7.6
androidx.compose.animation:animation:1.7.6
androidx.compose.foundation:foundation-android:1.7.6
androidx.compose.foundation:foundation-layout-android:1.7.6
androidx.compose.foundation:foundation-layout:1.7.6
androidx.compose.foundation:foundation:1.7.6
androidx.compose.material3.adaptive:adaptive-android:1.0.0
androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0
androidx.compose.material3.adaptive:adaptive-layout:1.0.0
androidx.compose.material3.adaptive:adaptive:1.0.0
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.3.0
androidx.compose.material3:material3-adaptive-navigation-suite:1.3.0
androidx.compose.material3:material3-android:1.3.0
androidx.compose.material3:material3:1.3.0
androidx.compose.material:material-android:1.7.1
androidx.compose.material:material-icons-core-android:1.7.1
androidx.compose.material:material-icons-core:1.7.1
androidx.compose.material:material-icons-extended-android:1.7.1
androidx.compose.material:material-icons-extended:1.7.1
androidx.compose.material:material-ripple-android:1.7.1
androidx.compose.material:material-ripple:1.7.1
androidx.compose.material:material:1.7.1
androidx.compose.runtime:runtime-android:1.7.4
androidx.compose.runtime:runtime-saveable-android:1.7.4
androidx.compose.runtime:runtime-saveable:1.7.4
androidx.compose.runtime:runtime:1.7.4
androidx.compose.ui:ui-android:1.7.4
androidx.compose.ui:ui-geometry-android:1.7.4
androidx.compose.ui:ui-geometry:1.7.4
androidx.compose.ui:ui-graphics-android:1.7.4
androidx.compose.ui:ui-graphics:1.7.4
androidx.compose.ui:ui-text-android:1.7.4
androidx.compose.ui:ui-text:1.7.4
androidx.compose.ui:ui-tooling-preview-android:1.7.4
androidx.compose.ui:ui-tooling-preview:1.7.4
androidx.compose.ui:ui-unit-android:1.7.4
androidx.compose.ui:ui-unit:1.7.4
androidx.compose.ui:ui-util-android:1.7.4
androidx.compose.ui:ui-util:1.7.4
androidx.compose.ui:ui:1.7.4
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.3.1
androidx.compose.material3:material3-adaptive-navigation-suite:1.3.1
androidx.compose.material3:material3-android:1.3.1
androidx.compose.material3:material3:1.3.1
androidx.compose.material:material-android:1.7.6
androidx.compose.material:material-icons-core-android:1.7.6
androidx.compose.material:material-icons-core:1.7.6
androidx.compose.material:material-icons-extended-android:1.7.6
androidx.compose.material:material-icons-extended:1.7.6
androidx.compose.material:material-ripple-android:1.7.6
androidx.compose.material:material-ripple:1.7.6
androidx.compose.material:material:1.7.6
androidx.compose.runtime:runtime-android:1.7.6
androidx.compose.runtime:runtime-saveable-android:1.7.6
androidx.compose.runtime:runtime-saveable:1.7.6
androidx.compose.runtime:runtime:1.7.6
androidx.compose.ui:ui-android:1.7.6
androidx.compose.ui:ui-geometry-android:1.7.6
androidx.compose.ui:ui-geometry:1.7.6
androidx.compose.ui:ui-graphics-android:1.7.6
androidx.compose.ui:ui-graphics:1.7.6
androidx.compose.ui:ui-text-android:1.7.6
androidx.compose.ui:ui-text:1.7.6
androidx.compose.ui:ui-tooling-preview-android:1.7.6
androidx.compose.ui:ui-tooling-preview:1.7.6
androidx.compose.ui:ui-unit-android:1.7.6
androidx.compose.ui:ui-unit:1.7.6
androidx.compose.ui:ui-util-android:1.7.6
androidx.compose.ui:ui-util:1.7.6
androidx.compose.ui:ui:1.7.6
androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.13.1
androidx.core:core:1.13.1
@ -61,21 +61,21 @@ androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.7
androidx.graphics:graphics-path:1.0.1
androidx.interpolator:interpolator:1.0.0
androidx.lifecycle:lifecycle-common-java8:2.8.6
androidx.lifecycle:lifecycle-common-jvm:2.8.6
androidx.lifecycle:lifecycle-common:2.8.6
androidx.lifecycle:lifecycle-livedata-core:2.8.6
androidx.lifecycle:lifecycle-process:2.8.6
androidx.lifecycle:lifecycle-runtime-android:2.8.6
androidx.lifecycle:lifecycle-runtime-compose-android:2.8.6
androidx.lifecycle:lifecycle-runtime-compose:2.8.6
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.6
androidx.lifecycle:lifecycle-runtime-ktx:2.8.6
androidx.lifecycle:lifecycle-runtime:2.8.6
androidx.lifecycle:lifecycle-viewmodel-android:2.8.6
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.6
androidx.lifecycle:lifecycle-viewmodel:2.8.6
androidx.lifecycle:lifecycle-common-java8:2.8.7
androidx.lifecycle:lifecycle-common-jvm:2.8.7
androidx.lifecycle:lifecycle-common:2.8.7
androidx.lifecycle:lifecycle-livedata-core:2.8.7
androidx.lifecycle:lifecycle-process:2.8.7
androidx.lifecycle:lifecycle-runtime-android:2.8.7
androidx.lifecycle:lifecycle-runtime-compose-android:2.8.7
androidx.lifecycle:lifecycle-runtime-compose:2.8.7
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7
androidx.lifecycle:lifecycle-runtime-ktx:2.8.7
androidx.lifecycle:lifecycle-runtime:2.8.7
androidx.lifecycle:lifecycle-viewmodel-android:2.8.7
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7
androidx.lifecycle:lifecycle-viewmodel:2.8.7
androidx.profileinstaller:profileinstaller:1.4.1
androidx.savedstate:savedstate-ktx:1.2.1
androidx.savedstate:savedstate:1.2.1
@ -92,42 +92,42 @@ com.google.accompanist:accompanist-drawablepainter:0.36.0
com.google.guava:listenablefuture:1.0
com.squareup.okio:okio-jvm:3.9.1
com.squareup.okio:okio:3.9.1
io.coil-kt.coil3:coil-compose-core-android:3.0.0-rc02
io.coil-kt.coil3:coil-compose-core:3.0.0-rc02
io.coil-kt.coil3:coil-core-android:3.0.0-rc02
io.coil-kt.coil3:coil-core:3.0.0-rc02
org.jetbrains.androidx.lifecycle:lifecycle-common:2.8.3
org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose:2.8.3
org.jetbrains.androidx.lifecycle:lifecycle-runtime:2.8.3
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel:2.8.3
org.jetbrains.androidx.window:window-core:1.3.0
org.jetbrains.compose.animation:animation-core:1.7.0
org.jetbrains.compose.animation:animation:1.7.0
org.jetbrains.compose.annotation-internal:annotation:1.7.0
org.jetbrains.compose.collection-internal:collection:1.7.0
org.jetbrains.compose.components:components-resources-android:1.7.0
org.jetbrains.compose.components:components-resources:1.7.0
org.jetbrains.compose.components:components-ui-tooling-preview-android:1.7.0
org.jetbrains.compose.components:components-ui-tooling-preview:1.7.0
org.jetbrains.compose.foundation:foundation-layout:1.7.0
org.jetbrains.compose.foundation:foundation:1.7.0
org.jetbrains.compose.material3.adaptive:adaptive-layout:1.0.0-alpha03
org.jetbrains.compose.material3.adaptive:adaptive:1.0.0
org.jetbrains.compose.material3:material3-adaptive-navigation-suite:1.7.0
org.jetbrains.compose.material3:material3:1.7.0
org.jetbrains.compose.material:material-icons-core:1.7.0
org.jetbrains.compose.material:material-icons-extended:1.7.0
org.jetbrains.compose.material:material-ripple:1.7.0
org.jetbrains.compose.material:material:1.7.0
org.jetbrains.compose.runtime:runtime-saveable:1.7.0
org.jetbrains.compose.runtime:runtime:1.7.0
org.jetbrains.compose.ui:ui-geometry:1.7.0
org.jetbrains.compose.ui:ui-graphics:1.7.0
org.jetbrains.compose.ui:ui-text:1.7.0
org.jetbrains.compose.ui:ui-unit:1.7.0
org.jetbrains.compose.ui:ui-util:1.7.0
org.jetbrains.compose.ui:ui:1.7.0
org.jetbrains.kotlin:kotlin-stdlib:2.0.21
io.coil-kt.coil3:coil-compose-core-android:3.0.3
io.coil-kt.coil3:coil-compose-core:3.0.3
io.coil-kt.coil3:coil-core-android:3.0.3
io.coil-kt.coil3:coil-core:3.0.3
org.jetbrains.androidx.lifecycle:lifecycle-common:2.8.4
org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose:2.8.4
org.jetbrains.androidx.lifecycle:lifecycle-runtime:2.8.4
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel:2.8.4
org.jetbrains.androidx.window:window-core:1.3.1
org.jetbrains.compose.animation:animation-core:1.7.3
org.jetbrains.compose.animation:animation:1.7.3
org.jetbrains.compose.annotation-internal:annotation:1.7.3
org.jetbrains.compose.collection-internal:collection:1.7.3
org.jetbrains.compose.components:components-resources-android:1.7.3
org.jetbrains.compose.components:components-resources:1.7.3
org.jetbrains.compose.components:components-ui-tooling-preview-android:1.7.3
org.jetbrains.compose.components:components-ui-tooling-preview:1.7.3
org.jetbrains.compose.foundation:foundation-layout:1.7.3
org.jetbrains.compose.foundation:foundation:1.7.3
org.jetbrains.compose.material3.adaptive:adaptive-layout:1.0.1
org.jetbrains.compose.material3.adaptive:adaptive:1.0.1
org.jetbrains.compose.material3:material3-adaptive-navigation-suite:1.7.3
org.jetbrains.compose.material3:material3:1.7.3
org.jetbrains.compose.material:material-icons-core:1.7.3
org.jetbrains.compose.material:material-icons-extended:1.7.3
org.jetbrains.compose.material:material-ripple:1.7.3
org.jetbrains.compose.material:material:1.7.3
org.jetbrains.compose.runtime:runtime-saveable:1.7.3
org.jetbrains.compose.runtime:runtime:1.7.3
org.jetbrains.compose.ui:ui-geometry:1.7.3
org.jetbrains.compose.ui:ui-graphics:1.7.3
org.jetbrains.compose.ui:ui-text:1.7.3
org.jetbrains.compose.ui:ui-unit:1.7.3
org.jetbrains.compose.ui:ui-util:1.7.3
org.jetbrains.compose.ui:ui:1.7.3
org.jetbrains.kotlin:kotlin-stdlib:2.1.0
org.jetbrains.kotlinx:atomicfu-jvm:0.23.2
org.jetbrains.kotlinx:atomicfu:0.23.2
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0

@ -1,12 +1,10 @@
package: name='com.google.samples.apps.nowinandroid' versionCode='8' versionName='0.1.2' platformBuildVersionName='15' platformBuildVersionCode='35' compileSdkVersion='35' compileSdkVersionCodename='15'
sdkVersion:'21'
targetSdkVersion:'35'
targetSdkVersion:'34'
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
uses-permission: name='android.permission.POST_NOTIFICATIONS'
uses-permission: name='android.permission.WAKE_LOCK'
uses-permission: name='com.google.android.c2dm.permission.RECEIVE'
uses-permission: name='com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE'
uses-permission: name='android.permission.RECEIVE_BOOT_COMPLETED'
uses-permission: name='android.permission.FOREGROUND_SERVICE'
uses-permission: name='com.google.samples.apps.nowinandroid.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION'
@ -105,14 +103,12 @@ application-icon-640:'res/mipmap-anydpi-v26/ic_launcher.xml'
application-icon-65534:'res/mipmap-anydpi-v26/ic_launcher.xml'
application: label='Now in Android' icon='res/mipmap-anydpi-v26/ic_launcher.xml'
launchable-activity: name='com.google.samples.apps.nowinandroid.MainActivity' label='' icon=''
uses-library-not-required:'android.ext.adservices'
uses-library-not-required:'androidx.window.extensions'
uses-library-not-required:'androidx.window.sidecar'
feature-group: label=''
uses-feature: name='android.hardware.faketouch'
uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps'
main
other-activities
other-receivers
other-services
supports-screens: 'small' 'normal' 'large' 'xlarge'

@ -25,7 +25,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.util.trace
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
@ -33,6 +32,7 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourc
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.navigateToBookmarks
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouBaseRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.navigateToForYou
import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests
import com.google.samples.apps.nowinandroid.feature.search.navigation.navigateToSearch
@ -156,7 +156,7 @@ class NiaAppState(
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
popUpTo<ForYouBaseRoute> {
saveState = true
}
// Avoid multiple copies of the same destination when

@ -118,7 +118,7 @@ private fun Project.configureComposeMultiplatformApp() {
// Fixes Cannot locate tasks that match ':core:model:testClasses' as task 'testClasses'
// not found in project ':core:model'. Some candidates are: 'jsTestClasses', 'jvmTestClasses'.
project.tasks.create("testClasses") {
project.tasks.register("testClasses") {
dependsOn("allTests")
}
}

@ -101,7 +101,7 @@ internal fun Project.configureKotlinMultiplatform() {
// Fixes Cannot locate tasks that match ':core:model:testClasses' as task 'testClasses'
// not found in project ':core:model'. Some candidates are: 'jsTestClasses', 'jvmTestClasses'.
project.tasks.create("testClasses") {
project.tasks.register("testClasses") {
dependsOn("allTests")
}
}

@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaBackground
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaGradientBackground
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -36,7 +35,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class BackgroundScreenshotTests {

@ -25,7 +25,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaButto
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaOutlinedButton
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -36,7 +35,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class ButtonScreenshotTests {

@ -35,7 +35,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaFilte
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -46,7 +45,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class FilterChipScreenshotTests {

@ -24,7 +24,6 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaIconToggleButton
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -35,7 +34,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class IconButtonScreenshotTests {

@ -26,7 +26,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaOverl
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -37,7 +36,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class LoadingWheelScreenshotTests {

@ -34,7 +34,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -45,7 +44,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class NavigationScreenshotTests {

@ -32,7 +32,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTabRo
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -43,7 +42,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class TabsScreenshotTests {

@ -29,7 +29,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopic
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -40,7 +39,7 @@ import org.robolectric.annotation.LooperMode
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class TagScreenshotTests {

@ -31,7 +31,6 @@ import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiTheme
import dagger.hilt.android.testing.HiltTestApplication
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -43,7 +42,7 @@ import org.robolectric.annotation.LooperMode
@OptIn(ExperimentalMaterial3Api::class)
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class, qualifiers = "480dpi")
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class TopAppBarScreenshotTests {

@ -15,6 +15,8 @@
*/
plugins {
alias(libs.plugins.nowinandroid.kmp.library)
alias(libs.plugins.jetbrains.compose)
alias(libs.plugins.compose)
}
android {

@ -22,11 +22,15 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepo
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Loading
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
@ -50,12 +54,18 @@ class BookmarksViewModelTest {
@BeforeTest
fun setup() {
Dispatchers.setMain(UnconfinedTestDispatcher())
viewModel = BookmarksViewModel(
userDataRepository = userDataRepository,
userNewsResourceRepository = userNewsResourceRepository,
)
}
@AfterTest
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun stateIsInitiallyLoading() = runTest {
assertEquals(Loading, viewModel.feedUiState.value)

@ -34,7 +34,6 @@ import com.google.samples.apps.nowinandroid.core.ui.UserNewsResourcePreviewParam
import com.google.samples.apps.nowinandroid.feature.foryou.OnboardingUiState.Loading
import com.google.samples.apps.nowinandroid.feature.foryou.OnboardingUiState.NotShown
import com.google.samples.apps.nowinandroid.feature.foryou.OnboardingUiState.Shown
import dagger.hilt.android.testing.HiltTestApplication
import org.hamcrest.Matchers
import org.junit.Before
import org.junit.Rule
@ -51,7 +50,7 @@ import java.util.TimeZone
*/
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(application = HiltTestApplication::class)
@Config(qualifiers = "480dpi")
@LooperMode(LooperMode.Mode.PAUSED)
class ForYouScreenScreenshotTests {

@ -43,6 +43,7 @@ kotlin {
androidUnitTest.dependencies {
implementation(libs.robolectric)
implementation(libs.roborazzi)
implementation(libs.androidx.navigation.testing)
implementation(projects.core.screenshotTesting)
}
androidInstrumentedTest.dependencies {

@ -21,11 +21,15 @@ import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
@ -38,9 +42,15 @@ class SettingsViewModelTest {
@BeforeTest
fun setup() {
Dispatchers.setMain(UnconfinedTestDispatcher())
viewModel = SettingsViewModel(userDataRepository)
}
@AfterTest
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun stateIsInitiallyLoading() = runTest {
assertEquals(Loading, viewModel.settingsUiState.value)

@ -44,6 +44,7 @@ kotlin {
androidUnitTest.dependencies {
implementation(libs.robolectric)
implementation(libs.roborazzi)
implementation(libs.androidx.navigation.testing)
implementation(projects.core.screenshotTesting)
}
androidInstrumentedTest.dependencies {

@ -26,6 +26,7 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepo
import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
@ -70,7 +71,7 @@ class TopicViewModelTest {
fun setup() {
viewModel = TopicViewModel(
savedStateHandle = SavedStateHandle(
// route = TopicRoute(id = testInputTopics[0].topic.id),
route = TopicRoute(id = testInputTopics[0].topic.id),
),
userDataRepository = userDataRepository,
topicsRepository = topicsRepository,

Loading…
Cancel
Save