/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- * Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ package org.mozilla.geckoview.test import android.os.Handler import android.os.Looper import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoSession import org.mozilla.geckoview.GeckoSessionSettings import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.* import org.mozilla.geckoview.test.util.Callbacks import org.mozilla.geckoview.test.util.UiThreadUtils import androidx.test.filters.MediumTest import androidx.test.ext.junit.runners.AndroidJUnit4 import org.hamcrest.Matchers.* import org.json.JSONArray import org.json.JSONObject import org.junit.Assume.assumeThat import org.junit.Test import org.junit.runner.RunWith /** * Test for the GeckoSessionTestRule class, to ensure it properly sets up a session for * each test, and to ensure it can properly wait for and assert delegate * callbacks. */ @RunWith(AndroidJUnit4::class) @MediumTest class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) { @Test fun getSession() { assertThat("Can get session", sessionRule.session, notNullValue()) assertThat("Session is open", sessionRule.session.isOpen, equalTo(true)) } @ClosedSessionAtStart @Test fun getSession_closedSession() { assertThat("Session is closed", sessionRule.session.isOpen, equalTo(false)) } @Setting.List(Setting(key = Setting.Key.USE_PRIVATE_MODE, value = "true"), Setting(key = Setting.Key.DISPLAY_MODE, value = "DISPLAY_MODE_MINIMAL_UI"), Setting(key = Setting.Key.ALLOW_JAVASCRIPT, value = "false")) @Setting(key = Setting.Key.USE_TRACKING_PROTECTION, value = "true") @Test fun settingsApplied() { assertThat("USE_PRIVATE_MODE should be set", sessionRule.session.settings.usePrivateMode, equalTo(true)) assertThat("DISPLAY_MODE should be set", sessionRule.session.settings.displayMode, equalTo(GeckoSessionSettings.DISPLAY_MODE_MINIMAL_UI)) assertThat("USE_TRACKING_PROTECTION should be set", sessionRule.session.settings.useTrackingProtection, equalTo(true)) assertThat("ALLOW_JAVASCRIPT should be set", sessionRule.session.settings.allowJavascript, equalTo(false)) } @Test(expected = UiThreadUtils.TimeoutException::class) @TimeoutMillis(2000) fun noPendingCallbacks() { // Make sure we don't have unexpected pending callbacks at the start of a test. sessionRule.waitUntilCalled(object : Callbacks.All { // There may be extraneous onSessionStateChange and onHistoryStateChange calls // after a test, so ignore the first received. @AssertCalled(count = 2) override fun onSessionStateChange(session: GeckoSession, state: GeckoSession.SessionState) { } @AssertCalled(count = 2) override fun onHistoryStateChange(session: GeckoSession, historyList: GeckoSession.HistoryDelegate.HistoryList) { } }) } @Test fun includesAllCallbacks() { for (ifce in GeckoSession::class.java.classes) { if (!ifce.isInterface || !ifce.simpleName.endsWith("Delegate")) { continue } assertThat("Callbacks.All should include interface " + ifce.simpleName, ifce.isInstance(Callbacks.Default), equalTo(true)) } } @NullDelegate.List(NullDelegate(GeckoSession.ContentDelegate::class), NullDelegate(Callbacks.NavigationDelegate::class)) @NullDelegate(Callbacks.ScrollDelegate::class) @Test fun nullDelegate() { assertThat("Content delegate should be null", sessionRule.session.contentDelegate, nullValue()) assertThat("Navigation delegate should be null", sessionRule.session.navigationDelegate, nullValue()) assertThat("Scroll delegate should be null", sessionRule.session.scrollDelegate, nullValue()) assertThat("Progress delegate should not be null", sessionRule.session.progressDelegate, notNullValue()) } @NullDelegate(GeckoSession.ProgressDelegate::class) @ClosedSessionAtStart @Test fun nullDelegate_closed() { assertThat("Progress delegate should be null", sessionRule.session.progressDelegate, nullValue()) } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.ProgressDelegate::class) @ClosedSessionAtStart fun nullDelegate_requireProgressOnOpen() { assertThat("Progress delegate should be null", sessionRule.session.progressDelegate, nullValue()) sessionRule.session.open() } @Test fun waitForPageStop() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(1)) } @Test(expected = AssertionError::class) fun waitForPageStop_throwOnChangedCallback() { sessionRule.session.progressDelegate = Callbacks.Default sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test fun waitForPageStops() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.waitForPageStops(2) var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.ProgressDelegate::class) @ClosedSessionAtStart fun waitForPageStops_throwOnNullDelegate() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.open(sessionRule.runtime) // Avoid waiting for initial load sessionRule.session.reload() sessionRule.session.waitForPageStops(2) } @Test fun waitUntilCalled_anyInterfaceMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(GeckoSession.ProgressDelegate::class) var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { override fun onPageStart(session: GeckoSession, url: String) { counter++ } override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } override fun onSecurityChange(session: GeckoSession, securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) { counter++ } override fun onProgressChange(session: GeckoSession, progress: Int) { counter++ } override fun onSessionStateChange(session: GeckoSession, state: GeckoSession.SessionState) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(1)) } @Test fun waitUntilCalled_specificInterfaceMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(GeckoSession.ProgressDelegate::class, "onPageStart", "onPageStop") var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { override fun onPageStart(session: GeckoSession, url: String) { counter++ } override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test(expected = AssertionError::class) fun waitUntilCalled_throwOnNotGeckoSessionInterface() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(CharSequence::class) } fun waitUntilCalled_notThrowOnCallbackInterface() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(Callbacks.ProgressDelegate::class) } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.ScrollDelegate::class) fun waitUntilCalled_throwOnNullDelegateInterface() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitUntilCalled(Callbacks.All::class) } @NullDelegate(GeckoSession.ScrollDelegate::class) @Test fun waitUntilCalled_notThrowOnNonNullDelegateMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitUntilCalled(Callbacks.All::class, "onPageStop") } @Test fun waitUntilCalled_anyObjectMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) var counter = 0 sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate { override fun onPageStart(session: GeckoSession, url: String) { counter++ } override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } override fun onSecurityChange(session: GeckoSession, securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) { counter++ } override fun onProgressChange(session: GeckoSession, progress: Int) { counter++ } override fun onSessionStateChange(session: GeckoSession, state: GeckoSession.SessionState) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(1)) } @Test fun waitUntilCalled_specificObjectMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) var counter = 0 sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate { @AssertCalled override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.ScrollDelegate::class) fun waitUntilCalled_throwOnNullDelegateObject() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitUntilCalled(object : Callbacks.All { @AssertCalled override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @NullDelegate(GeckoSession.ScrollDelegate::class) @Test fun waitUntilCalled_notThrowOnNonNullDelegateObject() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitUntilCalled(object : Callbacks.All { @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun waitUntilCalled_multipleCount() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() var counter = 0 sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate { @AssertCalled(count = 2) override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled(count = 2) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(4)) } @Test fun waitUntilCalled_currentCall() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() var counter = 0 sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate { @AssertCalled(count = 2, order = [1, 2]) override fun onPageStop(session: GeckoSession, success: Boolean) { val info = sessionRule.currentCall assertThat("Method info should be valid", info, notNullValue()) assertThat("Counter should be correct", info.counter, equalTo(forEachCall(1, 2))) assertThat("Order should equal counter", info.order, equalTo(info.counter)) counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test(expected = IllegalStateException::class) fun waitUntilCalled_passThroughExceptions() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate { @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { throw IllegalStateException() } }) } @Test fun waitUntilCalled_zeroCount() { // Support having @AssertCalled(count = 0) annotations for waitUntilCalled calls. sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate, Callbacks.ScrollDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { } @AssertCalled(count = 0) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @Test fun forCallbacksDuringWait_anyMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(1)) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnAnyMethodNotCalled() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : GeckoSession.ScrollDelegate {}) } @Test fun forCallbacksDuringWait_specificMethod() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test fun forCallbacksDuringWait_specificMethodMultipleTimes() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.waitForPageStops(2) var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(4)) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnSpecificMethodNotCalled() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : GeckoSession.ScrollDelegate { @AssertCalled override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @Test fun forCallbacksDuringWait_specificCount() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.waitForPageStops(2) var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 2) override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled(count = 2) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(4)) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnWrongCount() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.waitForPageStops(2) sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStart(session: GeckoSession, url: String) { } @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun forCallbacksDuringWait_specificOrder() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(order = [1]) override fun onPageStart(session: GeckoSession, url: String) { } @AssertCalled(order = [2]) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnWrongOrder() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(order = [2]) override fun onPageStart(session: GeckoSession, url: String) { } @AssertCalled(order = [1]) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun forCallbacksDuringWait_multipleOrder() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.waitForPageStops(2) sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(order = [1, 3, 1]) override fun onPageStart(session: GeckoSession, url: String) { } @AssertCalled(order = [2, 4, 1]) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnWrongMultipleOrder() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.waitForPageStops(2) sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(order = [1, 2, 1]) override fun onPageStart(session: GeckoSession, url: String) { } @AssertCalled(order = [3, 4, 1]) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun forCallbacksDuringWait_notCalled() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : GeckoSession.ScrollDelegate { @AssertCalled(false) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnCallingNoCall() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun forCallbacksDuringWait_zeroCountEqualsNotCalled() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : GeckoSession.ScrollDelegate { @AssertCalled(count = 0) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @Test(expected = AssertionError::class) fun forCallbacksDuringWait_throwOnCallingZeroCount() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 0) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun forCallbacksDuringWait_limitedToLastWait() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.reload() sessionRule.session.reload() sessionRule.session.reload() // Wait for Gecko to finish all loads. Thread.sleep(100) sessionRule.waitForPageStop() // Wait for loadUri. sessionRule.waitForPageStop() // Wait for first reload. var counter = 0 // assert should only apply to callbacks within range (loadUri, first reload]. sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test fun forCallbacksDuringWait_currentCall() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { val info = sessionRule.currentCall assertThat("Method info should be valid", info, notNullValue()) assertThat("Counter should be correct", info.counter, equalTo(1)) assertThat("Order should equal counter", info.order, equalTo(0)) } }) } @Test(expected = IllegalStateException::class) fun forCallbacksDuringWait_passThroughExceptions() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { throw IllegalStateException() } }) } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.ScrollDelegate::class) fun forCallbacksDuringWait_throwOnAnyNullDelegate() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitForPageStop() sessionRule.session.forCallbacksDuringWait(object : Callbacks.All {}) } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.ScrollDelegate::class) fun forCallbacksDuringWait_throwOnSpecificNullDelegate() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitForPageStop() sessionRule.session.forCallbacksDuringWait(object : Callbacks.All { @AssertCalled override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @NullDelegate(GeckoSession.ScrollDelegate::class) @Test fun forCallbacksDuringWait_notThrowOnNonNullDelegate() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.session.reload() sessionRule.session.waitForPageStop() sessionRule.session.forCallbacksDuringWait(object : Callbacks.All { @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test(expected = AssertionError::class) fun getCurrentCall_throwOnNoCurrentCall() { sessionRule.currentCall } @Test fun delegateUntilTestEnd() { var counter = 0 sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1, order = [1]) override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled(count = 1, order = [2]) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() assertThat("Callback count should be correct", counter, equalTo(2)) } @Test fun delegateUntilTestEnd_notCalled() { sessionRule.delegateUntilTestEnd(object : GeckoSession.ScrollDelegate { @AssertCalled(false) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) } @Test(expected = AssertionError::class) fun delegateUntilTestEnd_throwOnNotCalled() { sessionRule.delegateUntilTestEnd(object : GeckoSession.ScrollDelegate { @AssertCalled(count = 1) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) sessionRule.performTestEndCheck() } @Test(expected = AssertionError::class) fun delegateUntilTestEnd_throwOnCallingNoCall() { sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test(expected = AssertionError::class) fun delegateUntilTestEnd_throwOnWrongOrder() { sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1, order = [2]) override fun onPageStart(session: GeckoSession, url: String) { } @AssertCalled(count = 1, order = [1]) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test fun delegateUntilTestEnd_currentCall() { sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { val info = sessionRule.currentCall assertThat("Method info should be valid", info, notNullValue()) assertThat("Counter should be correct", info.counter, equalTo(1)) assertThat("Order should equal counter", info.order, equalTo(0)) } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test fun delegateDuringNextWait() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var counter = 0 sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1, order = [1]) override fun onPageStart(session: GeckoSession, url: String) { counter++ } @AssertCalled(count = 1, order = [2]) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() assertThat("Should have delegated", counter, equalTo(2)) sessionRule.session.reload() sessionRule.waitForPageStop() assertThat("Delegate should be cleared", counter, equalTo(2)) } @Test(expected = AssertionError::class) fun delegateDuringNextWait_throwOnNotCalled() { sessionRule.delegateDuringNextWait(object : GeckoSession.ScrollDelegate { @AssertCalled(count = 1) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test(expected = AssertionError::class) fun delegateDuringNextWait_throwOnNotCalledAtTestEnd() { sessionRule.delegateDuringNextWait(object : GeckoSession.ScrollDelegate { @AssertCalled(count = 1) override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) { } }) sessionRule.performTestEndCheck() } @Test fun delegateDuringNextWait_hasPrecedence() { var testCounter = 0 var waitCounter = 0 sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate, Callbacks.NavigationDelegate { @AssertCalled(count = 1, order = [2]) override fun onPageStart(session: GeckoSession, url: String) { testCounter++ } @AssertCalled(count = 1, order = [4]) override fun onPageStop(session: GeckoSession, success: Boolean) { testCounter++ } @AssertCalled(count = 2, order = [1, 3]) override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { testCounter++ } @AssertCalled(count = 2, order = [1, 3]) override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { testCounter++ } }) sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1, order = [1]) override fun onPageStart(session: GeckoSession, url: String) { waitCounter++ } @AssertCalled(count = 1, order = [2]) override fun onPageStop(session: GeckoSession, success: Boolean) { waitCounter++ } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() assertThat("Text delegate should be overridden", testCounter, equalTo(2)) assertThat("Wait delegate should be used", waitCounter, equalTo(2)) sessionRule.session.reload() sessionRule.waitForPageStop() assertThat("Test delegate should be used", testCounter, equalTo(6)) assertThat("Wait delegate should be cleared", waitCounter, equalTo(2)) } @Test(expected = IllegalStateException::class) fun delegateDuringNextWait_passThroughExceptions() { sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate { @AssertCalled override fun onPageStop(session: GeckoSession, success: Boolean) { throw IllegalStateException() } }) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test(expected = AssertionError::class) @NullDelegate(GeckoSession.NavigationDelegate::class) fun delegateDuringNextWait_throwOnNullDelegate() { sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate { override fun onLocationChange(session: GeckoSession, url: String?) { } }) } @Test fun wrapSession() { val session = sessionRule.wrapSession( GeckoSession(sessionRule.session.settings)) sessionRule.openSession(session) session.reload() session.waitForPageStop() } @Test fun createOpenSession() { val newSession = sessionRule.createOpenSession() assertThat("Can create session", newSession, notNullValue()) assertThat("New session is open", newSession.isOpen, equalTo(true)) assertThat("New session has same settings", newSession.settings, equalTo(sessionRule.session.settings)) } @Test fun createOpenSession_withSettings() { val settings = GeckoSessionSettings.Builder(sessionRule.session.settings) .usePrivateMode(true) .build() val newSession = sessionRule.createOpenSession(settings) assertThat("New session has same settings", newSession.settings, equalTo(settings)) } @Test fun createOpenSession_canInterleaveOtherCalls() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) val newSession = sessionRule.createOpenSession() sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStops(2) newSession.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) sessionRule.session.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 2) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun createClosedSession() { val newSession = sessionRule.createClosedSession() assertThat("Can create session", newSession, notNullValue()) assertThat("New session is open", newSession.isOpen, equalTo(false)) assertThat("New session has same settings", newSession.settings, equalTo(sessionRule.session.settings)) } @Test fun createClosedSession_withSettings() { val settings = GeckoSessionSettings.Builder(sessionRule.session.settings).usePrivateMode(true).build() val newSession = sessionRule.createClosedSession(settings) assertThat("New session has same settings", newSession.settings, equalTo(settings)) } @Test(expected = UiThreadUtils.TimeoutException::class) @TimeoutMillis(2000) @ClosedSessionAtStart fun noPendingCallbacks_withSpecificSession() { sessionRule.createOpenSession() // Make sure we don't have unexpected pending callbacks after opening a session. sessionRule.waitUntilCalled(object : Callbacks.All { // There may be extraneous onSessionStateChange and onHistoryStateChange calls // after a test, so ignore the first received. @AssertCalled(count = 2) override fun onSessionStateChange(session: GeckoSession, state: GeckoSession.SessionState) { } @AssertCalled(count = 2) override fun onHistoryStateChange(session: GeckoSession, historyList: GeckoSession.HistoryDelegate.HistoryList) { } }) } @Test fun waitForPageStop_withSpecificSession() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitForPageStop() } @Test fun waitForPageStop_withAllSessions() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() } @Test(expected = AssertionError::class) fun waitForPageStop_throwOnNotWrapped() { GeckoSession(sessionRule.session.settings).waitForPageStop() } @Test fun waitForPageStops_withSpecificSessions() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.reload() newSession.waitForPageStops(2) } @Test fun waitForPageStops_withAllSessions() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStops(2) } @Test fun waitForPageStops_acrossSessionCreation() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) val session = sessionRule.createOpenSession() sessionRule.session.reload() session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStops(3) } @Test fun waitUntilCalled_interfaceWithSpecificSession() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitUntilCalled(Callbacks.ProgressDelegate::class, "onPageStop") } @Test fun waitUntilCalled_interfaceWithAllSessions() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(Callbacks.ProgressDelegate::class, "onPageStop") } @Test fun waitUntilCalled_callbackWithSpecificSession() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitUntilCalled(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun waitUntilCalled_callbackWithAllSessions() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate { @AssertCalled(count = 2) override fun onPageStop(session: GeckoSession, success: Boolean) { } }) } @Test fun forCallbacksDuringWait_withSpecificSession() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitForPageStop() var counter = 0 newSession.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) sessionRule.session.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(1)) } @Test fun forCallbacksDuringWait_withAllSessions() { val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStops(2) var counter = 0 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 2) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test fun forCallbacksDuringWait_limitedToLastSessionWait() { val newSession = sessionRule.createOpenSession() sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitForPageStop() // forCallbacksDuringWait calls strictly apply to the last wait, session-specific or not. var counter = 0 sessionRule.session.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) newSession.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) assertThat("Callback count should be correct", counter, equalTo(2)) } @Test fun delegateUntilTestEnd_withSpecificSession() { val newSession = sessionRule.createOpenSession() var counter = 0 newSession.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) sessionRule.session.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitForPageStop() assertThat("Callback count should be correct", counter, equalTo(1)) } @Test fun delegateUntilTestEnd_withAllSessions() { var counter = 0 sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitForPageStop() assertThat("Callback count should be correct", counter, equalTo(1)) } @Test fun delegateDuringNextWait_hasPrecedenceWithSpecificSession() { val newSession = sessionRule.createOpenSession() var counter = 0 newSession.delegateDuringNextWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) newSession.delegateUntilTestEnd(object : Callbacks.ProgressDelegate { @AssertCalled(false) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStops(2) assertThat("Callback count should be correct", counter, equalTo(1)) } @Test fun delegateDuringNextWait_specificSessionOverridesAll() { val newSession = sessionRule.createOpenSession() var counter = 0 newSession.delegateDuringNextWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate { @AssertCalled(count = 1) override fun onPageStop(session: GeckoSession, success: Boolean) { counter++ } }) newSession.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStops(2) assertThat("Callback count should be correct", counter, equalTo(2)) } @WithDisplay(width = 100, height = 100) @Test fun synthesizeTap() { sessionRule.session.loadTestPath(CLICK_TO_RELOAD_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.synthesizeTap(50, 50) sessionRule.session.waitForPageStop() } @Test fun evaluateJS() { sessionRule.session.loadTestPath(HELLO_HTML_PATH); sessionRule.session.waitForPageStop(); assertThat("JS string result should be correct", sessionRule.session.evaluateJS("'foo'") as String, equalTo("foo")) assertThat("JS number result should be correct", sessionRule.session.evaluateJS("1+1") as Double, equalTo(2.0)) assertThat("JS boolean result should be correct", sessionRule.session.evaluateJS("!0") as Boolean, equalTo(true)) val expected = JSONObject("{bar:42,baz:true,foo:'bar'}") val actual = sessionRule.session.evaluateJS("({foo:'bar',bar:42,baz:true})") as JSONObject for (key in expected.keys()) { assertThat("JS object result should be correct", actual.get(key), equalTo(expected.get(key))) } assertThat("JS array result should be correct", sessionRule.session.evaluateJS("[1,2,3]") as JSONArray, equalTo(JSONArray("[1,2,3]"))) assertThat("JS DOM object result should be correct", sessionRule.session.evaluateJS("document.body.tagName") as String, equalTo("BODY")) } @Test fun evaluateJS_windowObject() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() assertThat("JS DOM window result should be correct", (sessionRule.session.evaluateJS("window.location.pathname")) as String, equalTo(HELLO_HTML_PATH)) } @Test fun evaluateJS_multipleSessions() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.evaluateJS("this.foo = 42") assertThat("Variable should be set", sessionRule.session.evaluateJS("this.foo") as Double, equalTo(42.0)) val newSession = sessionRule.createOpenSession() newSession.loadTestPath(HELLO_HTML_PATH) newSession.waitForPageStop() val result = newSession.evaluateJS("this.foo") assertThat("New session should have separate JS context", result, nullValue()) } @Test fun evaluateJS_supportPromises() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() assertThat("Can get resolved promise", sessionRule.session.evaluatePromiseJS( "new Promise(resolve => resolve('foo'))").value as String, equalTo("foo")); val promise = sessionRule.session.evaluatePromiseJS( "new Promise(r => window.resolve = r)") sessionRule.session.evaluateJS("window.resolve('bar')") assertThat("Can wait for promise to resolve", promise.value as String, equalTo("bar")) } @Test(expected = RejectedPromiseException::class) fun evaluateJS_throwOnRejectedPromise() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.evaluatePromiseJS("Promise.reject('foo')").value } @Test fun evaluateJS_notBlockMainThread() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() // Test that we can still receive delegate callbacks during evaluateJS, // by calling alert(), which blocks until prompt delegate is called. assertThat("JS blocking result should be correct", sessionRule.session.evaluateJS("alert(); 'foo'") as String, equalTo("foo")) } @TimeoutMillis(1000) @Test(expected = UiThreadUtils.TimeoutException::class) fun evaluateJS_canTimeout() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.delegateUntilTestEnd(object : Callbacks.PromptDelegate { override fun onAlertPrompt(session: GeckoSession, prompt: GeckoSession.PromptDelegate.AlertPrompt): GeckoResult { // Return a GeckoResult that we will never complete, so it hangs. val res = GeckoResult() return res } }) sessionRule.session.evaluateJS("alert()") } @Test(expected = RuntimeException::class) fun evaluateJS_throwOnJSException() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.evaluateJS("throw Error()") } @Test(expected = RuntimeException::class) fun evaluateJS_throwOnSyntaxError() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.evaluateJS("<{[") } @Test(expected = RuntimeException::class) fun evaluateJS_throwOnChromeAccess() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.waitForPageStop() sessionRule.session.evaluateJS("ChromeUtils") } @Test fun getPrefs_undefinedPrefReturnsNull() { assertThat("Undefined pref should have null value", sessionRule.getPrefs("invalid.pref")[0], equalTo(JSONObject.NULL)) } @Test fun setPrefsUntilTestEnd() { sessionRule.setPrefsUntilTestEnd(mapOf( "test.pref.bool" to true, "test.pref.int" to 1, "test.pref.foo" to "foo")) var prefs = sessionRule.getPrefs( "test.pref.bool", "test.pref.int", "test.pref.foo", "test.pref.bar") assertThat("Prefs should be set", prefs[0] as Boolean, equalTo(true)) assertThat("Prefs should be set", prefs[1] as Int, equalTo(1)) assertThat("Prefs should be set", prefs[2] as String, equalTo("foo")) assertThat("Prefs should be set", prefs[3], equalTo(JSONObject.NULL)) sessionRule.setPrefsUntilTestEnd(mapOf( "test.pref.foo" to "bar", "test.pref.bar" to "baz")) prefs = sessionRule.getPrefs( "test.pref.bool", "test.pref.int", "test.pref.foo", "test.pref.bar") assertThat("New prefs should be set", prefs[0] as Boolean, equalTo(true)) assertThat("New prefs should be set", prefs[1] as Int, equalTo(1)) assertThat("New prefs should be set", prefs[2] as String, equalTo("bar")) assertThat("New prefs should be set", prefs[3] as String, equalTo("baz")) } @Test fun setPrefsDuringNextWait() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.setPrefsDuringNextWait(mapOf( "test.pref.bool" to true, "test.pref.int" to 1, "test.pref.foo" to "foo")) var prefs = sessionRule.getPrefs( "test.pref.bool", "test.pref.int", "test.pref.foo") assertThat("Prefs should be set before wait", prefs[0] as Boolean, equalTo(true)) assertThat("Prefs should be set before wait", prefs[1] as Int, equalTo(1)) assertThat("Prefs should be set before wait", prefs[2] as String, equalTo("foo")) sessionRule.session.reload() sessionRule.session.waitForPageStop() prefs = sessionRule.getPrefs( "test.pref.bool", "test.pref.int", "test.pref.foo") assertThat("Prefs should be cleared after wait", prefs[0], equalTo(JSONObject.NULL)) assertThat("Prefs should be cleared after wait", prefs[1], equalTo(JSONObject.NULL)) assertThat("Prefs should be cleared after wait", prefs[2], equalTo(JSONObject.NULL)) } @Test fun setPrefsDuringNextWait_hasPrecedence() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() sessionRule.setPrefsUntilTestEnd(mapOf( "test.pref.int" to 1, "test.pref.foo" to "foo")) sessionRule.setPrefsDuringNextWait(mapOf( "test.pref.foo" to "bar", "test.pref.bar" to "baz")) var prefs = sessionRule.getPrefs( "test.pref.int", "test.pref.foo", "test.pref.bar") assertThat("Prefs should be overridden", prefs[0] as Int, equalTo(1)) assertThat("Prefs should be overridden", prefs[1] as String, equalTo("bar")) assertThat("Prefs should be overridden", prefs[2] as String, equalTo("baz")) sessionRule.session.reload() sessionRule.session.waitForPageStop() prefs = sessionRule.getPrefs( "test.pref.int", "test.pref.foo", "test.pref.bar") assertThat("Overriden prefs should be restored", prefs[0] as Int, equalTo(1)) assertThat("Overriden prefs should be restored", prefs[1] as String, equalTo("foo")) assertThat("Overriden prefs should be restored", prefs[2], equalTo(JSONObject.NULL)) } @Test fun waitForJS() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() assertThat("waitForJS should return correct result", sessionRule.session.waitForJS("alert(), 'foo'") as String, equalTo("foo")) sessionRule.session.forCallbacksDuringWait(object : Callbacks.PromptDelegate { @AssertCalled(count = 1) override fun onAlertPrompt(session: GeckoSession, prompt: GeckoSession.PromptDelegate.AlertPrompt): GeckoResult? { return null; } }) } @Test fun waitForJS_resolvePromise() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() assertThat("waitForJS should wait for promises", sessionRule.session.waitForJS("Promise.resolve('foo')") as String, equalTo("foo")) } @Test fun waitForJS_delegateDuringWait() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var count = 0 sessionRule.session.delegateDuringNextWait(object : Callbacks.PromptDelegate { override fun onAlertPrompt(session: GeckoSession, prompt: GeckoSession.PromptDelegate.AlertPrompt): GeckoResult { count++ return GeckoResult.fromValue(prompt.dismiss()) } }) sessionRule.session.waitForJS("alert()") sessionRule.session.waitForJS("alert()") // The delegate set through delegateDuringNextWait // should have been cleared after the first wait. assertThat("Delegate should only run once", count, equalTo(1)) } private interface TestDelegate { fun onDelegate(foo: String, bar: String): Int } @Test fun addExternalDelegateUntilTestEnd() { lateinit var delegate: TestDelegate sessionRule.addExternalDelegateUntilTestEnd( TestDelegate::class, { newDelegate -> delegate = newDelegate }, { }, object : TestDelegate { @AssertCalled(count = 1) override fun onDelegate(foo: String, bar: String): Int { assertThat("First argument should be correct", foo, equalTo("foo")) assertThat("Second argument should be correct", bar, equalTo("bar")) return 42 } }) assertThat("Delegate should be registered", delegate, notNullValue()) assertThat("Delegate return value should be correct", delegate.onDelegate("foo", "bar"), equalTo(42)) sessionRule.performTestEndCheck() } @Test(expected = AssertionError::class) fun addExternalDelegateUntilTestEnd_throwOnNotCalled() { sessionRule.addExternalDelegateUntilTestEnd(TestDelegate::class, { }, { }, object : TestDelegate { @AssertCalled(count = 1) override fun onDelegate(foo: String, bar: String): Int { return 42 } }) sessionRule.performTestEndCheck() } @Test fun addExternalDelegateDuringNextWait() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var delegate: Runnable? = null sessionRule.addExternalDelegateDuringNextWait(Runnable::class, { newDelegate -> delegate = newDelegate }, { delegate = null }, Runnable { }) assertThat("Delegate should be registered", delegate, notNullValue()) delegate?.run() mainSession.reload() mainSession.waitForPageStop() mainSession.forCallbacksDuringWait(Runnable @AssertCalled(count = 1) {}) assertThat("Delegate should be unregistered after wait", delegate, nullValue()) } @Test fun addExternalDelegateDuringNextWait_hasPrecedence() { sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.waitForPageStop() var delegate: TestDelegate? = null val register = { newDelegate: TestDelegate -> delegate = newDelegate } val unregister = { _: TestDelegate -> delegate = null } sessionRule.addExternalDelegateDuringNextWait(TestDelegate::class, register, unregister, object : TestDelegate { @AssertCalled(count = 1) override fun onDelegate(foo: String, bar: String): Int { return 24 } }) sessionRule.addExternalDelegateUntilTestEnd(TestDelegate::class, register, unregister, object : TestDelegate { @AssertCalled(count = 1) override fun onDelegate(foo: String, bar: String): Int { return 42 } }) assertThat("Wait delegate should be registered", delegate, notNullValue()) assertThat("Wait delegate return value should be correct", delegate?.onDelegate("", ""), equalTo(24)) mainSession.reload() mainSession.waitForPageStop() assertThat("Test delegate should still be registered", delegate, notNullValue()) assertThat("Test delegate return value should be correct", delegate?.onDelegate("", ""), equalTo(42)) sessionRule.performTestEndCheck() } @IgnoreCrash @Test fun contentCrashIgnored() { assumeThat(sessionRule.env.isMultiprocess, equalTo(true)) mainSession.loadUri(CONTENT_CRASH_URL) mainSession.waitUntilCalled(object : Callbacks.ContentDelegate { @AssertCalled(count = 1) override fun onCrash(session: GeckoSession) = Unit }) } @Test(expected = ChildCrashedException::class) fun contentCrashFails() { assumeThat(sessionRule.env.isMultiprocess, equalTo(true)) assumeThat(sessionRule.env.shouldShutdownOnCrash(), equalTo(false)) sessionRule.session.loadUri(CONTENT_CRASH_URL) sessionRule.waitForPageStop() } @Test fun waitForResult() { val handler = Handler(Looper.getMainLooper()) val result = object : GeckoResult() { init { handler.postDelayed({ complete(42) }, 100) } } val value = sessionRule.waitForResult(result) assertThat("Value should match", value, equalTo(42)) } @Test(expected = IllegalStateException::class) fun waitForResultExceptionally() { val handler = Handler(Looper.getMainLooper()) val result = object : GeckoResult() { init { handler.postDelayed({ completeExceptionally(IllegalStateException("boom")) }, 100) } } sessionRule.waitForResult(result) } }