require File.dirname(__FILE__) + '/../spec_helper'
describe "SAXMachine" do
describe "element" do
describe "when parsing a single element" do
before :each do
@klass = Class.new do
include SAXMachine
element :title
end
end
it "should provide an accessor" do
document = @klass.new
document.title = "Title"
document.title.should == "Title"
end
it "should not overwrite the setter if there is already one present" do
@klass = Class.new do
def title=(val)
@title = "#{val} **"
end
include SAXMachine
element :title
end
document = @klass.new
document.title = "Title"
document.title.should == "Title **"
end
it "should not overwrite the accessor when the element is not present" do
document = @klass.new
document.title = "Title"
document.parse("")
document.title.should == "Title"
end
it "should overwrite the value when the element is present" do
document = @klass.new
document.title = "Old title"
document.parse("
New title")
document.title.should == "New title"
end
it "should save the element text into an accessor" do
document = @klass.parse("My Title")
document.title.should == "My Title"
end
it "should save cdata into an accessor" do
document = @klass.parse("")
document.title.should == "A Title"
end
it "should save the element text into an accessor when there are multiple elements" do
document = @klass.parse("My Titlebar")
document.title.should == "My Title"
end
it "should save the first element text when there are multiple of the same element" do
document = @klass.parse("My Titlebar")
document.title.should == "My Title"
end
end
describe "when parsing multiple elements" do
before :each do
@klass = Class.new do
include SAXMachine
element :title
element :name
end
end
it "should save the element text for a second tag" do
document = @klass.parse("My TitlePaul")
document.name.should == "Paul"
document.title.should == "My Title"
end
end
describe "when using options for parsing elements" do
describe "using the 'as' option" do
before :each do
@klass = Class.new do
include SAXMachine
element :description, :as => :summary
end
end
it "should provide an accessor using the 'as' name" do
document = @klass.new
document.summary = "a small summary"
document.summary.should == "a small summary"
end
it "should save the element text into the 'as' accessor" do
document = @klass.parse("here is a description")
document.summary.should == "here is a description"
end
end
describe "using the :with option" do
describe "and the :value option" do
before :each do
@klass = Class.new do
include SAXMachine
element :link, :value => :href, :with => {:foo => "bar"}
end
end
it "should save the value of a matching element" do
document = @klass.parse("asdf")
document.link.should == "test"
end
it "should save the value of the first matching element" do
document = @klass.parse("")
document.link.should == "first"
end
describe "and the :as option" do
before :each do
@klass = Class.new do
include SAXMachine
element :link, :value => :href, :as => :url, :with => {:foo => "bar"}
element :link, :value => :href, :as => :second_url, :with => {:asdf => "jkl"}
end
end
it "should save the value of the first matching element" do
document = @klass.parse("")
document.url.should == "first"
document.second_url.should == "second"
end
end
end
describe "with only one element" do
before :each do
@klass = Class.new do
include SAXMachine
element :link, :with => {:foo => "bar"}
end
end
it "should save the text of an element that has matching attributes" do
document = @klass.parse("match")
document.link.should == "match"
end
it "should not save the text of an element that doesn't have matching attributes" do
document = @klass.parse("no match")
document.link.should be_nil
end
it "should save the text of an element that has matching attributes when it is the second of that type" do
document = @klass.parse("no matchmatch")
document.link.should == "match"
end
it "should save the text of an element that has matching attributes plus a few more" do
document = @klass.parse("no matchmatch")
document.link.should == "match"
end
end
describe "with multiple elements of same tag" do
before :each do
@klass = Class.new do
include SAXMachine
element :link, :as => :first, :with => {:foo => "bar"}
element :link, :as => :second, :with => {:asdf => "jkl"}
end
end
it "should match the first element" do
document = @klass.parse("no matchfirst matchno match")
document.first.should == "first match"
end
it "should match the second element" do
document = @klass.parse("no matchfirst matchsecond matchhi")
document.second.should == "second match"
end
end
end # using the 'with' option
describe "using the 'value' option" do
before :each do
@klass = Class.new do
include SAXMachine
element :link, :value => :foo
end
end
it "should save the attribute value" do
document = @klass.parse("hello")
document.link.should == 'test'
end
it "should save the attribute value when there is no text enclosed by the tag" do
document = @klass.parse("")
document.link.should == 'test'
end
it "should save the attribute value when the tag close is in the open" do
document = @klass.parse("")
document.link.should == 'test'
end
it "should save two different attribute values on a single tag" do
@klass = Class.new do
include SAXMachine
element :link, :value => :foo, :as => :first
element :link, :value => :bar, :as => :second
end
document = @klass.parse("")
document.first.should == "foo value"
document.second.should == "bar value"
end
end
end
end
describe "elements" do
describe "when parsing multiple elements" do
before :each do
@klass = Class.new do
include SAXMachine
elements :entry, :as => :entries
end
end
it "should provide a collection accessor" do
document = @klass.new
document.entries << :foo
document.entries.should == [:foo]
end
it "should parse a single element" do
document = @klass.parse("hello")
document.entries.should == ["hello"]
end
it "should parse multiple elements" do
document = @klass.parse("helloworld")
document.entries.should == ["hello", "world"]
end
end
describe "when using the class option" do
before :each do
class Foo
include SAXMachine
element :title
end
@klass = Class.new do
include SAXMachine
elements :entry, :as => :entries, :class => Foo
end
end
it "should parse a single element with children" do
document = @klass.parse("a title")
document.entries.size.should == 1
document.entries.first.title.should == "a title"
end
it "should parse multiple elements with children" do
document = @klass.parse("title 1title 2")
document.entries.size.should == 2
document.entries.first.title.should == "title 1"
document.entries.last.title.should == "title 2"
end
it "should not parse a top level element that is specified only in a child" do
document = @klass.parse("no parsecorrect title")
document.entries.size.should == 1
document.entries.first.title.should == "correct title"
end
it "should parse out an attribute value from the tag that starts the collection" do
class Foo
element :entry, :value => :href, :as => :url
end
document = @klass.parse("paul")
document.entries.size.should == 1
document.entries.first.title.should == "paul"
document.entries.first.url.should == "http://pauldix.net"
end
end
end
describe "full example" do
before :each do
@xml = File.read('spec/sax-machine/atom.xml')
class AtomEntry
include SAXMachine
element :title
element :name, :as => :author
element "feedburner:origLink", :as => :url
element :summary
element :content
element :published
end
class Atom
include SAXMachine
element :title
element :link, :value => :href, :as => :url, :with => {:type => "text/html"}
element :link, :value => :href, :as => :feed_url, :with => {:type => "application/atom+xml"}
elements :entry, :as => :entries, :class => AtomEntry
end
end # before
it "should parse the url" do
f = Atom.parse(@xml)
f.url.should == "http://www.pauldix.net/"
end
end
end