mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-08-02 19:33:38 +00:00
260 lines
7.8 KiB
Ruby
260 lines
7.8 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
RSpec.describe Jobs::GenerateConceptsFromPopularItems do
|
||
|
fab!(:topic) { Fabricate(:topic, posts_count: 6, views: 150, like_count: 12) }
|
||
|
fab!(:post) { Fabricate(:post, like_count: 8, post_number: 2) }
|
||
|
|
||
|
before do
|
||
|
SiteSetting.inferred_concepts_enabled = true
|
||
|
SiteSetting.inferred_concepts_daily_topics_limit = 20
|
||
|
SiteSetting.inferred_concepts_daily_posts_limit = 30
|
||
|
SiteSetting.inferred_concepts_min_posts = 5
|
||
|
SiteSetting.inferred_concepts_min_likes = 10
|
||
|
SiteSetting.inferred_concepts_min_views = 100
|
||
|
SiteSetting.inferred_concepts_post_min_likes = 5
|
||
|
SiteSetting.inferred_concepts_lookback_days = 30
|
||
|
SiteSetting.inferred_concepts_background_match = false
|
||
|
end
|
||
|
|
||
|
describe "#execute" do
|
||
|
it "does nothing when inferred_concepts_enabled is false" do
|
||
|
SiteSetting.inferred_concepts_enabled = false
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).not_to receive(
|
||
|
:find_candidate_topics,
|
||
|
)
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).not_to receive(
|
||
|
:find_candidate_posts,
|
||
|
)
|
||
|
allow(Jobs).to receive(:enqueue)
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
|
||
|
it "processes popular topics when enabled" do
|
||
|
candidate_topics = [topic]
|
||
|
|
||
|
freeze_time do
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).with(
|
||
|
limit: 20,
|
||
|
min_posts: 5,
|
||
|
min_likes: 10,
|
||
|
min_views: 100,
|
||
|
created_after: 30.days.ago,
|
||
|
).and_return(candidate_topics)
|
||
|
|
||
|
allow(Jobs).to receive(:enqueue).with(
|
||
|
:generate_inferred_concepts,
|
||
|
item_type: "topics",
|
||
|
item_ids: [topic.id],
|
||
|
batch_size: 10,
|
||
|
)
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).and_return([])
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "processes popular posts when enabled" do
|
||
|
candidate_posts = [post]
|
||
|
|
||
|
freeze_time do
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).and_return([])
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).with(
|
||
|
limit: 30,
|
||
|
min_likes: 5,
|
||
|
exclude_first_posts: true,
|
||
|
created_after: 30.days.ago,
|
||
|
).and_return(candidate_posts)
|
||
|
|
||
|
allow(Jobs).to receive(:enqueue).with(
|
||
|
:generate_inferred_concepts,
|
||
|
item_type: "posts",
|
||
|
item_ids: [post.id],
|
||
|
batch_size: 10,
|
||
|
)
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "schedules background matching jobs when enabled" do
|
||
|
SiteSetting.inferred_concepts_background_match = true
|
||
|
|
||
|
candidate_topics = [topic]
|
||
|
candidate_posts = [post]
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).and_return(candidate_topics)
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).and_return(candidate_posts)
|
||
|
|
||
|
# Expect generation jobs
|
||
|
allow(Jobs).to receive(:enqueue).with(
|
||
|
:generate_inferred_concepts,
|
||
|
item_type: "topics",
|
||
|
item_ids: [topic.id],
|
||
|
batch_size: 10,
|
||
|
)
|
||
|
|
||
|
allow(Jobs).to receive(:enqueue).with(
|
||
|
:generate_inferred_concepts,
|
||
|
item_type: "posts",
|
||
|
item_ids: [post.id],
|
||
|
batch_size: 10,
|
||
|
)
|
||
|
|
||
|
# Expect background matching jobs
|
||
|
allow(Jobs).to receive(:enqueue_in).with(
|
||
|
1.hour,
|
||
|
:generate_inferred_concepts,
|
||
|
item_type: "topics",
|
||
|
item_ids: [topic.id],
|
||
|
batch_size: 10,
|
||
|
match_only: true,
|
||
|
)
|
||
|
|
||
|
allow(Jobs).to receive(:enqueue_in).with(
|
||
|
1.hour,
|
||
|
:generate_inferred_concepts,
|
||
|
item_type: "posts",
|
||
|
item_ids: [post.id],
|
||
|
batch_size: 10,
|
||
|
match_only: true,
|
||
|
)
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
|
||
|
it "does not schedule jobs when no candidates found" do
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).and_return([])
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).and_return([])
|
||
|
|
||
|
allow(Jobs).to receive(:enqueue)
|
||
|
allow(Jobs).to receive(:enqueue_in)
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
|
||
|
it "uses site setting values for topic filtering" do
|
||
|
SiteSetting.inferred_concepts_daily_topics_limit = 50
|
||
|
SiteSetting.inferred_concepts_min_posts = 8
|
||
|
SiteSetting.inferred_concepts_min_likes = 15
|
||
|
SiteSetting.inferred_concepts_min_views = 200
|
||
|
SiteSetting.inferred_concepts_lookback_days = 45
|
||
|
|
||
|
freeze_time do
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).with(
|
||
|
limit: 50,
|
||
|
min_posts: 8,
|
||
|
min_likes: 15,
|
||
|
min_views: 200,
|
||
|
created_after: 45.days.ago,
|
||
|
).and_return([])
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).and_return([])
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "uses site setting values for post filtering" do
|
||
|
SiteSetting.inferred_concepts_daily_posts_limit = 40
|
||
|
SiteSetting.inferred_concepts_post_min_likes = 8
|
||
|
SiteSetting.inferred_concepts_lookback_days = 45
|
||
|
|
||
|
freeze_time do
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).and_return([])
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).with(
|
||
|
limit: 40,
|
||
|
min_likes: 8,
|
||
|
exclude_first_posts: true,
|
||
|
created_after: 45.days.ago,
|
||
|
).and_return([])
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "handles nil site setting values gracefully" do
|
||
|
SiteSetting.inferred_concepts_daily_topics_limit = nil
|
||
|
SiteSetting.inferred_concepts_daily_posts_limit = nil
|
||
|
SiteSetting.inferred_concepts_min_posts = nil
|
||
|
SiteSetting.inferred_concepts_min_likes = nil
|
||
|
SiteSetting.inferred_concepts_min_views = nil
|
||
|
SiteSetting.inferred_concepts_post_min_likes = nil
|
||
|
# Keep lookback_days at default so .days.ago doesn't fail
|
||
|
|
||
|
freeze_time do
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).with(
|
||
|
limit: 0, # nil becomes 0
|
||
|
min_posts: 0, # nil becomes 0
|
||
|
min_likes: 0, # nil becomes 0
|
||
|
min_views: 0, # nil becomes 0
|
||
|
created_after: 30.days.ago, # default from before block
|
||
|
).and_return([])
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).with(
|
||
|
limit: 0, # nil becomes 0
|
||
|
min_likes: 0, # nil becomes 0
|
||
|
exclude_first_posts: true,
|
||
|
created_after: 30.days.ago, # default from before block
|
||
|
).and_return([])
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "processes both topics and posts in the same run" do
|
||
|
candidate_topics = [topic]
|
||
|
candidate_posts = [post]
|
||
|
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_topics,
|
||
|
).and_return(candidate_topics)
|
||
|
expect_any_instance_of(DiscourseAi::InferredConcepts::Manager).to receive(
|
||
|
:find_candidate_posts,
|
||
|
).and_return(candidate_posts)
|
||
|
|
||
|
allow(Jobs).to receive(:enqueue).twice
|
||
|
|
||
|
subject.execute({})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "when scheduling the job" do
|
||
|
it "is scheduled to run daily" do
|
||
|
expect(described_class.every).to eq(1.day)
|
||
|
end
|
||
|
end
|
||
|
end
|