Skip to content

Commit b478cea

Browse files
committed
Fix failing UI test, add unit test and refactor
1 parent fbf0558 commit b478cea

File tree

6 files changed

+165
-135
lines changed

6 files changed

+165
-135
lines changed

app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.samples.apps.nowinandroid.ui
1818

19+
import androidx.compose.ui.semantics.SemanticsActions.ScrollBy
1920
import androidx.compose.ui.test.assertCountEquals
2021
import androidx.compose.ui.test.assertIsOn
2122
import androidx.compose.ui.test.assertIsSelected
@@ -290,9 +291,19 @@ class NavigationTest {
290291
// Note: Possible flakiness. If the content of the news resource is long then the topic
291292
// tag might not be visible meaning it cannot be clicked
292293
onNodeWithTag("forYou:feed")
293-
.performScrollToNode(
294-
hasTestTag("newsResourceCard:${newsResource.id}"),
295-
)
294+
.performScrollToNode(hasTestTag("newsResourceCard:${newsResource.id}"))
295+
.fetchSemanticsNode()
296+
.apply {
297+
val newsResourceCardNode = onNodeWithTag("newsResourceCard:${newsResource.id}")
298+
.fetchSemanticsNode()
299+
config[ScrollBy].action?.invoke(
300+
0f,
301+
// to ensure the bottom of the card is visible,
302+
// manually scroll the difference between the height of
303+
// the scrolling node and the height of the card
304+
(newsResourceCardNode.size.height - size.height).coerceAtLeast(0).toFloat(),
305+
)
306+
}
296307

297308
// Click the first topic tag
298309
onAllNodesWithTag("topicTag:${topic.id}", useUnmergedTree = true)

core/data-test/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/test/repository/FakeNewsRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
package com.google.samples.apps.nowinandroid.core.data.test.repository
1818

1919
import com.google.samples.apps.nowinandroid.core.data.Synchronizer
20+
import com.google.samples.apps.nowinandroid.core.data.model.asExternalModel
2021
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
2122
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
2223
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
2324
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
2425
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
2526
import com.google.samples.apps.nowinandroid.core.network.demo.DemoNiaNetworkDataSource
26-
import com.google.samples.apps.nowinandroid.core.network.model.asExternalModel
2727
import kotlinx.coroutines.CoroutineDispatcher
2828
import kotlinx.coroutines.flow.Flow
2929
import kotlinx.coroutines.flow.flow

core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/model/NewsResource.kt

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ package com.google.samples.apps.nowinandroid.core.data.model
1919
import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceEntity
2020
import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceTopicCrossRef
2121
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
22+
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
2223
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
23-
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResourceExpanded
24+
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
25+
import com.google.samples.apps.nowinandroid.core.network.model.asExternalModel
2426

2527
fun NetworkNewsResource.asEntity() = NewsResourceEntity(
2628
id = id,
@@ -32,16 +34,6 @@ fun NetworkNewsResource.asEntity() = NewsResourceEntity(
3234
type = type,
3335
)
3436

35-
fun NetworkNewsResourceExpanded.asEntity() = NewsResourceEntity(
36-
id = id,
37-
title = title,
38-
content = content,
39-
url = url,
40-
headerImageUrl = headerImageUrl,
41-
publishDate = publishDate,
42-
type = type,
43-
)
44-
4537
/**
4638
* A shell [TopicEntity] to fulfill the foreign key constraint when inserting
4739
* a [NewsResourceEntity] into the DB
@@ -65,3 +57,17 @@ fun NetworkNewsResource.topicCrossReferences(): List<NewsResourceTopicCrossRef>
6557
topicId = topicId,
6658
)
6759
}
60+
61+
fun NetworkNewsResource.asExternalModel(topics: List<NetworkTopic>) =
62+
NewsResource(
63+
id = id,
64+
title = title,
65+
content = content,
66+
url = url,
67+
headerImageUrl = headerImageUrl,
68+
publishDate = publishDate,
69+
type = type,
70+
topics = topics
71+
.filter { networkTopic -> this.topics.contains(networkTopic.id) }
72+
.map(NetworkTopic::asExternalModel),
73+
)

core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/model/NetworkEntityKtTest.kt

Lines changed: 0 additions & 91 deletions
This file was deleted.
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.samples.apps.nowinandroid.core.data.model
18+
19+
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
20+
import com.google.samples.apps.nowinandroid.core.model.data.Topic
21+
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
22+
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
23+
import kotlinx.datetime.Instant
24+
import org.junit.Test
25+
import kotlin.test.assertEquals
26+
27+
class NetworkEntityTest {
28+
29+
@Test
30+
fun networkTopicMapsToDatabaseModel() {
31+
val networkModel = NetworkTopic(
32+
id = "0",
33+
name = "Test",
34+
shortDescription = "short description",
35+
longDescription = "long description",
36+
url = "URL",
37+
imageUrl = "image URL",
38+
)
39+
val entity = networkModel.asEntity()
40+
41+
assertEquals("0", entity.id)
42+
assertEquals("Test", entity.name)
43+
assertEquals("short description", entity.shortDescription)
44+
assertEquals("long description", entity.longDescription)
45+
assertEquals("URL", entity.url)
46+
assertEquals("image URL", entity.imageUrl)
47+
}
48+
49+
@Test
50+
fun networkNewsResourceMapsToDatabaseModel() {
51+
val networkModel =
52+
NetworkNewsResource(
53+
id = "0",
54+
title = "title",
55+
content = "content",
56+
url = "url",
57+
headerImageUrl = "headerImageUrl",
58+
publishDate = Instant.fromEpochMilliseconds(1),
59+
type = "Article 📚",
60+
)
61+
val entity = networkModel.asEntity()
62+
63+
assertEquals("0", entity.id)
64+
assertEquals("title", entity.title)
65+
assertEquals("content", entity.content)
66+
assertEquals("url", entity.url)
67+
assertEquals("headerImageUrl", entity.headerImageUrl)
68+
assertEquals(Instant.fromEpochMilliseconds(1), entity.publishDate)
69+
assertEquals("Article 📚", entity.type)
70+
}
71+
72+
@Test
73+
fun networkNewsResourceMapsToExternalModel() {
74+
val networkNewsResource = NetworkNewsResource(
75+
id = "0",
76+
title = "title",
77+
content = "content",
78+
url = "url",
79+
headerImageUrl = "headerImageUrl",
80+
publishDate = Instant.fromEpochMilliseconds(1),
81+
type = "Article 📚",
82+
topics = listOf("1", "2"),
83+
)
84+
85+
val networkTopics = listOf(
86+
NetworkTopic(
87+
id = "1",
88+
name = "Test 1",
89+
shortDescription = "short description 1",
90+
longDescription = "long description 1",
91+
url = "url 1",
92+
imageUrl = "imageUrl 1",
93+
),
94+
NetworkTopic(
95+
id = "2",
96+
name = "Test 2",
97+
shortDescription = "short description 2",
98+
longDescription = "long description 2",
99+
url = "url 2",
100+
imageUrl = "imageUrl 2",
101+
),
102+
)
103+
104+
val expected = NewsResource(
105+
id = "0",
106+
title = "title",
107+
content = "content",
108+
url = "url",
109+
headerImageUrl = "headerImageUrl",
110+
publishDate = Instant.fromEpochMilliseconds(1),
111+
type = "Article 📚",
112+
topics = listOf(
113+
Topic(
114+
id = "1",
115+
name = "Test 1",
116+
shortDescription = "short description 1",
117+
longDescription = "long description 1",
118+
url = "url 1",
119+
imageUrl = "imageUrl 1",
120+
),
121+
Topic(
122+
id = "2",
123+
name = "Test 2",
124+
shortDescription = "short description 2",
125+
longDescription = "long description 2",
126+
url = "url 2",
127+
imageUrl = "imageUrl 2",
128+
),
129+
),
130+
)
131+
assertEquals(expected, networkNewsResource.asExternalModel(networkTopics))
132+
}
133+
}

core/network/src/main/kotlin/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,32 +34,3 @@ data class NetworkNewsResource(
3434
val type: String,
3535
val topics: List<String> = listOf(),
3636
)
37-
38-
fun NetworkNewsResource.asExternalModel(topics: List<NetworkTopic>) =
39-
NewsResource(
40-
id = id,
41-
title = title,
42-
content = content,
43-
url = url,
44-
headerImageUrl = headerImageUrl,
45-
publishDate = publishDate,
46-
type = type,
47-
topics = topics
48-
.filter { networkTopic -> this.topics.contains(networkTopic.id) }
49-
.map(NetworkTopic::asExternalModel),
50-
)
51-
52-
/**
53-
* Network representation of [NewsResource] when fetched from /newsresources/{id}
54-
*/
55-
@Serializable
56-
data class NetworkNewsResourceExpanded(
57-
val id: String,
58-
val title: String,
59-
val content: String,
60-
val url: String,
61-
val headerImageUrl: String,
62-
val publishDate: Instant,
63-
val type: String,
64-
val topics: List<NetworkTopic> = listOf(),
65-
)

0 commit comments

Comments
 (0)