PageRenderTime 26ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/path/ruby/1.9.1/gems/nokogiri-1.4.4/test/xml/test_node_reparenting.rb

https://github.com/vinniv/sample_app
Ruby | 321 lines | 258 code | 20 blank | 43 comment | 3 complexity | 6495475d7cd9b353d04c9913924d0458 MD5 | raw file
  1. require "helper"
  2. module Nokogiri
  3. module XML
  4. class TestNodeReparenting < Nokogiri::TestCase
  5. describe "standard node reparenting behavior" do
  6. # describe "namespace handling during reparenting" do
  7. # describe "given a Node" do
  8. # describe "with a Namespace" do
  9. # it "keeps the Namespace"
  10. # end
  11. # describe "given a parent Node with a default and a non-default Namespace" do
  12. # describe "passed an Node without a namespace" do
  13. # it "inserts an Node that inherits the default Namespace"
  14. # end
  15. # describe "passed a Node with a Namespace that matches the parent's non-default Namespace" do
  16. # it "inserts a Node that inherits the matching parent Namespace"
  17. # end
  18. # end
  19. # end
  20. # describe "given a markup string" do
  21. # describe "parsed relative to the document" do
  22. # describe "with a Namespace" do
  23. # it "keeps the Namespace"
  24. # end
  25. # describe "given a parent Node with a default and a non-default Namespace" do
  26. # describe "passed an Node without a namespace" do
  27. # it "inserts an Node that inherits the default Namespace"
  28. # end
  29. # describe "passed a Node with a Namespace that matches the parent's non-default Namespace" do
  30. # it "inserts a Node that inherits the matching parent Namespace"
  31. # end
  32. # end
  33. # end
  34. # describe "parsed relative to a specific node" do
  35. # describe "with a Namespace" do
  36. # it "keeps the Namespace"
  37. # end
  38. # describe "given a parent Node with a default and a non-default Namespace" do
  39. # describe "passed an Node without a namespace" do
  40. # it "inserts an Node that inherits the default Namespace"
  41. # end
  42. # describe "passed a Node with a Namespace that matches the parent's non-default Namespace" do
  43. # it "inserts a Node that inherits the matching parent Namespace"
  44. # end
  45. # end
  46. # end
  47. # end
  48. # end
  49. {
  50. :add_child => {:target => "/root/a1", :returns_self => false, :children_tags => %w[text b1 b2]},
  51. :<< => {:target => "/root/a1", :returns_self => false, :children_tags => %w[text b1 b2]},
  52. :replace => {:target => "/root/a1/node()", :returns_self => false, :children_tags => %w[b1 b2]},
  53. :swap => {:target => "/root/a1/node()", :returns_self => true, :children_tags => %w[b1 b2]},
  54. :children= => {:target => "/root/a1", :returns_self => false, :children_tags => %w[b1 b2]},
  55. :inner_html= => {:target => "/root/a1", :returns_self => true, :children_tags => %w[b1 b2]},
  56. :add_previous_sibling => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[b1 b2 text]},
  57. :previous= => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[b1 b2 text]},
  58. :before => {:target => "/root/a1/text()", :returns_self => true, :children_tags => %w[b1 b2 text]},
  59. :add_next_sibling => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[text b1 b2]},
  60. :next= => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[text b1 b2]},
  61. :after => {:target => "/root/a1/text()", :returns_self => true, :children_tags => %w[text b1 b2]}
  62. }.each do |method, params|
  63. before do
  64. @doc = Nokogiri::XML "<root><a1>First node</a1><a2>Second node</a2><a3>Third <bx />node</a3></root>"
  65. @doc2 = @doc.dup
  66. @fragment_string = "<b1>foo</b1><b2>bar</b2>"
  67. @fragment = Nokogiri::XML::DocumentFragment.parse @fragment_string
  68. @node_set = Nokogiri::XML("<root><b1>foo</b1><b2>bar</b2></root>").xpath("/root/node()")
  69. end
  70. describe "##{method}" do
  71. describe "passed a Node" do
  72. [:current, :another].each do |which|
  73. describe "passed a Node in the #{which} document" do
  74. before do
  75. @other_doc = which == :current ? @doc : @doc2
  76. @other_node = @other_doc.at_xpath("/root/a2")
  77. end
  78. it "unlinks the Node from its previous position" do
  79. @doc.at_xpath(params[:target]).send(method, @other_node)
  80. @other_doc.at_xpath("/root/a2").must_be_nil
  81. end
  82. it "inserts the Node in the proper position" do
  83. @doc.at_xpath(params[:target]).send(method, @other_node)
  84. @doc.at_xpath("/root/a1/a2").wont_be_nil
  85. end
  86. it "returns the expected value" do
  87. sendee = @doc.at_xpath(params[:target])
  88. result = sendee.send(method, @other_node)
  89. if params[:returns_self]
  90. result.must_equal sendee
  91. else
  92. result.must_equal @other_node
  93. end
  94. end
  95. end
  96. end
  97. end
  98. describe "passed a markup string" do
  99. it "inserts the fragment roots in the proper position" do
  100. @doc.at_xpath(params[:target]).send(method, @fragment_string)
  101. @doc.xpath("/root/a1/node()").collect {|n| n.name}.must_equal params[:children_tags]
  102. end
  103. it "returns the expected value" do
  104. sendee = @doc.at_xpath(params[:target])
  105. result = sendee.send(method, @fragment_string)
  106. if params[:returns_self]
  107. result.must_equal sendee
  108. else
  109. result.must_be_kind_of Nokogiri::XML::NodeSet
  110. result.to_html.must_equal @fragment_string
  111. end
  112. end
  113. end
  114. describe "passed a fragment" do
  115. it "inserts the fragment roots in the proper position" do
  116. @doc.at_xpath(params[:target]).send(method, @fragment)
  117. @doc.xpath("/root/a1/node()").collect {|n| n.name}.must_equal params[:children_tags]
  118. end
  119. end
  120. describe "passed a document" do
  121. it "raises an exception" do
  122. proc { @doc.at_xpath("/root/a1").send(method, @doc2) }.must_raise(ArgumentError)
  123. end
  124. end
  125. describe "passed a non-Node" do
  126. it "raises an exception" do
  127. proc { @doc.at_xpath("/root/a1").send(method, 42) }.must_raise(ArgumentError)
  128. end
  129. end
  130. describe "passed a NodeSet" do
  131. it "inserts each member of the NodeSet in the proper order" do
  132. @doc.at_xpath(params[:target]).send(method, @node_set)
  133. @doc.xpath("/root/a1/node()").collect {|n| n.name}.must_equal params[:children_tags]
  134. end
  135. end
  136. end
  137. end
  138. describe "text node merging" do
  139. describe "#add_child" do
  140. it "merges the Text node with adjacent Text nodes" do
  141. @doc.at_xpath("/root/a1").add_child Nokogiri::XML::Text.new('hello', @doc)
  142. @doc.at_xpath("/root/a1/text()").content.must_equal "First nodehello"
  143. end
  144. end
  145. describe "#replace" do
  146. it "merges the Text node with adjacent Text nodes" do
  147. @doc.at_xpath("/root/a3/bx").replace Nokogiri::XML::Text.new('hello', @doc)
  148. @doc.at_xpath("/root/a3/text()").content.must_equal "Third hellonode"
  149. end
  150. end
  151. end
  152. end
  153. describe "ad hoc node reparenting behavior" do
  154. describe "#add_child" do
  155. describe "given a new node with a namespace" do
  156. it "keeps the namespace" do
  157. doc = Nokogiri::XML::Document.new
  158. item = Nokogiri::XML::Element.new('item', doc)
  159. doc.root = item
  160. entry = Nokogiri::XML::Element.new('entry', doc)
  161. entry.add_namespace('tlm', 'http://tenderlovemaking.com')
  162. assert_equal 'http://tenderlovemaking.com', entry.namespaces['xmlns:tlm']
  163. item.add_child(entry)
  164. assert_equal 'http://tenderlovemaking.com', entry.namespaces['xmlns:tlm']
  165. end
  166. end
  167. describe "given a parent node with a default namespace" do
  168. before do
  169. @doc = Nokogiri::XML(<<-eoxml)
  170. <root xmlns="http://tenderlovemaking.com/">
  171. <first>
  172. </first>
  173. </root>
  174. eoxml
  175. end
  176. it "inserts a node that inherits the default namespace" do
  177. assert node = @doc.at('//xmlns:first')
  178. child = Nokogiri::XML::Node.new('second', @doc)
  179. node.add_child(child)
  180. assert @doc.at('//xmlns:second')
  181. end
  182. end
  183. describe "given a parent node with a non-default namespace" do
  184. before do
  185. @doc = Nokogiri::XML(<<-eoxml)
  186. <root xmlns="http://tenderlovemaking.com/" xmlns:foo="http://flavorjon.es/">
  187. <first>
  188. </first>
  189. </root>
  190. eoxml
  191. end
  192. describe "and a child node with a namespace matching the parent's non-default namespace" do
  193. it "inserts a node that inherits the matching parent namespace" do
  194. assert node = @doc.at('//xmlns:first')
  195. child = Nokogiri::XML::Node.new('second', @doc)
  196. ns = @doc.root.namespace_definitions.detect { |x| x.prefix == "foo" }
  197. child.namespace = ns
  198. node.add_child(child)
  199. assert @doc.at('//foo:second', "foo" => "http://flavorjon.es/")
  200. end
  201. end
  202. end
  203. end
  204. describe "#add_previous_sibling" do
  205. it "should not merge text nodes during the operation" do
  206. xml = Nokogiri::XML %Q(<root>text node</root>)
  207. replacee = xml.root.children.first
  208. replacee.add_previous_sibling "foo <p></p> bar"
  209. assert_equal "foo <p></p> bartext node", xml.root.children.to_html
  210. end
  211. end
  212. describe "#add_next_sibling" do
  213. it "should not merge text nodes during the operation" do
  214. xml = Nokogiri::XML %Q(<root>text node</root>)
  215. replacee = xml.root.children.first
  216. replacee.add_next_sibling "foo <p></p> bar"
  217. assert_equal "text nodefoo <p></p> bar", xml.root.children.to_html
  218. end
  219. end
  220. describe "#replace" do
  221. describe "a text node with a text node" do
  222. it "should not merge text nodes during the operation" do
  223. xml = Nokogiri::XML %Q(<root>text node</root>)
  224. replacee = xml.root.children.first
  225. replacee.replace "new text node"
  226. assert_equal "new text node", xml.root.children.first.content
  227. end
  228. end
  229. describe "when a document has a default namespace" do
  230. before do
  231. @fruits = Nokogiri::XML(<<-eoxml)
  232. <fruit xmlns="http://fruits.org">
  233. <apple />
  234. </fruit>
  235. eoxml
  236. end
  237. it "inserts a node with default namespaces" do
  238. apple = @fruits.css('apple').first
  239. orange = Nokogiri::XML::Node.new('orange', @fruits)
  240. apple.replace(orange)
  241. assert_equal orange, @fruits.css('orange').first
  242. end
  243. end
  244. end
  245. describe "unlinking a node and then reparenting it" do
  246. it "not blow up" do
  247. # see http://github.com/tenderlove/nokogiri/issues#issue/22
  248. 10.times do
  249. STDOUT.putc "."
  250. STDOUT.flush
  251. begin
  252. doc = Nokogiri::XML <<-EOHTML
  253. <root>
  254. <a>
  255. <b/>
  256. <c/>
  257. </a>
  258. </root>
  259. EOHTML
  260. assert root = doc.at("root")
  261. assert a = root.at("a")
  262. assert b = a.at("b")
  263. assert c = a.at("c")
  264. a.add_next_sibling(b.unlink)
  265. c.unlink
  266. end
  267. GC.start
  268. end
  269. end
  270. end
  271. describe "replace-merging text nodes" do
  272. [
  273. ['<root>a<br/></root>', 'afoo'],
  274. ['<root>a<br/>b</root>', 'afoob'],
  275. ['<root><br/>b</root>', 'foob']
  276. ].each do |xml, result|
  277. it "doesn't blow up on #{xml}" do
  278. doc = Nokogiri::XML.parse(xml)
  279. saved_nodes = doc.root.children
  280. doc.at_xpath("/root/br").replace(Nokogiri::XML::Text.new('foo', doc))
  281. saved_nodes.each { |child| child.inspect } # try to cause a crash
  282. assert_equal result, doc.at_xpath("/root/text()").inner_text
  283. end
  284. end
  285. end
  286. end
  287. end
  288. end
  289. end