nokogiri 1.5.0-java → 1.5.1-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (81) hide show
  1. data/CHANGELOG.ja.rdoc +56 -12
  2. data/CHANGELOG.rdoc +45 -0
  3. data/C_CODING_STYLE.rdoc +27 -0
  4. data/Manifest.txt +4 -0
  5. data/README.rdoc +11 -7
  6. data/Rakefile +44 -26
  7. data/bin/nokogiri +10 -2
  8. data/ext/java/nokogiri/HtmlDocument.java +37 -2
  9. data/ext/java/nokogiri/NokogiriService.java +10 -2
  10. data/ext/java/nokogiri/XmlAttr.java +1 -1
  11. data/ext/java/nokogiri/XmlDocument.java +68 -11
  12. data/ext/java/nokogiri/XmlDocumentFragment.java +16 -5
  13. data/ext/java/nokogiri/XmlElement.java +0 -40
  14. data/ext/java/nokogiri/XmlNamespace.java +8 -1
  15. data/ext/java/nokogiri/XmlNode.java +131 -27
  16. data/ext/java/nokogiri/XmlNodeSet.java +4 -1
  17. data/ext/java/nokogiri/XmlSaxParserContext.java +2 -13
  18. data/ext/java/nokogiri/XmlXpathContext.java +4 -1
  19. data/ext/java/nokogiri/XsltStylesheet.java +198 -37
  20. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +40 -2
  21. data/ext/java/nokogiri/internals/NokogiriHelpers.java +82 -9
  22. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +4 -3
  23. data/ext/java/nokogiri/internals/ParserContext.java +33 -3
  24. data/ext/java/nokogiri/internals/SaveContextVisitor.java +203 -12
  25. data/ext/java/nokogiri/internals/XmlDomParser.java +33 -2
  26. data/ext/java/nokogiri/internals/XmlDomParserContext.java +32 -12
  27. data/ext/nokogiri/extconf.rb +11 -3
  28. data/ext/nokogiri/html_document.c +16 -0
  29. data/ext/nokogiri/html_sax_parser_context.c +59 -37
  30. data/ext/nokogiri/html_sax_push_parser.c +87 -0
  31. data/ext/nokogiri/html_sax_push_parser.h +9 -0
  32. data/ext/nokogiri/nokogiri.c +6 -8
  33. data/ext/nokogiri/nokogiri.h +3 -0
  34. data/ext/nokogiri/xml_document.c +101 -3
  35. data/ext/nokogiri/xml_document.h +3 -3
  36. data/ext/nokogiri/xml_node.c +150 -58
  37. data/ext/nokogiri/xml_node_set.c +169 -120
  38. data/ext/nokogiri/xml_node_set.h +5 -0
  39. data/ext/nokogiri/xml_sax_parser_context.c +64 -41
  40. data/ext/nokogiri/xml_text.c +2 -0
  41. data/ext/nokogiri/xml_xpath_context.c +30 -24
  42. data/ext/nokogiri/xslt_stylesheet.c +62 -16
  43. data/ext/nokogiri/xslt_stylesheet.h +5 -0
  44. data/lib/nokogiri/css/parser.rb +163 -157
  45. data/lib/nokogiri/css/parser.y +6 -3
  46. data/lib/nokogiri/css/tokenizer.rb +1 -1
  47. data/lib/nokogiri/css/tokenizer.rex +1 -1
  48. data/lib/nokogiri/html.rb +1 -0
  49. data/lib/nokogiri/html/document.rb +82 -42
  50. data/lib/nokogiri/html/sax/push_parser.rb +16 -0
  51. data/lib/nokogiri/nokogiri.jar +0 -0
  52. data/lib/nokogiri/version.rb +1 -1
  53. data/lib/nokogiri/xml.rb +6 -0
  54. data/lib/nokogiri/xml/builder.rb +7 -1
  55. data/lib/nokogiri/xml/document.rb +32 -17
  56. data/lib/nokogiri/xml/document_fragment.rb +6 -1
  57. data/lib/nokogiri/xml/node.rb +40 -9
  58. data/lib/nokogiri/xslt.rb +5 -1
  59. data/tasks/cross_compile.rb +1 -0
  60. data/tasks/nokogiri.org.rb +6 -0
  61. data/tasks/test.rb +1 -0
  62. data/test/css/test_xpath_visitor.rb +6 -0
  63. data/test/helper.rb +1 -0
  64. data/test/html/test_document.rb +26 -0
  65. data/test/html/test_document_fragment.rb +1 -2
  66. data/test/test_memory_leak.rb +81 -1
  67. data/test/test_xslt_transforms.rb +152 -123
  68. data/test/xml/test_builder.rb +24 -2
  69. data/test/xml/test_c14n.rb +151 -0
  70. data/test/xml/test_document.rb +48 -0
  71. data/test/xml/test_namespace.rb +5 -0
  72. data/test/xml/test_node.rb +82 -1
  73. data/test/xml/test_node_attributes.rb +19 -0
  74. data/test/xml/test_node_inheritance.rb +32 -0
  75. data/test/xml/test_node_reparenting.rb +32 -0
  76. data/test/xml/test_node_set.rb +16 -8
  77. data/test/xml/test_reader_encoding.rb +16 -0
  78. data/test/xml/test_unparented_node.rb +32 -0
  79. data/test/xml/test_xinclude.rb +83 -0
  80. data/test/xml/test_xpath.rb +22 -0
  81. metadata +147 -123
@@ -199,13 +199,34 @@ module Nokogiri
199
199
  assert_equal 'hello', builder.doc.at('/root').content
200
200
  end
201
201
 
202
+ def test_raw_xml_append
203
+ builder = Nokogiri::XML::Builder.new do |xml|
204
+ xml.root do
205
+ xml << '<aaa><bbb/><ccc/></aaa>'
206
+ end
207
+ end
208
+
209
+ assert_equal ["aaa"], builder.doc.at_css("root").children.collect(&:name)
210
+ assert_equal ["bbb","ccc"], builder.doc.at_css("aaa").children.collect(&:name)
211
+ end
212
+
202
213
  def test_cdata
203
214
  builder = Nokogiri::XML::Builder.new do
204
215
  root {
205
216
  cdata "hello world"
206
217
  }
207
218
  end
208
- assert_equal("<?xml version=\"1.0\"?><root><![CDATA[hello world]]></root>", builder.to_xml.gsub(/\n/, ''))
219
+ assert_equal("<?xml version=\"1.0\"?><root><![CDATA[hello world]]></root>",
220
+ builder.to_xml.gsub(/\n/, ""))
221
+ end
222
+
223
+ def test_comment
224
+ builder = Nokogiri::XML::Builder.new do
225
+ root {
226
+ comment "this is a comment"
227
+ }
228
+ end
229
+ assert builder.doc.root.children.first.comment?
209
230
  end
210
231
 
211
232
  def test_builder_no_block
@@ -214,7 +235,8 @@ module Nokogiri
214
235
  builder.root {
215
236
  cdata string
216
237
  }
217
- assert_equal("<?xml version=\"1.0\"?><root><![CDATA[hello world]]></root>", builder.to_xml.gsub(/\n/, ''))
238
+ assert_equal("<?xml version=\"1.0\"?><root><![CDATA[hello world]]></root>",
239
+ builder.to_xml.gsub(/\n/, ''))
218
240
  end
219
241
 
220
242
  private
@@ -0,0 +1,151 @@
1
+ require "helper"
2
+
3
+ module Nokogiri
4
+ module XML
5
+ class TestC14N < Nokogiri::TestCase
6
+ # http://www.w3.org/TR/xml-c14n#Example-OutsideDoc
7
+ def test_3_1
8
+ doc = Nokogiri.XML <<-eoxml
9
+ <?xml version="1.0"?>
10
+
11
+ <?xml-stylesheet href="doc.xsl"
12
+ type="text/xsl" ?>
13
+
14
+ <!DOCTYPE doc SYSTEM "doc.dtd">
15
+
16
+ <doc>Hello, world!<!-- Comment 1 --></doc>
17
+
18
+ <?pi-without-data ?>
19
+
20
+ <!-- Comment 2 -->
21
+
22
+ <!-- Comment 3 -->
23
+ eoxml
24
+
25
+ c14n = doc.canonicalize
26
+ assert_no_match(/version=/, c14n)
27
+ assert_match(/Hello, world/, c14n)
28
+ assert_no_match(/Comment/, c14n)
29
+ c14n = doc.canonicalize(nil, nil, true)
30
+ assert_match(/Comment/, c14n)
31
+ end
32
+
33
+ def test_exclude_block_params
34
+ xml = '<a><b></b></a>'
35
+ doc = Nokogiri.XML xml
36
+
37
+ list = []
38
+ doc.canonicalize do |node, parent|
39
+ list << [node, parent]
40
+ true
41
+ end
42
+ if Nokogiri.jruby?
43
+ assert_equal(
44
+ ['a', 'document', 'document', nil, 'b', 'a'],
45
+ list.flatten.map { |x| x ? x.name : x }
46
+ )
47
+ else
48
+ assert_equal(
49
+ ['a', 'document', 'document', nil, 'b', 'a', 'a', 'document'],
50
+ list.flatten.map { |x| x ? x.name : x }
51
+ )
52
+ end
53
+ end
54
+
55
+ def test_exclude_block_true
56
+ xml = '<a><b></b></a>'
57
+ doc = Nokogiri.XML xml
58
+
59
+ c14n = doc.canonicalize do |node, parent|
60
+ true
61
+ end
62
+ assert_equal xml, c14n
63
+ end
64
+
65
+ def test_exclude_block_false
66
+ xml = '<a><b></b></a>'
67
+ doc = Nokogiri.XML xml
68
+
69
+ c14n = doc.canonicalize do |node, parent|
70
+ false
71
+ end
72
+ assert_equal '', c14n
73
+ end
74
+
75
+ def test_exclude_block_nil
76
+ xml = '<a><b></b></a>'
77
+ doc = Nokogiri.XML xml
78
+
79
+ c14n = doc.canonicalize do |node, parent|
80
+ nil
81
+ end
82
+ assert_equal '', c14n
83
+ end
84
+
85
+ def test_exclude_block_object
86
+ xml = '<a><b></b></a>'
87
+ doc = Nokogiri.XML xml
88
+
89
+ c14n = doc.canonicalize do |node, parent|
90
+ Object.new
91
+ end
92
+ assert_equal xml, c14n
93
+ end
94
+
95
+ def test_c14n_node
96
+ xml = '<a><b><c></c></b></a>'
97
+ doc = Nokogiri.XML xml
98
+ c14n = doc.at_xpath('//b').canonicalize
99
+ assert_equal '<b><c></c></b>', c14n
100
+ end
101
+
102
+ def test_c14n_modes
103
+ skip("C14N Exclusive implementation will complete by next version after 1.5.1") if Nokogiri.jruby?
104
+ # http://www.w3.org/TR/xml-exc-c14n/#sec-Enveloping
105
+
106
+ doc1 = Nokogiri.XML <<-eoxml
107
+ <n0:local xmlns:n0="http://foobar.org" xmlns:n3="ftp://example.org">
108
+ <n1:elem2 xmlns:n1="http://example.net" xml:lang="en">
109
+ <n3:stuff xmlns:n3="ftp://example.org"/>
110
+ </n1:elem2>
111
+ </n0:local>
112
+ eoxml
113
+ doc2 = Nokogiri.XML <<-eoxml
114
+ <n2:pdu xmlns:n1="http://example.com"
115
+ xmlns:n2="http://foo.example"
116
+ xml:lang="fr"
117
+ xml:space="retain">
118
+ <n1:elem2 xmlns:n1="http://example.net" xml:lang="en">
119
+ <n3:stuff xmlns:n3="ftp://example.org"/>
120
+ </n1:elem2>
121
+ </n2:pdu>
122
+ eoxml
123
+
124
+ c14n = doc1.at_xpath('//n1:elem2', {'n1' => 'http://example.net'}).canonicalize
125
+ assert_equal '<n1:elem2 xmlns:n0="http://foobar.org" xmlns:n1="http://example.net" xmlns:n3="ftp://example.org" xml:lang="en">
126
+ <n3:stuff></n3:stuff>
127
+ </n1:elem2>', c14n
128
+ c14n = doc2.at_xpath('//n1:elem2', {'n1' => 'http://example.net'}).canonicalize
129
+ assert_equal '<n1:elem2 xmlns:n1="http://example.net" xmlns:n2="http://foo.example" xml:lang="en" xml:space="retain">
130
+ <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
131
+ </n1:elem2>', c14n
132
+
133
+ excl_c14n = '<n1:elem2 xmlns:n1="http://example.net" xml:lang="en">
134
+ <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
135
+ </n1:elem2>'
136
+ c14n = doc1.at_xpath('//n1:elem2', {'n1' => 'http://example.net'}).canonicalize(XML::XML_C14N_EXCLUSIVE_1_0)
137
+ assert_equal excl_c14n, c14n
138
+ c14n = doc2.at_xpath('//n1:elem2', {'n1' => 'http://example.net'}).canonicalize(XML::XML_C14N_EXCLUSIVE_1_0)
139
+ assert_equal excl_c14n, c14n
140
+
141
+ c14n = doc2.at_xpath('//n1:elem2', {'n1' => 'http://example.net'}).canonicalize(XML::XML_C14N_EXCLUSIVE_1_0, ['n2'])
142
+ assert_equal '<n1:elem2 xmlns:n1="http://example.net" xmlns:n2="http://foo.example" xml:lang="en">
143
+ <n3:stuff xmlns:n3="ftp://example.org"></n3:stuff>
144
+ </n1:elem2>', c14n
145
+
146
+ end
147
+
148
+
149
+ end
150
+ end
151
+ end
@@ -51,6 +51,14 @@ module Nokogiri
51
51
  assert_equal @xml, txt.document
52
52
  end
53
53
 
54
+ def test_create_text_node_with_block
55
+ @xml.create_text_node 'foo' do |txt|
56
+ assert_instance_of Nokogiri::XML::Text, txt
57
+ assert_equal 'foo', txt.text
58
+ assert_equal @xml, txt.document
59
+ end
60
+ end
61
+
54
62
  def test_create_element
55
63
  elm = @xml.create_element('foo')
56
64
  assert_instance_of Nokogiri::XML::Element, elm
@@ -58,6 +66,14 @@ module Nokogiri
58
66
  assert_equal @xml, elm.document
59
67
  end
60
68
 
69
+ def test_create_element_with_block
70
+ @xml.create_element('foo') do |elm|
71
+ assert_instance_of Nokogiri::XML::Element, elm
72
+ assert_equal 'foo', elm.name
73
+ assert_equal @xml, elm.document
74
+ end
75
+ end
76
+
61
77
  def test_create_element_with_attributes
62
78
  elm = @xml.create_element('foo',:a => "1")
63
79
  assert_instance_of Nokogiri::XML::Element, elm
@@ -70,6 +86,11 @@ module Nokogiri
70
86
  assert_equal 'http://tenderlovemaking.com', elm.namespaces['xmlns:foo']
71
87
  end
72
88
 
89
+ def test_create_element_with_hyphenated_namespace
90
+ elm = @xml.create_element('foo',:'xmlns:SOAP-ENC' => 'http://tenderlovemaking.com')
91
+ assert_equal 'http://tenderlovemaking.com', elm.namespaces['xmlns:SOAP-ENC']
92
+ end
93
+
73
94
  def test_create_element_with_content
74
95
  elm = @xml.create_element('foo',"needs more xml/violence")
75
96
  assert_equal "needs more xml/violence", elm.content
@@ -81,6 +102,26 @@ module Nokogiri
81
102
  assert_equal "abc", cdata.content
82
103
  end
83
104
 
105
+ def test_create_cdata_with_block
106
+ @xml.create_cdata("abc") do |cdata|
107
+ assert_instance_of Nokogiri::XML::CDATA, cdata
108
+ assert_equal "abc", cdata.content
109
+ end
110
+ end
111
+
112
+ def test_create_comment
113
+ comment = @xml.create_comment("abc")
114
+ assert_instance_of Nokogiri::XML::Comment, comment
115
+ assert_equal "abc", comment.content
116
+ end
117
+
118
+ def test_create_comment_with_block
119
+ @xml.create_comment("abc") do |comment|
120
+ assert_instance_of Nokogiri::XML::Comment, comment
121
+ assert_equal "abc", comment.content
122
+ end
123
+ end
124
+
84
125
  def test_pp
85
126
  out = StringIO.new('')
86
127
  assert_nothing_raised do
@@ -204,6 +245,13 @@ module Nokogiri
204
245
  end
205
246
  end
206
247
 
248
+ def test_add_child_with_string
249
+ doc = Nokogiri::XML::Document.new
250
+ doc.add_child "<div>quack!</div>"
251
+ assert_equal 1, doc.root.children.length
252
+ assert_equal "quack!", doc.root.children.first.content
253
+ end
254
+
207
255
  def test_move_root_to_document_with_no_root
208
256
  sender = Nokogiri::XML('<root>foo</root>')
209
257
  newdoc = Nokogiri::XML::Document.new
@@ -65,6 +65,11 @@ module Nokogiri
65
65
  ns = @xml.root.add_namespace_definition('baz', 'bar')
66
66
  assert_equal 'baz', ns.prefix
67
67
  end
68
+
69
+ def test_remove_entity_namespace
70
+ s = %q{<?xml version='1.0'?><!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "XMLSchema.dtd" [<!ENTITY % p ''>]>}
71
+ Nokogiri::XML(s).remove_namespaces!
72
+ end
68
73
  end
69
74
  end
70
75
  end
@@ -125,6 +125,13 @@ module Nokogiri
125
125
  @xml.root.parse('<hello>')
126
126
  assert(error_count < @xml.errors.length, "errors should have increased")
127
127
  end
128
+
129
+ def test_parse_error_on_fragment_with_empty_document
130
+ doc = Document.new
131
+ fragment = DocumentFragment.new(doc, '<foo><bar/></foo>')
132
+ node = fragment%'bar'
133
+ node.parse('<baz><</baz>')
134
+ end
128
135
 
129
136
  def test_subclass_dup
130
137
  subclass = Class.new(Nokogiri::XML::Node)
@@ -209,6 +216,13 @@ module Nokogiri
209
216
  end
210
217
  end
211
218
 
219
+ def test_append_with_attr
220
+ r = Nokogiri.XML('<r a="1" />').root
221
+ assert_raises(ArgumentError) do
222
+ r << r.at_xpath('@a')
223
+ end
224
+ end
225
+
212
226
  def test_inspect_ns
213
227
  xml = Nokogiri::XML(<<-eoxml) { |c| c.noblanks }
214
228
  <root xmlns="http://tenderlovemaking.com/" xmlns:foo="bar">
@@ -592,6 +606,19 @@ module Nokogiri
592
606
  assert_nil address['domestic']
593
607
  end
594
608
 
609
+ def test_attribute_setter_accepts_non_string
610
+ address = @xml.xpath("/staff/employee/address").first
611
+ assert_equal "Yes", address[:domestic]
612
+ address[:domestic] = "Altered Yes"
613
+ assert_equal "Altered Yes", address[:domestic]
614
+ end
615
+
616
+ def test_attribute_accessor_accepts_non_string
617
+ address = @xml.xpath("/staff/employee/address").first
618
+ assert_equal "Yes", address["domestic"]
619
+ assert_equal "Yes", address[:domestic]
620
+ end
621
+
595
622
  def test_delete
596
623
  address = @xml.xpath('/staff/employee/address').first
597
624
  assert_equal 'Yes', address['domestic']
@@ -807,6 +834,46 @@ module Nokogiri
807
834
  assert_equal 1, tires.length
808
835
  end
809
836
 
837
+ def test_namespaced_attribute_search_with_xpath
838
+ # from #593
839
+ xmlContent = <<-EOXML
840
+ <?xml version="1.0"?>
841
+ <ns1:el1 xmlns:ns1="http://blabla.com" >
842
+ <ns1:el2 ns1:att="123">with namespace</ns1:el2 >
843
+ <ns1:el2 att="noNameSpace">no namespace</ns1:el2 >
844
+ </ns1:el1>
845
+ EOXML
846
+ xml_doc = Nokogiri::XML(xmlContent)
847
+
848
+ no_ns = xml_doc.xpath("//*[@att]")
849
+ assert_equal no_ns.length, 1
850
+ assert_equal no_ns.first.content, "no namespace"
851
+
852
+ with_ns = xml_doc.xpath("//*[@ns1:att]")
853
+ assert_equal with_ns.length, 1
854
+ assert_equal with_ns.first.content, "with namespace"
855
+ end
856
+
857
+ def test_namespaced_attribute_search_with_css
858
+ # from #593
859
+ xmlContent = <<-EOXML
860
+ <?xml version="1.0"?>
861
+ <ns1:el1 xmlns:ns1="http://blabla.com" >
862
+ <ns1:el2 ns1:att="123">with namespace</ns1:el2 >
863
+ <ns1:el2 att="noNameSpace">no namespace</ns1:el2 >
864
+ </ns1:el1>
865
+ EOXML
866
+ xml_doc = Nokogiri::XML(xmlContent)
867
+
868
+ no_ns = xml_doc.css('*[att]')
869
+ assert_equal no_ns.length, 1
870
+ assert_equal no_ns.first.content, "no namespace"
871
+
872
+ with_ns = xml_doc.css('*[ns1|att]')
873
+ assert_equal with_ns.length, 1
874
+ assert_equal with_ns.first.content, "with namespace"
875
+ end
876
+
810
877
  def test_namespaces_should_include_all_namespace_definitions
811
878
  xml = Nokogiri::XML.parse(<<-EOF)
812
879
  <x xmlns="http://quux.com/" xmlns:a="http://foo.com/" xmlns:b="http://bar.com/">
@@ -854,7 +921,7 @@ module Nokogiri
854
921
  <b:div>hello b</b:div>
855
922
  <c:div>hello c</c:div>
856
923
  <div>hello moon</div>
857
- </y>
924
+ </y>
858
925
  </x>
859
926
  EOF
860
927
  set = xml.search("//y/*")
@@ -912,6 +979,20 @@ module Nokogiri
912
979
  assert_equal @xml, node_set.document
913
980
  assert node_set.respond_to?(:awesome!)
914
981
  end
982
+
983
+ def test_blank
984
+ doc = Nokogiri::XML('')
985
+ assert_equal false, doc.blank?
986
+ end
987
+
988
+ def test_to_xml_allows_to_serialize_with_as_xml_save_option
989
+ xml = Nokogiri::XML("<root><ul><li>Hello world</li></ul></root>")
990
+ set = xml.search("//ul")
991
+ node = set.first
992
+
993
+ assert_no_match("<ul>\n <li>", xml.to_xml(:save_with => XML::Node::SaveOptions::AS_XML))
994
+ assert_no_match("<ul>\n <li>", node.to_xml(:save_with => XML::Node::SaveOptions::AS_XML))
995
+ end
915
996
  end
916
997
  end
917
998
  end
@@ -29,6 +29,25 @@ module Nokogiri
29
29
  assert node.namespaced_key?('foo', nil)
30
30
  assert !node.namespaced_key?('foo', 'foo')
31
31
  end
32
+
33
+ def test_set_attribute_frees_nodes # testing a segv
34
+ skip("JRuby doesn't do GC.") if Nokogiri.jruby?
35
+ document = Nokogiri::XML.parse("<foo></foo>")
36
+
37
+ node = document.root
38
+ node['visible'] = 'foo'
39
+ attribute = node.attribute('visible')
40
+ text = Nokogiri::XML::Text.new 'bar', document
41
+ attribute.add_child(text)
42
+
43
+ begin
44
+ gc_previous = GC.stress
45
+ GC.stress = true
46
+ node['visible'] = 'attr'
47
+ ensure
48
+ GC.stress = gc_previous
49
+ end
50
+ end
32
51
  end
33
52
  end
34
53
  end
@@ -0,0 +1,32 @@
1
+ # issue#560
2
+
3
+ require 'helper'
4
+
5
+ module Nokogiri
6
+ module XML
7
+ class TestNodeInheritance < Nokogiri::TestCase
8
+ MyNode = Class.new Nokogiri::XML::Node
9
+ def setup
10
+ super
11
+ @node = MyNode.new 'foo', Nokogiri::XML::Document.new
12
+ @node['foo'] = 'bar'
13
+ end
14
+
15
+ def test_node_name
16
+ assert @node.name == 'foo'
17
+ end
18
+
19
+ def test_node_writing_an_attribute_accessing_via_attributes
20
+ assert @node.attributes['foo']
21
+ end
22
+
23
+ def test_node_writing_an_attribute_accessing_via_key
24
+ assert @node.key? 'foo'
25
+ end
26
+
27
+ def test_node_writing_an_attribute_accessing_via_brackets
28
+ assert @node['foo'] == 'bar'
29
+ end
30
+ end
31
+ end
32
+ end