ensure atom feeds have absolute urls and authors; fixes #7047

named_context_url wasn't always giving back absolute urls where it needed to
for atom feeds. additionally, some atom entries did not author entries which
are needed when the main feed does not have an author entry.

test-plan:
- view a modified atom feed in the browser and make sure all links are absolute
  and all entries have an author.
- if the url is externally available, run it through http://feedvalidator.org/
  and check that it validates.

Change-Id: I9bc2b99cd15ed5677bfd9d2cb977a29568ae4016
Reviewed-on: https://gerrit.instructure.com/9833
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
This commit is contained in:
Simon Williams 2012-04-04 13:06:48 -06:00
parent a71075f781
commit e4e34ca31d
29 changed files with 297 additions and 50 deletions

View File

@ -45,9 +45,9 @@ class AnnouncementsController < ApplicationController
format.atom {
feed = Atom::Feed.new do |f|
f.title = t(:feed_name, "%{course} Announcements Feed", :course => @context.name)
f.links << Atom::Link.new(:href => named_context_url(@context, :context_announcements_url))
f.links << Atom::Link.new(:href => polymorphic_url([@context, :announcements]), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_announcements_url)
f.id = polymorphic_url([@context, :announcements])
end
announcements.each do |e|
feed.entries << e.to_atom
@ -65,7 +65,7 @@ class AnnouncementsController < ApplicationController
elsif @context.is_a?(Group)
channel.description = t(:podcast_feed_description_group, "Any media files linked from or embedded within announcements in the group \"%{group}\" will appear in this feed.", :group => @context.name)
end
channel.link = named_context_url(@context, :context_announcements_url)
channel.link = polymorphic_url([@context, :announcements])
channel.pubDate = Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")
elements = Announcement.podcast_elements(announcements, @context)
elements.each do |item|

View File

@ -207,7 +207,7 @@ class CalendarsController < ApplicationController
format.atom do
feed = Atom::Feed.new do |f|
f.title = t :feed_title, "%{course_or_group_name} Calendar Feed", :course_or_group_name => @context.name
f.links << Atom::Link.new(:href => calendar_url_for(@context))
f.links << Atom::Link.new(:href => calendar_url_for(@context), :rel => 'self')
f.updated = Time.now
f.id = calendar_url_for(@context)
end

View File

@ -633,7 +633,7 @@ class ConversationsController < ApplicationController
load_all_contexts
feed = Atom::Feed.new do |f|
f.title = t('titles.rss_feed', "Conversations Feed")
f.links << Atom::Link.new(:href => conversations_url)
f.links << Atom::Link.new(:href => conversations_url, :rel => 'self')
f.updated = Time.now
f.id = conversations_url
end

View File

@ -1054,9 +1054,9 @@ class CoursesController < ApplicationController
return unless get_feed_context(:only => [:course])
feed = Atom::Feed.new do |f|
f.title = t('titles.rss_feed', "%{course} Feed", :course => @context.name)
f.links << Atom::Link.new(:href => named_context_url(@context, :context_url))
f.links << Atom::Link.new(:href => course_url(@context), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_url)
f.id = course_url(@context)
end
@entries = []
@entries.concat @context.assignments.active

View File

@ -179,9 +179,9 @@ class DiscussionEntriesController < ApplicationController
format.atom {
feed = Atom::Feed.new do |f|
f.title = t :posts_feed_title, "%{title} Posts Feed", :title => @topic.title
f.links << Atom::Link.new(:href => named_context_url(@context, :context_discussion_topic_url, @topic.id))
f.links << Atom::Link.new(:href => polymorphic_url([@context, @topic]), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_discussion_topic_url, @topic.id)
f.id = polymorphic_url([@context, @topic])
end
feed.entries << @topic.to_atom
@discussion_entries.sort_by{|e| e.updated_at}.each do |e|
@ -196,7 +196,7 @@ class DiscussionEntriesController < ApplicationController
channel = RSS::Rss::Channel.new
channel.title = t :podcast_feed_title, "%{title} Posts Podcast Feed", :title => @topic.title
channel.description = t :podcast_description, "Any media files linked from or embedded within entries in the topic \"%{title}\" will appear in this feed.", :title => @topic.title
channel.link = named_context_url(@context, :context_discussion_topic_url, @topic.id)
channel.link = polymorphic_url([@context, @topic])
channel.pubDate = Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")
elements = Announcement.podcast_elements(@entries, @context)
elements.each do |item|

View File

@ -349,9 +349,9 @@ class DiscussionTopicsController < ApplicationController
return unless get_feed_context
feed = Atom::Feed.new do |f|
f.title = t :discussion_feed_title, "%{title} Discussion Feed", :title => @context.name
f.links << Atom::Link.new(:href => named_context_url(@context, :context_discussion_topics_url))
f.links << Atom::Link.new(:href => polymorphic_url([@context, :discussion_topics]), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_discussion_topics_url)
f.id = polymorphic_url([@context, :discussion_topics])
end
@entries = []
@entries.concat @context.discussion_topics.reject{|a| a.locked_for?(@current_user, :check_policies => true) }

View File

@ -186,22 +186,22 @@ class EportfoliosController < ApplicationController
def public_feed
@portfolio = Eportfolio.find(params[:eportfolio_id])
respond_to do |format|
if @portfolio.public || params[:verifier] == @portfolio.uuid
@entries = @portfolio.eportfolio_entries.find(:all, :order => 'eportfolio_entries.created_at DESC')
feed = Atom::Feed.new do |f|
f.title = t(:title, "%{portfolio_name} Feed", :portfolio_name => @portfolio.name)
f.links << Atom::Link.new(:href => eportfolio_url(@portfolio.id))
f.updated = @entries.first.updated_at rescue Time.now
f.id = eportfolio_url(@portfolio.id)
end
@entries.each do |e|
feed.entries << e.to_atom(:private => params[:verifier] == @portfolio.uuid)
end
format.atom { render :text => feed.to_xml }
else
authorized_action(nil, nil, :bad_permission)
if @portfolio.public || params[:verifier] == @portfolio.uuid
@entries = @portfolio.eportfolio_entries.find(:all, :order => 'eportfolio_entries.created_at DESC')
feed = Atom::Feed.new do |f|
f.title = t(:title, "%{portfolio_name} Feed", :portfolio_name => @portfolio.name)
f.links << Atom::Link.new(:href => eportfolio_url(@portfolio.id), :rel => 'self')
f.updated = @entries.first.updated_at rescue Time.now
f.id = eportfolio_url(@portfolio.id)
end
@entries.each do |e|
feed.entries << e.to_atom(:private => params[:verifier] == @portfolio.uuid)
end
respond_to do |format|
format.atom { render :text => feed.to_xml }
end
else
authorized_action(nil, nil, :bad_permission)
end
end
end

View File

@ -656,9 +656,9 @@ class FilesController < ApplicationController
return unless get_feed_context
feed = Atom::Feed.new do |f|
f.title = t :feed_title, "%{course_or_group} Files Feed", :course_or_group => @context.name
f.links << Atom::Link.new(:href => named_context_url(@context, :context_files_url))
f.links << Atom::Link.new(:href => polymorphic_url([@context, :files]), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_files_url)
f.id = polymorphic_url([@context, :files])
end
@entries = []
@entries.concat @context.attachments.active

View File

@ -341,9 +341,9 @@ class GradebooksController < ApplicationController
respond_to do |format|
feed = Atom::Feed.new do |f|
f.title = t('titles.feed_for_course', "%{course} Gradebook Feed", :course => @context.name)
f.links << Atom::Link.new(:href => named_context_url(@context, :context_gradebook_url))
f.links << Atom::Link.new(:href => course_gradebook_url(@context), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_gradebook_url)
f.id = course_gradebook_url(@context)
end
@context.submissions.each do |e|
feed.entries << e.to_atom

View File

@ -251,9 +251,9 @@ class GroupsController < ApplicationController
return unless get_feed_context(:only => [:group])
feed = Atom::Feed.new do |f|
f.title = t(:feed_title, "%{course_or_account_name} Feed", :course_or_account_name => @context.full_name)
f.links << Atom::Link.new(:href => named_context_url(@context, :context_url))
f.links << Atom::Link.new(:href => group_url(@context), :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_url)
f.id = group_url(@context)
end
@entries = []
@entries.concat @context.calendar_events.active

View File

@ -845,9 +845,9 @@ class UsersController < ApplicationController
return unless get_feed_context(:only => [:user])
feed = Atom::Feed.new do |f|
f.title = "#{@context.name} Feed"
f.links << Atom::Link.new(:href => dashboard_url)
f.links << Atom::Link.new(:href => dashboard_url, :rel => 'self')
f.updated = Time.now
f.id = named_context_url(@context, :context_url)
f.id = user_url(@context)
end
@entries = []
@context.courses.each do |context|

View File

@ -613,9 +613,11 @@ class Assignment < ActiveRecord::Base
def to_atom(opts={})
extend ApplicationHelper
author_name = self.context.present? ? self.context.name : t('atom_no_author', "No Author")
Atom::Entry.new do |entry|
entry.title = t(:feed_entry_title, "Assignment: %{assignment}", :assignment => self.title) unless opts[:include_context]
entry.title = t(:feed_entry_title_with_course, "Assignment, %{course}: %{assignment}", :assignment => self.title, :course => self.context.name) if opts[:include_context]
entry.authors << Atom::Person.new(:name => author_name)
entry.updated = self.updated_at.utc
entry.published = self.created_at.utc
entry.id = "tag:#{HostUrl.default_host},#{self.created_at.strftime("%Y-%m-%d")}:/assignments/#{self.feed_code}_#{self.due_at.strftime("%Y-%m-%d-%H-%M") rescue "none"}"

View File

@ -854,13 +854,14 @@ class Attachment < ActiveRecord::Base
def to_atom(opts={})
Atom::Entry.new do |entry|
entry.title = t(:feed_title_with_context, "File, %{course_or_group}: %{title}", :course_or_group => self.context.name, :title => self.context.name) if opts[:include_context]
entry.title = t(:feed_title, "File: %{title}", :title => self.context.name) unless opts[:include_context]
entry.title = t(:feed_title_with_context, "File, %{course_or_group}: %{title}", :course_or_group => self.context.name, :title => self.context.name) if opts[:include_context]
entry.authors << Atom::Person.new(:name => self.context.name)
entry.updated = self.updated_at
entry.published = self.created_at
entry.id = "tag:#{HostUrl.default_host},#{self.created_at.strftime("%Y-%m-%d")}:/files/#{self.feed_code}"
entry.links << Atom::Link.new(:rel => 'alternate',
:href => "http://#{HostUrl.context_host(self.context)}/#{context_url_prefix}/files/#{self.id}")
:href => "http://#{HostUrl.context_host(self.context)}/#{context_url_prefix}/files/#{self.id}")
entry.content = Atom::Content::Html.new("#{self.display_name}")
end
end

View File

@ -340,6 +340,7 @@ class CalendarEvent < ActiveRecord::Base
Atom::Entry.new do |entry|
entry.title = t(:feed_item_title, "Calendar Event: %{event_title}", :event_title => self.title) unless opts[:include_context]
entry.title = t(:feed_item_title_with_context, "Calendar Event, %{course_or_account_name}: %{event_title}", :course_or_account_name => self.context.name, :event_title => self.title) if opts[:include_context]
entry.authors << Atom::Person.new(:name => self.context.name)
entry.updated = self.updated_at.utc
entry.published = self.created_at.utc
entry.links << Atom::Link.new(:rel => 'alternate',

View File

@ -240,7 +240,7 @@ class ConversationMessage < ActiveRecord::Base
if !self.attachments.empty?
content += "<ul>"
self.attachments.each do |attachment|
href = file_download_url(attachment, :verifier => attachment.uuid,
href = file_download_url(attachment, :verifier => attachment.uuid,
:download => '1',
:download_frd => '1',
:host => HostUrl.context_host(self.context))

View File

@ -272,6 +272,7 @@ class DiscussionEntry < ActiveRecord::Base
named_scope :newest_first, :order => 'discussion_entries.created_at DESC'
def to_atom(opts={})
author_name = self.user.present? ? self.user.name : t('atom_no_author', "No Author")
Atom::Entry.new do |entry|
subject = [self.discussion_topic.title]
subject << self.discussion_topic.context.name if opts[:include_context]
@ -280,6 +281,7 @@ class DiscussionEntry < ActiveRecord::Base
else
entry.title = subject.to_sentence
end
entry.authors << Atom::Person.new(:name => author_name)
entry.updated = self.updated_at
entry.published = self.created_at
entry.id = "tag:#{HostUrl.default_host},#{self.created_at.strftime("%Y-%m-%d")}:/discussion_entries/#{self.feed_code}"

View File

@ -509,10 +509,12 @@ class DiscussionTopic < ActiveRecord::Base
end
def to_atom(opts={})
author_name = self.user.present? ? self.user.name : t('#discussion_topic.atom_no_author', "No Author")
prefix = [self.is_announcement ? t('#titles.announcement', "Announcement") : t('#titles.discussion', "Discussion")]
prefix << self.context.name if opts[:include_context]
Atom::Entry.new do |entry|
entry.title = [before_label(prefix.to_sentence), self.title].join(" ")
entry.authors << Atom::Person.new(:name => author_name)
entry.updated = self.updated_at
entry.published = self.created_at
entry.id = "tag:#{HostUrl.default_host},#{self.created_at.strftime("%Y-%m-%d")}:/discussion_topics/#{self.feed_code}"

View File

@ -144,6 +144,7 @@ class EportfolioEntry < ActiveRecord::Base
def to_atom(opts={})
Atom::Entry.new do |entry|
entry.title = "#{self.name}"
entry.authors << Atom::Person.new(:name => t(:atom_author, "ePortfolio Entry"))
entry.updated = self.updated_at
entry.published = self.created_at
url = "http://#{HostUrl.default_host}/eportfolios/#{self.eportfolio_id}/#{self.eportfolio_category.slug}/#{self.slug}"

View File

@ -908,8 +908,10 @@ class Submission < ActiveRecord::Base
def to_atom(opts={})
prefix = self.assignment.context_prefix || ""
author_name = self.assignment.present? && self.assignment.context.present? ? self.assignment.context.name : t('atom_no_author', "No Author")
Atom::Entry.new do |entry|
entry.title = "#{self.user && self.user.name} -- #{self.assignment && self.assignment.title}#{", " + self.assignment.context.name if self.assignment && opts[:include_context]}"
entry.title = "#{self.user && self.user.name} -- #{self.assignment && self.assignment.title}#{", " + self.assignment.context.name if opts[:include_context]}"
entry.authors << Atom::Person.new(:name => author_name)
entry.updated = self.updated_at
entry.published = self.created_at
entry.id = "tag:#{HostUrl.default_host},#{self.created_at.strftime("%Y-%m-%d")}:/submissions/#{self.feed_code}_#{self.updated_at.strftime("%Y-%m-%d")}"

View File

@ -327,6 +327,7 @@ class WikiPage < ActiveRecord::Base
prefix = namespace.context_prefix || ""
Atom::Entry.new do |entry|
entry.title = t(:atom_entry_title, "Wiki Page, %{course_or_group_name}: %{page_title}", :course_or_group_name => namespace.context.name, :page_title => self.title)
entry.authors << Atom::Person.new(:name => t(:atom_author, "Wiki Page"))
entry.updated = self.updated_at
entry.published = self.created_at
entry.id = "tag:#{HostUrl.default_host},#{self.created_at.strftime("%Y-%m-%d")}:/wiki_pages/#{self.feed_code}_#{self.updated_at.strftime("%Y-%m-%d")}"

View File

@ -59,5 +59,33 @@ describe AnnouncementsController do
assigns[:announcements][0].should eql(@announcement)
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
course_with_student(:active_all => true)
@context = @course
announcement_model
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @enrollment.feed_code + 'x'
assigns[:problem].should match /The verification code does not match/
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @enrollment.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @enrollment.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -101,12 +101,15 @@ describe CalendarsController do
end
describe "GET 'public_feed'" do
it "should assign variables" do
before(:each) do
course_with_student(:active_all => true)
course_event
@course.is_public = true
@course.save!
@course.assignments.create!(:title => "some assignment")
end
it "should assign variables" do
get 'public_feed', :feed_code => "course_#{@course.uuid}"
response.should be_success
assigns[:events].should_not be_nil
@ -115,12 +118,6 @@ describe CalendarsController do
end
it "should assign variables" do
course_with_student(:active_all => true)
course_event
@course.is_public = true
@course.save!
@course.assignments.create!(:title => "some assignment")
e = @user.calendar_events.create(:title => "my event")
get 'public_feed', :feed_code => "user_#{@user.uuid}"
response.should be_success
@ -128,6 +125,27 @@ describe CalendarsController do
assigns[:events].should_not be_empty
assigns[:events].should be_include(e)
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code + 'x'
assigns[:problem].should eql("The verification code is invalid.")
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
describe "POST 'switch_calendar'" do

View File

@ -780,6 +780,33 @@ describe CoursesController do
}
}
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
course_with_student(:active_all => true)
assignment_model(:course => @course)
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @enrollment.feed_code + 'x'
assigns[:problem].should match /The verification code does not match/
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @enrollment.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @enrollment.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -412,4 +412,32 @@ describe DiscussionTopicsController do
@course.discussion_topics.should_not be_include(@topic)
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
course_with_student(:active_all => true)
course_topic
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @course.feed_code + 'x'
assigns[:problem].should eql("The verification code is invalid.")
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @course.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @course.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -189,4 +189,28 @@ describe EportfoliosController do
e3.position.should eql(2)
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
eportfolio_model
@eportfolio.public = true
@eportfolio.save!
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :eportfolio_id => @eportfolio.id, :format => 'atom'
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :eportfolio_id => @eportfolio.id, :format => 'atom'
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -549,4 +549,32 @@ describe FilesController do
response.status.to_i.should == 400
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
course_with_student(:active_all => true)
user_file
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code + 'x'
assigns[:problem].should match /The verification code is invalid/
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -28,7 +28,6 @@ describe GradebooksController do
before(:each) do
Course.expects(:find).returns(['a course'])
end
end
describe "GET 'grade_summary'" do
@ -141,7 +140,6 @@ describe GradebooksController do
end
describe "POST 'update_submission'" do
it "should have a route for update_submission" do
params_from(:post, "/courses/20/gradebook/update_submission").should ==
{:controller => "gradebooks", :action => "update_submission", :course_id => "20"}
@ -207,7 +205,34 @@ describe GradebooksController do
params_from(:get, "/courses/20/gradebook/speed_grader").should ==
{:controller => "gradebooks", :action => "speed_grader", :course_id => "20"}
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
course_with_student(:active_all => true)
assignment_model(:course => @course)
@submission = @assignment.submit_homework(@student, { :url => "http://www.instructure.com/" })
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @course.feed_code + 'x'
assigns[:problem].should match /The verification code is invalid/
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @course.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @course.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -759,4 +759,32 @@ describe GroupsController do
group2_assignments.map{ |u| u['user_id'] }.sort.should == student_ids.sort
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
group_with_user(:active_all => true)
@group.discussion_topics.create!(:title => "hi", :message => "intros", :user => @user)
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @group.feed_code + 'x'
assigns[:problem].should match /The verification code is invalid/
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @group.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @group.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end

View File

@ -411,4 +411,33 @@ describe UsersController do
end
end
describe "GET 'public_feed.atom'" do
before(:each) do
course_with_student(:active_all => true)
assignment_model(:course => @course)
@course.discussion_topics.create!(:title => "hi", :message => "blah", :user => @student)
wiki_page_model(:course => @course)
end
it "should require authorization" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code + 'x'
assigns[:problem].should match /The verification code is invalid/
end
it "should include absolute path for rel='self' link" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.links.first.rel.should match(/self/)
feed.links.first.href.should match(/http:\/\//)
end
it "should include an author for each entry" do
get 'public_feed', :format => 'atom', :feed_code => @user.feed_code
feed = Atom::Feed.load_feed(response.body) rescue nil
feed.should_not be_nil
feed.entries.should_not be_empty
feed.entries.all?{|e| e.authors.present?}.should be_true
end
end
end