Skip to content

Commit

Permalink
optionally decode html entities (defaults to true) to make behavior r…
Browse files Browse the repository at this point in the history
…e html entities a bit more consistent
  • Loading branch information
Sven Fuchs committed Apr 2, 2010
1 parent 71180d4 commit 7f31143
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 20 deletions.
1 change: 1 addition & 0 deletions Rakefile
Expand Up @@ -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"
Expand Down
15 changes: 9 additions & 6 deletions 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)
Expand Down
28 changes: 28 additions & 0 deletions 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
8 changes: 4 additions & 4 deletions lib/locator/dom/nokogiri/element.rb
Expand Up @@ -25,10 +25,6 @@ def css_path
element.css_path.to_s
end

def content
element.content
end

def value
case name
when 'input'
Expand All @@ -45,6 +41,10 @@ def checked
checked ? checked.value : nil
end

def content
element.content
end

def inner_html
element.inner_html
end
Expand Down
2 changes: 2 additions & 0 deletions lib/locator/element.rb
Expand Up @@ -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] == '.'
Expand Down
1 change: 1 addition & 0 deletions lib/locator/result.rb
Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions test/locator/dom/nokogiri_test.rb
Expand Up @@ -13,4 +13,30 @@ class NokogiriTest < Test::Unit::TestCase
dom = Locator::Dom::Nokogiri::Page.new('<a href="#">the link</a>')
assert Element.new.locate(dom, 'the link')
end

# test "Nokogiri and Umlauts" do
# encoded = '<p>&ouml;</p>'
# unencoded = '<p>ö</p>'
#
# # 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
52 changes: 42 additions & 10 deletions test/locator_test.rb
Expand Up @@ -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 = '<span>Berlin</span><span>München</span>'
assert_equal 'München', locate(html, 'München').content
end

test "locates an element by node name and attribute (containing an umlaut)" do
html = '<input type="text" value="München">'
assert_equal html, locate(html, :value => 'München').to_s
end

# within

test "within scopes to a locator" do
Expand Down Expand Up @@ -97,4 +87,46 @@ class LocatorTest < Test::Unit::TestCase
html = '<form></form><div><form><p id="foo"><p></form></div>'
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 = '<span>Berlin</span><span>M&uuml;nchen</span>'
assert_equal 'München', locate(html, 'M&uuml;nchen').content
end

test "locates an element by encoded selector from html containing an non-encoded umlaut" do
html = '<span>Berlin</span><span>München</span>'
assert_equal 'München', locate(html, 'M&uuml;nchen').content
end

test "locates an element by non-encoded selector from html containing an encoded umlaut" do
html = '<span>Berlin</span><span>M&uuml;nchen</span>'
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 = '<span>Berlin</span><span>München</span>'
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 = '<input type="text" value="M&uuml;nchen">'
assert_equal 'München', locate(html, :value => 'M&uuml;nchen').value
end

test "locates an element by encoded attribute from html containing an non-encoded umlaut" do
html = '<input type="text" value="München">'
assert_equal 'München', locate(html, :value => 'M&uuml;nchen').value
end

test "locates an element by non-encoded attribute from html containing an encoded umlaut" do
html = '<input type="text" value="M&uuml;nchen">'
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 = '<input type="text" value="München">'
assert_equal 'München', locate(html, :value => 'München').value
end
end
27 changes: 27 additions & 0 deletions 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 '<span>München</span>'
field = field_by_xpath(".//span")
p field.element.to_s
end
end

0 comments on commit 7f31143

Please sign in to comment.