# frozen_string_literal: true RSpec.describe BookmarkQuery do before { SearchIndexer.enable } fab!(:user) def bookmark_query(user: nil, search_term: nil, per_page: nil) BookmarkQuery.new(user: user || self.user, search_term:, per_page:) end describe "#list_all" do before do register_test_bookmarkable Fabricate(:topic_user, user: user, topic: post_bookmark.bookmarkable.topic) Fabricate(:topic_user, user: user, topic: topic_bookmark.bookmarkable) user_bookmark end after { DiscoursePluginRegistry.reset! } let(:post_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:post)) } let(:topic_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:topic)) } let(:user_bookmark) do Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:user, username: "bookmarkqueen")) end it "returns all the bookmarks for a user" do expect(bookmark_query.list_all.count).to eq(3) end it "does not return deleted bookmarkables" do post_bookmark.bookmarkable.trash! topic_bookmark.bookmarkable.trash! expect(bookmark_query.list_all.count).to eq(1) end it "runs the on_preload block provided passing in bookmarks" do preloaded_bookmarks = [] BookmarkQuery.on_preload { |bookmarks, bq| (preloaded_bookmarks << bookmarks).flatten } bookmark_query.list_all expect(preloaded_bookmarks.any?).to eq(true) end it "returns a mixture of post, topic, and custom bookmarkable type bookmarks" do bookmarks = bookmark_query.list_all expect(bookmarks.map(&:id)).to match_array( [post_bookmark.id, topic_bookmark.id, user_bookmark.id], ) end it "handles the user not having permission for all of the bookmarks of a certain bookmarkable" do UserTestBookmarkable.expects(:list_query).returns(nil) bookmarks = bookmark_query.list_all expect(bookmarks.map(&:id)).to match_array([post_bookmark.id, topic_bookmark.id]) end it "handles the user not having permission to see any of their bookmarks" do topic_bookmark.bookmarkable.update( category: Fabricate(:private_category, group: Fabricate(:group)), ) post_bookmark.bookmarkable.topic.update(category: topic_bookmark.bookmarkable.category) UserTestBookmarkable.expects(:list_query).returns(nil) bookmarks = bookmark_query.list_all expect(bookmarks.map(&:id)).to eq([]) end context "when search_term is provided" do let!(:post) do Fabricate( :post, raw: "Some post content here", topic: Fabricate(:topic, title: "Bugfix game for devs"), ) end after { DiscoursePluginRegistry.reset! } let(:bookmark3) do Fabricate(:bookmark, user: user, name: "Check up later", bookmarkable: Fabricate(:post)) end let(:bookmark4) { Fabricate(:bookmark, user: user, bookmarkable: post) } before do Fabricate(:topic_user, user: user, topic: bookmark3.bookmarkable.topic) Fabricate(:topic_user, user: user, topic: bookmark4.bookmarkable.topic) end it "can search by bookmark name" do bookmarks = bookmark_query(search_term: "check").list_all expect(bookmarks.map(&:id)).to eq([bookmark3.id]) end it "can search by post content" do bookmarks = bookmark_query(search_term: "content").list_all expect(bookmarks.map(&:id)).to eq([bookmark4.id]) end it "can search by topic title" do bookmarks = bookmark_query(search_term: "bugfix").list_all expect(bookmarks.map(&:id)).to eq([bookmark4.id]) end context "with custom bookmarkable fitering" do before { register_test_bookmarkable } after { DiscoursePluginRegistry.reset! } let!(:bookmark5) do Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:user, username: "bookmarkking")) end it "allows searching bookmarkables by fields in other tables" do bookmarks = bookmark_query(search_term: "bookmarkk").list_all expect(bookmarks.map(&:id)).to eq([bookmark5.id]) end end end context "for a whispered post" do before do post_bookmark.bookmarkable.update(post_type: Post.types[:whisper]) SiteSetting.whispers_allowed_groups = "#{Group::AUTO_GROUPS[:staff]}" end fab!(:whisperers_group) { Fabricate(:group) } context "when the user is moderator" do it "does return the whispered post" do user.grant_moderation! expect(bookmark_query.list_all.count).to eq(3) end end context "when the user is admin" do it "does return the whispered post" do user.grant_admin! expect(bookmark_query.list_all.count).to eq(3) end end context "when the user is a member of whisperers group" do it "returns the whispered post" do SiteSetting.whispers_allowed_groups = "#{whisperers_group.id}" user.update!(groups: [whisperers_group]) expect(bookmark_query.list_all.count).to eq(3) end end context "when the user is not staff" do it "does not return the whispered post" do expect(bookmark_query.list_all.count).to eq(2) end end end context "for a private message topic bookmark" do let(:pm_topic) { Fabricate(:private_message_topic) } before do post_bookmark.update(bookmarkable: Fabricate(:post, topic: pm_topic)) TopicUser.change(user.id, pm_topic.id, total_msecs_viewed: 1) end context "when the user is a topic_allowed_user" do before { TopicAllowedUser.create(topic: pm_topic, user: user) } it "shows the user the bookmark in the PM" do expect(bookmark_query.list_all.map(&:id).count).to eq(3) end end context "when the user is in a topic_allowed_group" do before do group = Fabricate(:group) GroupUser.create(group: group, user: user) TopicAllowedGroup.create(topic: pm_topic, group: group) end it "shows the user the bookmark in the PM" do expect(bookmark_query.list_all.map(&:id).count).to eq(3) end end context "when the user is not a topic_allowed_user" do it "does not show the user a bookmarked post in a PM where they are not an allowed user" do expect(bookmark_query.list_all.map(&:id).count).to eq(2) end end context "when the user is not in a topic_allowed_group" do it "does not show the user a bookmarked post in a PM where they are not in an allowed group" do expect(bookmark_query.list_all.map(&:id).count).to eq(2) end end end context "when the topic category is private" do let(:group) { Fabricate(:group) } before do post_bookmark.bookmarkable.topic.update( category: Fabricate(:private_category, group: group), ) post_bookmark.reload end it "does not show the user a post/topic in a private category they cannot see" do expect(bookmark_query.list_all.map(&:id)).not_to include(post_bookmark.id) end it "does show the user a post/topic in a private category they can see" do GroupUser.create(user: user, group: group) expect(bookmark_query.list_all.map(&:id)).to include(post_bookmark.id) end end context "when the per_page is provided" do it "is respected" do expect(bookmark_query(per_page: 1).list_all.count).to eq(1) end end end describe "#list_all ordering" do let!(:bookmark1) { Fabricate(:bookmark, user: user, updated_at: 1.day.ago, reminder_at: nil) } let!(:bookmark2) { Fabricate(:bookmark, user: user, updated_at: 2.days.ago, reminder_at: nil) } let!(:bookmark3) { Fabricate(:bookmark, user: user, updated_at: 6.days.ago, reminder_at: nil) } let!(:bookmark4) { Fabricate(:bookmark, user: user, updated_at: 4.days.ago, reminder_at: nil) } let!(:bookmark5) { Fabricate(:bookmark, user: user, updated_at: 3.days.ago, reminder_at: nil) } before do [bookmark1, bookmark2, bookmark3, bookmark4, bookmark5].each do |bm| Fabricate(:topic_user, topic: bm.bookmarkable.topic, user: user) bm.reload end end it "order defaults to updated_at DESC" do expect(bookmark_query.list_all.map(&:id)).to eq( [bookmark1.id, bookmark2.id, bookmark5.id, bookmark4.id, bookmark3.id], ) end it "orders by reminder_at, then updated_at" do bookmark4.update_column(:reminder_at, 1.day.from_now) bookmark5.update_column(:reminder_at, 26.hours.from_now) expect(bookmark_query.list_all.map(&:id)).to eq( [bookmark4.id, bookmark5.id, bookmark1.id, bookmark2.id, bookmark3.id], ) end it "shows pinned bookmarks first ordered by reminder_at ASC then updated_at DESC" do bookmark3.update_column(:pinned, true) bookmark3.update_column(:reminder_at, 1.day.from_now) bookmark4.update_column(:pinned, true) bookmark4.update_column(:reminder_at, 28.hours.from_now) bookmark1.update_column(:pinned, true) bookmark2.update_column(:pinned, true) bookmark5.update_column(:reminder_at, 1.day.from_now) expect(bookmark_query.list_all.map(&:id)).to eq( [bookmark3.id, bookmark4.id, bookmark1.id, bookmark2.id, bookmark5.id], ) end end end