Merge branch 'main' of https://github.com/android/nowinandroid into dependabot/gradle/androidx.activity-activity-compose-1.8.2
@ -1,3 +1,3 @@
|
|||||||
# :app-nia-catalog module
|
# :app-nia-catalog module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../docs/images/graphs/dep_graph_app_nia_catalog.png)
|
![Dependency graph](../docs/images/graphs/dep_graph_app_nia_catalog.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :app module
|
# :app module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../docs/images/graphs/dep_graph_app.png)
|
![Dependency graph](../docs/images/graphs/dep_graph_app.svg)
|
||||||
|
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.samples.apps.nowinandroid.ui
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.material3.SnackbarDuration.Indefinite
|
||||||
|
import androidx.compose.material3.SnackbarHostState
|
||||||
|
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowSizeClass
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||||
|
import androidx.compose.ui.test.onRoot
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.DpSize
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.work.Configuration
|
||||||
|
import androidx.work.testing.SynchronousExecutor
|
||||||
|
import androidx.work.testing.WorkManagerTestInitHelper
|
||||||
|
import com.github.takahirom.roborazzi.captureRoboImage
|
||||||
|
import com.google.accompanist.testharness.TestHarness
|
||||||
|
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
|
||||||
|
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository
|
||||||
|
import com.google.samples.apps.nowinandroid.core.data.test.repository.FakeUserDataRepository
|
||||||
|
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.core.designsystem.theme.NiaTheme
|
||||||
|
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
|
||||||
|
import com.google.samples.apps.nowinandroid.uitesthiltmanifest.HiltComponentActivity
|
||||||
|
import dagger.hilt.android.testing.BindValue
|
||||||
|
import dagger.hilt.android.testing.HiltAndroidRule
|
||||||
|
import dagger.hilt.android.testing.HiltAndroidTest
|
||||||
|
import dagger.hilt.android.testing.HiltTestApplication
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
import org.robolectric.annotation.GraphicsMode
|
||||||
|
import org.robolectric.annotation.LooperMode
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the Snackbar is correctly displayed on different screen sizes.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
||||||
|
// Configure Robolectric to use a very large screen size that can fit all of the test sizes.
|
||||||
|
// This allows enough room to render the content under test without clipping or scaling.
|
||||||
|
@Config(application = HiltTestApplication::class, qualifiers = "w1000dp-h1000dp-480dpi")
|
||||||
|
@LooperMode(LooperMode.Mode.PAUSED)
|
||||||
|
@HiltAndroidTest
|
||||||
|
class SnackbarScreenshotTests {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the components' state and is used to perform injection on your test
|
||||||
|
*/
|
||||||
|
@get:Rule(order = 0)
|
||||||
|
val hiltRule = HiltAndroidRule(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a temporary folder used to create a Data Store file. This guarantees that
|
||||||
|
* the file is removed in between each test, preventing a crash.
|
||||||
|
*/
|
||||||
|
@BindValue
|
||||||
|
@get:Rule(order = 1)
|
||||||
|
val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a test activity to set the content on.
|
||||||
|
*/
|
||||||
|
@get:Rule(order = 2)
|
||||||
|
val composeTestRule = createAndroidComposeRule<HiltComponentActivity>()
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var networkMonitor: NetworkMonitor
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var timeZoneMonitor: TimeZoneMonitor
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var userDataRepository: FakeUserDataRepository
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var topicsRepository: TopicsRepository
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var userNewsResourceRepository: UserNewsResourceRepository
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
val config = Configuration.Builder()
|
||||||
|
.setMinimumLoggingLevel(Log.DEBUG)
|
||||||
|
.setExecutor(SynchronousExecutor())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Initialize WorkManager for instrumentation tests.
|
||||||
|
WorkManagerTestInitHelper.initializeTestWorkManager(
|
||||||
|
InstrumentationRegistry.getInstrumentation().context,
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
|
||||||
|
hiltRule.inject()
|
||||||
|
|
||||||
|
// Configure user data
|
||||||
|
runBlocking {
|
||||||
|
userDataRepository.setShouldHideOnboarding(true)
|
||||||
|
|
||||||
|
userDataRepository.setFollowedTopicIds(
|
||||||
|
setOf(topicsRepository.getTopics().first().first().id),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun phone_noSnackbar() {
|
||||||
|
val snackbarHostState = SnackbarHostState()
|
||||||
|
testSnackbarScreenshotWithSize(
|
||||||
|
snackbarHostState,
|
||||||
|
400.dp,
|
||||||
|
500.dp,
|
||||||
|
"snackbar_compact_medium_noSnackbar",
|
||||||
|
action = { },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun snackbarShown_phone() {
|
||||||
|
val snackbarHostState = SnackbarHostState()
|
||||||
|
testSnackbarScreenshotWithSize(
|
||||||
|
snackbarHostState,
|
||||||
|
400.dp,
|
||||||
|
500.dp,
|
||||||
|
"snackbar_compact_medium",
|
||||||
|
) {
|
||||||
|
snackbarHostState.showSnackbar(
|
||||||
|
"This is a test snackbar message",
|
||||||
|
actionLabel = "Action Label",
|
||||||
|
duration = Indefinite,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun snackbarShown_foldable() {
|
||||||
|
val snackbarHostState = SnackbarHostState()
|
||||||
|
testSnackbarScreenshotWithSize(
|
||||||
|
snackbarHostState,
|
||||||
|
600.dp,
|
||||||
|
600.dp,
|
||||||
|
"snackbar_medium_medium",
|
||||||
|
) {
|
||||||
|
snackbarHostState.showSnackbar(
|
||||||
|
"This is a test snackbar message",
|
||||||
|
actionLabel = "Action Label",
|
||||||
|
duration = Indefinite,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun snackbarShown_tablet() {
|
||||||
|
val snackbarHostState = SnackbarHostState()
|
||||||
|
testSnackbarScreenshotWithSize(
|
||||||
|
snackbarHostState,
|
||||||
|
900.dp,
|
||||||
|
900.dp,
|
||||||
|
"snackbar_expanded_expanded",
|
||||||
|
) {
|
||||||
|
snackbarHostState.showSnackbar(
|
||||||
|
"This is a test snackbar message",
|
||||||
|
actionLabel = "Action Label",
|
||||||
|
duration = Indefinite,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun testSnackbarScreenshotWithSize(
|
||||||
|
snackbarHostState: SnackbarHostState,
|
||||||
|
width: Dp,
|
||||||
|
height: Dp,
|
||||||
|
screenshotName: String,
|
||||||
|
action: suspend () -> Unit,
|
||||||
|
) {
|
||||||
|
lateinit var scope: CoroutineScope
|
||||||
|
composeTestRule.setContent {
|
||||||
|
scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
TestHarness(size = DpSize(width, height)) {
|
||||||
|
BoxWithConstraints {
|
||||||
|
val appState = rememberNiaAppState(
|
||||||
|
windowSizeClass = WindowSizeClass.calculateFromSize(
|
||||||
|
DpSize(maxWidth, maxHeight),
|
||||||
|
),
|
||||||
|
networkMonitor = networkMonitor,
|
||||||
|
userNewsResourceRepository = userNewsResourceRepository,
|
||||||
|
timeZoneMonitor = timeZoneMonitor,
|
||||||
|
)
|
||||||
|
NiaTheme {
|
||||||
|
NiaApp(appState, snackbarHostState, false, {}, {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onRoot()
|
||||||
|
.captureRoboImage(
|
||||||
|
"src/testDemo/screenshots/$screenshotName.png",
|
||||||
|
roborazziOptions = DefaultRoborazziOptions,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 72 KiB |
@ -0,0 +1,3 @@
|
|||||||
|
# :core:analytics module
|
||||||
|
## Dependency graph
|
||||||
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_analytics.svg)
|
@ -1,3 +1,3 @@
|
|||||||
# :core:common module
|
# :core:common module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_common.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_common.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:data-test module
|
# :core:data-test module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_data_test.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_data_test.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:data module
|
# :core:data module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_data.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_data.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:database module
|
# :core:database module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_database.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_database.svg)
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
# :core:datastore-proto module
|
||||||
|
## Dependency graph
|
||||||
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_proto.svg)
|
@ -1,3 +1,3 @@
|
|||||||
# :core:datastore-test module
|
# :core:datastore-test module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_test.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_test.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:datastore module
|
# :core:datastore module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:designsystem module
|
# :core:designsystem module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_designsystem.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_designsystem.svg)
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
# :core:domain module
|
||||||
|
## Dependency graph
|
||||||
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_domain.svg)
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.google.samples.apps.nowinandroid.core.domain
|
|
||||||
|
|
||||||
import com.google.samples.apps.nowinandroid.core.data.repository.SearchContentsRepository
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A use case which returns total count of *Fts tables
|
|
||||||
*/
|
|
||||||
class GetSearchContentsCountUseCase @Inject constructor(
|
|
||||||
private val searchContentsRepository: SearchContentsRepository,
|
|
||||||
) {
|
|
||||||
operator fun invoke(): Flow<Int> =
|
|
||||||
searchContentsRepository.getSearchContentsCount()
|
|
||||||
}
|
|
@ -1,3 +1,3 @@
|
|||||||
# :core:model module
|
# :core:model module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_model.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_model.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:network module
|
# :core:network module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_network.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_network.svg)
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
# :core:notifications module
|
||||||
|
## Dependency graph
|
||||||
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_notifications.svg)
|
@ -0,0 +1,3 @@
|
|||||||
|
# :core:screenshot-testing module
|
||||||
|
## Dependency graph
|
||||||
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_screenshot_testing.svg)
|
@ -1,3 +1,3 @@
|
|||||||
# :core:testing module
|
# :core:testing module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_testing.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_testing.svg)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# :core:ui module
|
# :core:ui module
|
||||||
|
## Dependency graph
|
||||||
![Dependency graph](../../docs/images/graphs/dep_graph_core_ui.png)
|
![Dependency graph](../../docs/images/graphs/dep_graph_core_ui.svg)
|
||||||
|
Before Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 863 B |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 893 B |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 872 B |
After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 851 B |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 46 KiB |