All Downloads are FREE. Search and download functionalities are using the official Maven repository.

teststate.domzipper.selenium.DomZipperSeleniumF.scala Maven / Gradle / Ivy

The newest version!
package teststate.domzipper.selenium

import org.openqa.selenium.{By, WebDriver, WebElement}
import scala.jdk.CollectionConverters._
import teststate.domzipper.DomZipper.{CssSelResult, DomCollection, Layer}
import teststate.domzipper.ErrorHandler.ErrorHandlerOptionOps
import teststate.domzipper._
import teststate.selenium.util.SeleniumExt._

object DomZipperSeleniumF {

  // The Function0 part here means that DomZipperSelenium has the same types as FastDomZipperSelenium.
  // This means one can switch their types from one to the other without having to change usage.
  type Dom = () => WebElement

  type DomCollection[F[_], C[_], A] = DomZipper.DomCollection[DomZipperSeleniumF, F, C, Dom, A]

  type CssSelEngine = DomZipper.CssSelEngine[Dom, Dom]

  private implicit val cssSelSelenium: CssSelEngine =
    DomZipper.CssSelEngine((css, parent) => parent().findElements(By.cssSelector(css)).asScala.iterator.map(() => _).toVector)

  private val rootDomFn: DomZipperBase.Layers[Dom] => Dom =
    _.latest.dom

  final class Constructors[F[_]](implicit F: ErrorHandler[F]) {

    def apply(name: String, webElement: WebElement)(implicit scrub: HtmlScrub, driver: WebDriver): DomZipperSeleniumF[F, Dom] =
      new DomZipperSeleniumF(DomZipperBase.Layers init Layer(name, "", () => webElement), rootDomFn)

    def apply(webElement: WebElement)(implicit scrub: HtmlScrub, driver: WebDriver): DomZipperSeleniumF[F, Dom] =
      apply("", webElement)

    def apply(name: String, webElement: WebElement, driver: WebDriver)(implicit scrub: HtmlScrub): DomZipperSeleniumF[F, Dom] =
      apply(name, webElement)(scrub, driver)

    def apply(webElement: WebElement, driver: WebDriver)(implicit scrub: HtmlScrub): DomZipperSeleniumF[F, Dom] =
      apply(webElement)(scrub, driver)

    def tag(tag: String, driver: WebDriver)(implicit scrub: HtmlScrub): DomZipperSeleniumF[F, Dom] =
      apply(tag, driver.findElement(By.tagName(tag)))(scrub, driver)

    def html(driver: WebDriver)(implicit scrub: HtmlScrub): DomZipperSeleniumF[F, Dom] =
      tag("html", driver)

    def body(driver: WebDriver)(implicit scrub: HtmlScrub): DomZipperSeleniumF[F, Dom] =
      tag("body", driver)

    def failBy[G[_]: ErrorHandler]: Constructors[G]   = new Constructors
    def failToOption: Constructors[Option           ] = failBy(ErrorHandler.ReturnOption)
    def failToEither: Constructors[Either[String, *]] = failBy(ErrorHandler.ReturnEither)

    type DomCollection [      C[_], A] = DomZipperSeleniumF.DomCollection[F, C, A]
    type DomCollectionF[G[_], C[_], A] = DomZipperSeleniumF.DomCollection[G, C, A]
  }
}

import DomZipperSeleniumF.Dom

final class DomZipperSeleniumF[F[_], A](override protected val layers: DomZipperBase.Layers[Dom],
                                        override protected val peek: DomZipperBase.Layers[Dom] => A
                                      )(implicit
                                        override protected val $: DomZipperSeleniumF.CssSelEngine,
                                        override protected[domzipper] val htmlScrub: HtmlScrub,
                                        override protected val F: ErrorHandler[F],
                                        driver: WebDriver
                                      ) extends DomZipperBase.WithStore[F, Dom, A, DomZipperSeleniumF] {

  override protected def newStore[B](pos: Pos, peek: Peek[B]): DomZipperSeleniumF[F, B] =
    new DomZipperSeleniumF(pos, peek)

  override def isCapable(c: DomZipper.Capability) = c match {
    case DomZipper.Capability.RadioButtonChecked => true
  }

  override def unmap =
    new DomZipperSeleniumF(layers, DomZipperSeleniumF.rootDomFn)

  override protected def self = this

  override protected def copySelf[G[_]](h: HtmlScrub, g: ErrorHandler[G]) =
    new DomZipperSeleniumF(layers, peek)($, h, g, driver)

  override protected def _parent: F[Dom] =
    F.attempt(() => dom().parent()(driver))

  override protected def _outerHTML: String =
    getAttribute("outerHTML").getOrElse("null")

  override protected def _innerHTML: String =
    getAttribute("innerHTML").getOrElse("null")

  private def newDomCollection[C[_]](desc: String, result: CssSelResult[Dom], C: DomCollection.Container[F, C]): DomCollection[DomZipperSeleniumF, F, C, Dom, A] =
    DomCollection[DomZipperSeleniumF, F, C, Dom, Dom, A](desc, enrichErr, result, C)(addLayer)

  override protected def collect[C[_]](sel: String, C: DomCollection.Container[F, C]): DomCollection[DomZipperSeleniumF, F, C, Dom, A] =
    newDomCollection(sel, runCssQuery(sel), C)

  override protected def collectChildren[C[_]](desc: String, C: DomCollection.Container[F, C]): DomCollection[DomZipperSeleniumF, F, C, Dom, A] =
    newDomCollection(desc, dom().children().map(() => _), C)

  override protected def collectChildren[C[_]](desc: String, sel: String, C: DomCollection.Container[F, C]): DomCollection[DomZipperSeleniumF, F, C, Dom, A] = {
    // WebElement implements hashCode and equals sensibly
    val all: Set[WebElement] = runCssQuery(sel).iterator.map(_()).toSet
    val children = dom().children().iterator.filter(all.contains).map(() => _).toVector
    newDomCollection(desc, children, C)
  }

  override def matches(css: String): F[Boolean] = {
    val all = driver.findElements(By.cssSelector(css)).asScala
    val dom = this.dom()
    F pass all.contains(dom) // WebElement implements hashCode and equals sensibly
  }

  override def getAttribute(name: String): Option[String] =
    Option(dom().getAttribute(name))

  override def tagName: String =
    dom().getTagName()

  override def innerText: String =
    dom().getText()

  override def checked: F[Boolean] =
    F pass dom().isSelected()

  override def classes: Set[String] =
    dom().classes()

  override def value: F[String] =
    getAttribute("value") orFail s".value failed on <${dom().getTagName}>."
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy