test-xml-0.1.8/ 0000755 0001750 0001750 00000000000 13137606226 012327 5 ustar pravi pravi test-xml-0.1.8/test_xml.gemspec 0000644 0001750 0001750 00000002237 13137606226 015537 0 ustar pravi pravi lib = File.expand_path('../lib/', __FILE__)
$:.unshift lib unless $:.include?(lib)
require 'test_xml/version'
Gem::Specification.new do |s|
s.name = "test_xml"
s.version = TestXml::VERSION
s.authors = ["Pavel Gabriel", "Nick Sutterer"]
s.homepage = "http://github.com/alovak/test_xml"
s.summary = "Test your XML with Test::Unit, MiniTest, RSpec, or Cucumber."
s.description = "Test your XML with Test::Unit, MiniTest, RSpec, or Cucumber using handy assertions like #assert_xml_equal or #assert_xml_structure_contain."
s.email = ["alovak@gmail.com", "apotonick@gmail.com"]
s.require_path = "lib"
s.has_rdoc = true
s.extra_rdoc_files = ['README.rdoc']
s.rdoc_options = ['--main', 'README.rdoc']
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.license = "MIT"
s.add_dependency("diffy", "~> 3.0")
s.add_dependency("nokogiri", ">= 1.3.2")
s.add_development_dependency("rake")
s.add_development_dependency("rdoc")
s.add_development_dependency("test-unit", "~> 3.1")
s.add_development_dependency("rspec", ">= 2.2")
end
test-xml-0.1.8/lib/ 0000755 0001750 0001750 00000000000 13137606226 013075 5 ustar pravi pravi test-xml-0.1.8/lib/test_xml/ 0000755 0001750 0001750 00000000000 13137606226 014734 5 ustar pravi pravi test-xml-0.1.8/lib/test_xml/mini_test.rb 0000644 0001750 0001750 00000000401 13137606226 017247 0 ustar pravi pravi require "test_xml"
# TODO: should we remove test_xml/spec?
MiniTest::Expectations.class_eval do
TestXml::ASSERTIONS.each do |cfg|
infect_an_assertion(cfg.assert_name, cfg.expectation)
end
end
class MiniTest::Test
include TestXml::Assertions
end
test-xml-0.1.8/lib/test_xml/assertions.rb 0000644 0001750 0001750 00000005276 13137606226 017465 0 ustar pravi pravi require 'ostruct'
require 'diffy'
module TestXml
class AssertionConfig < OpenStruct
def assert_name
"assert_#{name}"
end
def assert_not_name
"assert_not_#{name}"
end
def expectation
"must_#{matcher}"
end
end
ASSERTIONS = [
AssertionConfig.new(
:name => :xml_contain,
:matcher => :contain_xml,
:message => lambda { |expect, actual| "the xml:\n#{actual}\nshould contain xml:\n#{expect}" },
:message_when_negated => lambda { |expect, actual| "the xml:\n#{actual}\nshould not contain xml:\n#{expect} but it does" }
),
AssertionConfig.new(
:name => :xml_structure_contain,
:matcher => :contain_xml_structure,
:message => lambda { |expect, actual| "the xml:\n#{actual}\nshould match xml structure:\n#{expect}" },
:message_when_negated => lambda { |expect, actual| "the xml:\n#{actual}\nshould not match xml structure:\n#{expect} but it does" }
),
AssertionConfig.new(
:name => :xml_equal,
:matcher => :equal_xml,
:message => lambda { |expect, actual| sprintf "the xml:\n%s\nshould exactly match xml:\n%s\n\nDiff:\n%s", actual, expect, diff(expect, actual) },
:message_when_negated => lambda { |expect, actual| "the xml:\n#{actual}\nshould not exactly match xml:\n#{expect} but it does" }
),
AssertionConfig.new(
:name => :xml_structure_equal,
:matcher => :equal_xml_structure,
:message => lambda { |expect, actual| "the xml:\n#{actual}\nshould exactly match xml structure:\n#{expect}" },
:message_when_negated => lambda { |expect, actual| "the xml:\n#{actual}\nshould not exactly match xml structure:\n#{expect} but it does" }
)
]
def self.diff(expect, actual)
doc_actual = Nokogiri::XML.parse(actual, &:noblanks)
doc_expect = Nokogiri::XML.parse(expect, &:noblanks)
diff = Diffy::Diff.new(doc_expect.to_xml, doc_actual.to_xml, :context => 3, :include_diff_info => true).to_a
return "" if diff.empty?
# Skip diff headers, they're useless since they refer to tempfiles
diff[2..-1].join("")
end
module Assertions
ASSERTIONS.each do |cfg|
define_method(cfg.assert_name) do |a, b|
correct_assert(MatcherMethods.send(cfg.name, a, b), cfg.message.call(a, b))
end
define_method(cfg.assert_not_name) do |a, b|
correct_assert(! MatcherMethods.send(cfg.name, a, b), cfg.message_when_negated.call(a, b))
end
end
private
def correct_assert(boolean, message)
if RUBY_VERSION =~ /1.9.2/ or defined?(MiniTest)
assert(boolean, message)
else
assert_block(message) do
boolean
end
end
end
end
end
test-xml-0.1.8/lib/test_xml/spec.rb 0000644 0001750 0001750 00000001332 13137606226 016212 0 ustar pravi pravi require 'test_xml'
# Adds assertions to RSpec.
TestXml::ASSERTIONS.each do |cfg|
RSpec::Matchers.define cfg.matcher do |expected|
match do |actual|
TestXml::MatcherMethods.send(cfg.name, actual, expected)
end
# RSpec 2 and 3 use different methods
# to access failure messages.
if RSpec::Expectations::Version::STRING[0] == "2"
failure_message_for_should { |actual| cfg.message.call(expected, actual) }
failure_message_for_should_not { |actual| cfg.message_when_negated.call(expected, actual) }
else
failure_message { |actual| cfg.message.call(expected, actual) }
failure_message_when_negated { |actual| cfg.message_when_negated.call(expected, actual) }
end
end
end
test-xml-0.1.8/lib/test_xml/matcher_methods.rb 0000644 0001750 0001750 00000001603 13137606226 020427 0 ustar pravi pravi module TestXml
# This module implements the actual matchers with their conditions.
module MatcherMethods
def self.xml_contain(subject, pattern)
actual, expected = parse_xml(subject, pattern)
actual.match?(expected, true)
end
def self.xml_equal(subject, pattern)
actual, expected = parse_xml(subject, pattern)
actual.match?(expected, true) && expected.match?(actual, true)
end
def self.xml_structure_contain(subject, pattern)
actual, expected = parse_xml(subject, pattern)
actual.match?(expected)
end
def self.xml_structure_equal(subject, pattern)
actual, expected = parse_xml(subject, pattern)
actual.match?(expected) && expected.match?(actual)
end
private
def self.parse_xml(subject, pattern)
[Nokogiri::XML.parse(subject).root, Nokogiri::XML.parse(pattern).root]
end
end
end
test-xml-0.1.8/lib/test_xml/test_unit.rb 0000644 0001750 0001750 00000000144 13137606226 017276 0 ustar pravi pravi require "test/unit"
require "test_xml"
class Test::Unit::TestCase
include TestXml::Assertions
end test-xml-0.1.8/lib/test_xml/nokogiri.rb 0000644 0001750 0001750 00000000103 13137606226 017074 0 ustar pravi pravi class Nokogiri::XML::Node
include TestXml::NokogiriExt::Node
end
test-xml-0.1.8/lib/test_xml/nokogiri/ 0000755 0001750 0001750 00000000000 13137606226 016555 5 ustar pravi pravi test-xml-0.1.8/lib/test_xml/nokogiri/node.rb 0000644 0001750 0001750 00000003403 13137606226 020027 0 ustar pravi pravi module TestXml
module NokogiriExt
module Node
def match?(element, compare_value = false)
if compare_value && element.leaf?
comparable_attributes == element.comparable_attributes and equal_text?(element)
else
#TODO clean this part of the code
if compare_value
(comparable_attributes == element.comparable_attributes) &&
contains_elements_of?(element) &&
element.elements.all? {|el| matches_at_least_one?(el, compare_value) }
else
contains_elements_of?(element) &&
element.elements.all? {|el| matches_at_least_one?(el, compare_value) }
end
end
end
def elements
children.collect {|node| node if node.element? }.delete_if {|node| node.nil?}
end
# Attributes of the current node.
def comparable_attributes
attributes.collect {|k,a| [k.downcase, a.value]}.sort
end
# Check if node is either childless, self-closing, or has content text.
def leaf?
children.size == 0 or (children.size == 1 && children.first.text?)
end
def placeholder?
TestXml.placeholders_enabled? and (content =~ /^`.*`$/)
end
private
def equal_text?(element)
element.content = content if element.placeholder?
content == element.content
end
def contains_elements_of?(element)
element.elements.find {|el| not contains?(el)}.nil?
end
def contains?(element)
children.find {|node| node.element? && node.name == element.name }
end
def matches_at_least_one?(element, compare_value)
search(element.name).find { |el| el.match?(element, compare_value) }
end
end
end
end
test-xml-0.1.8/lib/test_xml/version.rb 0000644 0001750 0001750 00000000047 13137606226 016747 0 ustar pravi pravi module TestXml
VERSION = "0.1.8"
end
test-xml-0.1.8/lib/test_xml.rb 0000644 0001750 0001750 00000000446 13137606226 015265 0 ustar pravi pravi require 'nokogiri'
require 'test_xml/nokogiri/node'
require 'test_xml/nokogiri'
require 'test_xml/assertions'
require 'test_xml/matcher_methods'
module TestXml
class << self
attr_accessor :enable_placeholders
def placeholders_enabled?
!!enable_placeholders
end
end
end
test-xml-0.1.8/README.rdoc 0000644 0001750 0001750 00000005244 13137606226 014142 0 ustar pravi pravi = TestXml
== DESCRIPTION
TestXml is a small extension for testing XML/HTML. Extending RSpec and TestUnit it makes asserting and comparing XML snippets easy, and is especially helpful for testing RESTful web services and their XML representations.
== FEATURES
* Runs with RSpec 2 or 3, Test::Unit, MiniTest and Cucumber
* Ruby >= 1.8
* Test XML structure and content
== INSTALL
gem install test_xml
== EXAMPLES
=== Test::Unit and MiniTest
def test_item_representation
assert_xml_equal "