rrsimple-rss 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile ADDED
@@ -0,0 +1,213 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require 'rubygems/package_task'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+ require './lib/simple-rss'
9
+
10
+ PKG_VERSION = SimpleRSS::VERSION
11
+ PKG_NAME = "simple-rss"
12
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
13
+ RUBY_FORGE_PROJECT = "simple-rss"
14
+ RUBY_FORGE_USER = ENV['RUBY_FORGE_USER'] || "cardmagic"
15
+ RELEASE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
16
+
17
+ PKG_FILES = FileList[
18
+ "lib/*", "bin/*", "test/**/*", "[A-Z]*", "Rakefile", "html/**/*"
19
+ ]
20
+
21
+ desc "Default Task"
22
+ task :default => [ :test ]
23
+
24
+ # Run the unit tests
25
+ desc "Run all unit tests"
26
+ Rake::TestTask.new("test") { |t|
27
+ t.libs << ["lib", "test"]
28
+ t.pattern = 'test/*/*_test.rb'
29
+ t.verbose = true
30
+ }
31
+
32
+ # Make a console, useful when working on tests
33
+ desc "Generate a test console"
34
+ task :console do
35
+ verbose( false ) { sh "irb -I lib/ -r 'simple-rss'" }
36
+ end
37
+
38
+ # Genereate the RDoc documentation
39
+ desc "Create documentation"
40
+ Rake::RDocTask.new("doc") { |rdoc|
41
+ rdoc.title = "Simple RSS - A Flexible RSS and Atom reader for Ruby"
42
+ rdoc.rdoc_dir = 'html'
43
+ rdoc.rdoc_files.include('README.markdown')
44
+ rdoc.rdoc_files.include('lib/*.rb')
45
+ }
46
+
47
+ # Genereate the package
48
+ spec = Gem::Specification.new do |s|
49
+
50
+ #### Basic information.
51
+
52
+ s.name = 'simple-rss'
53
+ s.version = PKG_VERSION
54
+ s.summary = <<-EOF
55
+ A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation.
56
+ EOF
57
+ s.description = <<-EOF
58
+ A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation.
59
+ EOF
60
+
61
+ #### Which files are to be included in this gem? Everything! (Except CVS directories.)
62
+
63
+ s.files = PKG_FILES
64
+
65
+ #### Load-time details: library and application (you will need one or both).
66
+
67
+ s.require_path = 'lib'
68
+
69
+ #### Documentation and testing.
70
+
71
+ s.has_rdoc = true
72
+
73
+ #### Author and project details.
74
+
75
+ s.author = "Lucas Carlson"
76
+ s.email = "lucas@rufy.com"
77
+ s.homepage = "https://github.com/cardmagic/simple-rss"
78
+ end
79
+
80
+ Gem::PackageTask.new(spec) do |pkg|
81
+ pkg.need_zip = true
82
+ pkg.need_tar = true
83
+ end
84
+
85
+ desc "Report code statistics (KLOCs, etc) from the application"
86
+ task :stats do
87
+ require 'code_statistics'
88
+ CodeStatistics.new(
89
+ ["Library", "lib"],
90
+ ["Units", "test"]
91
+ ).to_s
92
+ end
93
+
94
+ desc "Publish new documentation"
95
+ task :publish do
96
+ Rake::RubyForgePublisher.new('simple-rss', 'cardmagic').upload
97
+ end
98
+
99
+
100
+ desc "Publish the release files to RubyForge."
101
+ task :upload => [:package] do
102
+ files = ["gem", "tar.gz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
103
+
104
+ if RUBY_FORGE_PROJECT then
105
+ require 'net/http'
106
+ require 'open-uri'
107
+
108
+ project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
109
+ project_data = open(project_uri) { |data| data.read }
110
+ group_id = project_data[/[?&]group_id=(\d+)/, 1]
111
+ raise "Couldn't get group id" unless group_id
112
+
113
+ # This echos password to shell which is a bit sucky
114
+ if ENV["RUBY_FORGE_PASSWORD"]
115
+ password = ENV["RUBY_FORGE_PASSWORD"]
116
+ else
117
+ print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
118
+ password = STDIN.gets.chomp
119
+ end
120
+
121
+ login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
122
+ data = [
123
+ "login=1",
124
+ "form_loginname=#{RUBY_FORGE_USER}",
125
+ "form_pw=#{password}"
126
+ ].join("&")
127
+ http.post("/account/login.php", data)
128
+ end
129
+
130
+ cookie = login_response["set-cookie"]
131
+ raise "Login failed" unless cookie
132
+ headers = { "Cookie" => cookie }
133
+
134
+ release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
135
+ release_data = open(release_uri, headers) { |data| data.read }
136
+ package_id = release_data[/[?&]package_id=(\d+)/, 1]
137
+ raise "Couldn't get package id" unless package_id
138
+
139
+ first_file = true
140
+ release_id = ""
141
+
142
+ files.each do |filename|
143
+ basename = File.basename(filename)
144
+ file_ext = File.extname(filename)
145
+ file_data = File.open(filename, "rb") { |file| file.read }
146
+
147
+ puts "Releasing #{basename}..."
148
+
149
+ release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
150
+ release_date = Time.now.strftime("%Y-%m-%d %H:%M")
151
+ type_map = {
152
+ ".zip" => "3000",
153
+ ".tgz" => "3110",
154
+ ".gz" => "3110",
155
+ ".gem" => "1400"
156
+ }; type_map.default = "9999"
157
+ type = type_map[file_ext]
158
+ boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
159
+
160
+ query_hash = if first_file then
161
+ {
162
+ "group_id" => group_id,
163
+ "package_id" => package_id,
164
+ "release_name" => RELEASE_NAME,
165
+ "release_date" => release_date,
166
+ "type_id" => type,
167
+ "processor_id" => "8000", # Any
168
+ "release_notes" => "",
169
+ "release_changes" => "",
170
+ "preformatted" => "1",
171
+ "submit" => "1"
172
+ }
173
+ else
174
+ {
175
+ "group_id" => group_id,
176
+ "release_id" => release_id,
177
+ "package_id" => package_id,
178
+ "step2" => "1",
179
+ "type_id" => type,
180
+ "processor_id" => "8000", # Any
181
+ "submit" => "Add This File"
182
+ }
183
+ end
184
+
185
+ query = "?" + query_hash.map do |(name, value)|
186
+ [name, URI.encode(value)].join("=")
187
+ end.join("&")
188
+
189
+ data = [
190
+ "--" + boundary,
191
+ "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
192
+ "Content-Type: application/octet-stream",
193
+ "Content-Transfer-Encoding: binary",
194
+ "", file_data, ""
195
+ ].join("\x0D\x0A")
196
+
197
+ release_headers = headers.merge(
198
+ "Content-Type" => "multipart/form-data; boundary=#{boundary}"
199
+ )
200
+
201
+ target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
202
+ http.post(target + query, data, release_headers)
203
+ end
204
+
205
+ if first_file then
206
+ release_id = release_response.body[/release_id=(\d+)/, 1]
207
+ raise("Couldn't get release id") unless release_id
208
+ end
209
+
210
+ first_file = false
211
+ end
212
+ end
213
+ end
data/install.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'rbconfig'
2
+ require 'find'
3
+ require 'ftools'
4
+
5
+ include Config
6
+
7
+ # this was adapted from rdoc's install.rb by ways of Log4r
8
+
9
+ $sitedir = CONFIG["sitelibdir"]
10
+ unless $sitedir
11
+ version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
12
+ $libdir = File.join(CONFIG["libdir"], "ruby", version)
13
+ $sitedir = $:.find {|x| x =~ /site_ruby/ }
14
+ if !$sitedir
15
+ $sitedir = File.join($libdir, "site_ruby")
16
+ elsif $sitedir !~ Regexp.quote(version)
17
+ $sitedir = File.join($sitedir, version)
18
+ end
19
+ end
20
+
21
+ makedirs = %w{ shipping }
22
+ makedirs.each {|f| File::makedirs(File.join($sitedir, *f.split(/\//)))}
23
+
24
+ Dir.chdir("lib")
25
+ begin
26
+ require 'rubygems'
27
+ require 'rake'
28
+ rescue LoadError
29
+ puts
30
+ puts "Please install Gem and Rake from http://rubyforge.org/projects/rubygems and http://rubyforge.org/projects/rake"
31
+ puts
32
+ exit(-1)
33
+ end
34
+
35
+ files = FileList["**/*"]
36
+
37
+ # File::safe_unlink *deprecated.collect{|f| File.join($sitedir, f.split(/\//))}
38
+ files.each {|f|
39
+ File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
40
+ }
data/lib/simple-rss.rb ADDED
@@ -0,0 +1,168 @@
1
+ require 'cgi'
2
+ require 'time'
3
+
4
+ class SimpleRSS
5
+ VERSION = "1.3.2"
6
+
7
+ attr_reader :items, :source
8
+ alias :entries :items
9
+
10
+ @@feed_tags = [
11
+ :id,
12
+ :title, :subtitle, :link,
13
+ :description,
14
+ :author, :webMaster, :managingEditor, :contributor,
15
+ :pubDate, :lastBuildDate, :updated, :'dc:date',
16
+ :generator, :language, :docs, :cloud,
17
+ :ttl, :skipHours, :skipDays,
18
+ :image, :logo, :icon, :rating,
19
+ :rights, :copyright,
20
+ :textInput, :'feedburner:browserFriendly',
21
+ :'itunes:author', :'itunes:category', :"full-text"
22
+ ]
23
+
24
+ @@item_tags = [
25
+ :id,
26
+ :title, :link, :'link+alternate', :'link+self', :'link+edit', :'link+replies',
27
+ :author, :contributor,
28
+ :description, :summary, :content, :'content:encoded', :comments,
29
+ :pubDate, :published, :updated, :expirationDate, :modified, :'dc:date',
30
+ :category, :guid,
31
+ :'trackback:ping', :'trackback:about',
32
+ :'dc:creator', :'dc:title', :'dc:subject', :'dc:rights', :'dc:publisher',
33
+ :'feedburner:origLink',
34
+ :'media:content#url', :'media:content#type', :'media:content#height', :'media:content#width',
35
+ :'media:title', :'media:thumbnail#url', :'media:thumbnail#height', :'media:thumbnail#width',
36
+ :'media:credit', :'media:credit#role',
37
+ :'media:category', :'media:category#scheme', :"full-text"
38
+ ]
39
+
40
+ def initialize(source, options={})
41
+ @source = source.respond_to?(:read) ? source.read : source.to_s
42
+ @items = Array.new
43
+ @options = Hash.new.update(options)
44
+
45
+ parse
46
+ end
47
+
48
+ def channel() self end
49
+ alias :feed :channel
50
+
51
+ class << self
52
+ def feed_tags
53
+ @@feed_tags
54
+ end
55
+ def feed_tags=(ft)
56
+ @@feed_tags = ft
57
+ end
58
+
59
+ def item_tags
60
+ @@item_tags
61
+ end
62
+ def item_tags=(it)
63
+ @@item_tags = it
64
+ end
65
+
66
+ # The strict attribute is for compatibility with Ruby's standard RSS parser
67
+ def parse(source, options={})
68
+ new source, options
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def parse
75
+ raise SimpleRSSError, "Poorly formatted feed" unless @source =~ %r{<(channel|feed).*?>.*?</(channel|feed)>}mi
76
+
77
+ # Feed's title and link
78
+ feed_content = $1 if @source =~ %r{(.*?)<(rss:|atom:)?(item|entry).*?>.*?</(rss:|atom:)?(item|entry)>}mi
79
+
80
+ @@feed_tags.each do |tag|
81
+ if feed_content && feed_content =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
82
+ nil
83
+ elsif feed_content && feed_content =~ %r{<(rss:|atom:)?#{tag}(.*?)\/\s*>}mi
84
+ nil
85
+ elsif @source =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
86
+ nil
87
+ elsif @source =~ %r{<(rss:|atom:)?#{tag}(.*?)\/\s*>}mi
88
+ nil
89
+ end
90
+
91
+ if $2 || $3
92
+ tag_cleaned = clean_tag(tag)
93
+ instance_variable_set("@#{ tag_cleaned }", clean_content(tag, $2, $3))
94
+ self.class.class_eval("attr_reader :#{ tag_cleaned }")
95
+ end
96
+ end
97
+
98
+ # RSS items' title, link, and description
99
+ @source.scan( %r{<(rss:|atom:)?(item|entry)([\s][^>]*)?>(.*?)</(rss:|atom:)?(item|entry)>}mi ) do |match|
100
+ item = Hash.new
101
+ @@item_tags.each do |tag|
102
+ if tag.to_s.include?("+")
103
+ tag_data = tag.to_s.split("+")
104
+ tag = tag_data[0]
105
+ rel = tag_data[1]
106
+
107
+ if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)rel=['"]#{rel}['"](.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
108
+ nil
109
+ elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)rel=['"]#{rel}['"](.*?)/\s*>}mi
110
+ nil
111
+ end
112
+ item[clean_tag("#{tag}+#{rel}")] = clean_content(tag, $3, $4) if $3 || $4
113
+ elsif tag.to_s.include?("#")
114
+ tag_data = tag.to_s.split("#")
115
+ tag = tag_data[0]
116
+ attrib = tag_data[1]
117
+ if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)#{attrib}=['"](.*?)['"](.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
118
+ nil
119
+ elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)#{attrib}=['"](.*?)['"](.*?)/\s*>}mi
120
+ nil
121
+ end
122
+ item[clean_tag("#{tag}_#{attrib}")] = clean_content(tag, attrib, $3) if $3
123
+ else
124
+ if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
125
+ nil
126
+ elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)/\s*>}mi
127
+ nil
128
+ end
129
+ item[clean_tag(tag)] = clean_content(tag, $2, $3) if $2 || $3
130
+ end
131
+ end
132
+
133
+ def item.method_missing(name, *args) self[name] end
134
+
135
+ @items << item
136
+ end
137
+
138
+ end
139
+
140
+ def clean_content(tag, attrs, content)
141
+ content = content.to_s
142
+ case tag
143
+ when :pubDate, :lastBuildDate, :published, :updated, :expirationDate, :modified, :'dc:date'
144
+ Time.parse(content) rescue unescape(content)
145
+ when :author, :contributor, :skipHours, :skipDays
146
+ unescape(content.gsub(/<.*?>/,''))
147
+ when :"full-text"
148
+ CGI.unescapeHTML unescape(content.gsub(/<.*?>/,'')).force_encoding("UTF-8")
149
+ else
150
+ content.empty? && "#{attrs} " =~ /href=['"]?([^'"]*)['" ]/mi ? $1.strip : unescape(content)
151
+ end
152
+ end
153
+
154
+ def clean_tag(tag)
155
+ tag != :'full-text' ? tag.to_s.gsub(':','_').intern : tag.to_s.gsub('-','_').intern
156
+ end
157
+
158
+ def unescape(content)
159
+ if content.respond_to?(:force_encoding) && content.force_encoding("binary") =~ /([^-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]%)/n then
160
+ CGI.unescape(content).gsub(/(<!\[CDATA\[|\]\]>)/,'').strip
161
+ else
162
+ content.gsub(/(<!\[CDATA\[|\]\]>)/,'').strip
163
+ end
164
+ end
165
+ end
166
+
167
+ class SimpleRSSError < StandardError
168
+ end
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "rrsimple-rss"
3
+ s.version = "1.3.2"
4
+ s.date = "2010-07-06"
5
+ s.summary = "A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation."
6
+ s.email = "rodrigo@rrmartins.com"
7
+ s.homepage = "http://github.com/cardmagic/simple-rss"
8
+ s.description = "A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation."
9
+ s.has_rdoc = true
10
+ s.authors = ["Lucas Carlson", "Rodrigo Martins"]
11
+ s.files = ["install.rb", "lib", "lib/simple-rss.rb", "LICENSE", "Rakefile", "README.markdown", "simple-rss.gemspec", "test", "test/base", "test/base/base_test.rb", "test/data", "test/data/atom.xml", "test/data/not-rss.xml", "test/data/rss09.rdf", "test/data/rss20.xml", "test/test_helper.rb"]
12
+ s.rubyforge_project = 'rrsimple-rss'
13
+ end
@@ -0,0 +1,95 @@
1
+ #!/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'test_helper'
5
+ require 'pry'
6
+
7
+ class BaseTest < Test::Unit::TestCase
8
+ def setup
9
+ @rss_bbc = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/bbc.xml')
10
+ @rss09 = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/rss09.rdf')
11
+ @rss20 = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/rss20.xml')
12
+ @media_rss = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/media_rss.xml')
13
+ @atom = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/atom.xml')
14
+ end
15
+
16
+ def test_channel
17
+ assert_equal @rss_bbc, @rss_bbc.channel
18
+ assert_equal @rss09, @rss09.channel
19
+ assert_equal @rss20, @rss20.channel
20
+ assert_equal @atom, @atom.feed
21
+ end
22
+
23
+ def test_items
24
+ assert_kind_of Array, @rss_bbc.items
25
+ assert_kind_of Array, @rss09.items
26
+ assert_kind_of Array, @rss20.items
27
+ assert_kind_of Array, @atom.entries
28
+ end
29
+
30
+ def test_rss_bbc
31
+ assert_equal 9, @rss_bbc.items.size
32
+ assert_equal "BBCBrasil.com | Vídeos e Fotos", @rss_bbc.title.force_encoding("UTF-8")
33
+ assert_equal "http://www.bbc.com/portuguese/full_all.xml", @rss_bbc.channel.link
34
+ assert_equal "http://www.bbc.com/portuguese/noticias/2015/11/151102_nadador_atlantico_desafio_lgb", @rss_bbc.items.first.link
35
+ assert_equal "http://www.bbc.com/portuguese/noticias/2015/11/151102_nadador_atlantico_desafio_lgb", @rss_bbc.items.first[:link]
36
+ assert_equal Time.parse("2015-11-03 08:21:50 -0200"), @rss_bbc.items.first.pubDate
37
+ assert_equal Time.parse("2015-11-05 07:33:38 -0200"), @rss_bbc.channel.lastBuildDate
38
+ assert_not_nil @rss_bbc.items.first.full_text
39
+ end
40
+
41
+ def test_rss09
42
+ assert_equal 10, @rss09.items.size
43
+ assert_equal "Slashdot", @rss09.title
44
+ assert_equal "http://slashdot.org/", @rss09.channel.link
45
+ assert_equal "http://books.slashdot.org/article.pl?sid=05/08/29/1319236&amp;from=rss", @rss09.items.first.link
46
+ assert_equal "http://books.slashdot.org/article.pl?sid=05/08/29/1319236&amp;from=rss", @rss09.items.first[:link]
47
+ assert_equal Time.parse("2005-09-09 06:52:31 -0300"), @rss09.items.first.dc_date
48
+ assert_equal Time.parse("Fri Sep 09 02:52:31 PDT 2005"), @rss09.channel.dc_date
49
+ assert_nil @rss09.items.first.full_text
50
+ end
51
+
52
+ def test_media_rss
53
+ assert_equal 20, @media_rss.items.size
54
+ assert_equal "Uploads from herval", @media_rss.title
55
+ assert_equal "http://www.flickr.com/photos/herval/", @media_rss.channel.link
56
+ assert_equal "http://www.flickr.com/photos/herval/4671960608/", @media_rss.items.first.link
57
+ assert_equal "http://www.flickr.com/photos/herval/4671960608/", @media_rss.items.first[:link]
58
+ assert_equal "http://farm5.static.flickr.com/4040/4671960608_10cb945d5c_o.jpg", @media_rss.items.first.media_content_url
59
+ assert_equal "image/jpeg", @media_rss.items.first.media_content_type
60
+ assert_equal "3168", @media_rss.items.first.media_content_height
61
+ assert_equal "4752", @media_rss.items.first.media_content_width
62
+ assert_equal "Woof?", @media_rss.items.first.media_title
63
+ assert_equal "http://farm5.static.flickr.com/4040/4671960608_954d2297bc_s.jpg", @media_rss.items.first.media_thumbnail_url
64
+ assert_equal "75", @media_rss.items.first.media_thumbnail_height
65
+ assert_equal "75", @media_rss.items.first.media_thumbnail_width
66
+ assert_equal "herval", @media_rss.items.first.media_credit
67
+ assert_equal "photographer", @media_rss.items.first.media_credit_role
68
+ assert_equal "pets frodo", @media_rss.items.first.media_category
69
+ assert_equal "urn:flickr:tags", @media_rss.items.first.media_category_scheme
70
+ assert_nil @media_rss.items.first.full_text
71
+ end
72
+
73
+ def test_rss20
74
+ assert_equal 10, @rss20.items.size
75
+ assert_equal "Technoblog", @rss20.title
76
+ assert_equal "http://tech.rufy.com", @rss20.channel.link
77
+ assert_equal "http://feeds.feedburner.com/rufytech?m=68", @rss20.items.first.link
78
+ assert_equal "http://feeds.feedburner.com/rufytech?m=68", @rss20.items.first[:link]
79
+ assert_equal "This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site.", @rss20.channel.feedburner_browserFriendly
80
+ assert_nil @rss20.items.first.full_text
81
+ end
82
+
83
+ def test_atom
84
+ assert_equal 1, @atom.entries.size
85
+ assert_equal "dive into mark", @atom.title
86
+ assert_equal "http://example.org/", @atom.feed.link
87
+ assert_equal "http://example.org/2005/04/02/atom", @atom.entries.first.link
88
+ assert_equal "http://example.org/2005/04/02/atom", @atom.entries.first[:link]
89
+ assert_nil @atom.entries.first.full_text
90
+ end
91
+
92
+ def test_bad_feed
93
+ assert_raise(SimpleRSSError) { SimpleRSS.parse(open(File.dirname(__FILE__) + '/../data/not-rss.xml')) }
94
+ end
95
+ end
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom">
3
+ <rss:title type="text">dive into mark</title>
4
+ <subtitle type="html">
5
+ A &lt;em&gt;lot&lt;/em&gt; of effort
6
+ went into making this effortless
7
+ </subtitle>
8
+ <updated>2005-07-31T12:29:29Z</updated>
9
+ <id>tag:example.org,2003:3</id>
10
+ <link rel="alternate" type="text/html"
11
+ hreflang="en" href="http://example.org/"/>
12
+ <link rel="self" type="application/atom+xml"
13
+ href="http://example.org/feed.atom"/>
14
+ <rights>Copyright (c) 2003, Mark Pilgrim</rights>
15
+ <generator uri="http://www.example.com/" version="1.0">
16
+ Example Toolkit
17
+ </generator>
18
+ <entry>
19
+ <title>Atom draft-07 snapshot</title>
20
+ <link rel="alternate" type="text/html"
21
+ href="http://example.org/2005/04/02/atom"/>
22
+ <link rel="enclosure" type="audio/mpeg" length="1337"
23
+ href="http://example.org/audio/ph34r_my_podcast.mp3"/>
24
+ <id>tag:example.org,2003:3.2397</id>
25
+ <updated>2005-07-31T12:29:29Z</updated>
26
+ <published>2003-12-13T08:29:29-04:00</published>
27
+ <author>
28
+ <name>Mark Pilgrim</name>
29
+ <uri>http://example.org/</uri>
30
+ <email>f8dy@example.com</email>
31
+ </author>
32
+ <contributor>
33
+ <name>Sam Ruby</name>
34
+ </contributor>
35
+ <contributor>
36
+ <name>Joe Gregorio</name>
37
+ </contributor>
38
+ <content type="xhtml" xml:lang="en"
39
+ xml:base="http://diveintomark.org/">
40
+ <div xmlns="http://www.w3.org/1999/xhtml">
41
+ <p><i>[Update: The Atom draft is finished.]</i></p>
42
+ </div>
43
+ </content>
44
+ </entry>
45
+ </feed>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>This ain't RSS!</title>
4
+ </head>
5
+ <body>
6
+ No, this is HTML, not RSS.
7
+ </body>
8
+ </html>
@@ -0,0 +1,79 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <rdf:RDF
4
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
5
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns="http://my.netscape.com/rdf/simple/0.9/">
7
+
8
+ <channel>
9
+ <title>Slashdot</title>
10
+ <link>http://slashdot.org/</link>
11
+ <description>News for nerds, stuff that matters</description>
12
+ <dc:date>2005-09-09T02:52:31-07:00</dc:date>
13
+ </channel>
14
+
15
+ <image>
16
+ <title>Slashdot</title>
17
+ <url>http://images.slashdot.org/topics/topicslashdot.gif</url>
18
+ <link>http://slashdot.org/</link>
19
+ </image>
20
+
21
+ <item>
22
+ <title>JBoss - A Developer's Notebook</title>
23
+ <link>http://books.slashdot.org/article.pl?sid=05/08/29/1319236&amp;from=rss</link>
24
+ <dc:date>2005-09-09T02:52:31-07:00</dc:date>
25
+ </item>
26
+
27
+ <item>
28
+ <title>Apple Hedges Its Bet on New Intel Chips</title>
29
+ <link>http://hardware.slashdot.org/article.pl?sid=05/08/29/1314219&amp;from=rss</link>
30
+ </item>
31
+
32
+ <item>
33
+ <title>Beowulf Pioneer Lured From Cal Tech to LSU</title>
34
+ <link>http://slashdot.org/article.pl?sid=05/08/29/1035240&amp;from=rss</link>
35
+ </item>
36
+
37
+ <item>
38
+ <title>Google Talk Claims Openness, Lacks S2S Support</title>
39
+ <link>http://it.slashdot.org/article.pl?sid=05/08/29/1022242&amp;from=rss</link>
40
+ </item>
41
+
42
+ <item>
43
+ <title>The End of the Bar Code</title>
44
+ <link>http://slashdot.org/article.pl?sid=05/08/29/1020220&amp;from=rss</link>
45
+ </item>
46
+
47
+ <item>
48
+ <title>2.6.13 Linux Kernel Released</title>
49
+ <link>http://linux.slashdot.org/article.pl?sid=05/08/29/0334205&amp;from=rss</link>
50
+ </item>
51
+
52
+ <item>
53
+ <title>HOWTO: The Anti-Printer</title>
54
+ <link>http://hardware.slashdot.org/article.pl?sid=05/08/29/1016204&amp;from=rss</link>
55
+ </item>
56
+
57
+ <item>
58
+ <title>OSDL Skeptical Of Joint Study with Microsoft</title>
59
+ <link>http://linux.slashdot.org/article.pl?sid=05/08/29/0625224&amp;from=rss</link>
60
+ </item>
61
+
62
+ <item>
63
+ <title>New Mad Cow Test on the Horizon?</title>
64
+ <link>http://science.slashdot.org/article.pl?sid=05/08/29/0619259&amp;from=rss</link>
65
+ </item>
66
+
67
+ <item>
68
+ <title>Coffee A Health Drink?</title>
69
+ <link>http://science.slashdot.org/article.pl?sid=05/08/29/0342207&amp;from=rss</link>
70
+ </item>
71
+
72
+ <textinput>
73
+ <title>Search Slashdot</title>
74
+ <description>Search Slashdot stories</description>
75
+ <name>query</name>
76
+ <link>http://slashdot.org/search.pl</link>
77
+ </textinput>
78
+
79
+ </rdf:RDF>