otwarchive-symphonyarchive/spec/controllers/works/default_rails_actions_spec.rb
2026-03-11 22:22:11 +00:00

940 lines
34 KiB
Ruby

# frozen_string_literal: true
require "spec_helper"
describe WorksController, work_search: true do
include LoginMacros
include RedirectExpectationHelper
let(:banned_user) { create(:user, banned: true) }
let(:banned_users_work) do
banned_user.update!(banned: false)
work = create(:work, authors: [banned_user.pseuds.first])
banned_user.update!(banned: true)
work
end
let(:suspended_user) { create(:user, suspended: true, suspended_until: 1.week.from_now) }
let(:suspended_users_work) do
suspended_user.update!(suspended: false, suspended_until: nil)
work = create(:work, authors: [suspended_user.pseuds.first])
suspended_user.update!(suspended: true, suspended_until: 1.week.from_now)
work
end
describe "before_action #clean_work_search_params" do
let(:params) { {} }
def call_with_params(params)
controller.params = { work_search: params }
controller.params[:work_search] = controller.clean_work_search_params
end
context "when no work search parameters are given" do
it "redirects to the login screen when no user is logged in" do
get :clean_work_search_params, params: params
it_redirects_to_with_error(new_user_session_path,
"Sorry, you don't have permission to access the page you were trying to reach. Please log in.")
end
end
context "when the query contains countable search parameters" do
it "escapes less and greater than in query" do
[
{ params: "< 5 words", expected: "&lt; 5 words", message: "Should escape <" },
{ params: "> 5 words", expected: "&gt; 5 words", message: "Should escape >" },
].each do |settings|
call_with_params(query: settings[:params])
expect(controller.params[:work_search][:query])
.to eq(settings[:expected]), settings[:message]
end
end
it "converts 'word' to 'word_count'" do
call_with_params(query: "word:6")
expect(controller.params[:work_search][:word_count]).to eq("6")
end
it "converts 'words' to 'word_count'" do
call_with_params(query: "words:7")
expect(controller.params[:work_search][:word_count]).to eq("7")
end
it "converts 'hits' queries to 'hits'" do
call_with_params(query: "hits:8")
expect(controller.params[:work_search][:hits]).to eq("8")
end
it "converts other queries to (pluralized term)_count" do
%w(kudo comment bookmark).each do |term|
call_with_params(query: "#{term}:9")
expect(controller.params[:work_search]["#{term.pluralize}_count"])
.to eq("9"), "Search term '#{term}' should become #{term.pluralize}_count key"
end
end
end
context "when sort parameters are provided" do
it "converts variations on 'sorted by: X' into :sort_column key" do
[
"sort by: words",
"sorted by: words",
"sorted: words",
"sort: words",
"sort by < words",
"sort by > words",
"sort by = words"
].each do |query|
call_with_params(query: query)
expect(controller.params[:work_search][:sort_column])
.to eq("word_count"), "Sort command '#{query}' should be converted to :sort_column"
end
end
it "converts variations on sort columns to column name" do
[
{ query: "sort by: word count", expected: "word_count" },
{ query: "sort by: words", expected: "word_count" },
{ query: "sort by: word", expected: "word_count" },
{ query: "sort by: creator", expected: "authors_to_sort_on" },
{ query: "sort by: title", expected: "title_to_sort_on" },
{ query: "sort by: date", expected: "created_at" },
{ query: "sort by: date posted", expected: "created_at" },
{ query: "sort by: hits", expected: "hits" },
{ query: "sort by: kudos", expected: "kudos_count" },
{ query: "sort by: comments", expected: "comments_count" },
{ query: "sort by: bookmarks", expected: "bookmarks_count" },
].each do |settings|
call_with_params(query: settings[:query])
actual = controller.params[:work_search][:sort_column]
expect(actual)
.to eq(settings[:expected]),
"Query '#{settings[:query]}' should be converted to :sort_column '#{settings[:expected]}' but is '#{actual}'"
end
end
it "converts 'ascending' or '>' into :sort_direction key 'asc'" do
[
"sort > word_count",
"sort: word_count ascending",
"sort: hits ascending",
].each do |query|
call_with_params(query: query)
expect(controller.params[:work_search][:sort_direction]).to eq("asc")
end
end
it "converts 'descending' or '<' into :sort_direction key 'desc'" do
[
"sort < word_count",
"sort: word_count descending",
"sort: hits descending",
].each do |query|
call_with_params(query: query)
expect(controller.params[:work_search][:sort_direction]).to eq("desc")
end
end
# The rest of these are probably bugs
it "returns no sort column if there is NO punctuation after 'sort by' clause" do
call_with_params(query: "sort by word count")
expect(controller.params[:work_search][:sort_column]).to be_nil
end
it "can't search by date updated" do
[
{ query: "sort by: date updated", expected: "revised_at" },
].each do |settings|
call_with_params(query: settings[:query])
expect(controller.params[:work_search][:sort_column]).to eq("created_at") # should be revised_at
end
end
it "can't sort ascending if more than one word follows the colon" do
[
"sort by: word count ascending",
].each do |query|
call_with_params(query: query)
expect(controller.params[:work_search][:sort_direction]).to be_nil
end
end
end
context "when the query contains categories" do
it "surrounds categories in quotes" do
[
{ query: "M/F sort by: comments", expected: "\"m/f\"" },
{ query: "f/f Scully/Reyes", expected: "\"f/f\" Scully/Reyes" },
].each do |settings|
call_with_params(query: settings[:query])
expect(controller.params[:work_search][:query]).to eq(settings[:expected])
end
end
it "does not surround categories in quotes when it shouldn't" do
query = "sam/frodo sort by: word"
call_with_params(query: query)
expect(controller.params[:work_search][:query]).to eq("sam/frodo")
end
end
end
describe "new" do
it "doesn't return the form for anyone not logged in" do
get :new
it_redirects_to_with_error(new_user_session_path,
"Sorry, you don't have permission to access the page you were trying to reach. Please log in.")
end
it "renders the form if logged in" do
fake_login
get :new
expect(response).to render_template("new")
end
it "errors and redirects to user page when user is banned" do
fake_login_known_user(banned_user)
get :new
it_redirects_to_simple(user_path(banned_user))
expect(flash[:error]).to include("Your account has been banned.")
end
end
describe "create" do
let(:user) { create(:user) }
before { fake_login_known_user(user) }
it "doesn't allow a user to create a work in a series that they don't own" do
@series = create(:series)
work_attributes = attributes_for(:work).except(:posted)
work_attributes[:series_attributes] = { id: @series.id }
expect {
post :create, params: { work: work_attributes }
}.not_to change { @series.works.all.count }
expect(response).to render_template :new
expect(assigns[:work].errors.full_messages).to \
include("You can't add a work to that series.")
end
it "doesn't allow a user to submit only a pseud that is not theirs" do
user2 = create(:user)
work_attributes = attributes_for(:work).except(:posted)
work_attributes[:author_attributes] = { ids: [user2.pseuds.first.id] }
expect {
post :create, params: { work: work_attributes }
}.to_not change(Work, :count)
expect(response).to render_template("new")
expect(assigns[:work].errors.full_messages).to \
include "You're not allowed to use that pseud."
end
it "renders new if the work has invalid pseuds" do
work_attributes = attributes_for(:work).except(:posted)
work_attributes[:author_attributes] = { ids: user.pseud_ids,
byline: "*impossible*" }
post :create, params: { work: work_attributes }
expect(response).to render_template("new")
expect(assigns[:work].errors.full_messages).to \
include "Invalid creator: Could not find a pseud *impossible*."
end
it "renders new if the work has ambiguous pseuds" do
create(:pseud, name: "ambiguous")
create(:pseud, name: "ambiguous")
work_attributes = attributes_for(:work).except(:posted)
work_attributes[:author_attributes] = { ids: user.pseud_ids,
byline: "ambiguous" }
post :create, params: { work: work_attributes }
expect(response).to render_template("new")
expect(assigns[:work].errors.full_messages).to \
include "Invalid creator: The pseud ambiguous is ambiguous."
end
it "renders new if the work has noncanonical warnings" do
work_attributes = attributes_for(:work).except(:posted, :archive_warning_string).merge(archive_warning_string: "Warning")
post :create, params: { work: work_attributes }
expect(response).to render_template("new")
expect(assigns[:work].errors.full_messages).to \
include /Only canonical warning tags are allowed./
end
it "renders new if the work has noncanonical rating" do
work_attributes = attributes_for(:work).except(:posted, :rating_string).merge(rating_string: "Rating")
post :create, params: { work: work_attributes }
expect(response).to render_template("new")
expect(assigns[:work].errors.full_messages).to \
include /Only canonical rating tags are allowed./
end
it "renders new if the work has noncanonical category" do
work_attributes = attributes_for(:work).except(:posted).merge(category_strings: ["Category"])
post :create, params: { work: work_attributes }
expect(response).to render_template("new")
expect(assigns[:work].errors.full_messages).to \
include /Only canonical category tags are allowed./
end
context "as a tag wrangler" do
let(:user) { create(:tag_wrangler) }
it "does not set wrangling activity when posting with a new fandom" do
work_attributes = attributes_for(:work).except(:posted, :fandom_string).merge(fandom_string: "New Fandom")
post :create, params: { work: work_attributes }
expect(user.last_wrangling_activity).to be_nil
end
it "does not set wrangling activity when posting with an unsorted tag" do
tag = create(:unsorted_tag)
work_attributes = attributes_for(:work).except(:posted, :freeform_string).merge(freeform_string: tag.name)
post :create, params: { work: work_attributes }
expect(user.last_wrangling_activity).to be_nil
end
end
it "errors and redirects to user page when user is banned" do
fake_login_known_user(banned_user)
tag = create(:unsorted_tag)
work_attributes = attributes_for(:work).except(:posted, :freeform_string).merge(freeform_string: tag.name)
post :create, params: { work: work_attributes }
it_redirects_to_simple(user_path(banned_user))
expect(flash[:error]).to include("Your account has been banned.")
end
end
describe "show" do
let(:work) { create(:work) }
it "doesn't error when a work has no fandoms" do
work_no_fandoms = build(:work, fandom_string: "")
work_no_fandoms.save!(validate: false)
fake_login
get :show, params: { id: work_no_fandoms.id }
expect(assigns(:page_title)).to include "No fandom specified"
end
it "assigns @page_subtitle with unrevealed work and not @page_title" do
work.update!(in_unrevealed_collection: true)
get :show, params: { id: work.id }
expect(assigns[:page_subtitle]).to eq("Mystery Work")
expect(assigns[:page_title]).to be_nil
end
context "when work does not exist" do
it "raises an error" do
expect do
get :show, params: { id: "999999999" }
end.to raise_error ActiveRecord::RecordNotFound
end
end
end
describe "share" do
it "returns a 404 response for unrevealed works" do
unrevealed_collection = create :unrevealed_collection
unrevealed_work = create :work, collections: [unrevealed_collection]
get :share, params: { id: unrevealed_work.id }, xhr: true
expect(response.status).to eq(404)
end
it "redirects to referer with an error for non-ajax warnings requests" do
work = create(:work)
referer = work_path(work)
request.headers["HTTP_REFERER"] = referer
get :share, params: { id: work.id }
it_redirects_to_with_error(referer, "Sorry, you need to have JavaScript enabled for this.")
end
end
describe "index" do
before do
@fandom = create(:canonical_fandom)
@work = create(:work, fandom_string: @fandom.name)
end
it "returns the work" do
get :index
expect(assigns(:works)).to include(@work)
end
it "sets the fandom when given a fandom id" do
params = { fandom_id: @fandom.id }
get :index, params: params
expect(assigns(:fandom)).to eq(@fandom)
end
describe "when the fandom id is invalid" do
it "raises a 404 for an invalid id" do
params = { fandom_id: 0 }
expect { get :index, params: params }
.to raise_error ActiveRecord::RecordNotFound
end
end
describe "when the fandom id is empty" do
it "returns the work" do
params = { fandom_id: nil }
get :index, params: params
expect(assigns(:works)).to include(@work)
end
end
describe "without caching" do
before do
AdminSetting.first.update_attribute(:enable_test_caching, false)
end
it "returns the result with different works the second time" do
get :index
expect(assigns(:works)).to include(@work)
work2 = create(:work)
get :index
expect(assigns(:works)).to include(work2)
end
end
describe "with caching" do
before do
AdminSetting.first.update_attribute(:enable_test_caching, true)
end
context "with NO owner tag" do
it "returns the same result the second time when a new work is created within the expiration time" do
get :index
expect(assigns(:works)).to include(@work)
work2 = create(:work)
run_all_indexing_jobs
get :index
expect(assigns(:works)).not_to include(work2)
end
end
context "with a valid owner tag" do
before do
@fandom2 = create(:canonical_fandom)
@work2 = create(:work, fandom_string: @fandom2.name)
run_all_indexing_jobs
end
it "only gets works under that tag" do
get :index, params: { tag_id: @fandom.name }
expect(assigns(:works).items).to include(@work)
expect(assigns(:works).items).not_to include(@work2)
end
it "shows different results on second page" do
get :index, params: { tag_id: @fandom.name, page: 2 }
expect(assigns(:works).items).not_to include(@work)
end
context "with restricted works" do
before do
@work2 = create(:work, fandom_string: @fandom.name, restricted: true)
run_all_indexing_jobs
end
it "shows restricted works to guests" do
get :index, params: { tag_id: @fandom.name }
expect(assigns(:works).items).to include(@work)
expect(assigns(:works).items).not_to include(@work2)
end
end
context "when tag is a synonym" do
let(:fandom_synonym) { create(:fandom, merger: @fandom) }
it "redirects to the merger's work index" do
params = { tag_id: fandom_synonym.name }
get :index, params: params
it_redirects_to tag_works_path(@fandom)
end
context "when collection is specified" do
let(:collection) { create(:collection) }
it "redirects to the merger's collection works index" do
params = { tag_id: fandom_synonym.name, collection_id: collection.name }
get :index, params: params
it_redirects_to collection_tag_works_path(collection, @fandom)
end
end
end
end
end
context "with an invalid owner tag" do
it "raises an error" do
params = { tag_id: "nonexistent_tag" }
expect { get :index, params: params }.to raise_error(
ActiveRecord::RecordNotFound,
"Couldn't find tag named 'nonexistent_tag'"
)
end
end
context "with an invalid owner user" do
it "raises an error" do
params = { user_id: "nonexistent_user" }
expect { get :index, params: params }.to raise_error(
ActiveRecord::RecordNotFound
)
end
context "with an invalid pseud" do
it "raises an error" do
params = { user_id: "nonexistent_user", pseud_id: "nonexistent_pseud" }
expect { get :index, params: params }.to raise_error(
ActiveRecord::RecordNotFound
)
end
end
end
context "with a valid owner user" do
let(:user) { create(:user) }
let!(:user_work) { create(:work, authors: [user.default_pseud]) }
let(:pseud) { create(:pseud, user: user) }
let!(:pseud_work) { create(:work, authors: [pseud]) }
before { run_all_indexing_jobs }
it "includes only works for that user" do
params = { user_id: user.login }
get :index, params: params
expect(assigns(:works).items).to include(user_work, pseud_work)
expect(assigns(:works).items).not_to include(@work)
end
context "with a valid pseud" do
it "includes only works for that pseud" do
params = { user_id: user.login, pseud_id: pseud.name }
get :index, params: params
expect(assigns(:works).items).to include(pseud_work)
expect(assigns(:works).items).not_to include(user_work, @work)
end
end
context "with an invalid pseud" do
it "includes all of that user's works" do
params = { user_id: user.login, pseud_id: "nonexistent_pseud" }
get :index, params: params
expect(assigns(:works).items).to include(user_work, pseud_work)
expect(assigns(:works).items).not_to include(@work)
end
end
end
end
describe "update" do
let(:update_user) { create(:user) }
let(:update_work) {
work = create(:work, authors: [update_user.default_pseud])
create(:chapter, work: work)
work
}
before do
fake_login_known_user(update_user)
end
it "doesn't allow the user to add a series that they don't own" do
@series = create(:series)
attrs = { series_attributes: { id: @series.id } }
expect {
put :update, params: { id: update_work.id, work: attrs }
}.not_to change { @series.works.all.count }
expect(response).to render_template :edit
expect(assigns[:work].errors.full_messages).to \
include("You can't add a work to that series.")
end
it "redirects to the edit page if the work could not be saved" do
allow_any_instance_of(Work).to receive(:save).and_return(false)
update_work.fandom_string = "Testing"
attrs = { title: "New Work Title" }
put :update, params: { id: update_work.id, work: attrs }
expect(response).to render_template :edit
allow_any_instance_of(Work).to receive(:save).and_call_original
end
it "updates the editor's pseuds for all chapters" do
new_pseud = create(:pseud, user: update_user)
put :update, params: { id: update_work.id, work: { author_attributes: { ids: [new_pseud.id] } } }
expect(update_work.pseuds.reload).to contain_exactly(new_pseud)
update_work.chapters.reload.each do |c|
expect(c.pseuds.reload).to contain_exactly(new_pseud)
end
end
it "allows the user to invite co-creators" do
co_creator = create(:user)
co_creator.preference.update!(allow_cocreator: true)
put :update, params: { id: update_work.id, work: { author_attributes: { byline: co_creator.login } } }
expect(update_work.pseuds.reload).not_to include(co_creator.default_pseud)
expect(update_work.user_has_creator_invite?(co_creator)).to be_truthy
end
it "prevents inviting users who have disallowed co-creators" do
no_co_creator = create(:user)
no_co_creator.preference.update!(allow_cocreator: false)
put :update, params: { id: update_work.id, work: { author_attributes: { byline: no_co_creator.login } } }
expect(response).to render_template :edit
expect(assigns[:work].errors.full_messages).to \
include "Invalid creator: #{no_co_creator.login} does not allow others to invite them to be a co-creator."
expect(update_work.pseuds.reload).not_to include(no_co_creator.default_pseud)
expect(update_work.user_has_creator_invite?(no_co_creator)).to be_falsey
end
context "when the work has broken dates" do
let(:update_work) { create(:work, authors: [update_user.default_pseud]) }
let(:update_chapter) { update_work.first_chapter }
let(:attributes) do
{
backdate: "1",
chapter_attributes: {
published_at: "2021-09-01"
}
}
end
before do
# Work where chapter published_at did not override revised_at, times
# taken from AO3-5392
update_work.update_column(:revised_at, Time.new(2018, 4, 22, 23, 51, 42, "+04:00"))
update_chapter.update_column(:published_at, Date.new(2015, 7, 23))
end
it "can be backdated" do
put :update, params: { id: update_work.id, work: attributes }
expect(update_chapter.reload.published_at).to eq(Date.new(2021, 9, 1))
expect(update_work.reload.revised_at).to eq(Time.utc(2021, 9, 1, 12)) # noon UTC
end
end
# If the time zone in config/application.rb is changed to something other
# than the default (UTC), these tests will need adjusting:
context "when redating to the present" do
let!(:update_work) do
# November 30, 2 PM UTC -- no time zone oddities here
travel_to(Time.utc(2021, 11, 30, 14)) do
create(:work, authors: [update_user.default_pseud])
end
end
let(:attributes) do
{
backdate: "1",
chapter_attributes: {
published_at: "2021-12-05"
}
}
end
before do
travel_to(redate_time)
# Simulate the system time being UTC:
allow(Time).to receive(:now).and_return(redate_time)
allow(DateTime).to receive(:now).and_return(redate_time)
allow(Date).to receive(:today).and_return(redate_time.to_date)
put :update, params: { id: update_work.id, work: attributes }
end
context "before midnight UTC and after midnight Samara" do
# December 5, 3 AM Europe/Samara (UTC+04:00) -- still December 4 in UTC
let(:redate_time) { Time.new(2021, 12, 5, 3, 0, 0, "+04:00") }
it "prevents setting the publication date to the future" do
expect(response).to render_template :edit
expect(assigns[:work].errors.full_messages).to \
include("Publication date can't be in the future.")
end
end
context "before noon UTC" do
# December 5, 6 AM Europe/Samara -- before noon, but after midnight in both time zones
let(:redate_time) { Time.new(2021, 12, 5, 6, 0, 0, "+04:00") }
it "doesn't set revised_at to the future" do
update_work.reload
expect(update_work.revised_at).to be <= Time.current
end
end
end
it "errors and redirects to user page when user is banned" do
fake_login_known_user(banned_user)
attrs = { title: "New Work Title" }
put :update, params: { id: banned_users_work.id, work: attrs }
it_redirects_to_simple(user_path(banned_user))
expect(flash[:error]).to include("Your account has been banned.")
end
end
describe "collected" do
let(:collection) { create(:collection) }
let(:collected_user) { create(:user) }
it "returns not found error if user does not exist" do
expect do
get :collected, params: { user_id: "dummyuser" }
end.to raise_error(ActiveRecord::RecordNotFound)
end
it "returns not found error if no user is set" do
expect do
get :collected
end.to raise_error(ActiveRecord::RecordNotFound)
end
context "with anonymous works" do
let(:anonymous_collection) { create(:anonymous_collection) }
let!(:work) do
create(:work,
authors: [collected_user.default_pseud],
collection_names: collection.name)
end
let!(:anonymous_work) do
create(:work,
authors: [collected_user.default_pseud],
collection_names: anonymous_collection.name)
end
before { run_all_indexing_jobs }
it "does not return anonymous works in collections for guests" do
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(work)
expect(assigns(:works)).not_to include(anonymous_work)
end
it "does not return anonymous works in collections for logged-in users" do
fake_login
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(work)
expect(assigns(:works)).not_to include(anonymous_work)
end
it "returns anonymous works in collections for the author" do
fake_login_known_user(collected_user)
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(work, anonymous_work)
end
end
context "with restricted works" do
let(:collected_fandom) { create(:canonical_fandom) }
let(:collected_fandom_2) { create(:canonical_fandom) }
let!(:unrestricted_work) do
create(:work,
authors: [collected_user.default_pseud],
fandom_string: collected_fandom.name)
end
let!(:unrestricted_work_in_collection) do
create(:work,
authors: [collected_user.default_pseud],
collection_names: collection.name,
fandom_string: collected_fandom.name)
end
let!(:unrestricted_work_2_in_collection) do
create(:work,
authors: [collected_user.default_pseud],
collection_names: collection.name,
fandom_string: collected_fandom_2.name)
end
let!(:restricted_work_in_collection) do
create(:work,
restricted: true,
authors: [collected_user.default_pseud],
collection_names: collection.name,
fandom_string: collected_fandom.name)
end
before { run_all_indexing_jobs }
context "as a guest" do
it "renders the collected form" do
get :collected, params: { user_id: collected_user.login }
expect(response).to render_template("collected")
end
it "returns ONLY unrestricted works in collections" do
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(unrestricted_work_in_collection, unrestricted_work_2_in_collection)
expect(assigns(:works)).not_to include(unrestricted_work, restricted_work_in_collection)
end
it "returns filtered works when search parameters are provided" do
get :collected, params: { user_id: collected_user.login, work_search: { query: "fandom_ids:#{collected_fandom_2.id}" }}
expect(assigns(:works)).to include(unrestricted_work_2_in_collection)
expect(assigns(:works)).not_to include(unrestricted_work_in_collection)
end
end
context "with a logged-in user" do
before { fake_login }
it "returns ONLY works in collections" do
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(unrestricted_work_in_collection, restricted_work_in_collection)
expect(assigns(:works)).not_to include(unrestricted_work)
end
end
end
context "with unrevealed works" do
let(:unrevealed_collection) { create(:unrevealed_collection) }
let!(:work) do
create(:work,
authors: [collected_user.default_pseud],
collection_names: collection.name)
end
let!(:unrevealed_work) do
create(:work,
authors: [collected_user.default_pseud],
collection_names: unrevealed_collection.name)
end
before { run_all_indexing_jobs }
it "doesn't return unrevealed works in collections for guests" do
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(work)
expect(assigns(:works)).not_to include(unrevealed_work)
end
it "doesn't return unrevealed works in collections for logged-in users" do
fake_login
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(work)
expect(assigns(:works)).not_to include(unrevealed_work)
end
it "returns unrevealed works in collections for the author" do
fake_login_known_user(collected_user)
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works)).to include(work, unrevealed_work)
end
end
context "with sorting options" do
let!(:new_work) do
create(:work,
title: "New Title",
authors: [collected_user.default_pseud],
collection_names: collection.name,
created_at: 3.days.ago,
revised_at: 3.days.ago)
end
let!(:old_work) do
create(:work,
title: "Old Title",
authors: [collected_user.default_pseud],
collection_names: collection.name,
created_at: 30.days.ago,
revised_at: 30.days.ago)
end
let!(:revised_work) do
create(:work,
title: "Revised Title",
authors: [collected_user.default_pseud],
collection_names: collection.name,
created_at: 20.days.ago,
revised_at: 2.days.ago)
end
before { run_all_indexing_jobs }
it "sorts by date" do
get :collected, params: { user_id: collected_user.login }
expect(assigns(:works).map(&:title)).to eq([revised_work, new_work, old_work].map(&:title))
get :collected, params: { user_id: collected_user.login, work_search: { sort_direction: "asc" } }
expect(assigns(:works).map(&:title)).to eq([old_work, new_work, revised_work].map(&:title))
end
it "sorts by title" do
get :collected, params: { user_id: collected_user.login, work_search: { sort_column: "title_to_sort_on" } }
expect(assigns(:works).map(&:title)).to eq([new_work, old_work, revised_work].map(&:title))
get :collected, params: { user_id: collected_user.login, work_search: { sort_column: "title_to_sort_on", sort_direction: "desc" } }
expect(assigns(:works).map(&:title)).to eq([revised_work, old_work, new_work].map(&:title))
end
end
end
describe "destroy" do
let(:work) { create(:work) }
let(:work_title) { work.title }
context "when a work has consecutive deleted comments in a thread" do
before do
thread_depth = 4
chapter = work.first_chapter
commentable = chapter
comments = []
thread_depth.times do
commentable = create(:comment, commentable: commentable, parent: chapter)
comments << commentable
end
# Delete all but the last comment in the thread.
# We should have (thread_depth - 1) consecutive deleted comment placeholders.
comments.reverse.drop(1).each(&:destroy_or_mark_deleted)
fake_login_known_user(work.users.first)
end
it "deletes the work and redirects to the user's works with a notice" do
delete :destroy, params: { id: work.id }
it_redirects_to_with_notice(user_works_path(controller.current_user), "Your work #{work_title} was deleted.")
expect { work.reload }.to raise_exception(ActiveRecord::RecordNotFound)
expect(Comment.count).to eq(0)
end
end
context "when a logged in user is suspended" do
before do
fake_login_known_user(suspended_user)
end
it "errors and redirects to user page" do
fake_login_known_user(suspended_user)
delete :destroy, params: { id: suspended_users_work.id }
it_redirects_to_simple(user_path(suspended_user))
expect(flash[:error]).to include("Your account has been suspended")
end
end
context "when a logged in user is banned" do
before do
fake_login_known_user(banned_user)
end
it "deletes the work and redirects to the user's works with a notice" do
delete :destroy, params: { id: banned_users_work.id }
it_redirects_to_with_notice(user_works_path(controller.current_user), "Your work #{banned_users_work.title} was deleted.")
expect { banned_users_work.reload }
.to raise_exception(ActiveRecord::RecordNotFound)
end
end
end
end