Guest User

Untitled

a guest
Feb 19th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.85 KB | None | 0 0
  1. module Merb::Test::Rspec::ViewMatchers
  2. class HaveXpath
  3. def initialize(expected)
  4. @expected = expected
  5. end
  6.  
  7. def matches?(stringlike)
  8. @document = case stringlike
  9. when LibXML::XML::Document, LibXML::XML::Node
  10. stringlike
  11. when StringIO
  12. LibXML::XML::HTMLParser.string(stringlike.string).parse
  13. else
  14. LibXML::XML::HTMLParser.string(stringlike).parse
  15. end
  16. !@document.find(@expected).empty?
  17. end
  18.  
  19. # ==== Returns
  20. # String:: The failure message.
  21. def failure_message
  22. "expected following text to match xpath #{@expected}:\n#{@document}"
  23. end
  24.  
  25. # ==== Returns
  26. # String:: The failure message to be displayed in negative matches.
  27. def negative_failure_message
  28. "expected following text to not match xpath #{@expected}:\n#{@document}"
  29. end
  30. end
  31.  
  32. class HaveSelector
  33.  
  34. # ==== Parameters
  35. # expected<String>:: The string to look for.
  36. def initialize(expected)
  37. @expected = expected
  38. end
  39.  
  40. # ==== Parameters
  41. # stringlike<Hpricot::Elem, StringIO, String>:: The thing to search in.
  42. #
  43. # ==== Returns
  44. # Boolean:: True if there was at least one match.
  45. def matches?(stringlike)
  46. @document = case stringlike
  47. when Hpricot::Elem
  48. stringlike
  49. when StringIO
  50. Hpricot.parse(stringlike.string)
  51. else
  52. Hpricot.parse(stringlike)
  53. end
  54. !@document.search(@expected).empty?
  55. end
  56.  
  57. # ==== Returns
  58. # String:: The failure message.
  59. def failure_message
  60. "expected following text to match selector #{@expected}:\n#{@document}"
  61. end
  62.  
  63. # ==== Returns
  64. # String:: The failure message to be displayed in negative matches.
  65. def negative_failure_message
  66. "expected following text to not match selector #{@expected}:\n#{@document}"
  67. end
  68. end
  69.  
  70. class MatchTag
  71.  
  72. # ==== Parameters
  73. # name<~to_s>:: The name of the tag to look for.
  74. # attrs<Hash>:: Attributes to look for in the tag (see below).
  75. #
  76. # ==== Options (attrs)
  77. # :content<String>:: Optional content to match.
  78. def initialize(name, attrs)
  79. @name, @attrs = name, attrs
  80. @content = @attrs.delete(:content)
  81. end
  82.  
  83. # ==== Parameters
  84. # target<String>:: The string to look for the tag in.
  85. #
  86. # ==== Returns
  87. # Boolean:: True if the tag matched.
  88. def matches?(target)
  89. @errors = []
  90. unless target.include?("<#{@name}")
  91. @errors << "Expected a <#{@name}>, but was #{target}"
  92. end
  93. @attrs.each do |attr, val|
  94. unless target.include?("#{attr}=\"#{val}\"")
  95. @errors << "Expected #{attr}=\"#{val}\", but was #{target}"
  96. end
  97. end
  98. if @content
  99. unless target.include?(">#{@content}<")
  100. @errors << "Expected #{target} to include #{@content}"
  101. end
  102. end
  103. @errors.size == 0
  104. end
  105.  
  106. # ==== Returns
  107. # String:: The failure message.
  108. def failure_message
  109. @errors[0]
  110. end
  111.  
  112. # ==== Returns
  113. # String:: The failure message to be displayed in negative matches.
  114. def negative_failure_message
  115. "Expected not to match against <#{@name} #{@attrs.map{ |a,v| "#{a}=\"#{v}\"" }.join(" ")}> tag, but it matched"
  116. end
  117. end
  118.  
  119. class NotMatchTag
  120.  
  121. # === Parameters
  122. # attrs<Hash>:: A set of attributes that must not be matched.
  123. def initialize(attrs)
  124. @attrs = attrs
  125. end
  126.  
  127. # ==== Parameters
  128. # target<String>:: The target to look for the match in.
  129. #
  130. # ==== Returns
  131. # Boolean:: True if none of the attributes were matched.
  132. def matches?(target)
  133. @errors = []
  134. @attrs.each do |attr, val|
  135. if target.include?("#{attr}=\"#{val}\"")
  136. @errors << "Should not include #{attr}=\"#{val}\", but was #{target}"
  137. end
  138. end
  139. @errors.size == 0
  140. end
  141.  
  142. # ==== Returns
  143. # String:: The failure message.
  144. def failure_message
  145. @errors[0]
  146. end
  147. end
  148.  
  149. class HasTag
  150.  
  151. # ==== Parameters
  152. # tag<~to_s>:: The tag to look for.
  153. # attributes<Hash>:: Attributes for the tag (see below).
  154. def initialize(tag, attributes = {}, &blk)
  155. @tag, @attributes = tag, attributes
  156. @id, @class = @attributes.delete(:id), @attributes.delete(:class)
  157. @blk = blk
  158. end
  159.  
  160. # ==== Parameters
  161. # stringlike<Hpricot::Elem, StringIO, String>:: The thing to search in.
  162. # &blk:: An optional block for searching in child elements using with_tag.
  163. #
  164. # ==== Returns
  165. # Boolean:: True if there was at least one match.
  166. def matches?(stringlike, &blk)
  167. @document = case stringlike
  168. when Hpricot::Elem
  169. stringlike
  170. when StringIO
  171. Hpricot.parse(stringlike.string)
  172. else
  173. Hpricot.parse(stringlike)
  174. end
  175.  
  176. @blk = blk unless blk.nil?
  177.  
  178. unless @blk.nil?
  179. !@document.search(selector).select do |ele|
  180. @blk.call ele
  181. true
  182. end.empty?
  183. else
  184. !@document.search(selector).empty?
  185. end
  186. end
  187.  
  188. # ==== Returns
  189. # String:: The complete selector for element queries.
  190. def selector
  191. @selector = "//#{@tag}#{id_selector}#{class_selector}"
  192. @selector << @attributes.map{|a, v| "[@#{a}=\"#{v}\"]"}.join
  193.  
  194. @selector << @inner_has_tag.selector unless @inner_has_tag.nil?
  195.  
  196. @selector
  197. end
  198.  
  199. # ==== Returns
  200. # String:: ID selector for use in element queries.
  201. def id_selector
  202. "##{@id}" if @id
  203. end
  204.  
  205. # ==== Returns
  206. # String:: Class selector for use in element queries.
  207. def class_selector
  208. ".#{@class}" if @class
  209. end
  210.  
  211. # ==== Returns
  212. # String:: The failure message.
  213. def failure_message
  214. "expected following output to contain a #{tag_for_error} tag:\n#{@document}"
  215. end
  216.  
  217. # ==== Returns
  218. # String:: The failure message to be displayed in negative matches.
  219. def negative_failure_message
  220. "expected following output to omit a #{tag_for_error} tag:\n#{@document}"
  221. end
  222.  
  223. # ==== Returns
  224. # String:: The tag used in failure messages.
  225. def tag_for_error
  226. "#{inner_failure_message}<#{@tag}#{id_for_error}#{class_for_error}#{attributes_for_error}>"
  227. end
  228.  
  229. # ==== Returns
  230. # String::
  231. # The failure message to be displayed in negative matches within the
  232. # have_tag block.
  233. def inner_failure_message
  234. "#{@inner_has_tag.tag_for_error} tag within a " unless @inner_has_tag.nil?
  235. end
  236.  
  237. # ==== Returns
  238. # String:: ID for the error tag.
  239. def id_for_error
  240. " id=\"#{@id}\"" unless @id.nil?
  241. end
  242.  
  243. # ==== Returns
  244. # String:: Class for the error tag.
  245. def class_for_error
  246. " class=\"#{@class}\"" unless @class.nil?
  247. end
  248.  
  249. # ==== Returns
  250. # String:: Class for the error tag.
  251. def attributes_for_error
  252. @attributes.map{|a,v| " #{a}=\"#{v}\""}.join
  253. end
  254.  
  255. # Search for a child tag within a have_tag block.
  256. #
  257. # ==== Parameters
  258. # tag<~to_s>:: The tag to look for.
  259. # attributes<Hash>:: Attributes for the tag (see below).
  260. def with_tag(name, attrs={})
  261. @inner_has_tag = HasTag.new(name, attrs)
  262. end
  263. end
  264.  
  265. class HasContent
  266. def initialize(content)
  267. @content = content
  268. end
  269.  
  270. def matches?(element)
  271. @element = element
  272.  
  273. case @content
  274. when String
  275. @element.contains?(@content)
  276. when Regexp
  277. @element.matches?(@content)
  278. end
  279. end
  280.  
  281. # ==== Returns
  282. # String:: The failure message.
  283. def failure_message
  284. "expected the following element's content to #{content_message}:\n#{@element.inner_text}"
  285. end
  286.  
  287. # ==== Returns
  288. # String:: The failure message to be displayed in negative matches.
  289. def negative_failure_message
  290. "expected the following element's content to not #{content_message}:\n#{@element.inner_text}"
  291. end
  292.  
  293. def content_message
  294. case @content
  295. when String
  296. "include \"#{@content}\""
  297. when Regexp
  298. "match #{@content.inspect}"
  299. end
  300. end
  301. end
  302.  
  303. # ==== Parameters
  304. # name<~to_s>:: The name of the tag to look for.
  305. # attrs<Hash>:: Attributes to look for in the tag (see below).
  306. #
  307. # ==== Options (attrs)
  308. # :content<String>:: Optional content to match.
  309. #
  310. # ==== Returns
  311. # MatchTag:: A new match tag matcher.
  312. def match_tag(name, attrs={})
  313. MatchTag.new(name, attrs)
  314. end
  315.  
  316. # ==== Parameters
  317. # attrs<Hash>:: A set of attributes that must not be matched.
  318. #
  319. # ==== Returns
  320. # NotMatchTag:: A new not match tag matcher.
  321. def not_match_tag(attrs)
  322. NotMatchTag.new(attrs)
  323. end
  324.  
  325. # ==== Parameters
  326. # expected<String>:: The string to look for.
  327. #
  328. # ==== Returns
  329. # HaveSelector:: A new have selector matcher.
  330. def have_selector(expected)
  331. HaveSelector.new(expected)
  332. end
  333. alias_method :match_selector, :have_selector
  334.  
  335. def have_xpath(expected)
  336. require "libxml"
  337. HaveXpath.new(expected)
  338. end
  339. alias_method :match_xpath, :have_xpath
  340.  
  341. # RSpec matcher to test for the presence of tags.
  342. #
  343. # ==== Parameters
  344. # tag<~to_s>:: The name of the tag.
  345. # attributes<Hash>:: Tag attributes.
  346. #
  347. # ==== Returns
  348. # HasTag:: A new has tag matcher.
  349. #
  350. # ==== Examples
  351. # # Check for <div>
  352. # body.should have_tag("div")
  353. #
  354. # # Check for <span id="notice">
  355. # body.should have_tag("span", :id => :notice)
  356. #
  357. # # Check for <h1 id="foo" class="bar">
  358. # body.should have_tag(:h2, :class => "bar", :id => "foo")
  359. #
  360. # # Check for <div attr="val">
  361. # body.should have_tag(:div, :attr => :val)
  362. def have_tag(tag, attributes = {}, &blk)
  363. HasTag.new(tag, attributes, &blk)
  364. end
  365.  
  366. alias_method :with_tag, :have_tag
  367.  
  368. def contain(content)
  369. HasContent.new(content)
  370. end
  371. end
Add Comment
Please, Sign In to add comment