1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
2  * Any copyright is dedicated to the Public Domain.
3    http://creativecommons.org/publicdomain/zero/1.0/ */
4 
5 package org.mozilla.geckoview.test
6 
7 import org.mozilla.geckoview.GeckoResult
8 import org.mozilla.geckoview.GeckoSession
9 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
10 
11 
12 import androidx.test.filters.MediumTest
13 import androidx.test.ext.junit.runners.AndroidJUnit4
14 import org.hamcrest.Matchers.*
15 import org.junit.Test
16 import org.junit.runner.RunWith
17 import org.mozilla.geckoview.test.util.Callbacks
18 import org.junit.Ignore
19 import org.mozilla.geckoview.test.util.UiThreadUtils
20 
21 @RunWith(AndroidJUnit4::class)
22 @MediumTest
23 class HistoryDelegateTest : BaseSessionTest() {
24     companion object {
25         // Keep in sync with the styles in `LINKS_HTML_PATH`.
26         const val UNVISITED_COLOR = "rgb(0, 0, 255)"
27         const val VISITED_COLOR = "rgb(255, 0, 0)"
28     }
29 
getVisitednull30     @Test fun getVisited() {
31         val testUri = createTestUrl(LINKS_HTML_PATH)
32         sessionRule.delegateDuringNextWait(object : GeckoSession.HistoryDelegate {
33             @AssertCalled(count = 1)
34             override fun onVisited(session: GeckoSession, url: String,
35                                    lastVisitedURL: String?,
36                                    flags: Int): GeckoResult<Boolean>? {
37                 assertThat("Should pass visited URL", url, equalTo(testUri))
38                 assertThat("Should not pass last visited URL", lastVisitedURL, nullValue())
39                 assertThat("Should set visit flags", flags,
40                     equalTo(GeckoSession.HistoryDelegate.VISIT_TOP_LEVEL))
41                 return GeckoResult.fromValue(true)
42             }
43 
44             @AssertCalled(count = 1)
45             override fun getVisited(session: GeckoSession,
46                                     urls: Array<String>) : GeckoResult<BooleanArray>? {
47                 val expected = arrayOf(
48                     "https://mozilla.org/",
49                     "https://getfirefox.com/",
50                     "https://bugzilla.mozilla.org/",
51                     "https://testpilot.firefox.com/",
52                     "https://accounts.firefox.com/"
53                 )
54                 assertThat("Should pass URLs to check", urls.sorted(),
55                     equalTo(expected.sorted()))
56 
57                 val visits = BooleanArray(urls.size, {
58                     when (urls[it]) {
59                         "https://mozilla.org/", "https://testpilot.firefox.com/" -> true
60                         else -> false
61                     }
62                 })
63                 return GeckoResult.fromValue(visits)
64             }
65         })
66 
67         // Since `getVisited` is called asynchronously after the page loads, we
68         // can't use `waitForPageStop` here.
69         sessionRule.session.loadUri(testUri)
70         sessionRule.session.waitUntilCalled(GeckoSession.HistoryDelegate::class,
71                                             "onVisited", "getVisited")
72 
73         // Sometimes link changes are not applied immediately, wait for a little bit
74         UiThreadUtils.waitForCondition({
75             sessionRule.getLinkColor(testUri, "#mozilla") == VISITED_COLOR
76         }, sessionRule.env.defaultTimeoutMillis)
77 
78         assertThat(
79             "Mozilla should be visited",
80             sessionRule.getLinkColor(testUri, "#mozilla"),
81             equalTo(VISITED_COLOR)
82         )
83 
84         assertThat(
85             "Test Pilot should be visited",
86             sessionRule.getLinkColor(testUri, "#testpilot"),
87             equalTo(VISITED_COLOR)
88         )
89 
90         assertThat(
91             "Bugzilla should be unvisited",
92             sessionRule.getLinkColor(testUri, "#bugzilla"),
93             equalTo(UNVISITED_COLOR)
94         )
95     }
96 
97     @Ignore //disable test on debug for frequent failures Bug 1544169
onHistoryStateChangenull98     @Test fun onHistoryStateChange() {
99         sessionRule.session.loadTestPath(HELLO_HTML_PATH)
100 
101         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
102             @AssertCalled(count = 1)
103             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
104                 assertThat("History should have one entry", state.size,
105                         equalTo(1))
106                 assertThat("URLs should match", state[state.currentIndex].uri,
107                         endsWith(HELLO_HTML_PATH))
108                 assertThat("History index should be 0", state.currentIndex,
109                         equalTo(0))
110             }
111         })
112 
113         sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
114 
115         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
116             @AssertCalled(count = 1)
117             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
118                 assertThat("History should have two entries", state.size,
119                         equalTo(2))
120                 assertThat("URLs should match", state[state.currentIndex].uri,
121                         endsWith(HELLO2_HTML_PATH))
122                 assertThat("History index should be 1", state.currentIndex,
123                         equalTo(1))
124             }
125         })
126 
127         sessionRule.session.goBack()
128 
129         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
130             @AssertCalled(count = 1)
131             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
132                 assertThat("History should have two entries", state.size,
133                         equalTo(2))
134                 assertThat("URLs should match", state[state.currentIndex].uri,
135                         endsWith(HELLO_HTML_PATH))
136                 assertThat("History index should be 0", state.currentIndex,
137                         equalTo(0))
138             }
139         })
140 
141         sessionRule.session.goForward()
142 
143         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
144             @AssertCalled(count = 1)
145             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
146                 assertThat("History should have two entries", state.size,
147                         equalTo(2))
148                 assertThat("URLs should match", state[state.currentIndex].uri,
149                         endsWith(HELLO2_HTML_PATH))
150                 assertThat("History index should be 1", state.currentIndex,
151                         equalTo(1))
152             }
153         })
154 
155         sessionRule.session.gotoHistoryIndex(0)
156 
157         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
158             @AssertCalled(count = 1)
159             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
160                 assertThat("History should have two entries", state.size,
161                         equalTo(2))
162                 assertThat("URLs should match", state[state.currentIndex].uri,
163                         endsWith(HELLO_HTML_PATH))
164                 assertThat("History index should be 1", state.currentIndex,
165                         equalTo(0))
166             }
167         })
168 
169         sessionRule.session.gotoHistoryIndex(1)
170 
171         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
172             @AssertCalled(count = 1)
173             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
174                 assertThat("History should have two entries", state.size,
175                         equalTo(2))
176                 assertThat("URLs should match", state[state.currentIndex].uri,
177                         endsWith(HELLO2_HTML_PATH))
178                 assertThat("History index should be 1", state.currentIndex,
179                         equalTo(1))
180             }
181         })
182     }
183 
onHistoryStateChangeSavingStatenull184     @Test fun onHistoryStateChangeSavingState() {
185         // This is a smaller version of the above test, in the hopes to minimize race conditions
186         sessionRule.session.loadTestPath(HELLO_HTML_PATH)
187 
188         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
189             @AssertCalled(count = 1)
190             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
191                 assertThat("History should have one entry", state.size,
192                         equalTo(1))
193                 assertThat("URLs should match", state[state.currentIndex].uri,
194                         endsWith(HELLO_HTML_PATH))
195                 assertThat("History index should be 0", state.currentIndex,
196                         equalTo(0))
197             }
198         })
199 
200         sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
201 
202         sessionRule.waitUntilCalled(object : Callbacks.HistoryDelegate {
203             @AssertCalled(count = 1)
204             override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) {
205                 assertThat("History should have two entries", state.size,
206                         equalTo(2))
207                 assertThat("URLs should match", state[state.currentIndex].uri,
208                         endsWith(HELLO2_HTML_PATH))
209                 assertThat("History index should be 1", state.currentIndex,
210                         equalTo(1))
211             }
212         })
213     }
214 
215 
216 
217 }
218