Merge "Merge remote-tracking branch 'github/main'" into main

pull/127/head
Jolanda Verhoef 3 years ago committed by Gerrit Code Review
commit fc9a62b893

@ -53,10 +53,18 @@ android {
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
} }
val benchmark by creating { val benchmark by creating {
// Enable all the optimizations from release build through initWith(release).
initWith(release) initWith(release)
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks.add("release") matchingFallbacks.add("release")
// Debug key signing is available to everyone.
signingConfig = signingConfigs.getByName("debug")
// Only use benchmark proguard rules
proguardFiles("benchmark-rules.pro") proguardFiles("benchmark-rules.pro")
// FIXME enabling minification breaks access to demo backend.
isMinifyEnabled = false
// Keep the build type debuggable so we can attach a debugger if needed.
isDebuggable = true
applicationIdSuffix = ".benchmark"
} }
} }

File diff suppressed because it is too large Load Diff

@ -25,6 +25,7 @@ android {
defaultConfig { defaultConfig {
minSdk = 23 minSdk = 23
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
missingDimensionStrategy("contentType", "demo")
} }
buildTypes { buildTypes {
@ -32,7 +33,7 @@ android {
// release build (for example, with minification on). It's signed with a debug key // release build (for example, with minification on). It's signed with a debug key
// for easy local/CI testing. // for easy local/CI testing.
val benchmark by creating { val benchmark by creating {
isDebuggable = true isDebuggable = false
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
matchingFallbacks.add("release") matchingFallbacks.add("release")
} }

@ -19,6 +19,7 @@ package com.google.samples.apps.nowinandroid.baselineprofile
import androidx.benchmark.macro.ExperimentalBaselineProfilesApi import androidx.benchmark.macro.ExperimentalBaselineProfilesApi
import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.uiautomator.By import androidx.test.uiautomator.By
import androidx.test.uiautomator.Direction
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -32,7 +33,7 @@ class BaselineProfileGenerator {
@Test @Test
fun startup() = fun startup() =
baselineProfileRule.collectBaselineProfile( baselineProfileRule.collectBaselineProfile(
packageName = "com.google.samples.apps.nowinandroid" packageName = "com.google.samples.apps.nowinandroid.demo.benchmark"
) { ) {
pressHome() pressHome()
// This block defines the app's critical user journey. Here we are interested in // This block defines the app's critical user journey. Here we are interested in
@ -45,6 +46,12 @@ class BaselineProfileGenerator {
findObject(By.text("Interests")) findObject(By.text("Interests"))
.click() .click()
waitForIdle() waitForIdle()
findObject(By.text("Accessibility")).scroll(Direction.DOWN, 2000f)
waitForIdle()
findObject(By.text("People")).click()
waitForIdle()
findObject(By.textStartsWith("Android")).scroll(Direction.DOWN, 2000f)
waitForIdle()
} }
} }
} }

@ -0,0 +1,45 @@
/*
* Copyright 2022 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.network.di
import com.google.samples.apps.nowinandroid.core.network.NiANetwork
import com.google.samples.apps.nowinandroid.core.network.fake.FakeNiANetwork
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import kotlinx.serialization.json.Json
@Module
@InstallIn(SingletonComponent::class)
interface NetworkModule {
@Binds
fun bindsNiANetwork(
niANetwork: FakeNiANetwork
): NiANetwork
companion object {
@Provides
@Singleton
fun providesNetworkJson(): Json = Json {
ignoreUnknownKeys = true
}
}
}

@ -20,8 +20,6 @@ import androidx.activity.ComponentActivity
import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass.Companion
import androidx.compose.ui.test.assertHasClickAction import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled import androidx.compose.ui.test.assertIsEnabled
@ -39,12 +37,7 @@ import androidx.compose.ui.unit.DpSize
import com.google.samples.apps.nowinandroid.core.model.data.Author import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.model.data.FollowableAuthor import com.google.samples.apps.nowinandroid.core.model.data.FollowableAuthor
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video
import com.google.samples.apps.nowinandroid.core.model.data.SaveableNewsResource
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
import kotlinx.datetime.Instant
import org.junit.Assert.assertTrue
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -554,155 +547,155 @@ class ForYouScreenTest {
.assertExists() .assertExists()
} }
@Test // @Test
fun feed_whenNoInterestsSelectionAndLoaded_showsFeed() { // fun feed_whenNoInterestsSelectionAndLoaded_showsFeed() {
lateinit var windowSizeClass: WindowSizeClass // lateinit var windowSizeClass: WindowSizeClass
//
val saveableNewsResources = listOf( // val saveableNewsResources = listOf(
SaveableNewsResource( // SaveableNewsResource(
newsResource = NewsResource( // newsResource = NewsResource(
id = "1", // id = "1",
episodeId = "52", // episodeId = "52",
title = "Thanks for helping us reach 1M YouTube Subscribers", // title = "Thanks for helping us reach 1M YouTube Subscribers",
content = "Thank you everyone for following the Now in Android series " + // content = "Thank you everyone for following the Now in Android series " +
"and everything the Android Developers YouTube channel has to offer. " + // "and everything the Android Developers YouTube channel has to offer. " +
"During the Android Developer Summit, our YouTube channel reached 1 " + // "During the Android Developer Summit, our YouTube channel reached 1 " +
"million subscribers! Heres a small video to thank you all.", // "million subscribers! Heres a small video to thank you all.",
url = "https://youtu.be/-fJ6poHQrjM", // url = "https://youtu.be/-fJ6poHQrjM",
headerImageUrl = "https://i.ytimg.com/vi/-fJ6poHQrjM/maxresdefault.jpg", // headerImageUrl = "https://i.ytimg.com/vi/-fJ6poHQrjM/maxresdefault.jpg",
publishDate = Instant.parse("2021-11-09T00:00:00.000Z"), // publishDate = Instant.parse("2021-11-09T00:00:00.000Z"),
type = Video, // type = Video,
topics = listOf( // topics = listOf(
Topic( // Topic(
id = "0", // id = "0",
name = "Headlines", // name = "Headlines",
shortDescription = "", // shortDescription = "",
longDescription = "", // longDescription = "",
url = "", // url = "",
imageUrl = "" // imageUrl = ""
) // )
), // ),
authors = emptyList() // authors = emptyList()
), // ),
isSaved = false // isSaved = false
), // ),
SaveableNewsResource( // SaveableNewsResource(
newsResource = NewsResource( // newsResource = NewsResource(
id = "2", // id = "2",
episodeId = "52", // episodeId = "52",
title = "Transformations and customisations in the Paging Library", // title = "Transformations and customisations in the Paging Library",
content = "A demonstration of different operations that can be performed " + // content = "A demonstration of different operations that can be performed " +
"with Paging. Transformations like inserting separators, when to " + // "with Paging. Transformations like inserting separators, when to " +
"create a new pager, and customisation options for consuming " + // "create a new pager, and customisation options for consuming " +
"PagingData.", // "PagingData.",
url = "https://youtu.be/ZARz0pjm5YM", // url = "https://youtu.be/ZARz0pjm5YM",
headerImageUrl = "https://i.ytimg.com/vi/ZARz0pjm5YM/maxresdefault.jpg", // headerImageUrl = "https://i.ytimg.com/vi/ZARz0pjm5YM/maxresdefault.jpg",
publishDate = Instant.parse("2021-11-01T00:00:00.000Z"), // publishDate = Instant.parse("2021-11-01T00:00:00.000Z"),
type = Video, // type = Video,
topics = listOf( // topics = listOf(
Topic( // Topic(
id = "1", // id = "1",
name = "UI", // name = "UI",
shortDescription = "", // shortDescription = "",
longDescription = "", // longDescription = "",
url = "", // url = "",
imageUrl = "" // imageUrl = ""
), // ),
), // ),
authors = emptyList() // authors = emptyList()
), // ),
isSaved = false // isSaved = false
), // ),
SaveableNewsResource( // SaveableNewsResource(
newsResource = NewsResource( // newsResource = NewsResource(
id = "3", // id = "3",
episodeId = "52", // episodeId = "52",
title = "Community tip on Paging", // title = "Community tip on Paging",
content = "Tips for using the Paging library from the developer community", // content = "Tips for using the Paging library from the developer community",
url = "https://youtu.be/r5JgIyS3t3s", // url = "https://youtu.be/r5JgIyS3t3s",
headerImageUrl = "https://i.ytimg.com/vi/r5JgIyS3t3s/maxresdefault.jpg", // headerImageUrl = "https://i.ytimg.com/vi/r5JgIyS3t3s/maxresdefault.jpg",
publishDate = Instant.parse("2021-11-08T00:00:00.000Z"), // publishDate = Instant.parse("2021-11-08T00:00:00.000Z"),
type = Video, // type = Video,
topics = listOf( // topics = listOf(
Topic( // Topic(
id = "1", // id = "1",
name = "UI", // name = "UI",
shortDescription = "", // shortDescription = "",
longDescription = "", // longDescription = "",
url = "", // url = "",
imageUrl = "" // imageUrl = ""
), // ),
), // ),
authors = emptyList() // authors = emptyList()
), // ),
isSaved = false // isSaved = false
), // ),
) // )
//
composeTestRule.setContent { // composeTestRule.setContent {
BoxWithConstraints { // BoxWithConstraints {
windowSizeClass = WindowSizeClass.calculateFromSize( // windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight) // DpSize(maxWidth, maxHeight)
) // )
//
ForYouScreen( // ForYouScreen(
windowSizeClass = windowSizeClass, // windowSizeClass = windowSizeClass,
interestsSelectionState = ForYouInterestsSelectionUiState.NoInterestsSelection, // interestsSelectionState = ForYouInterestsSelectionUiState.NoInterestsSelection,
feedState = ForYouFeedUiState.Success( // feedState = ForYouFeedUiState.Success(
feed = saveableNewsResources // feed = saveableNewsResources
), // ),
onAuthorCheckedChanged = { _, _ -> }, // onAuthorCheckedChanged = { _, _ -> },
onTopicCheckedChanged = { _, _ -> }, // onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {}, // saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> } // onNewsResourcesCheckedChanged = { _, _ -> }
) // )
} // }
} // }
//
// Scroll until the second feed item is visible // // Scroll until the second feed item is visible
// This will cause both the first and second feed items to be visible at the same time, // // This will cause both the first and second feed items to be visible at the same time,
// so we can compare their positions to each other. // // so we can compare their positions to each other.
composeTestRule // composeTestRule
.onAllNodes(hasScrollToNodeAction()) // .onAllNodes(hasScrollToNodeAction())
.onFirst() // .onFirst()
.performScrollToNode( // .performScrollToNode(
hasText( // hasText(
"Transformations and customisations in the Paging Library", // "Transformations and customisations in the Paging Library",
substring = true // substring = true
) // )
) // )
//
val firstFeedItem = composeTestRule // val firstFeedItem = composeTestRule
.onNodeWithText( // .onNodeWithText(
"Thanks for helping us reach 1M YouTube Subscribers", // "Thanks for helping us reach 1M YouTube Subscribers",
substring = true // substring = true
) // )
.assertHasClickAction() // .assertHasClickAction()
.fetchSemanticsNode() // .fetchSemanticsNode()
//
val secondFeedItem = composeTestRule // val secondFeedItem = composeTestRule
.onNodeWithText( // .onNodeWithText(
"Transformations and customisations in the Paging Library", // "Transformations and customisations in the Paging Library",
substring = true // substring = true
) // )
.assertHasClickAction() // .assertHasClickAction()
.fetchSemanticsNode() // .fetchSemanticsNode()
//
when (windowSizeClass.widthSizeClass) { // when (windowSizeClass.widthSizeClass) {
WindowWidthSizeClass.Compact, Companion.Medium -> { // WindowWidthSizeClass.Compact, Companion.Medium -> {
// On smaller screen widths, the second feed item should be below the first because // // On smaller screen widths, the second feed item should be below the first because
// they are displayed in a single column // // they are displayed in a single column
assertTrue( // assertTrue(
firstFeedItem.positionInRoot.y < secondFeedItem.positionInRoot.y // firstFeedItem.positionInRoot.y < secondFeedItem.positionInRoot.y
) // )
} // }
else -> { // else -> {
// On larger screen widths, the second feed item should be inline with the first // // On larger screen widths, the second feed item should be inline with the first
// because they are displayed in more than one column // // because they are displayed in more than one column
assertTrue( // assertTrue(
firstFeedItem.positionInRoot.y == secondFeedItem.positionInRoot.y // firstFeedItem.positionInRoot.y == secondFeedItem.positionInRoot.y
) // )
} // }
} // }
} // }
} }

@ -33,7 +33,7 @@ kotlinxDatetime = "0.3.3"
kotlinxSerializationJson = "1.3.3" kotlinxSerializationJson = "1.3.3"
ksp = "1.6.21-1.0.5" ksp = "1.6.21-1.0.5"
ktlint = "0.43.0" ktlint = "0.43.0"
material3 = "1.5.0-alpha05" material3 = "1.6.1"
okhttp = "4.9.3" okhttp = "4.9.3"
protobuf = "3.20.0" protobuf = "3.20.0"
protobufPlugin = "0.8.18" protobufPlugin = "0.8.18"

Loading…
Cancel
Save