This commit is contained in:
@@ -756,6 +756,211 @@ RSpec.describe 'Posts API', type: :request do
|
|||||||
end
|
end
|
||||||
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
|
describe 'POST /posts/:id/viewed' do
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
|||||||
@@ -215,22 +215,29 @@ export default (() => {
|
|||||||
change.versionNo } に差戻します.\nよろしいですか?`)))
|
change.versionNo } に差戻します.\nよろしいですか?`)))
|
||||||
return
|
return
|
||||||
|
|
||||||
await apiPut (
|
try
|
||||||
`/posts/${ change.postId }`,
|
{
|
||||||
{ title: change.title.current,
|
await apiPut (
|
||||||
tags: change.tags
|
`/posts/${ change.postId }`,
|
||||||
.filter (t => t.type !== 'removed')
|
{ title: change.title.current,
|
||||||
.map (t => t.name)
|
tags: change.tags
|
||||||
.filter (t => t.slice (0, 5) !== 'nico:')
|
.filter (t => t.type !== 'removed')
|
||||||
.join (' '),
|
.map (t => t.name)
|
||||||
original_created_from:
|
.filter (t => t.slice (0, 5) !== 'nico:')
|
||||||
change.originalCreatedFrom.current,
|
.join (' '),
|
||||||
original_created_before:
|
original_created_from:
|
||||||
change.originalCreatedBefore.current })
|
change.originalCreatedFrom.current,
|
||||||
|
original_created_before:
|
||||||
|
change.originalCreatedBefore.current })
|
||||||
|
|
||||||
qc.invalidateQueries ({ queryKey: postsKeys.root })
|
qc.invalidateQueries ({ queryKey: postsKeys.root })
|
||||||
qc.invalidateQueries ({ queryKey: tagsKeys.root })
|
qc.invalidateQueries ({ queryKey: tagsKeys.root })
|
||||||
toast ({ description: '更新しました.' })
|
toast ({ description: '差戻しました.' })
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
toast ({ description: '差戻に失敗……' })
|
||||||
|
}
|
||||||
}}>
|
}}>
|
||||||
復元
|
復元
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user