SimpliTest 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +22 -0
  3. data/SimpliTest.gemspec +42 -0
  4. data/bin/SimpliTest +22 -0
  5. data/lib/SimpliTest.rb +2 -0
  6. data/lib/SimpliTest/cli/main.rb +305 -0
  7. data/lib/SimpliTest/config/configuration.rb +107 -0
  8. data/lib/SimpliTest/config/directory_paths.rb +36 -0
  9. data/lib/SimpliTest/config/environment.rb +67 -0
  10. data/lib/SimpliTest/config/local_environment.rb +20 -0
  11. data/lib/SimpliTest/config/profiles/chrome.rb +18 -0
  12. data/lib/SimpliTest/config/profiles/firefox.rb +14 -0
  13. data/lib/SimpliTest/config/profiles/internet_explorer.rb +12 -0
  14. data/lib/SimpliTest/config/profiles/phantom.rb +9 -0
  15. data/lib/SimpliTest/config/profiles/phantom_debug.rb +12 -0
  16. data/lib/SimpliTest/config/profiles/selenium.rb +13 -0
  17. data/lib/SimpliTest/config/screen_size.rb +25 -0
  18. data/lib/SimpliTest/config/steps.rb +8 -0
  19. data/lib/SimpliTest/helpers/data_validation.rb +60 -0
  20. data/lib/SimpliTest/helpers/file.rb +38 -0
  21. data/lib/SimpliTest/helpers/project_setup.rb +186 -0
  22. data/lib/SimpliTest/helpers/step_helpers/custom_chrome_helpers.rb +14 -0
  23. data/lib/SimpliTest/helpers/step_helpers/custom_date_helpers.rb +64 -0
  24. data/lib/SimpliTest/helpers/step_helpers/custom_form_helpers.rb +66 -0
  25. data/lib/SimpliTest/helpers/step_helpers/custom_phantomjs_helpers.rb +49 -0
  26. data/lib/SimpliTest/helpers/step_helpers/custom_selenium_helpers.rb +41 -0
  27. data/lib/SimpliTest/helpers/step_helpers/html_selectors_helpers.rb +154 -0
  28. data/lib/SimpliTest/helpers/step_helpers/navigation_helpers.rb +196 -0
  29. data/lib/SimpliTest/helpers/step_helpers/tolerance_for_sync_issues.rb +38 -0
  30. data/lib/SimpliTest/helpers/step_helpers/within_helpers.rb +6 -0
  31. data/lib/SimpliTest/helpers/windows_ui.rb +52 -0
  32. data/lib/SimpliTest/steps/debugging_steps.rb +19 -0
  33. data/lib/SimpliTest/steps/form_steps.rb +352 -0
  34. data/lib/SimpliTest/steps/form_verification_steps.rb +190 -0
  35. data/lib/SimpliTest/steps/navigation_steps.rb +47 -0
  36. data/lib/SimpliTest/steps/scoper.rb +42 -0
  37. data/lib/SimpliTest/steps/verification_steps.rb +306 -0
  38. data/lib/SimpliTest/tasks/document.rb +169 -0
  39. data/lib/SimpliTest/tasks/examples.rb +18 -0
  40. data/lib/SimpliTest/tasks/internal_release.rb +39 -0
  41. data/lib/SimpliTest/tasks/testinstall.rb +5 -0
  42. data/lib/SimpliTest/templates/NewSimpliTestProject/Readme.txt +5 -0
  43. data/lib/SimpliTest/templates/NewSimpliTestProject/cucumber.yml +26 -0
  44. data/lib/SimpliTest/templates/NewSimpliTestProject/documentation/step_definitions.html +87 -0
  45. data/lib/SimpliTest/templates/NewSimpliTestProject/features/specifications/RegressionTests/HelloWorld.feature +4 -0
  46. data/lib/SimpliTest/templates/NewSimpliTestProject/features/specifications/SmokeTest/HelloWorld.feature +4 -0
  47. data/lib/SimpliTest/templates/NewSimpliTestProject/features/specifications/accessibilityTests/HelloWorld.feature +4 -0
  48. data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/environments.yml +11 -0
  49. data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/pages.yml +26 -0
  50. data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/selectors.yml +44 -0
  51. data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/config/settings.yml +26 -0
  52. data/lib/SimpliTest/templates/NewSimpliTestProject/features/support/env.rb +33 -0
  53. data/lib/SimpliTest/templates/NewSimpliTestProject/license.txt +30 -0
  54. data/lib/SimpliTest/templates/document/css/style.css +28 -0
  55. data/lib/SimpliTest/templates/document/index.html +60 -0
  56. data/lib/version.rb +3 -0
  57. metadata +395 -0
@@ -0,0 +1,38 @@
1
+ # coding: UTF-8
2
+ # :nocov:
3
+ module ToleranceForSyncIssues
4
+ RETRY_ERRORS = %w[Capybara::ElementNotFound Capybara::ExpectationNotMet
5
+ Spec::Expectations::ExpectationNotMetError RSpec::Expectations::ExpectationNotMetError
6
+ Capybara::Poltergeist::ClickFailed Selenium::WebDriver::Error::StaleElementReferenceError
7
+ Selenium::WebDriver::Error::NoAlertPresentError Capybara::Poltergeist::JavascriptError
8
+ Capybara::Driver::Webkit::WebkitInvalidResponseError Capybara::Webkit::InvalidResponseError]
9
+
10
+ # This is similiar but not entirely the same as Capybara::Node::Base#wait_until or Capybara::Session#wait_until
11
+ def patiently(seconds=Capybara.default_max_wait_time, &block)
12
+ #puts "Tried waiting"
13
+ old_wait_time = Capybara.default_max_wait_time
14
+ # dont make nested wait_untils use up all the alloted time
15
+ Capybara.default_max_wait_time = 0 # for we are a jealous gem
16
+ if page.driver.wait?
17
+ start_time = Time.now
18
+ begin
19
+ block.call
20
+ rescue Exception => e
21
+ raise e unless RETRY_ERRORS.include?(e.class.name)
22
+ puts "Failed: #{e.message}" if SimpliTest.mode == 'DEBUG'
23
+ wait_time = SimpliTest.config_settings ? SimpliTest.config_settings['MAX_WAIT_TIME'] : 5
24
+ raise e if (Time.now - start_time) >= wait_time
25
+ sleep(0.1)
26
+ raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Time.now == start_time
27
+ puts "Retrying..." if SimpliTest.mode == 'DEBUG'
28
+ retry
29
+ end
30
+ else
31
+ block.call
32
+ end
33
+ ensure
34
+ Capybara.default_max_wait_time = old_wait_time
35
+ end
36
+ end
37
+ # :nocov:
38
+ World(ToleranceForSyncIssues)
@@ -0,0 +1,6 @@
1
+ module WithinHelpers
2
+ def with_scope(locator)
3
+ locator ? within(*selector_for(locator)) { yield } : yield
4
+ end
5
+ end
6
+ World(WithinHelpers)
@@ -0,0 +1,52 @@
1
+ module WindowsUIHelpers
2
+ # :nocov:
3
+ # button constants
4
+ BUTTONS_OK = 0
5
+ BUTTONS_OKCANCEL = 1
6
+ BUTTONS_ABORTRETRYIGNORE = 2
7
+ BUTTONS_YESNO = 4
8
+
9
+ # return code constants
10
+ CLICKED_OK = 1
11
+ CLICKED_CANCEL = 2
12
+ CLICKED_ABORT = 3
13
+ CLICKED_RETRY = 4
14
+ CLICKED_IGNORE = 5
15
+ CLICKED_YES = 6
16
+ CLICKED_NO = 7
17
+ APP_TITLE ='SimpliTest'
18
+
19
+ def message_box(txt, title, buttons)
20
+ MessageBox::MessageBoxA nil, txt, title, buttons
21
+ end
22
+
23
+ def user_consents_via_prompt?(question)
24
+ message_box(question, APP_TITLE, BUTTONS_YESNO) == CLICKED_YES
25
+ end
26
+
27
+ def user_informed_via_prompt?(message)
28
+ message_box(message, APP_TITLE, BUTTONS_OK) == CLICKED_OK
29
+ end
30
+ # :nocov:
31
+ end
32
+
33
+
34
+ # Create module as body for an importer instance
35
+ module MessageBox
36
+ # Load importer part of fiddle (ffi) library
37
+ require 'fiddle/import'
38
+
39
+ # Extend this module to an importer
40
+ extend Fiddle::Importer
41
+ # Load 'user32' dynamic library into this importer
42
+ dlload 'user32'
43
+ # Set C aliases to this importer for further understanding of function signatures
44
+ typealias 'HANDLE', 'void*'
45
+ typealias 'HWND', 'HANDLE'
46
+ typealias 'LPCSTR', 'const char*'
47
+ typealias 'LPCWSTR', 'const wchar_t*'
48
+ typealias 'UINT', 'unsigned int'
49
+ # Import C functions from loaded libraries and set them as module functions
50
+ extern 'int MessageBoxA(HWND, LPCSTR, LPCSTR, UINT)'
51
+ extern 'int MessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT)'
52
+ end
@@ -0,0 +1,19 @@
1
+ #Example: Then show me the page
2
+ Then /^show me the page$/ do
3
+ save_and_open_page
4
+ end
5
+
6
+ #Example: And I wait 10 seconds
7
+ When /^I wait (\d+) second(?:|s)$/ do |seconds|
8
+ seconds = seconds.to_i #TODO: Write a God Damned Transformer for this for Christ's sake!!!!!
9
+ sleep(seconds)
10
+ end
11
+
12
+ #Example: And I take a screenshot
13
+ And /^I take a screenshot$/ do
14
+ timestamp = Time.now.strftime('%b_%e_%Y_%m_%M_%p')
15
+ dir = File.join(SimpliTest.config_support_directory, 'files', 'screenshots')
16
+ FileUtils.mkdir_p(dir) unless Dir.exists?(dir)
17
+ file_name = File.join(dir, "screenshot-#{timestamp}") + '.png'
18
+ capture_screenshot file_name
19
+ end
@@ -0,0 +1,352 @@
1
+ # Use this to fill in an entire form with data from a table. Example:
2
+ #
3
+ # When I fill in the following:
4
+ # | Account Number | 5002 |
5
+ # | Expiry date | 2009-11-01 |
6
+ # | Note | Nice guy |
7
+ # | Wants Email? | |
8
+ # | Sex (select) | Male |
9
+ # | Accept user agrement (checkbox) | check |
10
+ # | Send me letters (checkbox) | uncheck |
11
+ # | radio 1 (radio) | choose |
12
+ # | Avatar (file) | avatar.png |
13
+ #
14
+ #Example: When I fill in the following:
15
+ When /^(?:|I )fill in the following:$/ do |fields|
16
+
17
+ select_tag = /^(.+\S+)\s*(?:\(select\))$/
18
+ check_box_tag = /^(.+\S+)\s*(?:\(checkbox\))$/
19
+ radio_button = /^(.+\S+)\s*(?:\(radio\))$/
20
+ file_field = /^(.+\S+)\s*(?:\(file\))$/
21
+
22
+ fields.rows_hash.each do |name, value|
23
+ case name
24
+ when select_tag
25
+ step %(I select "#{value}" from "#{$1}")
26
+ when check_box_tag
27
+ case value
28
+ when 'check'
29
+ step %(I check "#{$1}")
30
+ when 'uncheck'
31
+ step %(I uncheck "#{$1}")
32
+ else
33
+ raise 'checkbox values: check|uncheck!'
34
+ end
35
+ when radio_button
36
+ step %{I choose "#{$1}"}
37
+ when file_field
38
+ #step %{I attach the file "#{value}" to "#{$1}"}
39
+ else
40
+ step %{I fill in "#{name}" with "#{value}"}
41
+ end
42
+ end
43
+ end
44
+
45
+ #************************ UPLOAD A FILE *****************************************
46
+ #Example: When I attach the file "sample.txt" to "field_name"
47
+ When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |file, field|
48
+ dir = File.join(SimpliTest.config_support_directory, 'files', 'attachments')
49
+ FileUtils.mkdir_p(dir) unless Dir.exists?(dir)
50
+ path = File.join(dir, file)
51
+ raise RuntimeError, "file '#{path}' does not exists" unless File.exists?(path)
52
+ attach_file(field, path)
53
+ end
54
+
55
+ #************************ UPLOAD A FILE *****************************************
56
+
57
+ #************************ TEXT FIELDS ********************************************
58
+
59
+
60
+ #Example: When I fill in "Name" with "my name"
61
+ When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value|
62
+ selector, selector_type = selector_for(field)
63
+ if ['xpath', 'css'].include?(selector_type)
64
+ patiently do
65
+ element = find(selector_type.to_sym, selector)
66
+ element.set value
67
+ end
68
+ else
69
+ patiently { fill_in(field, :with => value) }
70
+ end
71
+ end
72
+
73
+ #TODO: Deprecate the step below
74
+ #Example: See Gist
75
+ When /^(?:|I )fill in "([^"]*)" with:$/ do |field, value|
76
+ selector, selector_type = selector_for(field)
77
+ if ['xpath', 'css'].include?(selector_type)
78
+ patiently do
79
+ element = find(selector_type.to_sym, selector)
80
+ element.set value
81
+ end
82
+ else
83
+ patiently { fill_in(field, :with => value) }
84
+ end
85
+ end
86
+
87
+ #Example: And I enter "I made this" in the "Describe yourself" field
88
+ When /^I enter "(.*?)" in the "(.*?)" field$/ do |value, field|
89
+ patiently do
90
+ step %Q{I fill in "#{field}" with "#{value}"}
91
+ step %Q{I move focus away from "#{field}"}
92
+ end
93
+ end
94
+
95
+ #TODO: Clean this code up, blur should handle xpath and name attributes as well
96
+ #Example: Then I key in the date "12/01/2013" in the "Date" field
97
+ When /^I key in the date "(.*?)" in the "(.*?)" field$/ do |date_rule, field|
98
+ selector, selector_type = selector_for(field)
99
+ value = calculated_date_from(date_rule)
100
+ raise "xpath is not yet supported for masked input. Please use the css selector instead" if selector_type == 'xpath'
101
+ patiently do
102
+ field = get_element_from(selector)
103
+ field.set(value)
104
+ end
105
+ end
106
+
107
+ #Example: When I key in "22031" in the "Location" field
108
+ When /^I key in "(.*?)" in the "(.*)" field$/ do |text, field|
109
+ selector, selector_type = selector_for(field)
110
+ if selector_type == 'other'
111
+ element = find_field(selector)
112
+ else
113
+ element = find(selector_type.to_sym, selector)
114
+ end
115
+ key_in text, element
116
+ end
117
+
118
+
119
+ #************************ END TEXT FIELDS ****************************************
120
+
121
+
122
+ #************************ DROP DOWNS**********************************************
123
+
124
+
125
+ #Example: When I select "Male" from "Sex"
126
+ When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, select_field_name_id_or_text|
127
+ selector, selector_type = selector_for(select_field_name_id_or_text)
128
+ if selector_type == 'other'
129
+ patiently { select(value, :from => select_field_name_id_or_text) }
130
+ else
131
+ field = find(selector_type.to_sym, selector)
132
+ patiently { field.select value }
133
+ end
134
+ end
135
+
136
+
137
+ #************************ END DROP DOWNS******************************************
138
+
139
+
140
+ #************************ CHECKBOXES *********************************************
141
+
142
+
143
+ #Example: And I check "Accept user agrement"
144
+ When /^(?:|I )check "([^"]*)"$/ do |field|
145
+ selector, selector_type = selector_for(field)
146
+ if selector_type == 'other'
147
+ patiently { check(field) }
148
+ else
149
+ field = find(selector_type.to_sym, selector)
150
+ field.set(true)
151
+ end
152
+ end
153
+
154
+ #Example: When I uncheck "Send me letters"
155
+ When /^(?:|I )uncheck "([^"]*)"$/ do |field|
156
+ patiently { uncheck(field) }
157
+ end
158
+
159
+
160
+ #************************ END CHECKBOXES******************************************
161
+
162
+
163
+ #************************ MULTI SELECT BOXES *************************************
164
+
165
+
166
+ #Example: When I select following values from "Filters": Accepts Gherkin Table
167
+ When /^(?:I|i) select following values from "([^"]*)":$/ do |field, values|
168
+ values = values.transpose.raw
169
+ if values.size > 1
170
+ raise 'table should have only one column in this step!'
171
+ else
172
+ values = values.first
173
+ end
174
+
175
+ values.each do |value|
176
+ patiently { select(value, :from => field) }
177
+ end
178
+ end
179
+
180
+ #Example: When I unselect following values from "Filters": Accepts Gherkin Table
181
+ When /^(?:I|i) unselect following values from "([^"]*)":$/ do |field, values|
182
+ values = values.transpose.raw
183
+ if values.size > 1
184
+ raise 'table should have only one column in this step!'
185
+ else
186
+ values = values.first
187
+ end
188
+
189
+ values.each do |value|
190
+ patiently { unselect(value, :from => field) }
191
+ end
192
+ end
193
+
194
+
195
+ #************************ END MULTI SELECT BOXES *********************************
196
+
197
+
198
+ #************************ RADIO BUTTONS*******************************************
199
+
200
+
201
+ #Example: When I choose "radio 1"
202
+ When /^(?:|I )choose "([^"]*)"$/ do |field|
203
+ patiently { choose(field) }
204
+ end
205
+
206
+ #************************ END RADIO BUTTONS***************************************
207
+
208
+
209
+ #************************ BUTTONS AND LINKS***************************************
210
+
211
+
212
+ #Example: When I press "Submit"
213
+ When /^(?:|I )press "([^"]*)"$/ do |button|
214
+ patiently { click_on(button) }
215
+ end
216
+ #Example: When I press the 4th instance of "nextButton"
217
+ Given /^I press the (first|last|[0-9]+(?:th|st|rd|nd)) instance of "(.*?)"$/ do |index,link|
218
+ index = numerize index
219
+ locator, selector_type = selector_for(link)
220
+ selector_type = selector_type == 'xpath' ? :xpath : :css
221
+ patiently do
222
+ begin
223
+ elements = all(selector_type, locator)
224
+ element = elements[index]
225
+ element.click
226
+ rescue
227
+ raise Capybara::ElementNotFound
228
+ end
229
+ end
230
+ end
231
+
232
+ #Example: When I click the next page button
233
+ When /^I click the (first|last|next|previous) page button$/ do |index|
234
+ pagination_element_for(index).click
235
+ end
236
+
237
+
238
+ #Example: When I click the "Submit" button
239
+ When /^I click the "(.*?)" (?:button|link)$/ do |button_or_link|
240
+ patiently do
241
+ element = get_button_or_link_from(button_or_link)
242
+ click_element(element)
243
+ end
244
+ end
245
+
246
+
247
+ #************************ END BUTTONS AND LINKS***********************************
248
+
249
+
250
+ #************************ PAGINATION ***********************************
251
+ #Example: When I go to page 1
252
+ When /^I go to page (\d+)$/ do |page_number|
253
+ pagination_links_for(page_number).first.click
254
+ end
255
+
256
+
257
+ #************************ KEYBOARD EVENTS ****************************************
258
+
259
+ #Example: Not implemented yet
260
+ When /^I move focus away from "(.*)"$/ do |locator|
261
+ element = get_element_from(locator)
262
+ tab_on element
263
+ end
264
+
265
+ #Example: When I press keydown on "LocationCSSSelector"
266
+ When /^I press keydown on "(.*)"$/ do |locator|
267
+ #selector, selector_type = selector_for(locator)
268
+ #element = get_element_from(locator)
269
+ #if selector_type == 'css'
270
+ #script = "var e = $.Event('keydown');e.keyCode = 40;$('#{locator}').trigger(e)"
271
+ #script = "var e = $.Event('keydown', { keyCode: 40 }); $('#nameTxtBox').trigger(e)"
272
+ #execute_js script
273
+ #keydown_on(element)
274
+ #else
275
+ #raise "OnlyCSSSelectorsAreSupported"
276
+ #end
277
+ end
278
+
279
+
280
+
281
+ #************************ END KEYBOARD EVENTS ************************************
282
+
283
+
284
+ #************************ MOUSE EVENTS *******************************************
285
+ #Example: And I hover over "BidPlansMenu"
286
+ Then /^I hover over "(.*?)"$/ do |locator|
287
+ element = get_element_from(locator)
288
+ element.hover
289
+ end
290
+
291
+ #************************ END MOUSE EVENTS ***************************************
292
+
293
+ #************************ MODAL AND DIALOGS **************************************
294
+
295
+
296
+ #Example: And I accept the confirmation dialog
297
+ When /^I accept the confirmation dialog box$/ do
298
+ page.driver.browser.switch_to.alert.accept
299
+
300
+ #accept_confirmation
301
+ end
302
+
303
+ #Example: And I switch to the iframe
304
+ And /^(?:|I )[Ss]witch to the iframe$/ do
305
+ page.driver.browser.switch_to.frame(0)
306
+ end
307
+
308
+ #************************ END MODAL AND DIALOGS **********************************
309
+
310
+ #Example: Then I attach file "testAttachment.txt" to "File"
311
+ Then /^I attach file "([^"]*)" to "([^"]*)"$/ do |file, field|
312
+ dir = File.join(SimpliTest.config_support_directory, 'files', 'attachments')
313
+ FileUtils.mkdir_p(dir) unless Dir.exists?(dir)
314
+ path = File.join(dir, file)
315
+ raise RuntimeError, "file '#{path}' does not exists" unless File.exists?(path)
316
+
317
+ element = get_element_from(field)
318
+ element.send_keys(path)
319
+ end
320
+
321
+ # Enter's current date in a field (e.g., 03/01/2016)
322
+
323
+ #Example: Then I enter today's date in the "date" field"
324
+ Then /^(?:|I )[Ee]nter today's date in the "([^"]*)" field$/ do |locator|
325
+ element = get_element_from(locator)
326
+ element.set Date.today.strftime('%m/%d/%Y')
327
+ end
328
+
329
+ #Example: Then I verify "date" field has today's date
330
+ Then(/^I verify "([^"]*)" field has today's date$/) do |locator|
331
+ date_td = get_element_from(locator).value
332
+ date_td.should == Date.today.strftime('%m/%d/%Y')
333
+ end
334
+
335
+ #Example: When I right-click "some element" and then click "Some Link" option
336
+ When /^I right-click on "(.*?)" and then click the "(.*?)" option$/ do | locator, link|
337
+
338
+ element = find('.x-grid-cell',:text => locator, :exact => true)
339
+ element.right_click
340
+ menulink = get_button_or_link_from(link)
341
+ click_element(menulink)
342
+
343
+ end
344
+
345
+ #Example: When I click the "Submit" tab
346
+ When /^I click the "(.*?)" tab$/ do |button_or_link|
347
+ patiently do
348
+ element = get_button_or_link_from(button_or_link)
349
+ click_element(element)
350
+ end
351
+ end
352
+