Commit bd47a000 by Clinton Blackburn

Merge pull request #179 from edx/clintonb/spec-cleanup

Updated specs
parents d5a1919e 0ec1250d
...@@ -18,12 +18,12 @@ describe "app" do ...@@ -18,12 +18,12 @@ describe "app" do
context "when filtering by course" do context "when filtering by course" do
it "returns only threads with matching course id" do it "returns only threads with matching course id" do
[@threads["t1"], @threads["t2"]].each do |t| [@threads["t1"], @threads["t2"]].each do |t|
t.course_id = "abc" t.course_id = "abc"
t.save! t.save!
end end
rs = thread_result course_id: "abc", sort_order: "asc" rs = thread_result course_id: "abc", sort_order: "asc"
rs.length.should == 2 rs.length.should == 2
rs.each_with_index { |res, i| rs.each_with_index { |res, i|
check_thread_result_json(nil, @threads["t#{i+1}"], res) check_thread_result_json(nil, @threads["t#{i+1}"], res)
res["course_id"].should == "abc" res["course_id"].should == "abc"
...@@ -89,7 +89,7 @@ describe "app" do ...@@ -89,7 +89,7 @@ describe "app" do
@threads["t3"].group_id = 100 @threads["t3"].group_id = 100
@threads["t3"].save! @threads["t3"].save!
rs = thread_result course_id: "omg", group_id: 100, sort_order: "asc" rs = thread_result course_id: "omg", group_id: 100, sort_order: "asc"
rs.length.should == 2 rs.length.should == 2
rs.each_with_index { |res, i| rs.each_with_index { |res, i|
check_thread_result_json(nil, @threads["t#{i+1}"], res) check_thread_result_json(nil, @threads["t#{i+1}"], res)
res["course_id"].should == "omg" res["course_id"].should == "omg"
...@@ -97,32 +97,32 @@ describe "app" do ...@@ -97,32 +97,32 @@ describe "app" do
end end
it "returns an empty result when no threads match course_id" do it "returns an empty result when no threads match course_id" do
rs = thread_result course_id: 99 rs = thread_result course_id: 99
rs.length.should == 0 rs.length.should == 0
end end
it "returns only group-less threads when no threads have matching group id" do it "returns only group-less threads when no threads have matching group id" do
@threads["t1"].group_id = 123 @threads["t1"].group_id = 123
@threads["t1"].save! @threads["t1"].save!
rs = thread_result course_id: DFLT_COURSE_ID, group_id: 321 rs = thread_result course_id: DFLT_COURSE_ID, group_id: 321
rs.each.map {|res| res["group_id"].should be_nil } rs.each.map { |res| res["group_id"].should be_nil }
end end
context "when filtering flagged posts" do context "when filtering flagged posts" do
it "returns threads that are flagged" do it "returns threads that are flagged" do
@threads["t1"].abuse_flaggers = [1] @threads["t1"].abuse_flaggers = [1]
@threads["t1"].save! @threads["t1"].save!
rs = thread_result course_id: DFLT_COURSE_ID, flagged: true rs = thread_result course_id: DFLT_COURSE_ID, flagged: true
rs.length.should == 1 rs.length.should == 1
check_thread_result_json(nil, @threads["t1"], rs.first) check_thread_result_json(nil, @threads["t1"], rs.first)
end end
it "returns threads that have flagged comments" do it "returns threads that have flagged comments" do
@comments["t2 c3"].abuse_flaggers = [1] @comments["t2 c3"].abuse_flaggers = [1]
@comments["t2 c3"].save! @comments["t2 c3"].save!
rs = thread_result course_id: DFLT_COURSE_ID, flagged: true rs = thread_result course_id: DFLT_COURSE_ID, flagged: true
rs.length.should == 1 rs.length.should == 1
check_thread_result_json(nil, @threads["t2"], rs.first) check_thread_result_json(nil, @threads["t2"], rs.first)
end end
it "returns an empty result when no posts were flagged" do it "returns an empty result when no posts were flagged" do
rs = thread_result course_id: DFLT_COURSE_ID, flagged: true rs = thread_result course_id: DFLT_COURSE_ID, flagged: true
rs.length.should == 0 rs.length.should == 0
end end
end end
it "filters unread posts" do it "filters unread posts" do
...@@ -180,12 +180,12 @@ describe "app" do ...@@ -180,12 +180,12 @@ describe "app" do
end end
it "correctly considers read state" do it "correctly considers read state" do
user = create_test_user(123) user = create_test_user(123)
[@threads["t1"], @threads["t2"]].each do |t| [@threads["t1"], @threads["t2"]].each do |t|
t.course_id = "abc" t.course_id = "abc"
t.save! t.save!
end end
rs = thread_result course_id: "abc", user_id: "123", sort_order: "asc" rs = thread_result course_id: "abc", user_id: "123", sort_order: "asc"
rs.length.should == 2 rs.length.should == 2
rs.each_with_index { |result, i| rs.each_with_index { |result, i|
check_thread_result_json(user, @threads["t#{i+1}"], result) check_thread_result_json(user, @threads["t#{i+1}"], result)
result["course_id"].should == "abc" result["course_id"].should == "abc"
...@@ -230,20 +230,20 @@ describe "app" do ...@@ -230,20 +230,20 @@ describe "app" do
context "sorting" do context "sorting" do
def thread_result_order (sort_key, sort_order) def thread_result_order (sort_key, sort_order)
results = thread_result course_id: DFLT_COURSE_ID, sort_key: sort_key, sort_order: sort_order results = thread_result course_id: DFLT_COURSE_ID, sort_key: sort_key, sort_order: sort_order
results.length.should == 10 results.length.should == 10
results.map {|t| t["title"]} results.map { |t| t["title"] }
end end
def move_to_end(ary, *vals) def move_to_end(ary, *vals)
vals.each do |val| vals.each do |val|
ary = ary.select {|v| v!=val } << val ary = ary.select { |v| v!=val } << val
end end
ary ary
end end
def move_to_front(ary, *vals) def move_to_front(ary, *vals)
vals.reverse.each do |val| vals.reverse.each do |val|
ary = ary.select {|v| v!=val }.insert(0, val) ary = ary.select { |v| v!=val }.insert(0, val)
end end
ary ary
end end
...@@ -263,7 +263,7 @@ describe "app" do ...@@ -263,7 +263,7 @@ describe "app" do
t5c.update(body: "changed!") t5c.update(body: "changed!")
t5c.save! t5c.save!
actual_order = thread_result_order("activity", "desc") actual_order = thread_result_order("activity", "desc")
expected_order = move_to_front(@default_order, "t5") expected_order = move_to_front(@default_order, "t5")
actual_order.should == expected_order actual_order.should == expected_order
end end
it "sorts using last activity / ascending" do it "sorts using last activity / ascending" do
...@@ -271,7 +271,7 @@ describe "app" do ...@@ -271,7 +271,7 @@ describe "app" do
t5c.update(body: "changed!") t5c.update(body: "changed!")
t5c.save! t5c.save!
actual_order = thread_result_order("activity", "asc") actual_order = thread_result_order("activity", "asc")
expected_order = move_to_end(@default_order.reverse, "t5") expected_order = move_to_end(@default_order.reverse, "t5")
actual_order.should == expected_order actual_order.should == expected_order
end end
it "sorts using vote count / descending" do it "sorts using vote count / descending" do
...@@ -280,7 +280,7 @@ describe "app" do ...@@ -280,7 +280,7 @@ describe "app" do
user.vote(t5, :up) user.vote(t5, :up)
t5.save! t5.save!
actual_order = thread_result_order("votes", "desc") actual_order = thread_result_order("votes", "desc")
expected_order = move_to_front(@default_order, "t5") expected_order = move_to_front(@default_order, "t5")
actual_order.should == expected_order actual_order.should == expected_order
end end
it "sorts using vote count / ascending" do it "sorts using vote count / ascending" do
...@@ -289,19 +289,19 @@ describe "app" do ...@@ -289,19 +289,19 @@ describe "app" do
user.vote(t5, :up) user.vote(t5, :up)
t5.save! t5.save!
actual_order = thread_result_order("votes", "asc") actual_order = thread_result_order("votes", "asc")
expected_order = move_to_end(@default_order, "t5") expected_order = move_to_end(@default_order, "t5")
actual_order.should == expected_order actual_order.should == expected_order
end end
it "sorts using comment count / descending" do it "sorts using comment count / descending" do
make_comment(@threads["t5"].author, @threads["t5"], "extra comment") make_comment(@threads["t5"].author, @threads["t5"], "extra comment")
actual_order = thread_result_order("comments", "desc") actual_order = thread_result_order("comments", "desc")
expected_order = move_to_front(@default_order, "t5") expected_order = move_to_front(@default_order, "t5")
actual_order.should == expected_order actual_order.should == expected_order
end end
it "sorts using comment count / ascending" do it "sorts using comment count / ascending" do
make_comment(@threads["t5"].author, @threads["t5"], "extra comment") make_comment(@threads["t5"].author, @threads["t5"], "extra comment")
actual_order = thread_result_order("comments", "asc") actual_order = thread_result_order("comments", "asc")
expected_order = move_to_end(@default_order, "t5") expected_order = move_to_end(@default_order, "t5")
actual_order.should == expected_order actual_order.should == expected_order
end end
it "sorts pinned items first" do it "sorts pinned items first" do
...@@ -332,7 +332,7 @@ describe "app" do ...@@ -332,7 +332,7 @@ describe "app" do
expected_order = move_to_front(@default_order.reverse, "t7", "t8") expected_order = move_to_front(@default_order.reverse, "t7", "t8")
actual_order.should == expected_order actual_order.should == expected_order
end end
context "pagination" do context "pagination" do
def thread_result_page (sort_key, sort_order, page, per_page, user_id=nil, unread=false) def thread_result_page (sort_key, sort_order, page, per_page, user_id=nil, unread=false)
get "/api/v1/threads", course_id: DFLT_COURSE_ID, sort_key: sort_key, sort_order: sort_order, page: page, per_page: per_page, user_id: user_id, unread: unread get "/api/v1/threads", course_id: DFLT_COURSE_ID, sort_key: sort_key, sort_order: sort_order, page: page, per_page: per_page, user_id: user_id, unread: unread
...@@ -368,12 +368,12 @@ describe "app" do ...@@ -368,12 +368,12 @@ describe "app" do
num_pages.times do |i| num_pages.times do |i|
page = i + 1 page = i + 1
result = thread_result_page( result = thread_result_page(
sort_spec['sort_key'], sort_spec['sort_key'],
sort_spec['sort_dir'], sort_spec['sort_dir'],
page, page,
per_page, per_page,
user_id, user_id,
filter_spec.include?("unread") filter_spec.include?("unread")
) )
result["collection"].length.should == (page * per_page <= expected_order.length ? per_page : expected_order.length % per_page) result["collection"].length.should == (page * per_page <= expected_order.length ? per_page : expected_order.length % per_page)
if filter_spec.include?("unread") if filter_spec.include?("unread")
...@@ -383,7 +383,7 @@ describe "app" do ...@@ -383,7 +383,7 @@ describe "app" do
result["num_pages"].should == num_pages result["num_pages"].should == num_pages
end end
result["page"].should == page result["page"].should == page
actual_order += result["collection"].map {|v| v["title"]} actual_order += result["collection"].map { |v| v["title"] }
end end
actual_order.should == expected_order actual_order.should == expected_order
end end
...@@ -393,7 +393,7 @@ describe "app" do ...@@ -393,7 +393,7 @@ describe "app" do
@threads["t7"].pinned = true @threads["t7"].pinned = true
@threads["t7"].save! @threads["t7"].save!
expected_order = move_to_front(move_to_end(@default_order, "t5"), "t7") expected_order = move_to_front(move_to_end(@default_order, "t5"), "t7")
test_paged_order({'sort_key'=>'comments', 'sort_dir'=>'asc', 'per_page'=>3}, expected_order) test_paged_order({'sort_key' => 'comments', 'sort_dir' => 'asc', 'per_page' => 3}, expected_order)
end end
it "orders correctly acrosss pages with unread filter" do it "orders correctly acrosss pages with unread filter" do
...@@ -405,21 +405,21 @@ describe "app" do ...@@ -405,21 +405,21 @@ describe "app" do
@threads["t7"].save! @threads["t7"].save!
expected_order = move_to_front(move_to_end(@default_order[1..8], "t5"), "t7") expected_order = move_to_front(move_to_end(@default_order[1..8], "t5"), "t7")
test_paged_order( test_paged_order(
{'sort_key'=>'comments', 'sort_dir'=>'asc', 'per_page'=>3}, {'sort_key' => 'comments', 'sort_dir' => 'asc', 'per_page' => 3},
expected_order, expected_order,
["unread"], ["unread"],
user.id user.id
) )
end end
end end
end end
end end
def test_unicode_data(text) def test_unicode_data(text)
course_id = "unicode_course" course_id = 'unicode_course'
thread = make_thread(User.first, text, course_id, "unicode_commentable") thread = create(:comment_thread, body: text, course_id: course_id)
make_comment(User.first, thread, text) create(:comment, comment_thread: thread, body: text)
result = thread_result(course_id: course_id).first result = thread_result(course_id: course_id).first
check_thread_result_json(nil, thread, result) check_thread_result_json(nil, thread, result)
end end
...@@ -427,107 +427,118 @@ describe "app" do ...@@ -427,107 +427,118 @@ describe "app" do
include_examples "unicode data" include_examples "unicode data"
end end
describe "GET /api/v1/threads/:thread_id" do describe 'GET /api/v1/threads/:thread_id' do
let(:thread) do
comment = create(:comment)
comment.comment_thread
end
before(:each) { init_without_subscriptions } subject do
it "returns JSON" do
thread = CommentThread.first
get "/api/v1/threads/#{thread.id}" get "/api/v1/threads/#{thread.id}"
last_response.should be_ok
last_response.content_type.should == "application/json;charset=utf-8"
end end
it "get information of a single comment thread" do it { should be_ok }
thread = CommentThread.first
get "/api/v1/threads/#{thread.id}" it 'returns JSON' do
last_response.should be_ok expect(subject.content_type).to eq 'application/json;charset=utf-8'
response_thread = parse last_response.body
check_thread_result_json(nil, thread, response_thread)
end end
it "computes endorsed correctly" do it 'get information of a single comment thread' do
thread = CommentThread.first check_thread_result_json(nil, thread, parse(subject.body))
comment = thread.root_comments[1] end
it 'computes endorsed correctly' do
comment = thread.root_comments[0]
comment.endorsed = true comment.endorsed = true
comment.save! comment.save!
get "/api/v1/threads/#{thread.id}"
last_response.should be_ok expect(subject).to be_ok
response_thread = parse last_response.body parsed = parse(subject.body)
response_thread["endorsed"].should == true expect(parsed).to include('endorsed' => true)
# re-request the thread from the database before checking it. thread.reload
thread = CommentThread.find(thread.id) check_thread_result_json(nil, thread, parsed)
check_thread_result_json(nil, thread, response_thread)
end end
# This is a test to ensure that the username is included even if the context 'when marking as read' do
# thread's author is the one looking at the comment. This is because of a subject do
# regression in which we used User.only(:id, :read_states). This worked get "/api/v1/threads/#{thread.id}", {:user_id => thread.author.id, :mark_as_read => true}
# before we included the identity map, but afterwards, the user was end
# missing the username and was not refetched.
# BBEGGS - Note 8/4/2015: Identify map has been removed during the mongoid 4.x upgrade. it { should be_ok }
# Should no longer be an issue.
it "includes the username even if the thread is being marked as read for the thread author" do # This is a test to ensure that the username is included even if the
thread = CommentThread.first # thread's author is the one looking at the comment. This is because of a
expected_username = thread.author.username # regression in which we used User.only(:id, :read_states). This worked
get "/api/v1/threads/#{thread.id}", {:user_id => thread.author_id, :mark_as_read => true} # before we included the identity map, but afterwards, the user was
last_response.should be_ok # missing the username and was not refetched.
response_thread = parse last_response.body # BBEGGS - Note 8/4/2015: Identify map has been removed during the mongoid 4.x upgrade.
response_thread["username"].should == expected_username # Should no longer be an issue.
it 'includes the username even if the thread is being marked as read for the thread author' do
expect(parse(subject.body)).to include('username' => thread.author.username)
end
end end
it "get information of a single comment thread with its comments" do context 'with comments' do
thread = CommentThread.first subject do
get "/api/v1/threads/#{thread.id}", recursive: true get "/api/v1/threads/#{thread.id}", recursive: true
last_response.should be_ok end
check_thread_result_json(nil, thread, parse(last_response.body))
check_thread_response_paging_json(thread, parse(last_response.body)) it { should be_ok }
it 'get information of a single comment thread with its comments' do
parsed = parse(subject.body)
check_thread_result_json(nil, thread, parsed)
check_thread_response_paging_json(thread, parsed)
end
end end
it "returns 404 when the thread does not exist" do it 'returns 404 when the thread does not exist' do
thread = CommentThread.first
path = "/api/v1/threads/#{thread.id}"
get path
last_response.should be_ok
thread.destroy thread.destroy
get path expect(subject.status).to eq 404
last_response.status.should == 404 expect(parse(last_response.body).first).to eq I18n.t(:requested_object_not_found)
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
end end
it "marks thread as read and confirms its value on returned response" do context 'with user specified' do
user = create_test_user(123) let(:user) { create(:user) }
thread = CommentThread.first
user.mark_as_read(thread) subject do
get "/api/v1/threads/#{thread.id}", user_id: user.id user.mark_as_read(thread)
last_response.should be_ok get "/api/v1/threads/#{thread.id}", user_id: user.id
json_response = parse(last_response.body) last_response
changed_thread = CommentThread.find(thread.id) end
check_thread_result_json(user, changed_thread, json_response)
json_response["read"].should == true it { should be_ok }
it 'marks thread as read and confirms its value on returned response' do
parsed = parse(subject.body)
thread.reload
check_thread_result_json(user, thread, parsed)
expect(parsed).to include('read' => true)
end
end end
def test_unicode_data(text) def test_unicode_data(text)
thread = make_thread(User.first, text, "unicode_course", "unicode_commentable") thread = create(:comment_thread, body: text)
make_comment(User.first, thread, text) create(:comment, comment_thread: thread, body: text)
get "/api/v1/threads/#{thread.id}", recursive: true get "/api/v1/threads/#{thread.id}", recursive: true
last_response.should be_ok expect(last_response).to be_ok
result = parse last_response.body
check_thread_result_json(nil, thread, result) parsed = parse(last_response.body)
check_thread_response_paging_json(thread, result) check_thread_result_json(nil, thread, parsed)
check_thread_response_paging_json(thread, parsed)
end end
include_examples "unicode data" include_examples 'unicode data'
context "response pagination" do context "response pagination" do
before(:each) do before(:each) do
User.all.delete User.all.delete
Content.all.delete Content.all.delete
@user = create_test_user(999) @user = create_test_user(999)
@threads = {} @threads = {}
@comments = {} @comments = {}
[20,10,3,2,1,0].each do |n| [20, 10, 3, 2, 1, 0].each do |n|
thread_key = "t#{n}" thread_key = "t#{n}"
thread = make_thread(@user, thread_key, DFLT_COURSE_ID, "pdq") thread = make_thread(@user, thread_key, DFLT_COURSE_ID, "pdq")
@threads[n] = thread @threads[n] = thread
...@@ -554,28 +565,28 @@ describe "app" do ...@@ -554,28 +565,28 @@ describe "app" do
@threads.each do |n, thread| @threads.each do |n, thread|
res = thread_result thread.id, {} res = thread_result thread.id, {}
check_thread_response_paging_json thread, res, 0, nil, false check_thread_response_paging_json thread, res, 0, nil, false
end end
end end
it "skips the specified number of responses" do it "skips the specified number of responses" do
@threads.each do |n, thread| @threads.each do |n, thread|
res = thread_result thread.id, {:resp_skip => 1} res = thread_result thread.id, {:resp_skip => 1}
check_thread_response_paging_json thread, res, 1, nil, false check_thread_response_paging_json thread, res, 1, nil, false
end end
end end
it "limits the specified number of responses" do it "limits the specified number of responses" do
@threads.each do |n, thread| @threads.each do |n, thread|
res = thread_result thread.id, {:resp_limit => 2} res = thread_result thread.id, {:resp_limit => 2}
check_thread_response_paging_json thread, res, 0, 2, false check_thread_response_paging_json thread, res, 0, 2, false
end end
end end
it "skips and limits responses" do it "skips and limits responses" do
@threads.each do |n, thread| @threads.each do |n, thread|
res = thread_result thread.id, {:resp_skip => 3, :resp_limit => 5} res = thread_result thread.id, {:resp_skip => 3, :resp_limit => 5}
check_thread_response_paging_json thread, res, 3, 5, false check_thread_response_paging_json thread, res, 3, 5, false
end end
end end
end end
...@@ -584,7 +595,7 @@ describe "app" do ...@@ -584,7 +595,7 @@ describe "app" do
describe "PUT /api/v1/threads/:thread_id" do describe "PUT /api/v1/threads/:thread_id" do
before(:each) { init_without_subscriptions } before(:each) { init_without_subscriptions }
it "update information of comment thread and don't mark thread as read" do it "update information of comment thread and don't mark thread as read" do
thread = CommentThread.first thread = CommentThread.first
comment = thread.comments.first comment = thread.comments.first
...@@ -665,7 +676,7 @@ describe "app" do ...@@ -665,7 +676,7 @@ describe "app" do
before(:each) { init_without_subscriptions } before(:each) { init_without_subscriptions }
let :default_params do let :default_params do
{body: "new comment", course_id: "1", user_id: User.first.id} {body: "new comment", course_id: "1", user_id: User.first.id}
end end
it "create a comment to the comment thread" do it "create a comment to the comment thread" do
...@@ -676,7 +687,7 @@ describe "app" do ...@@ -676,7 +687,7 @@ describe "app" do
last_response.should be_ok last_response.should be_ok
changed_thread = CommentThread.find(thread.id) changed_thread = CommentThread.find(thread.id)
changed_thread.comment_count.should == orig_count + 1 changed_thread.comment_count.should == orig_count + 1
comment = changed_thread.comments.select{|c| c["body"] == "new comment"}.first comment = changed_thread.comments.select { |c| c["body"] == "new comment" }.first
comment.should_not be_nil comment.should_not be_nil
comment.author_id.should == user.id comment.author_id.should == user.id
end end
...@@ -688,7 +699,7 @@ describe "app" do ...@@ -688,7 +699,7 @@ describe "app" do
last_response.should be_ok last_response.should be_ok
changed_thread = CommentThread.find(thread.id) changed_thread = CommentThread.find(thread.id)
changed_thread.comment_count.should == orig_count + 1 changed_thread.comment_count.should == orig_count + 1
comment = changed_thread.comments.select{|c| c["body"] == "new comment"}.first comment = changed_thread.comments.select { |c| c["body"] == "new comment" }.first
comment.should_not be_nil comment.should_not be_nil
comment.anonymous.should be_true comment.anonymous.should be_true
end end
...@@ -720,18 +731,29 @@ describe "app" do ...@@ -720,18 +731,29 @@ describe "app" do
include_examples "unicode data" include_examples "unicode data"
end end
describe "DELETE /api/v1/threads/:thread_id" do
before(:each) { init_without_subscriptions } describe 'DELETE /api/v1/threads/:thread_id' do
it "delete the comment thread and its comments" do let(:thread) { create_comment_thread_and_comments }
thread = CommentThread.first.to_hash
delete "/api/v1/threads/#{thread['id']}" subject { delete "/api/v1/threads/#{thread.id}" }
last_response.should be_ok
CommentThread.where(title: thread["title"]).first.should be_nil it { should be_ok }
it 'deletes the comment thread and its comments' do
expect(CommentThread.where(id: thread.id).count).to eq 1
expect(Comment.where(comment_thread: thread).count).to eq 2
subject
expect(CommentThread.where(id: thread.id).count).to eq 0
expect(Comment.where(comment_thread: thread).count).to eq 0
end end
it "returns 400 when the thread does not exist" do
delete "/api/v1/threads/does_not_exist" context 'when thread does not exist' do
last_response.status.should == 400 subject { delete '/api/v1/threads/does_not_exist' }
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
it 'returns 400 when the thread does not exist' do
expect(subject.status).to eq 400
expect(parse(subject.body).first).to eq I18n.t(:requested_object_not_found)
end
end end
end end
end end
......
require 'spec_helper' require 'spec_helper'
require 'unicode_shared_examples' require 'unicode_shared_examples'
describe "app" do describe 'app' do
describe "commentables" do describe 'commentables' do
before(:each) { set_api_key_header }
let(:commentable_id) { Faker::Lorem.word }
before(:each) do describe 'DELETE /api/v1/:commentable_id/threads' do
init_without_subscriptions it 'delete all associated threads and comments of a commentable' do
set_api_key_header thread_count = 2
end create_list(:comment_thread, thread_count, commentable_id: commentable_id)
expect(Commentable.find(commentable_id).comment_threads.count).to eq thread_count
describe "DELETE /api/v1/:commentable_id/threads" do delete "/api/v1/#{commentable_id}/threads"
it "delete all associated threads and comments of a commentable" do expect(last_response).to be_ok
delete '/api/v1/question_1/threads' expect(Commentable.find(commentable_id).comment_threads.count).to eq 0
last_response.should be_ok
Commentable.find("question_1").comment_threads.count.should == 0
end end
it "handle normally when commentable does not exist" do
delete '/api/v1/does_not_exist/threads' context 'if the commentable does not exist' do
last_response.should be_ok subject { delete '/api/v1/does_not_exist/threads' }
it { should be_ok }
end end
end end
describe "GET /api/v1/:commentable_id/threads" do
def thread_result(commentable_id, params={}) describe 'GET /api/v1/:commentable_id/threads' do
get "/api/v1/#{commentable_id}/threads", params let(:returned_threads) { parse(subject.body)['collection'] }
last_response.should be_ok subject { get "/api/v1/#{commentable_id}/threads" }
parse(last_response.body)["collection"]
end shared_examples_for 'a filterable API endpoint' do
it "get all comment threads associated with a commentable object" do let!(:ignored_threads) { create_list(:comment_thread, 3, commentable_id: commentable_id) }
threads = thread_result "question_1" subject { get "/api/v1/#{commentable_id}/threads", parameters }
threads.length.should == 2
threads.index{|c| c["body"] == "can anyone help me?"}.should_not be_nil it { should be_ok }
threads.index{|c| c["body"] == "it is unsolvable"}.should_not be_nil
end it 'returns the correct CommentThreads' do
it "returns standalone threads if explicitly requested" do expect(returned_threads.length).to eq threads.length
threads = thread_result "question_1", context: "standalone" threads.sort_by!(&:_id).reverse!
threads.length.should == 1 threads.each_with_index do |thread, index|
threads[0]["body"].should == "no one can see us" expect(returned_threads[index]).to include('id' => thread.id.to_s, 'body' => thread.body)
end end
it "filters by course_id" do end
course1_threads = thread_result "question_1", course_id: "1" end
course1_threads.length.should == 1
course2_threads = thread_result "question_1", course_id: "2" context 'without filtering' do
course2_threads.length.should == 1 let(:parameters) { {} }
course1_threads.should_not == course2_threads let!(:threads) { ignored_threads + create_list(:comment_thread, 3, :with_group_id, commentable_id: commentable_id) }
end
it "filters by group_id" do it_behaves_like 'a filterable API endpoint'
group_thread = Commentable.find("question_1").comment_threads.sort(_id: 1).first end
threads = thread_result "question_1", group_id: 42
threads.length.should == 2 context 'when filtering by the standalone context' do
group_thread.group_id = 43 let(:parameters) { {context: :standalone} }
group_thread.save! let!(:threads) { create_list(:comment_thread, 3, commentable_id: commentable_id, context: :standalone) }
threads = thread_result "question_1", group_id: 42
threads.length.should == 1 it_behaves_like 'a filterable API endpoint'
group_thread.group_id = 42 end
group_thread.save!
threads = thread_result "question_1", group_id: 42 context 'when filtering by course_id' do
threads.length.should == 2 let(:course_id) { Faker::Lorem.word }
end let(:parameters) { {course_id: course_id} }
it "filters by group_ids" do let!(:threads) { create_list(:comment_thread, 3, commentable_id: commentable_id, course_id: course_id) }
group_thread = Commentable.find("question_1").comment_threads.sort(_id: 1).first
group_thread.group_id = 42
group_thread.save! it_behaves_like 'a filterable API endpoint'
threads = thread_result "question_1", group_ids: "42,43" end
threads.length.should == 2
group_thread.group_id = 43 context 'when filtering by group_id' do
group_thread.save! let(:group_id) { Faker::Number.number(4) }
threads = thread_result "question_1", group_ids: "42,43" let(:parameters) { {group_id: group_id} }
threads.length.should == 2 let!(:threads) { create_list(:comment_thread, 3, commentable_id: commentable_id, group_id: group_id) }
group_thread.group_id = 44
group_thread.save
threads = thread_result "question_1", group_ids: "42,43" it_behaves_like 'a filterable API endpoint'
threads.length.should == 1 end
end
it "returns an empty array when the commentable object does not exist (no threads)" do context 'when filtering by multiple group_id values' do
threads = thread_result "does_not_exist" let(:group_ids) { [Faker::Number.number(4), Faker::Number.number(4)] }
threads.length.should == 0 let(:parameters) { {group_ids: group_ids.join(',')} }
it_behaves_like 'a filterable API endpoint' do
let!(:threads) do
threads = []
group_ids.each do |group_id|
threads += create_list(:comment_thread, 3, commentable_id: commentable_id, group_id: group_id)
end
threads
end
end
end
context 'when the commentable does not exist' do
subject { get '/api/v1/does_not_exist/threads' }
it { should be_ok }
it 'should not return any results' do
expect(returned_threads.length).to eq 0
end
end end
def test_unicode_data(text) def test_unicode_data(text)
commentable_id = "unicode_commentable" commentable_id = 'unicode_commentable'
thread = make_thread(User.first, text, "unicode_course", commentable_id) thread = create(:comment_thread, commentable_id: commentable_id, body: text)
make_comment(User.first, thread, text) create(:comment, comment_thread: thread, body: text)
get "/api/v1/#{commentable_id}/threads" get "/api/v1/#{commentable_id}/threads"
last_response.should be_ok last_response.should be_ok
result = parse(last_response.body)["collection"] result = parse(last_response.body)['collection']
result.should_not be_empty result.should_not be_empty
check_thread_result_json(nil, thread, result.first) check_thread_result_json(nil, thread, result.first)
end end
include_examples "unicode data" include_examples 'unicode data'
end end
describe "POST /api/v1/:commentable_id/threads" do
let(:default_params) do describe 'POST /api/v1/:commentable_id/threads' do
{title: "Interesting question", body: "cool", course_id: "1", user_id: "1"} let(:commentable_id) { Faker::Lorem.word }
let(:user) { create(:user) }
let(:parameters) { attributes_for(:comment_thread, user_id: user.id) }
subject { post "/api/v1/#{commentable_id}/threads", parameters }
shared_examples_for 'CommentThread creation API' do |context='course'|
it 'creates a new CommentThread' do
expect(CommentThread.count).to eq 0
body = parse(subject.body)
expect(body).to include('read' => false,
'unread_comments_count' => 0,
'endorsed' => false,
'resp_total' => 0)
expect(CommentThread.count).to eq 1
thread = CommentThread.find(body['id'])
expect(thread).to_not be_nil
expect(thread.context).to eq context
end
end end
it "create a new comment thread for the commentable object" do
old_count = CommentThread.count it { should be_ok }
post '/api/v1/question_1/threads', default_params
last_response.should be_ok it_behaves_like 'CommentThread creation API'
result = parse(last_response.body) it_behaves_like 'CommentThread creation API', 'standalone' do
result["read"].should == false let(:parameters) { attributes_for(:comment_thread, user_id: user.id, context: 'standalone') }
result["unread_comments_count"].should == 0
result["endorsed"].should == false
result["resp_total"].should == 0
CommentThread.count.should == old_count + 1
thread = CommentThread.where(title: "Interesting question").first
thread.should_not be_nil
thread.context.should == "course"
end
it "can create a standalone thread" do
old_count = CommentThread.count
post '/api/v1/question_1/threads', default_params.merge(:context => "standalone")
CommentThread.count.should == old_count + 1
thread = CommentThread.where(title: "Interesting question").first
thread.should_not be_nil
thread.context.should == "standalone"
end end
CommentThread.thread_type.values.each do |thread_type| CommentThread.thread_type.values.each do |thread_type|
it "can create a #{thread_type} thread" do it "can create a #{thread_type} thread" do
old_count = CommentThread.where(thread_type: thread_type).count old_count = CommentThread.where(thread_type: thread_type).count
post "/api/v1/question_1/threads", default_params.merge(thread_type: thread_type.to_s) post '/api/v1/question_1/threads', parameters.merge(thread_type: thread_type.to_s)
last_response.should be_ok last_response.should be_ok
parse(last_response.body)["thread_type"].should == thread_type.to_s parse(last_response.body)['thread_type'].should == thread_type.to_s
CommentThread.where(thread_type: thread_type).count.should == old_count + 1 CommentThread.where(thread_type: thread_type).count.should == old_count + 1
end end
end end
it "allows anonymous thread" do
old_count = CommentThread.count it 'allows anonymous thread' do
post '/api/v1/question_1/threads', default_params.merge(anonymous: true) post '/api/v1/question_1/threads', parameters.merge!(anonymous: true)
last_response.should be_ok
CommentThread.count.should == old_count + 1
c = CommentThread.where(title: "Interesting question").first
c.should_not be_nil
c["anonymous"].should be_true
end
it "create a new comment thread for a new commentable object" do
post '/api/v1/does_not_exist/threads', default_params
last_response.should be_ok last_response.should be_ok
Commentable.find("does_not_exist").comment_threads.length.should == 1 body = parse(subject.body)
Commentable.find("does_not_exist").comment_threads.first.body.should == "cool"
thread = CommentThread.find(body['id'])
expect(thread).to_not be_nil
expect(thread['anonymous']).to be_true
end end
it "returns error when title, body or course id does not exist" do
params = default_params.dup it 'returns error when title, body or course id does not exist' do
params.delete(:title) [:title, :body, :course_id].each do |parameter|
post '/api/v1/question_1/threads', params params = parameters.dup
last_response.status.should == 400 params.delete(parameter)
params = default_params.dup post '/api/v1/question_1/threads', params
params.delete(:body) last_response.status.should == 400
post '/api/v1/question_1/threads', params end
last_response.status.should == 400
params = default_params.dup
params.delete(:course_id)
post '/api/v1/question_1/threads', params
last_response.status.should == 400
end end
it "returns error when title or body is blank (only consists of spaces and new lines)" do it "returns error when title or body is blank (only consists of spaces and new lines)" do
post '/api/v1/question_1/threads', default_params.merge(title: " ") post '/api/v1/question_1/threads', parameters.merge(title: " ")
last_response.status.should == 400 last_response.status.should == 400
post '/api/v1/question_1/threads', default_params.merge(body: " \n \n") post '/api/v1/question_1/threads', parameters.merge(body: " \n \n")
last_response.status.should == 400 last_response.status.should == 400
end end
it "returns 503 and does not create when the post content is blocked" do
post '/api/v1/question_1/threads', default_params.merge(body: "BLOCKED POST") it 'returns 503 and does not create when the post content is blocked' do
body = 'BLOCKED POST'
hash = block_post_body
post '/api/v1/question_1/threads', parameters.merge!(body: body)
last_response.status.should == 503 last_response.status.should == 503
parse(last_response.body).first.should == I18n.t(:blocked_content_with_body_hash, :hash => Digest::MD5.hexdigest("blocked post")) parse(last_response.body).first.should == I18n.t(:blocked_content_with_body_hash, :hash => hash)
CommentThread.where(body: "BLOCKED POST").to_a.should be_empty expect(CommentThread.where(body: body).length).to eq 0
end end
def test_unicode_data(text) def test_unicode_data(text)
commentable_id = "unicode_commentable" commentable_id = 'unicode_commentable'
post "/api/v1/#{commentable_id}/threads", default_params.merge(body: text, title: text) post "/api/v1/#{commentable_id}/threads", parameters.merge!(body: text, title: text)
last_response.should be_ok last_response.should be_ok
CommentThread.where(commentable_id: commentable_id, body: text, title: text).should_not be_empty expect(CommentThread.where(commentable_id: commentable_id, body: text, title: text)).to_not be_empty
end end
include_examples "unicode data" include_examples 'unicode data'
end end
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment