258 lines
7.7 KiB
Ruby
258 lines
7.7 KiB
Ruby
require 'rails_helper'
|
|
|
|
describe 'stories', type: :request do
|
|
let(:user) { create(:user) }
|
|
let(:story) { create(:story, user: user) }
|
|
let(:mod) { create(:user, :moderator) }
|
|
|
|
describe "#check_url_dupe" do
|
|
before { sign_in user }
|
|
|
|
context "json" do
|
|
it "returns similar story matching URL" do
|
|
post "/stories/check_url_dupe.json",
|
|
params: { story: { title: "some other title", url: story.url } }
|
|
|
|
expect(response).to be_successful
|
|
|
|
json = JSON.parse(response.body)
|
|
|
|
expect(json.fetch("title")).to eq "some other title"
|
|
expect(json.fetch("similar_stories").count).to eq(1)
|
|
|
|
similar_story = json.fetch("similar_stories").first
|
|
expect(similar_story.fetch("title")).to eq story.title
|
|
expect(similar_story.fetch("short_id")).to eq story.short_id
|
|
expect(similar_story.fetch("url")).to eq story.url
|
|
expect(similar_story.fetch("comments_url")).to eq story.comments_url
|
|
expect(similar_story.fetch("comment_count")).to eq story.comments_count
|
|
end
|
|
|
|
it "returns no matches if previously submitted URL is only partial match" do
|
|
post "/stories/check_url_dupe.json",
|
|
params: { story: { title: "some other title", url: story.url[0...-1] } }
|
|
|
|
expect(response).to be_successful
|
|
|
|
json = JSON.parse(response.body)
|
|
|
|
expect(json.fetch("title")).to eq "some other title"
|
|
expect(json.fetch("similar_stories").count).to eq(0)
|
|
end
|
|
|
|
it "returns no matches if no matching URL" do
|
|
post "/stories/check_url_dupe.json",
|
|
params: { story: { title: "some other title", url: "invalid_url" } }
|
|
|
|
expect(response).to be_successful
|
|
|
|
json = JSON.parse(response.body)
|
|
|
|
expect(json.fetch("title")).to eq "some other title"
|
|
expect(json.fetch("similar_stories").count).to eq(0)
|
|
end
|
|
|
|
it "throws a 400 if there's no URL present" do
|
|
expect {
|
|
post "/stories/check_url_dupe.json",
|
|
params: { story: { url: "" } }
|
|
}.to raise_error(ActionController::ParameterMissing)
|
|
|
|
expect {
|
|
post "/stories/check_url_dupe.json",
|
|
params: { story: {} }
|
|
}.to raise_error(ActionController::ParameterMissing)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#delete" do
|
|
before { sign_in user }
|
|
|
|
it "increments the user's count of deleted stories" do
|
|
expect {
|
|
put "/stories/#{story.short_id}/destroy", params: {
|
|
id: story.short_id,
|
|
story: {
|
|
title: story.title,
|
|
},
|
|
}
|
|
}.to change { user.stories_deleted_count }.by(1)
|
|
end
|
|
end
|
|
|
|
describe "#undelete" do
|
|
before { sign_in user }
|
|
|
|
let(:deleted_story) { create(:story, :deleted, user: user) }
|
|
|
|
it "decrements the user's count of deleted stories" do
|
|
expect {
|
|
put "/stories/#{deleted_story.short_id}/undelete", params: {
|
|
id: deleted_story.short_id,
|
|
story: {
|
|
title: deleted_story.title,
|
|
},
|
|
}
|
|
}.to change { user.stories_deleted_count }.by(-1)
|
|
end
|
|
end
|
|
|
|
describe "merged stories" do
|
|
it "can be merged by mod" do
|
|
sign_in mod
|
|
s = create(:story)
|
|
put "/stories/#{s.short_id}",
|
|
params: {
|
|
story: {
|
|
merge_story_short_id: story.short_id,
|
|
moderation_reason: 'cuz',
|
|
},
|
|
}
|
|
expect(response).to be_redirect
|
|
|
|
s.reload
|
|
expect(s.merged_into_story).to eq(story)
|
|
|
|
ml = Moderation.last
|
|
expect(ml.story).to eq(s)
|
|
expect(ml.reason).to eq('cuz')
|
|
end
|
|
|
|
it "can't be done by submitter" do
|
|
sign_in user
|
|
|
|
s = create(:story)
|
|
put "/stories/#{s.short_id}",
|
|
params: {
|
|
story: {
|
|
merge_story_short_id: story.short_id,
|
|
moderation_reason: 'anarchy!',
|
|
},
|
|
}
|
|
expect(response).to be_redirect
|
|
s.reload
|
|
expect(s.merged_into_story).to be_nil
|
|
end
|
|
end
|
|
|
|
describe "show" do
|
|
it "displays a story" do
|
|
story = create(:story)
|
|
get story_path(story)
|
|
|
|
expect(response).to be_successful
|
|
expect(response.body).to include(story.title)
|
|
end
|
|
|
|
context "story removed by submitter" do
|
|
let(:story) { create(:story, is_deleted: false) }
|
|
|
|
# feels brittle to copy StoriesController and keep leaning on the
|
|
# log_moderation callback but too big a refactor right now
|
|
before do
|
|
story.is_deleted = true
|
|
story.editor = story.user
|
|
story.save!
|
|
end
|
|
|
|
it "404s to logged-out visitor" do
|
|
get story_path(story)
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to_not include(story.title)
|
|
expect(response.body).to_not include('removed by moderator')
|
|
expect(response.body).to_not include('removed by submitter')
|
|
expect(response.body).to_not include(story.user.username)
|
|
end
|
|
|
|
it "shows submitter removed to logged-in user" do
|
|
sign_in create(:user)
|
|
get story_path(story)
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to_not include(story.title)
|
|
expect(response.body).to include('removed by submitter')
|
|
expect(response.body).to include(story.user.username)
|
|
end
|
|
end
|
|
|
|
context "story removed by moderator" do
|
|
let(:story) { create(:story, is_deleted: false) }
|
|
let(:mod) { create(:user, :moderator) }
|
|
let(:reason) { "Unacceptably low ratio of cat photos to words." }
|
|
|
|
# feels brittle to copy StoriesController and keep leaning on the
|
|
# log_moderation callback but too big a refactor right now
|
|
before do
|
|
story.moderation_reason = reason
|
|
story.is_deleted = true
|
|
story.editor = mod
|
|
story.save!
|
|
end
|
|
|
|
it "404s to logged-out visitor" do
|
|
get story_path(story)
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to_not include(story.title)
|
|
expect(response.body).to_not include(reason)
|
|
expect(response.body).to_not include('removed by submitter')
|
|
expect(response.body).to_not include(story.user.username)
|
|
end
|
|
|
|
it "shows mod log to logged-in user" do
|
|
sign_in create(:user)
|
|
get story_path(story)
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to_not include(story.title)
|
|
expect(response.body).to include(reason)
|
|
end
|
|
end
|
|
|
|
context "json" do
|
|
let(:headers) { { 'Content-Type' => 'application/json', 'Accept' => 'application/json' } }
|
|
|
|
context "for a story that merged into another story" do
|
|
let(:merged_into_story) { create(:story) }
|
|
let(:story) { create(:story, merged_into_story: merged_into_story) }
|
|
|
|
it "redirects to the merged story's json" do
|
|
get "/stories/#{story.short_id}",
|
|
headers: headers
|
|
expect(response).to redirect_to(action: :show,
|
|
id: merged_into_story.short_id,
|
|
format: :json)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "upvoting" do
|
|
let(:target) { create(:story) }
|
|
|
|
before { sign_in user }
|
|
|
|
it 'works' do
|
|
expect {
|
|
post "/stories/#{target.short_id}/upvote"
|
|
expect(response.status).to eq(200)
|
|
}.to change { target.reload.score }.by(1)
|
|
expect(Vote.where(user: user).count).to eq(1)
|
|
end
|
|
|
|
it 'does nothing to deleted comments' do
|
|
expect {
|
|
target.is_deleted = true
|
|
target.editor = target.user
|
|
target.save!
|
|
|
|
post "/stories/#{target.short_id}/upvote"
|
|
expect(response.status).to eq(400)
|
|
}.to change { target.reload.score }.by(0)
|
|
expect(Vote.where(user: user).count).to eq(0)
|
|
end
|
|
end
|
|
end
|