diff --git a/Rakefile b/Rakefile index 0bd87d6..7a7873a 100644 --- a/Rakefile +++ b/Rakefile @@ -24,6 +24,7 @@ begin s.description = "Generic html element locators for integration testing" s.authors = ['Sven Fuchs'] s.files = FileList["[A-Z]*", "{lib,test,vendor}/**/*"] + s.add_dependency 'htmlentities' end rescue LoadError puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" diff --git a/lib/locator.rb b/lib/locator.rb index 5027701..14b6ad4 100644 --- a/lib/locator.rb +++ b/lib/locator.rb @@ -1,12 +1,15 @@ require 'core_ext/string/underscore' module Locator - autoload :Boolean, 'locator/boolean' - autoload :Dom, 'locator/dom' - autoload :Element, 'locator/element' - autoload :Matcher, 'locator/matcher' - autoload :Result, 'locator/result' - autoload :Xpath, 'locator/xpath' + autoload :Boolean, 'locator/boolean' + autoload :Dom, 'locator/dom' + autoload :Decoding, 'locator/decoding' + autoload :Element, 'locator/element' + autoload :Matcher, 'locator/matcher' + autoload :Result, 'locator/result' + autoload :Xpath, 'locator/xpath' + + extend Decoding class ElementNotFound < StandardError def initialize(*args) diff --git a/lib/locator/decoding.rb b/lib/locator/decoding.rb new file mode 100644 index 0000000..0bfea11 --- /dev/null +++ b/lib/locator/decoding.rb @@ -0,0 +1,28 @@ +module Locator + module Decoding + def decode_entities? + @decode_entities ||= true + end + + def decode_entities=(decode_entities) + @decode_entities = decode_entities + end + + def decode_attributes(hash) + Hash[*hash.map { |name, value| [name, decode(value)] }.flatten] + end + + def decode(value) + value.is_a?(String) ? html_entities.decode(value) : value + end + + protected + + def html_entities + html_entities ||= begin + require 'htmlentities' + HTMLEntities.new + end + end + end +end \ No newline at end of file diff --git a/lib/locator/dom/nokogiri/element.rb b/lib/locator/dom/nokogiri/element.rb index 70f3e67..c0c7941 100644 --- a/lib/locator/dom/nokogiri/element.rb +++ b/lib/locator/dom/nokogiri/element.rb @@ -25,10 +25,6 @@ def css_path element.css_path.to_s end - def content - element.content - end - def value case name when 'input' @@ -45,6 +41,10 @@ def checked checked ? checked.value : nil end + def content + element.content + end + def inner_html element.inner_html end diff --git a/lib/locator/element.rb b/lib/locator/element.rb index 915866a..d5dbe92 100644 --- a/lib/locator/element.rb +++ b/lib/locator/element.rb @@ -52,6 +52,8 @@ def xpath(*args) protected def lookup(scope, selector, attributes = {}) + attributes = Locator.decode_attributes(attributes) if Locator.decode_entities? + scope = scope.respond_to?(:elements_by_xpath) ? scope : Locator::Dom.page(scope) xpath = xpath(attributes) xpath = ".#{xpath}" unless xpath[0, 1] == '.' diff --git a/lib/locator/result.rb b/lib/locator/result.rb index 07c2ec3..bcb6910 100644 --- a/lib/locator/result.rb +++ b/lib/locator/result.rb @@ -8,6 +8,7 @@ class Result < Array class << self def matches?(name, value, selector) + value, selector = Locator.decode(value), Locator.decode(selector) if Locator.decode_entities? value = normalize_whitespace(value) case selector when Regexp diff --git a/test/locator/dom/nokogiri_test.rb b/test/locator/dom/nokogiri_test.rb index a1ac6e2..46ac10f 100644 --- a/test/locator/dom/nokogiri_test.rb +++ b/test/locator/dom/nokogiri_test.rb @@ -13,4 +13,30 @@ class NokogiriTest < Test::Unit::TestCase dom = Locator::Dom::Nokogiri::Page.new('the link') assert Element.new.locate(dom, 'the link') end + + # test "Nokogiri and Umlauts" do + # encoded = '

ö

' + # unencoded = '

ö

' + # + # # this is ok + # fragment = Nokogiri::HTML.fragment(encoded) + # assert_equal encoded, fragment.to_s + # + # # this seems weird ... wtf experiences ahead + # fragment = Nokogiri::HTML.fragment(unencoded) + # assert_equal encoded, fragment.to_s + # + # options = + # Nokogiri::XML::ParseOptions::RECOVER | + # Nokogiri::XML::ParseOptions::NOERROR | + # Nokogiri::XML::ParseOptions::NOWARNING + # + # # this is ok + # node = Nokogiri::HTML.parse(encoded, nil, nil, options) + # assert_equal encoded, node.xpath('//p').first.to_s + # + # # this is ok + # node = Nokogiri::HTML.parse(unencoded, nil, 'utf-8', options) + # assert_equal unencoded, node.xpath('//p').first.to_s + # end end \ No newline at end of file diff --git a/test/locator_test.rb b/test/locator_test.rb index e6391ab..8714227 100644 --- a/test/locator_test.rb +++ b/test/locator_test.rb @@ -33,16 +33,6 @@ class LocatorTest < Test::Unit::TestCase assert_equal 'foo', element.attribute('id') end - test "locates an element by node name and selector (containing an umlaut)" do - html = 'BerlinMünchen' - assert_equal 'München', locate(html, 'München').content - end - - test "locates an element by node name and attribute (containing an umlaut)" do - html = '' - assert_equal html, locate(html, :value => 'München').to_s - end - # within test "within scopes to a locator" do @@ -97,4 +87,46 @@ class LocatorTest < Test::Unit::TestCase html = '

' assert_nil locate(html, :div) { locate(html, :form, :class => 'bar') { locate(html, :p) } } end + + # locate with umlauts + + test "locates an element by encoded selector from html containing an encoded umlaut" do + html = 'BerlinMünchen' + assert_equal 'München', locate(html, 'München').content + end + + test "locates an element by encoded selector from html containing an non-encoded umlaut" do + html = 'BerlinMünchen' + assert_equal 'München', locate(html, 'München').content + end + + test "locates an element by non-encoded selector from html containing an encoded umlaut" do + html = 'BerlinMünchen' + assert_equal 'München', locate(html, 'München').content + end + + test "locates an element by non-encoded selector from html containing a non-encoded umlaut" do + html = 'BerlinMünchen' + assert_equal 'München', locate(html, 'München').content + end + + test "locates an element by encoded attribute from html containing an encoded umlaut" do + html = '' + assert_equal 'München', locate(html, :value => 'München').value + end + + test "locates an element by encoded attribute from html containing an non-encoded umlaut" do + html = '' + assert_equal 'München', locate(html, :value => 'München').value + end + + test "locates an element by non-encoded attribute from html containing an encoded umlaut" do + html = '' + assert_equal 'München', locate(html, :value => 'München').value + end + + test "locates an element by non-encoded attribute from html containing a non-encoded umlaut" do + html = '' + assert_equal 'München', locate(html, :value => 'München').value + end end \ No newline at end of file diff --git a/test/webrat.rb b/test/webrat.rb new file mode 100644 index 0000000..9d70c22 --- /dev/null +++ b/test/webrat.rb @@ -0,0 +1,27 @@ +# encoding: utf-8 +require File.expand_path('../test_helper', __FILE__) +require 'action_pack' +require 'webrat' +require 'rack/test' + +Webrat.configure do |config| + config.mode = :rack +end + +class WebratBehaviorTest < Test::Unit::TestCase + include Webrat::Methods + + def last_response + @last_response ||= Rack::Response.new + end + + def with_html(html) + last_response.body = html + end + + test "foo" do + with_html 'München' + field = field_by_xpath(".//span") + p field.element.to_s + end +end \ No newline at end of file