このコミットが含まれているのは:
2026-09-23 02:46:56 +09:00
コミット 2dbd5260ea
12個のファイルの変更333行の追加92行の削除
+134 -10
ファイルの表示
@@ -93,6 +93,26 @@ RSpec.describe 'Posts API', type: :request do
count
end
def expect_external_tag_json tag_json, external_tag
external_tag.reload
expect(tag_json).to include(
'id' => external_tag.id,
'name' => "#{ external_tag.platform }:#{ external_tag.name }",
'category' => 'nico',
'created_at' => external_tag.created_at.as_json,
'updated_at' => external_tag.created_at.as_json,
'deprecated_at' => nil,
'aliases' => [],
'parents' => [],
'post_count' => external_tag.post_count,
'has_wiki' => false,
'material_id' => nil,
'has_deerjikists' => false,
'children' => [],
'sections' => [])
end
let!(:tag_name) { TagName.create!(name: 'spec_tag') }
let!(:tag) { Tag.create!(tag_name: tag_name, category: :general) }
@@ -612,6 +632,30 @@ RSpec.describe 'Posts API', type: :request do
expect(json.fetch('count')).to eq(2)
end
end
it 'returns internal and external tags with colliding ids in the legacy tags array' do
external_tag = create(:external_tag, id: tag.id, name: 'post_index_external')
PostExternalTag.create!(post: hit_post, external_tag:)
get '/posts'
expect(response).to have_http_status(:ok)
post_json =
json
.fetch('posts')
.find { _1.fetch('id') == hit_post.id }
external_json =
post_json
.fetch('tags')
.find { _1['name'] == 'nico:post_index_external' }
expect(post_json.fetch('tags')).to include(
a_hash_including('id' => tag.id, 'name' => tag.name, 'category' => 'general'))
expect(external_json).not_to be_nil
expect_external_tag_json(external_json, external_tag)
end
end
describe 'GET /posts/:id' do
@@ -769,6 +813,25 @@ RSpec.describe 'Posts API', type: :request do
expect(response).to have_http_status(:ok)
expect(query_count).to be <= 45
end
it 'returns external tags as root nodes in the legacy tag tree' do
external_tag = create(:external_tag, id: tag.id, name: 'post_detail_external')
PostExternalTag.create!(post: post_record, external_tag:)
request
expect(response).to have_http_status(:ok)
expect(json.fetch('tags')).to include(
a_hash_including('id' => tag.id, 'name' => tag.name, 'category' => 'general'))
external_json =
json
.fetch('tags')
.find { _1['name'] == 'nico:post_detail_external' }
expect(external_json).not_to be_nil
expect_external_tag_json(external_json, external_tag)
end
end
context 'when post does not exist' do
@@ -1938,6 +2001,14 @@ RSpec.describe 'Posts API', type: :request do
expect(names).to include('spec_tag')
expect(names).to include(Tag.no_deerjikist.name)
expect(post_record.external_tags).to contain_exactly(nico_tag)
external_json =
json
.fetch('tags')
.find { _1['name'] == "nico:#{ nico_tag.name }" }
expect(external_json).not_to be_nil
expect_external_tag_json(external_json, nico_tag)
end
it 'allows non-nico tags linked from nico tags to be removed by normal post update' do
@@ -2180,18 +2251,71 @@ RSpec.describe 'Posts API', type: :request do
expect(first.fetch('created_at')).to eq(t_v1.iso8601)
end
it 'does not treat an external id as the internal tag filter' do
external_post = create(:post)
external = create(:external_tag, id: tag.id)
PostExternalTag.create!(post: external_post, external_tag: external)
PostVersionRecorder.record!(post: external_post,
event_type: :create, created_by_user: member)
context 'with external tag history' do
let(:external_id) { tag.id }
let(:external) { create(:external_tag, id: external_id) }
let(:external_post) { create(:post) }
get '/posts/versions', params: { post: external_post.id, tag: tag.id }
before do
PostExternalTag.create!(post: external_post, external_tag: external)
PostVersionRecorder.record!(
post: external_post, event_type: :create, created_by_user: member)
expect(response).to have_http_status(:ok)
expect(json.fetch('versions')).to be_empty
expect(json.fetch('count')).to eq(0)
unrelated_post = create(:post)
PostExternalTag.create!(post: unrelated_post, external_tag: create(:external_tag))
PostVersionRecorder.record!(
post: unrelated_post, event_type: :create, created_by_user: member)
end
it 'prefers Tag over ExternalTag for the legacy tag parameter' do
get '/posts/versions', params: { tag: tag.id }
expect(response).to have_http_status(:ok)
expect(json.fetch('count')).to eq(3)
expect(json.fetch('versions').map { [_1.fetch('post_id'), _1.fetch('version_no')] })
.to contain_exactly(
[post_record.id, 1], [post_record.id, 2], [other_post_version.post_id, 1])
end
it 'explicitly filters ExternalTag even when its id collides with Tag' do
get '/posts/versions', params: { external_tag: external.id }
expect(response).to have_http_status(:ok)
expect(json.fetch('count')).to eq(1)
expect(json.fetch('versions')).to contain_exactly(
a_hash_including('post_id' => external_post.id, 'version_no' => 1))
end
context 'without an internal Tag with the external id' do
let(:external_id) { Tag.maximum(:id).to_i + 10_000 }
it 'falls back to ExternalTag for the legacy tag parameter' do
expect(Tag.exists?(external.id)).to be(false)
get '/posts/versions', params: { tag: external.id }
expect(response).to have_http_status(:ok)
expect(json.fetch('count')).to eq(1)
expect(json.fetch('versions')).to contain_exactly(
a_hash_including('post_id' => external_post.id, 'version_no' => 1))
end
[:tag, :external_tag].each do |parameter|
it "includes external tag removal history through #{ parameter }" do
external_post.post_external_tags.destroy_all
PostVersionRecorder.record!(
post: external_post.reload, event_type: :update, created_by_user: member)
get '/posts/versions', params: { parameter => external.id }
expect(response).to have_http_status(:ok)
expect(json.fetch('count')).to eq(2)
expect(json.fetch('versions')).to contain_exactly(
a_hash_including('post_id' => external_post.id, 'version_no' => 1),
a_hash_including('post_id' => external_post.id, 'version_no' => 2))
end
end
end
end
it 'can render history containing external identifiers' do