ファイル
btrc-hub/backend/spec/requests/sitemap_entries_spec.rb
T
2026-10-20 20:44:14 +09:00

156 行
6.0 KiB
Ruby

require 'rails_helper'
RSpec.describe 'Sitemap entries API', type: :request do
include_context 'Ainu locale'
let(:user) { create(:user, :member) }
it 'serves public resource counts with the default locale and page size' do
create(:post)
create(:tag, primary_name: 'sitemap_count_tag')
get '/sitemap_entries'
expect(response).to have_http_status(:ok)
expect(json.fetch('page_size')).to eq(1_000)
counts = json.fetch('resources').to_h { |entry|
[entry.fetch('resource'), entry.fetch('count')]
}
expect(counts).to eq(
'posts' => Post.count, 'tags' => Tag.count, 'deerjikists' => 0,
'materials' => 0, 'descriptions' => 0, 'tag_groups' => 0, 'theatres' => 0)
end
it 'paginates public post IDs in ascending order without exposing post contents' do
stub_const('SitemapEntriesController::PAGE_SIZE', 2)
posts = create_list(:post, 3)
get '/sitemap_entries/posts'
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => posts.first(2).map(&:id))
get '/sitemap_entries/posts', params: { page: 2 }
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [posts.last.id])
get '/sitemap_entries/posts', params: { page: 3 }
expect(response).to have_http_status(:not_found)
end
['0', '-1', 'invalid', '1.5'].each do |page|
it "rejects invalid sitemap page #{ page.inspect }" do
get '/sitemap_entries/posts', params: { page: }
expect(response).to have_http_status(:bad_request)
end
end
it 'rejects unsupported resource names' do
get '/sitemap_entries/users'
expect(response).to have_http_status(:not_found)
end
it 'returns an empty first page for a resource without entries' do
get '/sitemap_entries/posts'
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [])
end
it 'rejects unregistered, deprecated and unsupported locales' do
get '/sitemap_entries', params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:not_found)
locale.update!(deprecated_at: Time.current)
['/sitemap_entries', '/sitemap_entries/posts'].each do |path|
get path, params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:not_found)
get path, params: { locale: 'en' }
expect(response).to have_http_status(:not_found)
end
end
it 'only lists live materials and theatres' do
material = Material.create!(url: 'https://example.com/sitemap-material')
discarded_material = Material.create!(url: 'https://example.com/sitemap-discarded')
discarded_material.discard!
theatre = create(:theatre)
create(:theatre).discard!
get '/sitemap_entries/materials'
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [material.id])
get '/sitemap_entries/theatres'
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [theatre.id])
end
context 'with an active Ainu locale' do
before { locale }
it 'uses tag IDs and only includes deerjikists with linked accounts' do
tagged = create(:tag, primary_name: 'sitemap_deer', category: :deerjikist)
unlinked = create(:tag, primary_name: 'sitemap_unlinked', category: :deerjikist)
Deerjikist.create!(tag: tagged, platform: 'youtube', code: 'sitemap-channel')
Deerjikist.create!(tag: tagged, platform: 'nico', code: 'sitemap-nico')
get '/sitemap_entries/tags', params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:ok)
expect(json.fetch('ids')).to contain_exactly(tagged.id, unlinked.id)
get '/sitemap_entries/deerjikists', params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [tagged.id])
end
it 'lists description IDs for the requested language with a nonempty current version' do
tag = create(:tag, primary_name: 'sitemap_description')
japanese = TagDescriptionOperation.create!(
Locale.nipponese, tag:, body: 'Japanese sitemap body', created_by_user: user)
ainu = TagDescriptionOperation.create!(
locale, tag:, body: 'Ainu sitemap body', created_by_user: user)
unversioned_tag = create(:tag, primary_name: 'sitemap_unversioned')
TagDescription.create!(tag: unversioned_tag, language_code: 'ain',
body: 'No revision', version_no: 1)
empty_tag = create(:tag, primary_name: 'sitemap_empty')
# Legacy empty bodies can exist even though the write service rejects them.
empty = TagDescription.create!(tag: empty_tag, language_code: 'ain',
body: '', version_no: 1)
TagDescriptionVersion.create!(tag_id: empty_tag.id, language_code: 'ain',
body: '', version_no: 1, event_type: 'create',
created_by_user_id: user.id, created_at: Time.current)
get '/sitemap_entries/descriptions', params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [ainu.id])
expect(json.fetch('ids')).not_to include(japanese.id, empty.id)
get '/sitemap_entries/descriptions', params: { locale: 'ja' }
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [japanese.id])
get '/sitemap_entries', params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:ok)
descriptions = json.fetch('resources').find { |entry|
entry.fetch('resource') == 'descriptions'
}
expect(descriptions.fetch('count')).to eq(1)
end
it 'excludes groups without a revision matching the current version' do
group = TagGroupOperation.create!(
Locale.nipponese, name: 'Sitemap group', description: 'Group description',
members: [], placements: [], actor: user)
TagGroup.create!(name: 'Unversioned sitemap group', version_no: 1)
get '/sitemap_entries/tag_groups', params: { locale: 'ain-Kana' }
expect(response).to have_http_status(:ok)
expect(json).to eq('ids' => [group.id])
end
end
end