libxml-ruby 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +28 -3
- data/LICENSE +2 -2
- data/README +21 -6
- data/Rakefile +13 -8
- data/TODO +5 -12
- data/ext/xml/extconf.rb +17 -17
- data/ext/xml/libxml.c +2 -2
- data/ext/xml/libxml.h +5 -2
- data/ext/xml/libxml.rb +107 -0
- data/ext/xml/ruby_xml_dtd.c +3 -3
- data/ext/xml/ruby_xml_node.c +112 -25
- data/ext/xml/ruby_xml_node_set.c +61 -10
- data/ext/xml/ruby_xml_parser.c +62 -8
- data/ext/xml/ruby_xml_sax_parser.c +298 -53
- data/ext/xml/ruby_xml_sax_parser.h +32 -1
- data/ext/xml/ruby_xml_schema.c +1 -1
- data/ext/xml/ruby_xml_schema.h +1 -1
- data/ext/xml/ruby_xml_xpath.c +7 -1
- data/ext/xml/ruby_xml_xpath_context.c +2 -1
- data/ext/xml/ruby_xml_xpath_context.h +2 -2
- data/ext/xml/ruby_xml_xpointer_context.c +1 -2
- data/ext/xml/sax_parser_callbacks.inc +202 -0
- data/tests/copy_bug.rb +1 -2
- data/tests/dtd-test.rb +1 -1
- data/tests/libxml_test.rb +2 -0
- data/tests/model/saxtest.xml +5 -0
- data/tests/runner.rb +2 -4
- data/tests/schema-test.rb +1 -1
- data/tests/tc_xml_document.rb +2 -2
- data/tests/tc_xml_document_write.rb +2 -2
- data/tests/tc_xml_document_write2.rb +2 -2
- data/tests/tc_xml_document_write3.rb +2 -2
- data/tests/tc_xml_node.rb +2 -2
- data/tests/tc_xml_node2.rb +2 -2
- data/tests/tc_xml_node3.rb +28 -0
- data/tests/tc_xml_node4.rb +84 -0
- data/tests/tc_xml_node_set.rb +2 -2
- data/tests/tc_xml_node_set2.rb +38 -0
- data/tests/tc_xml_node_xlink.rb +2 -2
- data/tests/tc_xml_parser.rb +2 -2
- data/tests/tc_xml_parser2.rb +2 -2
- data/tests/tc_xml_parser3.rb +2 -2
- data/tests/tc_xml_parser4.rb +2 -2
- data/tests/tc_xml_parser5.rb +2 -2
- data/tests/tc_xml_parser6.rb +2 -2
- data/tests/tc_xml_parser7.rb +2 -2
- data/tests/tc_xml_parser8.rb +32 -0
- data/tests/tc_xml_parser_context.rb +2 -2
- data/tests/tc_xml_xinclude.rb +2 -2
- data/tests/tc_xml_xpath.rb +3 -2
- data/tests/tc_xml_xpointer.rb +3 -2
- data/tests/test_xml_sax_parser.rb +64 -0
- metadata +13 -6
- data/tests/tc_default_validation.rb +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: ruby_xml_sax_parser.h,v 1.
|
1
|
+
/* $Id: ruby_xml_sax_parser.h,v 1.2 2006/04/14 14:45:52 roscopeco Exp $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
@@ -7,9 +7,40 @@
|
|
7
7
|
|
8
8
|
extern VALUE cXMLSaxParser;
|
9
9
|
|
10
|
+
typedef struct ruby_xml_sax_parser_callbacks {
|
11
|
+
VALUE internalSubset;
|
12
|
+
VALUE isStandalone;
|
13
|
+
VALUE hasInternalSubset;
|
14
|
+
VALUE hasExternalSubset;
|
15
|
+
VALUE resolveEntity;
|
16
|
+
VALUE getEntity;
|
17
|
+
VALUE entityDecl;
|
18
|
+
VALUE notationDecl;
|
19
|
+
VALUE attributeDecl;
|
20
|
+
VALUE elementDecl;
|
21
|
+
VALUE unparsedEntityDecl;
|
22
|
+
VALUE setDocumentLocator;
|
23
|
+
VALUE startDocument;
|
24
|
+
VALUE endDocument;
|
25
|
+
VALUE startElement;
|
26
|
+
VALUE endElement;
|
27
|
+
VALUE reference;
|
28
|
+
VALUE characters;
|
29
|
+
VALUE ignorableWhitespace;
|
30
|
+
VALUE processingInstruction;
|
31
|
+
VALUE comment;
|
32
|
+
VALUE xmlParserWarning;
|
33
|
+
VALUE xmlParserError;
|
34
|
+
VALUE xmlParserFatalError;
|
35
|
+
VALUE getParameterEntity;
|
36
|
+
VALUE cdataBlock;
|
37
|
+
VALUE externalSubset;
|
38
|
+
} ruby_xml_sax_parser_callbacks;
|
39
|
+
|
10
40
|
typedef struct ruby_xml_sax_parser {
|
11
41
|
xmlParserCtxtPtr xpc;
|
12
42
|
xmlSAXHandlerPtr xsh;
|
43
|
+
ruby_xml_sax_parser_callbacks *cbp;
|
13
44
|
VALUE filename;
|
14
45
|
VALUE str;
|
15
46
|
} ruby_xml_sax_parser;
|
data/ext/xml/ruby_xml_schema.c
CHANGED
data/ext/xml/ruby_xml_schema.h
CHANGED
data/ext/xml/ruby_xml_xpath.c
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
-
/* $Id: ruby_xml_xpath.c,v 1.
|
1
|
+
/* $Id: ruby_xml_xpath.c,v 1.2 2006/04/14 14:45:25 roscopeco Exp $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
5
5
|
#include "libxml.h"
|
6
6
|
#include "ruby_xml_xpath.h"
|
7
7
|
|
8
|
+
/*
|
9
|
+
* Document-class: XML::XPath
|
10
|
+
*
|
11
|
+
* Includes Enumerable.
|
12
|
+
*/
|
8
13
|
VALUE cXMLXPath;
|
9
14
|
VALUE eXMLXPathInvalidPath;
|
10
15
|
|
@@ -330,6 +335,7 @@ ruby_xml_xpath_string(VALUE self) {
|
|
330
335
|
void
|
331
336
|
ruby_init_xml_xpath(void) {
|
332
337
|
cXMLXPath = rb_define_class_under(mXML, "XPath", rb_cObject);
|
338
|
+
rb_include_module(cXMLNode, rb_const_get(rb_cObject, rb_intern("Enumerable")));
|
333
339
|
|
334
340
|
eXMLXPathInvalidPath = rb_define_class_under(cXMLXPath,
|
335
341
|
"InvalidPath", rb_eException);
|
@@ -1,10 +1,11 @@
|
|
1
|
-
/* $Id: ruby_xml_xpath_context.c,v 1.
|
1
|
+
/* $Id: ruby_xml_xpath_context.c,v 1.2 2006/02/27 12:55:32 roscopeco Exp $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
5
5
|
#include "libxml.h"
|
6
6
|
#include "ruby_xml_xpath_context.h"
|
7
7
|
|
8
|
+
VALUE cXMLXPathContext;
|
8
9
|
|
9
10
|
/*
|
10
11
|
* call-seq:
|
@@ -1,11 +1,11 @@
|
|
1
|
-
/* $Id: ruby_xml_xpath_context.h,v 1.
|
1
|
+
/* $Id: ruby_xml_xpath_context.h,v 1.2 2006/02/27 12:55:32 roscopeco Exp $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
5
5
|
#ifndef __RUBY_XML_XPATH_CONTEXT__
|
6
6
|
#define __RUBY_XML_XPATH_CONTEXT__
|
7
7
|
|
8
|
-
VALUE cXMLXPathContext;
|
8
|
+
extern VALUE cXMLXPathContext;
|
9
9
|
|
10
10
|
typedef struct ruby_xml_xpath_context {
|
11
11
|
VALUE xd;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/* $Id: ruby_xml_xpointer_context.c,v 1.
|
1
|
+
/* $Id: ruby_xml_xpointer_context.c,v 1.2 2006/02/27 12:55:32 roscopeco Exp $ */
|
2
2
|
|
3
3
|
/* Please see the LICENSE file for copyright and distribution information */
|
4
4
|
|
@@ -6,7 +6,6 @@
|
|
6
6
|
#include "ruby_xml_xpointer_context.h"
|
7
7
|
|
8
8
|
VALUE cXMLXPointerContext;
|
9
|
-
VALUE eXMLXPointehContextInvalidPath;
|
10
9
|
VALUE eXMLXPointerContextInvalidPath;
|
11
10
|
|
12
11
|
// Rdoc needs to know
|
@@ -0,0 +1,202 @@
|
|
1
|
+
/* $Id: sax_parser_callbacks.inc,v 1.1 2006/04/14 14:50:58 roscopeco Exp $ */
|
2
|
+
|
3
|
+
/* Please see the LICENSE file for copyright and distribution information */
|
4
|
+
|
5
|
+
/*
|
6
|
+
* SAX CALLBACK HANDLERS
|
7
|
+
*/
|
8
|
+
static void internal_subset_func(ruby_xml_sax_parser_callbacks *cbp,
|
9
|
+
const char *name,
|
10
|
+
const char *extid,
|
11
|
+
const char *sysid) {
|
12
|
+
VALUE handler = cbp->internalSubset;
|
13
|
+
|
14
|
+
if (handler && handler != Qnil) {
|
15
|
+
rb_funcall(handler, callsym, 3, rb_str_new2(name),
|
16
|
+
rb_str_new2(extid), rb_str_new2(sysid));
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
static void is_standalone_func(ruby_xml_sax_parser_callbacks *cbp) {
|
21
|
+
VALUE handler = cbp->isStandalone;
|
22
|
+
|
23
|
+
if (handler && handler != Qnil) {
|
24
|
+
rb_funcall(handler,callsym,0);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
static void has_internal_subset_func(ruby_xml_sax_parser_callbacks *cbp) {
|
29
|
+
VALUE handler = cbp->hasInternalSubset;
|
30
|
+
|
31
|
+
if (handler && handler != Qnil) {
|
32
|
+
rb_funcall(handler,callsym,0);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
static void has_external_subset_func(ruby_xml_sax_parser_callbacks *cbp) {
|
37
|
+
VALUE handler = cbp->hasExternalSubset;
|
38
|
+
|
39
|
+
if (handler && handler != Qnil) {
|
40
|
+
rb_funcall(handler,callsym,0);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
static void start_document_func(ruby_xml_sax_parser_callbacks *cbp) {
|
45
|
+
VALUE handler = cbp->startDocument;
|
46
|
+
|
47
|
+
if (handler && handler != Qnil) {
|
48
|
+
rb_funcall(handler,callsym,0);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
static void end_document_func(ruby_xml_sax_parser_callbacks *cbp) {
|
53
|
+
VALUE handler = cbp->endDocument;
|
54
|
+
|
55
|
+
if (handler && handler != Qnil) {
|
56
|
+
rb_funcall(handler,callsym,0);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
static void start_element_func(ruby_xml_sax_parser_callbacks *cbp,
|
61
|
+
const char *name, const char **attrs) {
|
62
|
+
VALUE handler = cbp->startElement;
|
63
|
+
VALUE ahsh = rb_hash_new();
|
64
|
+
const char *attr, *value;
|
65
|
+
|
66
|
+
if (attrs) {
|
67
|
+
while ((attr = *(attrs++))) {
|
68
|
+
value = *(attrs++);
|
69
|
+
rb_hash_aset(ahsh, rb_str_new2(attr), rb_str_new2(value));
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
if (handler && handler != Qnil) {
|
74
|
+
rb_funcall(handler,callsym,2,rb_str_new2(name),ahsh);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
static void end_element_func(ruby_xml_sax_parser_callbacks *cbp,
|
79
|
+
const char *name) {
|
80
|
+
VALUE handler = cbp->endElement;
|
81
|
+
|
82
|
+
if (handler && handler != Qnil) {
|
83
|
+
rb_funcall(handler,callsym,1,rb_str_new2(name));
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
static void reference_func(ruby_xml_sax_parser_callbacks *cbp,
|
88
|
+
const char *name) {
|
89
|
+
VALUE handler = cbp->reference;
|
90
|
+
|
91
|
+
if (handler && handler != Qnil) {
|
92
|
+
rb_funcall(handler,callsym,1,rb_str_new2(name));
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
static void characters_func(ruby_xml_sax_parser_callbacks *cbp,
|
97
|
+
const char *chars, int len) {
|
98
|
+
VALUE handler = cbp->characters;
|
99
|
+
|
100
|
+
if (handler && handler != Qnil) {
|
101
|
+
rb_funcall(handler,callsym,1,rb_str_new(chars, len));
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
static void processing_instruction_func(ruby_xml_sax_parser_callbacks *cbp,
|
106
|
+
const char *target, const char *data) {
|
107
|
+
VALUE handler = cbp->processingInstruction;
|
108
|
+
|
109
|
+
if (handler && handler != Qnil) {
|
110
|
+
rb_funcall(handler, callsym, 2,
|
111
|
+
rb_str_new2(target),rb_str_new2(data));
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
static void comment_func(ruby_xml_sax_parser_callbacks *cbp,
|
116
|
+
const char *msg) {
|
117
|
+
VALUE handler = cbp->comment;
|
118
|
+
|
119
|
+
if (handler && handler != Qnil) {
|
120
|
+
rb_funcall(handler,callsym,1,rb_str_new2(msg));
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
// TODO these next three should actually be formatting messages.
|
125
|
+
static void warning_func(ruby_xml_sax_parser_callbacks *cbp,
|
126
|
+
const char *msg, ...) {
|
127
|
+
VALUE handler = cbp->xmlParserWarning;
|
128
|
+
|
129
|
+
if (handler && handler != Qnil) {
|
130
|
+
rb_funcall(handler,callsym,1,rb_str_new2(msg));
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
static void error_func(ruby_xml_sax_parser_callbacks *cbp,
|
135
|
+
const char *msg, ...) {
|
136
|
+
VALUE handler = cbp->xmlParserError;
|
137
|
+
|
138
|
+
if (handler && handler != Qnil) {
|
139
|
+
rb_funcall(handler,callsym,1,rb_str_new2(msg));
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
static void fatal_error_func(ruby_xml_sax_parser_callbacks *cbp,
|
144
|
+
const char *msg, ...) {
|
145
|
+
VALUE handler = cbp->xmlParserFatalError;
|
146
|
+
|
147
|
+
if (handler && handler != Qnil) {
|
148
|
+
rb_funcall(handler,callsym,1,rb_str_new2(msg));
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
static void cdata_block_func(ruby_xml_sax_parser_callbacks *cbp,
|
153
|
+
const char *value, int len) {
|
154
|
+
VALUE handler = cbp->cdataBlock;
|
155
|
+
|
156
|
+
if (handler && handler != Qnil) {
|
157
|
+
rb_funcall(handler,callsym,1,rb_str_new(value, len));
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
static void external_subset_func(ruby_xml_sax_parser_callbacks *cbp,
|
162
|
+
const char *name,
|
163
|
+
const char *extid,
|
164
|
+
const char *sysid) {
|
165
|
+
VALUE handler = cbp->externalSubset;
|
166
|
+
|
167
|
+
if (handler && handler != Qnil) {
|
168
|
+
rb_funcall(handler, callsym, 3, rb_str_new2(name),
|
169
|
+
rb_str_new2(extid), rb_str_new2(sysid));
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
static xmlSAXHandler rubySAXHandlerStruct = {
|
174
|
+
(internalSubsetSAXFunc)internal_subset_func,
|
175
|
+
(isStandaloneSAXFunc)is_standalone_func,
|
176
|
+
(hasInternalSubsetSAXFunc)has_internal_subset_func,
|
177
|
+
(hasExternalSubsetSAXFunc)has_external_subset_func,
|
178
|
+
0, /* resolveEntity */
|
179
|
+
0, /* getEntity */
|
180
|
+
0, /* entityDecl */
|
181
|
+
0, /* notationDecl */
|
182
|
+
0, /* attributeDecl */
|
183
|
+
0, /* elementDecl */
|
184
|
+
0, /* unparsedEntityDecl */
|
185
|
+
0, /* setDocumentLocator */
|
186
|
+
(startDocumentSAXFunc)start_document_func,
|
187
|
+
(endDocumentSAXFunc)end_document_func,
|
188
|
+
(startElementSAXFunc)start_element_func,
|
189
|
+
(endElementSAXFunc)end_element_func,
|
190
|
+
(referenceSAXFunc)reference_func,
|
191
|
+
(charactersSAXFunc)characters_func,
|
192
|
+
0, /* ignorableWhitespace */
|
193
|
+
(processingInstructionSAXFunc)processing_instruction_func,
|
194
|
+
(commentSAXFunc)comment_func,
|
195
|
+
(warningSAXFunc)warning_func,
|
196
|
+
(errorSAXFunc)error_func,
|
197
|
+
(fatalErrorSAXFunc)fatal_error_func,
|
198
|
+
0, /* xmlGetParameterEntity */
|
199
|
+
(cdataBlockSAXFunc)cdata_block_func,
|
200
|
+
(externalSubsetSAXFunc)external_subset_func,
|
201
|
+
1
|
202
|
+
};
|
data/tests/copy_bug.rb
CHANGED
data/tests/dtd-test.rb
CHANGED
data/tests/runner.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
3
|
# Allsuite for Eclipse and GEM.
|
4
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
5
|
+
require "libxml_test"
|
4
6
|
|
5
7
|
ALL_TESTS = true
|
6
8
|
TESTS = File.expand_path(File.dirname(__FILE__))
|
7
|
-
HOME = File.expand_path(File.join(TESTS,'../ext/xml'))
|
8
|
-
|
9
|
-
#$LOAD_PATH.unshift(HOME)
|
10
|
-
require "#{HOME}/libxml"
|
11
9
|
|
12
10
|
glob = File.join(TESTS, ENV['TESTS'] || 'tc_*.rb')
|
13
11
|
Dir[glob].each { |fn| require fn }
|
data/tests/schema-test.rb
CHANGED
data/tests/tc_xml_document.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# $Id: tc_xml_document.rb,v 1.
|
1
|
+
# $Id: tc_xml_document.rb,v 1.3 2006/04/17 13:30:20 roscopeco Exp $
|
2
2
|
require 'test/unit'
|
3
|
-
require "
|
3
|
+
require "libxml_test"
|
4
4
|
|
5
5
|
class TC_XML_Document < Test::Unit::TestCase
|
6
6
|
def setup()
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# $Id: tc_xml_document_write.rb,v 1.
|
2
|
-
require "
|
1
|
+
# $Id: tc_xml_document_write.rb,v 1.3 2006/04/17 13:30:19 roscopeco Exp $
|
2
|
+
require "libxml_test"
|
3
3
|
require 'test/unit'
|
4
4
|
|
5
5
|
class TC_XML_Document_Write < Test::Unit::TestCase
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# $Id: tc_xml_document_write2.rb,v 1.
|
2
|
-
require "
|
1
|
+
# $Id: tc_xml_document_write2.rb,v 1.3 2006/04/17 13:30:18 roscopeco Exp $
|
2
|
+
require "libxml_test"
|
3
3
|
require 'test/unit'
|
4
4
|
|
5
5
|
class TC_XML_Document_Write2 < Test::Unit::TestCase
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# $Id: tc_xml_document_write3.rb,v 1.
|
2
|
-
require "
|
1
|
+
# $Id: tc_xml_document_write3.rb,v 1.3 2006/04/17 13:30:22 roscopeco Exp $
|
2
|
+
require "libxml_test"
|
3
3
|
require 'test/unit'
|
4
4
|
|
5
5
|
class TC_XML_Document_Write3 < Test::Unit::TestCase
|
data/tests/tc_xml_node.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# $Id: tc_xml_node.rb,v 1.
|
2
|
-
require "
|
1
|
+
# $Id: tc_xml_node.rb,v 1.3 2006/04/17 13:30:19 roscopeco Exp $
|
2
|
+
require "libxml_test"
|
3
3
|
require 'test/unit'
|
4
4
|
|
5
5
|
class TC_XML_Node < Test::Unit::TestCase
|
data/tests/tc_xml_node2.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# $Id: tc_xml_node2.rb,v 1.
|
2
|
-
require "
|
1
|
+
# $Id: tc_xml_node2.rb,v 1.3 2006/04/17 13:30:19 roscopeco Exp $
|
2
|
+
require "libxml_test"
|
3
3
|
require 'test/unit'
|
4
4
|
|
5
5
|
class TC_XML_Node2 < Test::Unit::TestCase
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# $Id: tc_xml_node3.rb,v 1.2 2006/04/17 13:30:22 roscopeco Exp $
|
2
|
+
require "libxml_test"
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class TC_XML_Node2 < Test::Unit::TestCase
|
6
|
+
def setup()
|
7
|
+
xp = XML::Parser.new()
|
8
|
+
str = '<ruby_array uga="booga" foo="bar"><fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>'
|
9
|
+
assert_equal(str, xp.string = str)
|
10
|
+
doc = xp.parse
|
11
|
+
assert_instance_of(XML::Document, doc)
|
12
|
+
assert_instance_of(XML::Node, doc.root)
|
13
|
+
@root = doc.root
|
14
|
+
assert_instance_of(XML::Node, @root)
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown()
|
18
|
+
@root = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_xml_node_doc_content()
|
22
|
+
assert_equal 'onetwo', @root.content
|
23
|
+
first = @root.child
|
24
|
+
|
25
|
+
assert_equal 'one', first.content
|
26
|
+
assert_equal 'two', first.next.content
|
27
|
+
end
|
28
|
+
end
|