183 lines
5.6 KiB
Ruby
183 lines
5.6 KiB
Ruby
require "rails_helper"
|
|
|
|
RSpec.describe "CommentsCreate", type: :request do
|
|
let(:user) { create(:user) }
|
|
let(:blocker) { create(:user) }
|
|
let(:article) { create(:article, user_id: user.id) }
|
|
let(:new_body) { -> { "NEW BODY #{rand(100)}" } }
|
|
let(:rate_limit_checker) { RateLimitChecker.new(user) }
|
|
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
def comment_params(**kwargs)
|
|
{
|
|
comment: {
|
|
body_markdown: new_body.call,
|
|
commentable_id: article.id,
|
|
commentable_type: "Article"
|
|
}.merge(kwargs)
|
|
}
|
|
end
|
|
|
|
it "creates a comment with proper params" do
|
|
expect do
|
|
post comments_path, params: comment_params
|
|
end.to change(user.comments, :count).by(1)
|
|
end
|
|
|
|
it "creates NotificationSubscription for comment" do
|
|
post comments_path, params: comment_params
|
|
|
|
expect(NotificationSubscription.last.notifiable).to eq(Comment.last)
|
|
end
|
|
|
|
context "when users hit their rate limits" do
|
|
before do
|
|
allow(RateLimitChecker).to receive(:new).and_return(rate_limit_checker)
|
|
end
|
|
|
|
it "returns 429 Too Many Requests when a user reaches their rate limit" do
|
|
# avoid hitting new user rate limit check
|
|
allow(user).to receive(:created_at).and_return(1.week.ago)
|
|
allow(rate_limit_checker).to receive(:limit_by_action)
|
|
.with(:comment_creation)
|
|
.and_return(true)
|
|
|
|
post comments_path, params: comment_params
|
|
|
|
expect(response).to have_http_status(:too_many_requests)
|
|
end
|
|
|
|
it "returns 429 Too Many Requests when a new user reaches their rate limit" do
|
|
allow(rate_limit_checker).to receive(:limit_by_action)
|
|
.with(:comment_antispam_creation)
|
|
.and_return(true)
|
|
|
|
post comments_path, params: comment_params
|
|
|
|
expect(response).to have_http_status(:too_many_requests)
|
|
end
|
|
end
|
|
|
|
context "when user is posting on an author that blocks user" do
|
|
it "returns unauthorized" do
|
|
create(:user_block, blocker: blocker, blocked: user, config: "default")
|
|
user.update(blocked_by_count: 1)
|
|
blocker_article = create(:article, user: blocker)
|
|
|
|
post comments_path, params: comment_params(commentable_id: blocker_article.id)
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
context "when user is posting on an author that does not block user, but the user has been blocked elsewhere" do
|
|
it "creates the new comment" do
|
|
user.update(blocked_by_count: 1)
|
|
blocker_article = create(:article, user: blocker)
|
|
|
|
post comments_path, params: comment_params(
|
|
body_markdown: "something allowed",
|
|
commentable_id: blocker_article.id,
|
|
)
|
|
|
|
new_comment = Comment.last
|
|
expect(new_comment.body_markdown).to eq("something allowed")
|
|
expect(new_comment.id).not_to be_nil
|
|
end
|
|
end
|
|
|
|
context "when an error is raised before authorization is performed" do
|
|
before do
|
|
allow(RateLimitChecker).to receive(:new).and_return(rate_limit_checker)
|
|
allow(rate_limit_checker).to receive(:check_limit!).and_raise(StandardError)
|
|
end
|
|
|
|
it "returns an unprocessable_entity response code" do
|
|
post comments_path, params: comment_params
|
|
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
context "when a comment is invalid" do
|
|
it "returns the proper JSON response" do
|
|
post comments_path, params: comment_params(body_markdown: "a" * 25_001)
|
|
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
expect(response.parsed_body["error"]).to be_present
|
|
end
|
|
end
|
|
|
|
context "when there's already a notification for comment" do
|
|
around do |example|
|
|
Sidekiq::Testing.inline!(&example)
|
|
end
|
|
|
|
let(:comment_author) { create(:user) }
|
|
let(:user_replier) { create(:user) }
|
|
let(:moderator_replier) { create(:user, :admin) }
|
|
let(:response_template) do
|
|
create(:response_template, type_of: "mod_comment",
|
|
content: text_mentioning_comment_author, user_id: nil)
|
|
end
|
|
let(:text_mentioning_comment_author) do
|
|
"Hello, @#{comment_author.username}"
|
|
end
|
|
|
|
it "doesn't create mention notification, when replying as regular user" do
|
|
comment = comment_on_article
|
|
reply_and_mention_comment_author(comment)
|
|
|
|
expect_no_duplicate_notifications_for_comment_author
|
|
end
|
|
|
|
it "doesn't create mention notification, when replying as moderator" do
|
|
comment = comment_on_article
|
|
reply_and_mention_comment_author_as_moderator(comment)
|
|
|
|
expect_no_duplicate_notifications_for_comment_author
|
|
end
|
|
|
|
private
|
|
|
|
def comment_on_article
|
|
sign_in comment_author
|
|
post comments_path, params: comment_params
|
|
expect_request_to_be_successful
|
|
|
|
Comment.first
|
|
end
|
|
|
|
def reply_and_mention_comment_author(comment)
|
|
sign_in user_replier
|
|
post comments_path, params: comment_params(
|
|
parent_id: comment.id,
|
|
body_markdown: text_mentioning_comment_author,
|
|
)
|
|
expect_request_to_be_successful
|
|
end
|
|
|
|
def reply_and_mention_comment_author_as_moderator(comment)
|
|
allow(Settings::General).to receive(:mascot_user_id)
|
|
.and_return(moderator_replier.id)
|
|
|
|
sign_in moderator_replier
|
|
post moderator_create_comments_path, params: comment_params(
|
|
parent_id: comment.id,
|
|
).merge(response_template: { id: response_template.id })
|
|
expect(response).to be_successful
|
|
end
|
|
|
|
def expect_no_duplicate_notifications_for_comment_author
|
|
expect(Mention.count).to eq 0
|
|
expect(Notification.where(user: comment_author).count).to eq 1
|
|
end
|
|
|
|
def expect_request_to_be_successful
|
|
expect(response.parsed_body["error"]).to be_nil
|
|
expect(response).to be_successful
|
|
end
|
|
end
|
|
end
|