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