Files
danbooru/test/unit/post_test.rb
albert 1c9d8c37c7 Fixed some major bugs with implications, cleaning up the cache
expiration process and adding some additional tests.

Cleaned up the unit tests.  They should all run cleanly with rake
test:units now.
2010-10-27 16:56:12 -04:00

621 lines
22 KiB
Ruby

require_relative '../test_helper'
class PostTest < ActiveSupport::TestCase
setup do
user = Factory.create(:user)
CurrentUser.user = user
CurrentUser.ip_addr = "127.0.0.1"
MEMCACHE.flush_all
end
teardown do
CurrentUser.user = nil
CurrentUser.ip_addr = nil
end
context "Removal:" do
context "Removing a post" do
should "update the fast count" do
post = Factory.create(:post, :tag_string => "aaa")
assert_equal(1, Post.fast_count)
assert_equal(1, Post.fast_count("aaa"))
post.remove!
assert_equal(0, Post.fast_count)
assert_equal(0, Post.fast_count("aaa"))
end
should "duplicate the post in the archive table and remove it from the base table" do
post = Factory.create(:post)
assert_difference("RemovedPost.count", 1) do
assert_difference("Post.count", -1) do
post.remove!
end
end
removed_post = RemovedPost.last
assert_equal(post.tag_string, removed_post.tag_string)
end
should "decrement the tag counts" do
post = Factory.create(:post, :tag_string => "aaa")
assert_equal(1, Tag.find_by_name("aaa").post_count)
post.remove!
assert_equal(0, Tag.find_by_name("aaa").post_count)
end
should "preserve the id" do
post = Factory.create(:post, :tag_string => "aaa")
post_id = post.id
post.remove!
removed_post = RemovedPost.last
assert_equal(post_id, removed_post.id)
removed_post.unremove!
post = Post.last
assert_equal(post_id, post.id)
end
end
end
context "Parenting:" do
context "Assignining a parent to a post" do
should "update the has_children flag on the parent" do
p1 = Factory.create(:post)
assert(!p1.has_children?, "Parent should not have any children")
c1 = Factory.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 = Factory.create(:post)
p2 = Factory.create(:post)
c1 = Factory.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
should "validate that the parent exists" do
post = Factory.build(:post, :parent_id => 1_000_000)
post.save
assert(post.errors[:parent].any?, "Parent should be invalid")
end
should "fail if the parent has a parent" do
p1 = Factory.create(:post)
c1 = Factory.create(:post, :parent_id => p1.id)
c2 = Factory.build(:post, :parent_id => c1.id)
c2.save
assert(c2.errors[:parent].any?, "Parent should be invalid")
end
end
context "Destroying a post with a parent" do
should "reassign favorites to the parent" do
p1 = Factory.create(:post)
c1 = Factory.create(:post, :parent_id => p1.id)
user = Factory.create(:user)
c1.add_favorite(user)
c1.remove!
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 "update the parent's has_children flag" do
p1 = Factory.create(:post)
c1 = Factory.create(:post, :parent_id => p1.id)
c1.remove!
p1.reload
assert(!p1.has_children?, "Parent should not have children")
end
end
context "Destroying a post with" do
context "one child" do
should "remove the parent of that child" do
p1 = Factory.create(:post)
c1 = Factory.create(:post, :parent_id => p1.id)
p1.remove!
c1.reload
assert_nil(c1.parent)
end
end
context "two or more children" do
should "reparent all children to the first child" do
p1 = Factory.create(:post)
c1 = Factory.create(:post, :parent_id => p1.id)
c2 = Factory.create(:post, :parent_id => p1.id)
c3 = Factory.create(:post, :parent_id => p1.id)
p1.remove!
c1.reload
c2.reload
c3.reload
assert_nil(c1.parent)
assert_equal(c1.id, c2.parent_id)
assert_equal(c1.id, c3.parent_id)
end
end
end
context "Undestroying a post with a parent" do
should "not preserve the parent's has_children flag" do
p1 = Factory.create(:post)
c1 = Factory.create(:post, :parent_id => p1.id)
c1.remove!
c1 = RemovedPost.last
c1.unremove!
c1 = Post.last
p1.reload
assert_nil(p1.parent_id)
assert(!p1.has_children?, "Parent should not have children")
end
end
end
context "Moderation:" do
context "An approved post" do
should "be unapproved once and only once" do
post = Factory.create(:post)
post.unapprove!("bad")
assert(post.is_flagged?, "Post should be flagged.")
assert_not_nil(post.unapproval, "Post should have an unapproval record.")
assert_equal("bad", post.unapproval.reason)
assert_raise(Unapproval::Error) {post.unapprove!("bad")}
end
should "not unapprove if no reason is given" do
post = Factory.create(:post)
assert_raise(Unapproval::Error) {post.unapprove!("")}
end
end
context "An unapproved post" do
should "preserve the approver's identity when approved" do
user = CurrentUser.user
post = Factory.create(:post, :is_pending => true)
post.approve!
assert_equal("approver:#{user.name}", post.approver_string)
end
should "preserve the unapproval association even when removed" do
post = Factory.create(:post)
post.unapprove!("bad")
post.remove!
removed_post = RemovedPost.last
assert_not_nil(removed_post.unapproval)
assert_equal("bad", removed_post.unapproval.reason)
end
context "that has been reapproved" do
should "no longer be flagged or pending" do
post = Factory.create(:post)
post.unapprove!("bad")
post.approve!
assert(post.errors.empty?, post.errors.full_messages.join(", "))
post.reload
assert_equal(false, post.is_flagged?)
assert_equal(false, post.is_pending?)
end
should "cannot be unapproved again" do
post = Factory.create(:post)
post.unapprove!("bad")
post.approve!
assert_raise(Unapproval::Error) {post.unapprove!("bad")}
end
end
end
end
context "Versioning:" do
context "Saving a post" do
should "create a new version" do
post = Factory.create(:post)
assert_equal(1, post.versions.size)
post.rating = "e"
post.save
assert_equal(2, post.versions.size)
assert_equal(CurrentUser.user.id, post.versions.last.updater_id)
assert_equal(CurrentUser.ip_addr, post.versions.last.updater_ip_addr)
post.revert_to!(PostVersion.first)
assert_equal("tag1 tag2", post.tag_string)
assert_equal("q", post.rating)
end
end
context "Reverting a post" do
should "identify the person who reverted the post" do
post = Factory.create(:post)
reverter = Factory.create(:user)
post.rating = "e"
post.save
post.rating = "q"
post.save
CurrentUser.user = Factory.create(:user)
post.revert_to!(PostVersion.first)
post.reload
assert_equal(CurrentUser.user.id, post.versions.last.updater_id)
end
end
end
context "Tagging:" do
context "A post" do
should "have an array representation of its tags" do
post = Factory.create(:post)
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 "that has been updated" do
should "reset its tag array cache" do
post = Factory.create(:post, :tag_string => "aaa bbb ccc")
user = Factory.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 = Factory.create(:post, :tag_string => "aaa bbb ccc")
end
end
should "update the post counts of relevant tag records" do
post1 = Factory.create(:post, :tag_string => "aaa bbb ccc")
post2 = Factory.create(:post, :tag_string => "bbb ccc ddd")
post3 = Factory.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.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 = Factory.create(:artist_tag)
copyright_tag = Factory.create(:copyright_tag)
general_tag = Factory.create(:tag)
new_post = Factory.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 changes that were made after loading the initial set of tags part 1" do
post = Factory.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), Tag.scan_tags(final_post.tag_string).sort)
end
should "merge any 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 = Factory.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), Tag.scan_tags(final_post.tag_string).sort)
end
end
context "that has been tagged with a metatag" do
should "not include the metatag in its tag string" do
post = Factory.create(:post)
post.tag_string = "aaa pool:1234 pool:test rating:s fav:bob"
post.save
assert_equal("aaa", post.tag_string)
end
end
end
end
context "Favorites:" do
context "Adding a post to a user's favorites" do
should "update the fav strings ont he post" do
user = Factory.create(:user)
post = Factory.create(:post)
post.add_favorite(user)
post.reload
assert_equal("fav:#{user.id}", post.fav_string)
assert(Favorite.exists?(:user_id => user.id, :post_id => post.id))
post.add_favorite(user)
post.reload
assert_equal("fav:#{user.id}", post.fav_string)
assert(Favorite.exists?(:user_id => user.id, :post_id => post.id))
post.remove_favorite(user)
post.reload
assert_equal("", post.fav_string)
assert(!Favorite.exists?(:user_id => user.id, :post_id => post.id))
post.remove_favorite(user)
post.reload
assert_equal("", post.fav_string)
assert(!Favorite.exists?(:user_id => user.id, :post_id => post.id))
end
end
end
context "Pools:" do
context "Adding a post to a pool" do
should "update the post's pool string" do
post = Factory.create(:post)
pool = Factory.create(:pool)
post.add_pool(pool)
post.reload
assert_equal("pool:#{pool.id}", post.pool_string)
post.add_pool(pool)
post.reload
assert_equal("pool:#{pool.id}", post.pool_string)
post.remove_pool(pool)
post.reload
assert_equal("", post.pool_string)
post.remove_pool(pool)
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 = Factory.create(:post)
user1 = Factory.create(:user)
user2 = Factory.create(:user)
user3 = Factory.create(:user)
post.uploader = user1
assert_equal("uploader:#{user1.id}", post.uploader_string)
post.uploader_id = user2.id
assert_equal("uploader:#{user2.id}", post.uploader_string)
assert_equal(user2.id, post.uploader_id)
assert_equal(user2.name, post.uploader_name)
end
end
end
context "Searching:" do
should "return posts for 1 tag" do
post1 = Factory.create(:post, :tag_string => "aaa")
post2 = Factory.create(:post, :tag_string => "aaa bbb")
post3 = Factory.create(:post, :tag_string => "bbb ccc")
relation = Post.find_by_tags("aaa")
assert_equal(2, relation.count)
assert_equal(post2.id, relation.all[0].id)
assert_equal(post1.id, relation.all[1].id)
end
should "return posts for a 2 tag join" do
post1 = Factory.create(:post, :tag_string => "aaa")
post2 = Factory.create(:post, :tag_string => "aaa bbb")
post3 = Factory.create(:post, :tag_string => "bbb ccc")
relation = Post.find_by_tags("aaa bbb")
assert_equal(1, relation.count)
assert_equal(post2.id, relation.first.id)
end
should "return posts for 1 tag with exclusion" do
post1 = Factory.create(:post, :tag_string => "aaa")
post2 = Factory.create(:post, :tag_string => "aaa bbb")
post3 = Factory.create(:post, :tag_string => "bbb ccc")
relation = Post.find_by_tags("aaa -bbb")
assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id)
end
should "return posts for 1 tag with a pattern" do
post1 = Factory.create(:post, :tag_string => "aaa")
post2 = Factory.create(:post, :tag_string => "aaab bbb")
post3 = Factory.create(:post, :tag_string => "bbb ccc")
relation = Post.find_by_tags("a*")
assert_equal(2, relation.count)
assert_equal(post2.id, relation.all[0].id)
assert_equal(post1.id, relation.all[1].id)
end
should "return posts for 2 tags, one with a pattern" do
post1 = Factory.create(:post, :tag_string => "aaa")
post2 = Factory.create(:post, :tag_string => "aaab bbb")
post3 = Factory.create(:post, :tag_string => "bbb ccc")
relation = Post.find_by_tags("a* bbb")
assert_equal(1, relation.count)
assert_equal(post2.id, relation.first.id)
end
should "return posts for the <id> metatag" do
post1 = Factory.create(:post)
post2 = Factory.create(:post)
post3 = Factory.create(:post)
relation = Post.find_by_tags("id:#{post2.id}")
assert_equal(1, relation.count)
assert_equal(post2.id, relation.first.id)
relation = Post.find_by_tags("id:>#{post2.id}")
assert_equal(1, relation.count)
assert_equal(post3.id, relation.first.id)
relation = Post.find_by_tags("id:<#{post2.id}")
assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id)
end
should "return posts for the <fav> metatag" do
post1 = Factory.create(:post)
post2 = Factory.create(:post)
post3 = Factory.create(:post)
user = Factory.create(:user)
post1.add_favorite(user)
relation = Post.find_by_tags("fav:#{user.name}")
assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id)
end
should "return posts for the <pool> metatag" do
post1 = Factory.create(:post)
post2 = Factory.create(:post)
post3 = Factory.create(:post)
pool = Factory.create(:pool)
post1.add_pool(pool)
relation = Post.find_by_tags("pool:#{pool.name}")
assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id)
end
should "return posts for the <uploader> metatag" do
second_user = Factory.create(:user)
post1 = Factory.create(:post)
CurrentUser.scoped(second_user, "127.0.0.2") do
post2 = Factory.create(:post)
post3 = Factory.create(:post)
end
relation = Post.find_by_tags("uploader:#{CurrentUser.user.name}")
assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id)
end
should "return posts for a list of md5 hashes" do
post1 = Factory.create(:post, :md5 => "abcd")
post2 = Factory.create(:post)
post3 = Factory.create(:post)
relation = Post.find_by_tags("md5:abcd")
assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id)
end
should "return posts for a source search" do
post1 = Factory.create(:post, :source => "abcd")
post2 = Factory.create(:post, :source => "abcdefg")
post3 = Factory.create(:post, :source => "xyz")
relation = Post.find_by_tags("source:abcde")
assert_equal(1, relation.count)
assert_equal(post2.id, relation.first.id)
end
should "return posts for a tag subscription search"
should "return posts for a particular rating" do
post1 = Factory.create(:post, :rating => "s")
post2 = Factory.create(:post, :rating => "q")
post3 = Factory.create(:post, :rating => "e")
relation = Post.find_by_tags("rating:e")
assert_equal(1, relation.count)
assert_equal(post3.id, relation.first.id)
end
should "return posts for a particular negated rating" do
post1 = Factory.create(:post, :rating => "s")
post2 = Factory.create(:post, :rating => "s")
post3 = Factory.create(:post, :rating => "e")
relation = Post.find_by_tags("-rating:s")
assert_equal(1, relation.count)
assert_equal(post3.id, relation.first.id)
end
should "return posts ordered by a particular attribute" do
post1 = Factory.create(:post, :rating => "s")
post2 = Factory.create(:post, :rating => "s")
post3 = Factory.create(:post, :rating => "e", :score => 5, :image_width => 1000)
relation = Post.find_by_tags("order:id")
assert_equal(post1.id, relation.first.id)
relation = Post.find_by_tags("order:mpixels")
assert_equal(post3.id, relation.first.id)
relation = Post.find_by_tags("order:landscape")
assert_equal(post3.id, relation.first.id)
end
end
context "Voting:" do
should "not allow duplicate votes" do
user = Factory.create(:user)
post = Factory.create(:post)
assert_nothing_raised {post.vote!(user, true)}
assert_raise(PostVote::Error) {post.vote!(user, true)}
post.reload
assert_equal(1, PostVote.count)
assert_equal(1, post.score)
end
end
context "Counting:" do
context "Creating a post" do
should "increment the post count" do
assert_equal(0, Post.fast_count(""))
post = Factory.create(:post, :tag_string => "aaa bbb")
assert_equal(1, Post.fast_count(""))
assert_equal(1, Post.fast_count("aaa"))
assert_equal(1, Post.fast_count("bbb"))
assert_equal(0, Post.fast_count("ccc"))
post.tag_string = "ccc"
post.save
assert_equal(1, Post.fast_count(""))
assert_equal(0, Post.fast_count("aaa"))
assert_equal(0, Post.fast_count("bbb"))
assert_equal(1, Post.fast_count("ccc"))
end
end
end
end