159 行
7.0 KiB
Ruby
159 行
7.0 KiB
Ruby
require 'rails_helper'
|
|
|
|
RSpec.describe 'Wiki and native API locale contracts', type: :request do
|
|
include WikiRecords
|
|
include TagGroupRecords
|
|
include_context 'Ainu locale contract'
|
|
|
|
let!(:user) { create_member_user! }
|
|
let!(:tag) { create(:tag, primary_name: 'japanese_title') }
|
|
let!(:ainu_name) { add_ainu_name(tag, 'ainu_title') }
|
|
let(:headers) { { 'X-Transfer-Code' => user.inheritance_code } }
|
|
let!(:japanese) do
|
|
TagDescriptionOperation.create!(
|
|
Locale.nipponese, tag:, body: 'Japanese body', created_by_user: user)
|
|
end
|
|
let!(:ainu) do
|
|
TagDescriptionOperation.create!(
|
|
ainu_locale, tag:, body: 'Ainu body', created_by_user: user)
|
|
end
|
|
|
|
['/wiki', '/wiki/search'].each do |path|
|
|
it "filters #{ path } by the selected language" do
|
|
get path, params: { locale: 'ain' }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json.map { _1.fetch('id') }).to eq([ainu.id])
|
|
expect(json.sole).to include('title' => 'ainu_title', 'body' => 'Ainu body')
|
|
|
|
get path, params: { locale: 'ain', title: 'japanese' }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json).to eq([])
|
|
end
|
|
end
|
|
|
|
it 'uses the existing default locale when no locale is specified' do
|
|
get '/wiki'
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json.map { _1.fetch('id') }).to eq([japanese.id])
|
|
end
|
|
|
|
it 'resolves titles and aliases only in the selected language in both APIs' do
|
|
['/wiki/title/japanese_title', '/tags/name/japanese_title/description'].each do |path|
|
|
get path, params: { locale: 'ain' }
|
|
expect(response).to have_http_status(:not_found)
|
|
end
|
|
['/wiki/title/ainu_title', '/tags/name/ainu_title/description'].each do |path|
|
|
get path, params: { locale: 'ain' }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json.fetch('body')).to eq('Ainu body')
|
|
end
|
|
get '/wiki/title/ainu_title/exists', params: { locale: 'ain' }
|
|
expect(response).to have_http_status(:no_content)
|
|
get '/wiki/title/japanese_title/exists', params: { locale: 'ain' }
|
|
expect(response).to have_http_status(:not_found)
|
|
end
|
|
|
|
it 'does not disclose another language through ID, existence, diff or history' do
|
|
revision = current_description_version(japanese)
|
|
["/wiki/#{ japanese.id }", "/wiki/#{ japanese.id }/exists",
|
|
"/wiki/#{ japanese.id }/diff"].each do |path|
|
|
get path, params: { locale: 'ain', from: revision.id }
|
|
expect(response).to have_http_status(:not_found)
|
|
expect(response.body).not_to include('Japanese body')
|
|
end
|
|
get '/wiki/changes', params: { locale: 'ain', id: japanese.id }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json).to eq([])
|
|
get '/wiki/changes', params: { locale: 'ain' }
|
|
expect(json.map { _1.fetch('revision_id') })
|
|
.to eq([current_description_version(ainu).id])
|
|
end
|
|
|
|
it 'does not update a description addressed through another language ID' do
|
|
snapshot = [japanese.attributes, ainu.attributes, ainu_name.attributes]
|
|
expect do
|
|
put "/wiki/#{ japanese.id }", params: {
|
|
locale: 'ain', title: 'renamed', body: 'wrong target' }, headers: headers
|
|
end.not_to change(TagDescriptionVersion, :count)
|
|
expect(response).to have_http_status(:not_found)
|
|
expect([japanese.reload.attributes, ainu.reload.attributes, ainu_name.reload.attributes])
|
|
.to eq(snapshot)
|
|
end
|
|
|
|
[:wiki, :native].each do |api|
|
|
it "creates the selected language through #{ api } without changing Japanese history" do
|
|
other = create(:tag, primary_name: 'other_japanese')
|
|
add_ainu_name(other, 'other_ainu')
|
|
original = TagDescriptionOperation.create!(
|
|
Locale.nipponese, tag: other, body: 'original', created_by_user: user)
|
|
snapshot = original.attributes
|
|
expect do
|
|
if api == :wiki
|
|
post '/wiki', params: { locale: 'ain', title: 'other_ainu', body: 'created' },
|
|
headers: headers
|
|
else
|
|
put "/tags/#{ other.id }/description", params: { locale: 'ain', body: 'created' },
|
|
headers: headers
|
|
end
|
|
end.to change(TagDescription, :count).by(1)
|
|
.and change(TagDescriptionVersion, :count).by(1)
|
|
expect(response).to have_http_status(:created)
|
|
created = TagDescription.find_by!(tag: other, language_code: 'ain')
|
|
expect(created).to have_attributes(body: 'created', version_no: 1)
|
|
expect(current_description_version(created)).to have_attributes(language_code: 'ain')
|
|
expect(original.reload.attributes).to eq(snapshot)
|
|
end
|
|
end
|
|
|
|
it 'shares selected-language edits and revision identity across both APIs' do
|
|
snapshot = japanese.attributes
|
|
first = current_description_version(ainu)
|
|
put "/tags/#{ tag.id }/description", params: { locale: 'ain', body: 'native edit' },
|
|
headers: headers
|
|
expect(response).to have_http_status(:ok)
|
|
second = current_description_version(ainu)
|
|
expect(second).to have_attributes(language_code: 'ain', version_no: 2)
|
|
expect(second.id).not_to eq(first.id)
|
|
get "/wiki/#{ ainu.id }", params: { locale: 'ain' }
|
|
expect(json).to include('body' => 'native edit', 'revision_id' => second.id)
|
|
|
|
put "/wiki/#{ ainu.id }", params: {
|
|
locale: 'ain', title: 'ainu_title', body: 'facade edit',
|
|
base_revision_id: second.id }, headers: headers
|
|
expect(response).to have_http_status(:ok)
|
|
get "/tags/#{ tag.id }/description", params: { locale: 'ain' }
|
|
expect(json).to include('body' => 'facade edit', 'language_code' => 'ain', 'version_no' => 3)
|
|
expect(japanese.reload.attributes).to eq(snapshot)
|
|
end
|
|
|
|
it 'rejects a stale selected-language revision without a partial title or body edit' do
|
|
stale = current_description_version(ainu)
|
|
TagDescriptionOperation.update!(
|
|
ainu_locale, tag:, body: 'current', updated_by_user: user)
|
|
snapshot = [ainu.reload.attributes, ainu_name.attributes, japanese.attributes]
|
|
expect do
|
|
put "/wiki/#{ ainu.id }", params: {
|
|
locale: 'ain', title: 'conflicting_name', body: 'current',
|
|
base_revision_id: stale.id }, headers: headers
|
|
end.to change(TagDescriptionVersion, :count).by(0).and change(TagVersion, :count).by(0)
|
|
expect(response).to have_http_status(:conflict)
|
|
expect([ainu.reload.attributes, ainu_name.reload.attributes, japanese.reload.attributes])
|
|
.to eq(snapshot)
|
|
end
|
|
|
|
it 'scopes historical show and diff to the selected description' do
|
|
first = current_description_version(ainu)
|
|
TagDescriptionOperation.update!(
|
|
ainu_locale, tag:, body: 'later', updated_by_user: user)
|
|
get "/wiki/#{ ainu.id }", params: { locale: 'ain', version: first.id }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json).to include('body' => 'Ainu body', 'revision_id' => first.id)
|
|
get "/wiki/#{ ainu.id }/diff", params: { locale: 'ain', from: first.id }
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json.fetch('newer_revision_id')).to eq(current_description_version(ainu).id)
|
|
get "/wiki/#{ ainu.id }/diff", params: {
|
|
locale: 'ain', from: current_description_version(japanese).id }
|
|
expect(response).to have_http_status(:not_found)
|
|
end
|
|
end
|