Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
317 lines (274 sloc) 14.4 KB
; Copyright (c) Christophe Grand, 2009. All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (
; which can be found in the file epl-v10.html at the root of this
; distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns net.cgrand.enlive-html.test
(:use net.cgrand.enlive-html)
(:require [net.cgrand.xml :as xml])
(:require [ :as z])
(:use [clojure.test :only [deftest is are run-all-tests]]))
;; test utilities
(defn- normalize [x]
(if (string? x)
(html-snippet x)
(html-resource x)))
(defn- same? [& xs]
(apply = (map normalize xs)))
(defmacro #^{:private true}
[& forms]
`(is (same? ~@forms)))
(defn- test-step [expected pred node]
(= expected (boolean (pred (xml/xml-zip node)))))
(defn- elt
([tag] (elt tag nil))
([tag attrs & content]
{:tag tag
:attrs attrs
:content content}))
(deftest tag=-test
(are [_1 _2 _3] (test-step _1 _2 _3)
true (tag= :foo) (elt :foo)
false (tag= :bar) (elt :foo)))
(deftest id=-test
(are [_1 _2 _3] (test-step _1 _2 _3)
true (id= "foo") (elt :div {:id "foo"})
false (id= "bar") (elt :div {:id "foo"})
false (id= "foo") (elt :div)))
(deftest attr?-test
(are [_1 _2 _3] (test-step _1 _2 _3)
true (attr? :href) (elt :a {:href ""})
false (attr? :href) (elt :a {:name "toc"})
false (attr? :href :title) (elt :a {:href ""})
true (attr? :href :title) (elt :a {:href "" :title "home"})))
(deftest attr=-test
(are [_1 _2] (test-step _1 _2 (elt :a {:href "" :title "home"}))
true (attr= :href "")
false (attr= :href "")
false (attr= :href "" :name "home")
false (attr= :href "" :title "homepage")
true (attr= :href "" :title "home")))
(deftest attr-starts-test
(are [_1 _2] (test-step _1 _2 (elt :a {:href "" :title "home"}))
true (attr-starts :href "http://cgr")
false (attr-starts :href "http://clo")
false (attr-starts :href "http://cgr" :name "ho")
false (attr-starts :href "http://cgr" :title "x")
true (attr-starts :href "http://cgr" :title "ho")))
(deftest attr-ends-test
(are [_1 _2] (test-step _1 _2 (elt :a {:href "" :title "home"}))
true (attr-ends :href "")
false (attr-ends :href "")
false (attr-ends :href "" :name "me")
false (attr-ends :href "" :title "hom")
true (attr-ends :href "" :title "me")))
(deftest attr-contains-test
(are [_1 _2] (test-step _1 _2 (elt :a {:href "" :title "home"}))
true (attr-contains :href "rand")
false (attr-contains :href "jure")
false (attr-contains :href "rand" :name "om")
false (attr-contains :href "rand" :title "pa")
true (attr-contains :href "rand" :title "om")))
(deftest nth-child-test
(are [_1 _2] (same? _2 (sniptest "<dl><dt>1<dt>2<dt>3<dt>4<dt>5" _1 (add-class "foo")))
[[:dt (nth-child 2)]] "<dl><dt>1<dt class=foo>2<dt>3<dt>4<dt>5"
[[:dt (nth-child 2 0)]] "<dl><dt>1<dt class=foo>2<dt>3<dt class=foo>4<dt>5"
[[:dt (nth-child 3 1)]] "<dl><dt class=foo>1<dt>2<dt>3<dt class=foo>4<dt>5"
[[:dt (nth-child -1 3)]] "<dl><dt class=foo>1<dt class=foo>2<dt class=foo>3<dt>4<dt>5"
[[:dt (nth-child 3 -1)]] "<dl><dt>1<dt class=foo>2<dt>3<dt>4<dt class=foo>5"))
(deftest nth-last-child-test
(are [_1 _2] (same? _2 (sniptest "<dl><dt>1<dt>2<dt>3<dt>4<dt>5" _1 (add-class "foo")))
[[:dt (nth-last-child 2)]] "<dl><dt>1<dt>2<dt>3<dt class=foo>4<dt>5"
[[:dt (nth-last-child 2 0)]] "<dl><dt>1<dt class=foo>2<dt>3<dt class=foo>4<dt>5"
[[:dt (nth-last-child 3 1)]] "<dl><dt>1<dt class=foo>2<dt>3<dt>4<dt class=foo>5"
[[:dt (nth-last-child -1 3)]] "<dl><dt>1<dt>2<dt class=foo>3<dt class=foo>4<dt class=foo>5"
[[:dt (nth-last-child 3 -1)]] "<dl><dt class=foo>1<dt>2<dt>3<dt class=foo>4<dt>5"))
(deftest nth-of-type-test
(are [_1 _2] (same? _2 (sniptest "<dl><dt>1<dd>def #1<dt>2<dt>3<dd>def #3<dt>4<dt>5" _1 (add-class "foo")))
[[:dt (nth-of-type 2)]] "<dl><dt>1<dd>def #1<dt class=foo>2<dt>3<dd>def #3<dt>4<dt>5"
[[: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"
[[: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"
[[: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"
[[: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"))
(deftest nth-last-of-type-test
(are [_1 _2] (same? _2 (sniptest "<dl><dt>1<dd>def #1<dt>2<dt>3<dd>def #3<dt>4<dt>5" _1 (add-class "foo")))
[[: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"
[[: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"
[[: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"
[[: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"
[[: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"))
(deftest has-test
(is-same "<div><p>XXX<p class='ok'><a>link</a><p>YYY"
(sniptest "<div><p>XXX<p><a>link</a><p>YYY"
[[:p (has [:a])]] (add-class "ok"))))
(deftest but-test
(is-same "<div><p>XXX<p><a class='ok'>link</a><p>YYY"
(sniptest "<div><p>XXX<p><a>link</a><p>YYY"
[:div (but :p)] (add-class "ok")))
(is-same "<div><p class='ok'>XXX<p><a>link</a><p class='ok'>YYY"
(sniptest "<div><p>XXX<p><a>link</a><p>YYY"
[[:p (but (has [:a]))]] (add-class "ok"))))
(deftest left-test
(are [_1 _2] (same? _2 (sniptest "<div><h1>T1<h2>T2<h3>T3<p>XXX" _1 (add-class "ok")))
[[:h3 (left :h2)]] "<div><h1>T1<h2>T2<h3 class=ok>T3<p>XXX"
[[:h3 (left :h1)]] "<div><h1>T1<h2>T2<h3>T3<p>XXX"
[[:h3 (left :p)]] "<div><h1>T1<h2>T2<h3>T3<p>XXX"))
(deftest lefts-test
(are [_1 _2] (same? _2 (sniptest "<div><h1>T1<h2>T2<h3>T3<p>XXX" _1 (add-class "ok")))
[[:h3 (lefts :h2)]] "<div><h1>T1<h2>T2<h3 class=ok>T3<p>XXX"
[[:h3 (lefts :h1)]] "<div><h1>T1<h2>T2<h3 class=ok>T3<p>XXX"
[[:h3 (lefts :p)]] "<div><h1>T1<h2>T2<h3>T3<p>XXX"))
(deftest right-test
(are [_1 _2] (same? _2 (sniptest "<div><h1>T1<h2>T2<h3>T3<p>XXX" _1 (add-class "ok")))
[[:h2 (right :h3)]] "<div><h1>T1<h2 class=ok>T2<h3>T3<p>XXX"
[[:h2 (right :p)]] "<div><h1>T1<h2>T2<h3>T3<p>XXX"
[[:h2 (right :h1)]] "<div><h1>T1<h2>T2<h3>T3<p>XXX"))
(deftest rights-test
(are [_1 _2] (same? _2 (sniptest "<div><h1>T1<h2>T2<h3>T3<p>XXX" _1 (add-class "ok")))
[[:h2 (rights :h3)]] "<div><h1>T1<h2 class=ok>T2<h3>T3<p>XXX"
[[:h2 (rights :p)]] "<div><h1>T1<h2 class=ok>T2<h3>T3<p>XXX"
[[:h2 (rights :h1)]] "<div><h1>T1<h2>T2<h3>T3<p>XXX"))
(deftest any-node-test
(is (= 3 (-> "<html><body><i>this</i> is a <i>test</i>" html-snippet
(select [:body :> any-node]) count))))
(deftest transform-test
(is-same "<div>" (sniptest "<div><span>" [:span] nil))
(is-same "<!-- comment -->" (sniptest "<!-- comment -->" [:span] nil))
(is-same "\n<feed xml:lang=\"en-us\">\n <title>1</title>\n <id>1</id>\n <link href=\"./\" />\n <link rel=\"self\" href=\"\" />\n <subtitle>1</subtitle>\n <updated>1</updated>\n\n<entry xml:base=\"\">\n <title>1</title>\n <link href=\"1\" />\n <id>1</id>\n <published>1</published>\n \n <category term=\"devops\" scheme=\"\">1</category>\n <summary type=\"xhtml\"><div>1</div></summary>\n <content type=\"xhtml\"><div>1</div></content>\n</entry><entry xml:base=\"\">\n <title>1</title>\n <link href=\"1\" />\n <id>1</id>\n <published>1</published>\n \n <category term=\"devops\" scheme=\"\">1</category>\n <summary type=\"xhtml\"><div>1</div></summary>\n <content type=\"xhtml\"><div>1</div></content>\n</entry>\n</feed>\n"
(sniptest "<?xml version='1.0' encoding='UTF-8'?>
<feed xml:lang='en-us' xmlns=''>
<title>Feed title</title>
<id>feed id</id>
<link href='./'/>
<link href='' rel='self'/>
<entry xml:base=''>
<link href=''/>
<category scheme='' term='devops'/>
<summary type='xhtml'><div xmlns=''></div></summary>
<content type='xhtml'><div xmlns=''></div></content>
" [:feed :title] (content "1")
[:feed :id] (content "1")
[:feed :subtitle] (content "1")
[:feed :updated] (content "1")
[:entry] (clone-for [x ["one" "two"]]
[:published] (content "1")
[:updated] nil
[:category] (content "1")
[:link] (set-attr :href "1")
[:id] (content "1")
[:summary :div] (content "1")
[:content :div] (content "1"))
(deftest clone-for-test
;; node selector
(is-same "<ul><li>one<li>two"
(sniptest "<ul><li>" [:li] (clone-for [x ["one" "two"]] (content x))))
;; fragment selector
(is-same "<dl><dt>term #1<dd>desc #1<dt>term #2<dd>desc #2"
(sniptest "<dl><dt>Sample term<dd>sample description"
{[:dt] [:dd]} (clone-for [[t d] {"term #1" "desc #1" "term #2" "desc #2"}]
[:dt] (content t)
[:dd] (content d)))))
(deftest move-test
(are [_1 _2] (same?
(sniptest "<body><span>1</span><div id=target>here</div><span>2</span>"
(move [:span] [:div] _1) ))
substitute "<body><span>1</span><span>2</span>"
content "<body><div id=target><span>1</span><span>2</span></div>"
after "<body><div id=target>here</div><span>1</span><span>2</span>"
before "<body><span>1</span><span>2</span><div id=target>here</div>"
append "<body><div id=target>here<span>1</span><span>2</span></div>"
prepend "<body><div id=target><span>1</span><span>2</span>here</div>")
(are [_1 _2] (same?
(sniptest "<div><h1>Title1<p>blabla<hr><h2>Title2<p>blibli"
(move {[:h1] [:p]} {[:h2] [:p]} _1) ))
substitute "<div><hr><h1>Title1<p>blabla"
after "<div><hr><h2>Title2<p>blibli<h1>Title1<p>blabla"
before "<div><hr><h1>Title1<p>blabla<h2>Title2<p>blibli")
(are [_1 _2] (same?
(sniptest "<div><h1>Title1<p>blabla<hr><h2>Title2<p>blibli"
(move {[:h1] [:p]} [:h2] _1) ))
substitute "<div><hr><h1>Title1<p>blabla<p>blibli"
content "<div><hr><h2><h1>Title1</h1><p>blabla</p></h2><p>blibli"
after "<div><hr><h2>Title2<h1>Title1<p>blabla<p>blibli"
before "<div><hr><h1>Title1<p>blabla<h2>Title2<p>blibli"
append "<div><hr><h2>Title2<h1>Title1</h1><p>blabla</p></h2><p>blibli"
prepend "<div><hr><h2><h1>Title1</h1><p>blabla</p>Title2</h2><p>blibli")
(are [_1 _2] (same? _2
(sniptest "<div><h1>Title1<p>blabla<hr><h2>Title2<p>blibli"
(move [:h1] {[:h2] [:p]} _1) ))
substitute "<div><p>blabla<hr><h1>Title1"
after "<div><p>blabla<hr><h2>Title2<p>blibli<h1>Title1"
before "<div><p>blabla<hr><h1>Title1<h2>Title2<p>blibli"))
(deftest wrap-test
(is-same "<dl><ol><dt>Sample term</dt></ol><dd>sample description</dd></dl>"
(sniptest "<dl><dt>Sample term<dd>sample description" [:dt] (wrap :ol)))
(is-same "<dl><ol><dt>Sample term</dt><dd>sample description</dd></ol></dl>"
(sniptest "<dl><dt>Sample term<dd>sample description" {[:dt] [:dd]} (wrap :ol))))
(deftest select-test
(is (= 3 (-> "<html><body><h1>hello</h1>" html-snippet (select [:*]) count))))
(deftest emit*-test
(is (= "<h1>hello&lt;<script>if (im < bad) document.write('&lt;')</script></h1>"
(sniptest "<h1>hello&lt;<script>if (im < bad) document.write('&lt;')"))))
(deftest transform-content-test
(is-same "<div><div class='bar'><div>"
(sniptest "<div><div><div>"
[:> :div] (transform-content [:> :div] (add-class "bar")))))
(deftemplate case-insensitive-doctype-template "resources/templates/doctype_case.html"
(deftest case-insensitive-doctype-test
(is (.startsWith (apply str (case-insensitive-doctype-template)) "<!DOCTYPE")))
(deftest templates-return-seqs
(is (seq? (case-insensitive-doctype-template))))
(deftest hiccup-like
(is-same "<div><b>world"
(sniptest "<div>"
[:div] (content (html [:b "world"]))))
(is-same "<div><b id=foo>world"
(sniptest "<div>"
[:div] (content (html [:b#foo "world"]))))
(is-same "<div><a id=foo class=\"link home\" href=\"\">world"
(sniptest "<div>"
[:div] (content (html [ {:href ""}
(is-same "<div><ul><li>a<li>b<li>c"
(sniptest "<div>"
[:div] (content (html [:ul (for [s ["a" "b" "c"]] [:li s])])))))
(deftest hiccup-mixed
(is-same "<div><p><i>big</i><b>world</b></p>"
(sniptest "<div>"
[:div] (content (html [:p '({:tag :i :content ["big"]}
{:tag :b :content ["world"]})])))
(sniptest "<div>"
[:div] (content (html [:p {:tag :i :content ["big"]}
{:tag :b :content ["world"]}])))
(sniptest "<div>"
[:div] (content (html {:tag :p
:content [[:i "big"] [:b "world"]]}))))
(is-same "<div><a href=''><i>big</i><b>world</b></a>"
(sniptest "<div>"
[:div] (content (html [:a {:href ""} {:tag :i :content ["big"]}
{:tag :b :content ["world"]}])))))
(deftest replace-vars-test
(is-same "<div><h1>untouched ${name}<p class=hello>hello world"
(sniptest "<div><h1>untouched ${name}<p class=\"${class}\">hello ${name}"
#{[:p] [:p any-node]} (replace-vars {:name "world" :class "hello"})))
(is (= ((replace-vars {:a "A" :b "B"}) "${a} ${b}")
"A B"))
(is (= ((replace-words {"Donald" "Mickey" "Duck" "Mouse"}) "Donald Duckling Duck")
"Mickey Duckling Mouse")))