undies 2.2.0 → 2.2.1
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/Gemfile.lock +4 -1
- data/README.rdoc +22 -1
- data/bench/bench_runner.rb +42 -61
- data/lib/undies/element.rb +51 -32
- data/lib/undies/node.rb +62 -11
- data/lib/undies/node_stack.rb +111 -0
- data/lib/undies/output.rb +9 -32
- data/lib/undies/template.rb +83 -25
- data/lib/undies/version.rb +1 -1
- data/test/element_test.rb +69 -48
- data/test/fixtures/write_thing.rb +21 -0
- data/test/node_stack_test.rb +109 -0
- data/test/node_test.rb +66 -16
- data/test/output_test.rb +13 -73
- data/test/template_builder_render_test.rb +32 -0
- data/test/template_source_render_test.rb +115 -0
- data/test/template_test.rb +149 -167
- data/undies.gemspec +1 -0
- metadata +32 -11
- data/lib/undies/node_buffer.rb +0 -35
- data/test/node_buffer_test.rb +0 -54
data/lib/undies/template.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'undies/source_stack'
|
2
|
+
require 'undies/node_stack'
|
2
3
|
require 'undies/output'
|
4
|
+
|
3
5
|
require 'undies/node'
|
4
6
|
require 'undies/element'
|
5
7
|
|
6
|
-
|
7
8
|
module Undies
|
8
9
|
class Template
|
9
10
|
|
@@ -11,12 +12,16 @@ module Undies
|
|
11
12
|
# polluting the public instance methods, the instance scope, and to
|
12
13
|
# maximize the effectiveness of the Template#method_missing logic
|
13
14
|
|
14
|
-
def self.
|
15
|
-
template.instance_variable_get("@
|
15
|
+
def self.source_stack(template)
|
16
|
+
template.instance_variable_get("@_undies_source_stack")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.node_stack(template)
|
20
|
+
template.instance_variable_get("@_undies_node_stack")
|
16
21
|
end
|
17
22
|
|
18
23
|
def self.flush(template)
|
19
|
-
template
|
24
|
+
node_stack(template).flush
|
20
25
|
end
|
21
26
|
|
22
27
|
# Ripped from Rack v1.3.0 ======================================
|
@@ -37,38 +42,82 @@ module Undies
|
|
37
42
|
# end Rip from Rack v1.3.0 =====================================
|
38
43
|
|
39
44
|
def initialize(*args)
|
40
|
-
|
45
|
+
# setup a node stack with the given output obj
|
46
|
+
output = if args.last.kind_of?(NodeStack) || args.last.kind_of?(Output)
|
41
47
|
args.pop
|
42
48
|
else
|
43
49
|
raise ArgumentError, "please provide an Output object"
|
44
50
|
end
|
45
|
-
|
46
|
-
source = args.last.kind_of?(Source) ? args.pop : Source.new(Proc.new {})
|
47
|
-
|
48
|
-
# setup the source stack and output objects
|
49
|
-
@_undies_source_stack = SourceStack.new(source)
|
51
|
+
@_undies_node_stack = NodeStack.create(output)
|
50
52
|
|
51
|
-
# apply data to template scope
|
53
|
+
# apply any given data to template scope
|
54
|
+
data = args.last.kind_of?(::Hash) ? args.pop : {}
|
52
55
|
if (data.keys.map(&:to_s) & self.public_methods.map(&:to_s)).size > 0
|
53
56
|
raise ArgumentError, "data conflicts with template public methods."
|
54
57
|
end
|
55
58
|
metaclass = class << self; self; end
|
56
59
|
data.each {|key, value| metaclass.class_eval { define_method(key){value} }}
|
57
60
|
|
58
|
-
#
|
59
|
-
|
61
|
+
# setup a source stack with the given source
|
62
|
+
source = args.last.kind_of?(Source) ? args.pop : Source.new(Proc.new {})
|
63
|
+
@_undies_source_stack = SourceStack.new(source)
|
60
64
|
|
61
65
|
# yield to recursivley render the source stack
|
62
66
|
self.__yield
|
63
67
|
|
64
|
-
# flush any
|
68
|
+
# flush any elements that need to be built
|
69
|
+
self.class.flush(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
# call this to modify element attrs inside a build block. Once content
|
73
|
+
# or child elements have been added, any '__attr' directives will
|
74
|
+
# be ignored b/c the elements start_tag has already been flushed
|
75
|
+
# to the output
|
76
|
+
def __attrs(attrs_hash={})
|
77
|
+
self.class.node_stack(self).current.tap do |node|
|
78
|
+
if node
|
79
|
+
node.class.merge_attrs(node, attrs_hash)
|
80
|
+
node.class.set_start_tag(node)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# call this method to manually push the currently cached node onto the
|
86
|
+
# node stack
|
87
|
+
# - implicitly flushes the cache
|
88
|
+
# - changes the context of template method calls to operate on that node
|
89
|
+
def __push
|
90
|
+
ns = self.class.node_stack(self)
|
91
|
+
node, ns.cached_node = ns.cached_node, nil
|
92
|
+
if node
|
93
|
+
# add an empty build block to generate a non-closing start tag
|
94
|
+
# and a closing end tag
|
95
|
+
node.class.add_build(node, Proc.new {})
|
96
|
+
node.class.set_start_tag(node)
|
97
|
+
node.class.set_end_tag(node)
|
98
|
+
|
99
|
+
ns.push(node)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# call this method to manually pop the current scoped node from the node stack
|
104
|
+
# - flushes the cache
|
105
|
+
# - changes the context of template method calls to operate on the parent node
|
106
|
+
def __pop
|
107
|
+
ns = self.class.node_stack(self)
|
108
|
+
ns.clear_cached
|
109
|
+
ns.pop
|
110
|
+
end
|
111
|
+
|
112
|
+
# call this to manually flush a template
|
113
|
+
def __flush
|
65
114
|
self.class.flush(self)
|
66
115
|
end
|
67
116
|
|
68
117
|
# call this to render template source
|
69
118
|
# use this method in layouts to insert a layout's content source
|
70
119
|
def __yield
|
71
|
-
return if
|
120
|
+
return if self.class.node_stack(self).nil? || (source = self.class.source_stack(self).pop).nil?
|
72
121
|
if source.file?
|
73
122
|
instance_eval(source.data, source.source, 1)
|
74
123
|
else
|
@@ -79,23 +128,32 @@ module Undies
|
|
79
128
|
# call this to render partial source embedded in a template
|
80
129
|
# partial source is rendered with its own scope/data but shares
|
81
130
|
# its parent template's output object
|
82
|
-
def __partial(source, data)
|
83
|
-
|
131
|
+
def __partial(source, data={})
|
132
|
+
if source.kind_of?(Source)
|
133
|
+
Undies::Template.new(source, data, self.class.node_stack(self))
|
134
|
+
else
|
135
|
+
self.__ source.to_s, :partial
|
136
|
+
end
|
84
137
|
end
|
85
138
|
|
86
139
|
# Add a text node (data escaped) to the nodes of the current node
|
87
|
-
def _(data=""
|
140
|
+
def _(data="", mode=:inline)
|
141
|
+
self.__ self.class.escape_html(data.to_s), mode
|
142
|
+
end
|
88
143
|
|
89
144
|
# Add a text node with the data un-escaped
|
90
|
-
def __(data=""
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
@_undies_output.node(Node.new(data.to_s, :force_pp => true))
|
145
|
+
def __(data="", mode=:inline)
|
146
|
+
Node.new(data.to_s, mode).tap do |node|
|
147
|
+
self.class.node_stack(self).node(node)
|
148
|
+
end
|
95
149
|
end
|
96
150
|
|
97
|
-
# Add an element to the
|
98
|
-
def element(*args, &
|
151
|
+
# Add an element to the node stack
|
152
|
+
def element(*args, &build)
|
153
|
+
Element.new(*args, &build).tap do |element|
|
154
|
+
self.class.node_stack(self).node(element)
|
155
|
+
end
|
156
|
+
end
|
99
157
|
alias_method :tag, :element
|
100
158
|
|
101
159
|
# Element proxy methods ('_<element>'') ========================
|
data/lib/undies/version.rb
CHANGED
data/test/element_test.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
require "assert"
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'undies/node'
|
4
|
+
require "undies/output"
|
4
5
|
require "undies/template"
|
5
6
|
|
7
|
+
require "undies/element"
|
8
|
+
|
9
|
+
|
6
10
|
class Undies::Element
|
7
11
|
|
8
12
|
class BasicTests < Assert::Context
|
@@ -12,19 +16,37 @@ class Undies::Element
|
|
12
16
|
end
|
13
17
|
subject { @e }
|
14
18
|
|
15
|
-
should have_class_methods :hash_attrs
|
16
|
-
should have_instance_method :to_str
|
19
|
+
should have_class_methods :hash_attrs
|
20
|
+
should have_instance_method :prefix, :to_str
|
17
21
|
|
18
22
|
should "be a Node" do
|
19
23
|
assert_kind_of Undies::Node, subject
|
20
24
|
end
|
21
25
|
|
22
|
-
should "store
|
26
|
+
should "store its name as a string" do
|
23
27
|
assert_equal "div", subject.instance_variable_get("@name")
|
24
28
|
end
|
25
29
|
|
30
|
+
should "know its name" do
|
31
|
+
assert_equal "div", subject.class.node_name(subject)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "know its start/end tags" do
|
35
|
+
assert_equal "<div />", subject.class.start_tag(subject)
|
36
|
+
assert_empty subject.class.end_tag(subject)
|
37
|
+
end
|
38
|
+
|
26
39
|
should "have no content itself" do
|
27
|
-
|
40
|
+
assert_empty subject.class.content(subject)
|
41
|
+
end
|
42
|
+
|
43
|
+
should "have no builds by default" do
|
44
|
+
assert_empty subject.class.builds(subject)
|
45
|
+
assert_empty subject.class.builds(nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
should "have no children by default" do
|
49
|
+
assert_equal false, subject.class.children(subject)
|
28
50
|
end
|
29
51
|
|
30
52
|
end
|
@@ -73,6 +95,7 @@ class Undies::Element
|
|
73
95
|
end
|
74
96
|
end
|
75
97
|
|
98
|
+
|
76
99
|
class CSSProxyTests < BasicTests
|
77
100
|
|
78
101
|
should "respond to any method ending in '!' as an id proxy" do
|
@@ -82,68 +105,62 @@ class Undies::Element
|
|
82
105
|
should "proxy id attr with methods ending in '!'" do
|
83
106
|
assert_equal({
|
84
107
|
:id => 'thing1'
|
85
|
-
}, subject.thing1
|
108
|
+
}, subject.class.attrs(subject.thing1!))
|
86
109
|
end
|
87
110
|
|
88
111
|
should "proxy id attr with last method call ending in '!'" do
|
89
112
|
assert_equal({
|
90
113
|
:id => 'thing2'
|
91
|
-
}, subject.thing1!.thing2
|
114
|
+
}, subject.class.attrs(subject.thing1!.thing2!))
|
92
115
|
end
|
93
116
|
|
94
117
|
should "set id attr to explicit if called last " do
|
95
118
|
assert_equal({
|
96
119
|
:id => 'thing3'
|
97
|
-
}, subject.thing1!.thing2!(:id => 'thing3')
|
120
|
+
}, subject.class.attrs(subject.thing1!.thing2!(:id => 'thing3')))
|
98
121
|
end
|
99
122
|
|
100
123
|
should "set id attr to proxy if called last" do
|
101
124
|
assert_equal({
|
102
125
|
:id => 'thing1'
|
103
|
-
}, subject.thing2!(:id => 'thing3').thing1
|
126
|
+
}, subject.class.attrs(subject.thing2!(:id => 'thing3').thing1!))
|
104
127
|
end
|
105
128
|
|
106
129
|
should "respond to any other method as a class proxy" do
|
107
|
-
|
130
|
+
assert_respond_to :asdgasdg, subject
|
108
131
|
end
|
109
132
|
|
110
133
|
should "proxy single html class attr" do
|
111
134
|
assert_equal({
|
112
135
|
:class => 'thing'
|
113
|
-
}, subject.
|
136
|
+
}, subject.class.attrs(subject.thing))
|
114
137
|
end
|
115
138
|
|
116
139
|
should "proxy multi html class attrs" do
|
117
140
|
assert_equal({
|
118
141
|
:class => 'list thing awesome'
|
119
|
-
}, subject.list.thing.awesome
|
142
|
+
}, subject.class.attrs(subject.list.thing.awesome))
|
120
143
|
end
|
121
144
|
|
122
145
|
should "set class attr with explicit if called last " do
|
123
146
|
assert_equal({
|
124
147
|
:class => 'list'
|
125
|
-
}, subject.thing.awesome(:class => "list")
|
148
|
+
}, subject.class.attrs(subject.thing.awesome(:class => "list")))
|
126
149
|
end
|
127
150
|
|
128
151
|
should "update class attr with proxy if called last" do
|
129
152
|
assert_equal({
|
130
153
|
:class => 'list is good'
|
131
|
-
}, subject.thing.awesome(:class => "list is").good
|
154
|
+
}, subject.class.attrs(subject.thing.awesome(:class => "list is").good))
|
132
155
|
end
|
133
156
|
|
134
157
|
should "proxy mixed class and id selector attrs" do
|
158
|
+
subject.thing1!.awesome({:class => "list is", :id => "thing2"}).good.thing3!
|
159
|
+
|
135
160
|
assert_equal({
|
136
161
|
:class => 'list is good',
|
137
162
|
:id => "thing3"
|
138
|
-
}, subject.
|
139
|
-
:class => "list is",
|
140
|
-
:id => "thing2"
|
141
|
-
}).good.thing3!.instance_variable_get("@attrs"))
|
142
|
-
end
|
143
|
-
|
144
|
-
should "not proxy if private methods are called" do
|
145
|
-
assert_equal "<div />", subject.send(:start_tag)
|
146
|
-
assert_equal nil, subject.send(:end_tag)
|
163
|
+
}, subject.class.attrs(subject))
|
147
164
|
end
|
148
165
|
|
149
166
|
end
|
@@ -154,58 +171,58 @@ class Undies::Element
|
|
154
171
|
end
|
155
172
|
|
156
173
|
should "serialize with no child elements" do
|
157
|
-
|
174
|
+
Undies::Template.new(Undies::Source.new do
|
158
175
|
element(:br)
|
159
|
-
end
|
160
|
-
|
176
|
+
end, {}, @output)
|
177
|
+
|
161
178
|
assert_equal "<br />", @out
|
162
179
|
end
|
163
180
|
|
164
181
|
should "serialize with attrs" do
|
165
|
-
|
182
|
+
Undies::Template.new(Undies::Source.new do
|
166
183
|
element(:br, :class => 'big')
|
167
|
-
end
|
168
|
-
|
184
|
+
end, {}, @output)
|
185
|
+
|
169
186
|
assert_equal '<br class="big" />', @out
|
170
187
|
end
|
171
188
|
|
172
189
|
should "serialize with attrs that have double-quotes" do
|
173
|
-
|
190
|
+
Undies::Template.new(Undies::Source.new do
|
174
191
|
element(:br, :class => '"this" is double-quoted')
|
175
|
-
end
|
176
|
-
|
192
|
+
end, {}, @output)
|
193
|
+
|
177
194
|
assert_equal '<br class=""this" is double-quoted" />', @out
|
178
195
|
end
|
179
196
|
|
180
197
|
should "serialize with attrs and content" do
|
181
|
-
|
198
|
+
Undies::Template.new(Undies::Source.new do
|
182
199
|
element(:strong, {:class => 'big'}) { __ "Loud Noises!" }
|
183
|
-
end
|
184
|
-
|
200
|
+
end, {}, @output)
|
201
|
+
|
185
202
|
assert_equal '<strong class="big">Loud Noises!</strong>', @out
|
186
203
|
end
|
187
204
|
|
188
205
|
should "serialize element proxy id call" do
|
189
|
-
|
206
|
+
Undies::Template.new(Undies::Source.new do
|
190
207
|
element(:div).thing1! { _ "stuff" }
|
191
|
-
end
|
192
|
-
|
208
|
+
end, {}, @output)
|
209
|
+
|
193
210
|
assert_equal "<div id=\"thing1\">stuff</div>", @out
|
194
211
|
end
|
195
212
|
|
196
213
|
should "serialize element proxy class call" do
|
197
|
-
|
214
|
+
Undies::Template.new(Undies::Source.new do
|
198
215
|
element(:div).thing { _ "stuff" }
|
199
|
-
end
|
200
|
-
|
216
|
+
end, {}, @output)
|
217
|
+
|
201
218
|
assert_equal "<div class=\"thing\">stuff</div>", @out
|
202
219
|
end
|
203
220
|
|
204
221
|
should "serialize content from separate content blocks" do
|
205
|
-
|
222
|
+
Undies::Template.new(Undies::Source.new do
|
206
223
|
element(:div){ _ "stuff" }.thing1!{ _ " and more stuff" }
|
207
|
-
end
|
208
|
-
|
224
|
+
end, {}, @output)
|
225
|
+
|
209
226
|
assert_equal "<div id=\"thing1\">stuff and more stuff</div>", @out
|
210
227
|
end
|
211
228
|
|
@@ -216,14 +233,18 @@ class Undies::Element
|
|
216
233
|
element(:span) { _ "Content!" }
|
217
234
|
__ "Raw"
|
218
235
|
element(:span) { _ "More content" }
|
236
|
+
element(:div).hi {
|
237
|
+
_ "first build"
|
238
|
+
}.there.you! {
|
239
|
+
_ "second build"
|
240
|
+
}
|
219
241
|
}
|
220
242
|
end
|
221
243
|
templ = Undies::Template.new(src, {}, output)
|
222
|
-
assert_equal "
|
223
|
-
<
|
224
|
-
<span>Content!</span>
|
225
|
-
Raw
|
244
|
+
assert_equal "<div>
|
245
|
+
<span>Content!</span>Raw
|
226
246
|
<span>More content</span>
|
247
|
+
<div class=\"hi there\" id=\"you\">first buildsecond build</div>
|
227
248
|
</div>", @out
|
228
249
|
end
|
229
250
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class WriteThing
|
2
|
+
|
3
|
+
# this is used in testing the write buffer
|
4
|
+
|
5
|
+
def self.hi(thing)
|
6
|
+
'hi'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.hello(thing)
|
10
|
+
'hello'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.hithere(thing)
|
14
|
+
'hithere'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.prefix(thing, meth, level, indent)
|
18
|
+
"#{level > 0 ? "\n": ''}#{' '*level*indent}"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'assert'
|
2
|
+
|
3
|
+
require 'undies/node'
|
4
|
+
require 'undies/element'
|
5
|
+
require 'test/fixtures/write_thing'
|
6
|
+
|
7
|
+
require 'undies/node_stack'
|
8
|
+
|
9
|
+
module Undies
|
10
|
+
|
11
|
+
class NodeStackTests < Assert::Context
|
12
|
+
desc "a NodeStack"
|
13
|
+
before do
|
14
|
+
@hello = Node.new "hello"
|
15
|
+
@something = Node.new "something else"
|
16
|
+
@hi = Node.new("hi")
|
17
|
+
@br = Element.new :br
|
18
|
+
@div = Element.new(:div) {}
|
19
|
+
|
20
|
+
@outstream = StringIO.new(@out = "")
|
21
|
+
@stream_test_output = Output.new(@outstream)
|
22
|
+
@ns = NodeStack.new @stream_test_output
|
23
|
+
end
|
24
|
+
subject { @ns }
|
25
|
+
|
26
|
+
should have_class_method :create
|
27
|
+
should have_readers :stack, :cached_node, :output
|
28
|
+
should have_instance_methods :current, :size, :level, :empty?, :first, :last
|
29
|
+
should have_instance_methods :push, :pop, :node, :flush
|
30
|
+
should have_instance_methods :clear_cached
|
31
|
+
|
32
|
+
should "be empty by default" do
|
33
|
+
assert_empty subject
|
34
|
+
end
|
35
|
+
|
36
|
+
should "have an empty cache by default" do
|
37
|
+
assert_nil subject.cached_node
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class StackTests < NodeStackTests
|
44
|
+
|
45
|
+
should "push nodes onto the stack" do
|
46
|
+
assert_nothing_raised do
|
47
|
+
subject.push(@hello)
|
48
|
+
subject.push(@something)
|
49
|
+
end
|
50
|
+
|
51
|
+
assert_equal 2, subject.size
|
52
|
+
end
|
53
|
+
|
54
|
+
should "know its level (should be one less than the array's size)" do
|
55
|
+
assert_equal 0, subject.level
|
56
|
+
subject.push(@hello)
|
57
|
+
assert_equal 1, subject.level
|
58
|
+
end
|
59
|
+
|
60
|
+
should "fetch the last item in the array with the current method" do
|
61
|
+
subject.push(@hello)
|
62
|
+
subject.push(@something)
|
63
|
+
|
64
|
+
assert_same @something, subject.current
|
65
|
+
end
|
66
|
+
|
67
|
+
should "remove the last item in the array with the pop method" do
|
68
|
+
subject.push(@hello)
|
69
|
+
subject.push(@something)
|
70
|
+
|
71
|
+
assert_equal 2, subject.size
|
72
|
+
|
73
|
+
node = subject.pop
|
74
|
+
assert_same @something, node
|
75
|
+
assert_equal 1, subject.size
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
class CacheTests < NodeStackTests
|
82
|
+
|
83
|
+
should "add nodes to its cache using the #node method" do
|
84
|
+
subject.node(@hi)
|
85
|
+
assert_equal @hi, subject.cached_node
|
86
|
+
end
|
87
|
+
|
88
|
+
should "push the current cached node onto the stack when caching a new node" do
|
89
|
+
subject.node(@br)
|
90
|
+
assert_equal @br, subject.cached_node
|
91
|
+
assert_equal 0, subject.size
|
92
|
+
|
93
|
+
subject.node(@div)
|
94
|
+
assert_equal @div, subject.cached_node
|
95
|
+
end
|
96
|
+
|
97
|
+
should "call the node's builds when flushed from cache" do
|
98
|
+
build = "build"
|
99
|
+
subject.node(Element.new(:div) { build += " called" })
|
100
|
+
subject.flush
|
101
|
+
|
102
|
+
assert_equal "build called", build
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
end
|
data/test/node_test.rb
CHANGED
@@ -1,39 +1,89 @@
|
|
1
1
|
require "assert"
|
2
2
|
|
3
|
+
require "undies/output"
|
3
4
|
require "undies/node"
|
4
|
-
require "undies/node_buffer"
|
5
5
|
|
6
6
|
class Undies::Node
|
7
7
|
|
8
8
|
class BasicTests < Assert::Context
|
9
9
|
desc 'a node'
|
10
|
-
before
|
10
|
+
before do
|
11
|
+
@output = Undies::Output.new(StringIO.new(@out = ""))
|
12
|
+
@n = Undies::Node.new("a text node here")
|
13
|
+
end
|
11
14
|
subject { @n }
|
12
15
|
|
13
|
-
should have_class_methods :
|
16
|
+
should have_class_methods :start_tag, :end_tag, :set_start_tag, :set_end_tag
|
17
|
+
should have_class_methods :builds, :add_build
|
18
|
+
should have_class_methods :children, :set_children
|
19
|
+
should have_class_methods :attrs, :merge_attrs
|
20
|
+
should have_class_methods :node_name, :content, :mode, :prefix
|
21
|
+
|
22
|
+
should "have no start/end tags" do
|
23
|
+
assert_empty subject.class.start_tag(subject)
|
24
|
+
assert_empty subject.class.end_tag(subject)
|
25
|
+
end
|
14
26
|
|
15
|
-
should "
|
27
|
+
should "have content" do
|
16
28
|
assert_equal "a text node here", subject.class.content(subject)
|
17
29
|
end
|
18
30
|
|
19
|
-
should "
|
20
|
-
|
21
|
-
|
31
|
+
should "have no builds" do
|
32
|
+
assert_empty subject.class.builds(subject)
|
33
|
+
end
|
34
|
+
|
35
|
+
should "be :inline mode by default" do
|
36
|
+
assert_equal :inline, subject.class.mode(subject)
|
37
|
+
end
|
38
|
+
|
39
|
+
should "have no prefix if :inline mode" do
|
40
|
+
assert_empty subject.class.prefix(subject, 'start_tag', 2, 2)
|
41
|
+
assert_empty subject.class.prefix(subject, 'end_tag', 1, 2)
|
42
|
+
end
|
43
|
+
|
44
|
+
should "have a pp prefix if not :inline mode" do
|
45
|
+
node = Undies::Node.new("a non inline node", :partial)
|
46
|
+
assert_equal "\n ", node.class.prefix(node, 'start_tag', 2, 2)
|
47
|
+
assert_equal "\n ", node.class.prefix(node, 'end_tag', 2, 2)
|
48
|
+
assert_equal "\n ", node.class.prefix(node, 'start_tag', 1, 2)
|
49
|
+
assert_equal "\n", node.class.prefix(node, 'end_tag', 1, 2)
|
50
|
+
assert_equal "", node.class.prefix(node, 'start_tag', 0, 2)
|
51
|
+
assert_equal "\n", node.class.prefix(node, 'end_tag', 0, 2)
|
22
52
|
end
|
23
53
|
|
24
|
-
should "
|
25
|
-
|
26
|
-
|
54
|
+
should "have no children by default" do
|
55
|
+
assert_equal false, subject.class.children(subject)
|
56
|
+
end
|
57
|
+
|
58
|
+
should "have no attrs by default" do
|
59
|
+
assert_empty subject.class.attrs(subject)
|
60
|
+
end
|
61
|
+
|
62
|
+
should "have no name by default" do
|
63
|
+
assert_empty subject.class.node_name(subject)
|
64
|
+
end
|
65
|
+
|
66
|
+
should "add a build if given a block" do
|
67
|
+
subject.class.add_build(subject, Proc.new {})
|
68
|
+
assert_equal [Proc.new {}], subject.class.builds(subject)
|
69
|
+
|
70
|
+
subject.class.add_build(subject, Proc.new {})
|
71
|
+
assert_equal [Proc.new {}, Proc.new {}], subject.class.builds(subject)
|
72
|
+
end
|
27
73
|
|
28
|
-
|
74
|
+
should "set children if given a value" do
|
75
|
+
subject.class.set_children(subject, true)
|
76
|
+
assert_equal true, subject.class.children(subject)
|
29
77
|
end
|
30
78
|
|
31
|
-
should "
|
32
|
-
|
33
|
-
|
34
|
-
|
79
|
+
should "merge attrs if given an attrs hash" do
|
80
|
+
attrs_hash = {:same => 'value', :new => 'a new value'}
|
81
|
+
subject.class.merge_attrs(subject, attrs_hash)
|
82
|
+
assert_equal attrs_hash, subject.class.attrs(subject)
|
35
83
|
|
36
|
-
|
84
|
+
attrs_hash = {:same => 'new same', :new => 'a new value'}
|
85
|
+
subject.class.merge_attrs(subject, attrs_hash)
|
86
|
+
assert_equal attrs_hash, subject.class.attrs(subject)
|
37
87
|
end
|
38
88
|
|
39
89
|
end
|