mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
Previously, the RSS Polling plugin's admin page predated Discourse's admin interface guidelines: it was a single inline-editable table with no breadcrumbs or page header, it truncated long feed URLs, it required horizontal scrolling on mobile, and it gave admins no way to verify a feed before saving it. This change rebuilds the page on the standard plugin "show route" structure (breadcrumbs, page header, and Settings + Feeds tabs) with a `d-table` feed list and dedicated FormKit new/edit routes, so the UI now matches the rest of the admin interface and works on mobile. It also: - Adds a **Test feed** dry-run that fetches a feed and previews which items would be imported or skipped, with plain-language reasons, so admins can validate a feed (and fix setup errors) before saving it. - Adds the `rss_polling_feed_request_timeout` and `rss_polling_verbose_logging` site settings. - Extracts the fetch/parse and import/skip logic into `FeedFetcher` and `FeedAnalyzer`, shared by the poll job and the new preview so the dry-run and the real import always agree. - Normalizes feed dates and categories so Atom feeds (which use `<updated>` and `term`-style `<category>` elements) are handled like RSS, and returns a clean error instead of a 500 when a feed cannot be read. --------- Co-authored-by: Martin Brennan <martin@discourse.org>
65 lines
2.2 KiB
Ruby
Vendored
65 lines
2.2 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe Jobs::DiscourseRssPolling::PollAllFeeds do
|
|
subject(:job) { described_class.new }
|
|
|
|
fab!(:user_a) { Fabricate(:user, username: "feed_user_a") }
|
|
fab!(:user_b) { Fabricate(:user, username: "feed_user_b") }
|
|
|
|
before { SiteSetting.rss_polling_enabled = true }
|
|
|
|
describe "#execute" do
|
|
fab!(:feed_a) { Fabricate(:rss_feed, url: "https://www.example.com/feed", user: user_a) }
|
|
fab!(:feed_b) { Fabricate(:rss_feed, url: "https://blog.discourse.org/feed/", user: user_b) }
|
|
|
|
before do
|
|
Jobs.run_later!
|
|
Discourse.redis.del("rss-polling-feeds-polled")
|
|
end
|
|
|
|
it "queues a PollFeed job per feed with the right user_id" do
|
|
Sidekiq::Testing.fake! do
|
|
expect { job.execute({}) }.to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }.by(2)
|
|
|
|
enqueued = Jobs::DiscourseRssPolling::PollFeed.jobs.last(2).map { |j| j["args"][0] }
|
|
|
|
expect(enqueued).to contain_exactly(
|
|
hash_including("feed_url" => "https://www.example.com/feed", "user_id" => user_a.id),
|
|
hash_including("feed_url" => "https://blog.discourse.org/feed/", "user_id" => user_b.id),
|
|
)
|
|
end
|
|
end
|
|
|
|
it "is rate limited" do
|
|
Sidekiq::Testing.fake! do
|
|
expect { job.execute({}) }.to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }.by(2)
|
|
expect { job.execute({}) }.not_to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }
|
|
end
|
|
end
|
|
|
|
context "when the plugin is disabled" do
|
|
before { SiteSetting.rss_polling_enabled = false }
|
|
|
|
it "does not queue PollFeed jobs" do
|
|
Sidekiq::Testing.fake! do
|
|
expect { job.execute({}) }.not_to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a feed is disabled" do
|
|
before { feed_a.update!(enabled: false) }
|
|
|
|
it "only queues a PollFeed job for the enabled feeds" do
|
|
Sidekiq::Testing.fake! do
|
|
expect { job.execute({}) }.to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }.by(
|
|
1,
|
|
)
|
|
|
|
enqueued = Jobs::DiscourseRssPolling::PollFeed.jobs.last["args"][0]
|
|
expect(enqueued["feed_url"]).to eq("https://blog.discourse.org/feed/")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|