forked from e621ng/e621ng

This will apply to all automated changes, though I think only implications really need it.
2272 lines
78 KiB
Ruby
2272 lines
78 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "test_helper"
|
|
|
|
class PostTest < ActiveSupport::TestCase
|
|
def assert_tag_match(posts, query)
|
|
assert_equal(posts.map(&:id), Post.tag_match(query).pluck(:id))
|
|
end
|
|
|
|
setup do
|
|
@user = create(:user, created_at: 2.weeks.ago)
|
|
CurrentUser.user = @user
|
|
reset_post_index
|
|
end
|
|
|
|
context "Deletion:" do
|
|
context "Expunging a post" do
|
|
# That belonged in a museum!
|
|
setup do
|
|
@upload = UploadService.new(attributes_for(:jpg_upload).merge({ uploader: @user })).start!
|
|
@post = @upload.post
|
|
FavoriteManager.add!(user: @post.uploader, post: @post)
|
|
end
|
|
|
|
should "delete the files" do
|
|
assert_nothing_raised { @post.file(:preview) }
|
|
assert_nothing_raised { @post.file(:original) }
|
|
|
|
@post.expunge!
|
|
|
|
assert_raise(StandardError) { @post.file(:preview) }
|
|
assert_raise(StandardError) { @post.file(:original) }
|
|
end
|
|
|
|
should "remove all favorites" do
|
|
@post.expunge!
|
|
|
|
assert_equal(0, Favorite.for_user(@post.uploader_id).where("post_id = ?", @post.id).count)
|
|
end
|
|
|
|
should "decrement the uploader's upload count" do
|
|
assert_difference("@post.uploader.reload.post_upload_count", -1) do
|
|
@post.expunge!
|
|
end
|
|
end
|
|
|
|
should "decrement the user's note update count" do
|
|
create(:note, post: @post)
|
|
assert_difference(["@post.uploader.reload.note_update_count"], -1) do
|
|
@post.expunge!
|
|
end
|
|
end
|
|
|
|
should "decrement the user's post update count" do
|
|
assert_difference(["@post.uploader.reload.post_update_count"], -1) do
|
|
@post.expunge!
|
|
end
|
|
end
|
|
|
|
should "decrement the user's favorite count" do
|
|
assert_difference(["@post.uploader.reload.favorite_count"], -1) do
|
|
@post.expunge!
|
|
end
|
|
end
|
|
|
|
should "remove the post from iqdb" do
|
|
@post.expects(:remove_iqdb_async).once
|
|
@post.expunge!
|
|
end
|
|
|
|
context "that is status locked" do
|
|
setup do
|
|
@post.update(is_status_locked: true)
|
|
end
|
|
|
|
should "not destroy the record" do
|
|
@post.expunge!
|
|
assert_equal(1, Post.where("id = ?", @post.id).count)
|
|
end
|
|
end
|
|
|
|
context "that belongs to a pool" do
|
|
setup do
|
|
@pool = create(:pool)
|
|
@pool.add!(@post)
|
|
|
|
@post.expunge!
|
|
@pool.reload
|
|
end
|
|
|
|
should "remove the post from all pools" do
|
|
assert_equal([], @pool.post_ids)
|
|
end
|
|
|
|
should "destroy the record" do
|
|
assert_equal([], @post.errors.full_messages)
|
|
assert_equal(0, Post.where("id = ?", @post.id).count)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Deleting a post" do
|
|
context "that is status locked" do
|
|
setup do
|
|
@post = create(:post, is_status_locked: true)
|
|
end
|
|
|
|
should "fail" do
|
|
@post.delete!("test")
|
|
assert_equal(["Is status locked ; cannot delete post"], @post.errors.full_messages)
|
|
assert_equal(1, Post.where("id = ?", @post.id).count)
|
|
end
|
|
end
|
|
|
|
context "that is pending" do
|
|
setup do
|
|
@post = create(:post, is_pending: true)
|
|
end
|
|
|
|
should "succeed" do
|
|
@post.delete!("test")
|
|
|
|
assert_equal(true, @post.is_deleted)
|
|
assert_equal(1, @post.flags.size)
|
|
assert_match(/test/, @post.flags.last.reason)
|
|
end
|
|
end
|
|
|
|
context "that is still in cooldown after being flagged" do
|
|
should "succeed" do
|
|
flag = create(:post_flag)
|
|
assert_equal([], flag.errors.full_messages)
|
|
flag.post.delete!("test deletion")
|
|
|
|
assert_equal(true, flag.post.is_deleted)
|
|
assert_equal(2, flag.post.flags.size)
|
|
end
|
|
end
|
|
|
|
should "toggle the is_deleted flag" do
|
|
post = create(:post)
|
|
assert_equal(false, post.is_deleted?)
|
|
post.delete!("test")
|
|
assert_equal(true, post.is_deleted?)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Parent:" do
|
|
setup do
|
|
@parent = create(:post, tag_string: "a b c d", source: "a\nb\nc")
|
|
@post = create(:post, parent_id: @parent.id, tag_string: "c d e f", source: "b\nc\nd")
|
|
end
|
|
should "Copy tags to parent" do
|
|
@post.copy_tags_to_parent
|
|
@post.parent.save
|
|
assert_equal(@parent.reload.tag_string, "a b c d e f")
|
|
end
|
|
should "Copy sources to parent" do
|
|
@post.copy_sources_to_parent
|
|
@post.parent.save
|
|
assert_equal(@parent.reload.source, "a\nb\nc\nd")
|
|
end
|
|
end
|
|
|
|
context "Parenting:" do
|
|
context "Assigning a parent to a post" do
|
|
should "update the has_children flag on the parent" do
|
|
p1 = create(:post)
|
|
assert(!p1.has_children?, "Parent should not have any children")
|
|
c1 = create(:post, parent_id: p1.id)
|
|
p1.reload
|
|
assert(p1.has_children?, "Parent not updated after child was added")
|
|
end
|
|
|
|
should "update the has_children flag on the old parent" do
|
|
p1 = create(:post)
|
|
p2 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c1.parent_id = p2.id
|
|
c1.save
|
|
p1.reload
|
|
p2.reload
|
|
assert(!p1.has_children?, "Old parent should not have a child")
|
|
assert(p2.has_children?, "New parent should have a child")
|
|
end
|
|
end
|
|
|
|
context "Expunging a post with" do
|
|
context "a parent" do
|
|
should "reset the has_children flag of the parent" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c1.expunge!
|
|
p1.reload
|
|
assert_equal(false, p1.has_children?)
|
|
end
|
|
|
|
should "update the parent's has_children flag" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c1.expunge!
|
|
p1.reload
|
|
assert(!p1.has_children?, "Parent should not have children")
|
|
end
|
|
end
|
|
|
|
context "one child" do
|
|
should "remove the parent of that child" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
p1.expunge!
|
|
c1.reload
|
|
assert_nil(c1.parent)
|
|
end
|
|
end
|
|
|
|
context "two or more children" do
|
|
setup do
|
|
# ensure initial post versions won't be merged.
|
|
travel_to(1.day.ago) do
|
|
@p1 = create(:post)
|
|
@c1 = create(:post, parent_id: @p1.id)
|
|
@c2 = create(:post, parent_id: @p1.id)
|
|
@c3 = create(:post, parent_id: @p1.id)
|
|
end
|
|
end
|
|
|
|
should "reparent all children to the first child" do
|
|
@p1.expunge!
|
|
@c1.reload
|
|
@c2.reload
|
|
@c3.reload
|
|
|
|
assert_nil(@c1.parent_id)
|
|
assert_equal(@c1.id, @c2.parent_id)
|
|
assert_equal(@c1.id, @c3.parent_id)
|
|
end
|
|
|
|
should "save a post version record for each child" do
|
|
assert_difference(["@c1.versions.count", "@c2.versions.count", "@c3.versions.count"]) do
|
|
@p1.expunge!
|
|
@c1.reload
|
|
@c2.reload
|
|
@c3.reload
|
|
end
|
|
end
|
|
|
|
should "set the has_children flag on the new parent" do
|
|
@p1.expunge!
|
|
assert_equal(true, @c1.reload.has_children?)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Deleting a post with" do
|
|
context "a parent" do
|
|
should "not reassign favorites to the parent by default" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
user = create(:privileged_user)
|
|
FavoriteManager.add!(user: user, post: c1)
|
|
c1.delete!("test")
|
|
p1.reload
|
|
assert(Favorite.exists?(:post_id => c1.id, :user_id => user.id))
|
|
assert(!Favorite.exists?(:post_id => p1.id, :user_id => user.id))
|
|
end
|
|
|
|
should "reassign favorites to the parent if specified" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
user = create(:privileged_user)
|
|
FavoriteManager.add!(user: user, post: c1)
|
|
with_inline_jobs { c1.delete!("test", move_favorites: true) }
|
|
p1.reload
|
|
assert(!Favorite.exists?(:post_id => c1.id, :user_id => user.id), "Child should not still have favorites")
|
|
assert(Favorite.exists?(:post_id => p1.id, :user_id => user.id), "Parent should have favorites")
|
|
end
|
|
|
|
should "not update the parent's has_children flag" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c1.delete!("test")
|
|
p1.reload
|
|
assert(p1.has_children?, "Parent should have children")
|
|
end
|
|
|
|
should "clear the has_active_children flag when the 'move favorites' option is set" do
|
|
user = create(:privileged_user)
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
FavoriteManager.add!(user: user, post: c1)
|
|
|
|
assert_equal(true, p1.reload.has_active_children?)
|
|
c1.delete!("test", :move_favorites => true)
|
|
assert_equal(false, p1.reload.has_active_children?)
|
|
end
|
|
end
|
|
|
|
context "one child" do
|
|
should "not remove the has_children flag" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
p1.delete!("test")
|
|
p1.reload
|
|
assert_equal(true, p1.has_children?)
|
|
end
|
|
|
|
should "not remove the parent of that child" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
p1.delete!("test")
|
|
c1.reload
|
|
assert_not_nil(c1.parent)
|
|
end
|
|
end
|
|
|
|
context "two or more children" do
|
|
should "not reparent all children to the first child" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c2 = create(:post, parent_id: p1.id)
|
|
c3 = create(:post, parent_id: p1.id)
|
|
p1.delete!("test")
|
|
c1.reload
|
|
c2.reload
|
|
c3.reload
|
|
assert_equal(p1.id, c1.parent_id)
|
|
assert_equal(p1.id, c2.parent_id)
|
|
assert_equal(p1.id, c3.parent_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Undeleting a post with a parent" do
|
|
should "update with a new approver" do
|
|
new_user = create(:moderator_user)
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c1.delete!("test")
|
|
as(new_user) do
|
|
c1.undelete!
|
|
end
|
|
p1.reload
|
|
assert_equal(new_user.id, c1.approver_id)
|
|
end
|
|
|
|
should "preserve the parent's has_children flag" do
|
|
p1 = create(:post)
|
|
c1 = create(:post, parent_id: p1.id)
|
|
c1.delete!("test")
|
|
c1.undelete!
|
|
p1.reload
|
|
assert_not_nil(c1.parent_id)
|
|
assert(p1.has_children?, "Parent should have children")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Moderation:" do
|
|
context "A deleted post" do
|
|
setup do
|
|
@post = create(:post, is_deleted: true)
|
|
end
|
|
|
|
context "that is status locked" do
|
|
setup do
|
|
@post.update(is_status_locked: true)
|
|
end
|
|
|
|
should "not allow undeletion" do
|
|
@post.undelete!
|
|
assert_equal(["Is status locked ; cannot undelete post"], @post.errors.full_messages)
|
|
assert_equal(true, @post.is_deleted?)
|
|
end
|
|
end
|
|
|
|
context "when undeleted" do
|
|
should "be undeleted" do
|
|
@post.undelete!
|
|
assert_equal(false, @post.reload.is_deleted?)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "An approved post" do
|
|
should "be flagged" do
|
|
post = create(:post)
|
|
assert_difference(-> { PostFlag.count }, 1) do
|
|
create(:post_flag, post: post)
|
|
end
|
|
assert(post.is_flagged?, "Post should be flagged.")
|
|
assert_equal(1, post.flags.count)
|
|
end
|
|
|
|
should "not be flagged if no reason is given" do
|
|
post = create(:post)
|
|
assert_no_difference(-> { PostFlag.count }) do
|
|
post.flags.create(reason_name: "")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "An unapproved post" do
|
|
should "preserve the approver's identity when approved" do
|
|
post = create(:post, is_pending: true)
|
|
post.approve!
|
|
assert_equal(post.approver_id, CurrentUser.id)
|
|
end
|
|
|
|
context "that was previously approved by person X" do
|
|
setup do
|
|
@user = create(:moderator_user, name: "xxx")
|
|
@user2 = create(:moderator_user, name: "yyy")
|
|
@post = create(:post)
|
|
@post.approve!(@user)
|
|
@post.unapprove!
|
|
end
|
|
|
|
should "allow person Y to approve the post" do
|
|
@post.approve!(@user2)
|
|
assert(@post.valid?)
|
|
end
|
|
end
|
|
|
|
context "that has been reapproved" do
|
|
setup do
|
|
@post = create(:post)
|
|
create(:post_flag, post: @post)
|
|
@post.reload
|
|
end
|
|
|
|
should "no longer be pending" do
|
|
@post.approve!
|
|
assert(@post.errors.empty?, @post.errors.full_messages.join(", "))
|
|
@post.reload
|
|
assert_equal(true, @post.is_flagged?)
|
|
assert_equal(false, @post.is_pending?)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "A status locked post" do
|
|
setup do
|
|
@post = create(:post, is_status_locked: true, is_pending: true)
|
|
end
|
|
|
|
should "not allow new flags" do
|
|
flag = build(:post_flag, post: @post)
|
|
flag.validate
|
|
assert_equal(["Post is locked and cannot be flagged"], flag.errors.full_messages)
|
|
end
|
|
|
|
should "not allow approval" do
|
|
assert_no_difference(-> { PostApproval.count }) do
|
|
@post.approve!
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Tagging:" do
|
|
context "A post" do
|
|
setup do
|
|
@post = create(:post)
|
|
end
|
|
|
|
context "as a new user" do
|
|
setup do
|
|
@post.update(:tag_string => "aaa bbb ccc ddd tagme")
|
|
CurrentUser.user = create(:user)
|
|
end
|
|
|
|
# TODO: This was moved to be a controller concern to fix issues with internal post updates
|
|
# should "not allow you to remove tags" do
|
|
# @post.update(:tag_string => "aaa")
|
|
# assert_equal(["You must have an account at least 1 week old to remove tags"], @post.errors.full_messages)
|
|
# end
|
|
|
|
should "allow you to remove request tags" do
|
|
@post.update(:tag_string => "aaa bbb ccc ddd")
|
|
@post.reload
|
|
assert_equal("aaa bbb ccc ddd", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with an artist tag that is then changed to copyright" do
|
|
setup do
|
|
CurrentUser.user = create(:janitor_user)
|
|
with_inline_jobs do
|
|
@post.update(tag_string: "art:abc")
|
|
@post.update(tag_string: "copy:abc")
|
|
end
|
|
@post.reload
|
|
end
|
|
|
|
should "update the category of the tag" do
|
|
assert_equal(Tag.categories.copyright, Tag.find_by_name("abc").category)
|
|
end
|
|
|
|
should "1234 update the category cache of the tag" do
|
|
assert_equal(Tag.categories.copyright, Cache.fetch("tc:abc"))
|
|
end
|
|
|
|
should "update the tag counts of the posts" do
|
|
assert_equal(0, @post.tag_count_artist)
|
|
assert_equal(1, @post.tag_count_copyright)
|
|
assert_equal(0, @post.tag_count_general)
|
|
end
|
|
end
|
|
|
|
context "using a tag prefix on an aliased tag" do
|
|
setup do
|
|
create(:tag_alias, antecedent_name: "abc", consequent_name: "xyz")
|
|
@post = Post.find(@post.id)
|
|
@post.update(:tag_string => "art:abc")
|
|
@post.reload
|
|
end
|
|
|
|
should "convert the tag to its normalized version" do
|
|
assert_equal("xyz", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with locked tags" do
|
|
context "without aliases or implications" do
|
|
setup do
|
|
@post = create(:post, locked_tags: "abc -what bcd -def", tag_string: "test_tag def")
|
|
end
|
|
|
|
should "contain correct tags" do
|
|
assert_equal("abc bcd test_tag", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with aliases" do
|
|
setup do
|
|
create(:tag_alias, antecedent_name: "abc", consequent_name: "xyz")
|
|
create(:tag_alias, antecedent_name: "def", consequent_name: "what")
|
|
@post = create(:post, locked_tags: "abc bcd -def", tag_string: "test_tag def what")
|
|
end
|
|
|
|
should "contain correct tags" do
|
|
assert_equal("bcd test_tag xyz", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with implications" do
|
|
should "contain correct tags" do
|
|
create(:tag_implication, antecedent_name: "specific_tag", consequent_name: "base_tag")
|
|
create(:tag_implication, antecedent_name: "female/female", consequent_name: "female")
|
|
create(:tag_implication, antecedent_name: "male/male", consequent_name: "male")
|
|
create(:tag_implication, antecedent_name: "trio", consequent_name: "group")
|
|
locked_tags = "-base_tag -female/female male/male test_tag"
|
|
tag_string = "specific_tag female/female group def"
|
|
@post = create(:post, locked_tags: locked_tags, tag_string: tag_string)
|
|
assert_equal("def group male male/male test_tag", @post.tag_string)
|
|
end
|
|
|
|
should "update the cache when implications change" do
|
|
@post = create(:post, locked_tags: "-group", tag_string: "trio specific_tag")
|
|
assert_equal("specific_tag trio", @post.tag_string)
|
|
|
|
ti = create(:tag_implication, antecedent_name: "trio", consequent_name: "group", status: "pending")
|
|
ti.approve!
|
|
create(:tag_implication, antecedent_name: "specific_tag", consequent_name: "base_tag", status: "pending")
|
|
@post.tag_string += " "
|
|
@post.save
|
|
assert_equal("specific_tag", @post.tag_string)
|
|
|
|
ti.reject!
|
|
@post.tag_string += " trio"
|
|
@post.save
|
|
assert_equal("specific_tag trio", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with dnp tags" do
|
|
should "prevent manually adding them" do
|
|
@post = create(:post, locked_tags: "", tag_string: "a b c")
|
|
@post.tag_string += " conditional_dnp"
|
|
@post.save
|
|
|
|
assert_equal("a b c", @post.tag_string)
|
|
assert_nil(@post.locked_tags)
|
|
end
|
|
|
|
should "add dnp tags through an implication" do
|
|
create(:tag_implication, antecedent_name: "artist", consequent_name: "avoid_posting")
|
|
@post = create(:post, locked_tags: "", tag_string: "a b c")
|
|
|
|
@post.tag_string += " artist"
|
|
@post.save
|
|
|
|
assert_equal("a artist avoid_posting b c", @post.tag_string)
|
|
assert_equal("avoid_posting", @post.locked_tags)
|
|
end
|
|
|
|
should "prevent removing them" do
|
|
create(:tag_implication, antecedent_name: "artist", consequent_name: "avoid_posting")
|
|
@post = create(:post, tag_string: "a artist avoid_posting b c")
|
|
|
|
@post.tag_string = "a b c"
|
|
@post.warnings.clear
|
|
@post.save
|
|
assert_match(/Forcefully added 1 locked tag: avoid_posting/, @post.warnings.full_messages.join(" "))
|
|
|
|
assert_equal("a avoid_posting b c", @post.tag_string)
|
|
end
|
|
|
|
should "not warn about dnp tags when dnp tags didn't change" do
|
|
create(:tag_implication, antecedent_name: "artist", consequent_name: "avoid_posting")
|
|
@post = create(:post, tag_string: "a artist avoid_posting b c")
|
|
|
|
@post.tag_string += "d e f"
|
|
@post.warnings.clear
|
|
@post.save
|
|
assert_no_match(/Forcefully added 1 locked tag: avoid_posting/, @post.warnings.full_messages.join(" "))
|
|
end
|
|
end
|
|
end
|
|
|
|
# TODO: Invalid tags are now reported as warnings, and don't trigger these.
|
|
# context "tagged with a valid tag" do
|
|
# subject { @post }
|
|
#
|
|
# should allow_value("touhou 100%").for(:tag_string)
|
|
# should allow_value("touhou FOO").for(:tag_string)
|
|
# should allow_value("touhou -foo").for(:tag_string)
|
|
# should allow_value("touhou pool:foo").for(:tag_string)
|
|
# should allow_value("touhou -pool:foo").for(:tag_string)
|
|
# should allow_value("touhou newpool:foo").for(:tag_string)
|
|
# should allow_value("touhou fav:self").for(:tag_string)
|
|
# should allow_value("touhou -fav:self").for(:tag_string)
|
|
# should allow_value("touhou upvote:self").for(:tag_string)
|
|
# should allow_value("touhou downvote:self").for(:tag_string)
|
|
# should allow_value("touhou parent:1").for(:tag_string)
|
|
# should allow_value("touhou child:1").for(:tag_string)
|
|
# should allow_value("touhou source:foo").for(:tag_string)
|
|
# should allow_value("touhou rating:z").for(:tag_string)
|
|
# should allow_value("touhou locked:rating").for(:tag_string)
|
|
# should allow_value("touhou -locked:rating").for(:tag_string)
|
|
#
|
|
# # \u3000 = ideographic space, \u00A0 = no-break space
|
|
# should allow_value("touhou\u3000foo").for(:tag_string)
|
|
# should allow_value("touhou\u00A0foo").for(:tag_string)
|
|
# end
|
|
|
|
# TODO: These are now warnings and don't trigger these.
|
|
# context "tagged with an invalid tag" do
|
|
# subject { @post }
|
|
#
|
|
# context "that doesn't already exist" do
|
|
# should_not allow_value("touhou user:evazion").for(:tag_string)
|
|
# should_not allow_value("touhou *~foo").for(:tag_string)
|
|
# should_not allow_value("touhou *-foo").for(:tag_string)
|
|
# should_not allow_value("touhou ,-foo").for(:tag_string)
|
|
#
|
|
# should_not allow_value("touhou ___").for(:tag_string)
|
|
# should_not allow_value("touhou ~foo").for(:tag_string)
|
|
# should_not allow_value("touhou _foo").for(:tag_string)
|
|
# should_not allow_value("touhou foo_").for(:tag_string)
|
|
# should_not allow_value("touhou foo__bar").for(:tag_string)
|
|
# should_not allow_value("touhou foo*bar").for(:tag_string)
|
|
# should_not allow_value("touhou foo,bar").for(:tag_string)
|
|
# should_not allow_value("touhou foo\abar").for(:tag_string)
|
|
# should_not allow_value("touhou café").for(:tag_string)
|
|
# should_not allow_value("touhou 東方").for(:tag_string)
|
|
# end
|
|
#
|
|
# context "that already exists" do
|
|
# setup do
|
|
# %W(___ ~foo _foo foo_ foo__bar foo*bar foo,bar foo\abar café 東方).each do |tag|
|
|
# build(:tag, name: tag).save(validate: false)
|
|
# end
|
|
# end
|
|
#
|
|
# should allow_value("touhou ___").for(:tag_string)
|
|
# should allow_value("touhou ~foo").for(:tag_string)
|
|
# should allow_value("touhou _foo").for(:tag_string)
|
|
# should allow_value("touhou foo_").for(:tag_string)
|
|
# should allow_value("touhou foo__bar").for(:tag_string)
|
|
# should allow_value("touhou foo*bar").for(:tag_string)
|
|
# should allow_value("touhou foo,bar").for(:tag_string)
|
|
# should allow_value("touhou foo\abar").for(:tag_string)
|
|
# should allow_value("touhou café").for(:tag_string)
|
|
# should allow_value("touhou 東方").for(:tag_string)
|
|
# end
|
|
# end
|
|
|
|
context "tagged with a metatag" do
|
|
|
|
context "for typing a tag" do
|
|
setup do
|
|
@post = create(:post, tag_string: "char:hoge")
|
|
@tags = @post.tag_array
|
|
end
|
|
|
|
should "change the type" do
|
|
assert(Tag.where(name: "hoge", category: 4).exists?, "expected 'moge' tag to be created as a character")
|
|
end
|
|
end
|
|
|
|
context "for a parent" do
|
|
setup do
|
|
@parent = create(:post)
|
|
end
|
|
|
|
should "update the parent relationships for both posts" do
|
|
@post.update(:tag_string => "aaa parent:#{@parent.id}")
|
|
@post.reload
|
|
@parent.reload
|
|
assert_equal(@parent.id, @post.parent_id)
|
|
assert(@parent.has_children?)
|
|
end
|
|
|
|
should "not allow self-parenting" do
|
|
@post.update(:tag_string => "parent:#{@post.id}")
|
|
assert_nil(@post.parent_id)
|
|
end
|
|
|
|
should "clear the parent with parent:none" do
|
|
@post.update(:parent_id => @parent.id)
|
|
assert_equal(@parent.id, @post.parent_id)
|
|
|
|
@post.update(:tag_string => "parent:none")
|
|
assert_nil(@post.parent_id)
|
|
end
|
|
|
|
should "clear the parent with -parent:1234" do
|
|
@post.update(:parent_id => @parent.id)
|
|
assert_equal(@parent.id, @post.parent_id)
|
|
|
|
@post.update(:tag_string => "-parent:#{@parent.id}")
|
|
assert_nil(@post.parent_id)
|
|
end
|
|
end
|
|
|
|
context "for a pool" do
|
|
context "on creation" do
|
|
setup do
|
|
@pool = create(:pool)
|
|
@post = create(:post, tag_string: "aaa pool:#{@pool.id}")
|
|
end
|
|
|
|
should "add the post to the pool" do
|
|
@post.reload
|
|
@pool.reload
|
|
assert_equal([@post.id], @pool.post_ids)
|
|
assert_equal("pool:#{@pool.id}", @post.pool_string)
|
|
end
|
|
end
|
|
|
|
context "negated" do
|
|
setup do
|
|
@pool = create(:pool)
|
|
@post = create(:post, tag_string: "aaa")
|
|
@pool.add(@post)
|
|
@post.tag_string = "aaa -pool:#{@pool.id}"
|
|
@post.save
|
|
end
|
|
|
|
should "remove the post from the pool" do
|
|
@post.reload
|
|
@pool.reload
|
|
assert_equal([], @pool.post_ids)
|
|
assert_equal("", @post.pool_string)
|
|
end
|
|
end
|
|
|
|
context "id" do
|
|
setup do
|
|
@pool = create(:pool)
|
|
@post.update(:tag_string => "aaa pool:#{@pool.id}")
|
|
end
|
|
|
|
should "add the post to the pool" do
|
|
@post.reload
|
|
@pool.reload
|
|
assert_equal([@post.id], @pool.post_ids)
|
|
assert_equal("pool:#{@pool.id}", @post.pool_string)
|
|
end
|
|
end
|
|
|
|
context "name" do
|
|
context "that exists" do
|
|
setup do
|
|
@pool = create(:pool, name: "abc")
|
|
@post.update(:tag_string => "aaa pool:abc")
|
|
end
|
|
|
|
should "add the post to the pool" do
|
|
@post.reload
|
|
@pool.reload
|
|
assert_equal([@post.id], @pool.post_ids)
|
|
assert_equal("pool:#{@pool.id}", @post.pool_string)
|
|
end
|
|
end
|
|
|
|
context "that doesn't exist" do
|
|
should "create a new pool and add the post to that pool" do
|
|
@post.update(:tag_string => "aaa newpool:abc")
|
|
@pool = Pool.find_by_name("abc")
|
|
@post.reload
|
|
assert_not_nil(@pool)
|
|
assert_equal([@post.id], @pool.post_ids)
|
|
assert_equal("pool:#{@pool.id}", @post.pool_string)
|
|
end
|
|
end
|
|
|
|
context "with special characters" do
|
|
should "not strip '%' from the name" do
|
|
@post.update(tag_string: "aaa newpool:ichigo_100%")
|
|
assert(Pool.exists?(name: "ichigo_100%"))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "for a rating" do
|
|
context "that is valid" do
|
|
should "update the rating if the post is unlocked" do
|
|
@post.update(:tag_string => "aaa rating:e")
|
|
@post.reload
|
|
assert_equal("e", @post.rating)
|
|
end
|
|
end
|
|
|
|
context "that is invalid" do
|
|
should "not update the rating" do
|
|
@post.update(:tag_string => "aaa rating:z")
|
|
@post.reload
|
|
assert_equal("q", @post.rating)
|
|
end
|
|
end
|
|
|
|
context "that is locked" do
|
|
should "change the rating if locked in the same update" do
|
|
@post.update(tag_string: "rating:e", is_rating_locked: true)
|
|
|
|
assert(@post.valid?)
|
|
assert_equal("e", @post.reload.rating)
|
|
end
|
|
|
|
should "not change the rating if locked previously" do
|
|
@post.is_rating_locked = true
|
|
@post.save
|
|
|
|
@post.update(:tag_string => "rating:e")
|
|
|
|
assert(@post.invalid?)
|
|
assert_not_equal("e", @post.reload.rating)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "for a fav" do
|
|
should "add/remove the current user to the post's favorite listing" do
|
|
@post.update(:tag_string => "aaa")
|
|
FavoriteManager.add!(user: CurrentUser.user, post: @post)
|
|
assert_equal("fav:#{@user.id}", @post.fav_string)
|
|
|
|
FavoriteManager.remove!(user: CurrentUser.user, post: @post)
|
|
assert_equal("", @post.fav_string)
|
|
end
|
|
end
|
|
|
|
context "for a child" do
|
|
should "add and remove children" do
|
|
@children = create_list(:post, 3, parent_id: nil)
|
|
|
|
@post.update(tag_string: "aaa child:#{@children.first.id}..#{@children.last.id}")
|
|
assert_equal(true, @post.reload.has_children?)
|
|
assert_equal(@post.id, @children[0].reload.parent_id)
|
|
assert_equal(@post.id, @children[1].reload.parent_id)
|
|
assert_equal(@post.id, @children[2].reload.parent_id)
|
|
|
|
@post.update(tag_string: "aaa -child:#{@children.first.id}")
|
|
assert_equal(true, @post.reload.has_children?)
|
|
assert_nil(@children[0].reload.parent_id)
|
|
assert_equal(@post.id, @children[1].reload.parent_id)
|
|
assert_equal(@post.id, @children[2].reload.parent_id)
|
|
|
|
@post.update(tag_string: "aaa child:none")
|
|
assert_equal(false, @post.reload.has_children?)
|
|
assert_nil(@children[0].reload.parent_id)
|
|
assert_nil(@children[1].reload.parent_id)
|
|
assert_nil(@children[2].reload.parent_id)
|
|
end
|
|
end
|
|
|
|
context "for a source" do
|
|
should "set the source with source:foo_bar_baz" do
|
|
@post.update(:tag_string => "source:foo_bar_baz")
|
|
assert_equal("foo_bar_baz", @post.source)
|
|
end
|
|
|
|
should 'set the source with source:"foo bar baz"' do
|
|
@post.update(:tag_string => 'source:"foo bar baz"')
|
|
assert_equal("foo bar baz", @post.source)
|
|
end
|
|
|
|
should 'strip the source with source:" foo bar baz "' do
|
|
@post.update(:tag_string => 'source:" foo bar baz "')
|
|
assert_equal("foo bar baz", @post.source)
|
|
end
|
|
|
|
should "clear the source with source:none" do
|
|
@post.update(:source => "foobar")
|
|
@post.update(:tag_string => "source:none")
|
|
assert_equal("", @post.source)
|
|
end
|
|
end
|
|
|
|
context "of" do
|
|
setup do
|
|
@janitor = create(:janitor_user)
|
|
end
|
|
|
|
context "locked:notes" do
|
|
context "by a member" do
|
|
should "not lock the notes" do
|
|
@post.update(:tag_string => "locked:notes")
|
|
assert_equal(false, @post.is_note_locked)
|
|
end
|
|
end
|
|
|
|
context "by a janitor" do
|
|
should "lock/unlock the notes" do
|
|
as(@janitor) do
|
|
@post.update(:tag_string => "locked:notes")
|
|
assert_equal(true, @post.is_note_locked)
|
|
|
|
@post.update(:tag_string => "-locked:notes")
|
|
assert_equal(false, @post.is_note_locked)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "locked:rating" do
|
|
context "by a member" do
|
|
should "not lock the rating" do
|
|
@post.update(:tag_string => "locked:rating")
|
|
assert_equal(false, @post.is_rating_locked)
|
|
end
|
|
end
|
|
|
|
context "by a janitor" do
|
|
should "lock/unlock the rating" do
|
|
as(@janitor) do
|
|
@post.update(:tag_string => "locked:rating")
|
|
assert_equal(true, @post.is_rating_locked)
|
|
|
|
@post.update(:tag_string => "-locked:rating")
|
|
assert_equal(false, @post.is_rating_locked)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "locked:status" do
|
|
context "by a member" do
|
|
should "not lock the status" do
|
|
@post.update(:tag_string => "locked:status")
|
|
assert_equal(false, @post.is_status_locked)
|
|
end
|
|
end
|
|
|
|
context "by an admin" do
|
|
should "lock/unlock the status" do
|
|
as(create(:admin_user)) do
|
|
@post.update(:tag_string => "locked:status")
|
|
assert_equal(true, @post.is_status_locked)
|
|
|
|
@post.update(:tag_string => "-locked:status")
|
|
assert_equal(false, @post.is_status_locked)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "tagged with a negated tag" do
|
|
should "remove the tag if present" do
|
|
@post.update(:tag_string => "aaa bbb ccc")
|
|
@post.update(:tag_string => "aaa bbb ccc -bbb")
|
|
@post.reload
|
|
assert_equal("aaa ccc", @post.tag_string)
|
|
end
|
|
|
|
should "resolve aliases" do
|
|
create(:tag_alias, antecedent_name: "tr", consequent_name: "translation_request")
|
|
@post.update(:tag_string => "aaa translation_request -tr")
|
|
|
|
assert_equal("aaa", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "tagged with animated_gif or animated_png" do
|
|
should "remove the tag if not a gif or png" do
|
|
@post.update(tag_string: "tagme animated_gif")
|
|
assert_equal("tagme", @post.tag_string)
|
|
|
|
@post.update(tag_string: "tagme animated_png")
|
|
assert_equal("tagme", @post.tag_string)
|
|
end
|
|
end
|
|
|
|
should "have an array representation of its tags" do
|
|
post = create(:post)
|
|
post.reload
|
|
post.set_tag_string("aaa bbb")
|
|
assert_equal(%w(aaa bbb), post.tag_array)
|
|
assert_equal(%w(tag1 tag2), post.tag_array_was)
|
|
end
|
|
|
|
context "with large dimensions" do
|
|
setup do
|
|
@post.image_width = 10_000
|
|
@post.image_height = 10
|
|
@post.tag_string = ""
|
|
@post.save
|
|
end
|
|
|
|
should "have the appropriate dimension tags added automatically" do
|
|
assert_match(/absurd_res/, @post.tag_string)
|
|
assert_match(/hi_res/, @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with a large file size" do
|
|
setup do
|
|
@post.file_size = 31.megabytes
|
|
@post.tag_string = ""
|
|
@post.save
|
|
end
|
|
|
|
should "have the appropriate file size tags added automatically" do
|
|
assert_match(/huge_filesize/, @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "with a .webm file extension" do
|
|
setup do
|
|
create(:tag_implication, antecedent_name: "webm", consequent_name: "animated")
|
|
@post.file_ext = "webm"
|
|
@post.tag_string = ""
|
|
@post.save
|
|
end
|
|
|
|
should "have the appropriate file type tag added automatically" do
|
|
assert_match(/webm/, @post.tag_string)
|
|
end
|
|
|
|
should "apply implications after adding the file type tag" do
|
|
assert(@post.has_tag?("animated"), "expected 'webm' to imply 'animated'")
|
|
end
|
|
end
|
|
|
|
context "with a .swf file extension" do
|
|
setup do
|
|
@post.file_ext = "swf"
|
|
@post.tag_string = ""
|
|
@post.save
|
|
end
|
|
|
|
should "have the appropriate file type tag added automatically" do
|
|
assert_match(/flash/, @post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "that has been updated" do
|
|
should "create a new version if it's the first version" do
|
|
assert_difference("PostVersion.count", 1) do
|
|
post = create(:post)
|
|
end
|
|
end
|
|
|
|
should "create a new version if the post is updated" do
|
|
post = create(:post)
|
|
assert_difference("PostVersion.count", 1) do
|
|
post.update(:tag_string => "zzz")
|
|
end
|
|
end
|
|
|
|
should "increment the updater's post_update_count" do
|
|
post = create(:post, tag_string: "aaa bbb ccc")
|
|
|
|
assert_difference("CurrentUser.user.reload.post_update_count", 1) do
|
|
post.update(:tag_string => "zzz")
|
|
end
|
|
end
|
|
|
|
should "reset its tag array cache" do
|
|
post = create(:post, tag_string: "aaa bbb ccc")
|
|
user = create(:user)
|
|
assert_equal(%w(aaa bbb ccc), post.tag_array)
|
|
post.tag_string = "ddd eee fff"
|
|
post.tag_string = "ddd eee fff"
|
|
post.save
|
|
assert_equal("ddd eee fff", post.tag_string)
|
|
assert_equal(%w(ddd eee fff), post.tag_array)
|
|
end
|
|
|
|
should "create the actual tag records" do
|
|
assert_difference("Tag.count", 3) do
|
|
post = create(:post, tag_string: "aaa bbb ccc")
|
|
end
|
|
end
|
|
|
|
should "update the post counts of relevant tag records" do
|
|
post1 = create(:post, tag_string: "aaa bbb ccc")
|
|
post2 = create(:post, tag_string: "bbb ccc ddd")
|
|
post3 = create(:post, tag_string: "ccc ddd eee")
|
|
assert_equal(1, Tag.find_by_name("aaa").post_count)
|
|
assert_equal(2, Tag.find_by_name("bbb").post_count)
|
|
assert_equal(3, Tag.find_by_name("ccc").post_count)
|
|
post3.reload
|
|
post3.tag_string = "xxx"
|
|
post3.save
|
|
assert_equal(1, Tag.find_by_name("aaa").post_count)
|
|
assert_equal(2, Tag.find_by_name("bbb").post_count)
|
|
assert_equal(2, Tag.find_by_name("ccc").post_count)
|
|
assert_equal(1, Tag.find_by_name("ddd").post_count)
|
|
assert_equal(0, Tag.find_by_name("eee").post_count)
|
|
assert_equal(1, Tag.find_by_name("xxx").post_count)
|
|
end
|
|
|
|
should "update its tag counts" do
|
|
artist_tag = create(:artist_tag)
|
|
copyright_tag = create(:copyright_tag)
|
|
general_tag = create(:tag)
|
|
new_post = create(:post, tag_string: "#{artist_tag.name} #{copyright_tag.name} #{general_tag.name}")
|
|
assert_equal(1, new_post.tag_count_artist)
|
|
assert_equal(1, new_post.tag_count_copyright)
|
|
assert_equal(1, new_post.tag_count_general)
|
|
assert_equal(0, new_post.tag_count_character)
|
|
assert_equal(3, new_post.tag_count)
|
|
|
|
new_post.tag_string = "babs"
|
|
new_post.save
|
|
assert_equal(0, new_post.tag_count_artist)
|
|
assert_equal(0, new_post.tag_count_copyright)
|
|
assert_equal(1, new_post.tag_count_general)
|
|
assert_equal(0, new_post.tag_count_character)
|
|
assert_equal(1, new_post.tag_count)
|
|
end
|
|
|
|
should "merge any tag changes that were made after loading the initial set of tags part 1" do
|
|
post = create(:post, tag_string: "aaa bbb ccc")
|
|
|
|
# user a adds <ddd>
|
|
post_edited_by_user_a = Post.find(post.id)
|
|
post_edited_by_user_a.old_tag_string = "aaa bbb ccc"
|
|
post_edited_by_user_a.tag_string = "aaa bbb ccc ddd"
|
|
post_edited_by_user_a.save
|
|
|
|
# user b removes <ccc> adds <eee>
|
|
post_edited_by_user_b = Post.find(post.id)
|
|
post_edited_by_user_b.old_tag_string = "aaa bbb ccc"
|
|
post_edited_by_user_b.tag_string = "aaa bbb eee"
|
|
post_edited_by_user_b.save
|
|
|
|
# final should be <aaa>, <bbb>, <ddd>, <eee>
|
|
final_post = Post.find(post.id)
|
|
assert_equal(%w(aaa bbb ddd eee), TagQuery.scan(final_post.tag_string).sort)
|
|
end
|
|
|
|
should "merge any tag changes that were made after loading the initial set of tags part 2" do
|
|
# This is the same as part 1, only the order of operations is reversed.
|
|
# The results should be the same.
|
|
|
|
post = create(:post, tag_string: "aaa bbb ccc")
|
|
|
|
# user a removes <ccc> adds <eee>
|
|
post_edited_by_user_a = Post.find(post.id)
|
|
post_edited_by_user_a.old_tag_string = "aaa bbb ccc"
|
|
post_edited_by_user_a.tag_string = "aaa bbb eee"
|
|
post_edited_by_user_a.save
|
|
|
|
# user b adds <ddd>
|
|
post_edited_by_user_b = Post.find(post.id)
|
|
post_edited_by_user_b.old_tag_string = "aaa bbb ccc"
|
|
post_edited_by_user_b.tag_string = "aaa bbb ccc ddd"
|
|
post_edited_by_user_b.save
|
|
|
|
# final should be <aaa>, <bbb>, <ddd>, <eee>
|
|
final_post = Post.find(post.id)
|
|
assert_equal(%w(aaa bbb ddd eee), TagQuery.scan(final_post.tag_string).sort)
|
|
end
|
|
|
|
should "merge any parent, source, and rating changes that were made after loading the initial set" do
|
|
post = create(:post, parent: nil, source: "", rating: "q")
|
|
parent_post = create(:post)
|
|
|
|
# user a changes rating to safe, adds parent
|
|
post_edited_by_user_a = Post.find(post.id)
|
|
post_edited_by_user_a.old_parent_id = ""
|
|
post_edited_by_user_a.old_source = ""
|
|
post_edited_by_user_a.old_rating = "q"
|
|
post_edited_by_user_a.parent_id = parent_post.id
|
|
post_edited_by_user_a.source = nil
|
|
post_edited_by_user_a.rating = "s"
|
|
post_edited_by_user_a.save
|
|
|
|
# user b adds source
|
|
post_edited_by_user_b = Post.find(post.id)
|
|
post_edited_by_user_b.old_parent_id = ""
|
|
post_edited_by_user_b.old_source = ""
|
|
post_edited_by_user_b.old_rating = "q"
|
|
post_edited_by_user_b.parent_id = nil
|
|
post_edited_by_user_b.source = "http://example.com"
|
|
post_edited_by_user_b.rating = "q"
|
|
post_edited_by_user_b.save
|
|
|
|
# final post should be rated safe and have the set parent and source
|
|
final_post = Post.find(post.id)
|
|
assert_equal(parent_post.id, final_post.parent_id)
|
|
assert_equal("https://example.com", final_post.source)
|
|
assert_equal("s", final_post.rating)
|
|
end
|
|
end
|
|
|
|
context "that has been tagged with a metatag" do
|
|
should "not include the metatag in its tag string" do
|
|
post = create(:post)
|
|
post.tag_string = "aaa pool:1234 pool:test rating:s fav:bob"
|
|
post.save
|
|
assert_equal("aaa", post.tag_string)
|
|
end
|
|
end
|
|
|
|
context "when validating tags" do
|
|
should "warn when creating a new general tag" do
|
|
@post.add_tag("tag")
|
|
@post.save
|
|
|
|
assert_match(/Created 1 new tag: \[\[tag\]\]/, @post.warnings.full_messages.join)
|
|
end
|
|
|
|
should "warn when adding an artist tag without an artist entry" do
|
|
@post.add_tag("artist:bkub")
|
|
@post.save
|
|
|
|
assert_match(/Artist \[\[bkub\]\] requires an artist entry./, @post.warnings.full_messages.join)
|
|
end
|
|
|
|
should "warn when a post from a known source is missing an artist tag" do
|
|
post = build(:post, source: "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=65985331")
|
|
post.save
|
|
assert_match(/Artist tag is required/, post.warnings.full_messages.join)
|
|
end
|
|
|
|
should "warn when an upload doesn't have enough tags" do
|
|
post = create(:post, tag_string: "tagme")
|
|
assert_match(/Uploads must have at least \d+ general tags/, post.warnings.full_messages.join)
|
|
end
|
|
|
|
should "error if the tagcount is above the limit" do
|
|
Danbooru.config.stubs(:max_tags_per_post).returns(5)
|
|
post = create(:post, tag_string: "1 2 3 4 5")
|
|
post.add_tag("6")
|
|
post.save
|
|
assert_match(/tag count exceeds maximum/, post.errors.full_messages.join)
|
|
end
|
|
|
|
should "error if the tagcount via implications is above the limit" do
|
|
Danbooru.config.stubs(:max_tags_per_post).returns(2)
|
|
create(:tag_implication, antecedent_name: "2", consequent_name: "3")
|
|
post = create(:post, tag_string: "1")
|
|
post.add_tag("2")
|
|
post.save
|
|
assert_match(/tag count exceeds maximum/, post.errors.full_messages.join)
|
|
end
|
|
|
|
should "allow removing tags when the post is above the limit" do
|
|
Danbooru.config.stubs(:max_tags_per_post).returns(2)
|
|
post = build(:post, tag_string: "1 2 3")
|
|
post.save(validate: false)
|
|
post.remove_tag("3")
|
|
post.save
|
|
assert_no_match(/tag count exceeds maximum/, post.errors.full_messages.join)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Updating:" do
|
|
context "an existing post" do
|
|
setup { @post = create(:post) }
|
|
|
|
should "call Tag.increment_post_counts with the correct params" do
|
|
@post.reload
|
|
Tag.expects(:increment_post_counts).once.with(["abc"])
|
|
@post.update(tag_string: "tag1 abc")
|
|
end
|
|
end
|
|
|
|
context "A rating unlocked post" do
|
|
setup { @post = create(:post) }
|
|
subject { @post }
|
|
|
|
should "not allow values S, safe, derp" do
|
|
["S", "safe", "derp"].each do |rating|
|
|
subject.rating = rating
|
|
assert(!subject.valid?)
|
|
end
|
|
end
|
|
|
|
should "allow values s, q, e" do
|
|
["s", "q", "e"].each do |rating|
|
|
subject.rating = rating
|
|
assert(subject.valid?)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "A rating locked post" do
|
|
setup { @post = create(:post, is_rating_locked: true) }
|
|
subject { @post }
|
|
|
|
should "not allow values S, safe, derp" do
|
|
["S", "safe", "derp"].each do |rating|
|
|
subject.rating = rating
|
|
assert(!subject.valid?)
|
|
end
|
|
end
|
|
|
|
should "not allow values s, e" do
|
|
["s", "e"].each do |rating|
|
|
subject.rating = rating
|
|
assert(!subject.valid?)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Favorites:" do
|
|
context "Removing a post from a user's favorites" do
|
|
setup do
|
|
@user = create(:privileged_user)
|
|
@post = create(:post)
|
|
FavoriteManager.add!(user: @user, post: @post)
|
|
@user.reload
|
|
end
|
|
|
|
should "decrement the user's favorite_count" do
|
|
assert_difference("@user.reload.favorite_count", -1) do
|
|
FavoriteManager.remove!(user: @user, post: @post)
|
|
end
|
|
end
|
|
|
|
should "not decrement the post's score" do
|
|
@member = create(:user)
|
|
|
|
assert_no_difference("@post.score") { FavoriteManager.add!(user: @member, post: @post) }
|
|
assert_no_difference("@post.score") { FavoriteManager.remove!(user: @member, post: @post) }
|
|
end
|
|
|
|
should "not decrement the user's favorite_count if the user did not favorite the post" do
|
|
@post2 = create(:post)
|
|
assert_no_difference("@user.reload.favorite_count") do
|
|
FavoriteManager.remove!(user: @user, post: @post2)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Adding a post to a user's favorites" do
|
|
setup do
|
|
@user = create(:privileged_user)
|
|
@post = create(:post)
|
|
end
|
|
|
|
should "periodically clean the fav_string" do
|
|
@post.update_column(:fav_string, "fav:1 fav:1 fav:1")
|
|
@post.update_column(:fav_count, 3)
|
|
@post.append_user_to_fav_string(2)
|
|
assert_equal("fav:1 fav:2", @post.fav_string)
|
|
assert_equal(2, @post.fav_count)
|
|
end
|
|
|
|
# TODO: Needs to reload relationship to obtain non cached value
|
|
should "increment the user's favorite_count" do
|
|
assert_difference("@user.reload.favorite_count", 1) do
|
|
FavoriteManager.add!(user: @user, post: @post)
|
|
end
|
|
end
|
|
|
|
should "not increment the post's score" do
|
|
@member = create(:user)
|
|
FavoriteManager.add!(user: @user, post: @post)
|
|
assert_equal(0, @post.score)
|
|
end
|
|
|
|
should "update the fav strings on the post" do
|
|
FavoriteManager.add!(user: @user, post: @post)
|
|
@post.reload
|
|
assert_equal("fav:#{@user.id}", @post.fav_string)
|
|
assert(Favorite.exists?(:user_id => @user.id, :post_id => @post.id))
|
|
|
|
assert_raises(Favorite::Error) { FavoriteManager.add!(user: @user, post: @post) }
|
|
@post.reload
|
|
assert_equal("fav:#{@user.id}", @post.fav_string)
|
|
assert(Favorite.exists?(:user_id => @user.id, :post_id => @post.id))
|
|
|
|
FavoriteManager.remove!(user: @user, post: @post)
|
|
@post.reload
|
|
assert_equal("", @post.fav_string)
|
|
assert(!Favorite.exists?(:user_id => @user.id, :post_id => @post.id))
|
|
|
|
FavoriteManager.remove!(user: @user, post: @post)
|
|
@post.reload
|
|
assert_equal("", @post.fav_string)
|
|
assert(!Favorite.exists?(:user_id => @user.id, :post_id => @post.id))
|
|
end
|
|
end
|
|
|
|
context "Moving favorites to a parent post" do
|
|
setup do
|
|
@parent = create(:post)
|
|
@child = create(:post, parent: @parent)
|
|
|
|
@user1 = create(:user, enable_privacy_mode: true)
|
|
@privileged1 = create(:privileged_user)
|
|
@supervoter1 = create(:user)
|
|
|
|
FavoriteManager.add!(user: @user1, post: @child)
|
|
FavoriteManager.add!(user: @privileged1, post: @child)
|
|
FavoriteManager.add!(user: @supervoter1, post: @child)
|
|
FavoriteManager.add!(user: @supervoter1, post: @parent)
|
|
|
|
with_inline_jobs { @child.give_favorites_to_parent }
|
|
@child.reload
|
|
@parent.reload
|
|
end
|
|
|
|
should "move the favorites" do
|
|
assert_equal(0, @child.fav_count)
|
|
assert_equal(0, @child.favorites.count)
|
|
assert_equal("", @child.fav_string)
|
|
assert_equal([], @child.favorites.pluck(:user_id))
|
|
|
|
assert_equal(3, @parent.fav_count)
|
|
assert_equal(3, @parent.favorites.count)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Pools:" do
|
|
context "Removing a post from a pool" do
|
|
should "update the post's pool string" do
|
|
post = create(:post)
|
|
pool = create(:pool)
|
|
pool.add!(post)
|
|
pool.remove!(post)
|
|
post.reload
|
|
assert_equal("", post.pool_string)
|
|
pool.remove!(post)
|
|
post.reload
|
|
assert_equal("", post.pool_string)
|
|
end
|
|
end
|
|
|
|
context "Adding a post to a pool" do
|
|
should "update the post's pool string" do
|
|
post = create(:post)
|
|
pool = create(:pool)
|
|
pool.add!(post)
|
|
post.reload
|
|
assert_equal("pool:#{pool.id}", post.pool_string)
|
|
pool.add!(post)
|
|
post.reload
|
|
assert_equal("pool:#{pool.id}", post.pool_string)
|
|
pool.remove!(post)
|
|
post.reload
|
|
assert_equal("", post.pool_string)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Uploading:" do
|
|
context "Uploading a post" do
|
|
should "capture who uploaded the post" do
|
|
post = create(:post)
|
|
user1 = create(:user)
|
|
user2 = create(:user)
|
|
user3 = create(:user)
|
|
|
|
post.uploader = user1
|
|
assert_equal(user1.id, post.uploader_id)
|
|
|
|
post.uploader_id = user2.id
|
|
assert_equal(user2.id, post.uploader_id)
|
|
assert_equal(user2.id, post.uploader_id)
|
|
assert_equal(user2.name, post.uploader_name)
|
|
end
|
|
|
|
context "tag post counts" do
|
|
setup { @post = build(:post) }
|
|
|
|
should "call Tag.increment_post_counts with the correct params" do
|
|
Tag.expects(:increment_post_counts).once.with(["tag1", "tag2"])
|
|
@post.save
|
|
end
|
|
end
|
|
|
|
should "increment the uploaders post_upload_count" do
|
|
assert_difference(-> { CurrentUser.user.post_upload_count }) do
|
|
post = create(:post, uploader: CurrentUser.user)
|
|
CurrentUser.user.reload
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "Searching:" do
|
|
should "return posts for the age:<1minute tag" do
|
|
post = create(:post)
|
|
assert_tag_match([post], "age:<1minute")
|
|
end
|
|
|
|
should "return posts for the age:<1minute tag when the user is in Pacific time zone" do
|
|
post = create(:post)
|
|
Time.zone = "Pacific Time (US & Canada)"
|
|
assert_tag_match([post], "age:<1minute")
|
|
Time.zone = "Eastern Time (US & Canada)"
|
|
end
|
|
|
|
should "return posts for the age:<1minute tag when the user is in Tokyo time zone" do
|
|
post = create(:post)
|
|
Time.zone = "Asia/Tokyo"
|
|
assert_tag_match([post], "age:<1minute")
|
|
Time.zone = "Eastern Time (US & Canada)"
|
|
end
|
|
|
|
should "return posts for the ' tag" do
|
|
post1 = create(:post, tag_string: "'")
|
|
post2 = create(:post, tag_string: "aaa bbb")
|
|
|
|
assert_tag_match([post1], "'")
|
|
end
|
|
|
|
should "return posts for the ? tag" do
|
|
post1 = create(:post, tag_string: "?")
|
|
post2 = create(:post, tag_string: "aaa bbb")
|
|
|
|
assert_tag_match([post1], "?")
|
|
end
|
|
|
|
should "return posts for 1 tag" do
|
|
post1 = create(:post, tag_string: "aaa")
|
|
post2 = create(:post, tag_string: "aaa bbb")
|
|
post3 = create(:post, tag_string: "bbb ccc")
|
|
|
|
assert_tag_match([post2, post1], "aaa")
|
|
end
|
|
|
|
should "return posts for a 2 tag join" do
|
|
post1 = create(:post, tag_string: "aaa")
|
|
post2 = create(:post, tag_string: "aaa bbb")
|
|
post3 = create(:post, tag_string: "bbb ccc")
|
|
|
|
assert_tag_match([post2], "aaa bbb")
|
|
end
|
|
|
|
should "return posts for a 2 tag union" do
|
|
post1 = create(:post, tag_string: "aaa")
|
|
post2 = create(:post, tag_string: "aaab bbb")
|
|
post3 = create(:post, tag_string: "bbb ccc")
|
|
|
|
assert_tag_match([post3, post1], "~aaa ~ccc")
|
|
end
|
|
|
|
should "return posts for 1 tag with exclusion" do
|
|
post1 = create(:post, tag_string: "aaa")
|
|
post2 = create(:post, tag_string: "aaa bbb")
|
|
post3 = create(:post, tag_string: "bbb ccc")
|
|
|
|
assert_tag_match([post1], "aaa -bbb")
|
|
end
|
|
|
|
should "return posts for 1 tag with a pattern" do
|
|
post1 = create(:post, tag_string: "aaa")
|
|
post2 = create(:post, tag_string: "aaab bbb")
|
|
post3 = create(:post, tag_string: "bbb ccc")
|
|
|
|
assert_tag_match([post2, post1], "a*")
|
|
end
|
|
|
|
should "return posts for 2 tags, one with a pattern" do
|
|
post1 = create(:post, tag_string: "aaa")
|
|
post2 = create(:post, tag_string: "aaab bbb")
|
|
post3 = create(:post, tag_string: "bbb ccc")
|
|
|
|
assert_tag_match([post2], "a* bbb")
|
|
end
|
|
|
|
should "return posts for the id:<N> metatag" do
|
|
posts = create_list(:post, 3)
|
|
|
|
assert_tag_match([posts[1]], "id:#{posts[1].id}")
|
|
assert_tag_match([posts[2]], "id:>#{posts[1].id}")
|
|
assert_tag_match([posts[0]], "id:<#{posts[1].id}")
|
|
|
|
assert_tag_match([posts[2], posts[0]], "-id:#{posts[1].id}")
|
|
assert_tag_match([posts[2], posts[1]], "id:>=#{posts[1].id}")
|
|
assert_tag_match([posts[1], posts[0]], "id:<=#{posts[1].id}")
|
|
assert_tag_match([posts[2], posts[0]], "id:#{posts[0].id},#{posts[2].id}")
|
|
assert_tag_match(posts.reverse, "id:#{posts[0].id}..#{posts[2].id}")
|
|
end
|
|
|
|
should "return posts for the fav:<name> metatag" do
|
|
users = create_list(:user, 2)
|
|
posts = users.map do |u|
|
|
as(u) do
|
|
post = create(:post, tag_string: "abc")
|
|
FavoriteManager.add!(user: u, post: post)
|
|
post
|
|
end
|
|
end
|
|
|
|
assert_tag_match([posts[0]], "fav:#{users[0].name}")
|
|
assert_tag_match([posts[1]], "-fav:#{users[0].name}")
|
|
end
|
|
|
|
should "return posts for the pool:<name> metatag" do
|
|
create(:pool, name: "test_a")
|
|
create(:pool, name: "test_b")
|
|
post1 = create(:post, tag_string: "pool:test_a")
|
|
post2 = create(:post, tag_string: "pool:test_b")
|
|
|
|
assert_tag_match([post1], "pool:test_a")
|
|
assert_tag_match([post2], "-pool:test_a")
|
|
assert_tag_match([], "-pool:test_a -pool:test_b")
|
|
|
|
assert_tag_match([post2, post1], "pool:any")
|
|
assert_tag_match([], "pool:none")
|
|
end
|
|
|
|
should "return posts for the parent:<N> metatag" do
|
|
parent = create(:post)
|
|
child = create(:post, tag_string: "parent:#{parent.id}")
|
|
|
|
assert_tag_match([parent], "parent:none")
|
|
assert_tag_match([child], "-parent:none")
|
|
assert_tag_match([child], "parent:#{parent.id}")
|
|
|
|
assert_tag_match([child], "child:none")
|
|
assert_tag_match([parent], "child:any")
|
|
end
|
|
|
|
should "return posts for the user:<name> metatag" do
|
|
users = create_list(:user, 2)
|
|
posts = users.map { |u| create(:post, uploader: u) }
|
|
|
|
assert_tag_match([posts[0]], "user:#{users[0].name}")
|
|
assert_tag_match([posts[1]], "-user:#{users[0].name}")
|
|
end
|
|
|
|
should "return posts for the approver:<name> metatag" do
|
|
users = create_list(:user, 2)
|
|
posts = users.map { |u| create(:post, approver: u) }
|
|
posts << create(:post, approver: nil)
|
|
|
|
assert_tag_match([posts[0]], "approver:#{users[0].name}")
|
|
assert_tag_match([posts[2], posts[1]], "-approver:#{users[0].name}")
|
|
assert_tag_match([posts[1], posts[0]], "approver:any")
|
|
assert_tag_match([posts[2]], "approver:none")
|
|
end
|
|
|
|
should "return posts for the commenter:<name> metatag" do
|
|
users = create_list(:user, 2, created_at: 2.weeks.ago)
|
|
posts = create_list(:post, 2)
|
|
comms = users.zip(posts).map { |u, p| as(u) { create(:comment, post: p) } }
|
|
|
|
assert_tag_match([posts[0]], "commenter:#{users[0].name}")
|
|
assert_tag_match([posts[1]], "commenter:#{users[1].name}")
|
|
end
|
|
|
|
should "return posts for the commenter:<any|none> metatag" do
|
|
posts = create_list(:post, 2)
|
|
create(:comment, post: posts[0], is_hidden: false)
|
|
create(:comment, post: posts[1], is_hidden: true)
|
|
|
|
assert_tag_match([posts[0]], "commenter:any")
|
|
assert_tag_match([posts[1]], "commenter:none")
|
|
end
|
|
|
|
should "return posts for the noter:<name> metatag" do
|
|
users = create_list(:user, 2)
|
|
posts = create_list(:post, 2)
|
|
notes = users.zip(posts).map { |u, p| create(:note, creator: u, post: p) }
|
|
|
|
assert_tag_match([posts[0]], "noter:#{users[0].name}")
|
|
assert_tag_match([posts[1]], "noter:#{users[1].name}")
|
|
end
|
|
|
|
should "return posts for the noter:<any|none> metatag" do
|
|
posts = create_list(:post, 2)
|
|
create(:note, post: posts[0], is_active: true)
|
|
create(:note, post: posts[1], is_active: false)
|
|
|
|
assert_tag_match([posts[0]], "noter:any")
|
|
assert_tag_match([posts[1]], "noter:none")
|
|
end
|
|
|
|
should "return posts for the description:<text> metatag" do
|
|
posts = create_list(:post, 2)
|
|
posts[0].update_attribute(:description, 'abc')
|
|
posts[1].update_attribute(:description, 'efg')
|
|
|
|
assert_tag_match([posts[0]], "description:abc")
|
|
assert_tag_match([posts[1]], "description:efg")
|
|
end
|
|
|
|
should "return posts for the date:<d> metatag" do
|
|
post = create(:post, created_at: Time.parse("2017-01-01 12:00"))
|
|
|
|
assert_tag_match([post], "date:2017-01-01")
|
|
end
|
|
|
|
should "return posts for the age:<n> metatag" do
|
|
post = create(:post)
|
|
|
|
assert_tag_match([post], "age:<60")
|
|
assert_tag_match([post], "age:<60s")
|
|
assert_tag_match([post], "age:<1mi")
|
|
assert_tag_match([post], "age:<1h")
|
|
assert_tag_match([post], "age:<1d")
|
|
assert_tag_match([post], "age:<1w")
|
|
assert_tag_match([post], "age:<1mo")
|
|
assert_tag_match([post], "age:<1y")
|
|
end
|
|
|
|
should "return posts for the ratio:<x:y> metatag" do
|
|
post = create(:post, image_width: 1000, image_height: 500)
|
|
|
|
assert_tag_match([post], "ratio:2:1")
|
|
assert_tag_match([post], "ratio:2.0")
|
|
end
|
|
|
|
should "return posts for the status:<type> metatag" do
|
|
pending = create(:post, is_pending: true)
|
|
flagged = create(:post, is_flagged: true)
|
|
deleted = create(:post, is_deleted: true)
|
|
all = [deleted, flagged, pending]
|
|
|
|
assert_tag_match([flagged, pending], "status:modqueue")
|
|
assert_tag_match([pending], "status:pending")
|
|
assert_tag_match([flagged], "status:flagged")
|
|
assert_tag_match([deleted], "status:deleted")
|
|
assert_tag_match([], "status:active")
|
|
assert_tag_match(all, "status:any")
|
|
assert_tag_match(all, "status:all")
|
|
|
|
# TODO: These don't quite make sense, what should hide deleted posts and what shouldn't?
|
|
assert_tag_match(all - [deleted, flagged, pending], "-status:modqueue")
|
|
assert_tag_match(all - [deleted, pending], "-status:pending")
|
|
assert_tag_match(all - [deleted, flagged], "-status:flagged")
|
|
|
|
assert_tag_match(all - [deleted], "-status:deleted")
|
|
assert_tag_match(all, "-status:active")
|
|
end
|
|
|
|
should "return posts for the filetype:<ext> metatag" do
|
|
png = create(:post, file_ext: "png")
|
|
jpg = create(:post, file_ext: "jpg")
|
|
|
|
assert_tag_match([png], "filetype:png")
|
|
assert_tag_match([jpg], "-filetype:png")
|
|
end
|
|
|
|
should "return posts for the tagcount:<n> metatags" do
|
|
post = create(:post, tag_string: "artist:wokada copyright:vocaloid char:hatsune_miku twintails")
|
|
|
|
assert_tag_match([post], "tagcount:4")
|
|
assert_tag_match([], "tagcount:3")
|
|
assert_tag_match([post], "arttags:1")
|
|
assert_tag_match([post], "copytags:1")
|
|
assert_tag_match([post], "chartags:1")
|
|
assert_tag_match([post], "gentags:1")
|
|
assert_tag_match([], "gentags:0")
|
|
end
|
|
|
|
should "return posts for the md5:<md5> metatag" do
|
|
post1 = create(:post, md5: "abcd")
|
|
post2 = create(:post)
|
|
|
|
assert_tag_match([post1], "md5:abcd")
|
|
end
|
|
|
|
should "return posts for a source search" do
|
|
post1 = create(:post, source: "abcd")
|
|
post2 = create(:post, source: "abcdefg")
|
|
post3 = create(:post, source: "")
|
|
|
|
assert_tag_match([post2], "source:abcde")
|
|
assert_tag_match([post3, post1], "-source:abcde")
|
|
|
|
assert_tag_match([post3], "source:none")
|
|
assert_tag_match([post2, post1], "-source:none")
|
|
end
|
|
|
|
# TODO: Known broken. Need to normalize source during search and before index to fix bug with index creation.
|
|
should_eventually "return posts for a case insensitive source search" do
|
|
post1 = create(:post, source: "ABCD")
|
|
post2 = create(:post, source: "1234")
|
|
|
|
assert_tag_match([post1], "source:*abcd")
|
|
end
|
|
|
|
should "return posts for a pixiv source search" do
|
|
url = "http://i1.pixiv.net/img123/img/artist-name/789.png"
|
|
post = create(:post, source: url)
|
|
|
|
assert_tag_match([post], "source:*.pixiv.net/img*/artist-name/*")
|
|
assert_tag_match([], "source:*.pixiv.net/img*/artist-fake/*")
|
|
assert_tag_match([post], "source:https://*.pixiv.net/img*/img/artist-name/*")
|
|
assert_tag_match([], "source:https://*.pixiv.net/img*/img/artist-fake/*")
|
|
end
|
|
|
|
should "return posts for a rating:<s|q|e> metatag" do
|
|
s = create(:post, rating: "s")
|
|
q = create(:post, rating: "q")
|
|
e = create(:post, rating: "e")
|
|
all = [e, q, s]
|
|
|
|
assert_tag_match([s], "rating:s")
|
|
assert_tag_match([q], "rating:q")
|
|
assert_tag_match([e], "rating:e")
|
|
|
|
assert_tag_match(all - [s], "-rating:s")
|
|
assert_tag_match(all - [q], "-rating:q")
|
|
assert_tag_match(all - [e], "-rating:e")
|
|
end
|
|
|
|
should "return posts for a locked:<rating|note|status> metatag" do
|
|
rating_locked = create(:post, is_rating_locked: true)
|
|
note_locked = create(:post, is_note_locked: true)
|
|
status_locked = create(:post, is_status_locked: true)
|
|
all = [status_locked, note_locked, rating_locked]
|
|
|
|
assert_tag_match([rating_locked], "locked:rating")
|
|
assert_tag_match([note_locked], "locked:note")
|
|
assert_tag_match([status_locked], "locked:status")
|
|
|
|
assert_tag_match(all - [rating_locked], "-locked:rating")
|
|
assert_tag_match(all - [note_locked], "-locked:note")
|
|
assert_tag_match(all - [status_locked], "-locked:status")
|
|
end
|
|
|
|
should "return posts for a upvote:<user>, downvote:<user> metatag" do
|
|
old_user = create(:mod_user, created_at: 5.days.ago)
|
|
as(old_user) do
|
|
upvoted = create(:post, tag_string: "abc")
|
|
downvoted = create(:post, tag_string: "abc")
|
|
VoteManager.vote!(user: CurrentUser.user, post: upvoted, score: 1)
|
|
VoteManager.vote!(user: CurrentUser.user, post: downvoted, score: -1)
|
|
|
|
assert_tag_match([upvoted], "upvote:#{CurrentUser.name}")
|
|
assert_tag_match([downvoted], "downvote:#{CurrentUser.name}")
|
|
end
|
|
end
|
|
|
|
# FIXME: This test fails randomly at different assertions
|
|
should_eventually "return posts ordered by a particular attribute" do
|
|
posts = (1..2).map do |n|
|
|
tags = ["tagme", "gentag1 gentag2 artist:arttag char:chartag copy:copytag"]
|
|
|
|
p = create(
|
|
:post,
|
|
score: n,
|
|
fav_count: n,
|
|
file_size: 1.megabyte * n,
|
|
# posts[0] is portrait, posts[1] is landscape. posts[1].mpixels > posts[0].mpixels.
|
|
image_height: 100*n*n,
|
|
image_width: 100*(3-n)*n,
|
|
tag_string: tags[n-1],
|
|
)
|
|
|
|
create(:comment, post: p, do_not_bump_post: false)
|
|
create(:note, post: p)
|
|
p
|
|
end
|
|
|
|
create(:note, post: posts.second)
|
|
|
|
assert_tag_match(posts.reverse, "order:id_desc")
|
|
assert_tag_match(posts.reverse, "order:score")
|
|
assert_tag_match(posts.reverse, "order:favcount")
|
|
assert_tag_match(posts.reverse, "order:change")
|
|
assert_tag_match(posts.reverse, "order:comment")
|
|
assert_tag_match(posts.reverse, "order:comment_bumped")
|
|
assert_tag_match(posts.reverse, "order:note")
|
|
assert_tag_match(posts.reverse, "order:mpixels")
|
|
assert_tag_match(posts.reverse, "order:portrait")
|
|
assert_tag_match(posts.reverse, "order:filesize")
|
|
assert_tag_match(posts.reverse, "order:tagcount")
|
|
assert_tag_match(posts.reverse, "order:gentags")
|
|
assert_tag_match(posts.reverse, "order:arttags")
|
|
assert_tag_match(posts.reverse, "order:chartags")
|
|
assert_tag_match(posts.reverse, "order:copytags")
|
|
assert_tag_match(posts.reverse, "order:rank")
|
|
assert_tag_match(posts.reverse, "order:note_count")
|
|
assert_tag_match(posts.reverse, "order:note_count_desc")
|
|
assert_tag_match(posts.reverse, "order:notes")
|
|
assert_tag_match(posts.reverse, "order:notes_desc")
|
|
|
|
assert_tag_match(posts, "order:id_asc")
|
|
assert_tag_match(posts, "order:score_asc")
|
|
assert_tag_match(posts, "order:favcount_asc")
|
|
assert_tag_match(posts, "order:change_asc")
|
|
assert_tag_match(posts, "order:comment_asc")
|
|
assert_tag_match(posts, "order:comment_bumped_asc")
|
|
assert_tag_match(posts, "order:note_asc")
|
|
assert_tag_match(posts, "order:mpixels_asc")
|
|
assert_tag_match(posts, "order:landscape")
|
|
assert_tag_match(posts, "order:filesize_asc")
|
|
assert_tag_match(posts, "order:tagcount_asc")
|
|
assert_tag_match(posts, "order:gentags_asc")
|
|
assert_tag_match(posts, "order:arttags_asc")
|
|
assert_tag_match(posts, "order:chartags_asc")
|
|
assert_tag_match(posts, "order:copytags_asc")
|
|
assert_tag_match(posts, "order:note_count_asc")
|
|
assert_tag_match(posts, "order:notes_asc")
|
|
end
|
|
|
|
should "return posts for order:comment_bumped" do
|
|
post1 = create(:post)
|
|
post2 = create(:post)
|
|
post3 = create(:post)
|
|
|
|
as(create(:privileged_user)) do
|
|
create(:comment, post: post1)
|
|
create(:comment, post: post2, do_not_bump_post: true)
|
|
create(:comment, post: post3)
|
|
end
|
|
|
|
assert_tag_match([post3, post1], "order:comment_bumped")
|
|
assert_tag_match([post1, post3], "order:comment_bumped_asc")
|
|
|
|
create(:comment, post: post2)
|
|
|
|
assert_tag_match([post2, post3, post1], "order:comment_bumped")
|
|
assert_tag_match([post1, post3, post2], "order:comment_bumped_asc")
|
|
end
|
|
|
|
should "return posts for a filesize search" do
|
|
post = create(:post, file_size: 1.megabyte)
|
|
|
|
assert_tag_match([post], "filesize:1mb")
|
|
assert_tag_match([post], "filesize:1000kb")
|
|
assert_tag_match([post], "filesize:1048576b")
|
|
end
|
|
|
|
should "not count free tags against the user's search limit" do
|
|
post1 = create(:post, tag_string: "aaa bbb rating:s")
|
|
|
|
Danbooru.config.expects(:is_unlimited_tag?).with("rating:s").once.returns(true)
|
|
Danbooru.config.expects(:is_unlimited_tag?).with(anything).twice.returns(false)
|
|
assert_tag_match([post1], "aaa bbb rating:s")
|
|
end
|
|
|
|
should "succeed for exclusive tag searches with no other tag" do
|
|
post1 = create(:post, rating: "s", tag_string: "aaa")
|
|
assert_nothing_raised do
|
|
relation = Post.tag_match("-aaa")
|
|
end
|
|
end
|
|
|
|
should "succeed for exclusive tag searches combined with a metatag" do
|
|
post1 = create(:post, rating: "s", tag_string: "aaa")
|
|
assert_nothing_raised do
|
|
relation = Post.tag_match("-aaa id:>0")
|
|
end
|
|
end
|
|
|
|
should "return posts for replacements" do
|
|
assert_tag_match([], "pending_replacements:true")
|
|
assert_tag_match([], "pending_replacements:false")
|
|
post = create(:post)
|
|
replacement = create(:png_replacement, creator: @user, post: post)
|
|
assert_tag_match([post], "pending_replacements:true")
|
|
end
|
|
|
|
should "return no posts when the replacement is not pending anymore" do
|
|
post1 = create(:post)
|
|
upload = UploadService.new(attributes_for(:upload).merge(file: fixture_file_upload("test.gif"), uploader: @user, tag_string: "tst")).start!
|
|
post2 = upload.post
|
|
post3 = create(:post)
|
|
post4 = create(:post)
|
|
replacement1 = create(:png_replacement, creator: @user, post: post1)
|
|
replacement1.reject!
|
|
replacement2 = create(:png_replacement, creator: @user, post: post2)
|
|
replacement2.approve!(penalize_current_uploader: true)
|
|
replacement3 = create(:jpg_replacement, creator: @user, post: post3)
|
|
promoted_post = replacement3.promote!.post
|
|
replacement4 = create(:webm_replacement, creator: @user, post: post4)
|
|
replacement4.destroy!
|
|
|
|
assert_tag_match([], "pending_replacements:true")
|
|
assert_tag_match([promoted_post, post4, post3, post2, post1], "pending_replacements:false")
|
|
end
|
|
|
|
should "not error for values beyond Integer.MAX_VALUE" do
|
|
assert_tag_match([], "id:1234567890987654321")
|
|
end
|
|
end
|
|
|
|
context "Voting:" do
|
|
should "not allow duplicate votes" do
|
|
user = create(:privileged_user)
|
|
post = create(:post)
|
|
as(user) do
|
|
assert_nothing_raised { VoteManager.vote!(user: user, post: post, score: 1) }
|
|
# Need unvote is returned upon duplicates that are accounted for.
|
|
assert_equal(:need_unvote, VoteManager.vote!(user: user, post: post, score: 1) )
|
|
post.reload
|
|
assert_equal(1, PostVote.count)
|
|
assert_equal(1, post.score)
|
|
end
|
|
end
|
|
|
|
should "allow undoing of votes" do
|
|
user = create(:privileged_user, created_at: 7.days.ago)
|
|
post = create(:post)
|
|
|
|
# We deliberately don't call post.reload until the end to verify that
|
|
# post.unvote! returns the correct score even when not forcibly reloaded.
|
|
as(user) do
|
|
VoteManager.vote!(post: post, user: user, score: 1)
|
|
assert_equal(1, post.score)
|
|
|
|
VoteManager.unvote!(post: post, user: user)
|
|
assert_equal(0, post.score)
|
|
|
|
assert_nothing_raised { VoteManager.vote!(post: post, user: user, score: -1) }
|
|
assert_equal(-1, post.score)
|
|
|
|
VoteManager.unvote!(post: post, user: user)
|
|
assert_equal(0, post.score)
|
|
|
|
assert_nothing_raised { VoteManager.vote!(post: post, user: user, score: 1) }
|
|
assert_equal(1, post.score)
|
|
|
|
post.reload
|
|
assert_equal(1, post.score)
|
|
end
|
|
end
|
|
end
|
|
|
|
# TODO: These are pretty messed up, both structurally, and expectation wise.
|
|
# New codebase uses fewer cached items, and the keys are different because of -status:deleted default
|
|
# Most of these need major refactoring.
|
|
# context "Counting:" do
|
|
# context "Creating a post" do
|
|
# setup do
|
|
# create(:tag_alias, antecedent_name: "alias", consequent_name: "aaa")
|
|
# create(:post, tag_string: "aaa", score: 42)
|
|
# end
|
|
#
|
|
# context "a single metatag" do
|
|
# should "return the correct cached count" do
|
|
# build(:tag, name: "score:42", post_count: -100).save(validate: false)
|
|
# Post.set_count_in_cache("score:42", 100)
|
|
#
|
|
# assert_equal(100, Post.fast_count("score:42"))
|
|
# end
|
|
#
|
|
# should "return the correct cached count for a pool:<id> search" do
|
|
# build(:tag, name: "pool:1234", post_count: -100).save(validate: false)
|
|
# Post.set_count_in_cache("pool:1234", 100)
|
|
#
|
|
# assert_equal(100, Post.fast_count("pool:1234"))
|
|
# end
|
|
# end
|
|
#
|
|
# context "a multi-tag search" do
|
|
# should "return the cached count, if it exists" do
|
|
# Post.set_count_in_cache("aaa score:42", 100)
|
|
# assert_equal(100, Post.fast_count("aaa score:42"))
|
|
# end
|
|
#
|
|
# should "return the true count, if not cached" do
|
|
# assert_equal(1, Post.fast_count("aaa score:42"))
|
|
# end
|
|
#
|
|
# should "set the expiration time" do
|
|
# Cache.expects(:put).with(Post.count_cache_key("aaa score:42"), 1, 180)
|
|
# Post.fast_count("aaa score:42")
|
|
# end
|
|
# end
|
|
#
|
|
# context "a blank search" do
|
|
# should "should execute a search" do
|
|
# Cache.delete(Post.count_cache_key(''))
|
|
# Post.expects(:fast_count_search).with("", kind_of(Hash)).once.returns(1)
|
|
# assert_equal(1, Post.fast_count(""))
|
|
# end
|
|
#
|
|
# should "set the value in cache" do
|
|
# Post.expects(:set_count_in_cache).with("", kind_of(Integer)).once
|
|
# Post.fast_count("")
|
|
# end
|
|
#
|
|
# context "with a primed cache" do
|
|
# setup do
|
|
# Cache.write(Post.count_cache_key(''), "100")
|
|
# end
|
|
#
|
|
# should "fetch the value from the cache" do
|
|
# assert_equal(100, Post.fast_count(""))
|
|
# end
|
|
# end
|
|
#
|
|
# should "translate an alias" do
|
|
# assert_equal(1, Post.fast_count("alias"))
|
|
# end
|
|
#
|
|
# should "return 0 for a nonexisting tag" do
|
|
# assert_equal(0, Post.fast_count("bbb"))
|
|
# end
|
|
#
|
|
# context "in safe mode" do
|
|
# setup do
|
|
# CurrentUser.stubs(:safe_mode?).returns(true)
|
|
# create(:post, rating: "s")
|
|
# end
|
|
#
|
|
# should "work for a blank search" do
|
|
# assert_equal(1, Post.fast_count(""))
|
|
# end
|
|
#
|
|
# should "work for a nil search" do
|
|
# assert_equal(1, Post.fast_count(nil))
|
|
# end
|
|
#
|
|
# should "not fail for a two tag search by a member" do
|
|
# post1 = create(:post, tag_string: "aaa bbb rating:s")
|
|
# post2 = create(:post, tag_string: "aaa bbb rating:e")
|
|
#
|
|
# Danbooru.config.expects(:is_unlimited_tag?).with("rating:s").once.returns(true)
|
|
# Danbooru.config.expects(:is_unlimited_tag?).with(anything).twice.returns(false)
|
|
# assert_equal(1, Post.fast_count("aaa bbb"))
|
|
# end
|
|
#
|
|
# should "set the value in cache" do
|
|
# Post.expects(:set_count_in_cache).with("rating:s", kind_of(Integer)).once
|
|
# Post.fast_count("")
|
|
# end
|
|
#
|
|
# context "with a primed cache" do
|
|
# setup do
|
|
# Cache.write(Post.count_cache_key('rating:s'), "100")
|
|
# end
|
|
#
|
|
# should "fetch the value from the cache" do
|
|
# assert_equal(100, Post.fast_count(""))
|
|
# end
|
|
# end
|
|
# end
|
|
# end
|
|
# end
|
|
# end
|
|
|
|
context "Reverting: " do
|
|
context "a post that is rating locked" do
|
|
setup do
|
|
@post = create(:post, rating: "s")
|
|
@post.update(rating: "q", is_rating_locked: true)
|
|
end
|
|
|
|
should "not revert the rating" do
|
|
assert_raises ActiveRecord::RecordInvalid do
|
|
@post.revert_to!(@post.versions.first)
|
|
end
|
|
|
|
assert_equal(["Rating is locked and cannot be changed. Unlock the post first."], @post.errors.full_messages)
|
|
assert_equal(@post.versions.last.rating, @post.reload.rating)
|
|
end
|
|
|
|
should "revert the rating after unlocking" do
|
|
@post.update(rating: "e", is_rating_locked: false)
|
|
assert_nothing_raised do
|
|
@post.revert_to!(@post.versions.first)
|
|
end
|
|
|
|
assert(@post.valid?)
|
|
assert_equal(@post.versions.first.rating, @post.rating)
|
|
end
|
|
end
|
|
|
|
context "a post that has been updated" do
|
|
setup do
|
|
@post = create(:post, rating: "q", tag_string: "aaa", source: "")
|
|
@post.reload
|
|
@post.update(:tag_string => "aaa bbb ccc ddd")
|
|
@post.reload
|
|
@post.update(:tag_string => "bbb xxx yyy", :source => "xyz")
|
|
@post.reload
|
|
@post.update(:tag_string => "bbb mmm yyy", :source => "abc")
|
|
@post.reload
|
|
end
|
|
|
|
context "and then reverted to an early version" do
|
|
setup do
|
|
@version = @post.versions[1]
|
|
@post.revert_to!(@version)
|
|
@post.reload
|
|
end
|
|
|
|
should "correctly revert all fields" do
|
|
assert_equal("aaa bbb ccc ddd", @post.tag_string)
|
|
assert_equal("", @post.source)
|
|
assert_equal("q", @post.rating)
|
|
assert_equal("Revert to version #{@version.version}", @post.versions.last.reason)
|
|
end
|
|
end
|
|
|
|
context "and then reverted to a later version" do
|
|
setup do
|
|
@post.revert_to(@post.versions[-2])
|
|
end
|
|
|
|
should "correctly revert all fields" do
|
|
assert_equal("bbb xxx yyy", @post.tag_string)
|
|
assert_equal("xyz", @post.source)
|
|
assert_equal("q", @post.rating)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "URLs:" do
|
|
should "generate the correct urls for animated gifs" do
|
|
@post = build(:post, md5: "deadbeef", file_ext: "gif", tag_string: "animated_gif")
|
|
|
|
assert_equal("#{Danbooru.config.hostname}/data/preview/deadbeef.jpg", @post.preview_file_url)
|
|
|
|
assert_equal("#{Danbooru.config.hostname}/data/deadbeef.gif", @post.large_file_url)
|
|
assert_equal("#{Danbooru.config.hostname}/data/deadbeef.gif", @post.file_url)
|
|
end
|
|
end
|
|
|
|
context "Notes:" do
|
|
context "#copy_notes_to" do
|
|
setup do
|
|
@src = create(:post, image_width: 100, image_height: 100, tag_string: "translated partially_translated")
|
|
@dst = create(:post, image_width: 200, image_height: 200, tag_string: "translation_request")
|
|
|
|
@src.notes.create(x: 10, y: 10, width: 10, height: 10, body: "test")
|
|
@src.notes.create(x: 10, y: 10, width: 10, height: 10, body: "deleted", is_active: false)
|
|
@src.reload
|
|
|
|
@src.copy_notes_to(@dst)
|
|
end
|
|
|
|
should "copy notes and tags" do
|
|
assert_equal(1, @dst.notes.active.length)
|
|
assert_equal("low_res partially_translated thumbnail translated", @dst.tag_string)
|
|
end
|
|
|
|
should "rescale notes" do
|
|
note = @dst.notes.active.first
|
|
assert_equal([20, 20, 20, 20], [note.x, note.y, note.width, note.height])
|
|
end
|
|
end
|
|
end
|
|
end
|