gwen.web.eval.binding.LocatorBindingResolver.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gwen-web Show documentation
Show all versions of gwen-web Show documentation
Web automation engine for Gwen
/*
* Copyright 2014-2021 Branko Juric, Brady Wood
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gwen.web.eval.binding
import gwen.web.eval.WebBrowser
import gwen.web.eval.WebContext
import gwen.web.eval.WebErrors._
import gwen.web.eval.WebSettings
import com.typesafe.scalalogging.LazyLogging
import org.openqa.selenium.WebElement
import scala.concurrent.duration.Duration
import scala.util.Try
import scala.util.chaining._
import java.util.concurrent.TimeUnit
import org.xml.sax.Locator
/**
* Resolves locator bindings to actual web elements.
*/
class LocatorBindingResolver(ctx: WebContext) extends LazyLogging {
/**
* Finds and resolves a locator binding to a single element.
*
* @param name the binding name
* @return a web element
*/
def resolve(name: String): WebElement = getBinding(name).get.resolve()
/**
* Finds and resolves a locator binding to a zero or more elements.
*
* @param name the binding name
* @return zero or more web elements
*/
def resolveAll(name: String): List[WebElement] = getBinding(name).get.resolveAll()
/**
* Gets a locator binding.
*
* @param name the name of the web element
* @param optional true to return None if not found; false to throw error
*/
def getBinding(name: String, optional: Boolean = false): Option[LocatorBinding] = {
ctx.topScope.getObject(name) match {
case None =>
val locatorKey = LocatorKey.baseKey(name)
ctx.scopes.getOpt(locatorKey) match {
case Some(boundValue) =>
val selectors = boundValue.split(",") flatMap { boundValue =>
val selectorType = Try(SelectorType.parse(boundValue)) getOrElse {
locatorBindingError(s"Unsupported selector type defined for: $name")
}
if (selectorType == SelectorType.xpath && WebSettings.`gwen.target.browser` == WebBrowser.ie ) {
locatorBindingError("IE does not support XPath selectors")
}
val selectorKey = ctx.interpolate(LocatorKey.selectorKey(name, selectorType))
ctx.scopes.getOpt(selectorKey) match {
case Some(expression) =>
val selector = ctx.interpolate(expression)
val rKeys = RelativeSelectorType.values map { rSelector =>
LocatorKey.relativeKey(name, selectorType, rSelector)
}
val rKeyAndElement: Option[(String, String)] = (rKeys flatMap { rKey =>
ctx.scopes.getOpt(ctx.interpolate(rKey)) map { rElement =>
(rKey, rElement)
}
}).headOption
if (ctx.options.dryRun) {
rKeyAndElement.foreach((k, e) => getBinding(e, optional))
}
val relative = rKeyAndElement map { (rKey, rElement) =>
val rSelector = RelativeSelectorType.valueOf(rKey.substring(rKey.lastIndexOf("/") + 1))
val rBinding = getBinding(rElement, false).get
val rKeyWithinPixels = LocatorKey.relativeKeyWithinPixels(name, selectorType, rSelector)
val withinPixels = ctx.scopes.getOpt(ctx.interpolate(rKeyWithinPixels)).map(_.toInt)
(rSelector, rBinding, withinPixels)
}
val timeout = ctx.scopes.getOpt(ctx.interpolate(LocatorKey.timeoutSecsKey(name, selectorType))).map { timeoutSecs =>
Duration.create(timeoutSecs.toLong, TimeUnit.SECONDS)
}
val index = ctx.scopes.getOpt(ctx.interpolate(LocatorKey.indexKey(name, selectorType))).map(_.toInt)
Some(Selector(selectorType, selector, relative, timeout, index))
case None =>
if (optional) None else locatorBindingError(s"Undefined selector for: $name")
}
}
if (selectors.nonEmpty) {
val binding = new LocatorBinding(name, selectors.toList, ctx)
if (WebSettings.`gwen.web.implicit.js.locators`) {
Some(binding.jsEquivalent)
} else {
Some(binding)
}
}
else None
case None => if (optional) None else locatorBindingError(s"Undefined selector for: $name")
}
case Some(x) if x.isInstanceOf[WebElement] || ctx.options.dryRun => Some(LocatorBinding(name, SelectorType.cache, name, None, None, None, ctx))
case _ => None
}
} tap { binding =>
binding foreach { b => logger.debug(s"getLocatorBinding($name,$optional)='$b'") }
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy