|
|
|
include Sorcery::TestHelpers::Rails
|
|
|
|
|
|
|
|
def locate(id)
|
|
|
|
id = id.gsub(/\s+/, '_')
|
|
|
|
e = page.all("[name=\"#{id}\"], [id=\"#{id}\"], [id^=\"#{id}--\"]")
|
|
|
|
return e.first[:id]
|
|
|
|
end
|
|
|
|
|
|
|
|
def selector_for(id)
|
|
|
|
prefixes = ['body.has-overlay .dlg.open ', 'body #primary-content ']
|
|
|
|
selectors = ['[name="{id}"]', '[id="{id}"]', '[id^="{id}--"]']
|
|
|
|
|
|
|
|
selector = []
|
|
|
|
prefixes.each do | pre |
|
|
|
|
selectors.each do | sel |
|
|
|
|
selector << "#{pre}#{sel}".gsub(/\{id\}/, id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
selector.join(',')
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_language_code(language)
|
|
|
|
languages = {
|
|
|
|
'english' => 'en',
|
|
|
|
'french' => 'fr',
|
|
|
|
'spanish' => 'es',
|
|
|
|
'german' => 'de'
|
|
|
|
}
|
|
|
|
languages[language.downcase]
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_filename(filename)
|
|
|
|
filename.gsub(/[^\w\s_-]+/, '')
|
|
|
|
.gsub(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
|
|
|
|
.gsub(/\s+/, '_')
|
|
|
|
end
|
|
|
|
|
|
|
|
def log_result(scenario)
|
|
|
|
if Capybara.current_session.server.present?
|
|
|
|
dir = "log/test-results/#{to_filename(scenario.feature.name)}"
|
|
|
|
FileUtils::mkdir_p dir
|
|
|
|
filename = "#{to_filename(scenario.name)}.html"
|
|
|
|
File.write("#{dir}/#{filename}", capture_html)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def capture_html(distance_from_root = 3)
|
|
|
|
html = page.html
|
|
|
|
host = "http://#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}"
|
|
|
|
public_dir = "#{'../' * distance_from_root}public/"
|
|
|
|
|
|
|
|
html.gsub(/(=\"|\(['"]?)(?:#{host})?\/(assets|uploads)/, "\\1#{public_dir}\\2")
|
|
|
|
end
|
|
|
|
|
|
|
|
def attempt_to(refresh_on_fail = false, &block)
|
|
|
|
exception = nil
|
|
|
|
begin
|
|
|
|
retries ||= 0
|
|
|
|
timeout ||= 0
|
|
|
|
timeout += 1
|
|
|
|
yield
|
|
|
|
rescue Exception => e
|
|
|
|
exception ||= e
|
|
|
|
raise exception unless (retries += 1) <= 4
|
|
|
|
visit TestState.last_page if TestState.last_page && refresh_on_fail
|
|
|
|
sleep(timeout * timeout)
|
|
|
|
retry
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def last_email_html
|
|
|
|
if TestState.last_email.parts
|
|
|
|
TestState.last_email.parts.last.body.raw_source
|
|
|
|
else
|
|
|
|
TestState.last_email.body.raw_source
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def find_in_last_email(selector, attribute = nil)
|
|
|
|
html = last_email_html.gsub(/^.*?(<table .*<\/table>).*$/m, '\1').gsub(/\n/, ' ').gsub(/\'/, '\\\'')
|
|
|
|
Nokogiri::HTML(html).at(selector).attr(attribute)
|
|
|
|
end
|
|
|
|
|
|
|
|
def emails_to(email_address, subject = nil)
|
|
|
|
ActionMailer::Base.deliveries.select do |mail|
|
|
|
|
mail.to.include?(email_address) &&
|
|
|
|
(subject.nil? || ActionView::Base.full_sanitizer.sanitize(mail.subject).downcase.include?(subject.downcase))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def str_to_num(num)
|
|
|
|
nums = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
|
|
|
|
return nums.find_index(num) if nums.include?(num)
|
|
|
|
|
|
|
|
case num
|
|
|
|
when 'no', 'none'
|
|
|
|
return 0
|
|
|
|
when 'a', 'an'
|
|
|
|
return 1
|
|
|
|
when 'two', 'couple', 'a couple', 'couple of', 'a couple of'
|
|
|
|
return 2
|
|
|
|
end
|
|
|
|
|
|
|
|
return num.to_i if num =~ /\d+/
|
|
|
|
|
|
|
|
fail "Could not interpret '#{num}' as a number"
|
|
|
|
end
|
|
|
|
|
|
|
|
def compare(expected, actual, negate = false)
|
|
|
|
case expected
|
|
|
|
when /any|some/
|
|
|
|
expectation = (be >= 1)
|
|
|
|
else
|
|
|
|
expectation = (be == str_to_num(expected))
|
|
|
|
end
|
|
|
|
expect(actual).send(negate ? :not_to : :to, expectation)
|
|
|
|
end
|
|
|
|
|
|
|
|
def email_address(user)
|
|
|
|
case user
|
|
|
|
when /(I|me)/
|
|
|
|
TestState.my_account.present? ? TestState.my_account.email : TestState.last_email_entered
|
|
|
|
when /^(?:the )?site administrator$/i
|
|
|
|
'goodgodwin@hotmail.com'
|
|
|
|
when /^'(.+)'$/
|
|
|
|
get_user($1).email
|
|
|
|
else
|
|
|
|
user
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_locale(language)
|
|
|
|
return ({
|
|
|
|
spanish: :es,
|
|
|
|
english: :en,
|
|
|
|
french: :fr,
|
|
|
|
german: :de,
|
|
|
|
klingon: :tlh
|
|
|
|
}[language.strip.downcase.to_sym] or fail "Unable to convert '#{language.trim}' into a locale")
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_field(field)
|
|
|
|
field = field.gsub(/^\s*(my|the)\s*(.+)$/, '\2').gsub(/\s/, '_')
|
|
|
|
aliases = {'phone_number' => 'phone', 'email_address' => 'email'}
|
|
|
|
return aliases[field] || field
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_user(username)
|
|
|
|
return create_user unless username.present?
|
|
|
|
|
|
|
|
TestState::Users[username] ||= create_user({
|
|
|
|
(username =~ /^[^\s]+@[^\s]+\.[^\s]+$/ ? :email : :firstname) => username
|
|
|
|
})
|
|
|
|
|
|
|
|
return TestState::Users[username]
|
|
|
|
end
|
|
|
|
|
|
|
|
def element_with_text(text, parent = page)
|
|
|
|
smallest = nil
|
|
|
|
parent.all('*', text: text).each do |node|
|
|
|
|
smallest = node if smallest.nil? || smallest.native['outerHTML'].length > node.native['outerHTML'].length
|
|
|
|
end
|
|
|
|
return smallest
|
|
|
|
end
|
|
|
|
|
|
|
|
def parent_element(node)
|
|
|
|
node.first(:xpath, './/..')
|
|
|
|
end
|
|
|
|
|
|
|
|
def headers_to_attributes(object)
|
|
|
|
new_object = {}
|
|
|
|
object.each do |key, value|
|
|
|
|
new_object[key.underscore] = value
|
|
|
|
end
|
|
|
|
|
|
|
|
return new_object
|
|
|
|
end
|
|
|
|
|
|
|
|
def string_to_time(str)
|
|
|
|
h, m = str.split(':')
|
|
|
|
h = h.to_i
|
|
|
|
m = m.to_i
|
|
|
|
h += 12 if h < 6
|
|
|
|
return h + (m > 0 ? 0.5 : 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
def string_to_time_length(str)
|
|
|
|
parts = str.match(/^(?:(\d+) hour)?\s*(?:(\d+) minutes)?$/)
|
|
|
|
return (parts[1] || '0').to_i + ((parts[2] || '0').to_i > 0 ? 0.5 : 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
def str_to_wday(str)
|
|
|
|
return [:sun, :mon, :tue, :wed, :thu, :fri, :sat].index(str[0...3].downcase.to_sym)
|
|
|
|
end
|