lib/bauxite/core/selector.rb in bauxite-0.6.18 vs lib/bauxite/core/selector.rb in bauxite-0.6.19

- old
+ new

@@ -1,153 +1,153 @@ -#-- -# Copyright (c) 2014 Patricio Zavolinsky -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -#++ - -module Bauxite - # Selector common state and behavior. - module SelectorModule - - # Constructs a new test selector instance. - def initialize(ctx, default_selector) - @ctx = ctx - @default = default_selector - end - - # Searches for elements using the specified selector string. - # - # For more information see Context#find. - # - # Selectors calling this method should forward their block as well. - # - # For example: - # # === selectors/example.rb ======= # - # class Selector - # # :category: Selector Methods - # def example(arg, &block) - # find(arg, &block) - # end - # end - # # === end selectors/example.rb === # - # - def find(selector, &block) - data = selector.split('=', 2) - type = data[0] - arg = data[-1] - unless data.length == 2 and type =~ /^[a-z_]+$/i - type = @default - arg = selector - end - raise ArgumentError, "Invalid selector type '#{type}'" unless Context::selectors.include? type - - custom_selectors = Context::selectors(false) - return send(type , arg, &block) if custom_selectors.include? type - return send(type+'_selector', arg, &block) if custom_selectors.include? type+'_selector' - selenium_find(type, arg, &block) - end - - protected - # Searches for elements using standard Selenium selectors. - # - # Selectors calling this method should forward their block as well. - # - # # === selectors/data.rb ======= # - # class Selector - # # :category: Selector Methods - # def data(arg, &block) - # # selector code goes here, for example: - # selenium_find(:css, "[data='#{arg}']", &block) - # end - # end - # # === end selectors/data.rb === # - # - def selenium_find(type, selector) - element = @ctx.driver.find_element(type, selector) - yield element if block_given? - element - end - end - - # Selector class. - # - # Selectors represent different strategies for finding elements. Selenium - # provides a list of standard selectors (e.g. by id, by css expression, etc). - # - # Additional selectors can be specified by defining custom methods in the - # Selector class. - # - # Each custom selector is defined in a separate file in the 'selectors/' - # directory. - # The name of the file must match the name of the selector. These files should - # avoid adding public methods other than the selector method itself. - # Also, no +attr_accessors+ should be added. - # - # Selector methods can use the +ctx+ attribute to refer to the current test - # Context. The protected method #selenium_find can also be used to locate elements - # using standard Selenium selectors. - # - # Selector methods should always take a block and forward that block to a call - # to either #find or #selenium_find. - # - # For example (new selector template): - # # === selectors/data.rb ======= # - # class Selector - # # :category: Selector Methods - # def data(arg, &block) - # # selector code goes here, for example: - # selenium_find(:css, "[data='#{arg}']", &block) - # end - # end - # # === end selectors/data.rb === # - # - # Context::selectors.include? 'data' # => true - # - # To avoid name clashing with Ruby reserved words, the '_selector' suffix can - # be included in the selector method name (this suffix will not be considered - # part of the selector name). - # - # For example (_selector suffix): - # # === selectors/end.rb ======= # - # class Selector - # # :category: Selector Methods - # def end_selector - # # do something - # end - # end - # # === end selector/end.rb === # - # - # Context::selectors.include? 'end' # => true - # - # --- - # - # === Standard Selenium Selectors - # - # [id=+targetValue+] {Locate elements whose +id+ attribute matches +targetValue+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-id] - # [name=+targetValue+] {Locate elements whose +name+ attribute matches +targetValue+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-name] - # [css=+cssSelectorSyntax+] {Locate elements using CSS selector syntax.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-css] - # [partial_link_text=+textFragment+] {Locate A elements whose text includes +textFragment+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-partial-link-text] - # [class=+className+ and class_name=+className+] {Locate elements whose +class+ attribute matches +className+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-class-name] - # [link=+exactText+ and link_text=+exactText+] {Locate A elements whose text is exactly +exactText+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-link-text] - # [tag_name=+targetValue+] {Locate elements whose tag name matches +targetValue+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-tag-name] - # [xpath=+xpathExpression+] {Locate elements using XPATH expressions.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-xpath] - # - class Selector - include Bauxite::SelectorModule - end +#-- +# Copyright (c) 2014 Patricio Zavolinsky +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +#++ + +module Bauxite + # Selector common state and behavior. + module SelectorModule + + # Constructs a new test selector instance. + def initialize(ctx, default_selector) + @ctx = ctx + @default = default_selector + end + + # Searches for elements using the specified selector string. + # + # For more information see Context#find. + # + # Selectors calling this method should forward their block as well. + # + # For example: + # # === selectors/example.rb ======= # + # class Selector + # # :category: Selector Methods + # def example(arg, &block) + # find(arg, &block) + # end + # end + # # === end selectors/example.rb === # + # + def find(selector, &block) + data = selector.split('=', 2) + type = data[0] + arg = data[-1] + unless data.length == 2 and type =~ /^[a-z_]+$/i + type = @default + arg = selector + end + raise ArgumentError, "Invalid selector type '#{type}'" unless Context::selectors.include? type + + custom_selectors = Context::selectors(false) + return send(type , arg, &block) if custom_selectors.include? type + return send(type+'_selector', arg, &block) if custom_selectors.include? type+'_selector' + selenium_find(type, arg, &block) + end + + protected + # Searches for elements using standard Selenium selectors. + # + # Selectors calling this method should forward their block as well. + # + # # === selectors/data.rb ======= # + # class Selector + # # :category: Selector Methods + # def data(arg, &block) + # # selector code goes here, for example: + # selenium_find(:css, "[data='#{arg}']", &block) + # end + # end + # # === end selectors/data.rb === # + # + def selenium_find(type, selector) + element = @ctx.driver.find_element(type, selector) + yield element if block_given? + element + end + end + + # Selector class. + # + # Selectors represent different strategies for finding elements. Selenium + # provides a list of standard selectors (e.g. by id, by css expression, etc). + # + # Additional selectors can be specified by defining custom methods in the + # Selector class. + # + # Each custom selector is defined in a separate file in the 'selectors/' + # directory. + # The name of the file must match the name of the selector. These files should + # avoid adding public methods other than the selector method itself. + # Also, no +attr_accessors+ should be added. + # + # Selector methods can use the +ctx+ attribute to refer to the current test + # Context. The protected method #selenium_find can also be used to locate elements + # using standard Selenium selectors. + # + # Selector methods should always take a block and forward that block to a call + # to either #find or #selenium_find. + # + # For example (new selector template): + # # === selectors/data.rb ======= # + # class Selector + # # :category: Selector Methods + # def data(arg, &block) + # # selector code goes here, for example: + # selenium_find(:css, "[data='#{arg}']", &block) + # end + # end + # # === end selectors/data.rb === # + # + # Context::selectors.include? 'data' # => true + # + # To avoid name clashing with Ruby reserved words, the '_selector' suffix can + # be included in the selector method name (this suffix will not be considered + # part of the selector name). + # + # For example (_selector suffix): + # # === selectors/end.rb ======= # + # class Selector + # # :category: Selector Methods + # def end_selector + # # do something + # end + # end + # # === end selector/end.rb === # + # + # Context::selectors.include? 'end' # => true + # + # --- + # + # === Standard Selenium Selectors + # + # [id=+targetValue+] {Locate elements whose +id+ attribute matches +targetValue+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-id] + # [name=+targetValue+] {Locate elements whose +name+ attribute matches +targetValue+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-name] + # [css=+cssSelectorSyntax+] {Locate elements using CSS selector syntax.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-css] + # [partial_link_text=+textFragment+] {Locate A elements whose text includes +textFragment+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-partial-link-text] + # [class=+className+ and class_name=+className+] {Locate elements whose +class+ attribute matches +className+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-class-name] + # [link=+exactText+ and link_text=+exactText+] {Locate A elements whose text is exactly +exactText+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-link-text] + # [tag_name=+targetValue+] {Locate elements whose tag name matches +targetValue+.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-tag-name] + # [xpath=+xpathExpression+] {Locate elements using XPATH expressions.}[http://docs.seleniumhq.org/docs/03_webdriver.jsp#by-xpath] + # + class Selector + include Bauxite::SelectorModule + end end \ No newline at end of file