Updated Comment API spec
- Using factories to create only the data that is actually needed for the tests - Replaced double quotes with single quotes - Fixed spacing - Created helper method, block_post_body, to centralize blocked post logic
This commit is contained in:
Родитель
0030050154
Коммит
f1d81865cd
|
@ -1,186 +1,208 @@
|
|||
require 'spec_helper'
|
||||
require 'unicode_shared_examples'
|
||||
|
||||
describe "app" do
|
||||
BLOCKED_BODY = 'BLOCKED POST'
|
||||
|
||||
describe 'Comment API' do
|
||||
before(:each) { set_api_key_header }
|
||||
let(:thread) { create_comment_thread_and_comments }
|
||||
|
||||
describe "comments" do
|
||||
before(:each) { init_without_subscriptions }
|
||||
|
||||
describe "GET /api/v1/comments/:comment_id" do
|
||||
it "returns JSON" do
|
||||
comment = Comment.first
|
||||
get "/api/v1/comments/#{comment.id}"
|
||||
last_response.should be_ok
|
||||
last_response.content_type.should == "application/json;charset=utf-8"
|
||||
end
|
||||
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
|
||||
retrieved["votes"]["point"].should == comment.votes_point
|
||||
retrieved["depth"].should == comment.depth
|
||||
retrieved["parent_id"].should == comment.parent_ids.map(&:to_s)[-1]
|
||||
end
|
||||
it "retrieve information of a single comment with its sub comments" do
|
||||
comment = Comment.order_by(_id: 'asc').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["votes"]["point"].should == comment.votes_point
|
||||
retrieved["children"].length.should == comment.children.length
|
||||
retrieved["children"].select{|c| c["body"] == comment.children.first.body}.first.should_not be_nil
|
||||
retrieved["children"].each{|c| c["parent_id"].should == comment.id.to_s}
|
||||
end
|
||||
it "returns 400 when the comment does not exist" do
|
||||
get "/api/v1/comments/does_not_exist"
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
|
||||
def test_unicode_data(text)
|
||||
comment = make_comment(User.first, CommentThread.first, text)
|
||||
get "/api/v1/comments/#{comment.id}"
|
||||
last_response.should be_ok
|
||||
retrieved = parse last_response.body
|
||||
retrieved["body"].should == text
|
||||
end
|
||||
|
||||
include_examples "unicode data"
|
||||
describe 'GET /api/v1/comments/:comment_id' do
|
||||
it 'returns JSON' do
|
||||
comment = thread.comments.first
|
||||
get "/api/v1/comments/#{comment.id}"
|
||||
last_response.should be_ok
|
||||
last_response.content_type.should == 'application/json;charset=utf-8'
|
||||
end
|
||||
|
||||
describe "PUT /api/v1/comments/:comment_id" do
|
||||
def test_update_endorsed(true_val, false_val)
|
||||
comment = Comment.first
|
||||
before = DateTime.now
|
||||
put "/api/v1/comments/#{comment.id}", endorsed: true_val, endorsement_user_id: "#{User.first.id}"
|
||||
after = DateTime.now
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.endorsed.should == true
|
||||
comment.endorsement.should_not be_nil
|
||||
comment.endorsement["user_id"].should == "#{User.first.id}"
|
||||
comment.endorsement["time"].should be_between(before, after)
|
||||
put "/api/v1/comments/#{comment.id}", endorsed: false_val
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.endorsed.should == false
|
||||
comment.endorsement.should be_nil
|
||||
end
|
||||
it "updates endorsed correctly" do
|
||||
test_update_endorsed(true, false)
|
||||
end
|
||||
it "updates endorsed correctly with Pythonic values" do
|
||||
test_update_endorsed("True", "False")
|
||||
end
|
||||
it "updates body correctly" do
|
||||
comment = Comment.first
|
||||
put "/api/v1/comments/#{comment.id}", body: "new body"
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.body.should == "new body"
|
||||
end
|
||||
it "can update endorsed and body simultaneously" do
|
||||
comment = Comment.first
|
||||
put "/api/v1/comments/#{comment.id}", body: "new body", endorsed: true
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.body.should == "new body"
|
||||
comment.endorsed.should == true
|
||||
end
|
||||
it "returns 400 when the comment does not exist" do
|
||||
put "/api/v1/comments/does_not_exist", body: "new body", endorsed: true
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
it "returns 503 and does not update when the post hash is blocked" do
|
||||
comment = Comment.first
|
||||
original_body = comment.body
|
||||
put "/api/v1/comments/#{comment.id}", body: "BLOCKED POST", endorsed: true
|
||||
last_response.status.should == 503
|
||||
parse(last_response.body).first.should == I18n.t(:blocked_content_with_body_hash, :hash => Digest::MD5.hexdigest("blocked post"))
|
||||
comment.reload
|
||||
comment.body.should == original_body
|
||||
end
|
||||
|
||||
def test_unicode_data(text)
|
||||
comment = Comment.first
|
||||
put "/api/v1/comments/#{comment.id}", body: text
|
||||
last_response.should be_ok
|
||||
comment = Comment.find(comment.id)
|
||||
comment.body.should == text
|
||||
end
|
||||
|
||||
include_examples "unicode data"
|
||||
it 'retrieve information of a single comment' do
|
||||
comment = thread.comments.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
|
||||
retrieved['votes']['point'].should == comment.votes_point
|
||||
retrieved['depth'].should == comment.depth
|
||||
retrieved['parent_id'].should == comment.parent_ids.map(&:to_s)[-1]
|
||||
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.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.id
|
||||
end
|
||||
it "returns 400 when the comment does not exist" do
|
||||
post "/api/v1/comments/does_not_exist", body: "new comment", course_id: "1", user_id: User.first.id
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
it "returns 503 and does not create when the post hash is blocked" do
|
||||
comment = Comment.first.to_hash(recursive: true)
|
||||
user = User.first
|
||||
post "/api/v1/comments/#{comment["id"]}", body: "BLOCKED POST", course_id: "1", user_id: User.first.id
|
||||
last_response.status.should == 503
|
||||
parse(last_response.body).first.should == I18n.t(:blocked_content_with_body_hash, :hash => Digest::MD5.hexdigest("blocked post"))
|
||||
Comment.where(body: "BLOCKED POST").to_a.should be_empty
|
||||
end
|
||||
it 'retrieve information of a single comment with its sub comments' do
|
||||
comment = thread.comments.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['votes']['point'].should == comment.votes_point
|
||||
|
||||
def test_unicode_data(text)
|
||||
parent = Comment.first
|
||||
post "/api/v1/comments/#{parent.id}", body: text, course_id: parent.course_id, user_id: User.first.id
|
||||
last_response.should be_ok
|
||||
parent.children.where(body: text).should_not be_empty
|
||||
end
|
||||
retrieved_children = retrieved['children']
|
||||
retrieved_children.length.should == comment.children.length
|
||||
|
||||
include_examples "unicode data"
|
||||
comment.children.each_with_index do |child, index|
|
||||
expect(retrieved_children[index]).to include('body' => child.body, 'parent_id' => comment.id.to_s)
|
||||
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
|
||||
it "can delete a sub comment" do
|
||||
child_comment = Comment.where(:parent.exists => true).first
|
||||
parent_comment = child_comment.parent
|
||||
delete "/api/v1/comments/#{child_comment.id}"
|
||||
it 'returns 400 when the comment does not exist' do
|
||||
get '/api/v1/comments/does_not_exist'
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
|
||||
Comment.where(:id => child_comment.id).should be_empty
|
||||
parent_comment.children.where(:id => child_comment.id).should be_empty
|
||||
end
|
||||
it "returns 400 when the comment does not exist" do
|
||||
delete "/api/v1/comments/does_not_exist"
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
def test_unicode_data(text)
|
||||
comment = create(:comment, body: text)
|
||||
get "/api/v1/comments/#{comment.id}"
|
||||
last_response.should be_ok
|
||||
parse(last_response.body)['body'].should == text
|
||||
end
|
||||
|
||||
include_examples 'unicode data'
|
||||
end
|
||||
|
||||
describe 'PUT /api/v1/comments/:comment_id' do
|
||||
def test_update_endorsed(true_val, false_val)
|
||||
comment = thread.comments.first
|
||||
before = DateTime.now
|
||||
put "/api/v1/comments/#{comment.id}", endorsed: true_val, endorsement_user_id: "#{User.first.id}"
|
||||
after = DateTime.now
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.endorsed.should == true
|
||||
comment.endorsement.should_not be_nil
|
||||
comment.endorsement["user_id"].should == "#{User.first.id}"
|
||||
comment.endorsement["time"].should be_between(before, after)
|
||||
put "/api/v1/comments/#{comment.id}", endorsed: false_val
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.endorsed.should == false
|
||||
comment.endorsement.should be_nil
|
||||
end
|
||||
|
||||
it 'updates endorsed correctly' do
|
||||
test_update_endorsed(true, false)
|
||||
end
|
||||
|
||||
it 'updates endorsed correctly with Pythonic values' do
|
||||
test_update_endorsed('True', 'False')
|
||||
end
|
||||
|
||||
it 'updates body correctly' do
|
||||
comment = thread.comments.first
|
||||
put "/api/v1/comments/#{comment.id}", body: 'new body'
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.body.should == 'new body'
|
||||
end
|
||||
|
||||
it 'can update endorsed and body simultaneously' do
|
||||
comment = thread.comments.first
|
||||
put "/api/v1/comments/#{comment.id}", body: 'new body', endorsed: true
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.body.should == 'new body'
|
||||
comment.endorsed.should == true
|
||||
end
|
||||
|
||||
it 'returns 400 when the comment does not exist' do
|
||||
put '/api/v1/comments/does_not_exist', body: 'new body', endorsed: true
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
|
||||
it 'returns 503 and does not update when the post hash is blocked' do
|
||||
blocked_hash = block_post_body(BLOCKED_BODY)
|
||||
comment = thread.comments.first
|
||||
original_body = comment.body
|
||||
put "/api/v1/comments/#{comment.id}", body: BLOCKED_BODY, endorsed: true
|
||||
last_response.status.should == 503
|
||||
parse(last_response.body).first.should == I18n.t(:blocked_content_with_body_hash, :hash => blocked_hash)
|
||||
comment.reload
|
||||
comment.body.should == original_body
|
||||
end
|
||||
|
||||
def test_unicode_data(text)
|
||||
comment = thread.comments.first
|
||||
put "/api/v1/comments/#{comment.id}", body: text
|
||||
last_response.should be_ok
|
||||
comment.reload
|
||||
comment.body.should == text
|
||||
end
|
||||
|
||||
include_examples 'unicode data'
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/comments/:comment_id' do
|
||||
it 'creates a sub comment to the comment' do
|
||||
comment = thread.comments.first
|
||||
previous_child_count = comment.children.length
|
||||
user = thread.author
|
||||
body = 'new comment'
|
||||
course_id = '1'
|
||||
post "/api/v1/comments/#{comment.id}", body: body, course_id: course_id, user_id: user.id
|
||||
last_response.should be_ok
|
||||
|
||||
comment.reload
|
||||
comment.children.length.should == previous_child_count + 1
|
||||
sub_comment = comment.children.order_by(created_at: :desc).first
|
||||
sub_comment.body.should == body
|
||||
sub_comment.course_id.should == course_id
|
||||
sub_comment.author.should == user
|
||||
end
|
||||
|
||||
it 'returns 400 when the comment does not exist' do
|
||||
post '/api/v1/comments/does_not_exist', body: 'new comment', course_id: '1', user_id: thread.author.id
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
|
||||
it 'returns 503 and does not create when the post hash is blocked' do
|
||||
blocked_hash = block_post_body(BLOCKED_BODY)
|
||||
comment = thread.comments.first
|
||||
user = comment.author
|
||||
post "/api/v1/comments/#{comment.id}", body: BLOCKED_BODY, course_id: '1', user_id: user.id
|
||||
last_response.status.should == 503
|
||||
parse(last_response.body).first.should == I18n.t(:blocked_content_with_body_hash, :hash => blocked_hash)
|
||||
Comment.where(body: BLOCKED_BODY).to_a.should be_empty
|
||||
end
|
||||
|
||||
def test_unicode_data(text)
|
||||
parent = thread.comments.first
|
||||
post "/api/v1/comments/#{parent.id}", body: text, course_id: parent.course_id, user_id: User.first.id
|
||||
last_response.should be_ok
|
||||
parent.children.where(body: text).should_not be_empty
|
||||
end
|
||||
|
||||
include_examples 'unicode data'
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/comments/:comment_id' do
|
||||
it 'delete the comment and its sub comments' do
|
||||
comment = thread.comments.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
|
||||
|
||||
it 'can delete a sub comment' do
|
||||
# Sort to ensure we get the thread's first comment, rather than the child of that comment.
|
||||
parent_comment = thread.comments.sort_by(&:_id).first
|
||||
child_comment = parent_comment.children.first
|
||||
delete "/api/v1/comments/#{child_comment.id}"
|
||||
|
||||
Comment.where(:id => child_comment.id).should be_empty
|
||||
parent_comment.children.where(:id => child_comment.id).should be_empty
|
||||
end
|
||||
|
||||
it 'returns 400 when the comment does not exist' do
|
||||
delete '/api/v1/comments/does_not_exist'
|
||||
last_response.status.should == 400
|
||||
parse(last_response.body).first.should == I18n.t(:requested_object_not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -59,6 +59,20 @@ def create_test_user(id)
|
|||
User.create!(external_id: id.to_s, username: "user#{id}")
|
||||
end
|
||||
|
||||
# Add the given body of text to the list of blocked texts/hashes.
|
||||
def block_post_body(body='blocked post')
|
||||
body = body.strip.downcase.gsub(/[^a-z ]/, '').gsub(/\s+/, ' ')
|
||||
blocked_hash = Digest::MD5.hexdigest(body)
|
||||
Content.mongo_client[:blocked_hash].insert_one(hash: blocked_hash)
|
||||
|
||||
# reload the global holding the blocked hashes
|
||||
CommentService.blocked_hashes = Content.mongo_client[:blocked_hash].find(nil, projection: {hash: 1}).map do |d|
|
||||
d['hash']
|
||||
end
|
||||
|
||||
blocked_hash
|
||||
end
|
||||
|
||||
def init_without_subscriptions
|
||||
commentable = Commentable.new("question_1")
|
||||
|
||||
|
@ -139,11 +153,7 @@ def init_without_subscriptions
|
|||
users[2, 9].each { |user| user.vote(c, [:up, :down].sample) }
|
||||
end
|
||||
|
||||
Content.mongo_client[:blocked_hash].insert_one(hash: Digest::MD5.hexdigest("blocked post"))
|
||||
# reload the global holding the blocked hashes
|
||||
CommentService.blocked_hashes = Content.mongo_client[:blocked_hash].find(nil, projection: {hash: 1}).map do |d|
|
||||
d["hash"]
|
||||
end
|
||||
block_post_body
|
||||
end
|
||||
|
||||
# this method is used to test results produced using the helper function handle_threads_query
|
||||
|
@ -370,3 +380,16 @@ def setup_10_threads
|
|||
end
|
||||
@default_order = 10.times.map { |i| "t#{i}" }.reverse
|
||||
end
|
||||
|
||||
# Creates a CommentThread with a Comment, and nested child Comment.
|
||||
# The author of the thread is subscribed to the thread.
|
||||
def create_comment_thread_and_comments
|
||||
# Create a new comment thread, and subscribe the author to the thread
|
||||
thread = create(:comment_thread, :subscribe_author)
|
||||
|
||||
# Create a comment along with a nested child comment
|
||||
comment = create(:comment, comment_thread: thread)
|
||||
create(:comment, parent: comment)
|
||||
|
||||
thread
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче