testcentricity 2.3.13

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +93 -0
  8. data/LICENSE.txt +28 -0
  9. data/README.md +1634 -0
  10. data/Rakefile +1 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/devices/devices.yml +344 -0
  14. data/lib/testcentricity.rb +144 -0
  15. data/lib/testcentricity/app_core/appium_connect_helper.rb +154 -0
  16. data/lib/testcentricity/app_core/appium_server.rb +69 -0
  17. data/lib/testcentricity/app_core/screen_objects_helper.rb +180 -0
  18. data/lib/testcentricity/app_core/screen_sections_helper.rb +332 -0
  19. data/lib/testcentricity/app_elements/app_element_helper.rb +293 -0
  20. data/lib/testcentricity/app_elements/button.rb +8 -0
  21. data/lib/testcentricity/app_elements/checkbox.rb +20 -0
  22. data/lib/testcentricity/app_elements/label.rb +8 -0
  23. data/lib/testcentricity/app_elements/list.rb +25 -0
  24. data/lib/testcentricity/app_elements/switch.rb +20 -0
  25. data/lib/testcentricity/app_elements/textfield.rb +12 -0
  26. data/lib/testcentricity/browser_helper.rb +174 -0
  27. data/lib/testcentricity/data_objects/data_objects_helper.rb +78 -0
  28. data/lib/testcentricity/data_objects/environment.rb +281 -0
  29. data/lib/testcentricity/data_objects/excel_helper.rb +242 -0
  30. data/lib/testcentricity/exception_queue_helper.rb +51 -0
  31. data/lib/testcentricity/utility_helpers.rb +28 -0
  32. data/lib/testcentricity/version.rb +3 -0
  33. data/lib/testcentricity/web_core/drag_drop_helper.rb +15 -0
  34. data/lib/testcentricity/web_core/page_objects_helper.rb +669 -0
  35. data/lib/testcentricity/web_core/page_sections_helper.rb +866 -0
  36. data/lib/testcentricity/web_core/webdriver_helper.rb +579 -0
  37. data/lib/testcentricity/web_elements/button.rb +8 -0
  38. data/lib/testcentricity/web_elements/cell_button.rb +8 -0
  39. data/lib/testcentricity/web_elements/cell_checkbox.rb +38 -0
  40. data/lib/testcentricity/web_elements/cell_element.rb +69 -0
  41. data/lib/testcentricity/web_elements/cell_image.rb +8 -0
  42. data/lib/testcentricity/web_elements/cell_radio.rb +31 -0
  43. data/lib/testcentricity/web_elements/checkbox.rb +100 -0
  44. data/lib/testcentricity/web_elements/file_field.rb +45 -0
  45. data/lib/testcentricity/web_elements/image.rb +34 -0
  46. data/lib/testcentricity/web_elements/label.rb +8 -0
  47. data/lib/testcentricity/web_elements/link.rb +8 -0
  48. data/lib/testcentricity/web_elements/list.rb +73 -0
  49. data/lib/testcentricity/web_elements/list_button.rb +8 -0
  50. data/lib/testcentricity/web_elements/list_checkbox.rb +38 -0
  51. data/lib/testcentricity/web_elements/list_element.rb +61 -0
  52. data/lib/testcentricity/web_elements/list_radio.rb +31 -0
  53. data/lib/testcentricity/web_elements/radio.rb +74 -0
  54. data/lib/testcentricity/web_elements/select_list.rb +197 -0
  55. data/lib/testcentricity/web_elements/siebel_open_ui_helper.rb +15 -0
  56. data/lib/testcentricity/web_elements/table.rb +612 -0
  57. data/lib/testcentricity/web_elements/textfield.rb +114 -0
  58. data/lib/testcentricity/web_elements/ui_elements_helper.rb +502 -0
  59. data/lib/testcentricity/world_extensions.rb +26 -0
  60. data/my_templates/default/method_details/setup.rb +3 -0
  61. data/spec/spec_helper.rb +14 -0
  62. data/spec/testcentricity_spec.rb +9 -0
  63. data/testcentricity.gemspec +47 -0
  64. metadata +328 -0
@@ -0,0 +1,78 @@
1
+ require 'yaml'
2
+ require 'json'
3
+
4
+
5
+ module TestCentricity
6
+
7
+ XL_PRIMARY_DATA_PATH ||= 'features/test_data/'
8
+ XL_PRIMARY_DATA_FILE ||= "#{XL_PRIMARY_DATA_PATH}data.xls"
9
+
10
+
11
+ class DataObject
12
+ attr_accessor :current
13
+ attr_accessor :context
14
+ attr_accessor :hash_table
15
+
16
+ def initialize(data)
17
+ @hash_table = data
18
+ end
19
+
20
+ # @deprecated Please use {#current=} instead
21
+ def self.set_current(current)
22
+ warn "[DEPRECATION] 'TestCentricity::DataObject.set_current' is deprecated. Please use 'current=' instead."
23
+ @current = current
24
+ end
25
+
26
+ def self.current
27
+ @current
28
+ end
29
+
30
+ def self.current=(current)
31
+ @current = current
32
+ end
33
+ end
34
+
35
+
36
+ class DataSource
37
+ attr_accessor :current
38
+
39
+ def read_yaml_node_data(file_name, node_name)
40
+ data = YAML.load_file("#{XL_PRIMARY_DATA_PATH}#{file_name}")
41
+ data[node_name]
42
+ end
43
+
44
+ def read_json_node_data(file_name, node_name)
45
+ raw_data = File.read("#{XL_PRIMARY_DATA_PATH}#{file_name}")
46
+ data = JSON.parse(raw_data)
47
+ data[node_name]
48
+ end
49
+ end
50
+
51
+
52
+ class ExcelDataSource < TestCentricity::DataSource
53
+ def pick_excel_data_source(sheet, row_spec)
54
+ if ENV['TEST_ENVIRONMENT']
55
+ environment = ENV['TEST_ENVIRONMENT']
56
+ data_file = "#{XL_PRIMARY_DATA_PATH}#{environment}_data.xls"
57
+ data_file = XL_PRIMARY_DATA_FILE unless ExcelData.rowspec_exists?(data_file, sheet, row_spec)
58
+ else
59
+ data_file = XL_PRIMARY_DATA_FILE
60
+ end
61
+ data_file
62
+ end
63
+
64
+ def read_excel_row_data(sheet, row_name, parallel = false)
65
+ parallel == :parallel && ENV['PARALLEL'] ? row_spec = "#{row_name}#{ENV['TEST_ENV_NUMBER']}" : row_spec = row_name
66
+ ExcelData.read_row_data(pick_excel_data_source(sheet, row_spec), sheet, row_spec)
67
+ end
68
+
69
+ def read_excel_pool_data(sheet, row_name, parallel = false)
70
+ parallel == :parallel && ENV['PARALLEL'] ? row_spec = "#{row_name}#{ENV['TEST_ENV_NUMBER']}" : row_spec = row_name
71
+ ExcelData.read_row_from_pool(pick_excel_data_source(sheet, row_name), sheet, row_spec)
72
+ end
73
+
74
+ def read_excel_range_data(sheet, range_name)
75
+ ExcelData.read_range_data(pick_excel_data_source(sheet, range_name), sheet, range_name)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,281 @@
1
+ module TestCentricity
2
+ class EnvironData < TestCentricity::ExcelDataSource
3
+ attr_accessor :current
4
+
5
+ WKS_ENVIRONS ||= 'Environments'
6
+
7
+ def find_environ(environ_name, source_type = :excel)
8
+ case source_type
9
+ when :excel
10
+ data = ExcelData.read_row_data(XL_PRIMARY_DATA_FILE, WKS_ENVIRONS, environ_name)
11
+ when :yaml
12
+ data = read_yaml_node_data('environments.yml', environ_name)
13
+ when :json
14
+ data = read_json_node_data('environments.json', environ_name)
15
+ end
16
+ @current = Environ.new(data)
17
+ Environ.current = @current
18
+ end
19
+ end
20
+
21
+
22
+ class Environ < TestCentricity::DataObject
23
+ @session_id = Time.now.strftime('%d%H%M%S%L')
24
+ @session_time_stamp = Time.now.strftime('%Y%m%d%H%M%S')
25
+ @session_code
26
+ @test_environment = ENV['TEST_ENVIRONMENT']
27
+ @screen_shots = []
28
+
29
+ attr_accessor :test_environment
30
+ attr_accessor :browser
31
+ attr_accessor :browser_size
32
+ attr_accessor :session_state
33
+ attr_accessor :os
34
+ attr_accessor :device
35
+ attr_accessor :device_name
36
+ attr_accessor :device_type
37
+ attr_accessor :device_os
38
+ attr_accessor :device_orientation
39
+ attr_accessor :platform
40
+ attr_accessor :driver
41
+ attr_accessor :tunneling
42
+
43
+ attr_accessor :signed_in
44
+ attr_accessor :portal_status
45
+ attr_accessor :portal_context
46
+ attr_accessor :external_page
47
+
48
+ attr_accessor :default_max_wait_time
49
+
50
+ attr_accessor :protocol
51
+ attr_accessor :hostname
52
+ attr_accessor :base_url
53
+ attr_accessor :user_id
54
+ attr_accessor :password
55
+ attr_accessor :append
56
+ attr_accessor :option1
57
+ attr_accessor :option2
58
+ attr_accessor :dns
59
+ attr_accessor :db_username
60
+ attr_accessor :db_password
61
+ attr_accessor :ios_app_path
62
+ attr_accessor :ios_ipa_path
63
+ attr_accessor :android_apk_path
64
+
65
+ def initialize(data)
66
+ @protocol = data['PROTOCOL']
67
+ @hostname = data['HOST_NAME']
68
+ @base_url = data['BASE_URL']
69
+ @user_id = data['USER_ID']
70
+ @password = data['PASSWORD']
71
+ @append = data['APPEND']
72
+ @option1 = data['OPTIONAL_1']
73
+ @option2 = data['OPTIONAL_2']
74
+ @dns = data['DNS']
75
+ @db_username = data['DB_USERNAME']
76
+ @db_password = data['DB_PASSWORD']
77
+ @ios_app_path = data['IOS_APP_PATH']
78
+ @ios_ipa_path = data['IOS_IPA_PATH']
79
+ @android_apk_path = data['ANDROID_APK_PATH']
80
+ super
81
+ end
82
+
83
+ def self.session_code
84
+ if @session_code.nil?
85
+ characters = ('a'..'z').to_a
86
+ @session_code = (0..12).map { characters.sample }.join
87
+ end
88
+ @session_code
89
+ end
90
+
91
+ def self.session_id
92
+ @session_id
93
+ end
94
+
95
+ def self.session_time_stamp
96
+ @session_time_stamp
97
+ end
98
+
99
+ def self.test_environment
100
+ if @test_environment.blank?
101
+ nil
102
+ else
103
+ @test_environment.downcase.to_sym
104
+ end
105
+ end
106
+
107
+ def self.default_max_wait_time=(timeout)
108
+ @default_max_wait_time = timeout
109
+
110
+ Capybara.default_max_wait_time = timeout if driver == :webdriver
111
+ end
112
+
113
+ def self.default_max_wait_time
114
+ @default_max_wait_time
115
+ end
116
+
117
+ def self.browser=(browser)
118
+ @browser = browser.downcase.to_sym
119
+ end
120
+
121
+ def self.browser
122
+ @browser
123
+ end
124
+
125
+ def self.browser_size=(size)
126
+ @browser_size = size
127
+ end
128
+
129
+ def self.browser_size
130
+ @browser_size
131
+ end
132
+
133
+ def self.session_state=(session_state)
134
+ @session_state = session_state
135
+ end
136
+
137
+ def self.session_state
138
+ @session_state
139
+ end
140
+
141
+ def self.os=(os)
142
+ @os = os
143
+ end
144
+
145
+ def self.os
146
+ @os
147
+ end
148
+
149
+ def self.device=(device)
150
+ @device = device
151
+ end
152
+
153
+ def self.device
154
+ @device
155
+ end
156
+
157
+ def self.is_device?
158
+ @device == :device
159
+ end
160
+
161
+ def self.is_simulator?
162
+ @device == :simulator
163
+ end
164
+
165
+ def self.is_web?
166
+ @device == :web
167
+ end
168
+
169
+ def self.device_type=(type)
170
+ @device_type = type.downcase.to_sym
171
+ end
172
+
173
+ def self.device_type
174
+ @device_type
175
+ end
176
+
177
+ def self.device_name=(name)
178
+ @device_name = name
179
+ end
180
+
181
+ def self.device_name
182
+ @device_name
183
+ end
184
+
185
+ def self.device_os=(os)
186
+ @device_os = os.downcase.to_sym
187
+ end
188
+
189
+ def self.device_os
190
+ @device_os
191
+ end
192
+
193
+ def self.is_ios?
194
+ @device_os == :ios
195
+ end
196
+
197
+ def self.is_android?
198
+ @device_os == :android
199
+ end
200
+
201
+ def self.device_orientation=(orientation)
202
+ @device_orientation = orientation.downcase.to_sym
203
+ end
204
+
205
+ def self.device_orientation
206
+ @device_orientation
207
+ end
208
+
209
+ def self.driver=(type)
210
+ @driver = type
211
+ end
212
+
213
+ def self.driver
214
+ @driver
215
+ end
216
+
217
+ def self.tunneling=(state)
218
+ @tunneling = state
219
+ end
220
+
221
+ def self.tunneling
222
+ @tunneling
223
+ end
224
+
225
+ def self.platform=(platform)
226
+ @platform = platform
227
+ end
228
+
229
+ def self.is_mobile?
230
+ @platform == :mobile
231
+ end
232
+
233
+ def self.is_desktop?
234
+ @platform == :desktop
235
+ end
236
+
237
+ def self.set_signed_in(signed_in)
238
+ @signed_in = signed_in
239
+ end
240
+
241
+ def self.is_signed_in?
242
+ @signed_in
243
+ end
244
+
245
+ def self.portal_state=(portal_state)
246
+ @portal_status = portal_state
247
+ end
248
+
249
+ def self.portal_state
250
+ @portal_status
251
+ end
252
+
253
+ def self.portal_context=(portal_context)
254
+ @portal_context = portal_context
255
+ end
256
+
257
+ def self.portal_context
258
+ @portal_context
259
+ end
260
+
261
+ def self.set_external_page(state)
262
+ @external_page = state
263
+ end
264
+
265
+ def self.external_page
266
+ @external_page
267
+ end
268
+
269
+ def self.save_screen_shot(screen_shot)
270
+ @screen_shots.push(screen_shot)
271
+ end
272
+
273
+ def self.get_screen_shots
274
+ @screen_shots
275
+ end
276
+
277
+ def self.reset_contexts
278
+ @screen_shots = []
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,242 @@
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