SimpliTest 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +22 -0
- data/SimpliTest.gemspec +42 -0
- data/bin/SimpliTest +22 -0
- data/lib/SimpliTest.rb +2 -0
- data/lib/SimpliTest/cli/main.rb +305 -0
- data/lib/SimpliTest/config/configuration.rb +107 -0
- data/lib/SimpliTest/config/directory_paths.rb +36 -0
- data/lib/SimpliTest/config/environment.rb +67 -0
- data/lib/SimpliTest/config/local_environment.rb +20 -0
- data/lib/SimpliTest/config/profiles/chrome.rb +18 -0
- data/lib/SimpliTest/config/profiles/firefox.rb +14 -0
- data/lib/SimpliTest/config/profiles/internet_explorer.rb +12 -0
- data/lib/SimpliTest/config/profiles/phantom.rb +9 -0
- data/lib/SimpliTest/config/profiles/phantom_debug.rb +12 -0
- data/lib/SimpliTest/config/profiles/selenium.rb +13 -0
- data/lib/SimpliTest/config/screen_size.rb +25 -0
- data/lib/SimpliTest/config/steps.rb +8 -0
- data/lib/SimpliTest/helpers/data_validation.rb +60 -0
- data/lib/SimpliTest/helpers/file.rb +38 -0
- data/lib/SimpliTest/helpers/project_setup.rb +186 -0
- data/lib/SimpliTest/helpers/step_helpers/custom_chrome_helpers.rb +14 -0
- data/lib/SimpliTest/helpers/step_helpers/custom_date_helpers.rb +64 -0
- data/lib/SimpliTest/helpers/step_helpers/custom_form_helpers.rb +66 -0
- data/lib/SimpliTest/helpers/step_helpers/custom_phantomjs_helpers.rb +49 -0
- data/lib/SimpliTest/helpers/step_helpers/custom_selenium_helpers.rb +41 -0
- data/lib/SimpliTest/helpers/step_helpers/html_selectors_helpers.rb +154 -0
- data/lib/SimpliTest/helpers/step_helpers/navigation_helpers.rb +196 -0
- data/lib/SimpliTest/helpers/step_helpers/tolerance_for_sync_issues.rb +38 -0
- data/lib/SimpliTest/helpers/step_helpers/within_helpers.rb +6 -0
- data/lib/SimpliTest/helpers/windows_ui.rb +52 -0
- data/lib/SimpliTest/steps/debugging_steps.rb +19 -0
- data/lib/SimpliTest/steps/form_steps.rb +352 -0
- data/lib/SimpliTest/steps/form_verification_steps.rb +190 -0
- data/lib/SimpliTest/steps/navigation_steps.rb +47 -0
- data/lib/SimpliTest/steps/scoper.rb +42 -0
- data/lib/SimpliTest/steps/verification_steps.rb +306 -0
- data/lib/SimpliTest/tasks/document.rb +169 -0
- data/lib/SimpliTest/tasks/examples.rb +18 -0
- data/lib/SimpliTest/tasks/internal_release.rb +39 -0
- data/lib/SimpliTest/tasks/testinstall.rb +5 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/Readme.txt +5 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/cucumber.yml +26 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/documentation/step_definitions.html +87 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/specifications/RegressionTests/HelloWorld.feature +4 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/specifications/SmokeTest/HelloWorld.feature +4 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/specifications/accessibilityTests/HelloWorld.feature +4 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/environments.yml +11 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/pages.yml +26 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/selectors.yml +44 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/settings.yml +26 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/env.rb +33 -0
- data/lib/SimpliTest/templates/NewSimpliTestProject/license.txt +30 -0
- data/lib/SimpliTest/templates/document/css/style.css +28 -0
- data/lib/SimpliTest/templates/document/index.html +60 -0
- data/lib/version.rb +3 -0
- metadata +395 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
#The chrome profile loads Selenium Helpers as well. These methods
|
2
|
+
#override the methods available in Selenium Helpers
|
3
|
+
module CustomChromeHelpers
|
4
|
+
def maximize_window
|
5
|
+
page.driver.browser.manage.window.resize_to(MAX_WIDTH,MAX_HEIGHT)
|
6
|
+
end
|
7
|
+
def keydown_on(element)
|
8
|
+
element.native.send_key(:arrow_down)
|
9
|
+
end
|
10
|
+
|
11
|
+
def capture_screenshot(filename)
|
12
|
+
page.driver.browser.save_screenshot(filename)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module CustomDateHelpers
|
2
|
+
def calculated_date_from(date_rule)
|
3
|
+
# Takes strings like "Today's Date", "4 days ago", "5 days since" etc. and
|
4
|
+
# returns a calculated date in the default_date_format
|
5
|
+
potential_date_formats = /[0-9]+\/[0-9]+\/[0-9]+/x
|
6
|
+
first_and_last_regex = /the (nearest|first|last) (.*)/
|
7
|
+
date = case date_rule
|
8
|
+
when potential_date_formats
|
9
|
+
date_rule
|
10
|
+
when /Today's Date/i
|
11
|
+
Date.today
|
12
|
+
when /(\d+) days (ago|since)/i
|
13
|
+
number_of_days = $1.to_i rescue nil
|
14
|
+
time_travel_method = $2.downcase.to_sym
|
15
|
+
raise "Invalid number of days. Please enter a valid number" if number_of_days.nil?
|
16
|
+
number_of_days.send(:days).send(time_travel_method)
|
17
|
+
when first_and_last_regex
|
18
|
+
first_and_last_date_rule(rule)
|
19
|
+
end
|
20
|
+
date.respond_to?(:strftime) ? date.strftime(default_date_format) : date
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_and_last_date_rule(phrase)
|
24
|
+
# Takes a phrase like "the first day of the month" or "last day of the
|
25
|
+
# previous month" and returns a calculated date in the default_date_format
|
26
|
+
case phrase
|
27
|
+
when /the (first|last) day of the month/i
|
28
|
+
Date.today.send(beginning_or_end($1))
|
29
|
+
when /the (first|last) day of next month/i
|
30
|
+
1.month.since.send(beginning_or_end($1))
|
31
|
+
when /the (first|last) day of previous month/i
|
32
|
+
1.month.ago.send(beginning_or_end($1))
|
33
|
+
when /the (first|last) day of (.*)/i
|
34
|
+
date_from_phrase($1, $2)
|
35
|
+
when /the nearest (first|last) day of month/i
|
36
|
+
rule = Date.today.day >= 15 ? "the #{$1} day of next month" : "the #{$1} day of the month"
|
37
|
+
calculated_date_from(rule)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def beginning_or_end(first_or_last)
|
42
|
+
first_or_last == 'first' ? :beginning_of_month : :end_of_month
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_date_format
|
46
|
+
format_for_strftime SimpliTest.config_settings['DEFAULT_DATE_FORMAT']
|
47
|
+
end
|
48
|
+
|
49
|
+
def date_from_phrase(first_or_last, month)
|
50
|
+
month_name = month.downcase.camelize
|
51
|
+
month = Date::MONTHNAMES.index(month_name)
|
52
|
+
if month.nil?
|
53
|
+
raise "Oops you provided an invalid month name. Please use a valid month name from January to December"
|
54
|
+
end
|
55
|
+
date = Date.parse("#{month}/1") #mm/dd in current year
|
56
|
+
date = date.send(:end_of_month) if first_or_last == 'last'
|
57
|
+
end
|
58
|
+
|
59
|
+
def format_for_strftime(string)
|
60
|
+
string.gsub('mm', '%m').gsub('dd', '%d').gsub('yyyy', '%Y').gsub('yy', '%y')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
World(CustomDateHelpers)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CustomFormHelpers
|
2
|
+
|
3
|
+
def numerize(number_name)
|
4
|
+
case number_name
|
5
|
+
when 'first'; 0
|
6
|
+
when 'last'; -1
|
7
|
+
else number_name.match(/[0-9]/)[1].to_i + 1 rescue 0 #take the first one if you cant figure it out
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def blur(selector_and_xpath)
|
12
|
+
css_selector, xpath = selector_and_xpath
|
13
|
+
selector = xpath ? xpath : css_selector
|
14
|
+
if xpath
|
15
|
+
return
|
16
|
+
else
|
17
|
+
#TODO: Hate how this done...need to come back to this
|
18
|
+
execute_script_for_driver(SimpliTest.config_driver, %Q{ $('#{selector}').blur(); })
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def fill_in_masked_field(css_selector, value)
|
23
|
+
STDOUT.puts "Entering #{value} in Masked Field #{css_selector} now" #TODO: Delete this debugging statement
|
24
|
+
execute_script_for_driver(SimpliTest.config_driver, %Q{ $("#{css_selector}").val("#{value}"); })
|
25
|
+
STDOUT.puts "Blurring the field now" #TODO: Delete this debugging statement
|
26
|
+
execute_script_for_driver(SimpliTest.config_driver, %Q{ $("#{css_selector}").blur(); })
|
27
|
+
#page.driver.debug
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def press_key(key)
|
32
|
+
keycode = keycode_for[key.downcase.gsub(' ','_')]
|
33
|
+
keypress_script = "var e = $.Event('keydown', { keyCode: #{keycode} }); $('body').trigger(e);"
|
34
|
+
execute_js(keypress_script)
|
35
|
+
end
|
36
|
+
|
37
|
+
def tab_on(element)
|
38
|
+
element.native.send_key(:tab)
|
39
|
+
end
|
40
|
+
|
41
|
+
def keypress_on(elem, key, charCode = 0)
|
42
|
+
keyCode = keycode_for[key]
|
43
|
+
elem.base.invoke('keypress', false, false, false, false, keyCode, charCode);
|
44
|
+
end
|
45
|
+
|
46
|
+
def keycode_for
|
47
|
+
{
|
48
|
+
:tab => 9,
|
49
|
+
:enter => 13,
|
50
|
+
:up_arrow => 38,
|
51
|
+
:down_arrow => 40,
|
52
|
+
:left_arrow => 37,
|
53
|
+
:right_arrow => 39,
|
54
|
+
:escape => 27,
|
55
|
+
:spacebar => 32,
|
56
|
+
:ctrl => 17,
|
57
|
+
:alt => 18,
|
58
|
+
:shift => 16,
|
59
|
+
:caps_lock => 20,
|
60
|
+
:backspace => 8,
|
61
|
+
:delete => 46
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
World(CustomFormHelpers)
|
66
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module CustomPhantomjsHelpers
|
2
|
+
def maximize_window
|
3
|
+
page.driver.resize_window(MAX_WIDTH,MAX_HEIGHT)
|
4
|
+
end
|
5
|
+
|
6
|
+
def tab_on(element)
|
7
|
+
element.native.send_key(:Tab)
|
8
|
+
end
|
9
|
+
|
10
|
+
def accept_confirmation
|
11
|
+
#TODO: accept confirmation
|
12
|
+
raise "NotImplementedError"
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute_js(script)
|
16
|
+
page.execute_script(script)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_text_from(element)
|
20
|
+
element.native.all_text
|
21
|
+
end
|
22
|
+
|
23
|
+
def click_element(element)
|
24
|
+
begin
|
25
|
+
element.click
|
26
|
+
rescue Capybara::Poltergeist::MouseEventFailed
|
27
|
+
element.trigger('click')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def key_in(character, element)
|
32
|
+
element.native.send_key(character)
|
33
|
+
end
|
34
|
+
|
35
|
+
def keydown_on(element)
|
36
|
+
key_in('Down', element)
|
37
|
+
end
|
38
|
+
|
39
|
+
def capture_screenshot(filename)
|
40
|
+
page.save_screenshot(filename)
|
41
|
+
end
|
42
|
+
|
43
|
+
def change_window(first_or_last)
|
44
|
+
raise "Invalid window name #{first_or_last}. You can only use 'first' or 'last'" unless first_or_last =~ /first|last/
|
45
|
+
window_handle = page.driver.browser.window_handles.send(first_or_last.to_sym)
|
46
|
+
page.driver.browser.switch_to_window(window_handle)
|
47
|
+
wait_for(page.driver.browser.window_handles.size, 1)
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module CustomSeleniumHelpers
|
2
|
+
def maximize_window
|
3
|
+
page.driver.browser.manage.window.resize_to(MAX_WIDTH, MAX_HEIGHT)
|
4
|
+
end
|
5
|
+
|
6
|
+
def capture_screenshot(filename)
|
7
|
+
page.driver.browser.save_screenshot(filename)
|
8
|
+
end
|
9
|
+
|
10
|
+
def accept_confirmation
|
11
|
+
page.driver.browser.switch_to.alert.accept
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute_js(script)
|
15
|
+
page.driver.browser.execute_script(script)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_text_from(element)
|
19
|
+
element.text
|
20
|
+
end
|
21
|
+
|
22
|
+
def click_element(element)
|
23
|
+
element.click
|
24
|
+
end
|
25
|
+
|
26
|
+
def key_in(character, element)
|
27
|
+
element.native.send_key(character)
|
28
|
+
end
|
29
|
+
|
30
|
+
def keydown_on(element)
|
31
|
+
key_in(:arrow_down, element)
|
32
|
+
end
|
33
|
+
|
34
|
+
def change_window(first_or_last)
|
35
|
+
raise "Invalid window name #{first_or_last}. You can only use 'first' or 'last'" unless first_or_last =~ /first|last/
|
36
|
+
window_handle = page.driver.browser.window_handles.send(first_or_last.to_sym)
|
37
|
+
page.driver.browser.switch_to.window(window_handle)
|
38
|
+
wait_for(page.driver.browser.window_handles.size, 1)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module HtmlSelectorsHelpers
|
2
|
+
#TODO: Rewrite without test app for template. The code here effing nuts'...clean this shit
|
3
|
+
@selectors_file = 'features/support/config/selectors.yml'
|
4
|
+
|
5
|
+
def pagination_links_for(page_number)
|
6
|
+
selector = "input[title='Page #{page_number}']"
|
7
|
+
all(:css, selector)
|
8
|
+
end
|
9
|
+
|
10
|
+
def pagination_element_for(index)
|
11
|
+
lookup = {
|
12
|
+
'first' => 'firstButton',
|
13
|
+
'last' => 'lastButton',
|
14
|
+
'previous' => 'prevButton',
|
15
|
+
'next' => 'nextButton'
|
16
|
+
}
|
17
|
+
selector = "##{lookup[index]}"
|
18
|
+
elements = all(:css, selector)
|
19
|
+
elements.first if elements
|
20
|
+
end
|
21
|
+
|
22
|
+
def select_options_for(locator)
|
23
|
+
element = get_element_from(locator)
|
24
|
+
get_text_from(element)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_element_from(locator, try_field=true, find_button_or_link=false)
|
28
|
+
selector, selector_type = selector_for(locator)
|
29
|
+
element = nil
|
30
|
+
patiently do
|
31
|
+
if selector_type == 'xpath'
|
32
|
+
element = page.find(:xpath, selector)
|
33
|
+
elsif selector_type == 'css'
|
34
|
+
element = page.find(:css, selector)
|
35
|
+
elsif try_field
|
36
|
+
element = page.find_field(selector)
|
37
|
+
elsif find_button_or_link
|
38
|
+
raise "Button or Link Not Found"
|
39
|
+
else
|
40
|
+
element = find(selector)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def get_button_or_link_from(locator)
|
47
|
+
begin
|
48
|
+
get_element_from(locator, false, true)
|
49
|
+
rescue
|
50
|
+
begin
|
51
|
+
page.find_link(locator)
|
52
|
+
rescue
|
53
|
+
page.find_button(locator)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def selector_for(locator)
|
59
|
+
if SimpliTest.config_selectors
|
60
|
+
mapping = mapping_for(locator)
|
61
|
+
mapping ? selector_from(mapping) : default_selector_for(locator)
|
62
|
+
else
|
63
|
+
default_selector_for(locator)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def mapping_for(selector)
|
68
|
+
SimpliTest.config_selectors[unquoted(selector)] || false
|
69
|
+
end
|
70
|
+
|
71
|
+
def selector_from(selector)
|
72
|
+
selector_type = is_xpath?(selector) ? 'xpath' : (is_css?(selector) ? 'css' : 'other')
|
73
|
+
selector = without_identifier(selector)
|
74
|
+
return selector, selector_type
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def is_xpath?(locator)
|
79
|
+
selector_for(locator)[0].match(/xpath:(.*)/)
|
80
|
+
end
|
81
|
+
|
82
|
+
def is_css?(locator)
|
83
|
+
selector_for(locator)[0].match(/css:(.*)/)
|
84
|
+
end
|
85
|
+
|
86
|
+
def without_identifier(locator)
|
87
|
+
if match = (is_xpath?(locator) || is_css?(locator))
|
88
|
+
return match[1]
|
89
|
+
else
|
90
|
+
return locator
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def unquoted(string)
|
96
|
+
#string[0] is the first char
|
97
|
+
#string[-1,1] is the last char
|
98
|
+
is_string_quoted = (string[0] == string[-1, 1]) && (%w[' "].include?(string[0]))
|
99
|
+
is_string_quoted ? string.gsub(/^"|"$/, '') : string
|
100
|
+
end
|
101
|
+
|
102
|
+
def default_selector_for(locator)
|
103
|
+
case locator
|
104
|
+
|
105
|
+
when "the page"
|
106
|
+
with_selector_type "html > body"
|
107
|
+
when "table's header"
|
108
|
+
with_selector_type "table tbody > tr th"
|
109
|
+
when /^paragraphs?$/
|
110
|
+
with_selector_type "p"
|
111
|
+
when "\"table tr\""
|
112
|
+
with_selector_type "table tr"
|
113
|
+
when "\"div.some_class\""
|
114
|
+
with_selector_type "div.some_class"
|
115
|
+
else
|
116
|
+
with_selector_type locator
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def with_selector_type(selector, selector_type='other')
|
121
|
+
[selector, selector_type]
|
122
|
+
end
|
123
|
+
|
124
|
+
def validate_absence_of(text)
|
125
|
+
min_wait_time = SimpliTest.config_settings ? SimpliTest.config_settings['MIN_WAIT_TIME'] : 2
|
126
|
+
using_wait_time min_wait_time do #because we are validating absence we don't need to wait all 5 seconds?
|
127
|
+
begin
|
128
|
+
should_not have_link(text)
|
129
|
+
rescue RSpec::Expectations::ExpectationNotMetError, Capybara::ExpectationNotMet
|
130
|
+
element = get_button_or_link_from(text)
|
131
|
+
element.should_not be_visible if element.respond_to?(:visible?)
|
132
|
+
## deprecating the approach below for performance reasons
|
133
|
+
##xpath = potential_hidden_paths_for(text).join('|')
|
134
|
+
##should have_xpath(xpath)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def selectors_from_section(section)
|
140
|
+
SimpliTest.config_selectors[section].values
|
141
|
+
end
|
142
|
+
|
143
|
+
#def potential_hidden_paths_for(text) #the different ways developers might choose to hide things in the DOM
|
144
|
+
#[
|
145
|
+
#"//*[@class='hidden' and contains(.,'#{text}')]",
|
146
|
+
#"//*[@class='invisible' and contains(.,'#{text}')]",
|
147
|
+
#"//*[@style='display: none;' and contains(.,'#{text}')]"
|
148
|
+
#]
|
149
|
+
|
150
|
+
#end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
World(HtmlSelectorsHelpers)
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module NavigationHelpers
|
2
|
+
# Maps a name to a path. Used by the
|
3
|
+
#
|
4
|
+
# When /^I go to (.+)$/ do |page_name|
|
5
|
+
#
|
6
|
+
#TODO: Rewrite without test app for template
|
7
|
+
def path_to(page_name)
|
8
|
+
if is_url?(page_name)
|
9
|
+
page_name
|
10
|
+
elsif SimpliTest.config_pages
|
11
|
+
matches = SimpliTest.config_pages.select { |p| unquoted(page_name) == p }
|
12
|
+
matches.any? ? url_from(matches, page_name) : default_path_for(page_name)
|
13
|
+
else
|
14
|
+
default_path_for(page_name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# :nocov:
|
18
|
+
def url_from(matches, page_name)
|
19
|
+
if matches.length > 1
|
20
|
+
raise "Oops ambigous page name! More than one matched our search. It seems you have similar page names. \n" +
|
21
|
+
"Now, go and modify #{page_name} to something cooler in config/pages.yml"
|
22
|
+
else
|
23
|
+
path = matches.values.first
|
24
|
+
end
|
25
|
+
url_to(path) if path
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_path_for(page_name)
|
29
|
+
case page_name
|
30
|
+
|
31
|
+
when /^home$/
|
32
|
+
'/'
|
33
|
+
when /^congratulations$/
|
34
|
+
'/congratulations'
|
35
|
+
when /^other$/
|
36
|
+
'/other/page'
|
37
|
+
when /^form$/
|
38
|
+
'/form/page'
|
39
|
+
when /^valid_links$/
|
40
|
+
'/valid-links'
|
41
|
+
when /^invalid_links$/
|
42
|
+
'/invalid-links'
|
43
|
+
# Add more mappings here.
|
44
|
+
# Here is an example that pulls values out of the Regexp:
|
45
|
+
#
|
46
|
+
# when /^(.*)'s profile page$/i
|
47
|
+
# user_profile_path(User.find_by_login($1))
|
48
|
+
|
49
|
+
else
|
50
|
+
begin
|
51
|
+
page_name =~ /^the (.*) page$/
|
52
|
+
path_components = $1.split(/\s+/)
|
53
|
+
self.send(path_components.push('path').join('_').to_sym)
|
54
|
+
rescue NoMethodError, ArgumentError
|
55
|
+
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
|
56
|
+
"Now, go and add a mapping in #{__FILE__}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# :nocov:
|
61
|
+
|
62
|
+
def url_to(path)
|
63
|
+
if is_url?(path)
|
64
|
+
path
|
65
|
+
else
|
66
|
+
begin
|
67
|
+
URI.parse(SimpliTest.config_environments[SimpliTest.config_environment] + path).normalize.to_s
|
68
|
+
rescue
|
69
|
+
puts "It seems that the #{SimpliTest.config_environment} enviroment has not been set up. Please add it to features/config/environments.yml"
|
70
|
+
raise "Unidentified Environment Requested!!"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def is_url?(path)
|
76
|
+
uri = URI.parse(path)
|
77
|
+
uri if uri.scheme =~ /^https?$/
|
78
|
+
rescue URI::BadURIError, URI::InvalidURIError
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
def is_relative?(path)
|
83
|
+
uri = URI.parse(path)
|
84
|
+
uri.relative?
|
85
|
+
end
|
86
|
+
|
87
|
+
def is_valid_url_or_path?(path)
|
88
|
+
is_url?(path) || is_relative?(path)
|
89
|
+
end
|
90
|
+
|
91
|
+
def is_javascript_href?(href)
|
92
|
+
href =~ /^(javascript|#)/
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_dom_tree(url)
|
96
|
+
Nokogiri::HTML(open(url))
|
97
|
+
end
|
98
|
+
|
99
|
+
def valid_assets_links_from(nokogiri_html_document)
|
100
|
+
doc = nokogiri_html_document
|
101
|
+
links = stylesheet_references_on(doc) + javascript_references_on(doc)
|
102
|
+
links.select{ |l| !is_javascript_href?(l) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def stylesheet_references_on(doc)
|
106
|
+
doc.css('link').collect{|l| l['href'] }.compact
|
107
|
+
end
|
108
|
+
|
109
|
+
def javascript_references_on(doc)
|
110
|
+
doc.css('script').collect{|l| l['src']}.compact
|
111
|
+
end
|
112
|
+
|
113
|
+
def links_on(doc)
|
114
|
+
doc.css('a').collect{|l| l['href']}.compact.select{ |l| !is_javascript_href?(l) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate_response_from(page_name, href)
|
118
|
+
begin
|
119
|
+
root_path = path_to(page_name)
|
120
|
+
uri = is_relative?(href) ? (URI.join(root_path, href)) : URI.parse(href)
|
121
|
+
response = get_response_from(uri)
|
122
|
+
valid_status_groups = [Net::HTTPRedirection, Net::HTTPInformation, Net::HTTPSuccess ]
|
123
|
+
valid_status_groups.should include(response.class.superclass)
|
124
|
+
rescue RSpec::Expectations::ExpectationNotMetError
|
125
|
+
message = "Received a #{response.code} #{ response.msg } from #{href} on #{page_name}"
|
126
|
+
fail message
|
127
|
+
rescue
|
128
|
+
message = "Invalid reference: #{href} found on #{page_name} page"
|
129
|
+
fail message
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
#this returns a hash with a response code and the url to help provide good fail detail
|
134
|
+
def get_response_from(uri)
|
135
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
136
|
+
http.read_timeout = http.open_timeout = SimpliTest.config[:settings]["HTTP_TIMEOUT"] || 3
|
137
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
138
|
+
if uri.scheme == 'https'
|
139
|
+
http.use_ssl = true
|
140
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
141
|
+
end
|
142
|
+
http.request(request)
|
143
|
+
end
|
144
|
+
|
145
|
+
#FIXME: Code not used. Should be deleted
|
146
|
+
def url_in_new_window
|
147
|
+
if handles = page.driver.browser.window_handles rescue nil
|
148
|
+
new_window = handles.last
|
149
|
+
page.within_window(new_window) do
|
150
|
+
return without_trailing_slash(current_url)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def without_trailing_slash(url)
|
156
|
+
url.chomp('/')
|
157
|
+
end
|
158
|
+
|
159
|
+
def with_encoded_white_space(string)
|
160
|
+
string.gsub(' ', '%20')
|
161
|
+
end
|
162
|
+
|
163
|
+
def with_unencoded_white_space(string)
|
164
|
+
string.gsub('%20', ' ')
|
165
|
+
end
|
166
|
+
|
167
|
+
def normalize(url)
|
168
|
+
normalized_uri = URI.parse(url).normalize
|
169
|
+
url = normalized_uri.to_s
|
170
|
+
encoded_url = URI::encode(url)
|
171
|
+
without_trailing_slash(encoded_url)
|
172
|
+
end
|
173
|
+
|
174
|
+
def normalize_path(path)
|
175
|
+
if path = is_url?(path)
|
176
|
+
path = path.path
|
177
|
+
end
|
178
|
+
with_encoded_white_space(without_trailing_slash(path))
|
179
|
+
end
|
180
|
+
|
181
|
+
def wait_for(left_argument, right_argument)
|
182
|
+
called_at = Time.now
|
183
|
+
until left_argument > right_argument do
|
184
|
+
past_wait_time = called_at < Time.now - SimpliTest.config['HTTP_TIMEOUT']
|
185
|
+
return if past_wait_time
|
186
|
+
sleep 1
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def comparable_urls_for(target_url, source_url)
|
191
|
+
is_url?(target_url) ? [target_url, source_url].map{|u| normalize(u)} : [target_url, URI.parse(source_url).path]
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
World(NavigationHelpers)
|