diff --git a/app/models/feed.rb b/app/models/feed.rb index 695411974..8ea3eecf1 100644 --- a/app/models/feed.rb +++ b/app/models/feed.rb @@ -165,7 +165,7 @@ def normalize_category(cat) end def publish_to_apple? - !!apple_config&.publish_to_apple? + false end def include_tags=(tags) diff --git a/app/models/feed/apple_subscription.rb b/app/models/feed/apple_subscription.rb index 4d8224e52..c823717e6 100644 --- a/app/models/feed/apple_subscription.rb +++ b/app/models/feed/apple_subscription.rb @@ -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 @@ -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 diff --git a/test/factories/feed_factory.rb b/test/factories/feed_factory.rb index cc1a947cd..3ecdcd8b0 100644 --- a/test/factories/feed_factory.rb +++ b/test/factories/feed_factory.rb @@ -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 diff --git a/test/jobs/publish_apple_job_test.rb b/test/jobs/publish_apple_job_test.rb index 8fd396277..c5d6c7b10 100644 --- a/test/jobs/publish_apple_job_test.rb +++ b/test/jobs/publish_apple_job_test.rb @@ -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 diff --git a/test/jobs/publish_feed_job_test.rb b/test/jobs/publish_feed_job_test.rb index a49885157..5ac462022 100644 --- a/test/jobs/publish_feed_job_test.rb +++ b/test/jobs/publish_feed_job_test.rb @@ -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 @@ -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 diff --git a/test/models/feed/apple_subscription_test.rb b/test/models/feed/apple_subscription_test.rb new file mode 100644 index 000000000..7c3c7993d --- /dev/null +++ b/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 diff --git a/test/models/feed_test.rb b/test/models/feed_test.rb index a20d76191..79a658e94 100644 --- a/test/models/feed_test.rb +++ b/test/models/feed_test.rb @@ -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 diff --git a/test/models/publishing_pipeline_state_test.rb b/test/models/publishing_pipeline_state_test.rb index 4239e4e77..4f3803f0c 100644 --- a/test/models/publishing_pipeline_state_test.rb +++ b/test/models/publishing_pipeline_state_test.rb @@ -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 diff --git a/test/test_helper.rb b/test/test_helper.rb index b870b61a7..fedf3d230 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -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"