aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/test/template/atom_feed_helper_test.rb
blob: 7fa5e042fb4eff44a40da5d4d3f34ba1f4687dda (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
require "abstract_unit"

Scroll = Struct.new(:id, :to_param, :title, :body, :updated_at, :created_at) do
  extend ActiveModel::Naming
  include ActiveModel::Conversion

  def persisted?
    false
  end
end

class ScrollsController < ActionController::Base
  FEEDS = {}
  FEEDS["defaults"] = <<-EOT
        atom_feed(:schema_date => '2008') do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["entry_options"] = <<-EOT
        atom_feed do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll, :url => "/otherstuff/" + scroll.to_param.to_s, :updated => Time.utc(2007, 1, scroll.id)) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["entry_type_options"] = <<-EOT
        atom_feed(:schema_date => '2008') do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll, :type => 'text/xml') do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["entry_url_false_option"] = <<-EOT
        atom_feed do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll, :url => false) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["xml_block"] = <<-EOT
        atom_feed do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          feed.author do |author|
            author.name("DHH")
          end

          @scrolls.each do |scroll|
            feed.entry(scroll, :url => "/otherstuff/" + scroll.to_param.to_s, :updated => Time.utc(2007, 1, scroll.id)) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')
            end
          end
        end
    EOT
  FEEDS["feed_with_atomPub_namespace"] = <<-EOT
        atom_feed({'xmlns:app' => 'http://www.w3.org/2007/app',
                 'xmlns:openSearch' => 'http://a9.com/-/spec/opensearch/1.1/'}) do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')
              entry.tag!('app:edited', Time.now)

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["feed_with_overridden_ids"] = <<-EOT
        atom_feed({:id => 'tag:test.rubyonrails.org,2008:test/'}) do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll, :id => "tag:test.rubyonrails.org,2008:"+scroll.id.to_s) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')
              entry.tag!('app:edited', Time.now)

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["feed_with_xml_processing_instructions"] = <<-EOT
        atom_feed(:schema_date => '2008',
          :instruct => {'xml-stylesheet' => { :href=> 't.css', :type => 'text/css' }}) do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["feed_with_xml_processing_instructions_duplicate_targets"] = <<-EOT
        atom_feed(:schema_date => '2008',
          :instruct => {'target1' => [{ :a => '1', :b => '2' }, { :c => '3', :d => '4' }]}) do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll) do |entry|
              entry.title(scroll.title)
              entry.content(scroll.body, :type => 'html')

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["feed_with_xhtml_content"] = <<-'EOT'
        atom_feed do |feed|
          feed.title("My great blog!")
          feed.updated(@scrolls.first.created_at)

          @scrolls.each do |scroll|
            feed.entry(scroll) do |entry|
              entry.title(scroll.title)
              entry.summary(:type => 'xhtml') do |xhtml|
                xhtml.p "before #{scroll.id}"
                xhtml.p {xhtml << scroll.body}
                xhtml.p "after #{scroll.id}"
              end
              entry.tag!('app:edited', Time.now)

              entry.author do |author|
                author.name("DHH")
              end
            end
          end
        end
    EOT
  FEEDS["provide_builder"] = <<-'EOT'
          # we pass in the new_xml to the helper so it doesn't
          # call anything on the original builder
          new_xml = Builder::XmlMarkup.new(:target=>''.dup)
          atom_feed(:xml => new_xml) do |feed|
            feed.title("My great blog!")
            feed.updated(@scrolls.first.created_at)

            @scrolls.each do |scroll|
              feed.entry(scroll) do |entry|
                entry.title(scroll.title)
                entry.content(scroll.body, :type => 'html')

                entry.author do |author|
                  author.name("DHH")
                end
              end
            end
          end
    EOT
  def index
    @scrolls = [
      Scroll.new(1, "1", "Hello One", "Something <i>COOL!</i>", Time.utc(2007, 12, 12, 15), Time.utc(2007, 12, 12, 15)),
      Scroll.new(2, "2", "Hello Two", "Something Boring", Time.utc(2007, 12, 12, 15)),
    ]

    render inline: FEEDS[params[:id]], type: :builder
  end
end

class AtomFeedTest < ActionController::TestCase
  tests ScrollsController

  def setup
    super
    @request.host = "www.nextangle.com"
  end

  def test_feed_should_use_default_language_if_none_is_given
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_match(%r{xml:lang="en-US"}, @response.body)
    end
  end

  def test_feed_should_include_two_entries
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_select "entry", 2
    end
  end

  def test_entry_should_only_use_published_if_created_at_is_present
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_select "published", 1
    end
  end

  def test_providing_builder_to_atom_feed
    with_restful_routing(:scrolls) do
      get :index, params: { id: "provide_builder" }
      # because we pass in the non-default builder, the content generated by the
      # helper should go 'nowhere'.  Leaving the response body blank.
      assert @response.body.blank?
    end
  end

  def test_entry_with_prefilled_options_should_use_those_instead_of_querying_the_record
    with_restful_routing(:scrolls) do
      get :index, params: { id: "entry_options" }

      assert_select "updated", Time.utc(2007, 1, 1).xmlschema
      assert_select "updated", Time.utc(2007, 1, 2).xmlschema
    end
  end

  def test_self_url_should_default_to_current_request_url
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_select "link[rel=self][href=\"http://www.nextangle.com/scrolls?id=defaults\"]"
    end
  end

  def test_feed_id_should_be_a_valid_tag
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_select "id", text: "tag:www.nextangle.com,2008:/scrolls?id=defaults"
    end
  end

  def test_entry_id_should_be_a_valid_tag
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_select "entry id", text: "tag:www.nextangle.com,2008:Scroll/1"
      assert_select "entry id", text: "tag:www.nextangle.com,2008:Scroll/2"
    end
  end

  def test_feed_should_allow_nested_xml_blocks
    with_restful_routing(:scrolls) do
      get :index, params: { id: "xml_block" }
      assert_select "author name", text: "DHH"
    end
  end

  def test_feed_should_include_atomPub_namespace
    with_restful_routing(:scrolls) do
      get :index, params: { id: "feed_with_atomPub_namespace" }
      assert_match %r{xml:lang="en-US"}, @response.body
      assert_match %r{xmlns="http://www\.w3\.org/2005/Atom"}, @response.body
      assert_match %r{xmlns:app="http://www\.w3\.org/2007/app"}, @response.body
    end
  end

  def test_feed_should_allow_overriding_ids
    with_restful_routing(:scrolls) do
      get :index, params: { id: "feed_with_overridden_ids" }
      assert_select "id", text: "tag:test.rubyonrails.org,2008:test/"
      assert_select "entry id", text: "tag:test.rubyonrails.org,2008:1"
      assert_select "entry id", text: "tag:test.rubyonrails.org,2008:2"
    end
  end

  def test_feed_xml_processing_instructions
    with_restful_routing(:scrolls) do
      get :index, params: { id: "feed_with_xml_processing_instructions" }
      assert_match %r{<\?xml-stylesheet [^\?]*type="text/css"}, @response.body
      assert_match %r{<\?xml-stylesheet [^\?]*href="t\.css"}, @response.body
    end
  end

  def test_feed_xml_processing_instructions_duplicate_targets
    with_restful_routing(:scrolls) do
      get :index, params: { id: "feed_with_xml_processing_instructions_duplicate_targets" }
      assert_match %r{<\?target1 (a="1" b="2"|b="2" a="1")\?>}, @response.body
      assert_match %r{<\?target1 (c="3" d="4"|d="4" c="3")\?>}, @response.body
    end
  end

  def test_feed_xhtml
    with_restful_routing(:scrolls) do
      get :index, params: { id:  "feed_with_xhtml_content" }
      assert_match %r{xmlns="http://www\.w3\.org/1999/xhtml"}, @response.body
      assert_select "summary", text: /Something Boring/
      assert_select "summary", text: /after 2/
    end
  end

  def test_feed_entry_type_option_default_to_text_html
    with_restful_routing(:scrolls) do
      get :index, params: { id: "defaults" }
      assert_select "entry link[rel=alternate][type=\"text/html\"]"
    end
  end

  def test_feed_entry_type_option_specified
    with_restful_routing(:scrolls) do
      get :index, params: { id: "entry_type_options" }
      assert_select "entry link[rel=alternate][type=\"text/xml\"]"
    end
  end

  def test_feed_entry_url_false_option_adds_no_link
    with_restful_routing(:scrolls) do
      get :index, params: { id: "entry_url_false_option" }
      assert_select "entry link", false
    end
  end

  private
    def with_restful_routing(resources)
      with_routing do |set|
        set.draw do
          resources(resources)
        end
        yield
      end
    end
end