radius 0.0.2 → 0.5.0

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.
Files changed (9) hide show
  1. data/CHANGELOG +12 -0
  2. data/QUICKSTART +232 -45
  3. data/README +61 -15
  4. data/ROADMAP +4 -10
  5. data/Rakefile +50 -8
  6. data/lib/radius.rb +415 -75
  7. data/test/radius_test.rb +263 -113
  8. metadata +3 -4
  9. data/DSL-SPEC +0 -151
@@ -1,84 +1,54 @@
1
1
  require 'test/unit'
2
2
  require 'radius'
3
3
 
4
- class TestContext < Radius::Context
5
- def initialize
6
- @prefix = "test"
7
- @items = ["Larry", "Moe", "Curly"]
8
- end
9
-
10
- def echo(attr)
11
- attr["text"]
12
- end
13
-
14
- def add(attr)
15
- (attr["param1"].to_i + attr["param2"].to_i).to_s
16
- end
17
-
18
- def reverse(attr)
19
- yield.reverse
20
- end
4
+ module RadiusTestHelper
5
+ class TestContext < Radius::Context; end
21
6
 
22
- def capitalize(attr)
23
- yield.upcase
24
- end
25
-
26
- def count(attr)
27
- case
28
- when attr["set"]
29
- @count = attr["set"].to_i
30
- ""
31
- when attr["inc"] == "true"
32
- @count = (@count || 0) + 1
33
- ""
34
- else
35
- @count.to_s
7
+ def new_context
8
+ Radius::Context.new do |c|
9
+ c.define_tag("reverse" ) { |tag| tag.expand.reverse }
10
+ c.define_tag("capitalize") { |tag| tag.expand.upcase }
11
+ c.define_tag("attr") { |tag| tag.attr.inspect }
36
12
  end
37
13
  end
38
14
 
39
- def repeat(attr)
40
- string = ''
41
- (attr['count'] || '1').to_i.times { string << yield }
42
- string
43
- end
44
-
45
- def each_item(attr)
46
- result = []
47
- @items.each { |@item| result << yield }
48
- @item = nil
49
- result.join(attr["between"] || "")
50
- end
51
-
52
- def item(attr)
53
- @item
54
- end
55
-
56
- def hello(attr)
57
- "Hello #{attr['name'] || 'World'}!"
15
+ def define_tag(name, options = {}, &block)
16
+ @context.define_tag name, options, &block
58
17
  end
59
18
  end
60
19
 
61
20
  class RadiusContextTest < Test::Unit::TestCase
21
+ include RadiusTestHelper
22
+
62
23
  def setup
63
- @context = TestContext.new
24
+ @context = new_context
64
25
  end
65
26
 
66
27
  def test_initialize
67
28
  @context = Radius::Context.new
68
- assert_equal 'radius', @context.prefix
69
29
  end
70
30
 
71
- def test_render_tag__individual
72
- text = @context.render_tag('hello')
73
- assert_equal('Hello World!', text)
74
-
75
- text = @context.render_tag('hello', 'name' => 'John')
76
- assert_equal('Hello John!', text)
31
+ def test_initialize_with_block
32
+ @context = Radius::Context.new do |c|
33
+ assert_kind_of Radius::Context, c
34
+ c.define_tag('test') { 'just a test' }
35
+ end
36
+ assert_not_equal Hash.new, @context.definitions
37
+ end
38
+
39
+ def test_with
40
+ got = @context.with do |c|
41
+ assert_equal @context, c
42
+ end
43
+ assert_equal @context, got
77
44
  end
78
45
 
79
- def test_render_tag__container
80
- text = @context.render_tag('repeat', 'count' => '5') { 'o' }
81
- assert_equal('ooooo', text)
46
+ def test_render_tag
47
+ define_tag "hello" do |tag|
48
+ "Hello #{tag.attr['name'] || 'World'}!"
49
+ end
50
+ assert_render_tag_output 'Hello World!', 'hello'
51
+ assert_render_tag_output 'Hello John!', 'hello', 'name' => 'John'
82
52
  end
83
53
 
84
54
  def test_render_tag__undefined_tag
@@ -86,14 +56,6 @@ class RadiusContextTest < Test::Unit::TestCase
86
56
  assert_equal "undefined tag `undefined_tag'", e.message
87
57
  end
88
58
 
89
- def test_render_tag__undefined_tag_with_wrong_signature
90
- class << @context
91
- def helper_method
92
- end
93
- end
94
- assert_raises(Radius::UndefinedTagError) { @context.render_tag('helper_method') }
95
- end
96
-
97
59
  def test_tag_missing
98
60
  class << @context
99
61
  def tag_missing(tag, attr, &block)
@@ -102,68 +64,256 @@ class RadiusContextTest < Test::Unit::TestCase
102
64
  end
103
65
 
104
66
  text = ''
105
- assert_nothing_raised { text = @context.render_tag('undefined_tag', 'cool' => 'beans') }
106
-
107
67
  expected = %{undefined tag `undefined_tag' with attributes {"cool"=>"beans"}}
68
+ assert_nothing_raised { text = @context.render_tag('undefined_tag', 'cool' => 'beans') }
108
69
  assert_equal expected, text
109
70
  end
71
+
72
+ private
73
+
74
+ def assert_render_tag_output(output, *render_tag_params)
75
+ assert_equal output, @context.render_tag(*render_tag_params)
76
+ end
77
+
110
78
  end
111
79
 
112
80
  class RadiusParserTest < Test::Unit::TestCase
81
+ include RadiusTestHelper
82
+
113
83
  def setup
114
- @t = Radius::Parser.new(TestContext.new )
84
+ @context = new_context
85
+ @parser = Radius::Parser.new(@context, :tag_prefix => 'r')
115
86
  end
116
87
 
117
- def test_parse_individual
118
- r = @t.parse_individual(%{<<test:echo text="hello world!" />>})
119
- assert_equal("<hello world!>", r)
120
-
121
- r = @t.parse_individual(%{<test:add param1="1" param2='2'/>})
122
- assert_equal("3", r)
123
-
124
- r = @t.parse_individual(%{a <test:echo text="3 + 1 =" /> <test:add param1="3" param2="1"/> b})
125
- assert_equal("a 3 + 1 = 4 b", r)
88
+ def test_initialize
89
+ @parser = Radius::Parser.new
90
+ assert_kind_of Radius::Context, @parser.context
91
+ end
92
+
93
+ def test_initialize_with_params
94
+ @parser = Radius::Parser.new(TestContext.new)
95
+ assert_kind_of TestContext, @parser.context
96
+
97
+ @parser = Radius::Parser.new(:context => TestContext.new)
98
+ assert_kind_of TestContext, @parser.context
99
+
100
+ @parser = Radius::Parser.new('context' => TestContext.new)
101
+ assert_kind_of TestContext, @parser.context
102
+
103
+ @parser = Radius::Parser.new(:tag_prefix => 'r')
104
+ assert_kind_of Radius::Context, @parser.context
105
+ assert_equal 'r', @parser.tag_prefix
106
+
107
+ @parser = Radius::Parser.new(TestContext.new, :tag_prefix => 'r')
108
+ assert_kind_of TestContext, @parser.context
109
+ assert_equal 'r', @parser.tag_prefix
110
+ end
111
+
112
+ def test_parse_individual_tags_and_parameters
113
+ define_tag "add" do |tag|
114
+ tag.attr["param1"].to_i + tag.attr["param2"].to_i
115
+ end
116
+ assert_parse_output "<3>", %{<<r:add param1="1" param2='2'/>>}
126
117
  end
127
118
 
128
119
  def test_parse_attributes
129
- r = @t.parse_attributes(%{ a="1" b='2'c="3"d="'" })
130
- assert_equal({"a" => "1", "b" => "2", "c" => "3", "d" => "'"}, r)
120
+ attributes = %{{"a"=>"1", "b"=>"2", "c"=>"3", "d"=>"'"}}
121
+ assert_parse_output attributes, %{<r:attr a="1" b='2'c="3"d="'" />}
122
+ assert_parse_output attributes, %{<r:attr a="1" b='2'c="3"d="'"></r:attr>}
131
123
  end
132
124
 
133
- def test_parse
134
- r = @t.parse(%{<<test:echo text="hello world!" />>})
135
- assert_equal("<hello world!>", r)
136
-
137
- r = @t.parse("<test:reverse>test</test:reverse>")
138
- assert_equal("test".reverse, r)
139
-
140
- r = @t.parse("<test:reverse>test</test:reverse> <test:capitalize>test</test:capitalize>")
141
- assert_equal("tset TEST", r)
142
-
143
- r = @t.parse("<test:echo text='hello world!' /> cool: <test:reverse>a <test:capitalize>test</test:capitalize> b</test:reverse> !")
144
- assert_equal("hello world! cool: b TSET a !", r)
125
+ def test_parse_attributes_with_slashes_or_angle_brackets
126
+ slash = %{{"slash"=>"/"}}
127
+ angle = %{{"angle"=>">"}}
128
+ assert_parse_output slash, %{<r:attr slash="/"></r:attr>}
129
+ assert_parse_output slash, %{<r:attr slash="/"><r:attr /></r:attr>}
130
+ assert_parse_output angle, %{<r:attr angle=">"></r:attr>}
131
+ end
132
+
133
+ def test_things_that_should_be_left_alone
134
+ # The parser currently fails on these assertions
135
+ #assert_parsed_either_way_is_unchanged %{ test="2"="4" }
136
+ #assert_parsed_either_way_is_unchanged %{="2" }
137
+ end
145
138
 
146
- r = @t.parse("<test:reverse><test:echo text='hello world!' /></test:reverse>")
147
- assert_equal("!dlrow olleh", r)
148
-
149
- r = @t.parse("<test:reverse><test:capitalize>test</test:capitalize> <test:echo text='hello world!' /></test:reverse>")
150
- assert_equal("!dlrow olleh TSET", r)
151
-
152
- r = @t.parse("<test:reverse>12<test:capitalize>at</test:capitalize>34</test:reverse>")
153
- assert_equal("43TA21", r)
139
+ def test_parse_result_is_always_a_string
140
+ define_tag("twelve") { 12 }
141
+ assert_parse_output "12", "<r:twelve />"
154
142
  end
155
- def test_parse__looping
156
- r = @t.parse(%{<test:count set="0" /><test:repeat count="5"><test:count inc="true" /><test:count /></test:repeat>})
157
- assert_equal("12345", r)
158
-
159
- r = @t.parse(%{Three Stooges: <test:each_item between=", ">"<test:item />"</test:each_item>})
160
- assert_equal(%{Three Stooges: "Larry", "Moe", "Curly"}, r)
143
+
144
+ def test_parse_double_tags
145
+ assert_parse_output "test".reverse, "<r:reverse>test</r:reverse>"
146
+ assert_parse_output "tset TEST", "<r:reverse>test</r:reverse> <r:capitalize>test</r:capitalize>"
147
+ end
148
+
149
+ def test_parse_tag_nesting
150
+ define_tag("parent", :for => '')
151
+ define_tag("parent:child", :for => '')
152
+ define_tag("extra", :for => '')
153
+ define_tag("nesting") { |tag| tag.nesting }
154
+ define_tag("extra:nesting") { |tag| tag.nesting.gsub(':', ' > ') }
155
+ define_tag("parent:child:nesting") { |tag| tag.nesting.gsub(':', ' * ') }
156
+ assert_parse_output "nesting", "<r:nesting />"
157
+ assert_parse_output "parent:nesting", "<r:parent:nesting />"
158
+ assert_parse_output "extra > nesting", "<r:extra:nesting />"
159
+ assert_parse_output "parent * child * nesting", "<r:parent:child:nesting />"
160
+ assert_parse_output "parent > extra > nesting", "<r:parent:extra:nesting />"
161
+ assert_parse_output "parent > child > extra > nesting", "<r:parent:child:extra:nesting />"
162
+ assert_parse_output "parent * extra * child * nesting", "<r:parent:extra:child:nesting />"
163
+ assert_parse_output "parent > extra > child > extra > nesting", "<r:parent:extra:child:extra:nesting />"
164
+ assert_parse_output "parent > extra > child > extra > nesting", "<r:parent><r:extra><r:child><r:extra><r:nesting /></r:extra></r:child></r:extra></r:parent>"
165
+ assert_parse_output "extra * parent * child * nesting", "<r:extra:parent:child:nesting />"
166
+ assert_parse_output "extra > parent > nesting", "<r:extra><r:parent:nesting /></r:extra>"
167
+ assert_parse_output "extra * parent * child * nesting", "<r:extra:parent><r:child:nesting /></r:extra:parent>"
168
+ assert_raises(Radius::UndefinedTagError) { @parser.parse("<r:child />") }
169
+ end
170
+
171
+ def test_parse_tag_nesting_2
172
+ define_tag("parent", :for => '')
173
+ define_tag("parent:child", :for => '')
174
+ define_tag "content" do |tag|
175
+ tag.nesting
176
+ end
177
+ assert_parse_output 'parent:child:content', '<r:parent><r:child:content /></r:parent>'
178
+ end
179
+
180
+ def test_parse_tag__binding_do_missing
181
+ define_tag 'test' do |tag|
182
+ tag.missing!
183
+ end
184
+ e = assert_raises(Radius::UndefinedTagError) { @parser.parse("<r:test />") }
185
+ assert_equal "undefined tag `test'", e.message
186
+ end
187
+
188
+ def test_parse_tag__binding_render_tag
189
+ define_tag('test') { |tag| "Hello #{tag.attr['name']}!" }
190
+ define_tag('hello') { |tag| tag.render('test', tag.attr) }
191
+ assert_parse_output 'Hello John!', '<r:hello name="John" />'
192
+ end
193
+ def test_parse_tag__binding_render_tag_with_block
194
+ define_tag('test') { |tag| "Hello #{tag.expand}!" }
195
+ define_tag('hello') { |tag| tag.render('test') { tag.expand } }
196
+ assert_parse_output 'Hello John!', '<r:hello>John</r:hello>'
197
+ end
198
+
199
+ def test_tag_locals
200
+ define_tag "outer" do |tag|
201
+ tag.locals.var = 'outer'
202
+ tag.expand
203
+ end
204
+ define_tag "outer:inner" do |tag|
205
+ tag.locals.var = 'inner'
206
+ tag.expand
207
+ end
208
+ define_tag "outer:var" do |tag|
209
+ tag.locals.var
210
+ end
211
+ assert_parse_output 'outer', "<r:outer><r:var /></r:outer>"
212
+ assert_parse_output 'outer:inner:outer', "<r:outer><r:var />:<r:inner><r:var /></r:inner>:<r:var /></r:outer>"
213
+ assert_parse_output 'outer:inner:outer:inner:outer', "<r:outer><r:var />:<r:inner><r:var />:<r:outer><r:var /></r:outer>:<r:var /></r:inner>:<r:var /></r:outer>"
214
+ assert_parse_output 'outer', "<r:outer:var />"
215
+ end
216
+
217
+ def test_tag_globals
218
+ define_tag "set" do |tag|
219
+ tag.globals.var = tag.attr['value']
220
+ ''
221
+ end
222
+ define_tag "var" do |tag|
223
+ tag.globals.var
224
+ end
225
+ assert_parse_output " true false", %{<r:var /> <r:set value="true" /> <r:var /> <r:set value="false" /> <r:var />}
161
226
  end
162
227
 
163
- def test_parse__fail_on_no_end_tag
164
- assert_raises(Radius::MissingEndTagError) { @t.parse("<test:reverse>") }
228
+ def test_parse_loops
229
+ @item = nil
230
+ define_tag "each" do |tag|
231
+ result = []
232
+ ["Larry", "Moe", "Curly"].each do |item|
233
+ tag.locals.item = item
234
+ result << tag.expand
235
+ end
236
+ result.join(tag.attr["between"] || "")
237
+ end
238
+ define_tag "each:item" do |tag|
239
+ tag.locals.item
240
+ end
241
+ assert_parse_output %{Three Stooges: "Larry", "Moe", "Curly"}, %{Three Stooges: <r:each between=", ">"<r:item />"</r:each>}
165
242
  end
166
- def test_parse__fail_on_no_end_tag_2
167
- assert_raises(Radius::MissingEndTagError) { @t.parse("<test:reverse><test:capitalize></test:reverse>") }
243
+
244
+ def test_tag_option_for
245
+ define_tag 'fun', :for => 'just for kicks'
246
+ assert_parse_output 'just for kicks', '<r:fun />'
168
247
  end
248
+
249
+ def test_tag_expose_option
250
+ define_tag 'user', :for => users.first, :expose => ['name', :age]
251
+ assert_parse_output 'John', '<r:user:name />'
252
+ assert_parse_output '25', '<r:user><r:age /></r:user>'
253
+ e = assert_raises(Radius::UndefinedTagError) { @parser.parse "<r:user:email />" }
254
+ assert_equal "undefined tag `email'", e.message
255
+ end
256
+
257
+ def test_tag_expose_attributes_option_on_by_default
258
+ define_tag 'user', :for => user_with_attributes
259
+ assert_parse_output 'John', '<r:user:name />'
260
+ end
261
+ def test_tag_expose_attributes_set_to_false
262
+ define_tag 'user_without_attributes', :for => user_with_attributes, :attributes => false
263
+ assert_raises(Radius::UndefinedTagError) { @parser.parse "<r:user_without_attributes:name />" }
264
+ end
265
+
266
+ def test_tag_options_must_contain_a_for_option_if_methods_are_exposed
267
+ e = assert_raises(ArgumentError) { define_tag('fun', :expose => :today) { 'test' } }
268
+ assert_equal "tag definition must contain a :for option when used with the :expose option", e.message
269
+ end
270
+
271
+ def test_parse_fail_on_missing_end_tag
272
+ assert_raises(Radius::MissingEndTagError) { @parser.parse("<r:reverse>") }
273
+ assert_raises(Radius::MissingEndTagError) { @parser.parse("<r:reverse><r:capitalize></r:reverse>") }
274
+ end
275
+
276
+ protected
277
+
278
+ def assert_parse_output(output, input, message = nil)
279
+ r = @parser.parse(input)
280
+ assert_equal(output, r, message)
281
+ end
282
+
283
+ def assert_parsed_is_unchanged(something)
284
+ assert_parse_output something, something
285
+ end
286
+
287
+ def assert_parsed_either_way_is_unchanged(middle)
288
+ assert_parsed_is_unchanged %{<r:attr#{middle}/>}
289
+ assert_parsed_is_unchanged %{<r:attr#{middle}></r:attr>}
290
+ end
291
+
292
+ class User
293
+ attr_accessor :name, :age, :email, :friend
294
+ def initialize(name, age, email)
295
+ @name, @age, @email = name, age, email
296
+ end
297
+ def <=>(other)
298
+ name <=> other.name
299
+ end
300
+ end
301
+
302
+ class UserWithAttributes < User
303
+ def attributes
304
+ { :name => name, :age => age, :email => email }
305
+ end
306
+ end
307
+
308
+ def users
309
+ [
310
+ User.new('John', 25, 'test@johnwlong.com'),
311
+ User.new('James', 27, 'test@jameslong.com')
312
+ ]
313
+ end
314
+
315
+ def user_with_attributes
316
+ UserWithAttributes.new('John', 25, 'test@johnwlong.com')
317
+ end
318
+
169
319
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: radius
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.2
7
- date: 2006-02-14
6
+ version: 0.5.0
7
+ date: 2006-05-01
8
8
  summary: Powerful tag-based template system.
9
9
  require_paths:
10
10
  - lib
@@ -29,8 +29,8 @@ platform: ruby
29
29
  authors: []
30
30
  files:
31
31
  - CHANGELOG
32
- - DSL-SPEC
33
32
  - lib
33
+ - pkg
34
34
  - QUICKSTART
35
35
  - Rakefile
36
36
  - README
@@ -49,7 +49,6 @@ extra_rdoc_files:
49
49
  - README
50
50
  - QUICKSTART
51
51
  - ROADMAP
52
- - DSL-SPEC
53
52
  - CHANGELOG
54
53
  executables: []
55
54
  extensions: []