specs for comment threads & comments & passed

This commit is contained in:
Rocky Duan 2012-07-16 11:04:35 -04:00
Родитель b8b278a128
Коммит 9203bad10b
6 изменённых файлов: 140 добавлений и 337 удалений

Просмотреть файл

@ -4,11 +4,7 @@ require 'bundler'
Bundler.setup
Bundler.require
require './models/comment.rb'
require './models/comment_thread.rb'
require './models/user.rb'
require './models/commentable.rb'
require './models/feed.rb'
Dir[File.dirname(__FILE__) + '/models/*.rb'].each {|file| require file}
desc "Load the environment"
task :environment do

16
app.rb
Просмотреть файл

@ -4,11 +4,7 @@ require 'bundler'
Bundler.setup
Bundler.require
require './models/comment'
require './models/comment_thread'
require './models/commentable'
require './models/user'
require './models/feed'
Dir[File.dirname(__FILE__) + '/models/*.rb'].each {|file| require file}
env_index = ARGV.index("-e")
env_arg = ARGV[env_index + 1] if env_index
@ -55,7 +51,7 @@ config = YAML.load_file("config/application.yml")
# delete the commentable object and all of its associated comment threads and comments
delete '/api/v1/commentables/:commentable_type/:commentable_id' do |commentable_type, commentable_id|
commentable = Commentable.find_or_create_by(commentable_type: commentable_type, commentable_id: commentable_id)
commentable = Commentable.find_or_initialize_by(commentable_type: commentable_type, commentable_id: commentable_id)
commentable.destroy
commentable.to_hash.to_json
end
@ -94,7 +90,8 @@ end
put '/api/v1/comment_threads/:comment_thread_id' do |comment_thread_id|
comment_thread = CommentThread.find(comment_thread_id)
comment_thread.update!(params.slice(*%w[title body endorsed])).to_hash.to_json
comment_thread.update_attributes!(params.slice(*%w[title body]))
comment_thread.to_hash.to_json
end
# POST /api/v1/comment_threads/:comment_thread_id/comments
@ -130,7 +127,8 @@ end
put '/api/v1/comments/:comment_id' do |comment_id|
comment = Comment.find(comment_id)
comment.update!(params.slice(*%w[body endorsed])).to_hash.to_json
comment.update_attributes!(params.slice(*%w[body endorsed]))
comment.to_hash.to_json
end
# POST /api/v1/comments/:comment_id
@ -138,7 +136,7 @@ end
post '/api/v1/comments/:comment_id' do |comment_id|
comment = Comment.find(comment_id)
sub_comment = comment.children.new(params.slice(*%w[body]))
sub_comment = comment.children.new(params.slice(*%w[body course_id]))
sub_comment.author = User.find_or_create_by(external_id: params["user_id"])
sub_comment.save!
sub_comment.to_hash.to_json

Просмотреть файл

@ -13,7 +13,7 @@ class Comment
belongs_to :author, class_name: "User", index: true
belongs_to :comment_thread, index: true
attr_accessible :body, :course_id
attr_accessible :body, :course_id, :endorsed
validates_presence_of :body
validates_presence_of :course_id # do we really need this?
@ -26,8 +26,12 @@ class Comment
nodes.map{|node, sub_nodes| node.to_hash.merge("children" => hash_tree(sub_nodes).compact)}
end
def comment_thread
comment_thread || root.comment_thread
def get_comment_thread
if comment_thread
comment_thread
else
root.comment_thread
end
end
def to_hash(params={})
@ -52,14 +56,14 @@ class Comment
feed = Feed.new(
feed_type: "post_reply",
info: {
comment_thread_id: comment_thread.id,
comment_thread_title: comment_thread.title,
comment_thread_id: get_comment_thread.id,
comment_thread_title: get_comment_thread.title,
comment_id: id,
},
)
feed.actor = author
feed.target = self
feed.subscribers << comment_thread.watchers
feed.subscribers << get_comment_thread.watchers
feed.subscribers << author.followers
feed.save!
end

Просмотреть файл

@ -37,10 +37,10 @@ class CommentThread
feed = Feed.new(
feed_type: "post_topic",
info: {
commentable_id: commentable.id,
commentable_type: commentable.type,
comment_thread_id: comment_thread.id,
comment_thread_title: comment_thread.title,
commentable_id: commentable.commentable_id,
commentable_type: commentable.commentable_type,
comment_thread_id: id,
comment_thread_title: title,
},
)
feed.actor = author

Просмотреть файл

@ -16,45 +16,49 @@ describe "app" do
User.delete_all
Feed.delete_all
commentable = Commentable.create!(commentable_type: "questions", commentable_id: "1")
commentable = Commentable.new(commentable_type: "questions", commentable_id: "1")
user = User.create!(external_id: "1")
comment_thread = commentable.comment_threads.create!(title: "I can't solve this problem", body: "can anyone help me?", course_id: "1")
commentable.watchers << user
commentable.save!
comment_thread = commentable.comment_threads.new(title: "I can't solve this problem", body: "can anyone help me?", course_id: "1")
comment_thread.author = user
comment_thread.watchers << user
comment_thread.save!
comment = comment_thread.comments.create!(body: "this problem is so easy", course_id: "1")
comment = comment_thread.comments.new(body: "this problem is so easy", course_id: "1")
comment.author = user
comment.save!
comment1 = comment.children.create!(body: "not for me!", course_id: "1")
comment1 = comment.children.new(body: "not for me!", course_id: "1")
comment1.author = user
comment1.save!
comment2 = comment1.children.create!(body: "not for me neither!", course_id: "1")
comment2 = comment1.children.new(body: "not for me neither!", course_id: "1")
comment2.author = user
comment2.save!
comment = comment_thread.comments.create!(body: "see the textbook on page 69. it's quite similar", course_id: "1")
comment = comment_thread.comments.new(body: "see the textbook on page 69. it's quite similar", course_id: "1")
comment.author = user
comment.save!
comment1 = comment.children.create!(body: "thank you!", course_id: "1")
comment1 = comment.children.new(body: "thank you!", course_id: "1")
comment1.author = user
comment1.save!
comment_thread = commentable.comment_threads.create!(title: "This problem is wrong", body: "it is unsolvable", course_id: "2")
comment_thread = commentable.comment_threads.new(title: "This problem is wrong", body: "it is unsolvable", course_id: "2")
comment_thread.author = user
comment_thread.save!
comment = comment_thread.comments.create!(body: "how do you know?", course_id: "1")
comment = comment_thread.comments.new(body: "how do you know?", course_id: "1")
comment.author = user
comment.save!
comment1 = comment.children.create!(body: "because blablabla", course_id: "1")
comment1 = comment.children.new(body: "because blablabla", course_id: "1")
comment1.author = user
comment1.save!
comment = comment_thread.comments.create!(body: "no wonder I can't solve it", course_id: "1")
comment = comment_thread.comments.new(body: "no wonder I can't solve it", course_id: "1")
comment.author = user
comment.save!
comment1 = comment.children.create!(body: "+1", course_id: "1")
comment1 = comment.children.new(body: "+1", course_id: "1")
comment1.author = user
comment1.save!
@ -91,7 +95,6 @@ describe "app" do
get "/api/v1/commentables/questions/1/comment_threads", recursive: true
last_response.should be_ok
comment_threads = Yajl::Parser.parse last_response.body
pp comment_threads
comment_threads.length.should == 2
comment_threads.index{|c| c["body"] == "can anyone help me?"}.should_not be_nil
comment_threads.index{|c| c["body"] == "it is unsolvable"}.should_not be_nil
@ -101,7 +104,6 @@ describe "app" do
children.index{|c| c["body"] == "this problem is so easy"}.should_not be_nil
children.index{|c| c["body"] =~ /^see the textbook/}.should_not be_nil
so_easy = children.select{|c| c["body"] == "this problem is so easy"}.first
pp so_easy
so_easy["children"].length.should == 1
not_for_me = so_easy["children"].first
not_for_me["body"].should == "not for me!"
@ -129,20 +131,112 @@ describe "app" do
comment_thread.title.should == response_thread["title"]
comment_thread.body.should == response_thread["body"]
comment_thread.course_id.should == response_thread["course_id"]
response_thread["children"].should be_nil
end
it "get information of a single comment thread with its comments" do
comment_thread = CommentThread.first
get "/api/v1/comment_threads/#{comment_thread.id}", recursive: true
last_response.should be_ok
response_thread = parse last_response.body
comment_thread.title.should == response_thread["title"]
comment_thread.body.should == response_thread["body"]
comment_thread.course_id.should == response_thread["course_id"]
response_thread["children"].should_not be_nil
response_thread["children"].length.should == comment_thread.comments.length
response_thread["children"].index{|c| c["body"] == comment_thread.comments.first.body}.should_not be_nil
end
end
describe "PUT /api/v1/comment_threads/:comment_thread_id" do
it "update information of comment thread" do
comment_thread = CommentThread.first
put "/api/v1/comment_threads/#{comment_thread.id}", body: "new body", title: "new title"
last_response.should be_ok
changed_thread = CommentThread.find(comment_thread.id)
changed_thread.body.should == "new body"
changed_thread.title.should == "new title"
end
end
# PUT /api/v1/comment_threads/:comment_thread_id
# POST /api/v1/comment_threads/:comment_thread_id/comments
# DELETE /api/v1/comment_threads/:comment_thread_id
#
describe "POST /api/v1/comment_threads/:comment_thread_id/comments" do
it "create a comment to the comment thread" do
comment_thread = CommentThread.first.to_hash(recursive: true)
user = User.first
post "/api/v1/comment_threads/#{comment_thread["_id"]}/comments", body: "new comment", course_id: "1", user_id: User.first.external_id
last_response.should be_ok
changed_thread = CommentThread.find(comment_thread["_id"]).to_hash(recursive: true)
changed_thread["children"].length.should == comment_thread["children"].length + 1
comment = changed_thread["children"].select{|c| c["body"] == "new comment"}.first
comment.should_not be_nil
comment["user_id"].should == user.external_id
end
end
describe "DELETE /api/v1/comment_threads/:comment_thread_id" do
it "delete the comment thread and its comments" do
comment_thread = CommentThread.first.to_hash
delete "/api/v1/comment_threads/#{comment_thread['_id']}"
last_response.should be_ok
CommentThread.where(title: comment_thread["title"]).first.should be_nil
end
end
end
describe "comments" do
# GET /api/v1/comments/:comment_id
# PUT /api/v1/comments/:comment_id
# POST /api/v1/comments/:comment_id
# DELETE /api/v1/comments/:comment_id
#
describe "GET /api/v1/comments/:comment_id" do
it "retrieve information of a single comment" do
comment = Comment.first
get "/api/v1/comments/#{comment.id}"
last_response.should be_ok
retrieved = parse last_response.body
retrieved["body"].should == comment.body
retrieved["endorsed"].should == comment.endorsed
retrieved["_id"].should == comment.id.to_s
retrieved["children"].should be_nil
end
it "retrieve information of a single comment with its sub comments" do
comment = Comment.first
get "/api/v1/comments/#{comment.id}", recursive: true
last_response.should be_ok
retrieved = parse last_response.body
retrieved["body"].should == comment.body
retrieved["endorsed"].should == comment.endorsed
retrieved["_id"].should == comment.id.to_s
retrieved["children"].length.should == comment.children.length
retrieved["children"].select{|c| c["body"] == comment.children.first.body}.first.should_not be_nil
end
end
describe "PUT /api/v1/comments/:comment_id" do
it "update information of the comment" do
comment = Comment.first
put "/api/v1/comments/#{comment.id}", body: "new body", endorsed: true
last_response.should be_ok
new_comment = Comment.find(comment.id)
new_comment.body.should == "new body"
new_comment.endorsed.should == true
end
end
describe "POST /api/v1/comments/:comment_id" do
it "create a sub comment to the comment" do
comment = Comment.first.to_hash(recursive: true)
user = User.first
post "/api/v1/comments/#{comment["_id"]}", body: "new comment", course_id: "1", user_id: User.first.external_id
last_response.should be_ok
changed_comment = Comment.find(comment["_id"]).to_hash(recursive: true)
changed_comment["children"].length.should == comment["children"].length + 1
subcomment = changed_comment["children"].select{|c| c["body"] == "new comment"}.first
subcomment.should_not be_nil
subcomment["user_id"].should == user.external_id
end
end
describe "DELETE /api/v1/comments/:comment_id" do
it "delete the comment and its sub comments" do
comment = Comment.first
cnt_comments = comment.descendants_and_self.length
prev_count = Comment.count
delete "/api/v1/comments/#{comment.id}"
Comment.count.should == prev_count - cnt_comments
Comment.all.select{|c| c.id == comment.id}.first.should be_nil
end
end
end
describe "votes" do
@ -163,295 +257,4 @@ describe "app" do
# POST /api/v1/users/:user_id/watch/comment_thread
# POST /api/v1/users/:user_id/unwatch/comment_thread
end
=begin
describe "POST on /api/v1/commentables/:commentable_type/:commentable_id/comment_threads" do
it "should create a top-level comment with correct body, title, user_id, and course_id" do
post "/api/v1/commentables/questions/1/comments", :body => "comment body", :title => "comment title", :user_id => 1, :course_id => 1
last_response.should be_ok
comment = CommentThread.first.root_comments.first
comment.should_not be_nil
comment.body.should == "comment body"
comment.title.should == "comment title"
comment.user_id.should == 1
comment.user_id.should == 1
end
it "should create a top-level comment with only title" do
post "/api/v1/commentables/questions/1/comments", :body => "", :title => "comment title", :user_id => 1, :course_id => 1
last_response.should be_ok
comment = CommentThread.first.root_comments.first
comment.should_not be_nil
comment.body.should == ""
comment.title.should == "comment title"
comment.user_id.should == 1
comment.user_id.should == 1
end
it "should create a top-level comment with only body" do
post "/api/v1/commentables/questions/1/comments", :body => "comment body", :title => "", :user_id => 1, :course_id => 1
last_response.should be_ok
comment = CommentThread.first.root_comments.first
comment.should_not be_nil
comment.body.should == "comment body"
comment.title.should == ""
comment.user_id.should == 1
comment.user_id.should == 1
end
it "should not create a top-level comment with neither title nor body" do
post "/api/v1/commentables/questions/1/comments", :body => "", :title => "", :user_id => 1, :course_id => 1
last_response.status.should == 400
end
end
describe "POST on /api/v1/comments/:comment_id" do
before :each do
CommentThread.create! :commentable_type => "questions", :commentable_id => 1
CommentThread.first.root_comments.create :body => "top comment", :title => "top", :user_id => 1, :course_id => 1, :comment_thread_id => CommentThread.first.id
end
it "should create a sub comment with correct body, title, user_id, and course_id" do
post "/api/v1/comments/#{CommentThread.first.root_comments.first.id}",
:body => "comment body", :title => "comment title", :user_id => 1, :course_id => 1
last_response.should be_ok
comment = CommentThread.first.root_comments.first.children.first
comment.should_not be_nil
comment.body.should == "comment body"
comment.title.should == "comment title"
comment.user_id.should == 1
comment.user_id.should == 1
end
it "should not create a sub comment for the super comment" do
post "/api/v1/comments/#{CommentThread.first.super_comment.id}",
:body => "comment body", :title => "comment title", :user_id => 1, :course_id => 1
last_response.status.should == 400
end
end
describe "GET on /api/v1/commentables/:commentable_type/:commentable_id/comments" do
it "should create a corresponding comment thread with a super comment" do
get "/api/v1/commentables/questions/1/comments"
last_response.should be_ok
comment_thread = CommentThread.first
comment_thread.should_not be_nil
comment_thread.super_comment.should_not be_nil
end
it "should create a corresponding comment thread with correct type and id" do
get "/api/v1/commentables/questions/1/comments"
last_response.should be_ok
comment_thread = CommentThread.first
comment_thread.commentable_type.should == 'questions'
comment_thread.commentable_id.should == '1'
end
it "returns an empty array when there are no comments" do
get "/api/v1/commentables/questions/1/comments"
last_response.should be_ok
comments = Yajl::Parser.parse last_response.body
comments.length.should == 0
end
it "retrieves all comments with their votes in a nested structure in json format" do
comment_thread = CommentThread.create! :commentable_type => "questions", :commentable_id => 1
comment = []
sub_comment = []
comment << (comment_thread.root_comments.create :body => "top comment", :title => "top 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
sub_comment << (comment[0].children.create :body => "comment body", :title => "comment title 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
sub_comment << (comment[0].children.create :body => "comment body", :title => "comment title 1", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
(1..4).each do |id|
user = User.find_or_create_by_id(id)
user.vote_for(comment[0])
end
(5..7).each do |id|
user = User.find_or_create_by_id(id)
user.vote_against(comment[0])
end
get "/api/v1/commentables/questions/1/comments"
last_response.should be_ok
comments = Yajl::Parser.parse last_response.body
comments.length.should == 1
c = comments[0]
c["title"].should == "top 0"
c["id"].should == comment[0].id
c["votes"]["up"].should == 4
c["votes"]["down"].should == 3
c["votes"]["plusminus"].should == 1
c["comment_thread_id"].should == comment_thread.id
c["created_at"].should_not be_nil
c["updated_at"].should_not be_nil
c["children"].length.should == 2
children = c["children"].reject{|comment| comment["title"] != "comment title 0"}.first
children.should_not be_nil
children["id"].should == sub_comment[0].id
children["created_at"].should_not be_nil
children["updated_at"].should_not be_nil
end
end
describe "GET on /api/v1/comments/:comment_id" do
it "returns information for a single comment" do
comment_thread = CommentThread.create! :commentable_type => "questions", :commentable_id => 1
comment = []
sub_comment = []
comment << (comment_thread.root_comments.create :body => "top comment", :title => "top 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
sub_comment << (comment[0].children.create :body => "comment body", :title => "comment title 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
sub_comment << (comment[0].children.create :body => "comment body", :title => "comment title 1", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
get "/api/v1/comments/#{comment[0].id}"
last_response.should be_ok
c = Yajl::Parser.parse last_response.body
c["title"].should == "top 0"
c["body"].should == "top comment"
c["user_id"].should == 1
c["course_id"].should == 1
c["comment_thread_id"].should == comment_thread.id
c["created_at"].should_not be_nil
c["updated_at"].should_not be_nil
c["votes"]["up"].should == 0
c["votes"]["down"].should == 0
c["votes"]["plusminus"].should == 0
c["children"].length.should == 0
end
end
describe "DELETE on /api/v1/commentables/:commentable_type/:commentable_id" do
before :each do
comment_thread = CommentThread.create! :commentable_type => "questions", :commentable_id => 1
comment = []
sub_comment = []
comment << (comment_thread.root_comments.create :body => "top comment", :title => "top 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
sub_comment << (comment[0].children.create :body => "comment body", :title => "comment title 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
comment << (comment_thread.root_comments.create :body => "top comment", :title => "top 1", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
sub_comment << (comment[1].children.create :body => "comment body", :title => "comment title 1", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id)
end
it "should return error when called on a nonexisted thread" do
delete "/api/v1/commentables/i_do_not_exist/1"
last_response.status.should == 400
end
it "deletes all comments associated with a thread when called on the thread" do
delete "/api/v1/commentables/questions/1"
last_response.should be_ok
CommentThread.count.should == 0
Comment.count.should == 0
end
it "deletes the comment and all sub comments when called on the comment" do
comment_thread = CommentThread.first
comment = comment_thread.root_comments.first
delete "/api/v1/comments/#{comment.id}"
last_response.should be_ok
comment_thread.root_comments.count.should == 1
comment_thread.comments.count.should == 2
comment_thread.root_comments.first.title.should == "top 1"
comment_thread.root_comments.first.children.first.title.should == "comment title 1"
end
it "should not delete the super comment" do
comment_thread = CommentThread.first
comment = comment_thread.super_comment
delete "/api/v1/comments/#{comment.id}"
last_response.status.should == 400
end
end
describe "PUT on /api/v1/comments/comment_id" do
before :each do
comment_thread = CommentThread.create! :commentable_type => "questions", :commentable_id => 1
comment_thread.root_comments.create :body => "top comment", :title => "top 0", :user_id => 1, :course_id => 1, :comment_thread_id => comment_thread.id
end
it "should update body and title" do
comment = CommentThread.first.comments.first
put "/api/v1/comments/#{comment.id}", :body => "new body", :title => "new title"
last_response.should be_ok
comment = CommentThread.first.comments.first
comment.body.should == "new body"
comment.title.should == "new title"
end
it "should update endorsement status" do
comment = CommentThread.first.comments.first
put "/api/v1/comments/#{comment.id}", :endorsed => true
comment = CommentThread.first.comments.first
comment.endorsed.should be_true
put "/api/v1/comments/#{comment.id}", :endorsed => false
comment = CommentThread.first.comments.first
comment.endorsed.should be_false
end
it "should not update the super comment" do
comment = CommentThread.first.super_comment
put "/api/v1/comments/#{comment.id}", :body => "new body", :title => "new title"
last_response.status.should == 400
end
it "should not update user_id nor course_id" do
comment = CommentThread.first.comments.first
put "/api/v1/comments/#{comment.id}", :user_id => 100, :course_id => 100
last_response.should be_ok
comment = CommentThread.first.comments.first
comment.user_id.should == 1
comment.course_id.should == 1
end
end
end
describe "votings" do
before :each do
CommentThread.delete_all
Comment.delete_all
Vote.delete_all
end
describe "PUT on /api/v1/votes/comments/:comment_id/users/:user_id" do
before :each do
comment_thread = CommentThread.create! :commentable_type => "questions", :commentable_id => 1
comment = CommentThread.first.root_comments.create :body => "top comment", :title => "top", :user_id => 1, :course_id => 1
comment.comment_thread = comment_thread
comment.save!
Vote.delete_all
end
it "votes up on a comment" do
comment = CommentThread.first.comments.first
put "/api/v1/votes/comments/#{comment.id}/users/1", :value => "up"
last_response.should be_ok
vote = Vote.first
vote.should_not be_nil
vote.voter_id.should == 1
vote.voteable_id.should == comment.id
vote.vote.should be_true
end
it "votes down on a comment" do
comment = CommentThread.first.comments.first
put "/api/v1/votes/comments/#{comment.id}/users/1", :value => "down"
last_response.should be_ok
vote = Vote.first
vote.should_not be_nil
vote.voter_id.should == 1
vote.voteable_id.should == comment.id
vote.vote.should be_false
end
it "rejects invalid vote value" do
comment = CommentThread.first.comments.first
put "/api/v1/votes/comments/#{comment.id}/users/1", :value => "up_or_down"
last_response.status.should == 400
end
it "rejects nonexisted comment id" do
comment = CommentThread.first.comments.first
put "/api/v1/votes/comments/#{comment.id ** 2}/users/1", :value => "up"
last_response.status.should == 400
end
it "change vote on comment" do
comment = CommentThread.first.comments.first
user = User.find_or_create_by_id(1)
user.vote_for(comment)
put "/api/v1/votes/comments/#{comment.id}/users/1", :value => "down"
last_response.should be_ok
Vote.first.vote.should be_false
end
end
describe "DELETE on /api/v1/votes/comments/:comment_id/users/:user_id" do
before :each do
CommentThread.create! :commentable_type => "questions", :commentable_id => 1
CommentThread.first.root_comments.create :body => "top comment", :title => "top", :user_id => 1, :course_id => 1, :comment_thread_id => CommentThread.first.id
end
it "deletes vote" do
comment = CommentThread.first.comments.first
user = User.find_or_create_by_id(1)
user.vote_for(comment)
delete "/api/v1/votes/comments/#{comment.id}/users/1"
last_response.should be_ok
Vote.count.should == 0
end
it "does nothing for nonexisted vote" do
comment = CommentThread.first.comments.first
delete "/api/v1/votes/comments/#{comment.id}/users/1"
last_response.should be_ok
end
end
=end
end

Просмотреть файл

@ -10,6 +10,8 @@ set :run, false
set :raise_errors, true
set :logging, false
Delayed::Worker.delay_jobs = false
def app
Sinatra::Application
end