testcentricity 2.4.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +29 -0
  3. data/.rspec +2 -1
  4. data/.rubocop.yml +38 -0
  5. data/.ruby-version +1 -1
  6. data/.simplecov +9 -0
  7. data/.yardopts +3 -0
  8. data/CHANGELOG.md +275 -0
  9. data/CODE_OF_CONDUCT.md +13 -0
  10. data/{LICENSE.txt → LICENSE.md} +3 -4
  11. data/README.md +938 -1384
  12. data/Rakefile +63 -1
  13. data/config/cucumber.yml +145 -0
  14. data/config/locales/en-US.yml +56 -0
  15. data/config/test_data/LOCAL_data.yml +11 -0
  16. data/config/test_data/data.yml +10 -0
  17. data/features/deep_links.feature +26 -0
  18. data/features/login.feature +30 -0
  19. data/features/navigation.feature +31 -0
  20. data/features/step_definitions/generic_steps.rb +72 -0
  21. data/features/support/android/screens/about_screen.rb +11 -0
  22. data/features/support/android/screens/base_app_screen.rb +29 -0
  23. data/features/support/android/screens/checkout_address_screen.rb +17 -0
  24. data/features/support/android/screens/checkout_payment_screen.rb +22 -0
  25. data/features/support/android/screens/login_screen.rb +18 -0
  26. data/features/support/android/screens/products_screen.rb +13 -0
  27. data/features/support/android/screens/saucebot_screen.rb +16 -0
  28. data/features/support/android/screens/webview_screen.rb +13 -0
  29. data/features/support/android/sections/nav_widgets/nav_menu.rb +39 -0
  30. data/features/support/env.rb +61 -0
  31. data/features/support/hooks.rb +135 -0
  32. data/features/support/ios/screens/about_screen.rb +11 -0
  33. data/features/support/ios/screens/base_app_screen.rb +19 -0
  34. data/features/support/ios/screens/checkout_address_screen.rb +17 -0
  35. data/features/support/ios/screens/checkout_payment_screen.rb +22 -0
  36. data/features/support/ios/screens/login_screen.rb +18 -0
  37. data/features/support/ios/screens/products_screen.rb +13 -0
  38. data/features/support/ios/screens/saucebot_screen.rb +16 -0
  39. data/features/support/ios/screens/webview_screen.rb +13 -0
  40. data/features/support/ios/sections/list_items/product_cell_item.rb +13 -0
  41. data/features/support/ios/sections/modals/base_modal.rb +23 -0
  42. data/features/support/ios/sections/modals/logout_modal.rb +6 -0
  43. data/features/support/ios/sections/modals/reset_app_state_modal.rb +6 -0
  44. data/features/support/ios/sections/nav_widgets/nav_bar.rb +31 -0
  45. data/features/support/ios/sections/nav_widgets/nav_menu.rb +41 -0
  46. data/features/support/shared_components/screens/base_app_screen.rb +31 -0
  47. data/features/support/shared_components/screens/checkout_address_screen.rb +17 -0
  48. data/features/support/shared_components/screens/checkout_payment_screen.rb +22 -0
  49. data/features/support/shared_components/screens/login_screen.rb +39 -0
  50. data/features/support/shared_components/screens/saucebot_screen.rb +17 -0
  51. data/features/support/shared_components/screens/webview_screen.rb +12 -0
  52. data/features/support/shared_components/sections/nav_menu.rb +58 -0
  53. data/features/support/world_data.rb +12 -0
  54. data/features/support/world_pages.rb +26 -0
  55. data/lib/testcentricity/app_core/appium_connect_helper.rb +343 -111
  56. data/lib/testcentricity/app_core/screen_object.rb +252 -0
  57. data/lib/testcentricity/app_core/screen_objects_helper.rb +29 -201
  58. data/lib/testcentricity/app_core/{screen_sections_helper.rb → screen_section.rb} +40 -105
  59. data/lib/testcentricity/app_elements/app_element_helper.rb +17 -8
  60. data/lib/testcentricity/app_elements/checkbox.rb +3 -3
  61. data/lib/testcentricity/data_objects/environment.rb +133 -39
  62. data/lib/testcentricity/version.rb +1 -1
  63. data/lib/testcentricity.rb +4 -129
  64. data/reports/.keep +1 -0
  65. data/spec/fixtures/page_object.rb +22 -0
  66. data/spec/fixtures/page_section_object.rb +21 -0
  67. data/spec/fixtures/screen_object.rb +16 -0
  68. data/spec/fixtures/screen_section_object.rb +16 -0
  69. data/spec/spec_helper.rb +28 -9
  70. data/spec/testcentricity/elements/button_spec.rb +18 -0
  71. data/spec/testcentricity/elements/checkbox_spec.rb +28 -0
  72. data/spec/testcentricity/elements/image_spec.rb +13 -0
  73. data/spec/testcentricity/elements/label_spec.rb +18 -0
  74. data/spec/testcentricity/elements/list_spec.rb +13 -0
  75. data/spec/testcentricity/elements/ui_element_spec.rb +72 -0
  76. data/spec/testcentricity/mobile/appium_connect_spec.rb +117 -0
  77. data/spec/testcentricity/mobile/screen_object_spec.rb +63 -0
  78. data/spec/testcentricity/mobile/screen_section_object_spec.rb +56 -0
  79. data/spec/testcentricity/version_spec.rb +7 -0
  80. data/spec/testcentricity/web/browser_spec.rb +41 -0
  81. data/spec/testcentricity/web/local_webdriver_spec.rb +86 -0
  82. data/spec/testcentricity/web/mobile_webdriver_spec.rb +123 -0
  83. data/spec/testcentricity/web/page_object_spec.rb +85 -0
  84. data/spec/testcentricity/web/page_section_object_spec.rb +72 -0
  85. data/testcentricity.gemspec +28 -27
  86. metadata +196 -127
  87. data/.ruby-gemset +0 -1
  88. data/Gemfile.lock +0 -93
  89. data/bin/console +0 -14
  90. data/bin/setup +0 -8
  91. data/lib/devices/devices.yml +0 -352
  92. data/lib/testcentricity/app_core/appium_server.rb +0 -69
  93. data/lib/testcentricity/browser_helper.rb +0 -174
  94. data/lib/testcentricity/data_objects/data_objects_helper.rb +0 -78
  95. data/lib/testcentricity/data_objects/excel_helper.rb +0 -242
  96. data/lib/testcentricity/exception_queue_helper.rb +0 -111
  97. data/lib/testcentricity/utility_helpers.rb +0 -32
  98. data/lib/testcentricity/web_core/drag_drop_helper.rb +0 -15
  99. data/lib/testcentricity/web_core/page_objects_helper.rb +0 -677
  100. data/lib/testcentricity/web_core/page_sections_helper.rb +0 -895
  101. data/lib/testcentricity/web_core/webdriver_helper.rb +0 -588
  102. data/lib/testcentricity/web_elements/button.rb +0 -8
  103. data/lib/testcentricity/web_elements/cell_button.rb +0 -8
  104. data/lib/testcentricity/web_elements/cell_checkbox.rb +0 -38
  105. data/lib/testcentricity/web_elements/cell_element.rb +0 -69
  106. data/lib/testcentricity/web_elements/cell_image.rb +0 -8
  107. data/lib/testcentricity/web_elements/cell_radio.rb +0 -31
  108. data/lib/testcentricity/web_elements/checkbox.rb +0 -100
  109. data/lib/testcentricity/web_elements/file_field.rb +0 -45
  110. data/lib/testcentricity/web_elements/image.rb +0 -34
  111. data/lib/testcentricity/web_elements/label.rb +0 -8
  112. data/lib/testcentricity/web_elements/link.rb +0 -8
  113. data/lib/testcentricity/web_elements/list.rb +0 -100
  114. data/lib/testcentricity/web_elements/list_button.rb +0 -8
  115. data/lib/testcentricity/web_elements/list_checkbox.rb +0 -38
  116. data/lib/testcentricity/web_elements/list_element.rb +0 -61
  117. data/lib/testcentricity/web_elements/list_radio.rb +0 -31
  118. data/lib/testcentricity/web_elements/radio.rb +0 -74
  119. data/lib/testcentricity/web_elements/select_list.rb +0 -208
  120. data/lib/testcentricity/web_elements/siebel_open_ui_helper.rb +0 -15
  121. data/lib/testcentricity/web_elements/table.rb +0 -612
  122. data/lib/testcentricity/web_elements/textfield.rb +0 -114
  123. data/lib/testcentricity/web_elements/ui_elements_helper.rb +0 -532
  124. data/lib/testcentricity/world_extensions.rb +0 -26
  125. data/my_templates/default/method_details/setup.rb +0 -3
  126. data/spec/testcentricity_spec.rb +0 -9
@@ -1,242 +0,0 @@
1
- require 'time'
2
- require 'chronic'
3
- require 'faker'
4
- require 'spreadsheet'
5
-
6
-
7
- module TestCentricity
8
- class ExcelData
9
- @mru = {}
10
-
11
- def self.worksheet_exists?(file, sheet)
12
- exists = false
13
- if File.exist?(file)
14
- work_book = Spreadsheet.open file
15
- worksheets = work_book.worksheets
16
- worksheets.each do |worksheet|
17
- if worksheet.name == sheet
18
- exists = true
19
- break
20
- end
21
- end
22
- end
23
- exists
24
- end
25
-
26
- def self.rowspec_exists?(file, sheet, rowspec)
27
- exists = false
28
- if worksheet_exists?(file, sheet)
29
- work_book = Spreadsheet.open file
30
- work_sheet = work_book.worksheet sheet
31
- # get column headings from row 0 of worksheet
32
- headings = work_sheet.row(0)
33
- # if rowspec is a string then we have to find a matching row name
34
- if rowspec.is_a? String
35
- column_number = 0
36
- exists = false
37
- headings.each do |heading|
38
- if heading == 'ROW_NAME'
39
- exists = true
40
- break
41
- end
42
- column_number += 1
43
- end
44
- raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless exists
45
- # find first cell in ROW_NAME column containing a string that matches the rowspec parameter
46
- exists = false
47
- row_number = 0
48
- work_sheet.each do |row|
49
- if row[column_number] == rowspec
50
- exists = true
51
- break
52
- end
53
- row_number += 1
54
- end
55
- end
56
- end
57
- exists
58
- end
59
-
60
- def self.read_row_from_pool(file, sheet, rowspec, columns = nil)
61
- raise "File #{file} does not exists" unless File.exist?(file)
62
- work_book = Spreadsheet.open file
63
- work_sheet = work_book.worksheet sheet
64
-
65
- pool_spec_key = "#{sheet}:#{rowspec}"
66
- if @mru.key?(pool_spec_key)
67
- pool_spec = @mru[pool_spec_key]
68
- row_start = pool_spec[:start_row]
69
- row_end = pool_spec[:num_rows]
70
- pool_rows = (row_start..row_start + row_end - 1).to_a
71
- mru_rows = pool_spec[:used_rows]
72
- new_row = pool_rows.sample.to_i
73
- if mru_rows.size == pool_spec[:num_rows]
74
- mru_rows = [new_row]
75
- else
76
- while mru_rows.include?(new_row)
77
- new_row = pool_rows.sample.to_i
78
- end
79
- mru_rows.push(new_row)
80
- mru_rows.sort!
81
- end
82
-
83
- pool_spec = {
84
- :start_row => row_start,
85
- :num_rows => row_end,
86
- :used_rows => mru_rows
87
- }
88
- else
89
- # get column headings from row 0 of worksheet
90
- headings = work_sheet.row(0)
91
- column_number = 0
92
- found = false
93
- headings.each do |heading|
94
- if heading == 'ROW_NAME'
95
- found = true
96
- break
97
- end
98
- column_number += 1
99
- end
100
- raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless found
101
- # find cell(s) in ROW_NAME column containing a string that matches the rowspec parameter
102
- found = []
103
- row_number = 0
104
- work_sheet.each do |row|
105
- if row[column_number] == rowspec
106
- found.push(row_number)
107
- elsif !found.empty?
108
- break
109
- end
110
- row_number += 1
111
- end
112
- raise "Could not find a row named '#{rowspec}' in worksheet #{sheet}" if found.empty?
113
-
114
- new_row = found.sample.to_i
115
- pool_spec = {
116
- :start_row => found[0],
117
- :num_rows => found.size,
118
- :used_rows => [new_row]
119
- }
120
- end
121
- @mru[pool_spec_key] = pool_spec
122
-
123
- read_row_data(file, sheet, new_row, columns)
124
- end
125
-
126
- def self.read_row_data(file, sheet, rowspec, columns = nil)
127
- raise "File #{file} does not exists" unless File.exist?(file)
128
- work_book = Spreadsheet.open file
129
- work_sheet = work_book.worksheet sheet
130
- # get column headings from row 0 of worksheet
131
- headings = work_sheet.row(0)
132
- # if rowspec is a string then we have to find a matching row name
133
- if rowspec.is_a? String
134
- column_number = 0
135
- found = false
136
- headings.each do |heading|
137
- if heading == 'ROW_NAME'
138
- found = true
139
- break
140
- end
141
- column_number += 1
142
- end
143
- raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless found
144
- # find first cell in ROW_NAME column containing a string that matches the rowspec parameter
145
- found = false
146
- row_number = 0
147
- work_sheet.each do |row|
148
- if row[column_number] == rowspec
149
- found = true
150
- break
151
- end
152
- row_number += 1
153
- end
154
- raise "Could not find a row named '#{rowspec}' in worksheet #{sheet}" unless found
155
- data = work_sheet.row(row_number)
156
- # if rowspec is a number then ensure that it doesn't exceed the number of available rows
157
- elsif rowspec.is_a? Numeric
158
- raise "Row # #{rowspec} is greater than number of rows in worksheet #{sheet}" if rowspec > work_sheet.last_row_index
159
- data = work_sheet.row(rowspec)
160
- end
161
-
162
- # if no columns have been specified, return all columns
163
- columns = headings if columns.nil?
164
- # create results hash table
165
- result = Hash.new
166
- columns.each do |column|
167
- column_number = 0
168
- found = false
169
- headings.each do |heading|
170
- if column == heading
171
- value = data[column_number].to_s
172
- value = calculate_dynamic_value(value) if value.start_with? 'eval!'
173
- result[column] = value
174
- found = true
175
- break
176
- end
177
- column_number += 1
178
- end
179
- raise "Could not find a column named '#{column}' in worksheet #{sheet}" unless found
180
- end
181
- result
182
- end
183
-
184
- def self.read_range_data(file, sheet, rangespec)
185
- raise "File #{file} does not exists" unless File.exist?(file)
186
- work_book = Spreadsheet.open file
187
- work_sheet = work_book.worksheet sheet
188
- # get column headings from row 0 of worksheet
189
- headings = work_sheet.row(0)
190
- column_number = 0
191
- found = false
192
- headings.each do |heading|
193
- if heading == 'ROW_NAME'
194
- found = true
195
- break
196
- end
197
- column_number += 1
198
- end
199
- raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless found
200
- # find cell(s) in ROW_NAME column containing a string that matches the rangespec parameter
201
- found = []
202
- row_number = 0
203
- work_sheet.each do |row|
204
- if row[column_number] == rangespec
205
- found.push(row_number)
206
- elsif !found.empty?
207
- break
208
- end
209
- row_number += 1
210
- end
211
- raise "Could not find a row named '#{rangespec}' in worksheet #{sheet}" if found.empty?
212
-
213
- result = []
214
- found.each do |row|
215
- result.push(read_row_data(file, sheet, row))
216
- end
217
- result
218
- end
219
-
220
- private
221
-
222
- def self.calculate_dynamic_value(value)
223
- test_value = value.split('!', 2)
224
- parameter = test_value[1].split('.', 2)
225
- case parameter[0]
226
- when 'Date'
227
- result = eval("Chronic.parse('#{parameter[1]}')")
228
- when 'FormattedDate', 'FormatDate'
229
- date_time_params = parameter[1].split(' format! ', 2)
230
- date_time = eval("Chronic.parse('#{date_time_params[0].strip}')")
231
- result = date_time.to_s.format_date_time("#{date_time_params[1].strip}")
232
- else
233
- if Faker.constants.include?(parameter[0].to_sym)
234
- result = eval("Faker::#{parameter[0]}.#{parameter[1]}")
235
- else
236
- result = eval(test_value[1])
237
- end
238
- end
239
- result.to_s
240
- end
241
- end
242
- end
@@ -1,111 +0,0 @@
1
- module TestCentricity
2
- class ExceptionQueue
3
- include Capybara::DSL
4
-
5
- @error_queue
6
-
7
- def self.enqueue_assert_equal(expected, actual, error_message)
8
- unless expected == actual
9
- enqueue("#{error_message} to be\n '#{expected}'\nbut found\n '#{actual}'")
10
- enqueue_screenshot
11
- end
12
- end
13
-
14
- def self.enqueue_assert_not_equal(expected, actual, error_message)
15
- unless expected != actual
16
- enqueue("#{error_message} to not be equal to '#{expected}'")
17
- enqueue_screenshot
18
- end
19
- end
20
-
21
- def self.enqueue_exception(error_message)
22
- enqueue(error_message)
23
- end
24
-
25
- def self.post_exceptions
26
- raise @error_queue unless @error_queue.nil?
27
- ensure
28
- @error_queue = nil
29
- end
30
-
31
- def self.enqueue_comparison(state, actual, error_msg)
32
- if state.is_a?(Hash) && state.length == 1
33
- state.each do |key, value|
34
- case key
35
- when :lt, :less_than
36
- enqueue_exception("#{error_msg} be less than #{value} but found '#{actual}'") unless actual < value
37
- when :lt_eq, :less_than_or_equal
38
- enqueue_exception("#{error_msg} be less than or equal to #{value} but found '#{actual}'") unless actual <= value
39
- when :gt, :greater_than
40
- enqueue_exception("#{error_msg} be greater than #{value} but found '#{actual}'") unless actual > value
41
- when :gt_eq, :greater_than_or_equal
42
- enqueue_exception("#{error_msg} be greater than or equal to #{value} but found '#{actual}'") unless actual >= value
43
- when :starts_with
44
- enqueue_exception("#{error_msg} start with '#{value}' but found '#{actual}'") unless actual.start_with?(value)
45
- when :ends_with
46
- enqueue_exception("#{error_msg} end with '#{value}' but found '#{actual}'") unless actual.end_with?(value)
47
- when :contains
48
- enqueue_exception("#{error_msg} contain '#{value}' but found '#{actual}'") unless actual.include?(value)
49
- when :not_contains, :does_not_contain
50
- enqueue_exception("#{error_msg} not contain '#{value}' but found '#{actual}'") if actual.include?(value)
51
- when :not_equal
52
- enqueue_exception("#{error_msg} not equal '#{value}' but found '#{actual}'") if actual == value
53
- when :like, :is_like
54
- actual_like = actual.delete("\n")
55
- actual_like = actual_like.delete("\r")
56
- actual_like = actual_like.delete("\t")
57
- actual_like = actual_like.delete(' ')
58
- actual_like = actual_like.downcase
59
- expected = value.delete("\n")
60
- expected = expected.delete("\r")
61
- expected = expected.delete("\t")
62
- expected = expected.delete(' ')
63
- expected = expected.downcase
64
- enqueue_exception("#{error_msg} be like '#{value}' but found '#{actual}'") unless actual_like.include?(expected)
65
- when :translate
66
- expected = I18n.t(value)
67
- enqueue_assert_equal(expected, actual, error_msg)
68
- when :translate_upcase
69
- expected = I18n.t(value).upcase
70
- enqueue_assert_equal(expected, actual, error_msg)
71
- when :translate_downcase
72
- expected = I18n.t(value).downcase
73
- enqueue_assert_equal(expected, actual, error_msg)
74
- when :translate_capitalize
75
- expected = I18n.t(value).capitalize
76
- enqueue_assert_equal(expected, actual, error_msg)
77
- end
78
- end
79
- else
80
- enqueue_assert_equal(state, actual, error_msg)
81
- end
82
- end
83
-
84
- private
85
-
86
- def self.enqueue(message)
87
- @error_queue = "#{@error_queue}#{message}\n\n"
88
- end
89
-
90
- def self.enqueue_screenshot
91
- timestamp = Time.now.strftime('%Y%m%d%H%M%S')
92
- filename = "Screenshot-#{timestamp}"
93
- path = File.join Dir.pwd, 'reports/screenshots/', filename
94
- if Environ.driver == :appium
95
- AppiumConnect.take_screenshot("#{path}.png")
96
- else
97
- Capybara.save_screenshot "#{path}.png"
98
- end
99
- puts "Screenshot saved at #{path}.png"
100
- screen_shot = { :path => path, :filename => filename }
101
- Environ.save_screen_shot(screen_shot)
102
- end
103
- end
104
-
105
-
106
- class ObjectNotFoundError < StandardError
107
- def initialize(message)
108
- super(message)
109
- end
110
- end
111
- end
@@ -1,32 +0,0 @@
1
- class Object
2
- def blank?
3
- respond_to?(:empty?) ? empty? : !self
4
- end
5
-
6
- def present?
7
- !blank?
8
- end
9
- end
10
-
11
-
12
- class String
13
- def to_bool
14
- return true if self == true || self =~ (/(true|t|yes|y|x|1)$/i)
15
- return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
16
- raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
17
- end
18
-
19
- def string_between(marker1, marker2)
20
- self[/#{Regexp.escape(marker1)}(.*?)#{Regexp.escape(marker2)}/m, 1]
21
- end
22
-
23
- def format_date_time(date_time_format)
24
- return if self.blank?
25
- new_date = DateTime.parse(self)
26
- if ENV['LOCALE'] && date_time_format.is_a?(Symbol)
27
- I18n.l(new_date, format: date_time_format)
28
- else
29
- new_date.strftime(date_time_format)
30
- end
31
- end
32
- end
@@ -1,15 +0,0 @@
1
- module CapybaraExtension
2
- def drag_by(right_by, down_by)
3
- base.drag_by(right_by, down_by)
4
- end
5
- end
6
-
7
-
8
- module CapybaraSeleniumExtension
9
- def drag_by(right_by, down_by)
10
- driver.browser.action.drag_and_drop_by(native, right_by, down_by).perform
11
- end
12
- end
13
-
14
- ::Capybara::Selenium::Node.send :include, CapybaraSeleniumExtension
15
- ::Capybara::Node::Element.send :include, CapybaraExtension