Skip to content

Commit

Permalink
Add validations and tests for apple feeds
Browse files Browse the repository at this point in the history
  • Loading branch information
radical-ube committed May 8, 2024
1 parent f82da83 commit 6112a95
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 51 deletions.
2 changes: 1 addition & 1 deletion app/models/feed.rb
Expand Up @@ -165,7 +165,7 @@ def normalize_category(cat)
end

def publish_to_apple?
!!apple_config&.publish_to_apple?
false
end

def include_tags=(tags)
Expand Down
41 changes: 39 additions & 2 deletions app/models/feed/apple_subscription.rb
Expand Up @@ -3,15 +3,27 @@ class Feed::AppleSubscription < Feed
DEFAULT_TITLE = "Apple Delegated Delivery Subscriptions"
DEFAULT_AUDIO_FORMAT = {"f" => "flac", "b" => 16, "c" => 2, "s" => 44100}.freeze

after_initialize :set_defaults

has_one :apple_config, class_name: "::Apple::Config", dependent: :destroy, autosave: true, validate: true
has_one :apple_key,
has_one :key,
through: :apple_config,
class_name: "Apple::Key",
dependent: :destroy,
foreign_key: :key_id

accepts_nested_attributes_for :apple_config, allow_destroy: true, reject_if: :all_blank
accepts_nested_attributes_for :apple_key, allow_destroy: true, reject_if: :all_blank
accepts_nested_attributes_for :key, allow_destroy: true, reject_if: :all_blank

validate :unchanged_defaults
validate :only_apple_feed
validate :must_be_private

def set_defaults
self.slug ||= DEFAULT_FEED_SLUG
self.title ||= DEFAULT_TITLE
self.audio_format ||= DEFAULT_AUDIO_FORMAT
end

def self.model_name
Feed.model_name
Expand Down Expand Up @@ -50,4 +62,29 @@ def self.build_apple_config(podcast, key)

Apple::Config.new(feed: find_or_build_private_feed(podcast), key: key)
end

def unchanged_defaults
return unless self.persisted?

if title_changed? || slug_changed?
errors.add(:feed, "cannot change properties once set")
end
end

def only_apple_feed
existing_feed = Feed.where(podcast_id: self.podcast_id, type: "Feed::AppleSubscription")
if existing_feed.present?
errors.add(:podcast, "cannot have more than one apple subscription")
end
end

def must_be_private
if self.private != true
errors.add(:feed, "must be a private feed")
end
end

def publish_to_apple?
!!apple_config&.publish_to_apple?
end
end
10 changes: 10 additions & 0 deletions test/factories/feed_factory.rb
Expand Up @@ -44,5 +44,15 @@
factory :public_feed do
private { false }
end

factory :apple_feed, class: "Feed::AppleSubscription" do
type { "Feed::AppleSubscription" }
private { true }
tokens { [FeedToken.new(label: "apple-private")] }

after(:build) do |feed, _evaluator|
feed.apple_config = build(:apple_config)
end
end
end
end
11 changes: 5 additions & 6 deletions test/jobs/publish_apple_job_test.rb
Expand Up @@ -4,24 +4,23 @@
let(:episode) { create(:episode, prx_uri: "/api/v1/stories/87683") }
let(:podcast) { episode.podcast }
let(:feed) { podcast.default_feed }
let(:private_feed) { create(:private_feed, podcast: podcast) }
let(:apple_config) { create(:apple_config, feed: private_feed) }
let(:apple_feed) { create(:apple_feed, podcast: podcast) }

describe "publishing to apple" do
it "does not publish to apple unless publish_enabled?" do
apple_config.update(publish_enabled: false)
apple_feed.apple_config.update(publish_enabled: false)

# test that the `publish_to_apple` method is not called
PublishAppleJob.stub(:publish_to_apple, ->(x) { raise "should not be called" }) do
assert_nil PublishAppleJob.perform_now(apple_config)
assert_nil PublishAppleJob.perform_now(apple_feed.apple_config)
end
end

it "does publish to apple if publish_enabled?" do
apple_config.update(publish_enabled: true)
apple_feed.apple_config.update(publish_enabled: true)

PublishAppleJob.stub(:publish_to_apple, :it_published!) do
assert_equal :it_published!, PublishAppleJob.perform_now(apple_config)
assert_equal :it_published!, PublishAppleJob.perform_now(apple_feed.apple_config)
end
end
end
Expand Down
38 changes: 20 additions & 18 deletions test/jobs/publish_feed_job_test.rb
Expand Up @@ -81,41 +81,41 @@
end

describe "publishing to apple" do
it "does not schedule publishing to apple if there is no apple config" do
assert_nil private_feed.apple_config
it "does not schedule publishing to apple if the feed is non-apple" do
assert_nil job.publish_apple(podcast, private_feed)
end

describe "when the apple config is present" do
let(:apple_config) { create(:apple_config, feed: private_feed) }
let(:apple_feed) { create(:apple_feed, podcast: podcast) }

it "does not schedule publishing to apple if the config is marked as not publishable" do
apple_config.update!(publish_enabled: false)
assert_equal apple_config, private_feed.apple_config.reload
assert_nil job.publish_apple(podcast, private_feed)
apple_feed.apple_config.update!(publish_enabled: false)
assert_nil job.publish_apple(podcast, apple_feed)
end

it "does run the apple publishing if the config is present and marked as publishable" do
assert_equal apple_config, private_feed.apple_config.reload
assert apple_feed.apple_config.present?
assert apple_feed.apple_config.publish_enabled
PublishAppleJob.stub(:perform_now, :publishing_apple!) do
assert_equal :publishing_apple!, job.publish_apple(podcast, private_feed)
assert_equal :publishing_apple!, job.publish_apple(podcast, apple_feed)
end
end

it "Performs the apple publishing job based regardless of sync_blocks_rss flag" do
assert_equal apple_config, private_feed.apple_config.reload
assert apple_feed.apple_config.present?
assert apple_feed.apple_config.publish_enabled

# stub the two possible ways the job can be called
# perform_later is not used.
PublishAppleJob.stub(:perform_later, :perform_later) do
PublishAppleJob.stub(:perform_now, :perform_now) do
apple_config.update!(sync_blocks_rss: true)
apple_feed.apple_config.update!(sync_blocks_rss: true)

assert_equal :perform_now, job.publish_apple(podcast, private_feed)
assert_equal :perform_now, job.publish_apple(podcast, apple_feed)

apple_config.update!(sync_blocks_rss: false)
apple_feed.apple_config.update!(sync_blocks_rss: false)
feed.reload
assert_equal :perform_now, job.publish_apple(podcast, private_feed)
assert_equal :perform_now, job.publish_apple(podcast, apple_feed)
end
end
end
Expand All @@ -128,26 +128,28 @@
PublishingPipelineState.start!(feed.podcast)
end
it "raises an error if the apple publishing fails" do
assert_equal apple_config, private_feed.apple_config.reload
assert apple_feed.apple_config.present?
assert apple_feed.apple_config.publish_enabled

PublishAppleJob.stub(:perform_now, ->(*, **) { raise "some apple error" }) do
# it raises
assert_raises(RuntimeError) { job.publish_apple(podcast, private_feed) }
assert_raises(RuntimeError) { job.publish_apple(podcast, apple_feed) }

assert_equal ["created", "started", "error_apple"].sort, PublishingPipelineState.where(podcast: feed.podcast).latest_pipelines.pluck(:status).sort
end
end

it "does not raise an error if the apple publishing is not blocking RSS" do
assert_equal apple_config, private_feed.apple_config.reload
private_feed.apple_config.update!(sync_blocks_rss: false)
assert apple_feed.apple_config.present?
assert apple_feed.apple_config.publish_enabled
apple_feed.apple_config.update!(sync_blocks_rss: false)

mock = Minitest::Mock.new
mock.expect(:call, nil, [RuntimeError])

PublishAppleJob.stub(:perform_now, ->(*, **) { raise "some apple error" }) do
NewRelic::Agent.stub(:notice_error, mock) do
job.publish_apple(podcast, private_feed)
job.publish_apple(podcast, apple_feed)
end
end
assert_equal ["created", "started", "error_apple"].sort, PublishingPipelineState.where(podcast: feed.podcast).latest_pipelines.pluck(:status).sort
Expand Down
65 changes: 65 additions & 0 deletions test/models/feed/apple_subscription_test.rb
@@ -0,0 +1,65 @@
require "test_helper"

describe Feed::AppleSubscription do
let(:podcast) { create(:podcast) }
let(:feed_1) { podcast.default_feed }
let(:apple_feed) { build(:apple_feed, podcast: podcast) }

describe "#valid?" do
it "cannot change the default properties once saved" do
apple_feed.title = "new apple feed"
apple_feed.slug = "new-apple-slug"
assert apple_feed.valid?
apple_feed.save!

apple_feed.title = "changed apple feed"
refute apple_feed.valid?
apple_feed.title = "new apple feed"
apple_feed.slug = "changed-apple-slug"
refute apple_feed.valid?
end

it "cannot have more than one apple feed on a single podcast" do
second_apple = build(:apple_feed, podcast: podcast)
assert second_apple.valid?

apple_feed.save!
refute second_apple.valid?
end

it "must be a private feed" do
apple_feed.private = false
refute apple_feed.valid?
end
end

describe "#apple_configs" do
it "has apple credentials" do
assert apple_feed.apple_config.present?
assert apple_feed.apple_config.valid?

apple_feed.save!
assert_equal feed_1, apple_feed.apple_config.public_feed
end
end

describe "#publish_to_apple?" do
it "returns true if the feed has apple credentials" do
apple_feed.save!

refute feed_1.publish_to_apple?
assert apple_feed.publish_to_apple?
end

it "returns false if the creds are not marked publish_enabled?" do
apple_feed.apple_config.publish_enabled = false
apple_feed.save!
refute apple_feed.publish_to_apple?
end

it "returns false if the feed is not an Apple Subscription feed" do
refute_equal feed_1.type, "Feed::AppleSubscription"
refute feed_1.publish_to_apple?
end
end
end
23 changes: 2 additions & 21 deletions test/models/feed_test.rb
Expand Up @@ -324,28 +324,9 @@
end
end

describe "#apple_configs" do
it "has apple credentials" do
creds = create(:apple_config, feed: feed2)
assert_equal creds, feed2.apple_config
assert_equal feed1, feed2.apple_config.public_feed
end
end

describe "#publish_to_apple?" do
it "returns true if the feed has apple credentials" do
create(:apple_config, feed: feed2, publish_enabled: true)
refute feed1.publish_to_apple?
assert feed2.publish_to_apple?
end

it "returns false if the creds are not marked publish_enabled?" do
create(:apple_config, feed: feed2, publish_enabled: false)
refute feed2.publish_to_apple?
end

it "returns false if the feed does not have apple credentials" do
refute feed2.apple_config
it "returns false if the feed is not an Apple Subscription feed" do
refute_equal feed2.type, "Feed::AppleSubscription"
refute feed2.publish_to_apple?
end
end
Expand Down
5 changes: 2 additions & 3 deletions test/models/publishing_pipeline_state_test.rb
Expand Up @@ -298,11 +298,10 @@
describe "Apple publishing" do
let(:f1) { podcast.default_feed }
let(:f2) { create(:private_feed, podcast: podcast) }
let(:f3) { create(:private_feed, podcast: podcast) }
let(:apple_config) { create(:apple_config, feed: f3, publish_enabled: true) }
let(:f3) { create(:apple_feed, podcast: podcast) }

it "can publish via the apple configs" do
assert [f1, f2, f3, apple_config]
assert [f1, f2, f3]

PublishAppleJob.stub(:perform_now, "published apple!") do
PublishFeedJob.stub_any_instance(:save_file, "saved rss!") do
Expand Down
1 change: 1 addition & 0 deletions test/test_helper.rb
Expand Up @@ -19,6 +19,7 @@
ENV["APPLE_KEY_PEM_B64"] =
"LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUhHWUUvUVBZVWtkVUFmczcyZ1FUQkE5aTVBNkRndklFOGlpV3RrQzFScDdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFaHFJSFVZUDN3QmxMdnMvQVpLM1ZHdW0vai8rMkhnVVF6dDc4TFQ0blMrckkxSlZJT0ZyVQpSVUZ6NmtSZ0pFeGxyZjdvSGZxZkxZanZGM0JvT3pmbWx3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQ=="
ENV["APPLE_API_BRIDGE_URL"] = "http://localhost:3000"
ENV["SLACK_CHANNEL_ID"] = ""

ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
Expand Down

0 comments on commit 6112a95

Please sign in to comment.