|
|
|
@@ -756,6 +756,211 @@ RSpec.describe 'Posts API', type: :request do |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
describe 'GET /posts/versions' do |
|
|
|
let(:member) { create(:user, :member, name: 'version member') } |
|
|
|
|
|
|
|
let(:t_v1) { Time.zone.local(2020, 1, 1, 12, 0, 0) } |
|
|
|
let(:t_v2) { Time.zone.local(2020, 1, 2, 12, 0, 0) } |
|
|
|
let(:t_other) { Time.zone.local(2020, 1, 3, 12, 0, 0) } |
|
|
|
|
|
|
|
let(:oc_from) { Time.zone.local(2019, 12, 31, 0, 0, 0) } |
|
|
|
let(:oc_before) { Time.zone.local(2020, 1, 1, 0, 0, 0) } |
|
|
|
|
|
|
|
let!(:tag_name2) { TagName.create!(name: 'spec_tag_2') } |
|
|
|
let!(:tag2) { Tag.create!(tag_name: tag_name2, category: :general) } |
|
|
|
|
|
|
|
def snapshot_tags(post) |
|
|
|
post.snapshot_tag_names.join(' ') |
|
|
|
end |
|
|
|
|
|
|
|
def create_post_version!(post, version_no:, event_type:, created_by_user:, created_at:) |
|
|
|
PostVersion.create!( |
|
|
|
post: post, |
|
|
|
version_no: version_no, |
|
|
|
event_type: event_type, |
|
|
|
title: post.title, |
|
|
|
url: post.url, |
|
|
|
thumbnail_base: post.thumbnail_base, |
|
|
|
tags: snapshot_tags(post), |
|
|
|
parent: post.parent, |
|
|
|
original_created_from: post.original_created_from, |
|
|
|
original_created_before: post.original_created_before, |
|
|
|
created_at: created_at, |
|
|
|
created_by_user: created_by_user |
|
|
|
) |
|
|
|
end |
|
|
|
|
|
|
|
let!(:v1) do |
|
|
|
travel_to(t_v1) do |
|
|
|
create_post_version!( |
|
|
|
post_record, |
|
|
|
version_no: 1, |
|
|
|
event_type: 'create', |
|
|
|
created_by_user: member, |
|
|
|
created_at: t_v1 |
|
|
|
) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
let!(:v2) do |
|
|
|
post_record.post_tags.kept.find_by!(tag: tag).discard_by!(member) |
|
|
|
PostTag.create!(post: post_record, tag: tag2, created_user: member) |
|
|
|
post_record.update!( |
|
|
|
title: 'updated spec post', |
|
|
|
original_created_from: oc_from, |
|
|
|
original_created_before: oc_before |
|
|
|
) |
|
|
|
|
|
|
|
travel_to(t_v2) do |
|
|
|
create_post_version!( |
|
|
|
post_record.reload, |
|
|
|
version_no: 2, |
|
|
|
event_type: 'update', |
|
|
|
created_by_user: member, |
|
|
|
created_at: t_v2 |
|
|
|
) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
let!(:other_post_version) do |
|
|
|
other_post = Post.create!( |
|
|
|
title: 'other versioned post', |
|
|
|
url: 'https://example.com/other-versioned' |
|
|
|
) |
|
|
|
PostTag.create!(post: other_post, tag: tag) |
|
|
|
|
|
|
|
travel_to(t_other) do |
|
|
|
create_post_version!( |
|
|
|
other_post, |
|
|
|
version_no: 1, |
|
|
|
event_type: 'create', |
|
|
|
created_by_user: member, |
|
|
|
created_at: t_other |
|
|
|
) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
it 'returns versions for the specified post in reverse chronological order' do |
|
|
|
get '/posts/versions', params: { post: post_record.id } |
|
|
|
|
|
|
|
expect(response).to have_http_status(:ok) |
|
|
|
expect(json).to include('versions', 'count') |
|
|
|
expect(json.fetch('count')).to eq(2) |
|
|
|
|
|
|
|
versions = json.fetch('versions') |
|
|
|
expect(versions.map { |v| v['post_id'] }.uniq).to eq([post_record.id]) |
|
|
|
expect(versions.map { |v| v['version_no'] }).to eq([2, 1]) |
|
|
|
|
|
|
|
latest = versions.first |
|
|
|
expect(latest).to include( |
|
|
|
'post_id' => post_record.id, |
|
|
|
'version_no' => 2, |
|
|
|
'event_type' => 'update', |
|
|
|
'created_by_user' => { |
|
|
|
'id' => member.id, |
|
|
|
'name' => member.name |
|
|
|
} |
|
|
|
) |
|
|
|
|
|
|
|
expect(latest.fetch('title')).to eq( |
|
|
|
'current' => 'updated spec post', |
|
|
|
'prev' => 'spec post' |
|
|
|
) |
|
|
|
expect(latest.fetch('url')).to eq( |
|
|
|
'current' => 'https://example.com/spec', |
|
|
|
'prev' => 'https://example.com/spec' |
|
|
|
) |
|
|
|
expect(latest.fetch('thumbnail')).to eq( |
|
|
|
'current' => nil, |
|
|
|
'prev' => nil |
|
|
|
) |
|
|
|
expect(latest.fetch('thumbnail_base')).to eq( |
|
|
|
'current' => nil, |
|
|
|
'prev' => nil |
|
|
|
) |
|
|
|
expect(latest.fetch('tags')).to include( |
|
|
|
{ 'name' => 'spec_tag_2', 'type' => 'added' }, |
|
|
|
{ 'name' => 'spec_tag', 'type' => 'removed' } |
|
|
|
) |
|
|
|
expect(latest.fetch('original_created_from')).to eq( |
|
|
|
'current' => oc_from.iso8601, |
|
|
|
'prev' => nil |
|
|
|
) |
|
|
|
expect(latest.fetch('original_created_before')).to eq( |
|
|
|
'current' => oc_before.iso8601, |
|
|
|
'prev' => nil |
|
|
|
) |
|
|
|
expect(latest.fetch('created_at')).to eq(t_v2.iso8601) |
|
|
|
|
|
|
|
first = versions.second |
|
|
|
expect(first).to include( |
|
|
|
'post_id' => post_record.id, |
|
|
|
'version_no' => 1, |
|
|
|
'event_type' => 'create', |
|
|
|
'created_by_user' => { |
|
|
|
'id' => member.id, |
|
|
|
'name' => member.name |
|
|
|
} |
|
|
|
) |
|
|
|
expect(first.fetch('title')).to eq( |
|
|
|
'current' => 'spec post', |
|
|
|
'prev' => nil |
|
|
|
) |
|
|
|
expect(first.fetch('tags')).to include( |
|
|
|
{ 'name' => 'spec_tag', 'type' => 'added' } |
|
|
|
) |
|
|
|
expect(first.fetch('created_at')).to eq(t_v1.iso8601) |
|
|
|
end |
|
|
|
|
|
|
|
it 'filters versions by tag when the current snapshot includes the tag' do |
|
|
|
get '/posts/versions', params: { post: post_record.id, tag: tag2.id } |
|
|
|
|
|
|
|
expect(response).to have_http_status(:ok) |
|
|
|
expect(json.fetch('count')).to eq(1) |
|
|
|
|
|
|
|
versions = json.fetch('versions') |
|
|
|
expect(versions.size).to eq(1) |
|
|
|
expect(versions[0]['post_id']).to eq(post_record.id) |
|
|
|
expect(versions[0]['version_no']).to eq(2) |
|
|
|
expect(versions[0]['tags']).to include( |
|
|
|
{ 'name' => 'spec_tag_2', 'type' => 'added' } |
|
|
|
) |
|
|
|
end |
|
|
|
|
|
|
|
it 'matches tag filter against current tags snapshot only' do |
|
|
|
get '/posts/versions', params: { post: post_record.id, tag: tag.id } |
|
|
|
|
|
|
|
expect(response).to have_http_status(:ok) |
|
|
|
expect(json.fetch('count')).to eq(1) |
|
|
|
|
|
|
|
versions = json.fetch('versions') |
|
|
|
expect(versions.size).to eq(1) |
|
|
|
expect(versions[0]['version_no']).to eq(1) |
|
|
|
expect(versions[0]['tags']).to include( |
|
|
|
{ 'name' => 'spec_tag', 'type' => 'added' } |
|
|
|
) |
|
|
|
end |
|
|
|
|
|
|
|
it 'returns empty when tag does not exist' do |
|
|
|
get '/posts/versions', params: { tag: 999_999_999 } |
|
|
|
|
|
|
|
expect(response).to have_http_status(:ok) |
|
|
|
expect(json.fetch('versions')).to eq([]) |
|
|
|
expect(json.fetch('count')).to eq(0) |
|
|
|
end |
|
|
|
|
|
|
|
it 'clamps page and limit to at least 1' do |
|
|
|
get '/posts/versions', params: { post: post_record.id, page: 0, limit: 0 } |
|
|
|
|
|
|
|
expect(response).to have_http_status(:ok) |
|
|
|
expect(json.fetch('count')).to eq(2) |
|
|
|
|
|
|
|
versions = json.fetch('versions') |
|
|
|
expect(versions.size).to eq(1) |
|
|
|
expect(versions[0]['version_no']).to eq(2) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
describe 'POST /posts/:id/viewed' do |
|
|
|
let(:user) { create(:user) } |
|
|
|
|
|
|
|
|