Skip to content

Commit

Permalink
Ensure all methods on Browser and Page are delegated to by BindingUpd…
Browse files Browse the repository at this point in the history
…ater to match what happens in base test classes.

Fixes geb/issues#601.
  • Loading branch information
erdi committed Jan 1, 2020
1 parent 86f28b5 commit 3829fdb
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
4 changes: 4 additions & 0 deletions doc/manual/src/docs/asciidoc/140-project.adoc
Expand Up @@ -94,6 +94,10 @@ This page lists the high level changes between versions of Geb.
* Add support to provide more information for UnexpectedPageException. [issue:596[]]
* Add integration with LambdaTest. [issue:603[]]

==== Fixes

* `BindingUpdater` is not forwarding methods from `geb.textmatching.TextMatchingSupport` onto the `Browser` instance. [issue:601[]]

==== Improvements

* Improve integration between cloud browser gradle plugins and driver factories. [issue:579[]]
Expand Down
41 changes: 35 additions & 6 deletions module/geb-core/src/main/groovy/geb/binding/BindingUpdater.groovy
Expand Up @@ -24,11 +24,34 @@ import geb.PageEventListenerSupport
class BindingUpdater {

static public final FORWARDED_BROWSER_METHODS = [
"go", "to", "via", "at",
"waitFor",
"getPage", "getDriver", "getAugmentedDriver", "getNavigatorFactory", "getConfig", "getSessionStorage", "getLocalStorage", "getBaseUrl", "getCurrentUrl", "getJs",
"getAvailableWindows", "getCurrentWindow", "getReportGroupDir",
"setDriver", "setBaseUrl",
"go", "to", "via",
"at", "isAt", "verifyAtImplicitly", "checkIfAtAnUnexpectedPage", "createPage",
"pause",
"withWindow", "withNewWindow",
"report", "reportGroup", "cleanReportGroupDir",
"registerPageChangeListener", "removePageChangeListener",
"clearCookies", "clearCookiesQuietly", "clearWebStorage",
"close", "quit"
].asImmutable()

static public final FORWARDED_PAGE_METHODS = [
"init",
/$/, "find",
"module",
"contains", "iContains", "notContains", "iNotContains", "endsWith", "iEndsWith", "notEndsWith", "iNotEndsWith", "containsWord", "iContainsWord", "notContainsWord", "iNotContainsWord",
"startsWith", "iStartsWith", "notStartsWith", "iNotStartsWith",
"withFrame",
"getOwner", "getPageFragment", "getRootContainer", "getContentNames", "getShouldVerifyAtImplicitly", "getAtVerificationResult", "getTitle", "getContentPath", "getContent", "getPageUrl",
"getBrowser", "getNavigator",
"onLoad", "onUnload",
"verifyAt", "verifyAtSafely",
"waitFor", "refreshWaitFor",
"focused", "interact", "convertToPath",
"withAlert", "withNoAlert", "withConfirm", "withNoConfirm",
"download", "downloadStream", "downloadText", "downloadBytes", "downloadContent",
"report", "reportGroup", "cleanReportGroupDir"
"download", "downloadStream", "downloadText", "downloadBytes", "downloadContent"
].asImmutable()

final Browser browser
Expand All @@ -50,6 +73,7 @@ class BindingUpdater {
BindingUpdater initialize() {
binding.browser = browser
binding.js = browser.js
binding.config = browser.config

FORWARDED_BROWSER_METHODS.each {
binding.setVariable(it, new InvocationForwarding(it, browser))
Expand All @@ -70,6 +94,7 @@ class BindingUpdater {

binding.variables.remove('browser')
binding.variables.remove('js')
binding.variables.remove('config')

FORWARDED_BROWSER_METHODS.each {
binding.variables.remove(it)
Expand All @@ -82,12 +107,16 @@ class BindingUpdater {
@Override
void pageWillChange(Browser browser, Page oldPage, Page newPage) {
binding.setVariable("page", newPage)
binding.setVariable("\$", new InvocationForwarding("\$", newPage))
FORWARDED_PAGE_METHODS.each {
binding.setVariable(it, new InvocationForwarding(it, newPage))
}
}

void clearBinding() {
binding.variables.remove("page")
binding.variables.remove("\$")
FORWARDED_PAGE_METHODS.each {
binding.variables.remove(it)
}
}
}

Expand Down
Expand Up @@ -15,6 +15,8 @@
*/
package geb.binding

import geb.Browser
import geb.Initializable
import geb.Page
import geb.test.GebSpecWithCallbackServer

Expand Down Expand Up @@ -108,6 +110,50 @@ class BindingUpdaterSpec extends GebSpecWithCallbackServer {
thrown MissingMethodException
}

def "all browser methods are delegated to"() {
given:
updater.initialize()

when:
def notDelegatedMethods = findPublicInstanceNonInternalMethodNames(Browser) - binding.variables.keySet()

then:
!notDelegatedMethods
}

def "all page methods are delegated to"() {
given:
updater.initialize()

when:
def notDelegatedMethods = findPublicInstanceNonInternalMethodNames(Page) - findPublicInstanceNonInternalMethodNames(Browser) - binding.variables.keySet()

then:
!notDelegatedMethods
}

def "only existing browser methods are delegated to"() {
when:
def extraDelegatedMethods = BindingUpdater.FORWARDED_BROWSER_METHODS - findPublicInstanceNonInternalMethodNames(Browser)

then:
!extraDelegatedMethods
}

def "only existing page methods are delegated to"() {
when:
def extraDelegatedMethods = BindingUpdater.FORWARDED_PAGE_METHODS - findPublicInstanceNonInternalMethodNames(Page)

then:
!extraDelegatedMethods
}

private Set<String> findPublicInstanceNonInternalMethodNames(Class clazz) {
def ignoredMethods = Object.methods + GroovyObject.methods + Initializable.methods
def internalMethodNames = ignoredMethods*.name + ["methodMissing", "propertyMissing"]
def publicInstanceMethods = clazz.metaClass.methods.findAll { it.public && !it.static }
publicInstanceMethods*.name.toSet() - internalMethodNames
}
}

class BindingUpdaterSpecPage1 extends Page {
Expand Down

0 comments on commit 3829fdb

Please sign in to comment.