/vendor/plugins/email-spec/lib/email_spec/helpers.rb

https://github.com/ganders/teambox · Ruby · 160 lines · 126 code · 32 blank · 2 comment · 6 complexity · ea0f2b48b1214d2a46b0261f7b65b95a MD5 · raw file

  1. require 'uri'
  2. require 'email_spec/deliveries'
  3. module EmailSpec
  4. module Helpers
  5. include Deliveries
  6. def visit_in_email(link_text)
  7. visit(parse_email_for_link(current_email, link_text))
  8. end
  9. def click_email_link_matching(regex, email = current_email)
  10. url = links_in_email(email).detect { |link| link =~ regex }
  11. raise "No link found matching #{regex.inspect} in #{email.default_part_body}" unless url
  12. request_uri = URI::parse(url).request_uri
  13. visit request_uri
  14. end
  15. def click_first_link_in_email(email = current_email)
  16. link = links_in_email(email).first
  17. request_uri = URI::parse(link).request_uri
  18. visit request_uri
  19. end
  20. def open_email(address, opts={})
  21. set_current_email(find_email!(address, opts))
  22. end
  23. alias_method :open_email_for, :open_email
  24. def open_last_email
  25. set_current_email(last_email_sent)
  26. end
  27. def open_last_email_for(address)
  28. set_current_email(mailbox_for(address).last)
  29. end
  30. def current_email(address=nil)
  31. address = convert_address(address)
  32. email = address ? email_spec_hash[:current_emails][address] : email_spec_hash[:current_email]
  33. raise RSpec::Expectations::ExpectationNotMetError, "Expected an open email but none was found. Did you forget to call open_email?" unless email
  34. email
  35. end
  36. def current_email_attachments(address=nil)
  37. current_email(address).attachments || Array.new
  38. end
  39. def unread_emails_for(address)
  40. mailbox_for(address) - read_emails_for(address)
  41. end
  42. def read_emails_for(address)
  43. email_spec_hash[:read_emails][convert_address(address)] ||= []
  44. end
  45. def find_email(address, opts={})
  46. address = convert_address(address)
  47. if opts[:with_subject]
  48. mailbox_for(address).find { |m| m.subject =~ Regexp.new(opts[:with_subject]) }
  49. elsif opts[:with_text]
  50. mailbox_for(address).find { |m| m.default_part_body =~ Regexp.new(opts[:with_text]) }
  51. else
  52. mailbox_for(address).first
  53. end
  54. end
  55. def links_in_email(email)
  56. URI.extract(email.default_part_body.to_s, ['http', 'https'])
  57. end
  58. private
  59. def email_spec_hash
  60. @email_spec_hash ||= {:read_emails => {}, :unread_emails => {}, :current_emails => {}, :current_email => nil}
  61. end
  62. def find_email!(address, opts={})
  63. email = find_email(address, opts)
  64. if email.nil?
  65. error = "#{opts.keys.first.to_s.humanize unless opts.empty?} #{('"' + opts.values.first.to_s.humanize + '"') unless opts.empty?}"
  66. raise RSpec::Expectations::ExpectationNotMetError, "Could not find email #{error}. \n Found the following emails:\n\n #{all_emails.to_s}"
  67. end
  68. email
  69. end
  70. def set_current_email(email)
  71. return unless email
  72. [email.to, email.cc, email.bcc].compact.flatten.each do |to|
  73. read_emails_for(to) << email
  74. email_spec_hash[:current_emails][to] = email
  75. end
  76. email_spec_hash[:current_email] = email
  77. end
  78. def parse_email_for_link(email, text_or_regex)
  79. email.should have_body_text(text_or_regex)
  80. url = parse_email_for_explicit_link(email, text_or_regex)
  81. url ||= parse_email_for_anchor_text_link(email, text_or_regex)
  82. raise "No link found matching #{text_or_regex.inspect} in #{email}" unless url
  83. url
  84. end
  85. # e.g. confirm in http://confirm
  86. def parse_email_for_explicit_link(email, regex)
  87. regex = /#{Regexp.escape(regex)}/ unless regex.is_a?(Regexp)
  88. url = links_in_email(email).detect { |link| link =~ regex }
  89. URI::parse(url).request_uri if url
  90. end
  91. # e.g. Click here in <a href="http://confirm">Click here</a>
  92. def parse_email_for_anchor_text_link(email, link_text)
  93. if textify_images(email.default_part_body) =~ %r{<a[^>]*href=['"]?([^'"]*)['"]?[^>]*?>[^<]*?#{link_text}[^<]*?</a>}
  94. URI.split($1)[5..-1].compact!.join("?").gsub("&amp;", "&")
  95. # sub correct ampersand after rails switches it (http://dev.rubyonrails.org/ticket/4002)
  96. else
  97. return nil
  98. end
  99. end
  100. def textify_images(email_body)
  101. email_body.to_s.gsub(%r{<img[^>]*alt=['"]?([^'"]*)['"]?[^>]*?/>}) { $1 }
  102. end
  103. def parse_email_count(amount)
  104. case amount
  105. when "no"
  106. 0
  107. when "an"
  108. 1
  109. else
  110. amount.to_i
  111. end
  112. end
  113. attr_reader :last_email_address
  114. def convert_address(address)
  115. @last_email_address = (address || current_email_address)
  116. AddressConverter.instance.convert(@last_email_address)
  117. end
  118. def mailbox_for(address)
  119. super(convert_address(address)) # super resides in Deliveries
  120. end
  121. def email_spec_deprecate(text)
  122. puts ""
  123. puts "DEPRECATION: #{text.split.join(' ')}"
  124. puts ""
  125. end
  126. end
  127. end