Repository: android/nowinandroid
File: app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt (Kotlin)

Code before:

            // Switch tab
            onNodeWithText(forYou).performClick()

            // Come back to Interests
            onNodeWithText(interests).performClick()

            // Verify the topic is still shown
            onNodeWithTag("topic:${topic.id}").assertExists()
        }
    }

    @Test
    fun navigatingToTopicFromForYou_showsTopicDetails() {
        composeTestRule.apply {
            // Follow a topic
            onNodeWithText(sampleTopic).performClick()

            // Get the topic ID
            val topic = runBlocking {
                topicsRepository.getTopics().first().filter { it.name == sampleTopic }.first()
            }

            // Tap the first topic chip
            onNodeWithTag("topicChip:${topic.id}", useUnmergedTree = true)
                .assertExists()
                .performClick()

            // TEST FAILING HERE
            composeTestRule.waitUntil(timeoutMillis = 3_600_000, condition = { false })

            // Verify that we're on the correct topic details screen
            onNodeWithTag("topic:${topic.id}").assertExists()
        }
    }
}


Review comment (bug):
```
java.lang.AssertionError: Failed: assertExists.
Reason: Expected exactly '1' node but found '2' nodes that satisfy: (TestTag = 'topicChip:1')
Nodes found:
1) Node #209 at (l=315.0, t=2707.0, r=516.0, b=2833.0)px, Tag: 'topicChip:1'
Has 1 child
2) Node #239 at (l=1293.0, t=2896.0, r=1494.0, b=3022.0)px, Tag: 'topicChip:1'
Has 1 child, 2 siblings
```

Code after:

            // Select the last topic
            val topic = runBlocking {
                topicsRepository.getTopics().first().sortedBy(Topic::name).last()
            }
            onNodeWithTag("interests:topics").performScrollToNode(hasText(topic.name))
            onNodeWithText(topic.name).performClick()

            // Switch tab
            onNodeWithText(forYou).performClick()

            // Come back to Interests
            onNodeWithText(interests).performClick()

            // Verify the topic is still shown
            onNodeWithTag("topic:${topic.id}").assertExists()
        }
    }

    @Test
    fun navigatingToTopicFromForYou_showsTopicDetails() {
        composeTestRule.apply {
            // Get the first news resource
            val newsResource = runBlocking {
                newsRepository.getNewsResources().first().first()
            }

            // Get its first topic and follow it
            val topic = newsResource.topics.first()
            onNodeWithText(topic.name).performClick()

            // Get the news feed and scroll to the news resource
            // Note: Possible flakiness. If the content of the news resource is long then the topic
            // tag might not be visible meaning it cannot be clicked
            onNodeWithTag("forYou:feed")
                .performScrollToNode(hasTestTag("newsResourceCard:${newsResource.id}"))
                .fetchSemanticsNode()
                .apply {
                    val newsResourceCardNode = onNodeWithTag("newsResourceCard:${newsResource.id}")
                        .fetchSemanticsNode()
                    config[ScrollBy].action?.invoke(
                        0f,
                        // to ensure the bottom of the card is visible,
                        // manually scroll the difference between the height of
                        // the scrolling node and the height of the card
                        (newsResourceCardNode.size.height - size.height).coerceAtLeast(0).toFloat(),
                    )
                }

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