PageRenderTime 38ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/test/parser_test.rb

http://github.com/jlong/radius
Ruby | 323 lines | 298 code | 24 blank | 1 comment | 1 complexity | 72d71f0082d088a4caf5b0c40cf89864 MD5 | raw file
  1. require File.expand_path(File.dirname(__FILE__) + '/test_helper')
  2. class RadiusParserTest < Minitest::Test
  3. include RadiusTestHelper
  4. def setup
  5. @context = new_context
  6. @parser = Radius::Parser.new(@context, :tag_prefix => 'r')
  7. end
  8. def test_initialize
  9. @parser = Radius::Parser.new
  10. assert_kind_of Radius::Context, @parser.context
  11. end
  12. def test_initialize_with_params
  13. @parser = Radius::Parser.new(TestContext.new)
  14. assert_kind_of TestContext, @parser.context
  15. @parser = Radius::Parser.new(:context => TestContext.new)
  16. assert_kind_of TestContext, @parser.context
  17. @parser = Radius::Parser.new('context' => TestContext.new)
  18. assert_kind_of TestContext, @parser.context
  19. @parser = Radius::Parser.new(:tag_prefix => 'r')
  20. assert_kind_of Radius::Context, @parser.context
  21. assert_equal 'r', @parser.tag_prefix
  22. @parser = Radius::Parser.new(TestContext.new, :tag_prefix => 'r')
  23. assert_kind_of TestContext, @parser.context
  24. assert_equal 'r', @parser.tag_prefix
  25. end
  26. def test_parse_tag_with_dashes
  27. define_tag 'some-tag' do |tag|
  28. 'ok'
  29. end
  30. assert_parse_output 'ok', '<r:some-tag>nope</r:some-tag>'
  31. end
  32. def test_parse_tag_with_dashed_attributes
  33. define_tag 'tag-with-dashed-attributes' do |tag|
  34. "dashed: #{tag.attr['data-dashed']} regular: #{tag.attr['regular']}"
  35. end
  36. assert_parse_output 'dashed: dashed-value regular: value', '<r:tag-with-dashed-attributes data-dashed="dashed-value" regular="value"></r:tag-with-dashed-attributes>'
  37. end
  38. def test_parse_individual_tags_and_parameters
  39. define_tag "add" do |tag|
  40. tag.attr["param1"].to_i + tag.attr["param2"].to_i
  41. end
  42. assert_parse_output "<3>", %{<<r:add param1="1" param2='2'/>>}
  43. end
  44. def test_parse_attributes
  45. attributes = %{{"a"=>"1", "b"=>"2", "c"=>"3", "d"=>"'"}}
  46. assert_parse_output attributes, %{<r:attr a="1" b='2'c="3"d="'" />}
  47. assert_parse_output attributes, %{<r:attr a="1" b='2'c="3"d="'"></r:attr>}
  48. end
  49. def test_parse_attributes_with_slashes_or_angle_brackets
  50. slash = %{{"slash"=>"/"}}
  51. angle = %{{"angle"=>">"}}
  52. assert_parse_output slash, %{<r:attr slash="/"></r:attr>}
  53. assert_parse_output slash, %{<r:attr slash="/"><r:attr /></r:attr>}
  54. assert_parse_output angle, %{<r:attr angle=">"></r:attr>}
  55. end
  56. def test_parse_quotes
  57. assert_parse_output "test []", %{<r:echo value="test" /> <r:wrap attr="test"></r:wrap>}
  58. end
  59. def test_things_that_should_be_left_alone
  60. [
  61. %{ test="2"="4" },
  62. %{="2" }
  63. ].each do |middle|
  64. assert_parsed_is_unchanged "<r:attr#{middle}/>"
  65. assert_parsed_is_unchanged "<r:attr#{middle}>"
  66. end
  67. end
  68. def test_tags_inside_html_tags
  69. assert_parse_output %{<div class="xzibit">tags in yo tags</div>},
  70. %{<div class="<r:reverse>tibizx</r:reverse>">tags in yo tags</div>}
  71. end
  72. def test_parse_result_is_always_a_string
  73. define_tag("twelve") { 12 }
  74. assert_parse_output "12", "<r:twelve />"
  75. end
  76. def test_parse_double_tags
  77. assert_parse_output "test".reverse, "<r:reverse>test</r:reverse>"
  78. assert_parse_output "tset TEST", "<r:reverse>test</r:reverse> <r:capitalize>test</r:capitalize>"
  79. end
  80. def test_parse_tag_nesting
  81. define_tag("parent", :for => '')
  82. define_tag("parent:child", :for => '')
  83. define_tag("extra", :for => '')
  84. define_tag("nesting") { |tag| tag.nesting }
  85. define_tag("extra:nesting") { |tag| tag.nesting.gsub(':', ' > ') }
  86. define_tag("parent:child:nesting") { |tag| tag.nesting.gsub(':', ' * ') }
  87. assert_parse_output "nesting", "<r:nesting />"
  88. assert_parse_output "parent:nesting", "<r:parent:nesting />"
  89. assert_parse_output "extra > nesting", "<r:extra:nesting />"
  90. assert_parse_output "parent * child * nesting", "<r:parent:child:nesting />"
  91. assert_parse_output "parent > extra > nesting", "<r:parent:extra:nesting />"
  92. assert_parse_output "parent > child > extra > nesting", "<r:parent:child:extra:nesting />"
  93. assert_parse_output "parent * extra * child * nesting", "<r:parent:extra:child:nesting />"
  94. assert_parse_output "parent > extra > child > extra > nesting", "<r:parent:extra:child:extra:nesting />"
  95. 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>"
  96. assert_parse_output "extra * parent * child * nesting", "<r:extra:parent:child:nesting />"
  97. assert_parse_output "extra > parent > nesting", "<r:extra><r:parent:nesting /></r:extra>"
  98. assert_parse_output "extra * parent * child * nesting", "<r:extra:parent><r:child:nesting /></r:extra:parent>"
  99. assert_raises(Radius::UndefinedTagError) { @parser.parse("<r:child />") }
  100. end
  101. def test_parse_tag_nesting_2
  102. define_tag("parent", :for => '')
  103. define_tag("parent:child", :for => '')
  104. define_tag("content") { |tag| tag.nesting }
  105. assert_parse_output 'parent:child:content', '<r:parent><r:child:content /></r:parent>'
  106. end
  107. def test_parse_tag__binding_do_missing
  108. define_tag 'test' do |tag|
  109. tag.missing!
  110. end
  111. e = assert_raises(Radius::UndefinedTagError) { @parser.parse("<r:test />") }
  112. assert_equal "undefined tag `test'", e.message
  113. end
  114. def test_parse_chirpy_bird
  115. # :> chirp chirp
  116. assert_parse_output "<:", "<:"
  117. end
  118. def test_parse_tag__binding_render_tag
  119. define_tag('test') { |tag| "Hello #{tag.attr['name']}!" }
  120. define_tag('hello') { |tag| tag.render('test', tag.attr) }
  121. assert_parse_output 'Hello John!', '<r:hello name="John" />'
  122. end
  123. def test_accessing_tag_attributes_through_tag_indexer
  124. define_tag('test') { |tag| "Hello #{tag['name']}!" }
  125. assert_parse_output 'Hello John!', '<r:test name="John" />'
  126. end
  127. def test_parse_tag__binding_render_tag_with_block
  128. define_tag('test') { |tag| "Hello #{tag.expand}!" }
  129. define_tag('hello') { |tag| tag.render('test') { tag.expand } }
  130. assert_parse_output 'Hello John!', '<r:hello>John</r:hello>'
  131. end
  132. def test_tag_locals
  133. define_tag "outer" do |tag|
  134. tag.locals.var = 'outer'
  135. tag.expand
  136. end
  137. define_tag "outer:inner" do |tag|
  138. tag.locals.var = 'inner'
  139. tag.expand
  140. end
  141. define_tag "outer:var" do |tag|
  142. tag.locals.var
  143. end
  144. assert_parse_output 'outer', "<r:outer><r:var /></r:outer>"
  145. assert_parse_output 'outer:inner:outer', "<r:outer><r:var />:<r:inner><r:var /></r:inner>:<r:var /></r:outer>"
  146. 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>"
  147. assert_parse_output 'outer', "<r:outer:var />"
  148. end
  149. def test_tag_globals
  150. define_tag "set" do |tag|
  151. tag.globals.var = tag.attr['value']
  152. ''
  153. end
  154. define_tag "var" do |tag|
  155. tag.globals.var
  156. end
  157. assert_parse_output " true false", %{<r:var /> <r:set value="true" /> <r:var /> <r:set value="false" /> <r:var />}
  158. end
  159. def test_parse_loops
  160. @item = nil
  161. define_tag "each" do |tag|
  162. result = []
  163. ["Larry", "Moe", "Curly"].each do |item|
  164. tag.locals.item = item
  165. result << tag.expand
  166. end
  167. result.join(tag.attr["between"] || "")
  168. end
  169. define_tag "each:item" do |tag|
  170. tag.locals.item
  171. end
  172. assert_parse_output %{Three Stooges: "Larry", "Moe", "Curly"}, %{Three Stooges: <r:each between=", ">"<r:item />"</r:each>}
  173. end
  174. def test_parse_speed
  175. define_tag "set" do |tag|
  176. tag.globals.var = tag.attr['value']
  177. ''
  178. end
  179. define_tag "var" do |tag|
  180. tag.globals.var
  181. end
  182. parts = %w{decima nobis augue at facer processus commodo legentis odio lectorum dolore nulla esse lius qui nonummy ullamcorper erat ii notare}
  183. multiplier = parts.map{|p| "#{p}=\"#{rand}\""}.join(' ')
  184. assert ->{
  185. Timeout.timeout(10) do
  186. assert_parse_output " false", %{<r:set value="false" #{multiplier} /> <r:var />}
  187. end
  188. }.call
  189. end
  190. def test_tag_option_for
  191. define_tag 'fun', :for => 'just for kicks'
  192. assert_parse_output 'just for kicks', '<r:fun />'
  193. end
  194. def test_tag_expose_option
  195. define_tag 'user', :for => users.first, :expose => ['name', :age]
  196. assert_parse_output 'John', '<r:user:name />'
  197. assert_parse_output '25', '<r:user><r:age /></r:user>'
  198. e = assert_raises(Radius::UndefinedTagError) { @parser.parse "<r:user:email />" }
  199. assert_equal "undefined tag `email'", e.message
  200. end
  201. def test_tag_expose_attributes_option_on_by_default
  202. define_tag 'user', :for => user_with_attributes
  203. assert_parse_output 'John', '<r:user:name />'
  204. end
  205. def test_tag_expose_attributes_set_to_false
  206. define_tag 'user_without_attributes', :for => user_with_attributes, :attributes => false
  207. assert_raises(Radius::UndefinedTagError) { @parser.parse "<r:user_without_attributes:name />" }
  208. end
  209. def test_tag_options_must_contain_a_for_option_if_methods_are_exposed
  210. e = assert_raises(ArgumentError) { define_tag('fun', :expose => :today) { 'test' } }
  211. assert_equal "tag definition must contain a :for option when used with the :expose option", e.message
  212. end
  213. def test_parse_fail_on_missing_end_tag
  214. assert_raises(Radius::MissingEndTagError) { @parser.parse("<r:reverse>") }
  215. end
  216. def test_parse_fail_on_wrong_end_tag
  217. assert_raises(Radius::WrongEndTagError) { @parser.parse("<r:reverse><r:capitalize></r:reverse>") }
  218. end
  219. def test_parse_with_default_tag_prefix
  220. @parser = Radius::Parser.new(@context)
  221. define_tag("hello") { |tag| "Hello world!" }
  222. assert_equal "<p>Hello world!</p>", @parser.parse('<p><radius:hello /></p>')
  223. end
  224. def test_parse_with_other_radius_like_tags
  225. @parser = Radius::Parser.new(@context, :tag_prefix => "ralph")
  226. define_tag('hello') { "hello" }
  227. assert_equal "<r:ralph:hello />", @parser.parse("<r:ralph:hello />")
  228. end
  229. def test_copyin_global_values
  230. @context.globals.foo = 'bar'
  231. assert_equal 'bar', Radius::Parser.new(@context).context.globals.foo
  232. end
  233. def test_does_not_pollute_copied_globals
  234. @context.globals.foo = 'bar'
  235. parser = Radius::Parser.new(@context)
  236. parser.context.globals.foo = '[baz]'
  237. assert_equal 'bar', @context.globals.foo
  238. end
  239. def test_parse_with_other_namespaces
  240. @parser = Radius::Parser.new(@context, :tag_prefix => 'r')
  241. assert_equal "<fb:test>hello world</fb:test>", @parser.parse("<fb:test>hello world</fb:test>")
  242. end
  243. protected
  244. def assert_parse_output(output, input, message = nil)
  245. r = @parser.parse(input)
  246. assert_equal(output, r, message)
  247. end
  248. def assert_parsed_is_unchanged(something)
  249. assert_parse_output something, something
  250. end
  251. class User
  252. attr_accessor :name, :age, :email, :friend
  253. def initialize(name, age, email)
  254. @name, @age, @email = name, age, email
  255. end
  256. def <=>(other)
  257. name <=> other.name
  258. end
  259. end
  260. class UserWithAttributes < User
  261. def attributes
  262. { :name => name, :age => age, :email => email }
  263. end
  264. end
  265. def users
  266. [
  267. User.new('John', 25, 'test@johnwlong.com'),
  268. User.new('James', 27, 'test@jameslong.com')
  269. ]
  270. end
  271. def user_with_attributes
  272. UserWithAttributes.new('John', 25, 'test@johnwlong.com')
  273. end
  274. end