Made published_at immutable after an article has been published once (#18384)
* Don't change published_at for articles that have already been published (even if unpublished later) * Removed unused code related to changing published_at * Added specs for updating published_from_feed articles, fixed specs * Removed old validation * Added specs for article validation published_from_feed * Added and reorganized specs for the Article model (setting published_at) * Remove the commented code, added a spec * Added specs for unpublishing * Removed unused update_published_at from article attributes spec * Fixed nullifying published_at seconds when republishing from rich editor
This commit is contained in:
parent
d0cac66353
commit
6ef1968377
8 changed files with 292 additions and 95 deletions
|
|
@ -33,8 +33,9 @@ export const Options = ({
|
|||
let existingSeries = '';
|
||||
let publishedAtField = '';
|
||||
|
||||
const wasScheduled = moment(publishedAtWas) > moment();
|
||||
const readonlyPublishedAt = published && !wasScheduled;
|
||||
const wasScheduled = publishedAtWas && moment(publishedAtWas) > moment();
|
||||
// allow to edit published at if it was not set earlier or if it's in the future
|
||||
const editablePublishedAt = !publishedAtWas || wasScheduled;
|
||||
|
||||
if (allSeries.length > 0) {
|
||||
const seriesNames = allSeries.map((name, index) => {
|
||||
|
|
@ -92,7 +93,7 @@ export const Options = ({
|
|||
}
|
||||
}
|
||||
|
||||
if (schedulingEnabled && !readonlyPublishedAt) {
|
||||
if (schedulingEnabled && editablePublishedAt) {
|
||||
const currentDate = moment().format('YYYY-MM-DD');
|
||||
publishedAtField = (
|
||||
<div className="crayons-field mb-6">
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ class Article < ApplicationRecord
|
|||
validates :video_state, inclusion: { in: %w[PROGRESSING COMPLETED] }, allow_nil: true
|
||||
validates :video_thumbnail_url, url: { allow_blank: true, schemes: %w[https http] }
|
||||
validate :future_or_current_published_at, on: :create
|
||||
validate :has_correct_published_at?, on: :update, unless: :admin_update
|
||||
validate :correct_published_at?, on: :update, unless: :admin_update
|
||||
|
||||
validate :canonical_url_must_not_have_spaces
|
||||
validate :validate_collection_permission
|
||||
|
|
@ -822,14 +822,22 @@ class Article < ApplicationRecord
|
|||
errors.add(:published_at, I18n.t("models.article.future_or_current_published_at"))
|
||||
end
|
||||
|
||||
def has_correct_published_at?
|
||||
return unless published_at_was && published
|
||||
# don't allow editing published_at if an article has already been published
|
||||
# allow changes within one minute in case of editing via frontmatter w/o specifying seconds
|
||||
return unless published_was && published_at_was < Time.current &&
|
||||
changes["published_at"] && !(published_at_was - published_at).between?(-60, 60)
|
||||
def correct_published_at?
|
||||
return unless changes["published_at"]
|
||||
|
||||
errors.add(:published_at, I18n.t("models.article.immutable_published_at"))
|
||||
# for drafts (that were never published before) or scheduled articles => allow future or current dates
|
||||
if !published_at_was || published_at_was > Time.current
|
||||
# for articles published_from_feed (exported from rss) we allow past published_at
|
||||
if (!published_at || published_at < 15.minutes.ago) && !published_from_feed
|
||||
errors.add(:published_at, I18n.t("models.article.future_or_current_published_at"))
|
||||
end
|
||||
else
|
||||
# for articles that have been published already (published or unpublished drafts) => immutable published_at
|
||||
# allow changes within one minute in case of editing via frontmatter w/o specifying seconds
|
||||
has_nils = changes["published_at"].include?(nil) # changes from nil or to nil
|
||||
close_enough = !has_nils && (published_at_was - published_at).between?(-60, 60)
|
||||
errors.add(:published_at, I18n.t("models.article.immutable_published_at")) if has_nils || !close_enough
|
||||
end
|
||||
end
|
||||
|
||||
def canonical_url_must_not_have_spaces
|
||||
|
|
|
|||
|
|
@ -11,17 +11,13 @@ module Articles
|
|||
@article_user = article_user
|
||||
end
|
||||
|
||||
def for_update(update_edited_at: false, update_published_at: false)
|
||||
def for_update(update_edited_at: false)
|
||||
hash = attributes.slice(*ATTRIBUTES)
|
||||
# don't reset the collection when no series was passed
|
||||
hash[:collection] = collection if attributes.key?(:series)
|
||||
hash[:tag_list] = tag_list
|
||||
hash[:edited_at] = Time.current if update_edited_at
|
||||
if update_published_at
|
||||
hash[:published_at] = Time.current
|
||||
elsif hash[:published_at]
|
||||
hash[:published_at] = hash[:published_at].to_datetime
|
||||
end
|
||||
hash[:published_at] = hash[:published_at].to_datetime if hash[:published_at]
|
||||
hash
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -17,16 +17,12 @@ module Articles
|
|||
|
||||
# updated edited time only if already published and not edited by an admin
|
||||
update_edited_at = article.user == user && article.published
|
||||
# TODO: move setting published_at to Articles::Attributes
|
||||
# when publishing (draft => published), and published_at is nil or is in the past, set it to Time.current
|
||||
# except for exported articles
|
||||
publishing = !article.published && article_params[:published]
|
||||
past_published_at = !article_params[:published_at] || article_params[:published_at] < Time.current
|
||||
update_published_at = publishing && !article.published_from_feed && past_published_at
|
||||
attrs = Articles::Attributes.new(article_params, article.user)
|
||||
.for_update(update_edited_at: update_edited_at,
|
||||
update_published_at: update_published_at)
|
||||
# remove published_at values received from a user if an articles was published before (has past published_at)
|
||||
# published_at will remain as it was in this case
|
||||
article_params.delete :published_at if article.published_at && !article.scheduled?
|
||||
|
||||
attrs = Articles::Attributes.new(article_params, article.user)
|
||||
.for_update(update_edited_at: update_edited_at)
|
||||
success = article.update(attrs)
|
||||
if success
|
||||
user.rate_limiter.track_limit_by_action(:article_update)
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ RSpec.describe Article, type: :model do
|
|||
expect(article_with_date.published_at.strftime("%d/%m/%Y")).to eq(date)
|
||||
end
|
||||
|
||||
it "sets published_at from frontmatter" do
|
||||
it "sets future published_at from frontmatter" do
|
||||
published_at = (Date.current + 10.days).strftime("%d/%m/%Y %H:%M")
|
||||
body_markdown = "---\ntitle: Title\npublished: false\npublished_at: #{published_at}\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
|
|
@ -493,6 +493,24 @@ RSpec.describe Article, type: :model do
|
|||
expect(article_with_published_at.published_at.strftime("%d/%m/%Y %H:%M")).to eq(published_at)
|
||||
end
|
||||
|
||||
it "sets published_at when publishing but no published_at passed from frontmatter" do
|
||||
body_markdown = "---\ntitle: Title\npublished: true\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
article = create(:article, body_markdown: body_markdown)
|
||||
article.reload
|
||||
expect(article.published_at).to be > 10.minutes.ago
|
||||
end
|
||||
|
||||
it "sets published_at when publishing from draft and no published_at passed from frontmatter" do
|
||||
body_markdown = "---\ntitle: Title\npublished: true\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
draft = create(:article, published: false, published_at: nil)
|
||||
draft.update(body_markdown: body_markdown)
|
||||
draft.reload
|
||||
expect(draft.published).to be true
|
||||
expect(draft.published_at).to be > 10.minutes.ago
|
||||
end
|
||||
|
||||
it "doesn't allow past published_at when publishing on create" do
|
||||
article2 = build(:article, published_at: 10.days.ago, published: true)
|
||||
expect(article2.valid?).to be false
|
||||
|
|
@ -512,11 +530,114 @@ RSpec.describe Article, type: :model do
|
|||
expect(article2.valid?).to be true
|
||||
end
|
||||
|
||||
it "doesn't allow updating published_at if an article has already been published" do
|
||||
article.published_at = (Date.current + 10.days).strftime("%d/%m/%Y %H:%M")
|
||||
expect(article.valid?).to be false
|
||||
expect(article.errors[:published_at])
|
||||
.to include("updating published_at for articles that have already been published is not allowed")
|
||||
context "when unpublishing" do
|
||||
let!(:published_at_was) { article.published_at }
|
||||
|
||||
it "keeps published_at" do
|
||||
article.update(published: false)
|
||||
article.reload
|
||||
expect(article.published_at).to be_within(1.second).of(published_at_was)
|
||||
end
|
||||
|
||||
it "keeps published_at if we try to unset it" do
|
||||
article.update(published: false, published_at: nil)
|
||||
article.reload
|
||||
expect(article.published_at).to be_within(1.second).of(published_at_was)
|
||||
end
|
||||
|
||||
it "keeps published_at when unpublising a scheduled article" do
|
||||
scheduled_published_at = 1.day.from_now
|
||||
article.update_columns(published_at: scheduled_published_at)
|
||||
article.update(published: false)
|
||||
article.reload
|
||||
expect(article.published_at).to be_within(1.second).of(scheduled_published_at)
|
||||
end
|
||||
end
|
||||
|
||||
context "when unpublishing a frontmatter article" do
|
||||
let(:published_at) { "2022-05-05 18:00 +0300" }
|
||||
let(:body_markdown) { "---\ntitle: Title\npublished: true\npublished_at: #{published_at}\n---\n\n" }
|
||||
let(:frontmatter_article) do
|
||||
a = create(:article, :past, past_published_at: DateTime.parse(published_at))
|
||||
# if we would set markdown on create, past_published_at would be overriden by body_markdown values
|
||||
# and the validation wouldn't pass
|
||||
a.update_columns(body_markdown: body_markdown)
|
||||
a
|
||||
end
|
||||
|
||||
it "keeps published at" do
|
||||
new_body_markdown = "---\ntitle: Title\npublished: false\n---\n\n"
|
||||
frontmatter_article.update(body_markdown: new_body_markdown)
|
||||
expect(frontmatter_article.published_at).to be_within(1.minute).of(DateTime.parse(published_at))
|
||||
end
|
||||
|
||||
it "keeps published at when trying to set published_at" do
|
||||
new_body_markdown = "---\ntitle: Title\npublished: false\npublished_at:2022-12-05 18:00 +0300---\n\n"
|
||||
frontmatter_article.update(body_markdown: new_body_markdown)
|
||||
expect(frontmatter_article.published_at).to be_within(1.minute).of(DateTime.parse(published_at))
|
||||
end
|
||||
|
||||
it "keeps published_at when unpublishing a scheduled article" do
|
||||
scheduled_time = 1.day.from_now
|
||||
time_str = scheduled_time.strftime("%d/%m/%Y %H:%M %z")
|
||||
scheduled_body_markdown = "---\ntitle: Title\npublished: true\npublished_at: #{time_str}\n---\n\n"
|
||||
frontmatter_scheduled_article = create(:article, body_markdown: scheduled_body_markdown)
|
||||
new_body_markdown = "---\ntitle: Title\npublished: false\npublished_at:2022-12-05 18:00 +0300---\n\n"
|
||||
frontmatter_scheduled_article.update(body_markdown: new_body_markdown)
|
||||
expect(frontmatter_scheduled_article.published_at).to be_within(1.minute).of(scheduled_time)
|
||||
end
|
||||
end
|
||||
|
||||
context "when publishing on update (draft => published)" do
|
||||
# has published_at means that the article was published before (and unpublished later, in this)
|
||||
it "doesn't allow updating published_at if an article has already been published" do
|
||||
article.published_at = (Date.current + 10.days).strftime("%d/%m/%Y %H:%M")
|
||||
expect(article.valid?).to be false
|
||||
expect(article.errors[:published_at])
|
||||
.to include("updating published_at for articles that have already been published is not allowed")
|
||||
end
|
||||
|
||||
it "allows past published_at for published_from_feed articles when publishing on update" do
|
||||
published_at = 10.days.ago
|
||||
article2 = create(:article, published: false, published_at: nil, published_from_feed: true)
|
||||
body_markdown = "---\ntitle: Title\npublished: true\npublished_at: #{published_at.strftime('%d/%m/%Y %H:%M')}
|
||||
\ndescription:\ntags: heytag\n---\n\nHey this is the article"
|
||||
article2.update(body_markdown: body_markdown)
|
||||
expect(article2.published_at).to be_within(1.minute).of(published_at)
|
||||
end
|
||||
|
||||
it "doesn't allow changing published_at for published_from_feed articles that have been published before" do
|
||||
published_at = Time.current
|
||||
published_at_was = 10.days.ago
|
||||
# has published_at means that the article was published before
|
||||
article2 = create(:article, published: false, published_at: published_at_was, published_from_feed: true)
|
||||
body_markdown = "---\ntitle: Title\npublished: true\npublished_at: #{published_at.strftime('%d/%m/%Y %H:%M')}
|
||||
\ndescription:\ntags: heytag\n---\n\nHey this is the article"
|
||||
success = article2.update(body_markdown: body_markdown)
|
||||
expect(success).to be false
|
||||
expect(article2.errors[:published_at]).to include(I18n.t("models.article.immutable_published_at"))
|
||||
end
|
||||
end
|
||||
|
||||
context "when updating a previously published (and unpublished) frontmatter article" do
|
||||
let(:published_at) { "2022-05-05 18:00 +0300" }
|
||||
let(:body_markdown) { "---\ntitle: Title\npublished: false\npublished_at: #{published_at}\n---\n\n" }
|
||||
let(:frontmatter_article) { create(:article, body_markdown: body_markdown) }
|
||||
|
||||
it "doesn't allow updating published_at if specifying published_at" do
|
||||
# expect(frontmatter_article.published_at < 10.days.ago).to be true
|
||||
new_body_markdown = "---\ntitle: Title\npublished: true\npublished_at: 2022-10-05 18:00 +0300\n---\n\n"
|
||||
success = frontmatter_article.update(body_markdown: new_body_markdown)
|
||||
expect(success).to be false
|
||||
expect(frontmatter_article.errors[:published_at]).to include(I18n.t("models.article.immutable_published_at"))
|
||||
end
|
||||
|
||||
it "doesn't allow updating published_at if removing published_at" do
|
||||
new_body_markdown = "---\ntitle: Title\npublished: true\n---\n\n"
|
||||
frontmatter_article.update(body_markdown: new_body_markdown)
|
||||
frontmatter_article.reload
|
||||
expect(frontmatter_article.published_at).to be_within(1.minute).of(DateTime.parse(published_at))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ RSpec.describe "ArticlesUpdate", type: :request do
|
|||
article: {
|
||||
title: "hello",
|
||||
body_markdown: "---\ntitle: hey hey hahuu\npublished: false\n---\nYo ho ho#{rand(100)}",
|
||||
tag_list: "yo"
|
||||
tag_list: "yo",
|
||||
version: "v1"
|
||||
}
|
||||
}
|
||||
expect(article.reload.edited_at).to be > 5.seconds.ago
|
||||
|
|
@ -133,7 +134,7 @@ RSpec.describe "ArticlesUpdate", type: :request do
|
|||
article.update_column(:published, false)
|
||||
sidekiq_assert_not_enqueued_with(job: Notifications::NotifiableActionWorker) do
|
||||
put "/articles/#{article.id}", params: {
|
||||
article: { published: true, body_markdown: "blah" }
|
||||
article: { published: true, body_markdown: "blah", version: "v1" }
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -146,7 +147,7 @@ RSpec.describe "ArticlesUpdate", type: :request do
|
|||
expect(article.notifications.size).to eq 1
|
||||
|
||||
put "/articles/#{article.id}", params: {
|
||||
article: { body_markdown: article.body_markdown.gsub("published: true", "published: false") }
|
||||
article: { body_markdown: article.body_markdown.gsub("published: true", "published: false"), version: "v1" }
|
||||
}
|
||||
expect(article.notifications.size).to eq 0
|
||||
end
|
||||
|
|
@ -193,7 +194,7 @@ RSpec.describe "ArticlesUpdate", type: :request do
|
|||
|
||||
# draft => scheduled
|
||||
it "sets published_at according to the timezone when updating draft => scheduled" do
|
||||
draft = create(:article, published: false, user_id: user.id)
|
||||
draft = create(:article, published: false, user_id: user.id, published_at: nil)
|
||||
attributes[:published] = true
|
||||
attributes[:timezone] = "America/Mexico_City"
|
||||
put "/articles/#{draft.id}", params: { article: attributes }
|
||||
|
|
@ -250,10 +251,22 @@ RSpec.describe "ArticlesUpdate", type: :request do
|
|||
draft = create(:article, published: false, user_id: user.id, published_from_feed: true, published_at: nil)
|
||||
body_markdown = "---\ntitle: super-article\npublished: true\ndescription:\ntags: heytag
|
||||
\ndate: #{date}---\n\nHey this is the article"
|
||||
put "/articles/#{draft.id}", params: { article: { body_markdown: body_markdown } }
|
||||
put "/articles/#{draft.id}", params: { article: { body_markdown: body_markdown, version: "v1" } }
|
||||
draft.reload
|
||||
expect(draft.published).to be true
|
||||
expect(draft.published_at).to be_within(1.minute).of(DateTime.parse(date))
|
||||
end
|
||||
|
||||
it "doesn't allow changing published_at when updating a published article published_from_feed" do
|
||||
date_was = "2022-05-02 19:00:30 UTC"
|
||||
date_new = "2022-08-30 19:00:30 UTC"
|
||||
article = create(:article, :past, published: true, user_id: user.id,
|
||||
published_from_feed: true, past_published_at: DateTime.parse(date_was))
|
||||
body_markdown = "---\ntitle: super-article\npublished: true\ndescription:\ntags: heytag
|
||||
\ndate: #{date_new}---\n\nHey this is the article"
|
||||
put "/articles/#{article.id}", params: { article: { body_markdown: body_markdown, version: "v1" } }
|
||||
article.reload
|
||||
expect(article.published_at).to be_within(1.minute).of(DateTime.parse(date_was))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -68,24 +68,9 @@ RSpec.describe Articles::Attributes, type: :service do
|
|||
expect(attrs[:edited_at]).to be_falsey
|
||||
end
|
||||
|
||||
it "sets published_at if update_published_at is true" do
|
||||
attrs = described_class.new({ title: "title" }, user).for_update(update_published_at: true)
|
||||
expect(attrs[:published_at]).to be_truthy
|
||||
end
|
||||
|
||||
it "doesn't set published_at if update_published_at is false" do
|
||||
attrs = described_class.new({ title: "title" }, user).for_update(update_published_at: false)
|
||||
expect(attrs[:published_at]).to be_falsey
|
||||
end
|
||||
|
||||
it "sets published_at correctly" do
|
||||
attrs = described_class.new({ title: "title", published_at: "2022-04-25" }, user).for_update
|
||||
expect(attrs[:published_at]).to eq(DateTime.new(2022, 4, 25))
|
||||
end
|
||||
|
||||
it "doesn't set published_at if it's nil and update_published_at is false" do
|
||||
attrs = described_class.new({ title: "title", published_at: nil }, user).for_update
|
||||
expect(attrs[:published_at]).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -49,65 +49,42 @@ RSpec.describe Articles::Updater, type: :service do
|
|||
end
|
||||
|
||||
describe "notifications" do
|
||||
let(:past_time) { 1.year.ago }
|
||||
let(:future_time) { 2.days.from_now }
|
||||
|
||||
context "when an article is updated and published the first time" do
|
||||
before { attributes[:published] = true }
|
||||
|
||||
# it "enqueues a job to send a notification" do
|
||||
# sidekiq_assert_enqueued_with(job: Notifications::NotifiableActionWorker) do
|
||||
# described_class.call(user, draft, attributes)
|
||||
# end
|
||||
# end
|
||||
|
||||
# it "delegates to the Mentions::CreateAll service to create mentions" do
|
||||
# allow(Mentions::CreateAll).to receive(:call)
|
||||
# described_class.call(user, draft, attributes)
|
||||
# expect(Mentions::CreateAll).to have_received(:call).with(draft)
|
||||
# end
|
||||
|
||||
# in case the article was published and unpublished before
|
||||
it "updates published_at to the current time when no published_at passed" do
|
||||
# actually, published_at is set in a model
|
||||
it "sets current published_at when publishing from a draft" do
|
||||
attributes[:published_at] = nil
|
||||
past_time = 1.year.ago
|
||||
draft.update_column(:published_at, past_time)
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published_at).to be_within(1.minute).of(Time.current)
|
||||
end
|
||||
|
||||
it "updates published_at to the current time when a past published_at is passed" do
|
||||
attributes[:published_at] = "2020-04-05 20:20"
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published_at).to be_within(1.minute).of(Time.current)
|
||||
end
|
||||
|
||||
it "doesn't update published_at when a future published_at is passed" do
|
||||
it "sets the passed published_at when a future published_at is passed" do
|
||||
attributes[:published_at] = 1.day.from_now
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published_at).to be_within(1.second).of(attributes[:published_at])
|
||||
end
|
||||
|
||||
it "doesn't update published_at when a past published_at is passed and an article was exported" do
|
||||
it "allows setting past published_at for exported articles (frontmatter)" do
|
||||
draft.update_columns(published_from_feed: true)
|
||||
past = 10.days.ago
|
||||
draft.update_columns(published_at: past, published_from_feed: true)
|
||||
attributes[:published_at] = past
|
||||
described_class.call(user, draft, attributes)
|
||||
expect(draft.published_at).to be_within(1.second).of(past)
|
||||
published_at = past.strftime("%d/%m/%Y %H:%M %z")
|
||||
body_markdown = "---\ntitle: Title\npublished: true\npublished_at: #{published_at}\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
frontmatter_attributes = { body_markdown: body_markdown }
|
||||
described_class.call(user, draft, frontmatter_attributes)
|
||||
expect(draft.published_at).to be_within(1.minute).of(past)
|
||||
end
|
||||
end
|
||||
|
||||
context "when an article is being updated and has already been published" do
|
||||
# it "doesn't enqueue a job to send a notification" do
|
||||
# attributes[:published] = true
|
||||
# sidekiq_assert_not_enqueued_with(job: Notifications::NotifiableActionWorker) do
|
||||
# described_class.call(user, article, attributes)
|
||||
# end
|
||||
# end
|
||||
|
||||
context "when an article is being updated (published => published)" do
|
||||
it "doesn't update published_at" do
|
||||
attributes[:published] = true
|
||||
past_time = 1.year.ago
|
||||
article.update_column(:published_at, past_time)
|
||||
described_class.call(user, article, attributes)
|
||||
article.reload
|
||||
|
|
@ -121,7 +98,107 @@ RSpec.describe Articles::Updater, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
context "when an article is unpublished" do
|
||||
context "when an article is being republished" do
|
||||
it "doesn't update past published_at" do
|
||||
draft.update_column(:published_at, past_time)
|
||||
attributes[:published] = true
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published).to be true
|
||||
expect(draft.published_at).to be_within(1.second).of(past_time)
|
||||
end
|
||||
|
||||
it "doesn't update future published_at" do
|
||||
draft.update_column(:published_at, future_time)
|
||||
attributes[:published] = true
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published).to be true
|
||||
expect(draft.published_at).to be_within(1.second).of(future_time)
|
||||
end
|
||||
|
||||
it "updates future published_at if new published_at is passed" do
|
||||
draft.update_column(:published_at, future_time)
|
||||
attributes[:published] = true
|
||||
new_published_at = 1.day.from_now
|
||||
attributes[:published_at] = new_published_at
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published).to be true
|
||||
expect(draft.published_at).to be_within(1.minute).of(new_published_at)
|
||||
end
|
||||
|
||||
it "doesn't update past published_at if new published_at is passed" do
|
||||
draft.update_column(:published_at, past_time)
|
||||
attributes[:published] = true
|
||||
new_published_at = 1.day.from_now
|
||||
attributes[:published_at] = new_published_at
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published).to be true
|
||||
expect(draft.published_at).to be_within(1.second).of(past_time)
|
||||
end
|
||||
|
||||
it "doesn't update published at when it is passed from frontmatter" do
|
||||
draft.update_columns(published_at: past_time)
|
||||
published_at = 10.days.from_now.strftime("%d/%m/%Y %H:%M %z")
|
||||
body_markdown = "---\ntitle: Title\npublished: false\npublished_at: #{published_at}\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
attributes = { body_markdown: body_markdown }
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published_at).to be_within(1.second).of(past_time)
|
||||
end
|
||||
|
||||
it "doesn't update published_at when published_at is passed and an article was exported" do
|
||||
draft.update_columns(published_at: past_time, published_from_feed: true)
|
||||
new_time = 10.days.from_now
|
||||
attributes[:published_at] = new_time
|
||||
described_class.call(user, draft, attributes)
|
||||
draft.reload
|
||||
expect(draft.published_at).to be_within(1.second).of(past_time)
|
||||
end
|
||||
|
||||
it "doesn't update published_at when published_at is passed (from frontmatter) and an article was exported" do
|
||||
draft.update_columns(published_at: past_time, published_from_feed: true)
|
||||
new_time = 10.days.from_now
|
||||
new_pub_at = new_time.strftime("%d/%m/%Y %H:%M %z")
|
||||
body_markdown = "---\ntitle: Title\npublished: true\npublished_at: #{new_pub_at}\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
frontmatter_attributes = { body_markdown: body_markdown }
|
||||
described_class.call(user, draft, frontmatter_attributes)
|
||||
draft.reload
|
||||
expect(draft.published_at).to be_within(1.second).of(past_time)
|
||||
end
|
||||
end
|
||||
|
||||
context "when an article is being unpublished from frontmatter" do
|
||||
let(:published_at) { 1.hour.from_now }
|
||||
let(:published_at_str) { published_at.strftime("%d/%m/%Y %H:%M %z") }
|
||||
let(:f_article) do
|
||||
markdown = "---\ntitle: Title\npublished: true\npublished_at: #{published_at_str}\n
|
||||
description:\ntags: heytag\n---\n\nHey this is the article"
|
||||
create(:article, user: user, body_markdown: markdown)
|
||||
end
|
||||
|
||||
it "doesn't remove published_at when it's not passed" do
|
||||
body_markdown = "---\ntitle: Title\npublished: false\ndescription:\ntags: heytag
|
||||
\n---\n\nHey this is the article"
|
||||
described_class.call(user, f_article, { body_markdown: body_markdown })
|
||||
f_article.reload
|
||||
expect(f_article.published_at).to be_within(1.minute).of(published_at)
|
||||
end
|
||||
|
||||
it "doesn't remove published_at when it's passed" do
|
||||
body_markdown = "---\ntitle: Title\npublished: false\n
|
||||
published_at: #{published_at_str}\ndescription:\ntags: heytag\n---\n\nHey this is the article"
|
||||
described_class.call(user, f_article, { body_markdown: body_markdown })
|
||||
f_article.reload
|
||||
expect(f_article.published_at).to be_within(1.minute).of(published_at)
|
||||
end
|
||||
end
|
||||
|
||||
context "when an article is being unpublished" do
|
||||
before { attributes[:published] = false }
|
||||
|
||||
it "doesn't update published_at" do
|
||||
|
|
@ -152,7 +229,7 @@ RSpec.describe Articles::Updater, type: :service do
|
|||
# expect(ContextNotification).to have_received(:delete_all)
|
||||
end
|
||||
|
||||
it "destroys the prexexisting context notifications" do
|
||||
it "destroys the preexisting context notifications" do
|
||||
create(:context_notification, context: article, action: "Published")
|
||||
expect do
|
||||
described_class.call(user, article, attributes)
|
||||
|
|
@ -160,7 +237,7 @@ RSpec.describe Articles::Updater, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
context "when an article is updated and remains unpublished" do
|
||||
context "when an article is updated and remains draft" do
|
||||
it "doesn't update published_at" do
|
||||
attributes[:published] = false
|
||||
described_class.call(user, draft, attributes)
|
||||
|
|
@ -169,7 +246,7 @@ RSpec.describe Articles::Updater, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
context "when an article is unpublished and contains comments" do
|
||||
context "when an article is being unpublished and contains comments" do
|
||||
let!(:comment) { create(:comment, user_id: user.id, commentable: article) }
|
||||
let(:notification) do
|
||||
create(:notification, user: user, notifiable_id: comment.id, notifiable_type: "Comment")
|
||||
|
|
@ -190,7 +267,7 @@ RSpec.describe Articles::Updater, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
context "when an article is unpublished and contains mentions" do
|
||||
context "when an article is being unpublished and contains mentions" do
|
||||
let!(:mention) { create(:mention, mentionable: article, user: user) }
|
||||
let(:notification) do
|
||||
create(:notification, user: user, notifiable_id: mention.id, notifiable_type: "Mention")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue