testcentricity_web 0.2.2

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.
@@ -0,0 +1,241 @@
1
+ require 'time'
2
+ require 'chronic'
3
+ require 'faker'
4
+ require 'spreadsheet'
5
+
6
+
7
+ module TestCentricity
8
+
9
+ XL_PRIMARY_DATA_PATH ||= 'features/test_data/'
10
+ XL_PRIMARY_DATA_FILE ||= "#{XL_PRIMARY_DATA_PATH}data.xls"
11
+
12
+
13
+ class Excel_Data
14
+ @mru = {}
15
+
16
+ def self.get_environment_data_file
17
+ environment = ENV['TEST_ENVIRONMENT']
18
+ "#{XL_PRIMARY_DATA_PATH}#{environment}_data.xls"
19
+ end
20
+
21
+ def self.worksheet_exists?(file, sheet)
22
+ exists = false
23
+ work_book = Spreadsheet.open file
24
+ worksheets = work_book.worksheets
25
+ worksheets.each do |worksheet|
26
+ if worksheet.name == sheet
27
+ exists = true
28
+ break
29
+ end
30
+ end
31
+ exists
32
+ end
33
+
34
+ def self.rowspec_exists?(file, sheet, rowspec)
35
+ exists = false
36
+ if worksheet_exists?(file, sheet)
37
+ work_book = Spreadsheet.open file
38
+ work_sheet = work_book.worksheet sheet
39
+ # get column headings from row 0 of worksheet
40
+ headings = work_sheet.row(0)
41
+ # if rowspec is a string then we have to find a matching row name
42
+ if rowspec.is_a? String
43
+ column_number = 0
44
+ exists = false
45
+ headings.each do |heading|
46
+ if heading == 'ROW_NAME'
47
+ exists = true
48
+ break
49
+ end
50
+ column_number += 1
51
+ end
52
+ raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless exists
53
+ # find first cell in ROW_NAME column containing a string that matches the rowspec parameter
54
+ exists = false
55
+ row_number = 0
56
+ work_sheet.each do |row|
57
+ if row[column_number] == rowspec
58
+ exists = true
59
+ break
60
+ end
61
+ row_number += 1
62
+ end
63
+ end
64
+ end
65
+ exists
66
+ end
67
+
68
+ def self.read_row_from_pool(file, sheet, rowspec, columns = nil)
69
+ work_book = Spreadsheet.open file
70
+ work_sheet = work_book.worksheet sheet
71
+
72
+ pool_spec_key = "#{sheet}:#{rowspec}"
73
+ if @mru.key?(pool_spec_key)
74
+ pool_spec = @mru[pool_spec_key]
75
+ row_start = pool_spec[:start_row]
76
+ row_end = pool_spec[:num_rows]
77
+ pool_rows = (row_start..row_start + row_end - 1).to_a
78
+ mru_rows = pool_spec[:used_rows]
79
+ new_row = pool_rows.sample.to_i
80
+ if mru_rows.size == pool_spec[:num_rows]
81
+ mru_rows = [new_row]
82
+ else
83
+ while mru_rows.include?(new_row)
84
+ new_row = pool_rows.sample.to_i
85
+ end
86
+ mru_rows.push(new_row)
87
+ mru_rows.sort!
88
+ end
89
+
90
+ pool_spec = {
91
+ :start_row => row_start,
92
+ :num_rows => row_end,
93
+ :used_rows => mru_rows
94
+ }
95
+ else
96
+ # get column headings from row 0 of worksheet
97
+ headings = work_sheet.row(0)
98
+ column_number = 0
99
+ found = false
100
+ headings.each do |heading|
101
+ if heading == 'ROW_NAME'
102
+ found = true
103
+ break
104
+ end
105
+ column_number += 1
106
+ end
107
+ raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless found
108
+ # find cell(s) in ROW_NAME column containing a string that matches the rowspec parameter
109
+ found = []
110
+ row_number = 0
111
+ work_sheet.each do |row|
112
+ if row[column_number] == rowspec
113
+ found.push(row_number)
114
+ elsif !found.empty?
115
+ break
116
+ end
117
+ row_number += 1
118
+ end
119
+ raise "Could not find a row named '#{rowspec}' in worksheet #{sheet}" if found.empty?
120
+
121
+ new_row = found.sample.to_i
122
+ pool_spec = {
123
+ :start_row => found[0],
124
+ :num_rows => found.size,
125
+ :used_rows => [new_row]
126
+ }
127
+ end
128
+ @mru[pool_spec_key] = pool_spec
129
+
130
+ read_row_data(file, sheet, new_row, columns)
131
+ end
132
+
133
+ def self.read_row_data(file, sheet, rowspec, columns = nil)
134
+ work_book = Spreadsheet.open file
135
+ work_sheet = work_book.worksheet sheet
136
+ # get column headings from row 0 of worksheet
137
+ headings = work_sheet.row(0)
138
+ # if rowspec is a string then we have to find a matching row name
139
+ if rowspec.is_a? String
140
+ column_number = 0
141
+ found = false
142
+ headings.each do |heading|
143
+ if heading == 'ROW_NAME'
144
+ found = true
145
+ break
146
+ end
147
+ column_number += 1
148
+ end
149
+ raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless found
150
+ # find first cell in ROW_NAME column containing a string that matches the rowspec parameter
151
+ found = false
152
+ row_number = 0
153
+ work_sheet.each do |row|
154
+ if row[column_number] == rowspec
155
+ found = true
156
+ break
157
+ end
158
+ row_number += 1
159
+ end
160
+ raise "Could not find a row named '#{rowspec}' in worksheet #{sheet}" unless found
161
+ data = work_sheet.row(row_number)
162
+ # if rowspec is a number then ensure that it doesn't exceed the number of available rows
163
+ elsif rowspec.is_a? Numeric
164
+ raise "Row # #{rowspec} is greater than number of rows in worksheet #{sheet}" if rowspec > work_sheet.last_row_index
165
+ data = work_sheet.row(rowspec)
166
+ end
167
+
168
+ # if no columns have been specified, return all columns
169
+ columns = headings if columns == nil
170
+ # create results hash table
171
+ result = Hash.new
172
+ columns.each do |column|
173
+ column_number = 0
174
+ found = false
175
+ headings.each do |heading|
176
+ if column == heading
177
+ value = data[column_number].to_s
178
+ value = calculate_dynamic_value(value) if value.start_with? 'eval!'
179
+ result[column] = value
180
+ found = true
181
+ break
182
+ end
183
+ column_number += 1
184
+ end
185
+ raise "Could not find a column named '#{column}' in worksheet #{sheet}" unless found
186
+ end
187
+ result
188
+ end
189
+
190
+ def self.read_range_data(file, sheet, rangespec)
191
+ work_book = Spreadsheet.open file
192
+ work_sheet = work_book.worksheet sheet
193
+ # get column headings from row 0 of worksheet
194
+ headings = work_sheet.row(0)
195
+ column_number = 0
196
+ found = false
197
+ headings.each do |heading|
198
+ if heading == 'ROW_NAME'
199
+ found = true
200
+ break
201
+ end
202
+ column_number += 1
203
+ end
204
+ raise "Could not find a column named ROW_NAME in worksheet #{sheet}" unless found
205
+ # find cell(s) in ROW_NAME column containing a string that matches the rangespec parameter
206
+ found = []
207
+ row_number = 0
208
+ work_sheet.each do |row|
209
+ if row[column_number] == rangespec
210
+ found.push(row_number)
211
+ elsif !found.empty?
212
+ break
213
+ end
214
+ row_number += 1
215
+ end
216
+ raise "Could not find a row named '#{rangespec}' in worksheet #{sheet}" if found.empty?
217
+
218
+ result = []
219
+ found.each do |row|
220
+ result.push(read_row_data(file, sheet, row))
221
+ end
222
+ result
223
+ end
224
+
225
+ private
226
+
227
+ def self.calculate_dynamic_value(value)
228
+ test_value = value.split('!', 2)
229
+ parameter = test_value[1].split('.', 2)
230
+ case parameter[0]
231
+ when 'Address', 'Business', 'Code', 'Company', 'PhoneNumber', 'Number', 'Name', 'Internet', 'Lorem', 'Commerce', 'Hacker'
232
+ result = eval("Faker::#{parameter[0]}.#{parameter[1]}")
233
+ when 'Date'
234
+ result = eval("Chronic.parse('#{parameter[1]}')")
235
+ else
236
+ result = eval(test_value[1])
237
+ end
238
+ result.to_s
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,29 @@
1
+ module TestCentricity
2
+ class ExceptionQueue
3
+ @error_queue
4
+
5
+ def self.enqueue_assert_equal(expected, actual, error_message)
6
+ unless expected == actual
7
+ @error_queue = "#{@error_queue}#{error_message} to be\n #{expected}\nbut found\n #{actual}\n\n"
8
+ screen_shot_and_save_page(nil)
9
+ end
10
+ end
11
+
12
+ def self.enqueue_assert_not_equal(expected, actual, error_message)
13
+ unless expected != actual
14
+ @error_queue = "#{@error_queue}#{error_message} to not be equal to #{expected}\n\n"
15
+ screen_shot_and_save_page(nil)
16
+ end
17
+ end
18
+
19
+ def self.enqueue_exception(error_message)
20
+ @error_queue = "#{@error_queue}#{error_message}\n\n"
21
+ end
22
+
23
+ def self.post_exceptions
24
+ raise @error_queue unless @error_queue.nil?
25
+ ensure
26
+ @error_queue = nil
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,147 @@
1
+ module TestCentricity
2
+ class PageObject
3
+ include Capybara::DSL
4
+ include Capybara::Node::Matchers
5
+ include RSpec::Matchers
6
+ include Test::Unit::Assertions
7
+
8
+ def self.trait(trait_name, &block)
9
+ define_method(trait_name.to_s, &block)
10
+ end
11
+
12
+ def self.element(element_name, locator)
13
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, nil);end))
14
+ end
15
+
16
+ def self.button(element_name, locator)
17
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, :button);end))
18
+ end
19
+
20
+ def self.textfield(element_name, locator)
21
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, :textfield);end))
22
+ end
23
+
24
+ def self.checkbox(element_name, locator)
25
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, :checkbox);end))
26
+ end
27
+
28
+ def self.label(element_name, locator)
29
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, :label);end))
30
+ end
31
+
32
+ def self.link(element_name, locator)
33
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, :link);end))
34
+ end
35
+
36
+ def self.table(element_name, locator)
37
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :page, :table);end))
38
+ end
39
+
40
+ def self.section(section_name, class_name, locator = nil)
41
+ class_eval(%Q(def #{section_name.to_s};@#{section_name.to_s} ||= #{class_name.to_s}.new(self, "#{locator}", :page);end))
42
+ end
43
+
44
+ def open_portal
45
+ environment = Environ.current
46
+ (environment.hostname.length > 0) ?
47
+ url = "#{environment.hostname}/#{environment.base_url}#{environment.append}" :
48
+ url = "#{environment.base_url}#{environment.append}"
49
+ if environment.user_id.length > 0 && environment.password.length > 0
50
+ visit "#{environment.protocol}://#{environment.user_id}:#{environment.password}@#{url}"
51
+ else
52
+ visit "#{environment.protocol}://#{url}"
53
+ end
54
+ Environ.set_portal_state(:open)
55
+ end
56
+
57
+ def verify_page_exists
58
+ unless page.has_selector?(page_locator)
59
+ body_class = find(:xpath, '//body')[:class]
60
+ error_message = "Expected page to have selector '#{page_locator}' but found '#{body_class}' instead.\nURL of page loaded = #{URI.parse(current_url)}"
61
+ raise error_message
62
+ end
63
+ end
64
+
65
+ def navigate_to; end
66
+
67
+ def verify_page_ui; end
68
+
69
+ def load_page
70
+ return if exists?
71
+ if defined?(page_url) && !page_url.nil?
72
+ visit page_url
73
+ begin
74
+ page.driver.browser.switch_to.alert.accept
75
+ rescue => e
76
+ end unless Environ.browser == :safari || Environ.browser == :ie || Environ.is_device?
77
+ else
78
+ navigate_to
79
+ end
80
+ verify_page_exists
81
+ PageManager.set_current_page(self)
82
+ end
83
+
84
+ def take_screen_shot(page_name, context)
85
+ save_page_screen_shot(page_name, context)
86
+ end
87
+
88
+ def verify_page_contains(content)
89
+ raise "Expected page to have content '#{content}'" unless page.has_content?(:visible, content)
90
+ end
91
+
92
+ def exists?
93
+ saved_wait_time = Capybara.default_max_wait_time
94
+ Capybara.default_max_wait_time = 0.1
95
+ tries ||= 2
96
+ attributes = [:id, :css, :xpath]
97
+ type = attributes[tries]
98
+ obj = page.find(type, page_locator)
99
+ obj != nil
100
+ rescue
101
+ Capybara.default_max_wait_time = saved_wait_time
102
+ retry if (tries -= 1) > 0
103
+ false
104
+ ensure
105
+ Capybara.default_max_wait_time = saved_wait_time
106
+ end
107
+
108
+ def secure?
109
+ !current_url.match(/^https/).nil?
110
+ end
111
+
112
+ def verify_ui_states(ui_states)
113
+ ui_states.each do | ui_object, object_states |
114
+ object_states.each do | property, state |
115
+ case property
116
+ when :exists
117
+ actual = ui_object.exists?
118
+ when :enabled
119
+ actual = ui_object.enabled?
120
+ when :visible
121
+ actual = ui_object.visible?
122
+ when :readonly
123
+ actual = ui_object.read_only?
124
+ when :checked
125
+ actual = ui_object.checked?
126
+ when :value
127
+ actual = ui_object.get_value
128
+ when :maxlength
129
+ actual = ui_object.get_max_length
130
+ when :options
131
+ actual = ui_object.get_options
132
+ when :siebel_options
133
+ actual = ui_object.get_siebel_options
134
+ else
135
+ if property.to_s.start_with? ('cell_')
136
+ cell = property.to_s.gsub('cell_', '')
137
+ cell = cell.split('_')
138
+ actual = ui_object.get_table_cell(cell[0].to_i, cell[1].to_i)
139
+ end
140
+ end
141
+ ExceptionQueue.enqueue_assert_equal(state, actual, "Expected #{ui_object.get_locator} #{property.to_s} property")
142
+ end
143
+ end
144
+ ExceptionQueue.post_exceptions
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,161 @@
1
+ module TestCentricity
2
+ class PageSection
3
+ include Capybara::DSL
4
+ include Capybara::Node::Matchers
5
+ include RSpec::Matchers
6
+ include Test::Unit::Assertions
7
+
8
+ attr_reader :locator, :context
9
+ attr_accessor :parent
10
+
11
+ def self.trait(trait_name, &block)
12
+ define_method(trait_name.to_s, &block)
13
+ end
14
+
15
+ def initialize(parent, locator, context)
16
+ @parent = parent
17
+ @locator = locator
18
+ @context = context
19
+ end
20
+
21
+ def self.element(element_name, locator)
22
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, nil);end))
23
+ end
24
+
25
+ def self.button(element_name, locator)
26
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, :button);end))
27
+ end
28
+
29
+ def self.textfield(element_name, locator)
30
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, :textfield);end))
31
+ end
32
+
33
+ def self.checkbox(element_name, locator)
34
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, :checkbox);end))
35
+ end
36
+
37
+ def self.label(element_name, locator)
38
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, :label);end))
39
+ end
40
+
41
+ def self.link(element_name, locator)
42
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, :link);end))
43
+ end
44
+
45
+ def self.table(element_name, locator)
46
+ class_eval(%Q(def #{element_name.to_s};@#{element_name.to_s} ||= TestCentricity::UIElement.new(self, "#{locator}", :section, :table);end))
47
+ end
48
+
49
+ def self.section(section_name, class_name, locator = nil)
50
+ class_eval(%Q(def #{section_name.to_s};@#{section_name.to_s} ||= #{class_name.to_s}.new(self, "#{locator}", :section);end))
51
+ end
52
+
53
+ def get_locator
54
+ (@locator.empty? && defined?(section_locator)) ? locator = section_locator : locator = @locator
55
+ (@context == :section && !@parent.nil? && !@parent.get_locator.nil?) ? "#{@parent.get_locator}#{locator}" : locator
56
+ end
57
+
58
+ def set_parent(parent)
59
+ @parent = parent
60
+ end
61
+
62
+ def exists?
63
+ section, _ = find_section
64
+ section != nil
65
+ end
66
+
67
+ def visible?
68
+ section, type = find_section
69
+ exists = section
70
+ invisible = false
71
+ if type == :css
72
+ Capybara.using_wait_time 0.1 do
73
+ # is section itself hidden with .ui-helper-hidden class?
74
+ self_hidden = page.has_css?("#{@locator}.ui-helper-hidden")
75
+ # is parent of section hidden, thus hiding the section?
76
+ parent_hidden = page.has_css?(".ui-helper-hidden > #{@locator}")
77
+ # is grandparent of section, or any other ancestor, hidden?
78
+ other_ancestor_hidden = page.has_css?(".ui-helper-hidden * #{@locator}")
79
+ # if any of the above conditions are true, then section is invisible
80
+ invisible = self_hidden || parent_hidden || other_ancestor_hidden
81
+ end
82
+ end
83
+ # the section is visible if it exists and it is not invisible
84
+ (exists && !invisible) ? true : false
85
+ end
86
+
87
+ def hidden?
88
+ not visible?
89
+ end
90
+
91
+ def wait_until_exists(seconds)
92
+ timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
93
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
94
+ wait.until { exists? }
95
+ rescue
96
+ raise "Could not find section #{get_locator} after #{timeout} seconds" unless exists?
97
+ end
98
+
99
+ def wait_until_gone(seconds)
100
+ timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
101
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
102
+ wait.until { !exists? }
103
+ rescue
104
+ raise "Section #{get_locator} remained visible after #{timeout} seconds" if exists?
105
+ end
106
+
107
+ def verify_ui_states(ui_states)
108
+ ui_states.each do | ui_object, object_states |
109
+ object_states.each do | property, state |
110
+ case property
111
+ when :exists
112
+ actual = ui_object.exists?
113
+ when :enabled
114
+ actual = ui_object.enabled?
115
+ when :visible
116
+ actual = ui_object.visible?
117
+ when :readonly
118
+ actual = ui_object.read_only?
119
+ when :checked
120
+ actual = ui_object.checked?
121
+ when :value
122
+ actual = ui_object.get_value
123
+ when :maxlength
124
+ actual = ui_object.get_max_length
125
+ when :options
126
+ actual = ui_object.get_options
127
+ when :siebel_options
128
+ actual = ui_object.get_siebel_options
129
+ else
130
+ if property.to_s.start_with? ('cell_')
131
+ cell = property.to_s.gsub('cell_', '')
132
+ cell = cell.split('_')
133
+ actual = ui_object.get_table_cell(cell[0].to_i, cell[1].to_i)
134
+ end
135
+ end
136
+ ExceptionQueue.enqueue_assert_equal(state, actual, "Expected #{ui_object.get_locator} #{property.to_s} property")
137
+ end
138
+ end
139
+ ExceptionQueue.post_exceptions
140
+ end
141
+
142
+ private
143
+
144
+ def find_section
145
+ locator = get_locator
146
+ saved_wait_time = Capybara.default_max_wait_time
147
+ Capybara.default_max_wait_time = 0.1
148
+ tries ||= 4
149
+ attributes = [:text, :name, :id, :css, :xpath]
150
+ type = attributes[tries]
151
+ obj = page.find(type, locator)
152
+ [obj, type]
153
+ rescue
154
+ Capybara.default_max_wait_time = saved_wait_time
155
+ retry if (tries -= 1) > 0
156
+ [nil, nil]
157
+ ensure
158
+ Capybara.default_max_wait_time = saved_wait_time
159
+ end
160
+ end
161
+ end