site_prism_plus 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: []