Module: AngularWebdriver
- Defined in:
- lib/angular_webdriver/version.rb,
lib/angular_webdriver/protractor/by.rb,
lib/angular_webdriver/protractor/watir_patch.rb,
lib/angular_webdriver/protractor/rspec_helpers.rb,
lib/angular_webdriver/protractor/by_repeater_inner.rb,
lib/angular_webdriver/protractor/protractor_element.rb
Defined Under Namespace
Modules: RSpecHelpers Classes: By, ByRepeaterInner, ProtractorElement
Constant Summary collapse
- VERSION =
'1.0.8'
- DATE =
'2015-08-17'
Class Method Summary collapse
- .define_page_methods(opts = {}) ⇒ Object
-
.install_rspec_helpers(context = RSpec::Core::ExampleGroup) ⇒ Object
call after invoking Protractor.new.
-
.patch_watir ⇒ Object
Patch watir must be invoked before watir-webdriver is required to ensure the methods are defined before inheritance occurs.
- .require_all_pages(glob_path = nil) ⇒ Object
Class Method Details
.define_page_methods(opts = {}) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/angular_webdriver/protractor/rspec_helpers.rb', line 28 def define_page_methods opts={} method = opts.fetch(:method, :define_singleton_method) page_module = opts[:page_module] || raise('must set page_module') target_class = opts[:target_class] || raise('must set target_class') driver_object = opts[:watir] || opts[:driver] || raise('must set driver') page_module.constants.each do |page_class| qualified_class = page_module.const_get(page_class) # enable use of by/element/no_wait within block passed to pageobject element # element(:greet_button) { element(by.binding('greet')) } AngularWebdriver.install_rspec_helpers qualified_class # ButtonsPage => buttons_page # https://github.com/rails/rails/blob/daaa21bc7d20f2e4ff451637423a25ff2d5e75c7/activesupport/lib/active_support/inflector/methods.rb#L96 page_name = page_class.to_s.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase target_class.send(method, page_name) do instance_name = "@#{page_module}#{page_class}" # must always set because the driver may have changed sessions obj = qualified_class.new driver_object instance_variable_set instance_name, obj end end end |
.install_rspec_helpers(context = RSpec::Core::ExampleGroup) ⇒ Object
call after invoking Protractor.new. Installs by/element/no_wait
10 11 12 13 14 15 16 17 18 |
# File 'lib/angular_webdriver/protractor/rspec_helpers.rb', line 10 def install_rspec_helpers context = RSpec::Core::ExampleGroup helpers = AngularWebdriver::RSpecHelpers helpers.singleton_methods(false).each do |method_symbol| context.send(:define_method, method_symbol) do |*args, &block| args.length == 0 ? helpers.send(method_symbol, &block) : helpers.send(method_symbol, *args, &block) end end end |
.patch_watir ⇒ Object
Patch watir must be invoked before watir-webdriver is required to ensure the methods are defined before inheritance occurs. Then patch_watir must be invoked after requiring watir-webdriver to restore the methods that were overridden.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/angular_webdriver/protractor/watir_patch.rb', line 14 def self.patch_watir # # This patch serves a few purposes. The first is matching Protractor semantics # of lazy finding elements and always relocating elements (ex: element.text) # # The second is removing unnecessary bloatware from Watir which has a number # of checks that don't make sense for angular.js testing. The specifics # of this patch will change in the next Watir release. Currently version # 0.7.0 is targeted. # # The third is teaching Watir about angular specific locators # # Design goal: element.all(by.binding('slowHttpStatus')) # should not make any server requests # ::Watir::Browser.class_eval do # avoid prepending 'http://' to non-urls because protractor handles # the prepending at the driver level. def goto(uri) @driver.navigate.to uri run_checkers url end end ::Watir::HTMLElementCollection.class_eval do # Return original selector. # Method added for protractor compatibility def locator @selector end end ::Watir::Container.module_eval do # # Alias of elements for Protractor # def all(*args) elements(*args) end # Redefine extract_selector to wrap find by repeater upstream_extract_selector = instance_method(:extract_selector) define_method(:extract_selector) do |selectors| selectors = AngularWebdriver::ByRepeaterInner.wrap_repeater selectors upstream_extract_selector.bind(self).call selectors end end # ::Watir::Container.module_eval # # Base class for HTML elements. # # Note the element class is different on master. ::Watir::Element.class_eval do # Always raise on stale element ref error. Prevents infinite retry loop. def element_call yield rescue Selenium::WebDriver::Error::StaleElementReferenceError raise end # Rescue all exceptions. Guarantee that we'll return true or false. # # Returns true if element exists and false otherwise. def exists? assert_exists true rescue Exception false end def selected? assert_exists element_call { @element.selected? } end # required for watir otherwise execute_script will fail # # e = browser.element(tag_name: 'div') # driver.execute_script 'return arguments[0].tagName', e # {"script":"return arguments[0].tagName","args":[{"ELEMENT":"0"}]} # # Convert to a WebElement JSON Object for transmission over the wire. # @see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#basic-terms-and-concepts # # @api private # def to_json(*args) assert_exists { ELEMENT: @element.ref }.to_json end # Ensure that the element exists by always relocating it # Required to trigger waitForAngular. Caching the element here will # break the Protractor sync feature so this must be @element = locate. def assert_exists @element = locate end def assert_not_stale nil end def assert_enabled nil end # Return original selector. # Method added for protractor compatibility def locator @selector end # avoid context lookup def locate locator_class.new(@parent.wd, @selector, self.class.attribute_list).locate end # Invoke protractor.allowAnimations with freshly located element and # optional value. def allowAnimations value=nil assert_exists driver.protractor.allowAnimations @element, value end # Watir doesn't define a clear method on element so we have to provide one. def clear assert_exists element_call { @element.clear } end # Evaluate an Angular expression as if it were on the scope # of the current element. # # @param expression <String> The expression to evaluate. # # @return <Object> The result of the evaluation. def evaluate expression assert_exists driver.protractor.evaluate @element, expression end # # Returns true if the element exists and is visible on the page. # Returns false if the element doesn't exist or isn't visible. # # @return [Boolean] # @see Watir::Wait # # # rescue element not found def present? exists? && visible? rescue Exception # if the element disappears between the exists? and visible? calls, # consider it not present. false end end # ::Watir::Element.class_eval # # The main class through which you control the browser. # ::Watir::Browser.class_eval do def assert_exists # remove expensive window check raise Exception::Error, 'browser was closed' if @closed end def inspect nil # avoid expensive browser url and title lookup end end # ::Watir::Browser.class_eval ::Watir::ElementLocator.class_eval do def validate_element(element) tn = @selector[:tag_name] return element unless tn # don't validate nil tag names element_tag_name = element.tag_name.downcase return if tn && !tag_name_matches?(element_tag_name, tn) if element_tag_name == 'input' return if @selector[:type] && @selector[:type] != element.attribute(:type) end element end # always raise element not found / stale reference error def locate # element.all(by.partialButtonText('text')).to_a[0].value creates the # selector {:element=>#<Selenium::WebDriver::Element ...>} # in that case we've already located the element. # # see 'should find multiple buttons containing "text"' in locators_spec.rb return @selector[:element] if @selector.is_a?(Hash) && @selector[:element].is_a?(Selenium::WebDriver::Element) e = by_id and return e # short-circuit if :id is given if @selector.size == 1 element = find_first_by_one else element = find_first_by_multiple end # This actually only applies when finding by xpath/css - browser.text_field(:xpath, "//input[@type='radio']") # We don't need to validate the element if we built the xpath ourselves. # It is also used to alter behavior of methods locating more than one type of element # (e.g. text_field locates both input and textarea) validate_element(element) if element end end # ::Watir::ElementLocator.class_eval end |
.require_all_pages(glob_path = nil) ⇒ Object
20 21 22 23 24 25 26 |
# File 'lib/angular_webdriver/protractor/rspec_helpers.rb', line 20 def require_all_pages glob_path=nil base_dir = Rake.application.original_dir if defined?(Rake) base_dir ||= @original_dir ||= Dir.pwd glob_path ||= File.join(base_dir, 'page', '**', '*.rb') Dir.glob(glob_path) { |file| require_relative file } end |