spec/unit/selector_builder/element_spec.rb in watir-7.2.0 vs spec/unit/selector_builder/element_spec.rb in watir-7.2.1
- old
+ new
@@ -1,799 +1,806 @@
# frozen_string_literal: true
require_relative '../unit_helper'
-describe Watir::Locators::Element::SelectorBuilder do
- include LocatorSpecHelper
+module Watir
+ module Locators
+ class Element
+ describe SelectorBuilder do
+ include LocatorSpecHelper
- let(:selector_builder) { described_class.new(attributes, query_scope) }
+ let(:selector_builder) { described_class.new(attributes, query_scope) }
- describe '#build' do
- it 'without any arguments' do
- selector = {}
- built = {xpath: './/*'}
+ describe '#build' do
+ it 'without any arguments' do
+ selector = {}
+ built = {xpath: './/*'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- context 'with xpath or css' do
- it 'locates with xpath only' do
- selector = {xpath: './/div'}
- built = selector.dup
+ context 'with xpath or css' do
+ it 'locates with xpath only' do
+ selector = {xpath: './/div'}
+ built = selector.dup
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'locates with css only' do
- selector = {css: 'div'}
- built = selector.dup
+ it 'locates with css only' do
+ selector = {css: 'div'}
+ built = selector.dup
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'locates when attributes combined with xpath' do
- selector = {xpath: './/div', random: 'foo'}
- built = selector.dup
+ it 'locates when attributes combined with xpath' do
+ selector = {xpath: './/div', random: 'foo'}
+ built = selector.dup
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'locates when attributes combined with css' do
- selector = {css: 'div', random: 'foo'}
- built = selector.dup
+ it 'locates when attributes combined with css' do
+ selector = {css: 'div', random: 'foo'}
+ built = selector.dup
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when using xpath & css' do
- selector = {xpath: './/*', css: 'div'}
- msg = 'Can not locate element with [:css, :xpath]'
+ it 'raises exception when using xpath & css' do
+ selector = {xpath: './/*', css: 'div'}
+ msg = 'Can not locate element with [:css, :xpath]'
- expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
- end
+ expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
+ end
- it 'raises exception when not a String' do
- selector = {xpath: 7}
- msg = /expected one of \[String\], got 7:Integer/
+ it 'raises exception when not a String' do
+ selector = {xpath: 7}
+ msg = /expected one of \[String\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
+ end
- context 'with tag_name' do
- it 'with String equals' do
- selector = {tag_name: 'div'}
- built = {xpath: ".//*[local-name()='div']"}
+ context 'with tag_name' do
+ it 'with String equals' do
+ selector = {tag_name: 'div'}
+ built = {xpath: ".//*[local-name()='div']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with simple Regexp contains' do
- selector = {tag_name: /div/}
- built = {xpath: './/*[contains(local-name(), "div")]'}
+ it 'with simple Regexp contains' do
+ selector = {tag_name: /div/}
+ built = {xpath: './/*[contains(local-name(), "div")]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with Symbol' do
- selector = {tag_name: :div}
- built = {xpath: ".//*[local-name()='div']"}
+ it 'with Symbol' do
+ selector = {tag_name: :div}
+ built = {xpath: ".//*[local-name()='div']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when not a String or Regexp' do
- selector = {tag_name: 7}
- msg = /expected one of \[String, Regexp, Symbol\], got 7:Integer/
+ it 'raises exception when not a String or Regexp' do
+ selector = {tag_name: 7}
+ msg = /expected one of \[String, Regexp, Symbol\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
+ end
- context 'with class names' do
- it 'class_name is converted to class' do
- selector = {class_name: 'user'}
- built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' user ')]"}
+ context 'with class names' do
+ it 'class_name is converted to class' do
+ selector = {class_name: 'user'}
+ built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' user ')]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'single String concatenates' do
- selector = {class: 'user'}
- built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' user ')]"}
+ it 'single String concatenates' do
+ selector = {class: 'user'}
+ built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' user ')]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'Array of String concatenates with and' do
- selector = {class: %w[multiple here]}
- built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' multiple ') and " \
- "contains(concat(' ', normalize-space(@class), ' '), ' here ')]"}
+ it 'Array of String concatenates with and' do
+ selector = {class: %w[multiple here]}
+ built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' multiple ') and " \
+ "contains(concat(' ', normalize-space(@class), ' '), ' here ')]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'merges values when class and class_name are both used' do
- selector = {class: 'foo', class_name: 'bar'}
- built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' foo ') and " \
- "contains(concat(' ', normalize-space(@class), ' '), ' bar ')]"}
+ it 'merges values when class and class_name are both used' do
+ selector = {class: 'foo', class_name: 'bar'}
+ built = {xpath: ".//*[contains(concat(' ', normalize-space(@class), ' '), ' foo ') and " \
+ "contains(concat(' ', normalize-space(@class), ' '), ' bar ')]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'simple Regexp contains' do
- selector = {class_name: /use/}
- built = {xpath: './/*[contains(@class, "use")]'}
+ it 'simple Regexp contains' do
+ selector = {class_name: /use/}
+ built = {xpath: './/*[contains(@class, "use")]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'Array of Regexp contains with and' do
- selector = {class: [/mult/, /her/]}
- built = {xpath: './/*[contains(@class, "mult") and contains(@class, "her")]'}
+ it 'Array of Regexp contains with and' do
+ selector = {class: [/mult/, /her/]}
+ built = {xpath: './/*[contains(@class, "mult") and contains(@class, "her")]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'single negated String concatenates with not' do
- selector = {class: '!multiple'}
- built = {xpath: ".//*[not(contains(concat(' ', normalize-space(@class), ' '), ' multiple '))]"}
+ it 'single negated String concatenates with not' do
+ selector = {class: '!multiple'}
+ built = {xpath: ".//*[not(contains(concat(' ', normalize-space(@class), ' '), ' multiple '))]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'single Boolean true provides the at' do
- selector = {class: true}
- built = {xpath: './/*[@class]'}
+ it 'single Boolean true provides the at' do
+ selector = {class: true}
+ built = {xpath: './/*[@class]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'single Boolean false provides the not atat' do
- selector = {class: false}
- built = {xpath: './/*[not(@class)]'}
+ it 'single Boolean false provides the not atat' do
+ selector = {class: false}
+ built = {xpath: './/*[not(@class)]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'Array of mixed String, Regexp and Boolean contains and concatenates with and and not' do
- selector = {class: [/mult/, 'classes', '!here']}
- built = {xpath: './/*[contains(@class, "mult") ' \
- "and contains(concat(' ', normalize-space(@class), ' '), ' classes ') " \
- "and not(contains(concat(' ', normalize-space(@class), ' '), ' here '))]"}
+ it 'Array of mixed String, Regexp and Boolean contains and concatenates with and and not' do
+ selector = {class: [/mult/, 'classes', '!here']}
+ built = {xpath: './/*[contains(@class, "mult") ' \
+ "and contains(concat(' ', normalize-space(@class), ' '), ' classes ') " \
+ "and not(contains(concat(' ', normalize-space(@class), ' '), ' here '))]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'empty string finds elements without class' do
- selector = {class_name: ''}
- built = {xpath: './/*[not(@class)]'}
+ it 'empty string finds elements without class' do
+ selector = {class_name: ''}
+ built = {xpath: './/*[not(@class)]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'empty Array finds elements without class' do
- selector = {class_name: []}
- built = {xpath: './/*[not(@class)]'}
+ it 'empty Array finds elements without class' do
+ selector = {class_name: []}
+ built = {xpath: './/*[not(@class)]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when not a String or Regexp or Array' do
- selector = {class: 7}
- msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
+ it 'raises exception when not a String or Regexp or Array' do
+ selector = {class: 7}
+ msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
- it 'raises exception when Array values are not a String or Regexp' do
- selector = {class: [7]}
- msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
+ it 'raises exception when Array values are not a String or Regexp' do
+ selector = {class: [7]}
+ msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
+ end
- context 'with attributes as predicates' do
- it 'with href attribute' do
- selector = {href: 'watirspec.css'}
- built = {xpath: ".//*[normalize-space(@href)='watirspec.css']"}
+ context 'with attributes as predicates' do
+ it 'with href attribute' do
+ selector = {href: 'watirspec.css'}
+ built = {xpath: ".//*[normalize-space(@href)='watirspec.css']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with String attribute key' do
- selector = {'id' => 'user_new'}
- built = {xpath: ".//*[@id='user_new']"}
+ it 'with String attribute key' do
+ selector = {'id' => 'user_new'}
+ built = {xpath: ".//*[@id='user_new']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with String equals' do
- selector = {id: 'user_new'}
- built = {xpath: ".//*[@id='user_new']"}
+ it 'with String equals' do
+ selector = {id: 'user_new'}
+ built = {xpath: ".//*[@id='user_new']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with TrueClass no equals' do
- selector = {tag_name: 'input', id: true}
- built = {xpath: ".//*[local-name()='input'][@id]"}
+ it 'with TrueClass no equals' do
+ selector = {tag_name: 'input', id: true}
+ built = {xpath: ".//*[local-name()='input'][@id]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with FalseClass not with no equals' do
- selector = {tag_name: 'input', name: false}
- built = {xpath: ".//*[local-name()='input'][not(@name)]"}
+ it 'with FalseClass not with no equals' do
+ selector = {tag_name: 'input', name: false}
+ built = {xpath: ".//*[local-name()='input'][not(@name)]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with multiple attributes: no equals and not with no equals and equals' do
- selector = {readonly: true, foo: false, id: 'good_luck'}
- built = {xpath: ".//*[@readonly and not(@foo) and @id='good_luck']"}
+ it 'with multiple attributes: no equals and not with no equals and equals' do
+ selector = {readonly: true, foo: false, id: 'good_luck'}
+ built = {xpath: ".//*[@readonly and not(@foo) and @id='good_luck']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when attribute value is not a Boolean, String or Regexp' do
- selector = {foo: 7}
- msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
+ it 'raises exception when attribute value is not a Boolean, String or Regexp' do
+ selector = {foo: 7}
+ msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
- it 'raises exception when attribute key is not a String or Regexp' do
- selector = {7 => 'foo'}
- msg = /Unable to build XPath using 7:Integer/
+ it 'raises exception when attribute key is not a String or Regexp' do
+ selector = {7 => 'foo'}
+ msg = /Unable to build XPath using 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
+ end
+ end
- context 'with attributes as partials' do
- it 'with Regexp' do
- selector = {name: /user/}
- built = {xpath: './/*[contains(@name, "user")]'}
+ context 'with attributes as partials' do
+ it 'with Regexp' do
+ selector = {name: /user/}
+ built = {xpath: './/*[contains(@name, "user")]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with multiple Regexp attributes separated by and' do
- selector = {readonly: /read/, id: /good/}
- built = {xpath: './/*[contains(@readonly, "read") and contains(@id, "good")]'}
+ it 'with multiple Regexp attributes separated by and' do
+ selector = {readonly: /read/, id: /good/}
+ built = {xpath: './/*[contains(@readonly, "read") and contains(@id, "good")]'}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- context 'with text' do
- it 'String uses normalize space equals' do
- selector = {text: 'Add user'}
- built = {xpath: ".//*[normalize-space()='Add user']"}
+ context 'with text' do
+ it 'String uses normalize space equals' do
+ selector = {text: 'Add user'}
+ built = {xpath: ".//*[normalize-space()='Add user']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'Regexp uses contains normalize space' do
- selector = {text: /Add/}
- built = {xpath: './/*[contains(normalize-space(), "Add")]'}
+ it 'Regexp uses contains normalize space' do
+ selector = {text: /Add/}
+ built = {xpath: './/*[contains(normalize-space(), "Add")]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when text is not a String or Regexp' do
- selector = {text: 7}
- msg = /expected one of \[String, Regexp\], got 7:Integer/
+ it 'raises exception when text is not a String or Regexp' do
+ selector = {text: 7}
+ msg = /expected one of \[String, Regexp\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
+ end
- context 'with index' do
- it 'positive' do
- selector = {tag_name: 'div', index: 7}
- built = {xpath: "(.//*[local-name()='div'])[8]"}
+ context 'with index' do
+ it 'positive' do
+ selector = {tag_name: 'div', index: 7}
+ built = {xpath: "(.//*[local-name()='div'])[8]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'negative' do
- selector = {tag_name: 'div', index: -7}
- built = {xpath: "(.//*[local-name()='div'])[last()-6]"}
+ it 'negative' do
+ selector = {tag_name: 'div', index: -7}
+ built = {xpath: "(.//*[local-name()='div'])[last()-6]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'last' do
- selector = {tag_name: 'div', index: -1}
- built = {xpath: "(.//*[local-name()='div'])[last()]"}
+ it 'last' do
+ selector = {tag_name: 'div', index: -1}
+ built = {xpath: "(.//*[local-name()='div'])[last()]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'does not return index if it is zero' do
- selector = {tag_name: 'div', index: 0}
- built = {xpath: ".//*[local-name()='div']"}
+ it 'does not return index if it is zero' do
+ selector = {tag_name: 'div', index: 0}
+ built = {xpath: ".//*[local-name()='div']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when index is not an Integer' do
- selector = {index: 'foo'}
- msg = /expected one of \[(Integer|Fixnum)\], got "foo":String/
+ it 'raises exception when index is not an Integer' do
+ selector = {index: 'foo'}
+ msg = /expected one of \[(Integer|Fixnum)\], got "foo":String/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
+ end
- context 'with labels' do
- it 'locates the element associated with the label element located by the text of the provided label key' do
- selector = {label: 'Cars'}
- built = {xpath: ".//*[@id=//label[normalize-space()='Cars']/@for " \
- "or parent::label[normalize-space()='Cars']]"}
+ context 'with labels' do
+ it 'locates the element associated with the label element located by the text of the provided label key' do
+ selector = {label: 'Cars'}
+ built = {xpath: ".//*[@id=//label[normalize-space()='Cars']/@for " \
+ "or parent::label[normalize-space()='Cars']]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'returns a label_element if complex' do
- selector = {label: /Ca|rs/}
- xpath = './/*[@id=//label[normalize-space()]/@for or parent::label[normalize-space()]]'
- built = {xpath: xpath, label_element: /Ca|rs/}
+ it 'returns a label_element if complex' do
+ selector = {label: /Ca|rs/}
+ xpath = './/*[@id=//label[normalize-space()]/@for or parent::label[normalize-space()]]'
+ built = {xpath: xpath, label_element: /Ca|rs/}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'returns a visible_label_element if complex' do
- selector = {visible_label: /Ca|rs/}
- built = {xpath: './/*', visible_label_element: /Ca|rs/}
+ it 'returns a visible_label_element if complex' do
+ selector = {visible_label: /Ca|rs/}
+ built = {xpath: './/*', visible_label_element: /Ca|rs/}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'does not use the label element when label is a valid attribute' do
- @attributes ||= Watir::Option.attribute_list
+ it 'does not use the label element when label is a valid attribute' do
+ @attributes ||= Watir::Option.attribute_list
- selector = {tag_name: 'option', label: 'Germany'}
- built = {xpath: ".//*[local-name()='option'][@label='Germany']"}
+ selector = {tag_name: 'option', label: 'Germany'}
+ built = {xpath: ".//*[local-name()='option'][@label='Germany']"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- context 'with adjacent locators' do
- it 'raises exception when not a Symbol' do
- selector = {adjacent: 'foo', index: 0}
- msg = 'expected one of [Symbol], got "foo":String'
+ context 'with adjacent locators' do
+ it 'raises exception when not a Symbol' do
+ selector = {adjacent: 'foo', index: 0}
+ msg = 'expected one of [Symbol], got "foo":String'
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
- it 'raises exception when not a valid value' do
- selector = {adjacent: :foo, index: 0}
- msg = 'Unable to process adjacent locator with foo'
+ it 'raises exception when not a valid value' do
+ selector = {adjacent: :foo, index: 0}
+ msg = 'Unable to process adjacent locator with foo'
- expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
- end
+ expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
+ end
- describe '#parent' do
- it 'with no other arguments' do
- selector = {adjacent: :ancestor, index: 0}
- built = {xpath: './ancestor::*[1]'}
+ describe '#parent' do
+ it 'with no other arguments' do
+ selector = {adjacent: :ancestor, index: 0}
+ built = {xpath: './ancestor::*[1]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with index' do
- selector = {adjacent: :ancestor, index: 2}
- built = {xpath: './ancestor::*[3]'}
+ it 'with index' do
+ selector = {adjacent: :ancestor, index: 2}
+ built = {xpath: './ancestor::*[3]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with multiple locators' do
- selector = {adjacent: :ancestor, id: true, tag_name: 'div', class: 'ancestor', index: 1}
- built = {xpath: "./ancestor::*[local-name()='div']" \
- "[contains(concat(' ', normalize-space(@class), ' '), ' ancestor ')][@id][2]"}
+ it 'with multiple locators' do
+ selector = {adjacent: :ancestor, id: true, tag_name: 'div', class: 'ancestor', index: 1}
+ built = {xpath: "./ancestor::*[local-name()='div']" \
+ "[contains(concat(' ', normalize-space(@class), ' '), ' ancestor ')][@id][2]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises an exception if text locator is used' do
- selector = {adjacent: :ancestor, index: 0, text: 'Foo'}
- msg = 'Can not find parent element with text locator'
- expect { selector_builder.build(selector) }
- .to raise_exception Watir::Exception::LocatorException, msg
- end
- end
+ it 'raises an exception if text locator is used' do
+ selector = {adjacent: :ancestor, index: 0, text: 'Foo'}
+ msg = 'Can not find parent element with text locator'
+ expect { selector_builder.build(selector) }
+ .to raise_exception Watir::Exception::LocatorException, msg
+ end
+ end
- describe '#following_sibling' do
- it 'with no other arguments' do
- selector = {adjacent: :following, index: 0}
- built = {xpath: './following-sibling::*[1]'}
+ describe '#following_sibling' do
+ it 'with no other arguments' do
+ selector = {adjacent: :following, index: 0}
+ built = {xpath: './following-sibling::*[1]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with index' do
- selector = {adjacent: :following, index: 2}
- built = {xpath: './following-sibling::*[3]'}
+ it 'with index' do
+ selector = {adjacent: :following, index: 2}
+ built = {xpath: './following-sibling::*[3]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with multiple locators' do
- selector = {adjacent: :following, tag_name: 'div', class: 'b', index: 0, id: true}
- built = {xpath: "./following-sibling::*[local-name()='div']" \
- "[contains(concat(' ', normalize-space(@class), ' '), ' b ')][@id][1]"}
+ it 'with multiple locators' do
+ selector = {adjacent: :following, tag_name: 'div', class: 'b', index: 0, id: true}
+ built = {xpath: "./following-sibling::*[local-name()='div']" \
+ "[contains(concat(' ', normalize-space(@class), ' '), ' b ')][@id][1]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with text' do
- selector = {adjacent: :following, text: 'Third', index: 0}
- built = {xpath: "./following-sibling::*[normalize-space()='Third'][1]"}
+ it 'with text' do
+ selector = {adjacent: :following, text: 'Third', index: 0}
+ built = {xpath: "./following-sibling::*[normalize-space()='Third'][1]"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- describe '#previous_sibling' do
- it 'with no other arguments' do
- selector = {adjacent: :preceding, index: 0}
- built = {xpath: './preceding-sibling::*[1]'}
+ describe '#previous_sibling' do
+ it 'with no other arguments' do
+ selector = {adjacent: :preceding, index: 0}
+ built = {xpath: './preceding-sibling::*[1]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with index' do
- selector = {adjacent: :preceding, index: 2}
- built = {xpath: './preceding-sibling::*[3]'}
+ it 'with index' do
+ selector = {adjacent: :preceding, index: 2}
+ built = {xpath: './preceding-sibling::*[3]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with multiple locators' do
- selector = {adjacent: :preceding, tag_name: 'div', class: 'b', id: true, index: 0}
- built = {xpath: "./preceding-sibling::*[local-name()='div']" \
- "[contains(concat(' ', normalize-space(@class), ' '), ' b ')][@id][1]"}
+ it 'with multiple locators' do
+ selector = {adjacent: :preceding, tag_name: 'div', class: 'b', id: true, index: 0}
+ built = {xpath: "./preceding-sibling::*[local-name()='div']" \
+ "[contains(concat(' ', normalize-space(@class), ' '), ' b ')][@id][1]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with text' do
- selector = {adjacent: :preceding, text: 'Second', index: 0}
- built = {xpath: "./preceding-sibling::*[normalize-space()='Second'][1]"}
+ it 'with text' do
+ selector = {adjacent: :preceding, text: 'Second', index: 0}
+ built = {xpath: "./preceding-sibling::*[normalize-space()='Second'][1]"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- describe '#child' do
- it 'with no other arguments' do
- selector = {adjacent: :child, index: 0}
- built = {xpath: './child::*[1]'}
+ describe '#child' do
+ it 'with no other arguments' do
+ selector = {adjacent: :child, index: 0}
+ built = {xpath: './child::*[1]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with index' do
- selector = {adjacent: :child, index: 2}
- built = {xpath: './child::*[3]'}
+ it 'with index' do
+ selector = {adjacent: :child, index: 2}
+ built = {xpath: './child::*[3]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with multiple locators' do
- selector = {adjacent: :child, tag_name: 'div', class: 'b', id: true, index: 0}
- built = {xpath: "./child::*[local-name()='div']" \
- "[contains(concat(' ', normalize-space(@class), ' '), ' b ')][@id][1]"}
+ it 'with multiple locators' do
+ selector = {adjacent: :child, tag_name: 'div', class: 'b', id: true, index: 0}
+ built = {xpath: "./child::*[local-name()='div']" \
+ "[contains(concat(' ', normalize-space(@class), ' '), ' b ')][@id][1]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'with text' do
- selector = {adjacent: :child, text: 'Second', index: 0}
- built = {xpath: "./child::*[normalize-space()='Second'][1]"}
+ it 'with text' do
+ selector = {adjacent: :child, text: 'Second', index: 0}
+ built = {xpath: "./child::*[normalize-space()='Second'][1]"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
+ end
- context 'with multiple locators' do
- it 'locates using tag name, class, attributes and text' do
- selector = {tag_name: 'div', class: 'content', contenteditable: 'true', text: 'Foo'}
- built = {xpath: ".//*[local-name()='div'][contains(concat(' ', normalize-space(@class), ' '), ' content ')]" \
- "[normalize-space()='Foo'][@contenteditable='true']"}
+ context 'with multiple locators' do
+ it 'locates using tag name, class, attributes and text' do
+ selector = {tag_name: 'div', class: 'content', contenteditable: 'true', text: 'Foo'}
+ built = {xpath: ".//*[local-name()='div']" \
+ "[contains(concat(' ', normalize-space(@class), ' '), ' content ')]" \
+ "[normalize-space()='Foo'][@contenteditable='true']"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- context 'with simple Regexp' do
- it 'handles spaces' do
- selector = {title: /od Lu/}
- built = {xpath: './/*[contains(@title, "od Lu")]'}
+ context 'with simple Regexp' do
+ it 'handles spaces' do
+ selector = {title: /od Lu/}
+ built = {xpath: './/*[contains(@title, "od Lu")]'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'handles escaped characters' do
- selector = {src: %r{ages/but}}
- built = {xpath: './/*[contains(@src, "ages/but")]'}
+ it 'handles escaped characters' do
+ selector = {src: %r{ages/but}}
+ built = {xpath: './/*[contains(@src, "ages/but")]'}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- context 'with complex Regexp' do
- it 'handles wildcards' do
- selector = {src: /ages.*but/}
- built = {xpath: './/*[contains(@src, "ages") and contains(@src, "but")]', src: /ages.*but/}
+ context 'with complex Regexp' do
+ it 'handles wildcards' do
+ selector = {src: /ages.*but/}
+ built = {xpath: './/*[contains(@src, "ages") and contains(@src, "but")]', src: /ages.*but/}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'handles optional characters' do
- selector = {src: /ages ?but/}
- built = {xpath: './/*[contains(@src, "ages") and contains(@src, "but")]', src: /ages ?but/}
+ it 'handles optional characters' do
+ selector = {src: /ages ?but/}
+ built = {xpath: './/*[contains(@src, "ages") and contains(@src, "but")]', src: /ages ?but/}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'handles anchors' do
- selector = {name: /^new_user_image$/}
- built = {xpath: './/*[contains(@name, "new_user_image")]', name: /^new_user_image$/}
+ it 'handles anchors' do
+ selector = {name: /^new_user_image$/}
+ built = {xpath: './/*[contains(@name, "new_user_image")]', name: /^new_user_image$/}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'handles beginning anchor' do
- selector = {src: /^i/}
- built = {xpath: ".//*[starts-with(@src, 'i')]"}
+ it 'handles beginning anchor' do
+ selector = {src: /^i/}
+ built = {xpath: ".//*[starts-with(@src, 'i')]"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'does not use starts-with if visible locator used' do
- selector = {id: /^vis/, visible_text: 'shown div'}
- built = {xpath: './/*[contains(@id, "vis")]', id: /^vis/, visible_text: 'shown div'}
+ it 'does not use starts-with if visible locator used' do
+ selector = {id: /^vis/, visible_text: 'shown div'}
+ built = {xpath: './/*[contains(@id, "vis")]', id: /^vis/, visible_text: 'shown div'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'handles case insensitive' do
- selector = {action: /ME/i}
- built = {xpath: './/*[contains(translate(@action,' \
- "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
- "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'), " \
- 'translate("me",' \
- "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
- "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'))]"}
+ it 'handles case insensitive' do
+ selector = {action: /ME/i}
+ built = {xpath: './/*[contains(translate(@action,' \
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'), " \
+ 'translate("me",' \
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'))]"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- context 'with special cased selectors' do
- it 'handles data-* attributes with String' do
- selector = {data_foo: 'user_new'}
- built = {xpath: ".//*[@data-foo='user_new']"}
+ context 'with special cased selectors' do
+ it 'handles data-* attributes with String' do
+ selector = {data_foo: 'user_new'}
+ built = {xpath: ".//*[@data-foo='user_new']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'handles aria-* attributes' do
- selector = {aria_foo: 'user_new'}
- built = {xpath: ".//*[@aria-foo='user_new']"}
+ it 'handles aria-* attributes' do
+ selector = {aria_foo: 'user_new'}
+ built = {xpath: ".//*[@aria-foo='user_new']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it "doesn't modify attribute name when the attribute key is a string" do
- selector = {'_underscore-dash' => 'user_new'}
- built = {xpath: ".//*[@_underscore-dash='user_new']"}
+ it "doesn't modify attribute name when the attribute key is a string" do
+ selector = {'_underscore-dash' => 'user_new'}
+ built = {xpath: ".//*[@_underscore-dash='user_new']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'translates ruby attribute names to content attribute names' do
- selector = {http_equiv: 'foo'}
- built = {xpath: ".//*[@http-equiv='foo']"}
+ it 'translates ruby attribute names to content attribute names' do
+ selector = {http_equiv: 'foo'}
+ built = {xpath: ".//*[@http-equiv='foo']"}
- expect(selector_builder.build(selector)).to eq built
- end
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
+ end
- context 'returns locators that can not be directly translated' do
- it 'attribute with complicated Regexp at end' do
- selector = {action: /me$/}
- built = {xpath: './/*[contains(@action, "me")]', action: /me$/}
+ context 'when can not be directly translated' do
+ it 'returns locator from attribute with complicated Regexp at end' do
+ selector = {action: /me$/}
+ built = {xpath: './/*[contains(@action, "me")]', action: /me$/}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'class with complicated Regexp' do
- selector = {class: /he?r/}
- built = {xpath: './/*[contains(@class, "h") and contains(@class, "r")]', class: [/he?r/]}
+ it 'returns locator from class with complicated Regexp' do
+ selector = {class: /he?r/}
+ built = {xpath: './/*[contains(@class, "h") and contains(@class, "r")]', class: [/he?r/]}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'visible' do
- selector = {tag_name: 'div', visible: true}
- built = {xpath: ".//*[local-name()='div']", visible: true}
+ it 'returns locator from visible' do
+ selector = {tag_name: 'div', visible: true}
+ built = {xpath: ".//*[local-name()='div']", visible: true}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'not visible' do
- selector = {tag_name: 'span', visible: false}
- built = {xpath: ".//*[local-name()='span']", visible: false}
+ it 'returns locator from not visible' do
+ selector = {tag_name: 'span', visible: false}
+ built = {xpath: ".//*[local-name()='span']", visible: false}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'visible text' do
- selector = {tag_name: 'span', visible_text: 'foo'}
- built = {xpath: ".//*[local-name()='span']", visible_text: 'foo'}
+ it 'returns locator from visible text' do
+ selector = {tag_name: 'span', visible_text: 'foo'}
+ built = {xpath: ".//*[local-name()='span']", visible_text: 'foo'}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'raises exception when visible is not boolean' do
- selector = {visible: 'foo'}
- msg = 'expected one of [TrueClass, FalseClass], got "foo":String'
+ it 'raises exception when visible is not boolean' do
+ selector = {visible: 'foo'}
+ msg = 'expected one of [TrueClass, FalseClass], got "foo":String'
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
- it 'raises exception when visible text is not a String or Regexp' do
- selector = {visible_text: 7}
- msg = /expected one of \[String, Regexp\], got 7:Integer/
+ it 'raises exception when visible text is not a String or Regexp' do
+ selector = {visible_text: 7}
+ msg = /expected one of \[String, Regexp\], got 7:Integer/
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
- end
- end
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
+ end
+ end
- context 'with generic element scope' do
- let(:query_scope) { instance_double Watir::HTMLElement }
- let(:scope_built) { {xpath: ".//*[local-name()='div'][@id='table-rows-test']"} }
+ context 'with generic element scope' do
+ let(:query_scope) { instance_double Watir::HTMLElement }
+ let(:scope_built) { {xpath: ".//*[local-name()='div'][@id='table-rows-test']"} }
- before do
- allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
- allow(query_scope).to receive(:browser).and_return(browser)
- allow(selector_builder).to receive(:built).and_return(scope_built)
- end
+ before do
+ allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
+ allow(query_scope).to receive(:browser).and_return(browser)
+ allow(selector_builder).to receive(:built).and_return(scope_built)
+ end
- it 'uses scope' do
- selector = {tag_name: 'div'}
- built = {xpath: "(#{scope_built[:xpath]})[1]//*[local-name()='div']"}
+ it 'uses scope' do
+ selector = {tag_name: 'div'}
+ built = {xpath: "(#{scope_built[:xpath]})[1]//*[local-name()='div']"}
- expect(selector_builder.build(selector)).to eq built
- end
+ expect(selector_builder.build(selector)).to eq built
+ end
- it 'does not use scope if selector is a CSS' do
- selector = {css: 'div'}
+ it 'does not use scope if selector is a CSS' do
+ selector = {css: 'div'}
- build_selector = selector_builder.build(selector)
- expect(build_selector.delete(:scope)).to_not be_nil
- expect(build_selector).to eq selector
- end
+ build_selector = selector_builder.build(selector)
+ expect(build_selector.delete(:scope)).not_to be_nil
+ expect(build_selector).to eq selector
+ end
- it 'does not use scope if selector is a XPath' do
- selector = {xpath: './/*'}
+ it 'does not use scope if selector is a XPath' do
+ selector = {xpath: './/*'}
- build_selector = selector_builder.build(selector)
- expect(build_selector.delete(:scope)).to_not be_nil
- expect(build_selector).to eq selector
- end
+ build_selector = selector_builder.build(selector)
+ expect(build_selector.delete(:scope)).not_to be_nil
+ expect(build_selector).to eq selector
+ end
- it 'does not use scope if selector has :adjacent' do
- selector = {adjacent: :ancestor, index: 0}
- built = {xpath: './ancestor::*[1]'}
+ it 'does not use scope if selector has :adjacent' do
+ selector = {adjacent: :ancestor, index: 0}
+ built = {xpath: './ancestor::*[1]'}
- build_selector = selector_builder.build(selector)
- expect(build_selector.delete(:scope)).to_not be_nil
- expect(build_selector).to eq built
- end
- end
+ build_selector = selector_builder.build(selector)
+ expect(build_selector.delete(:scope)).not_to be_nil
+ expect(build_selector).to eq built
+ end
+ end
- context 'with invalid query scopes' do
- let(:query_scope) { instance_double Watir::HTMLElement }
+ context 'with invalid query scopes' do
+ let(:query_scope) { instance_double Watir::HTMLElement }
- it 'does not use scope if query_scope built has multiple keys' do
- scope_built = {xpath: ".//*[local-name()='div']", visible: true}
- allow(selector_builder).to receive(:built).and_return(scope_built)
- allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
+ it 'does not use scope if query_scope built has multiple keys' do
+ scope_built = {xpath: ".//*[local-name()='div']", visible: true}
+ allow(selector_builder).to receive(:built).and_return(scope_built)
+ allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
- selector = {tag_name: 'div'}
- built = {xpath: ".//*[local-name()='div']"}
+ selector = {tag_name: 'div'}
+ built = {xpath: ".//*[local-name()='div']"}
- build_selector = selector_builder.build(selector)
- expect(build_selector.delete(:scope)).to_not be_nil
- expect(build_selector).to eq built
- end
+ build_selector = selector_builder.build(selector)
+ expect(build_selector.delete(:scope)).not_to be_nil
+ expect(build_selector).to eq built
+ end
- it 'does not use scope if query_scope uses different Selenium Locator' do
- scope_built = {css: '#foo'}
- allow(selector_builder).to receive(:built).and_return(scope_built)
- allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
+ it 'does not use scope if query_scope uses different Selenium Locator' do
+ scope_built = {css: '#foo'}
+ allow(selector_builder).to receive(:built).and_return(scope_built)
+ allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
- selector = {tag_name: 'div'}
- built = {xpath: ".//*[local-name()='div']"}
+ selector = {tag_name: 'div'}
+ built = {xpath: ".//*[local-name()='div']"}
- build_selector = selector_builder.build(selector)
- expect(build_selector.delete(:scope)).to_not be_nil
- expect(build_selector).to eq built
- end
- end
+ build_selector = selector_builder.build(selector)
+ expect(build_selector.delete(:scope)).not_to be_nil
+ expect(build_selector).to eq built
+ end
+ end
- context 'with specific element scope' do
- let(:scope_built) { {xpath: ".//*[local-name()='iframe'][@id='one']"} }
+ context 'with specific element scope' do
+ let(:scope_built) { {xpath: ".//*[local-name()='iframe'][@id='one']"} }
- it 'does not use scope if query scope is an IFrame' do
- query_scope = instance_double Watir::IFrame
- selector_builder = described_class.new(attributes, query_scope)
+ it 'does not use scope if query scope is an IFrame' do
+ query_scope = instance_double Watir::IFrame
+ selector_builder = described_class.new(attributes, query_scope)
- allow(selector_builder).to receive(:built).and_return(scope_built)
- allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
- allow(query_scope).to receive(:browser).and_return(browser)
- allow(query_scope).to receive(:is_a?).with(Watir::Browser).and_return(false)
- allow(query_scope).to receive(:is_a?).with(Watir::ShadowRoot).and_return(false)
- allow(query_scope).to receive(:is_a?).with(Watir::IFrame).and_return(true)
+ allow(selector_builder).to receive(:built).and_return(scope_built)
+ allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
+ allow(query_scope).to receive(:browser).and_return(browser)
+ allow(query_scope).to receive(:is_a?).with(Watir::Browser).and_return(false)
+ allow(query_scope).to receive(:is_a?).with(Watir::ShadowRoot).and_return(false)
+ allow(query_scope).to receive(:is_a?).with(Watir::IFrame).and_return(true)
- selector = {tag_name: 'div'}
- built = {xpath: ".//*[local-name()='div']"}
+ selector = {tag_name: 'div'}
+ built = {xpath: ".//*[local-name()='div']"}
- build_selector = selector_builder.build(selector)
- expect(build_selector.delete(:scope)).to_not be_nil
- expect(build_selector).to eq built
- end
- end
+ build_selector = selector_builder.build(selector)
+ expect(build_selector.delete(:scope)).not_to be_nil
+ expect(build_selector).to eq built
+ end
+ end
- context 'with case-insensitive attributes' do
- let(:upper) { "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'" }
- let(:lower) { "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'" }
+ context 'with case-insensitive attributes' do
+ let(:upper) { "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'" }
+ let(:lower) { "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'" }
- it 'respects case when locating uknown element with uknown attribute' do
- expect(selector_builder.build(hreflang: 'en')).to eq(xpath: ".//*[@hreflang='en']")
- expect(selector_builder.build(hreflang: /en/)).to eq(xpath: './/*[contains(@hreflang, "en")]')
- end
+ it 'respects case when locating uknown element with uknown attribute' do
+ expect(selector_builder.build(hreflang: 'en')).to eq(xpath: ".//*[@hreflang='en']")
+ expect(selector_builder.build(hreflang: /en/)).to eq(xpath: './/*[contains(@hreflang, "en")]')
+ end
- it 'ignores case when locating uknown element with defined attribute' do
- lhs = "translate(@lang,#{upper},#{lower})"
- rhs = "translate('en',#{upper},#{lower})"
- rhs_regex = "translate(\"en\",#{upper},#{lower})"
- expect(selector_builder.build(lang: 'en')).to eq(xpath: ".//*[#{lhs}=#{rhs}]")
- expect(selector_builder.build(lang: /en/)).to eq(xpath: ".//*[contains(#{lhs}, #{rhs_regex})]")
- expect(selector_builder.build(tag_name: /a/, lang: 'en'))
- .to eq(xpath: ".//*[contains(local-name(), \"a\")][#{lhs}=#{rhs}]")
- expect(selector_builder.build(tag_name: /a/, lang: /en/))
- .to eq(xpath: ".//*[contains(local-name(), \"a\")][contains(#{lhs}, #{rhs_regex})]")
- end
+ it 'ignores case when locating uknown element with defined attribute' do
+ lhs = "translate(@lang,#{upper},#{lower})"
+ rhs = "translate('en',#{upper},#{lower})"
+ rhs_regex = "translate(\"en\",#{upper},#{lower})"
+ expect(selector_builder.build(lang: 'en')).to eq(xpath: ".//*[#{lhs}=#{rhs}]")
+ expect(selector_builder.build(lang: /en/)).to eq(xpath: ".//*[contains(#{lhs}, #{rhs_regex})]")
+ expect(selector_builder.build(tag_name: /a/, lang: 'en'))
+ .to eq(xpath: ".//*[contains(local-name(), \"a\")][#{lhs}=#{rhs}]")
+ expect(selector_builder.build(tag_name: /a/, lang: /en/))
+ .to eq(xpath: ".//*[contains(local-name(), \"a\")][contains(#{lhs}, #{rhs_regex})]")
+ end
- it 'ignores case when attribute is defined for element' do
- lhs = "translate(@hreflang,#{upper},#{lower})"
- rhs = "translate('en',#{upper},#{lower})"
- rhs_regex = "translate(\"en\",#{upper},#{lower})"
- expect(selector_builder.build(tag_name: 'a', hreflang: 'en'))
- .to eq(xpath: ".//*[local-name()='a'][#{lhs}=#{rhs}]")
- expect(selector_builder.build(tag_name: 'a', hreflang: /en/))
- .to eq(xpath: ".//*[local-name()='a'][contains(#{lhs}, #{rhs_regex})]")
- end
+ it 'ignores case when attribute is defined for element' do
+ lhs = "translate(@hreflang,#{upper},#{lower})"
+ rhs = "translate('en',#{upper},#{lower})"
+ rhs_regex = "translate(\"en\",#{upper},#{lower})"
+ expect(selector_builder.build(tag_name: 'a', hreflang: 'en'))
+ .to eq(xpath: ".//*[local-name()='a'][#{lhs}=#{rhs}]")
+ expect(selector_builder.build(tag_name: 'a', hreflang: /en/))
+ .to eq(xpath: ".//*[local-name()='a'][contains(#{lhs}, #{rhs_regex})]")
+ end
- it 'respects case when attribute is not defined for element' do
- expect(selector_builder.build(tag_name: 'table', hreflang: 'en'))
- .to eq(xpath: ".//*[local-name()='table'][@hreflang='en']")
- expect(selector_builder.build(tag_name: 'table', hreflang: /en/))
- .to eq(xpath: ".//*[local-name()='table'][contains(@hreflang, \"en\")]")
- expect(selector_builder.build(tag_name: /a/, hreflang: 'en'))
- .to eq(xpath: ".//*[contains(local-name(), \"a\")][@hreflang='en']")
- expect(selector_builder.build(tag_name: /a/, hreflang: /en/))
- .to eq(xpath: './/*[contains(local-name(), "a")][contains(@hreflang, "en")]')
+ it 'respects case when attribute is not defined for element' do
+ expect(selector_builder.build(tag_name: 'table', hreflang: 'en'))
+ .to eq(xpath: ".//*[local-name()='table'][@hreflang='en']")
+ expect(selector_builder.build(tag_name: 'table', hreflang: /en/))
+ .to eq(xpath: ".//*[local-name()='table'][contains(@hreflang, \"en\")]")
+ expect(selector_builder.build(tag_name: /a/, hreflang: 'en'))
+ .to eq(xpath: ".//*[contains(local-name(), \"a\")][@hreflang='en']")
+ expect(selector_builder.build(tag_name: /a/, hreflang: /en/))
+ .to eq(xpath: './/*[contains(local-name(), "a")][contains(@hreflang, "en")]')
+ end
+ end
+ end
end
end
end
end