discourse/spec/jobs/process_post_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

129 lines
4.4 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
RSpec.describe Jobs::ProcessPost do
2013-02-06 03:16:51 +08:00
it "returns when the post cannot be found" do
DEV: Fix threading error when running jobs immediately in system tests (#19811) ``` class Jobs::DummyDelayedJob < Jobs::Base def execute(args = {}) end end RSpec.describe "Jobs.run_immediately!" do before { Jobs.run_immediately! } it "explodes" do current_user = Fabricate(:user) Jobs.enqueue_in(1.seconds, :dummy_delayed_job) sign_in(current_user) end end ``` The test above will fail with the following error if `ActiveRecord::Base.connection_handler.clear_active_connections!` is called before the configured Capybara server checks out a connection from the connection pool. ``` ActiveRecord::ActiveRecordError: Cannot expire connection, it is owned by a different thread: #<Thread:0x00007f437391df58@puma srv tp 001 /home/tgxworld/.asdf/installs/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/puma-6.0.2/lib/puma/thread_pool.rb:106 sleep_forever>. Current thread: #<Thread:0x00007f437d6cfc60 run>. ``` We're not exactly sure if this is an ActiveRecord bug or not but we've invested too much time into investigating this problem. Fundamentally, we also no longer understand why `ActiveRecord::Base.connection_handler.clear_active_connections!` is being called in an ensure block within `Jobs::Base#perform` which was added in ceddb6e0da92e874b3bee9543915726f1d27d60b 10 years ago. This commit moves the logic for running jobs immediately out of the `Jobs::Base#perform` method into another `Jobs::Base#perform_immediately` method such that `ActiveRecord::Base.connection_handler.clear_active_connections!` is not called. This change will only impact the test environment.
2023-01-10 13:41:25 +08:00
expect { Jobs::ProcessPost.new.execute(post_id: 1) }.not_to raise_error
2013-02-06 03:16:51 +08:00
end
context "with a post" do
fab!(:post)
2013-02-06 03:16:51 +08:00
2014-12-07 15:11:38 +08:00
it "does not erase posts when CookedPostProcessor malfunctions" do
# Look kids, an actual reason why you want to use mocks
CookedPostProcessor.any_instance.expects(:html).returns(" ")
cooked = post.cooked
post.reload
expect(post.cooked).to eq(cooked)
2014-12-07 15:11:38 +08:00
Jobs::ProcessPost.new.execute(post_id: post.id, cook: true)
2013-02-06 03:16:51 +08:00
end
2014-12-07 15:11:38 +08:00
it "recooks if needed" do
cooked = post.cooked
post.update_columns(cooked: "frogs")
Jobs::ProcessPost.new.execute(post_id: post.id, cook: true)
post.reload
expect(post.cooked).to eq(cooked)
2013-02-06 03:16:51 +08:00
end
2014-12-07 15:11:38 +08:00
it "processes posts" do
post =
Fabricate(:post, raw: "<img src='#{Discourse.base_url_no_prefix}/awesome/picture.png'>")
expect(post.cooked).to match(/http/)
stub_image_size
2014-12-07 15:11:38 +08:00
Jobs::ProcessPost.new.execute(post_id: post.id)
post.reload
# subtle but cooked post processor strip this stuff, this ensures all the code gets a workout
expect(post.cooked).not_to match(/http/)
2013-02-26 00:42:20 +08:00
end
2013-02-06 03:16:51 +08:00
it "always re-extracts links on post process" do
post.update_columns(raw: "sam has a blog at https://samsaffron.com")
2017-01-31 16:40:56 +08:00
expect { Jobs::ProcessPost.new.execute(post_id: post.id) }.to change { TopicLink.count }.by(1)
end
it "extracts links to quoted posts" do
quoted_post =
Fabricate(
:post,
raw: "This is a post with a link to https://www.discourse.org",
post_number: 42,
)
post.update_columns(
raw:
"This quote is the best\n\n[quote=\"#{quoted_post.user.username}, topic:#{quoted_post.topic_id}, post:#{quoted_post.post_number}\"]\n#{quoted_post.excerpt}\n[/quote]",
)
stub_image_size
# when creating a quote, we also create the reflexion link
expect { Jobs::ProcessPost.new.execute(post_id: post.id) }.to change { TopicLink.count }.by(2)
end
2013-02-06 03:16:51 +08:00
it "extracts links to oneboxed topics" do
oneboxed_post = Fabricate(:post)
post.update_columns(raw: "This post is the best\n\n#{oneboxed_post.full_url}")
stub_image_size
# when creating a quote, we also create the reflexion link
expect { Jobs::ProcessPost.new.execute(post_id: post.id) }.to change { TopicLink.count }.by(2)
end
it "works for posts that belong to no existing user" do
cooked = post.cooked
post.update_columns(cooked: "frogs", user_id: nil)
Jobs::ProcessPost.new.execute(post_id: post.id, cook: true)
post.reload
expect(post.cooked).to eq(cooked)
post.update_columns(cooked: "frogs", user_id: User.maximum("id") + 1)
Jobs::ProcessPost.new.execute(post_id: post.id, cook: true)
post.reload
expect(post.cooked).to eq(cooked)
end
it "updates the topic excerpt when first post" do
post = Fabricate(:post, raw: "Some OP content", cooked: "")
post.topic.update_excerpt("Incorrect")
Jobs::ProcessPost.new.execute(post_id: post.id)
expect(post.topic.reload.excerpt).to eq("Some OP content")
post2 = Fabricate(:post, raw: "Some reply content", cooked: "", topic: post.topic)
Jobs::ProcessPost.new.execute(post_id: post2.id)
expect(post.topic.reload.excerpt).to eq("Some OP content")
end
end
describe "#enqueue_pull_hotlinked_images" do
fab!(:post) { Fabricate(:post, created_at: 20.days.ago) }
let(:job) { Jobs::ProcessPost.new }
it "runs even when download_remote_images_to_local is disabled" do
# We want to run it to pull hotlinked optimized images
SiteSetting.download_remote_images_to_local = false
expect_enqueued_with(job: :pull_hotlinked_images, args: { post_id: post.id }) do
job.execute({ post_id: post.id })
end
end
context "when download_remote_images_to_local? is enabled" do
before { SiteSetting.download_remote_images_to_local = true }
it "enqueues" do
expect_enqueued_with(job: :pull_hotlinked_images, args: { post_id: post.id }) do
job.execute({ post_id: post.id })
end
end
it "does not run when requested to skip" do
job.execute({ post_id: post.id, skip_pull_hotlinked_images: true })
expect(Jobs::PullHotlinkedImages.jobs.size).to eq(0)
end
end
end
2013-02-06 03:16:51 +08:00
end