site_prism_plus 0.2.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9b648678b00c5ed7508a2fd1c0a2bff2109bb7817de679588c7b2470f0ee4aa5
4
+ data.tar.gz: 82393ae8d6b6d1a6ff1044d5b3514d84bb754c1596c4c253a617412d7f346b21
5
+ SHA512:
6
+ metadata.gz: cd9c7e052a7e859a7c28db9dc5f8846e6e9ffb6306bcd5e067d7325e0f676e722fbc5e59c2309fd10a75d35e65096b6e77a032b853605540a23d3bff9179fb07
7
+ data.tar.gz: f548351d34ba03a954f8b854eac4b47ba18d9e086612719b136792e158f0d30ad0f5fa349500638f161875eeb94a710f641425ab77cd5c237d80dc735a9ec713
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ **/results
10
+ .DS_Store
11
+ .idea
12
+
13
+ # rspec failure tracking
14
+ .rspec_status
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in site_prism_metrics.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ site_prism_plus (0.1.0)
5
+ site_prism (~> 2.9)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ addressable (2.5.2)
11
+ public_suffix (>= 2.0.2, < 4.0)
12
+ archive-zip (0.11.0)
13
+ io-like (~> 0.3.0)
14
+ capybara (2.18.0)
15
+ addressable
16
+ mini_mime (>= 0.1.3)
17
+ nokogiri (>= 1.3.3)
18
+ rack (>= 1.0.0)
19
+ rack-test (>= 0.5.4)
20
+ xpath (>= 2.0, < 4.0)
21
+ childprocess (0.9.0)
22
+ ffi (~> 1.0, >= 1.0.11)
23
+ chromedriver-helper (1.2.0)
24
+ archive-zip (~> 0.10)
25
+ nokogiri (~> 1.8)
26
+ coderay (1.1.2)
27
+ diff-lcs (1.3)
28
+ ffi (1.9.25)
29
+ io-like (0.3.0)
30
+ method_source (0.9.0)
31
+ mini_mime (1.0.0)
32
+ mini_portile2 (2.3.0)
33
+ nokogiri (1.8.2)
34
+ mini_portile2 (~> 2.3.0)
35
+ pry (0.11.3)
36
+ coderay (~> 1.1.0)
37
+ method_source (~> 0.9.0)
38
+ public_suffix (3.0.2)
39
+ rack (2.0.5)
40
+ rack-test (1.0.0)
41
+ rack (>= 1.0, < 3)
42
+ rake (10.5.0)
43
+ rspec (3.7.0)
44
+ rspec-core (~> 3.7.0)
45
+ rspec-expectations (~> 3.7.0)
46
+ rspec-mocks (~> 3.7.0)
47
+ rspec-core (3.7.1)
48
+ rspec-support (~> 3.7.0)
49
+ rspec-expectations (3.7.0)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.7.0)
52
+ rspec-mocks (3.7.0)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.7.0)
55
+ rspec-support (3.7.1)
56
+ rubyzip (1.2.1)
57
+ selenium-webdriver (3.10.0)
58
+ childprocess (~> 0.5)
59
+ rubyzip (~> 1.2)
60
+ site_prism (2.13)
61
+ addressable (~> 2.4)
62
+ capybara (~> 2.12)
63
+ xpath (3.1.0)
64
+ nokogiri (~> 1.8)
65
+
66
+ PLATFORMS
67
+ ruby
68
+
69
+ DEPENDENCIES
70
+ bundler (~> 1.16)
71
+ chromedriver-helper (~> 1.2.0)
72
+ pry (~> 0.11.0)
73
+ rake (~> 10.0)
74
+ rspec (~> 3.0)
75
+ selenium-webdriver (>= 3.4.0, <= 3.10.0)
76
+ site_prism_plus!
77
+
78
+ BUNDLED WITH
79
+ 1.16.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Ibarra Alfonso
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # SitePrismPlus
2
+
3
+ ###THIS IS NOT PUBLISHED YET.
4
+
5
+ Extends the page object model [site_prism ruby gem](https://github.com/natritmeyer/site_prism). It adds common methods to make test execution robust. The gem also can log events such as click errors or page load times into a flat file.
6
+
7
+ Dynamic single page applications are getting difficult to test usually caused by timing issues resulting in raised
8
+ exceptions. Automation frameworks or util libraries are typically written to catch these exceptions and handled accordingly. Site Prism
9
+ is a great POM framework so it's quite useful extend it and put your utils.
10
+
11
+ ## Installation
12
+
13
+ ###THIS IS NOT PUBLISHED YET.
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'site_prism_plus'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install site_prism_plus
28
+
29
+ ## Usage
30
+
31
+ ```ruby
32
+ class DemoSite < SitePrismPlus::Page
33
+ set_url 'https://some_site.com'
34
+
35
+ element :header_logo, :xpath, '//img[@src="some_source"]'
36
+ element :sub_link, '#link_id'
37
+ element :click_result_elem, '#some_elem_loc'
38
+ element :name_input_field, '#user_name'
39
+ element :search_input, '#q_search'
40
+ end
41
+ ```
42
+
43
+ #### Loading the page and verify element
44
+ Loads the page and verifies if the element expected is present. Method __load_and_verify__ takes an element
45
+ as a parameter. The page is loaded and the element is checked until visible.
46
+ ```ruby
47
+ demo_site = DemoSite.new('page_description')
48
+ demo_site.load('header_logo')
49
+ ```
50
+
51
+ #### Clicking an element
52
+ Clicking an element sometimes results in exceptions such as StateElement. Method __click_element__ catches
53
+ exceptions and does a retry. If a second element is passed as a parameter, it verifies this second element
54
+ to determine if the click action was successful.
55
+ ```ruby
56
+ demo_site.click_element('sub_link', 'click_result_elem')
57
+ ```
58
+
59
+ #### Send keys and verify
60
+ For input fields with auto-complete or has match recommendation, sending keys to the field sometimes results with several
61
+ issues. Method __send_and_verify__ sends the text to an input field and verifies field has the correct text. If not
62
+ field is cleared and text is resent.
63
+ ```ruby
64
+ demo_site.send_and_verify('name_input_field', 'some_user_name')
65
+ ```
66
+
67
+ #### Send chars
68
+ Sends text to an input field one character at a time with a slight delay between characters. Useful when checking for
69
+ auto-complete or search matching.
70
+ ```ruby
71
+ demo_site.send_chars('search_input', 'cheap flights')
72
+ ```
73
+
74
+ #### Checking Visibility
75
+ Returns true or false if an element is found and is visible. Catches possible exceptions
76
+ (ex. SitePrism::TimeOutWaitingForElementVisibility:).
77
+ * is_element_visible('name_of_element')
78
+ * wait_till_element_visible('name_of_element')
79
+ * wait_till_element_not_visible('name_of_element')
80
+ ```ruby
81
+ demo_site.wait_till_element_visible('header_logo')
82
+ ```
83
+
84
+ #### Hover and click
85
+ Useful for hover activated drop downs. An optional third parameter (expected_element) can be passed. This element will
86
+ be verified to determine if the click was successful.
87
+ ```ruby
88
+ demo_site.hover_and_click('hover_element', 'drop_option')
89
+
90
+ # or
91
+
92
+ demo_site.hover_and_click('hover_element', 'drop_option', 'resulting_element')
93
+ ```
94
+
95
+ ### Sections
96
+ All methods in Page are available for Section. See RSpec tests in spec folder for examples.
97
+
98
+ ## Capturing Some Test Metrics
99
+ Lots of open source and commercial applications out there to capture metrics for your web application, this gem
100
+ just captures test related metrics such as click retries, page loads, or transitions times (like modals). These metrics are
101
+ saved in a flat file and can be graphed (separate application).
102
+
103
+ By default, metrics are saved in current working directory __./results/metrics.txt__
104
+
105
+
106
+
107
+ #### Enable capture metrics
108
+ Set environment variable *_SITEPRISM_METRICS_ENABLED_*
109
+
110
+ #### Some optional environment variables
111
+ * SITEPRISM_PLUS_DEBUG - prints out info of commands being executed
112
+ * SITEPRISM_PLUS_RESULT_DIR - directory where metrics file is saved
113
+ * SITEPRISM_PLUS_RESULT_FILE - name of file to save metrics
114
+
115
+ ## Development
116
+ This is the initial release, so likely a few bugs. RSpec tests in specs directory. Any contribution/collaboration/help/criticism
117
+ is highly welcomed.
118
+ * More methods for other use cases
119
+ * Currently working on graph app for the metrics
120
+ * More RSpec tests - isn't that always the case
121
+ * Obviously, improve this documentation
122
+ ## Contributing
123
+
124
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/site_prism_plus.
125
+
126
+ ## License
127
+
128
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
129
+ # site_prism_plus
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "site_prism_metrics"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ require "site_prism_plus/version"
2
+ require 'capybara'
3
+ require 'capybara/dsl'
4
+ require_relative 'site_prism_plus/metrics.rb'
5
+ require_relative 'site_prism_plus/page.rb'
6
+ require_relative 'site_prism_plus/site_prism_plus_commons.rb'
7
+ require_relative 'site_prism_plus/section.rb'
8
+
9
+ module SitePrismPlus
10
+ # Your code goes here...
11
+ end
@@ -0,0 +1,70 @@
1
+ require 'csv'
2
+ # Singleton to capture and log metrics
3
+ #
4
+ class Metrics
5
+
6
+ DEFAULT_METRICS_DIR = Dir.pwd
7
+ DEFAULT_METRICS_FILE = 'metrics.txt'
8
+
9
+ attr_accessor :default_log_file, :default_log_directory
10
+
11
+ def initialize
12
+ @default_log_directory = DEFAULT_METRICS_DIR
13
+ if ENV['SITEPRISM_PLUS_RESULT_DIR']
14
+ if Dir.exist?(ENV['SITEPRISM_PLUS_RESULT_DIR'])
15
+ @default_log_directory = ENV['SITEPRISM_PLUS_RESULT_DIR']
16
+ end
17
+ else
18
+ results_folder = DEFAULT_METRICS_DIR + '/results'
19
+ unless Dir.exist? (results_folder)
20
+ Dir.mkdir(results_folder)
21
+ end
22
+ @default_log_directory = results_folder
23
+ end
24
+ @default_log_file = @default_log_directory + "/" + DEFAULT_METRICS_FILE
25
+ if ENV['SITEPRISM_PLUS_RESULT_FILE']
26
+ @default_log_file = @default_log_directory + "/" + ENV['SITEPRISM_PLUS_RESULT_FILE']
27
+ end
28
+ @stime = nil
29
+ @etime = nil
30
+ end
31
+
32
+ def self.instance
33
+ @@instance
34
+ end
35
+
36
+ def clear_file
37
+ if File.exist?(@default_log_file)
38
+ File.delete(@default_log_file)
39
+ end
40
+ end
41
+
42
+ def start_time
43
+ @stime = Time.now
44
+ end
45
+
46
+ def end_time
47
+ @etime = Time.now
48
+ end
49
+
50
+ def log_metric(page, action, tag)
51
+ return unless ENV['SITEPRISM_METRICS_ENABLED']
52
+ @etime = Time.now
53
+ time_laps = @etime - @stime
54
+ CSV.open(@default_log_file, "a") do |csv|
55
+ csv << [page, action, tag, time_laps]
56
+ end
57
+ end
58
+
59
+ def log_error_metric(page, action, tag)
60
+ return unless ENV['SITEPRISM_METRICS_ENABLED']
61
+ CSV.open(@default_log_file, "a") do |csv|
62
+ csv << [page, action, tag]
63
+ end
64
+ end
65
+
66
+ @@instance = Metrics.new
67
+
68
+ private_class_method :new
69
+
70
+ end
@@ -0,0 +1,51 @@
1
+ require 'site_prism'
2
+ require_relative 'metrics'
3
+ require_relative 'site_prism_plus_commons'
4
+
5
+ # Extends SitePrism Page class to include common methods
6
+ # and logging metrics
7
+ module SitePrismPlus
8
+
9
+ class Page < SitePrism::Page
10
+ include SitePrismPlusCommons
11
+
12
+ def initialize(page_name)
13
+ @page_name = page_name
14
+ @metrics = Metrics.instance
15
+ end
16
+
17
+ # Page loads typically takes longer.
18
+ def load_and_verify(element_name)
19
+ load_override(element_name)
20
+ end
21
+
22
+ def log_transition_metric(click_element, verify_element)
23
+ @metrics.start_time
24
+ result = click_element(click_element, verify_element)
25
+ @metrics.log_metric(@page_name, 'click', verify_element)
26
+ result
27
+ end
28
+
29
+ def reset_logfile
30
+ @metrics.clear_file
31
+ end
32
+
33
+ def metrics_file
34
+ @metrics.default_log_file
35
+ end
36
+
37
+ private
38
+
39
+ def load_override(verify_element = nil)
40
+ result = true
41
+ @metrics.start_time
42
+ load
43
+ if verify_element
44
+ result = wait_till_element_visible(verify_element, 3)
45
+ end
46
+ @metrics.log_metric(@page_name, 'load', verify_element)
47
+ result
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,26 @@
1
+ require 'site_prism'
2
+
3
+ module SitePrismPlus
4
+
5
+ class Section < SitePrism::Section
6
+ include SitePrismPlusCommons
7
+
8
+ def set_name(section_name)
9
+ @section_name = section_name
10
+ end
11
+
12
+ def log_transition_metric(click_element, verify_element, metric_tag = nil)
13
+ @metrics = Metrics.instance
14
+ @metrics.start_time
15
+ click_element(click_element, verify_element)
16
+ unless metric_tag
17
+ metric_tag = "#{click_element} => #{verify_element}"
18
+ end
19
+ @metrics.log_metric(@section_name, 'click', metric_tag)
20
+ end
21
+
22
+
23
+ private
24
+
25
+ end
26
+ end
@@ -0,0 +1,295 @@
1
+ # Common methods to
2
+ # - catch exceptions
3
+ # - run retries
4
+ # - log
5
+ # Metrics to capture
6
+ # - click retry
7
+ # - wait till found
8
+ module SitePrismPlusCommons
9
+
10
+ LOCATOR_TYPES = [:xpath, :css, :id, :name]
11
+
12
+ # Finds element on the browser using locator
13
+ # * *Args* :
14
+ # - +loc_type_or_element+ -> name of element or locator type (:xpath, :id, ...)
15
+ # - +locator+ -> syntax for element locator
16
+ # * *Returns* :
17
+ # - Capybara element object if element is found, nil otherwise
18
+ def find_element(loc_type_or_element, locator = nil)
19
+ ret_elem = nil
20
+ begin
21
+ if LOCATOR_TYPES.include?(loc_type_or_element)
22
+ ret_elem = find(loc_type_or_element, locator)
23
+ else
24
+ ret_elem = eval(loc_type_or_element)
25
+ end
26
+ # rescue Capybara::ElementNotFound
27
+ # dbg_msg("Finding Element raised ElementNotFound #{loc_type_or_element}", 'error')
28
+ # return
29
+ # rescue Selenium::WebDriver::Error::StaleElementReferenceError
30
+ # dbg_msg("Finding Element raised StaleElementReferenceError #{loc_type_or_element}", 'error')
31
+ # return
32
+ rescue Exception => e
33
+ dbg_msg('error',"Finding Element unexpected exception #{loc_type_or_element} #{e.message}", loc_type_or_element)
34
+ return
35
+ end
36
+ if !ret_elem
37
+ dbg_msg('error',"Finding Element #{loc_type_or_element}NOT FOUND.", loc_type_or_element)
38
+ end
39
+ ret_elem
40
+ end
41
+
42
+ # Wraps click call inside begin-rescue to catch possible
43
+ # raised exceptions
44
+ # * *Args* :
45
+ # - +element_object+ -> capybara element obj, Capybara::Element
46
+ # * *Returns* :
47
+ # - true if no exceptions are raised after clicking on element
48
+ # false if exception is caught
49
+ def is_element_visible?(element_name)
50
+ result = false
51
+ elem_to_check = find_element(element_name)
52
+ unless elem_to_check.nil?
53
+ result = elem_to_check.visible?
54
+ end
55
+ if result
56
+ dbg_msg('info',"Checking Element #{element_name} is_element_visible? - true")
57
+ else
58
+ dbg_msg('info',"Checking if element is visible #{element_name} - false")
59
+ end
60
+ return result
61
+ end
62
+
63
+ # Checks till an element is visible or not visible anymore
64
+ #
65
+ def wait_for_visibility(element_name, visible_test = true, max_retry = 3)
66
+ nretry = 0
67
+ res = false
68
+ while nretry < max_retry && !res do
69
+ puts "CHECKING VISIBLE!!!!!!!!!!! #{element_name} result #{res}"
70
+ nretry += 1
71
+ res = is_element_visible?(element_name)
72
+ if !visible_test
73
+ res = !res
74
+ end
75
+
76
+ if !res
77
+ puts "WAITING VISIBILITY"
78
+ sleep(1)
79
+ end
80
+ end
81
+ res
82
+ end
83
+
84
+ # Just to be more verbose
85
+ def wait_till_element_visible(element_name, n_retry = 3)
86
+ dbg_msg('info',"Wait till element #{element_name} is visible")
87
+ wait_for_visibility(element_name, true, n_retry)
88
+ end
89
+
90
+ # Just to be more verbose
91
+ def wait_till_element_not_visible(element_name, n_retry = 3)
92
+ dbg_msg('info',"Wait till element #{element_name} is NOT visible")
93
+ wait_for_visibility(element_name, false, n_retry)
94
+ end
95
+
96
+ # Locates an element and clicks it. Verifies if the click action was successful
97
+ # by locating an element that results from the click action. Retries once.
98
+ # * *Args* :
99
+ # - +element_name+ -> name of element defined
100
+ # - +expected_element_name+ -> name of element to verify after the click
101
+ # - +expected_type+ -> locator type of element to verify
102
+ # - +expected_locator+ -> syntax for element to verify
103
+ # * *Returns* :
104
+ # - true if after clicking an element the expected element is found
105
+ # false otherwise
106
+ def click_element(element_name, expected_element_name = nil)
107
+ result = false
108
+ nretry = 0
109
+ while !result && nretry < 2
110
+ nretry += 1
111
+ elem_to_click = find_element(element_name)
112
+ if elem_to_click
113
+ result = click_action(elem_to_click, element_name)
114
+ dbg_msg('info',"Clicking element - #{element_name}")
115
+ if expected_element_name
116
+ result = is_element_visible?(expected_element_name)
117
+ dbg_msg('info', "Expected element after click: #{expected_element_name} visible? - #{result}")
118
+ end
119
+ end
120
+ if !result && nretry < 2
121
+ dbg_msg('error', "retry_click", element_name)
122
+ sleep(1)
123
+ end
124
+ end
125
+ result
126
+ end
127
+
128
+ # Sends text to an input field
129
+ # * *Args* :
130
+ # - +element_name+ -> name of element
131
+ # - +txt_to_send+ -> text (string) to type in input field
132
+ # * *Returns* :
133
+ # - true if element is found and send_keys successful, false otherwise
134
+ def send_keys(element_name, txt_to_send)
135
+ result = false
136
+ dbg_msg('info', "Send keys to element: #{element_name} - Text: #{txt_to_send}")
137
+ elem_input = find_element(element_name)
138
+ unless elem_input.nil?
139
+ begin
140
+ elem_input.send_keys(txt_to_send)
141
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
142
+ dbg_msg('error', "StaleElement exception send_keys to element: #{element_name}", element_name)
143
+ return false
144
+ end
145
+ result = true
146
+ end
147
+ return result
148
+ end
149
+
150
+ # Use when dealing with auto-complete fields
151
+ # Sends text to an input field one character at a time with a slight
152
+ # delay between characters
153
+ def send_chars(element_name, txt_to_send)
154
+ elem_input = find_element(element_name)
155
+ unless elem_input.nil?
156
+ txt_to_send.chars.each do |onechar|
157
+ begin
158
+ elem_input.send_keys(onechar)
159
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
160
+ dbg_msg('error', "StaleElement exception send_keys to element: #{element_name}", element_name)
161
+ return false
162
+ end
163
+ sleep(0.5)
164
+ end
165
+
166
+ if wait_for_text(element_name, txt_to_send)
167
+ return true
168
+ else
169
+ return false
170
+ end
171
+ end
172
+ end
173
+
174
+ # Checks element for value to equal expected text.
175
+ #
176
+ def wait_for_text(element_name, expected_text)
177
+ wait_sec = 0
178
+ while wait_sec < 2
179
+ wait_sec += 1
180
+ element_with_text = find_element(element_name)
181
+ if element_with_text
182
+ found_text = ""
183
+ begin
184
+ found_text = element_with_text.value
185
+ if expected_text == found_text
186
+ return true
187
+ end
188
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
189
+ dbg_msg('error', "StaleElement exception wait_for_text in element: #{element_name}", element_name)
190
+ end
191
+ end
192
+ sleep(1)
193
+ end
194
+ return false
195
+ end
196
+
197
+
198
+ # Similar to send_chars, this method auto correct itself if the
199
+ # text is not the same as what was sent
200
+ # - happens with input fields not ready
201
+ # - character send does not register especially with auto-complete fields
202
+ def send_and_verify(element_name, txt_to_send)
203
+ nretry = 0
204
+ while nretry < 2
205
+ nretry += 1
206
+ if send_keys(element_name, txt_to_send)
207
+ if wait_for_text(element_name, txt_to_send)
208
+ return true
209
+ end
210
+ end
211
+ backspace_clear(element_name)
212
+ end
213
+ return false
214
+ end
215
+
216
+ # Clears the text inside an input field by sending backspaces
217
+ # * *Args* :
218
+ # - +element_name+ -> name of element defined in POM
219
+ # * *Returns* :
220
+ # - true if element is found, false otherwise
221
+ def backspace_clear(element_name)
222
+ field_element = find_element(element_name)
223
+ if field_element
224
+ field_text = field_element.value
225
+ (0..field_text.size).each do
226
+ send_keys(element_name, :backspace)
227
+ end
228
+ else
229
+ return false
230
+ end
231
+ true
232
+ end
233
+
234
+ # Routine for hover activated dropdown menus
235
+ # * *Args* :
236
+ # - +hover_elem+ -> POM defined element to move mouse over
237
+ # - +click_elem+ -> POM defined element to click
238
+ # - +expected_elem+ -> resulting POM defined element to verify
239
+ # * *Returns* :
240
+ # - true if element is found, false otherwise
241
+ def hover_and_click(hover_elem, click_elem, expected_elem = nil)
242
+ result = false
243
+ helem = find_element(hover_elem)
244
+ if helem
245
+ dbg_msg('info', "Hovering over #{hover_elem}")
246
+ helem.hover
247
+ end
248
+ if wait_till_element_visible(click_elem)
249
+ result = click_element(click_elem, expected_elem)
250
+ end
251
+ result
252
+ end
253
+
254
+ private
255
+
256
+ # Wraps click call inside begin-rescue to catch possible
257
+ # raised exceptions
258
+ # * *Args* :
259
+ # - +element_object+ -> capybara element obj, Capybara::Element
260
+ # * *Returns* :
261
+ # - true if no exceptions are raised after clicking on element
262
+ # false if exception is caught
263
+ def click_action(element_object, element_name)
264
+ begin
265
+ element_object.click
266
+ # rescue Selenium::WebDriver::Error::StaleElementReferenceError
267
+ # dbg_msg('error', "Stale Element exception - click_element")
268
+ # return false
269
+ # rescue Selenium::WebDriver::Error::UnknownError
270
+ # dbg_msg('error', "Unknown error exception - click_element")
271
+ # return false
272
+ rescue Exception => e
273
+ dbg_msg('error', 'click_exception', element_name)
274
+ return false
275
+ end
276
+ true
277
+ end
278
+
279
+ def dbg_msg(dlevel, msg, msg_tag = nil)
280
+ case dlevel.downcase
281
+ when 'info'
282
+ puts "INFO: #{msg}" if ENV['SITEPRISM_PLUS_DEBUG']
283
+ when 'error'
284
+ puts "ERROR: #{msg}" if ENV['SITEPRISM_PLUS_DEBUG']
285
+ log_metric(@page_name, msg, msg_tag) if ENV['SITEPRISM_METRICS_ENABLED']
286
+ end
287
+ end
288
+
289
+ # Log error or retry events
290
+ def log_metric(page, action, error_tag)
291
+ @metric = Metrics.instance
292
+ @metric.log_error_metric(page, action, error_tag)
293
+ end
294
+
295
+ end
@@ -0,0 +1,3 @@
1
+ module SitePrismPlus
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,44 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "site_prism_plus/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "site_prism_plus"
8
+ spec.version = SitePrismPlus::VERSION
9
+ spec.required_ruby_version = '>= 2.1'
10
+ spec.platform = Gem::Platform::RUBY
11
+ spec.authors = ["Ibarra Alfonso"]
12
+ spec.email = ["ibarraalfonso@gmail.com"]
13
+
14
+ spec.summary = %q{Extends site_prism gem with methods for robust tests and collect test metrics }
15
+ spec.description = %q{Adds more robust methods and collects test metrics. .}
16
+ spec.homepage = "https://github.com/ibaralf/site_prism_plus"
17
+ spec.license = "MIT"
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ # if spec.respond_to?(:metadata)
22
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
23
+ # else
24
+ # raise "RubyGems 2.0 or newer is required to protect against " \
25
+ # "public gem pushes."
26
+ # end
27
+
28
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
29
+ f.match(%r{^(test|spec|features)/})
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+ spec.add_dependency "site_prism", "~> 2.9"
35
+
36
+ # NOTE: breaking with pry seems to affect webdriver that it could
37
+ # not find the elements in the current window
38
+ spec.add_development_dependency "bundler", "~> 1.16"
39
+ spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency "rspec", "~> 3.0"
41
+ spec.add_development_dependency "selenium-webdriver", ['>= 3.4.0', '<= 3.10.0']
42
+ spec.add_development_dependency "chromedriver-helper", "~> 1.2.0"
43
+ spec.add_development_dependency "pry", "~> 0.11.0"
44
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: site_prism_plus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Ibarra Alfonso
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-06-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: site_prism
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: selenium-webdriver
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.4.0
76
+ - - "<="
77
+ - !ruby/object:Gem::Version
78
+ version: 3.10.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: 3.4.0
86
+ - - "<="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.10.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: chromedriver-helper
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 1.2.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.2.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: pry
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 0.11.0
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 0.11.0
117
+ description: Adds more robust methods and collects test metrics. .
118
+ email:
119
+ - ibarraalfonso@gmail.com
120
+ executables: []
121
+ extensions: []
122
+ extra_rdoc_files: []
123
+ files:
124
+ - ".gitignore"
125
+ - Gemfile
126
+ - Gemfile.lock
127
+ - LICENSE.txt
128
+ - README.md
129
+ - Rakefile
130
+ - bin/console
131
+ - bin/setup
132
+ - lib/site_prism_plus.rb
133
+ - lib/site_prism_plus/metrics.rb
134
+ - lib/site_prism_plus/page.rb
135
+ - lib/site_prism_plus/section.rb
136
+ - lib/site_prism_plus/site_prism_plus_commons.rb
137
+ - lib/site_prism_plus/version.rb
138
+ - site_prism_plus.gemspec
139
+ homepage: https://github.com/ibaralf/site_prism_plus
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '2.1'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.7.5
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Extends site_prism gem with methods for robust tests and collect test metrics
163
+ test_files: []