-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(688) Add content block updates to a document's timeline #9754
base: main
Are you sure you want to change the base?
Changes from 1 commit
03d0567
fcfa164
e1cd197
00332b7
5b44220
da9ce39
d99f6db
8d4a784
090f1d6
297f3b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,14 +13,20 @@ def entries | |
remarks = document.remarks_by_ids(query.remark_ids) | ||
versions = document.decorated_edition_versions_by_ids(query.version_ids) | ||
|
||
raw_entries.map do |entry| | ||
versions_and_remarks = raw_entries.map do |entry| | ||
case entry.model | ||
when "Version" | ||
versions.fetch(entry.id) | ||
when "EditorialRemark" | ||
remarks.fetch(entry.id) | ||
end | ||
end | ||
|
||
if only.present? | ||
versions_and_remarks | ||
else | ||
[*versions_and_remarks, *host_content_update_events].sort_by(&:created_at).reverse! | ||
end | ||
end | ||
end | ||
|
||
|
@@ -89,4 +95,30 @@ def prev_page | |
false | ||
end | ||
end | ||
|
||
private | ||
|
||
def next_page_entries | ||
if next_page | ||
Document::PaginatedTimelineQuery.new(document:, page: next_page, only:).raw_entries | ||
end | ||
end | ||
|
||
def host_content_update_events | ||
return [] if query.raw_entries.empty? | ||
|
||
@host_content_update_events ||= HostContentUpdateEvent.all_for_date_window( | ||
document:, | ||
from: date_window.last, | ||
to: date_window.first, | ||
) | ||
end | ||
|
||
def date_window | ||
@date_window ||= begin | ||
start = page == 1 ? Time.zone.now : query.raw_entries.first.created_at | ||
ends = next_page_entries ? next_page_entries.first.created_at : query.raw_entries.last.created_at | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Better yet, perhaps just handle the first page in this first commit, and then add the "next page" logic in a subsequent commit, rather than doing it all at once. |
||
(start.to_time.round.utc..ends.to_time.round.utc) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FactoryBot.define do | ||
factory :host_content_update_event do | ||
author { create(:user) } | ||
created_at { Time.zone.now } | ||
content_id { SecureRandom.uuid } | ||
content_title { "Some title" } | ||
|
||
initialize_with do | ||
new(author:, created_at:, content_id:, content_title:) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ class PaginatedTimelineTest < ActiveSupport::TestCase | |
assert_equal entry_timestamps.sort.reverse, entry_timestamps | ||
end | ||
|
||
it "is is a list of VersionDecorator and EditorialRemark objects when no 'only' argument is passed in" do | ||
it "is is a list of VersionDecorator and EditorialRemark objects when no 'only' argument is not passed in" do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is difficult to parse 😅 can we reword to remove the double negative? Similarly on line 92 |
||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
assert_equal [VersionDecorator, EditorialRemark].to_set, | ||
timeline.entries.map(&:class).to_set | ||
|
@@ -45,27 +45,6 @@ class PaginatedTimelineTest < ActiveSupport::TestCase | |
assert_equal unpaginated_results.each_slice(results_per_page).to_a, paginated_results | ||
end | ||
|
||
it "is a list of EditorialRemark objects when 'internal_notes' is passed into the 'only' argument" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1, only: "internal_notes") | ||
expected_entries = [@editorial_remark3, @editorial_remark2, @editorial_remark1] | ||
|
||
assert_equal expected_entries, timeline.entries | ||
end | ||
|
||
it "is a list of VersionDecorator objects when 'history' is passed in as a 'only' argument" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1, only: "history") | ||
expected_actions = %w[updated | ||
editioned | ||
published | ||
submitted | ||
updated | ||
rejected | ||
submitted | ||
created] | ||
|
||
assert_equal expected_actions, timeline.entries.map(&:action) | ||
end | ||
|
||
it "correctly determines actions" do | ||
mock_pagination(per_page: 30) do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
|
@@ -96,6 +75,140 @@ class PaginatedTimelineTest < ActiveSupport::TestCase | |
|
||
assert_equal expected_actors, entries.map(&:actor) | ||
end | ||
|
||
describe "when there are HostContentUpdateEvents present" do | ||
let(:host_content_update_events) { build_list(:host_content_update_event, 3) } | ||
|
||
before do | ||
HostContentUpdateEvent.stubs(:all_for_date_window).returns(host_content_update_events) | ||
end | ||
|
||
it "orders newest first (reverse chronological order)" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
entry_timestamps = timeline.entries.flatten.map(&:created_at) | ||
assert_equal entry_timestamps.sort.reverse, entry_timestamps | ||
end | ||
|
||
it "is is a list of VersionDecorator, EditorialRemark and HostContentUpdateEvent objects when no 'only' argument is passed in" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
assert_equal [VersionDecorator, EditorialRemark, HostContentUpdateEvent].to_set, | ||
timeline.entries.map(&:class).to_set | ||
end | ||
|
||
it "includes all of the HostContentUpdateEvent objects" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
|
||
host_content_update_events.each do |event| | ||
assert_includes timeline.entries, event | ||
end | ||
end | ||
|
||
describe "fetching HostContentUpdateEvents" do | ||
before do | ||
HostContentUpdateEvent.reset_mocha | ||
end | ||
|
||
describe "when on the first page" do | ||
it "requests a date window from the first created_at date of the next page to the current datetime" do | ||
Timecop.freeze do | ||
page2_entries = Document::PaginatedTimeline.new(document: @document, page: 2).query.raw_entries | ||
|
||
HostContentUpdateEvent.expects(:all_for_date_window).with( | ||
document: @document, | ||
from: page2_entries.first.created_at.to_time.utc, | ||
to: Time.zone.now.to_time.round.utc, | ||
).at_least_once.returns(host_content_update_events) | ||
|
||
Document::PaginatedTimeline.new(document: @document, page: 1).entries | ||
end | ||
end | ||
|
||
describe "when there are no results" do | ||
it "does not request any events" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
timeline.query.expects(:raw_entries).at_least_once.returns([]) | ||
|
||
HostContentUpdateEvent.expects(:all_for_date_window).never | ||
|
||
timeline.entries | ||
end | ||
end | ||
end | ||
|
||
describe "when not on the first page" do | ||
it "requests a window between the first created_at date of the next page to the first created_at date of the current page" do | ||
mock_pagination(per_page: 3) do | ||
page2_entries = Document::PaginatedTimeline.new(document: @document, page: 2).query.raw_entries | ||
page3_entries = Document::PaginatedTimeline.new(document: @document, page: 3).query.raw_entries | ||
|
||
HostContentUpdateEvent.expects(:all_for_date_window).with( | ||
document: @document, | ||
from: page3_entries.first.created_at.to_time.utc, | ||
to: page2_entries.first.created_at.to_time.utc, | ||
).at_least_once.returns(host_content_update_events) | ||
|
||
Document::PaginatedTimeline.new(document: @document, page: 2).entries | ||
end | ||
end | ||
end | ||
|
||
describe "when on the last page" do | ||
it "fetches with the created_at date for the last item" do | ||
Timecop.freeze do | ||
mock_pagination(per_page: 30) do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1) | ||
timeline_entries = timeline.query.raw_entries | ||
|
||
HostContentUpdateEvent.expects(:all_for_date_window).with( | ||
document: @document, | ||
from: timeline_entries.last.created_at.to_time.utc, | ||
to: timeline_entries.first.created_at.to_time.utc, | ||
).at_least_once.returns(host_content_update_events) | ||
|
||
timeline.entries | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe "when only argument is set to history" do | ||
it "is a list of VersionDecorator objects" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1, only: "history") | ||
expected_actions = %w[updated | ||
editioned | ||
published | ||
submitted | ||
updated | ||
rejected | ||
submitted | ||
created] | ||
|
||
assert_equal expected_actions, timeline.entries.map(&:action) | ||
end | ||
|
||
it "does not fetch any HostContentUpdateEvents" do | ||
HostContentUpdateEvent.expects(:all_for_date_window).never | ||
|
||
Document::PaginatedTimeline.new(document: @document, page: 1, only: "history").entries | ||
end | ||
end | ||
|
||
describe "when only argument is set to internal_notes" do | ||
it "is a list of EditorialRemark objects when 'internal_notes'" do | ||
timeline = Document::PaginatedTimeline.new(document: @document, page: 1, only: "internal_notes") | ||
expected_entries = [@editorial_remark3, @editorial_remark2, @editorial_remark1] | ||
|
||
assert_equal expected_entries, timeline.entries | ||
end | ||
|
||
it "does not fetch any HostContentUpdateEvents" do | ||
HostContentUpdateEvent.expects(:all_for_date_window).never | ||
|
||
Document::PaginatedTimeline.new(document: @document, page: 1, only: "internal_notes").entries | ||
end | ||
end | ||
end | ||
|
||
describe "#total_count" do | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move this below
def date_window
as it isn't called until further down in the file (nice to have methods defined in the order they're called)