From 660429b23185c3a00b133e58e5ad71b3f704c3b6 Mon Sep 17 00:00:00 2001 From: starzu Date: Thu, 28 Jan 2016 12:08:57 +0100 Subject: [PATCH] jQuery wrapper tests - this closes #2 --- .travis.yml | 2 +- build.sbt | 11 +- .../io/udash/wrappers/jquery/JQuery.scala | 93 +++---- .../udash/wrappers/jquery/JQueryStatic.scala | 6 +- .../jquery_test/DomManipulationTest.scala | 241 ++++++++++++++++++ .../jquery_test/EventsHandlingTest.scala | 73 ++++++ .../jquery_test/MiscellaneousTest.scala | 48 ++++ .../wrappers/jquery_test/SelectorsTest.scala | 57 +++++ .../wrappers/jquery_test/TraversingTest.scala | 169 ++++++++++++ 9 files changed, 643 insertions(+), 57 deletions(-) create mode 100644 src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala create mode 100644 src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala create mode 100644 src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala create mode 100644 src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala create mode 100644 src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala diff --git a/.travis.yml b/.travis.yml index 25cad24..d8e2485 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ scala: - 2.11.7 script: - - sbt ++$TRAVIS_SCALA_VERSION compile \ No newline at end of file + - sbt ++$TRAVIS_SCALA_VERSION test \ No newline at end of file diff --git a/build.sbt b/build.sbt index 33ddd17..35f3888 100644 --- a/build.sbt +++ b/build.sbt @@ -15,11 +15,18 @@ scalacOptions in ThisBuild ++= Seq( "-Xlint:_,-missing-interpolator,-adapted-args" ) -libraryDependencies += - "org.scala-js" %%% "scalajs-dom" % "0.8.2" +libraryDependencies ++= Seq( + "org.scala-js" %%% "scalajs-dom" % "0.8.2", + "org.scalatest" %%% "scalatest" % "3.0.0-M15" % Test, + "com.lihaoyi" %%% "scalatags" % "0.5.4" % Test +) jsDependencies += "org.webjars" % "jquery" % "2.2.0" / "2.2.0/jquery.js" minified "2.2.0/jquery.min.js" +requiresDOM in Test := true +persistLauncher in Test := false +scalaJSUseRhino in Test := false + lazy val root = project.in(file(".")) .enablePlugins(ScalaJSPlugin) \ No newline at end of file diff --git a/src/main/scala/io/udash/wrappers/jquery/JQuery.scala b/src/main/scala/io/udash/wrappers/jquery/JQuery.scala index 453c00b..fb1a94e 100644 --- a/src/main/scala/io/udash/wrappers/jquery/JQuery.scala +++ b/src/main/scala/io/udash/wrappers/jquery/JQuery.scala @@ -54,11 +54,11 @@ trait JQuery extends js.Object { /** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */ - private[jquery] def animate(properties: js.Dictionary[js.Any], duration: Int, easing: String, callback: js.ThisFunction0[Element, Any]): JQuery = js.native + private[jquery] def animate(properties: js.Dictionary[Any], duration: Int, easing: String, callback: js.ThisFunction0[Element, Any]): JQuery = js.native /** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */ - private[jquery] def animate(properties: js.Dictionary[js.Any], options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def animate(properties: js.Dictionary[Any], options: js.Dictionary[Any]): JQuery = js.native /** Insert content, specified by the parameter, to the end of each element in the set of matched elements.
* See: jQuery Docs */ @@ -130,20 +130,12 @@ trait JQuery extends js.Object { /** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
* See: jQuery Docs */ - def closest(selector: String): JQuery = js.native + def closest(selector: String | Element | JQuery): JQuery = js.native /** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
* See: jQuery Docs */ def closest(selector: String, context: Element): JQuery = js.native - /** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
- * See: jQuery Docs */ - def closest(selection: JQuery): JQuery = js.native - - /** For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
- * See: jQuery Docs */ - def closest(element: Element): JQuery = js.native - /** Get the children of each element in the set of matched elements, including text and comment nodes.
* See: jQuery Docs */ def contents(): JQuery = js.native @@ -171,11 +163,11 @@ trait JQuery extends js.Object { /** Store arbitrary data associated with the matched elements.
* See: jQuery Docs */ - def data(key: String, value: js.Any): JQuery = js.native + def data(key: String, value: Any): JQuery = js.native /** Store arbitrary data associated with the matched elements.
* See: jQuery Docs */ - private[jquery] def data(obj: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def data(obj: js.Dictionary[Any]): JQuery = js.native /** Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute.
* See: jQuery Docs */ @@ -183,7 +175,7 @@ trait JQuery extends js.Object { /** Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute.
* See: jQuery Docs */ - private[jquery] def data(key: String): UndefOr[js.Any] = js.native + private[jquery] def data(key: String): UndefOr[Any] = js.native /** Trigger dblclick event on an element.
* See: jQuery Docs */ @@ -234,7 +226,7 @@ trait JQuery extends js.Object { /** Display the matched elements by fading them to opaque.
* See: jQuery Docs */ - private[jquery] def fadeIn(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def fadeIn(options: js.Dictionary[Any]): JQuery = js.native /** Hide the matched elements by fading them to transparent.
* See: jQuery Docs */ @@ -246,7 +238,7 @@ trait JQuery extends js.Object { /** Hide the matched elements by fading them to transparent.
* See: jQuery Docs */ - private[jquery] def fadeOut(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def fadeOut(options: js.Dictionary[Any]): JQuery = js.native /** Adjust the opacity of the matched elements.
* See: jQuery Docs */ @@ -274,7 +266,7 @@ trait JQuery extends js.Object { /** Display or hide the matched elements by animating their opacity.
* See: jQuery Docs */ - private[jquery] def fadeToggle(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def fadeToggle(options: js.Dictionary[Any]): JQuery = js.native /** Reduce the set of matched elements to those that match the selector or pass the function's test.
* See: jQuery Docs */ @@ -352,7 +344,7 @@ trait JQuery extends js.Object { /** Hide the matched elements.
* See: jQuery Docs */ - private[jquery] def hide(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def hide(options: js.Dictionary[Any]): JQuery = js.native /** Get the HTML contents of the first element in the set of matched elements.
* See: jQuery Docs */ @@ -366,7 +358,7 @@ trait JQuery extends js.Object { * See: jQuery Docs */ def index(): Int = js.native - /** Search for a given element from among the matched elements.
+ /** Search for a given element from among the matched elements. If the element is not found, this method will return -1.
* See: jQuery Docs */ def index(selector: Selector | Element | JQuery): Int = js.native @@ -649,15 +641,15 @@ trait JQuery extends js.Object { /** Set one or more properties for the set of matched elements.
* See: jQuery Docs */ - private[jquery] def prop(properties: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def prop(properties: js.Dictionary[Any]): JQuery = js.native /** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */ - private[jquery] def pushStack(elements: js.Array[js.Any]): JQuery = js.native + private[jquery] def pushStack(elements: js.Array[Any]): JQuery = js.native /** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */ - private[jquery] def pushStack(elements: js.Array[js.Any], name: String, arguments: js.Array[js.Any]): JQuery = js.native + private[jquery] def pushStack(elements: js.Array[Any], name: String, arguments: js.Array[Any]): JQuery = js.native /** Specify a function to execute when the DOM is fully loaded.
* See: jQuery Docs */ @@ -745,13 +737,13 @@ trait JQuery extends js.Object { /** Display the matched elements.
* See: jQuery Docs */ - private[jquery] def show(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def show(options: js.Dictionary[Any]): JQuery = js.native /** Get the siblings of each element in the set of matched elements, optionally filtered by a selector.
* See: jQuery Docs */ def siblings(selector: String = js.native): JQuery = js.native - /** Reduce the set of matched elements to a subset specified by a range of indices.
+ /** Reduce the set of matched elements to a subset specified by a range of indices. Including `start`, without `end`.
* See: jQuery Docs */ def slice(start: Int, end: Int = js.native): JQuery = js.native @@ -765,7 +757,7 @@ trait JQuery extends js.Object { /** Display the matched elements with a sliding motion.
* See: jQuery Docs */ - private[jquery] def slideDown(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def slideDown(options: js.Dictionary[Any]): JQuery = js.native /** Display or hide the matched elements with a sliding motion.
* See: jQuery Docs */ @@ -777,7 +769,7 @@ trait JQuery extends js.Object { /** Display or hide the matched elements with a sliding motion.
* See: jQuery Docs */ - private[jquery] def slideToggle(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def slideToggle(options: js.Dictionary[Any]): JQuery = js.native /** Hide the matched elements with a sliding motion.
* See: jQuery Docs */ @@ -789,7 +781,7 @@ trait JQuery extends js.Object { /** Hide the matched elements with a sliding motion.
* See: jQuery Docs */ - private[jquery] def slideUp(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def slideUp(options: js.Dictionary[Any]): JQuery = js.native /** Stop the currently-running animation on the matched elements.
* See: jQuery Docs */ @@ -813,7 +805,7 @@ trait JQuery extends js.Object { /** Retrieve all the elements contained in the jQuery set, as an array.
* See: jQuery Docs */ - private[jquery] def toArray: js.Array[Element] = js.native + private[jquery] def toArray(): js.Array[Element] = js.native /** Display or hide the matched elements.
* See: jQuery Docs */ @@ -829,7 +821,7 @@ trait JQuery extends js.Object { /** Display or hide the matched elements.
* See: jQuery Docs */ - private[jquery] def toggle(options: js.Dictionary[js.Any]): JQuery = js.native + private[jquery] def toggle(options: js.Dictionary[Any]): JQuery = js.native /** Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the state argument.
* See: jQuery Docs */ @@ -849,7 +841,7 @@ trait JQuery extends js.Object { /** Execute all handlers and behaviors attached to the matched elements for the given event type.
* See: jQuery Docs */ - private[jquery] def trigger(event: String | JQueryEvent, extraParams: js.Dictionary[js.Any] | js.Array[js.Any]): JQuery = js.native + private[jquery] def trigger(event: String | JQueryEvent, extraParams: js.Dictionary[Any] | js.Array[Any]): JQuery = js.native /** Execute all handlers attached to an element for an event.
* See: jQuery Docs */ @@ -857,7 +849,7 @@ trait JQuery extends js.Object { /** Execute all handlers attached to an element for an event.
* See: jQuery Docs */ - private[jquery] def triggerHandler(event: String | JQueryEvent, extraParams: js.Dictionary[js.Any] | js.Array[js.Any]): JQuery = js.native + private[jquery] def triggerHandler(event: String | JQueryEvent, extraParams: js.Dictionary[Any] | js.Array[Any]): JQuery = js.native /** Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place.
* See: jQuery Docs */ @@ -866,12 +858,12 @@ trait JQuery extends js.Object { /** Get the current value of the first element in the set of matched elements.
* See: jQuery Docs */ @JSName("val") - def value(): String | Number | js.Array[js.Any] = js.native + def value(): String | Number | js.Array[Any] = js.native /** Set the value of each element in the set of matched elements.
* See: jQuery Docs */ @JSName("val") - def value(value: String | Number | js.Array[js.Any]): JQuery = js.native + def value(value: String | Number | js.Array[Any]): JQuery = js.native /** Set the value of each element in the set of matched elements.
* See: jQuery Docs */ @@ -933,8 +925,8 @@ object JQuery { done: (JQueryPromise[js.Function1[js.Any, js.Any], js.Any], Boolean) => js.Any = null, fail: (JQueryPromise[js.Function1[js.Any, js.Any], js.Any], Boolean) => js.Any = null, always: (JQueryPromise[js.Function1[js.Any, js.Any], js.Any], Boolean) => js.Any = null) { - def toJSDictionary: js.Dictionary[js.Any] = { - val r = js.Dictionary[js.Any]() + def toJSDictionary: js.Dictionary[Any] = { + val r = js.Dictionary[Any]() if (duration.isDefined) r.update("duration", duration.get) if (easing != null) r.update("easing", easing) if (queue.isDefined) r.update("queue", queue.get) @@ -972,11 +964,11 @@ object JQuery { /** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */ - def animate(properties: Map[String, js.Any], duration: Int = 400, easing: String = "swing", callback: (Element) => Any = (_) => {}): JQuery = jquery.animate(properties.toJSDictionary, duration, easing, callback) + def animate(properties: Map[String, Any], duration: Int = 400, easing: String = "swing", callback: (Element) => Any = (_) => {}): JQuery = jquery.animate(properties.toJSDictionary, duration, easing, callback) /** Perform a custom animation of a set of CSS properties.
* See: jQuery Docs */ - def animate(properties: Map[String, js.Any], options: AnimationOptions): JQuery = jquery.animate(properties.toJSDictionary, options.toJSDictionary) + def animate(properties: Map[String, Any], options: AnimationOptions): JQuery = jquery.animate(properties.toJSDictionary, options.toJSDictionary) /** Insert content, specified by the parameter, to the end of each element in the set of matched elements.
* See: jQuery Docs */ @@ -1052,7 +1044,7 @@ object JQuery { /** Store arbitrary data associated with the matched elements.
* See: jQuery Docs */ - def data(obj: Map[String, js.Any]): JQuery = jquery.data(obj.toJSDictionary) + def data(obj: Map[String, Any]): JQuery = jquery.data(obj.toJSDictionary) /** Bind an event handler to the "dblclick" JavaScript event on an element.
* See: jQuery Docs */ @@ -1339,19 +1331,18 @@ object JQuery { /** Remove an event handler.
* See: jQuery Docs */ def off(event: String, callback: JQueryCallback): JQuery = { - jquery - .toArray + jquery.toArray() .foreach( el => { if (registrations.contains(el)) { val jqueryRegs: mutable.Buffer[CallbackRegistrationRef] = registrations.get(el).get - val founded: mutable.Buffer[CallbackRegistrationRef] = jqueryRegs.filter(r => { + val found: mutable.Buffer[CallbackRegistrationRef] = jqueryRegs.filter(r => { r match { case CallbackRegistrationRef(ev, cb, _) if cb == callback && ev == event => true case _ => false } }) - founded.foreach( _.registration.unregister()) - jqueryRegs --= founded + found.foreach( _.registration.unregister()) + jqueryRegs --= found if (jqueryRegs.isEmpty) registrations.remove(el) } }) @@ -1412,15 +1403,15 @@ object JQuery { /** Set one or more properties for the set of matched elements.
* See: jQuery Docs */ - def prop(properties: Map[String, js.Any]): JQuery = jquery.prop(properties.toJSDictionary) + def prop(properties: Map[String, Any]): JQuery = jquery.prop(properties.toJSDictionary) /** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */ - def pushStack(elements: Seq[js.Any]): JQuery = jquery.pushStack(elements.toJSArray) + def pushStack(elements: Seq[Any]): JQuery = jquery.pushStack(elements.toJSArray) /** Add a collection of DOM elements onto the jQuery stack.
* See: jQuery Docs */ - def pushStack(elements: Seq[js.Any], name: String, arguments: Seq[js.Any]): JQuery = jquery.pushStack(elements.toJSArray, name, arguments.toJSArray) + def pushStack(elements: Seq[Any], name: String, arguments: Seq[Any]): JQuery = jquery.pushStack(elements.toJSArray, name, arguments.toJSArray) /** Specify a function to execute when the DOM is fully loaded.
* See: jQuery Docs */ @@ -1504,7 +1495,7 @@ object JQuery { /** Retrieve all the elements contained in the jQuery set, as an array.
* See: jQuery Docs */ - def toArray: Seq[Element] = jquery.toArray.toSeq + def toArray: Seq[Element] = jquery.toArray().toSeq /** Display or hide the matched elements.
* See: jQuery Docs */ @@ -1524,19 +1515,19 @@ object JQuery { /** Execute all handlers and behaviors attached to the matched elements for the given event type.
* See: jQuery Docs */ - def trigger(event: String | JQueryEvent, extraParams: Map[String, js.Any]): JQuery = jquery.trigger(event, extraParams.toJSDictionary) + def trigger(event: String | JQueryEvent, extraParams: Map[String, Any]): JQuery = jquery.trigger(event, extraParams.toJSDictionary) /** Execute all handlers and behaviors attached to the matched elements for the given event type.
* See: jQuery Docs */ - def trigger(event: String | JQueryEvent, extraParams: Seq[js.Any]): JQuery = jquery.trigger(event, extraParams.toJSArray) + def trigger(event: String | JQueryEvent, extraParams: Seq[Any]): JQuery = jquery.trigger(event, extraParams.toJSArray) /** Execute all handlers attached to an element for an event.
* See: jQuery Docs */ - def triggerHandler(event: String | JQueryEvent, extraParams: Map[String, js.Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSDictionary) + def triggerHandler(event: String | JQueryEvent, extraParams: Map[String, Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSDictionary) /** Execute all handlers attached to an element for an event.
* See: jQuery Docs */ - def triggerHandler(event: String | JQueryEvent, extraParams: Seq[js.Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSArray) + def triggerHandler(event: String | JQueryEvent, extraParams: Seq[Any]): JQuery = jquery.triggerHandler(event, extraParams.toJSArray) /** Set the value of each element in the set of matched elements.
* See: jQuery Docs */ diff --git a/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala b/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala index 060ec9a..be471d1 100644 --- a/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala +++ b/src/main/scala/io/udash/wrappers/jquery/JQueryStatic.scala @@ -188,7 +188,7 @@ object JQueryStatic { /** Return a collection of matched elements either found in the DOM based on passed argument(s) or created by passing an HTML string.
* See: jQuery Docs */ - def apply(elementArray: Seq[Element]): JQuery = jQueryStatic(elementArray.toJSArray) + def apply(elementArray: Element*): JQuery = jQueryStatic(elementArray.toJSArray) /** Binds a function to be executed when the DOM has finished loading.
* See: jQuery Docs */ @@ -196,8 +196,8 @@ object JQueryStatic { /** Binds a function to be executed when the DOM has finished loading.
* See: jQuery Docs */ - def apply(option: Option[Any]): JQuery = option match { - case Some(element) => jQueryStatic.apply(element.asInstanceOf[js.Any]) + def apply(option: Option[js.Any]): JQuery = option match { + case Some(element) => jQueryStatic.apply(element) case None => jQueryStatic.apply() } diff --git a/src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala new file mode 100644 index 0000000..ede038d --- /dev/null +++ b/src/test/scala/io/udash/wrappers/jquery_test/DomManipulationTest.scala @@ -0,0 +1,241 @@ +package io.udash.wrappers.jquery_test + +import org.scalatest.{Matchers, WordSpec} + +class DomManipulationTest extends WordSpec with Matchers { + import io.udash.wrappers.jquery._ + import scalatags.JsDom.all._ + + "jQuery" should { + "set text content of DOM element" in { + val text = "test 123" + val dom = div().render + + jQ(dom).text() should be("") + dom.textContent should be("") + + jQ(dom).text(text) + + jQ(dom).text() should be(text) + dom.textContent should be(text) + } + + "set content of DOM element" in { + val text = "test 123" + val dom = div().render + val content = span(ul(li(text))).render + + jQ(dom).html() should be("") + dom.textContent should be("") + + jQ(dom).html(content) + + jQ(dom).html() should be(s"") + jQ(dom).text() should be(text) + dom.textContent should be(text) + } + + "set DOM element attribute" in { + val attrName = "attr" + val attrValue = "val" + val dom = div().render + + jQ(dom).attr(attrName) should be(None) + + jQ(dom).attr(attrName, attrValue) + + jQ(dom).attr(attrName) should be(Some(attrValue)) + dom.getAttribute(attrName) should be(attrValue) + } + + "manage DOM element CSS classes" in { + val c1 = "c1" + val c2 = "c2" + val dom = div().render + + jQ(dom).addClass(c1) + jQ(dom).addClass(c2) + + dom.className.split(" ") should contain(c1) + dom.className.split(" ") should contain(c2) + + jQ(dom).removeClass(c2) + + dom.className.split(" ") should contain(c1) + dom.className.split(" ") shouldNot contain(c2) + + jQ(dom).toggleClass(c1) + jQ(dom).toggleClass(c2) + + dom.className.split(" ") shouldNot contain(c1) + dom.className.split(" ") should contain(c2) + + jQ(dom).toggleClass(c1) + jQ(dom).toggleClass(c2) + + dom.className.split(" ") should contain(c1) + dom.className.split(" ") shouldNot contain(c2) + } + + "show/hide DOM elements" in { + val dom = div( + h1("a"), + span("b") + ).render + + val h = jQ(dom).find("h1") + val s = jQ(dom).find("span") + + h.hide() + h.css("display") should be("none") + s.css("display") shouldNot be("none") + + s.hide() + h.css("display") should be("none") + s.css("display") should be("none") + + h.show() + s.show() + h.css("display") shouldNot be("none") + s.css("display") shouldNot be("none") + } + + "remove DOM elements" in { + val dom = div( + h1("a"), + span(cls :="c1")("b"), + h1("a"), + span("c"), + h1("a"), + span(cls :="c1")("d"), + h1("a"), + span("e", span("f"), "g") + ).render + + val h = jQ(dom).find("h1") + val s = jQ(dom).find("span") + val c = jQ(dom).find(".c1") + + dom.childElementCount should be(8) + dom.textContent should be("abacadaefg") + + h.remove() + + dom.childElementCount should be(4) + dom.textContent should be("bcdefg") + + c.remove() + + dom.childElementCount should be(2) + dom.textContent should be("cefg") + + s.remove() + + dom.childElementCount should be(0) + dom.textContent should be("") + } + + "remove childrens of DOM elements" in { + val dom = div( + h1("a"), + span(cls :="c1")("b"), + h1("a"), + span("c"), + h1("a"), + span(cls :="c1")("d"), + h1("a"), + span("e", span("f"), "g") + ).render + + val h = jQ(dom).find("h1") + val s = jQ(dom).find("span") + val c = jQ(dom).find(".c1") + + dom.childElementCount should be(8) + dom.textContent should be("abacadaefg") + + h.empty() + + dom.childElementCount should be(8) + dom.textContent should be("bcdefg") + + c.empty() + + dom.childElementCount should be(8) + dom.textContent should be("cefg") + + s.empty() + + dom.childElementCount should be(8) + dom.textContent should be("") + } + + "append/prepend DOM elements" in { + val dom = div( + span(), span(), span(), span() + ).render + + val s = jQ(dom).find("span") + + dom.childElementCount should be(4) + dom.textContent should be("") + + s.append("a") + + dom.childElementCount should be(4) + dom.textContent should be("aaaa") + + s.prepend("b") + + dom.childElementCount should be(4) + dom.textContent should be("babababa") + + s.filter(":nth-child(2n)").append("c") + + dom.childElementCount should be(4) + dom.textContent should be("babacbabac") + + s.filter(":nth-child(2n+1)").prepend("d") + + dom.childElementCount should be(4) + dom.textContent should be("dbabacdbabac") + } + + "append/prepend DOM element into another element" in { + val dom = div().render + + jQ(span("a").render).appendTo(dom) + + dom.childElementCount should be(1) + dom.textContent should be("a") + + jQ(span("b").render).appendTo(jQ(dom)) + + dom.childElementCount should be(2) + dom.textContent should be("ab") + + jQ(span("x").render).prependTo(jQ(dom)) + + dom.childElementCount should be(3) + dom.textContent should be("xab") + + jQ(span("y").render).prependTo(dom) + + dom.childElementCount should be(4) + dom.textContent should be("yxab") + } + + "manage input values" in { + val dom = input().render + + jQ(dom).value("abc") + jQ(dom).value() should be("abc") + dom.value should be("abc") + + jQ(dom).value("cba") + jQ(dom).value() should be("cba") + dom.value should be("cba") + } + } + +} diff --git a/src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala new file mode 100644 index 0000000..42fea1c --- /dev/null +++ b/src/test/scala/io/udash/wrappers/jquery_test/EventsHandlingTest.scala @@ -0,0 +1,73 @@ +import org.scalajs.dom.Element +import org.scalajs.dom.html.Input +import org.scalatest.{Matchers, WordSpec} + +class EventsHandlingTest extends WordSpec with Matchers { + import io.udash.wrappers.jquery._ + + import scalatags.JsDom.all._ + + class C(i: Int) + + "jQuery" should { + "handle JS events" in { + val i = jQ(input().render) + + var event: JQueryEvent = null + + val callback: (Element, JQueryEvent) => Unit = + (el: Element, ev: JQueryEvent) => + event = ev + + i.on("change", callback) + + i.trigger("change") + event shouldNot be(null) + + i.off("change", callback) + + event = null + i.trigger("change") + event should be(null) + } + + "handle JS events (inlined)" in { + val i: Input = input().render + var event: JQueryEvent = null + + val callback: (Element, JQueryEvent) => Unit = + (el: Element, ev: JQueryEvent) => + event = ev + + jQ(i).on("change", callback) + + jQ(i).trigger("change") + event shouldNot be(null) + + jQ(i).off("change", callback) + + event = null + jQ(i).trigger("change") + event should be(null) + } + + "handle JS events (one)" in { + val i: Input = input().render + var event: JQueryEvent = null + + val callback: (Element, JQueryEvent) => Unit = + (el: Element, ev: JQueryEvent) => + event = ev + + jQ(i).one("change", callback) + + jQ(i).trigger("change") + event shouldNot be(null) + + event = null + jQ(i).trigger("change") + event should be(null) + } + } + +} diff --git a/src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala new file mode 100644 index 0000000..c2630c7 --- /dev/null +++ b/src/test/scala/io/udash/wrappers/jquery_test/MiscellaneousTest.scala @@ -0,0 +1,48 @@ +package io.udash.wrappers.jquery_test + +import org.scalatest.{Matchers, WordSpec} + +class MiscellaneousTest extends WordSpec with Matchers { + import io.udash.wrappers.jquery._ + + import scalatags.JsDom.all._ + + class C(i: Int) + + "jQuery" should { + "keep data in DOM elements" in { + val c = new C(5) + val f = (i: Int) => i + 1 + + val dom = div().render + val selection = jQ(dom) + selection.data(Map("key" -> "value", "int" -> 1, "cls" -> c, "func" -> f)) + + selection.data().key should be("value") + selection.data("key") should be(Some("value")) + selection.data().int should be(1) + selection.data("int") should be(Some(1)) + selection.data().cls should be(c) + selection.data("cls") should be(Some(c)) + selection.data().func should be(f) + selection.data("func") should be(Some(f)) + + selection.data("nothing") should be(None) + } + + "find element index in selection" in { + val el1 = span.render + val el2 = span(id := "id").render + val el3 = h1.render + val el4 = h1(cls := "lolzy").render + val dom = div(el1, el2, el3).render + + val selection = jQ(dom).children() + selection.index(el1) should be(0) + selection.index(el2) should be(1) + selection.index(jQ(el3)) should be(2) + selection.index(el4) should be(-1) + } + } + +} diff --git a/src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala new file mode 100644 index 0000000..ede080c --- /dev/null +++ b/src/test/scala/io/udash/wrappers/jquery_test/SelectorsTest.scala @@ -0,0 +1,57 @@ +package io.udash.wrappers.jquery_test + +import org.scalatest.{Matchers, WordSpec} + +class SelectorsTest extends WordSpec with Matchers { + import io.udash.wrappers.jquery._ + import scalatags.JsDom.all._ + + "jQuery" should { + "select elements by class" in { + val el1 = span(cls := "c1").render + val el2 = span(cls := "c1 c2").render + val el3 = h1(cls := "c3").render + val dom = div(el1, el2, el3).render + + jQ(dom).children(".c1").each((el, _, _) => jQ(el).attr("a1", 1)) + jQ(dom).children(".c2").each((el, _, _) => jQ(el).attr("a2", 1)) + jQ(dom).children(".c3").each((el, _, _) => jQ(el).attr("a3", 1)) + + jQ(el1).attr("a1") should be(Some("1")) + jQ(el1).attr("a2") should be(None) + jQ(el1).attr("a3") should be(None) + + jQ(el2).attr("a1") should be(Some("1")) + jQ(el2).attr("a2") should be(Some("1")) + jQ(el2).attr("a3") should be(None) + + jQ(el3).attr("a1") should be(None) + jQ(el3).attr("a2") should be(None) + jQ(el3).attr("a3") should be(Some("1")) + } + + "select elements by id" in { + val el1 = span(id := "el1").render + val el2 = span(id := "el2").render + val el3 = h1(id := "el3").render + val dom = div(el1, el2, el3).render + + jQ(dom).children("#el1").each((el, _, _) => jQ(el).attr("a1", 1)) + jQ(dom).children("#el2").each((el, _, _) => jQ(el).attr("a2", 1)) + jQ(dom).children("#el3").each((el, _, _) => jQ(el).attr("a3", 1)) + + jQ(el1).attr("a1") should be(Some("1")) + jQ(el1).attr("a2") should be(None) + jQ(el1).attr("a3") should be(None) + + jQ(el2).attr("a1") should be(None) + jQ(el2).attr("a2") should be(Some("1")) + jQ(el2).attr("a3") should be(None) + + jQ(el3).attr("a1") should be(None) + jQ(el3).attr("a2") should be(None) + jQ(el3).attr("a3") should be(Some("1")) + } + } + +} diff --git a/src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala b/src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala new file mode 100644 index 0000000..c9b1860 --- /dev/null +++ b/src/test/scala/io/udash/wrappers/jquery_test/TraversingTest.scala @@ -0,0 +1,169 @@ +package io.udash.wrappers.jquery_test + +import org.scalatest.{Matchers, WordSpec} + +class TraversingTest extends WordSpec with Matchers { + import io.udash.wrappers.jquery._ + + import scalatags.JsDom.all._ + + "jQuery" should { + "add elements to selection" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + + val j1 = jQ(el1) + j1.each((el, _, _) => jQ(el).attr("a1", 1)) + val j2 = j1.add(el2) + j2.each((el, _, _) => jQ(el).attr("a2", 1)) + val j3 = j2.add(el3) + j3.each((el, _, _) => jQ(el).attr("a3", 1)) + + jQ(el1).attr("a1") should be(Some("1")) + jQ(el1).attr("a2") should be(Some("1")) + jQ(el1).attr("a3") should be(Some("1")) + + jQ(el2).attr("a1") should be(None) + jQ(el2).attr("a2") should be(Some("1")) + jQ(el2).attr("a3") should be(Some("1")) + + jQ(el3).attr("a1") should be(None) + jQ(el3).attr("a2") should be(None) + jQ(el3).attr("a3") should be(Some("1")) + } + + "iterate over a selection" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + + val selection = jQ(el1, el2, el3) + selection.each((el, _, _) => jQ(el).attr("a", 1)) + + jQ(el1).attr("a") should be(Some("1")) + jQ(el2).attr("a") should be(Some("1")) + jQ(el3).attr("a") should be(Some("1")) + } + + "filter a selection" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + + val selection = jQ(el1, el2, el3) + selection.filter("h1").each((el, _, _) => jQ(el).attr("a", 1)) + + jQ(el1).attr("a") should be(None) + jQ(el2).attr("a") should be(None) + jQ(el3).attr("a") should be(Some("1")) + } + + "find elements parent" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + val p1 = div(el1).render + val p2 = div(el2).render + val p3 = div(el3).render + + val selection = jQ(el1, el2, el3) + selection.parent().filter("div").length should be(3) + } + + "find descendants" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + val p1 = div(el1).render + val p2 = div(el2).render + val p3 = div(el3).render + val p = div(p1, p2, p3).render + + jQ(p).find("span").length should be(2) + jQ(p).find("div").length should be(3) + jQ(p).find("h1").length should be(1) + } + + "find elements parent (should be unique)" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + val d = div(el1, el2, el3).render + + val selection = jQ(el1, el2, el3) + selection.parent().filter("div").length should be(1) + } + + "slice elements" in { + val el1 = span.render + val el2 = span.render + val el3 = h1.render + + val selection = jQ(el1, el2, el3) + selection.slice(1).get() should be(Seq(el2, el3)) + selection.slice(1, 2).get() should be(Seq(el2)) + selection.slice(0, 2).get() should be(Seq(el1, el2)) + selection.slice(0, 10).get() should be(Seq(el1, el2, el3)) + intercept[Exception](selection.slice(-2, 1).get() should be(Seq(el1))) + intercept[Exception](selection.slice(1, 1).get() should be(Seq(el1))) + } + + "find closest matching parent" in { + val dom = div( + div(cls := "a")( + div(cls := "b")( + span(cls := "d") + ), + div(cls := "b c")( + span(cls := "e") + ) + ) + ).render + + val root = jQ(dom) + root.find("span").closest(".a").length should be(1) + root.find("span").closest(".b").length should be(2) + root.find("span").closest(".c").length should be(1) + root.find("span").closest(".d").length should be(1) + root.find("span").closest(".d").get(0).get.tagName.toLowerCase should be("span") + } + + "find prev/next matching element" in { + val dom = div( + span("a"), + span("b"), + span(cls := "start")("c"), + span("d"), + span("e") + ).render + + val root = jQ(dom).children(".start") + root.prev().text() should be("b") + root.prev("span").prev().text() should be("a") + root.prev().prev().prev().length should be(0) + root.next().text() should be("d") + root.next().next().text() should be("e") + root.next().next().next().length should be(0) + root.prev("a").length should be(0) + } + + "find first/last matching element" in { + val dom = div( + span("a"), + span("b"), + span(cls := "start")("c"), + span("d"), + span("e") + ).render + + val root = jQ(dom) + root.children("span").first().text() should be("a") + root.children("span").last().text() should be("e") + root.children(".start").first().text() should be("c") + root.children(".start").last().text() should be("c") + root.children("a").first().length should be(0) + root.children("a").last().length should be(0) + } + } +}