PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/test/net/cgrand/enlive_html/test.clj

https://github.com/thickey/enlive
Clojure | 215 lines | 169 code | 37 blank | 9 comment | 7 complexity | ac91ac4ec759b013df84790a903b2a57 MD5 | raw file
  1. ; Copyright (c) Christophe Grand, 2009. All rights reserved.
  2. ; The use and distribution terms for this software are covered by the
  3. ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
  4. ; which can be found in the file epl-v10.html at the root of this
  5. ; distribution.
  6. ; By using this software in any fashion, you are agreeing to be bound by
  7. ; the terms of this license.
  8. ; You must not remove this notice, or any other, from this software.
  9. (ns net.cgrand.enlive-html.test
  10. (:use net.cgrand.enlive-html)
  11. (:require [net.cgrand.xml :as xml])
  12. (:require [clojure.zip :as z])
  13. (:require [net.cgrand.enlive-html.state-machine :as sm])
  14. (:use [clojure.contrib.test-is :as test-is :only [set-test is are]]))
  15. ;; test utilities
  16. (defn- htmlize* [node]
  17. (cond
  18. (xml/tag? node)
  19. (-> node
  20. (assoc-in [:attrs :class] (attr-values node :class))
  21. (update-in [:content] (comp htmlize* seq)))
  22. (or (coll? node) (seq? node))
  23. (map htmlize* node)
  24. :else node))
  25. (defn- htmlize [s]
  26. (htmlize*
  27. (if (string? s)
  28. (html-resource (java.io.StringReader. s))
  29. s)))
  30. (defn html-src [s]
  31. (first (html-resource (java.io.StringReader. s))))
  32. (defn- same? [& xs]
  33. (apply = (map htmlize xs)))
  34. (defmacro #^{:private true}
  35. is-same
  36. [& forms]
  37. `(is (same? ~@forms)))
  38. (defmacro sniptest
  39. "A handy macro for experimenting at the repl"
  40. [source-string & forms]
  41. `(apply str (emit* ((transformation ~@forms) (html-src ~source-string)))))
  42. (defn- test-step [expected state node]
  43. (= expected (boolean (sm/accept? (sm/step state (xml/xml-zip node))))))
  44. (defn- elt
  45. ([tag] (elt tag nil))
  46. ([tag attrs & content]
  47. {:tag tag
  48. :attrs attrs
  49. :content content}))
  50. (set-test net.cgrand.enlive-html/compile-keyword
  51. (are (= _2 (@#'net.cgrand.enlive-html/compile-keyword _1))
  52. :foo `(tag= :foo)
  53. :* `any
  54. :#id `(id= "id")
  55. :.class1 `(has-class "class1")
  56. :foo#bar.baz1.baz2 `(sm/intersection (tag= :foo) (id= "bar") (has-class "baz1" "baz2"))))
  57. (set-test tag=
  58. (are (test-step _1 _2 _3)
  59. true (tag= :foo) (elt :foo)
  60. false (tag= :bar) (elt :foo)))
  61. (set-test id=
  62. (are (test-step _1 _2 _3)
  63. true (id= "foo") (elt :div {:id "foo"})
  64. false (id= "bar") (elt :div {:id "foo"})
  65. false (id= "foo") (elt :div)))
  66. (set-test attr?
  67. (are (test-step _1 _2 _3)
  68. true (attr? :href) (elt :a {:href "http://cgrand.net/"})
  69. false (attr? :href) (elt :a {:name "toc"})
  70. false (attr? :href :title) (elt :a {:href "http://cgrand.net/"})
  71. true (attr? :href :title) (elt :a {:href "http://cgrand.net/" :title "home"})))
  72. (set-test attr=
  73. (are (test-step _1 _2 (elt :a {:href "http://cgrand.net/" :title "home"}))
  74. true (attr= :href "http://cgrand.net/")
  75. false (attr= :href "http://clojure.org/")
  76. false (attr= :href "http://cgrand.net/" :name "home")
  77. false (attr= :href "http://cgrand.net/" :title "homepage")
  78. true (attr= :href "http://cgrand.net/" :title "home")))
  79. (set-test attr-starts
  80. (are (test-step _1 _2 (elt :a {:href "http://cgrand.net/" :title "home"}))
  81. true (attr-starts :href "http://cgr")
  82. false (attr-starts :href "http://clo")
  83. false (attr-starts :href "http://cgr" :name "ho")
  84. false (attr-starts :href "http://cgr" :title "x")
  85. true (attr-starts :href "http://cgr" :title "ho")))
  86. (set-test attr-ends
  87. (are (test-step _1 _2 (elt :a {:href "http://cgrand.net/" :title "home"}))
  88. true (attr-ends :href "d.net/")
  89. false (attr-ends :href "e.org/")
  90. false (attr-ends :href "d.net/" :name "me")
  91. false (attr-ends :href "d.net/" :title "hom")
  92. true (attr-ends :href "d.net/" :title "me")))
  93. (set-test attr-contains
  94. (are (test-step _1 _2 (elt :a {:href "http://cgrand.net/" :title "home"}))
  95. true (attr-contains :href "rand")
  96. false (attr-contains :href "jure")
  97. false (attr-contains :href "rand" :name "om")
  98. false (attr-contains :href "rand" :title "pa")
  99. true (attr-contains :href "rand" :title "om")))
  100. (set-test nth-child
  101. (are (same? _2 (at (html-src "<dl><dt>1<dt>2<dt>3<dt>4<dt>5") _1 (add-class "foo")))
  102. [[:dt (nth-child 2)]] "<dl><dt>1<dt class=foo>2<dt>3<dt>4<dt>5"
  103. [[:dt (nth-child 2 0)]] "<dl><dt>1<dt class=foo>2<dt>3<dt class=foo>4<dt>5"
  104. [[:dt (nth-child 3 1)]] "<dl><dt class=foo>1<dt>2<dt>3<dt class=foo>4<dt>5"
  105. [[:dt (nth-child -1 3)]] "<dl><dt class=foo>1<dt class=foo>2<dt class=foo>3<dt>4<dt>5"
  106. [[:dt (nth-child 3 -1)]] "<dl><dt>1<dt class=foo>2<dt>3<dt>4<dt class=foo>5"))
  107. (set-test nth-last-child
  108. (are (same? _2 (at (html-src "<dl><dt>1<dt>2<dt>3<dt>4<dt>5") _1 (add-class "foo")))
  109. [[:dt (nth-last-child 2)]] "<dl><dt>1<dt>2<dt>3<dt class=foo>4<dt>5"
  110. [[:dt (nth-last-child 2 0)]] "<dl><dt>1<dt class=foo>2<dt>3<dt class=foo>4<dt>5"
  111. [[:dt (nth-last-child 3 1)]] "<dl><dt>1<dt class=foo>2<dt>3<dt>4<dt class=foo>5"
  112. [[:dt (nth-last-child -1 3)]] "<dl><dt>1<dt>2<dt class=foo>3<dt class=foo>4<dt class=foo>5"
  113. [[:dt (nth-last-child 3 -1)]] "<dl><dt class=foo>1<dt>2<dt>3<dt class=foo>4<dt>5"))
  114. (set-test nth-of-type
  115. (are (same? _2 (at (html-src "<dl><dt>1<dd>def #1<dt>2<dt>3<dd>def #3<dt>4<dt>5") _1 (add-class "foo")))
  116. [[:dt (nth-of-type 2)]] "<dl><dt>1<dd>def #1<dt class=foo>2<dt>3<dd>def #3<dt>4<dt>5"
  117. [[:dt (nth-of-type 2 0)]] "<dl><dt>1<dd>def #1<dt class=foo>2<dt>3<dd>def #3<dt class=foo>4<dt>5"
  118. [[:dt (nth-of-type 3 1)]] "<dl><dt class=foo>1<dd>def #1<dt>2<dt>3<dd>def #3<dt class=foo>4<dt>5"
  119. [[:dt (nth-of-type -1 3)]] "<dl><dt class=foo>1<dd>def #1<dt class=foo>2<dt class=foo>3<dd>def #3<dt>4<dt>5"
  120. [[:dt (nth-of-type 3 -1)]] "<dl><dt>1<dd>def #1<dt class=foo>2<dt>3<dd>def #3<dt>4<dt class=foo>5"))
  121. (set-test nth-last-of-type
  122. (are (same? _2 (at (html-src "<dl><dt>1<dd>def #1<dt>2<dt>3<dd>def #3<dt>4<dt>5") _1 (add-class "foo")))
  123. [[:dt (nth-last-of-type 2)]] "<dl><dt>1<dd>def #1<dt>2<dt>3<dd>def #3<dt class=foo>4<dt>5"
  124. [[:dt (nth-last-of-type 2 0)]] "<dl><dt>1<dd>def #1<dt class=foo>2<dt>3<dd>def #3<dt class=foo>4<dt>5"
  125. [[:dt (nth-last-of-type 3 1)]] "<dl><dt>1<dd>def #1<dt class=foo>2<dt>3<dd>def #3<dt>4<dt class=foo>5"
  126. [[:dt (nth-last-of-type -1 3)]] "<dl><dt>1<dd>def #1<dt>2<dt class=foo>3<dd>def #3<dt class=foo>4<dt class=foo>5"
  127. [[:dt (nth-last-of-type 3 -1)]] "<dl><dt class=foo>1<dd>def #1<dt>2<dt>3<dd>def #3<dt class=foo>4<dt>5"))
  128. (set-test has
  129. (is-same "<div><p>XXX<p class='ok'><a>link</a><p>YYY"
  130. (at (html-src "<div><p>XXX<p><a>link</a><p>YYY")
  131. [[:p (has [:a])]] (add-class "ok"))))
  132. (set-test but
  133. (is-same "<div><p>XXX<p><a class='ok'>link</a><p>YYY"
  134. (at (html-src "<div><p>XXX<p><a>link</a><p>YYY")
  135. [:div (but :p)] (add-class "ok")))
  136. (is-same "<div><p class='ok'>XXX<p><a>link</a><p class='ok'>YYY"
  137. (at (html-src "<div><p>XXX<p><a>link</a><p>YYY")
  138. [[:p (but (has [:a]))]] (add-class "ok"))))
  139. (set-test left
  140. (are (same? _2 (at (html-src "<h1>T1<h2>T2<h3>T3<p>XXX") _1 (add-class "ok")))
  141. [[:h3 (left :h2)]] "<h1>T1<h2>T2<h3 class=ok>T3<p>XXX"
  142. [[:h3 (left :h1)]] "<h1>T1<h2>T2<h3>T3<p>XXX"
  143. [[:h3 (left :p)]] "<h1>T1<h2>T2<h3>T3<p>XXX"))
  144. (set-test lefts
  145. (are (same? _2 (at (html-src "<h1>T1<h2>T2<h3>T3<p>XXX") _1 (add-class "ok")))
  146. [[:h3 (lefts :h2)]] "<h1>T1<h2>T2<h3 class=ok>T3<p>XXX"
  147. [[:h3 (lefts :h1)]] "<h1>T1<h2>T2<h3 class=ok>T3<p>XXX"
  148. [[:h3 (lefts :p)]] "<h1>T1<h2>T2<h3>T3<p>XXX"))
  149. (set-test right
  150. (are (same? _2 (at (html-src "<h1>T1<h2>T2<h3>T3<p>XXX") _1 (add-class "ok")))
  151. [[:h2 (right :h3)]] "<h1>T1<h2 class=ok>T2<h3>T3<p>XXX"
  152. [[:h2 (right :p)]] "<h1>T1<h2>T2<h3>T3<p>XXX"
  153. [[:h2 (right :h1)]] "<h1>T1<h2>T2<h3>T3<p>XXX"))
  154. (set-test rights
  155. (are (same? _2 (at (html-src "<h1>T1<h2>T2<h3>T3<p>XXX") _1 (add-class "ok")))
  156. [[:h2 (rights :h3)]] "<h1>T1<h2 class=ok>T2<h3>T3<p>XXX"
  157. [[:h2 (rights :p)]] "<h1>T1<h2 class=ok>T2<h3>T3<p>XXX"
  158. [[:h2 (rights :h1)]] "<h1>T1<h2>T2<h3>T3<p>XXX"))
  159. (set-test any-node
  160. (is (= 3 (count (select (htmlize "<i>this</i> is a <i>test</i>") [:body :> any-node])))))
  161. (set-test transform
  162. (is-same "<div>" (at (html-src "<div><span>") [:span] nil))
  163. (is-same "<!-- comment -->" (at (html-src "<!-- comment -->") [:span] nil)))
  164. (set-test clone-for
  165. (is-same "<ul><li>one<li>two" (at (html-src "<ul><li>") [:li] (clone-for [x ["one" "two"]] (content x)))))
  166. (set-test move
  167. (are (same? _2 ((move [:span] [:div] _1) (html-src "<span>1</span><div id=target>here</div><span>2</span>")))
  168. substitute "<span>1</span><span>2</span>"
  169. content "<div id=target><span>1</span><span>2</span></div>"
  170. after "<div id=target>here</div><span>1</span><span>2</span>"
  171. before "<span>1</span><span>2</span><div id=target>here</div>"
  172. append "<div id=target>here<span>1</span><span>2</span></div>"
  173. prepend "<div id=target><span>1</span><span>2</span>here</div>"))
  174. (set-test select
  175. (is (= 3 (count (select (htmlize "<h1>hello</h1>") [:*])))))
  176. (set-test emit*
  177. (is (= "<html><body><h1>hello&lt;<script>if (im < bad) document.write('&lt;')</script></h1></body></html>"
  178. (sniptest "<h1>hello&lt;<script>if (im < bad) document.write('&lt;')"))))