Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 193
- Log:
First stage commit of Typo 4.1, modified for the ROOL site.
Includes all local modifications but a final pass needs to be
made to delete any files left over from earlier Typo versions
that shouldn't be here anymore. See the 'tags' section of the
repository for a clean Typo 4.1 tree.Note that symlinks to shared files in the RISC OS Open theme
directory have been deliberately included this time around; I
decided that on balance it was better to leave them in as
placeholders, since unlike symlinks in app/views/shared, the
Typo theme structure is not a standard Rails concept.
- Author:
- rool
- Date:
- Wed Apr 04 18:51:02 +0100 2007
- Size:
- 10678 Bytes
1 | require File.dirname(__FILE__) + '/../test_helper' |
2 | require 'xml_controller' |
3 | require 'dns_mock' |
4 | |
5 | # This test now has optional support for validating the generated RSS feeds. |
6 | # Since Ruby doesn't have a RSS/Atom validator, I'm using the Python source |
7 | # for http://feedvalidator.org and calling it via 'system'. |
8 | # |
9 | # To install the validator, download the source from |
10 | # http://sourceforge.net/cvs/?group_id=99943 |
11 | # Then copy src/feedvalidator and src/rdflib into a Python lib directory. |
12 | # Finally, copy src/demo.py into your path as 'feedvalidator', make it executable, |
13 | # and change the first line to something like '#!/usr/bin/python'. |
14 | |
15 | if($validator_installed == nil) |
16 | $validator_installed = false |
17 | begin |
18 | IO.popen("feedvalidator 2> /dev/null","r") do |pipe| |
19 | if (pipe.read =~ %r{Validating http://www.intertwingly.net/blog/index.}) |
20 | puts "Using locally installed Python feed validator" |
21 | $validator_installed = true |
22 | end |
23 | end |
24 | rescue |
25 | nil |
26 | end |
27 | end |
28 | |
29 | # Re-raise errors caught by the controller. |
30 | class XmlController; def rescue_action(e) raise e end; end |
31 | |
32 | class XmlControllerTest < Test::Unit::TestCase |
33 | fixtures :contents, :categories, :categorizations, :tags, |
34 | :articles_tags, :users, :blogs, :resources |
35 | |
36 | def setup |
37 | @controller = XmlController.new |
38 | @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new |
39 | |
40 | Article.create!(:title => "News from the future!", |
41 | :body => "The future is cool!", |
42 | :keywords => "future", |
43 | :created_at => Time.now + 12.minutes) |
44 | end |
45 | |
46 | def assert_feedvalidator(rss, todo=nil) |
47 | return unless $validator_installed |
48 | |
49 | begin |
50 | file = Tempfile.new('typo-feed-test') |
51 | filename = file.path |
52 | file.write(rss) |
53 | file.close |
54 | |
55 | messages = '' |
56 | |
57 | IO.popen("feedvalidator file://#{filename}") do |pipe| |
58 | messages = pipe.read |
59 | end |
60 | |
61 | okay, messages = parse_validator_messages(messages) |
62 | |
63 | if todo && ! ENV['RUN_TODO_TESTS'] |
64 | assert !okay, messages + "\nTest unexpectedly passed!\nFeed text:\n"+rss |
65 | else |
66 | assert okay, messages + "\nFeed text:\n"+rss |
67 | end |
68 | end |
69 | end |
70 | |
71 | def parse_validator_messages(message) |
72 | messages=message.split(/\n/).reject do |m| |
73 | m =~ /Feeds should not be served with the "text\/plain" media type/ || |
74 | m =~ /Self reference doesn't match document location/ |
75 | end |
76 | |
77 | if(messages.size > 1) |
78 | [false, messages.join("\n")] |
79 | else |
80 | [true, ""] |
81 | end |
82 | end |
83 | |
84 | def test_feed_rss20 |
85 | get :feed, :format => 'rss20', :type => 'feed' |
86 | assert_response :success |
87 | assert_xml @response.body |
88 | assert_feedvalidator @response.body, :todo |
89 | |
90 | assert_rss20(7) |
91 | end |
92 | |
93 | def test_feed_rss20_comments |
94 | get :feed, :format => 'rss20', :type => 'comments' |
95 | assert_response :success |
96 | assert_xml @response.body |
97 | assert_feedvalidator @response.body |
98 | |
99 | assert_rss20(3) |
100 | end |
101 | |
102 | def test_feed_rss20_trackbacks |
103 | get :feed, :format => 'rss20', :type => 'trackbacks' |
104 | assert_response :success |
105 | assert_xml @response.body |
106 | assert_feedvalidator @response.body |
107 | |
108 | assert_rss20(3) |
109 | end |
110 | |
111 | def test_feed_rss20_article |
112 | get :feed, :format => 'rss20', :type => 'article', :id => 1 |
113 | assert_response :success |
114 | assert_xml @response.body |
115 | assert_feedvalidator @response.body, :todo |
116 | |
117 | assert_rss20(2) |
118 | end |
119 | |
120 | def test_feed_rss20_category |
121 | get :feed, :format => 'rss20', :type => 'category', :id => 'personal' |
122 | assert_response :success |
123 | assert_xml @response.body |
124 | assert_feedvalidator @response.body, :todo |
125 | |
126 | assert_rss20(3) |
127 | end |
128 | |
129 | def test_feed_rss20_tag |
130 | get :feed, :format => 'rss20', :type => 'tag', :id => 'foo' |
131 | assert_response :success |
132 | assert_xml @response.body |
133 | assert_feedvalidator @response.body, :todo |
134 | |
135 | assert_rss20(2) |
136 | end |
137 | |
138 | def test_feed_atom10_feed |
139 | get :feed, :format => 'atom10', :type => 'feed' |
140 | |
141 | assert_response :success |
142 | assert_xml @response.body |
143 | assert_feedvalidator @response.body |
144 | |
145 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, |
146 | assigns(:items)) |
147 | |
148 | assert_atom10(7) |
149 | end |
150 | |
151 | def test_feed_atom10_comments |
152 | get :feed, :format => 'atom10', :type => 'comments' |
153 | assert_response :success |
154 | assert_xml @response.body |
155 | assert_feedvalidator @response.body |
156 | |
157 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, |
158 | assigns(:items)) |
159 | |
160 | assert_atom10(3) |
161 | |
162 | assert_xpath('//title[@type="html"]') |
163 | end |
164 | |
165 | def test_feed_atom10_trackbacks |
166 | get :feed, :format => 'atom10', :type => 'trackbacks' |
167 | assert_response :success |
168 | assert_xml @response.body |
169 | assert_feedvalidator @response.body |
170 | |
171 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, |
172 | assigns(:items)) |
173 | |
174 | assert_atom10(3) |
175 | |
176 | assert_xpath('//title[@type="html"]') |
177 | assert_xpath('//summary', "Trackback entry has no summaries") |
178 | end |
179 | |
180 | def test_feed_atom10_article |
181 | get :feed, :format => 'atom10', :type => 'article', :id => 1 |
182 | assert_response :success |
183 | assert_xml @response.body |
184 | assert_feedvalidator @response.body |
185 | |
186 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, |
187 | assigns(:items)) |
188 | |
189 | assert_atom10(2) |
190 | end |
191 | |
192 | def test_feed_atom10_category |
193 | get :feed, :format => 'atom10', :type => 'category', :id => 'personal' |
194 | assert_response :success |
195 | assert_xml @response.body |
196 | assert_feedvalidator @response.body |
197 | |
198 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, |
199 | assigns(:items)) |
200 | |
201 | assert_atom10(3) |
202 | end |
203 | |
204 | def test_feed_atom10_tag |
205 | get :feed, :format => 'atom10', :type => 'tag', :id => 'foo' |
206 | assert_response :success |
207 | assert_xml @response.body |
208 | assert_feedvalidator @response.body |
209 | |
210 | assert_equal(assigns(:items).sort { |a, b| b.created_at <=> a.created_at }, |
211 | assigns(:items)) |
212 | |
213 | assert_atom10(2) |
214 | end |
215 | |
216 | def test_articlerss |
217 | get :articlerss, :id => 1 |
218 | assert_response :redirect |
219 | end |
220 | |
221 | def test_commentrss |
222 | get :commentrss, :id => 1 |
223 | assert_response :redirect |
224 | end |
225 | |
226 | def test_trackbackrss |
227 | get :trackbackrss, :id => 1 |
228 | assert_response :redirect |
229 | end |
230 | |
231 | def test_bad_format |
232 | get :feed, :format => 'atom04', :type => 'feed' |
233 | assert_response :missing |
234 | end |
235 | |
236 | def test_bad_type |
237 | get :feed, :format => 'rss20', :type => 'foobar' |
238 | assert_response :missing |
239 | end |
240 | |
241 | def test_pubdate_conformance |
242 | get :feed, :format => 'rss20', :type => 'feed' |
243 | assert_response :success |
244 | |
245 | assert_equal contents(:article2).created_at.rfc822, get_xpath('/rss/channel/item[title="Article 2!"]/pubDate').first.text |
246 | end |
247 | |
248 | def test_rsd |
249 | get :rsd, :id => 1 |
250 | assert_response :success |
251 | assert_nothing_raised do |
252 | assert REXML::Document.new(@response.body) |
253 | end |
254 | end |
255 | |
256 | def test_extended_rss20 |
257 | set_extended_on_rss true |
258 | get :feed, :format => 'rss20', :type => 'feed' |
259 | assert_response :success |
260 | assert_match /extended content/, @response.body |
261 | |
262 | @controller = XmlController.new |
263 | set_extended_on_rss false |
264 | get :feed, :format => 'rss20', :type => 'feed' |
265 | assert_response :success |
266 | assert_no_match /extended content/, @response.body |
267 | end |
268 | |
269 | def test_atom03 |
270 | get :feed, :format => 'atom03', :type => 'feed' |
271 | assert_response :redirect |
272 | assert_redirected_to :format => 'atom' |
273 | end |
274 | |
275 | def test_extended_atom10 |
276 | set_extended_on_rss true |
277 | get :feed, :format => 'atom10', :type => 'feed' |
278 | assert_response :success |
279 | assert_match /extended content/, @response.body |
280 | assert_not_equal 0, get_xpath(%{//summary]}).size, "Extended feed has no summaries" |
281 | assert_not_equal 0, get_xpath(%{//content]}).size, "Extended feed has no content" |
282 | |
283 | @controller = XmlController.new |
284 | set_extended_on_rss false |
285 | get :feed, :format => 'atom10', :type => 'feed' |
286 | assert_response :success |
287 | assert_no_match /extended content/, @response.body |
288 | assert_not_equal 0, get_xpath(%{//summary]}).size, "Non-Extended feed has no summaries" |
289 | assert_equal 0, get_xpath(%{//content]}).size, "Non-extended feed has content" |
290 | end |
291 | |
292 | def test_xml_atom10 |
293 | get :feed, :format => 'atom10', :type => 'feed' |
294 | assert_response :success |
295 | |
296 | # titles are escaped html |
297 | assert_xpath('//entry/title[text()="Associations aren\'t :dependent =&gt; true anymore" and @type="html"]') |
298 | |
299 | # categories are well formed |
300 | assert_match /this & that/, @response.body |
301 | end |
302 | |
303 | def test_enclosure_rss20 |
304 | get :feed, :format => 'rss20', :type => 'feed' |
305 | assert_response :success |
306 | |
307 | # There's an enclosure in there somewhere |
308 | assert_xpath('/rss/channel/item/enclosure') |
309 | |
310 | # There's an enclosure attached to the node with the title "Article 1!" |
311 | assert_xpath('/rss/channel/item[title="Article 1!"]/enclosure') |
312 | assert_xpath('/rss/channel/item[title="Article 2!"]/enclosure') |
313 | |
314 | # Article 3 exists, but has no enclosure |
315 | assert_xpath('/rss/channel/item[title="Article 3!"]') |
316 | assert_not_xpath('/rss/channel/item[title="Article 3!"]/enclosure') |
317 | end |
318 | |
319 | def test_enclosure_atom10 |
320 | get :feed, :format => 'atom10', :type => 'feed' |
321 | assert_response :success |
322 | |
323 | # There's an enclosure in there somewhere |
324 | assert_xpath('/feed/entry/link[@rel="enclosure"]') |
325 | |
326 | # There's an enclosure attached to "Article 1!" with a length |
327 | assert_xpath('/feed/entry[title="Article 1!"]/link[@rel="enclosure" and @length]') |
328 | |
329 | # There's an enclosure attached to "Article 2!" with no length |
330 | assert_xpath('/feed/entry[title="Article 2!"]/link[@rel="enclosure" and not(@length)]') |
331 | |
332 | # Article 3 exists, but has no enclosure |
333 | assert_xpath('/feed/entry[title="Article 3!"]') |
334 | assert_not_xpath('/feed/entry[title="Article 3!"]/link[@rel="enclosure"]') |
335 | end |
336 | |
337 | def test_itunes |
338 | get :itunes |
339 | assert_response :success |
340 | assert_xml @response.body |
341 | assert_feedvalidator @response.body, :todo |
342 | end |
343 | |
344 | # TODO(laird): make this more robust |
345 | def test_sitemap |
346 | get :feed, :format => 'googlesitemap', :type => 'sitemap' |
347 | |
348 | assert_response :success |
349 | assert_xml @response.body |
350 | end |
351 | |
352 | def assert_rss20(items) |
353 | assert_equal 1, get_xpath(%{/rss[@version="2.0"]/channel[count(child::item)=#{items}]}).size, "RSS 2.0 feed has wrong number of channel/item nodes" |
354 | end |
355 | |
356 | def assert_atom10(entries) |
357 | assert_equal 1, get_xpath(%{/feed[@xmlns="http://www.w3.org/2005/Atom" and count(child::entry)=#{entries}]}).size, "Atom 1.0 feed has wrong number of feed/entry nodes" |
358 | end |
359 | |
360 | def set_extended_on_rss(value) |
361 | this_blog.show_extended_on_rss = value |
362 | end |
363 | end |