Skip to content

Commit 26b63a1

Browse files
Williamraicoolteydbrant
authored
Espresso reading list test (#5350)
* - adds reading list test * - adds reading list specific tests * - minor code fix --------- Co-authored-by: Cooltey Feng <[email protected]> Co-authored-by: Dmitry Brant <[email protected]>
1 parent 86689f0 commit 26b63a1

11 files changed

+205
-13
lines changed

app/src/androidTest/java/org/wikipedia/base/actions/ListActions.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ class ListActions {
5252
)
5353
}
5454

55-
fun longClickOnItemInList(@IdRes listId: Int, position: Int) {
55+
fun clickOnItemInList(textViewId: Int) {
56+
onView(withId(textViewId))
57+
.perform(click())
58+
}
59+
60+
fun longClickOnItemInList(@IdRes listId: Int, position: Int) {
5661
onView(withId(listId))
5762
.perform(
5863
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
@@ -114,7 +119,8 @@ class ListActions {
114119
recyclerViewId: Int = R.id.feed_view,
115120
title: String,
116121
textViewId: Int = R.id.view_card_header_title,
117-
verticalOffset: Int = 200
122+
verticalOffset: Int = 200,
123+
action: (() -> Unit)? = null
118124
) = apply {
119125
var currentOccurrence = 0
120126
onView(withId(recyclerViewId))
@@ -155,6 +161,7 @@ class ListActions {
155161
})
156162
}
157163
}
164+
action?.invoke()
158165
}
159166

160167
fun verifyRecyclerViewItemCount(@IdRes viewId: Int, expectedCount: Int) {

app/src/androidTest/java/org/wikipedia/base/actions/VerificationActions.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.annotation.ColorRes
55
import androidx.annotation.IdRes
66
import androidx.recyclerview.widget.RecyclerView
77
import androidx.test.espresso.Espresso.onView
8+
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
89
import androidx.test.espresso.assertion.ViewAssertions.matches
910
import androidx.test.espresso.contrib.RecyclerViewActions
1011
import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition
@@ -27,18 +28,28 @@ class VerificationActions {
2728
onView(withId(viewId)).check(matches(isDisplayed()))
2829
}
2930

30-
fun viewDoesNotExist(@IdRes viewId: Int) {
31+
fun viewWithIdIsNotVisible(@IdRes viewId: Int) {
3132
onView(withId(viewId)).check(matches(not(isDisplayed())))
3233
}
3334

3435
fun viewWithTextDisplayed(text: String) {
3536
onView(withText(text)).check(matches(isDisplayed()))
3637
}
3738

38-
fun textDoesNotExist(text: String) {
39+
fun textIsNotVisible(text: String) {
3940
onView(withText(text)).check(matches(not(isDisplayed())))
4041
}
4142

43+
fun viewWithIdDoesNotExist(@IdRes viewId: Int) {
44+
onView(withId(viewId))
45+
.check(doesNotExist())
46+
}
47+
48+
fun viewWithTextDoesNotExist(title: String) {
49+
onView(withText(title))
50+
.check(doesNotExist())
51+
}
52+
4253
fun viewWithIdDisplayed(@IdRes viewId: Int) {
4354
onView(withId(viewId)).check(matches(isDisplayed()))
4455
}

app/src/androidTest/java/org/wikipedia/robots/AppThemeRobot.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class AppThemeRobot : BaseRobot() {
1818

1919
fun switchOffMatchSystemTheme() = apply {
2020
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
21-
verify.viewDoesNotExist(R.id.theme_chooser_match_system_theme_switch)
21+
verify.viewWithIdIsNotVisible(R.id.theme_chooser_match_system_theme_switch)
2222
} else {
2323
scroll.toViewAndClick(R.id.theme_chooser_match_system_theme_switch)
2424
}

app/src/androidTest/java/org/wikipedia/robots/DialogRobot.kt

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.wikipedia.robots
22

3+
import android.content.Context
4+
import org.wikipedia.R
35
import org.wikipedia.base.base.BaseRobot
46

57
class DialogRobot : BaseRobot() {
@@ -15,4 +17,14 @@ class DialogRobot : BaseRobot() {
1517
fun clickLogOutUser() = apply {
1618
click.ifDialogShown("Log out", errorString = "Cannot click Log out.")
1719
}
20+
21+
fun dismissPromptLogInToSyncDialog(context: Context) = apply {
22+
click.ifDialogShown(
23+
context.getString(R.string.reading_list_prompt_turned_sync_on_dialog_no_thanks),
24+
errorString = "Cannot click")
25+
}
26+
27+
fun click(string: String) = apply {
28+
click.ifDialogShown(string, "Cannot click")
29+
}
1830
}

app/src/androidTest/java/org/wikipedia/robots/feature/ExploreFeedRobot.kt

+1-4
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,7 @@ class ExploreFeedRobot : BaseRobot() {
120120
}
121121

122122
fun verifyFeaturedArticleImageIsNotVisible() = apply {
123-
list.verifyItemDoesNotExistAtPosition(
124-
recyclerViewId = R.id.feed_view,
125-
itemId = R.id.articleImage
126-
)
123+
verify.viewWithIdIsNotVisible(viewId = R.id.articleImage)
127124
delay(TestConfig.DELAY_MEDIUM)
128125
}
129126

app/src/androidTest/java/org/wikipedia/robots/feature/MediaRobot.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class MediaRobot : BaseRobot() {
5959
return@apply
6060
}
6161

62-
verify.viewDoesNotExist(R.id.toolbar_container)
62+
verify.viewWithIdIsNotVisible(R.id.toolbar_container)
6363
delay(TestConfig.DELAY_MEDIUM)
6464
}
6565

app/src/androidTest/java/org/wikipedia/robots/feature/MoreMenuRobot.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class MoreMenuRobot : BaseRobot() {
3030
verify.viewExists(R.id.main_drawer_contribs_container)
3131
verify.viewExists(R.id.main_drawer_talk_container)
3232
verify.viewExists(R.id.main_drawer_watchlist_container)
33-
verify.viewDoesNotExist(R.id.main_drawer_login_button)
33+
verify.viewWithIdIsNotVisible(R.id.main_drawer_login_button)
3434
}
3535

3636
fun clickPlaces() = apply {

app/src/androidTest/java/org/wikipedia/robots/feature/PageRobot.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class PageRobot(private val context: Context) : BaseRobot() {
8383
}
8484

8585
fun verifyLeadImageIsNotVisible() = apply {
86-
verify.viewDoesNotExist(R.id.page_header_view)
86+
verify.viewWithIdIsNotVisible(R.id.page_header_view)
8787
}
8888

8989
fun swipePagerLeft() = apply {

app/src/androidTest/java/org/wikipedia/robots/feature/ReadingListRobot.kt

+59
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,53 @@ import org.wikipedia.base.TestConfig
2121
import org.wikipedia.base.base.BaseRobot
2222

2323
class ReadingListRobot : BaseRobot() {
24+
25+
fun clickOnReadingLists(position: Int) = apply {
26+
list.clickOnItemInList(
27+
listId = R.id.recycler_view,
28+
position
29+
)
30+
delay(TestConfig.DELAY_MEDIUM)
31+
}
32+
33+
fun clickOnReadingLists(title: String) = apply {
34+
list.scrollToRecyclerView(
35+
recyclerViewId = R.id.recycler_view,
36+
title = title,
37+
textViewId = R.id.item_title,
38+
action = {
39+
click.onDisplayedViewWithText(
40+
viewId = R.id.item_title,
41+
text = title
42+
)
43+
}
44+
)
45+
delay(TestConfig.DELAY_SHORT)
46+
}
47+
48+
fun clickOnReadingListItem(position: Int) = apply {
49+
list.clickOnItemInList(
50+
listId = R.id.reading_list_recycler_view,
51+
position = position
52+
)
53+
}
54+
55+
fun longClickReadingLists(position: Int) = apply {
56+
list.longClickOnItemInList(
57+
listId = R.id.recycler_view,
58+
position = position
59+
)
60+
}
61+
62+
fun deleteList(context: Context) {
63+
click.onViewWithText(context.getString(R.string.reading_list_menu_delete))
64+
}
65+
66+
fun removeArticleList(listName: String) = apply {
67+
click.onViewWithText("Remove from $listName")
68+
delay(TestConfig.DELAY_LARGE)
69+
}
70+
2471
fun saveArticleToReadingList() = apply {
2572
click.onViewWithId(R.id.page_save)
2673
delay(TestConfig.DELAY_SHORT)
@@ -62,6 +109,18 @@ class ReadingListRobot : BaseRobot() {
62109
}
63110
}
64111

112+
fun verifySavedArticleExists(title: String) = apply {
113+
verify.viewWithTextDisplayed(title)
114+
}
115+
116+
fun verifySavedArticleDoesNotExists(title: String) = apply {
117+
verify.viewWithTextDoesNotExist(title)
118+
}
119+
120+
fun verifyListDoesNotExist(title: String) = apply {
121+
verify.viewWithTextDoesNotExist(title)
122+
}
123+
65124
fun verifyArticleHasNotDownloaded() = apply {
66125
delay(TestConfig.DELAY_MEDIUM)
67126
onView(withId(R.id.reading_list_recycler_view))

app/src/androidTest/java/org/wikipedia/robots/feature/SettingsRobot.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class SettingsRobot : BaseRobot() {
176176
}
177177

178178
fun verifyExploreFeedIsNotEmpty(context: Context) = apply {
179-
verify.textDoesNotExist(context.getString(R.string.feed_empty_message))
179+
verify.textIsNotVisible(context.getString(R.string.feed_empty_message))
180180
delay(TestConfig.DELAY_SHORT)
181181
}
182182

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package org.wikipedia.tests
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import androidx.test.filters.LargeTest
5+
import org.junit.Test
6+
import org.junit.runner.RunWith
7+
import org.wikipedia.base.BaseTest
8+
import org.wikipedia.main.MainActivity
9+
import org.wikipedia.robots.DialogRobot
10+
import org.wikipedia.robots.SystemRobot
11+
import org.wikipedia.robots.feature.LoginRobot
12+
import org.wikipedia.robots.feature.ReadingListRobot
13+
import org.wikipedia.robots.feature.SearchRobot
14+
import org.wikipedia.robots.navigation.BottomNavRobot
15+
16+
@LargeTest
17+
@RunWith(AndroidJUnit4::class)
18+
class ReadingListsTest : BaseTest<MainActivity>(
19+
activityClass = MainActivity::class.java
20+
) {
21+
private val systemRobot = SystemRobot()
22+
private val bottomNavRobot = BottomNavRobot()
23+
private val loginRobot = LoginRobot()
24+
private val searchRobot = SearchRobot()
25+
private val readingListRobot = ReadingListRobot()
26+
private val dialogRobot = DialogRobot()
27+
28+
@Test
29+
fun runTest() {
30+
systemRobot
31+
.clickOnSystemDialogWithText("Allow")
32+
// 1. saved article should be in the "Saved" reading list
33+
search(SEARCH_QUERY_WATERMELON)
34+
readingListRobot
35+
.saveArticleToReadingList()
36+
.pressBack()
37+
.pressBack()
38+
.pressBack()
39+
bottomNavRobot
40+
.navigateToSavedPage()
41+
readingListRobot
42+
.clickOnReadingLists(LIST_NAME_SAVED)
43+
.verifySavedArticleExists(SEARCH_QUERY_WATERMELON)
44+
.pressBack()
45+
bottomNavRobot
46+
.navigateToExploreFeed()
47+
// 2. article saved to a custom list should be in the custom list in the reading list
48+
search(SEARCH_QUERY_LEMON)
49+
readingListRobot
50+
.saveArticleToReadingList()
51+
.addToReadingList(context)
52+
.typeNameOfTheList(LIST_NAME_NEW, context)
53+
.saveTheList(context)
54+
.pressBack()
55+
.pressBack()
56+
.pressBack()
57+
dialogRobot
58+
.dismissPromptLogInToSyncDialog(context)
59+
bottomNavRobot
60+
.navigateToSavedPage()
61+
readingListRobot
62+
.clickOnReadingLists(LIST_NAME_NEW)
63+
.verifySavedArticleExists(SEARCH_QUERY_LEMON)
64+
.pressBack()
65+
// 3. unsaved article should not be in the "Saved" or "custom list" in the reading list
66+
bottomNavRobot
67+
.navigateToSavedPage()
68+
readingListRobot
69+
.clickOnReadingLists(LIST_NAME_SAVED)
70+
.clickOnReadingListItem(1)
71+
.saveArticleToReadingList()
72+
.removeArticleList(LIST_NAME_SAVED)
73+
.pressBack()
74+
.verifySavedArticleDoesNotExists(SEARCH_QUERY_WATERMELON)
75+
.pressBack()
76+
.clickOnReadingLists(LIST_NAME_NEW)
77+
.clickOnReadingListItem(1)
78+
.saveArticleToReadingList()
79+
.removeArticleList(LIST_NAME_NEW)
80+
.pressBack()
81+
.verifySavedArticleDoesNotExists(SEARCH_QUERY_LEMON)
82+
.pressBack()
83+
// 4. can delete lists
84+
readingListRobot
85+
.longClickReadingLists(1)
86+
.deleteList(context)
87+
dialogRobot
88+
.click("OK")
89+
readingListRobot
90+
.verifyListDoesNotExist(LIST_NAME_NEW)
91+
}
92+
93+
private fun search(title: String) {
94+
searchRobot
95+
.tapSearchView()
96+
.typeTextInView(title)
97+
.clickOnItemFromSearchList(0)
98+
}
99+
100+
companion object {
101+
private const val LIST_NAME_SAVED = "Saved"
102+
private const val LIST_NAME_NEW = "new"
103+
private const val SEARCH_QUERY_WATERMELON = "Watermelon"
104+
private const val SEARCH_QUERY_LEMON = "Lemon"
105+
}
106+
}

0 commit comments

Comments
 (0)