このコミットが含まれているのは:
@@ -0,0 +1,116 @@
|
||||
require 'rails_helper'
|
||||
require 'tempfile'
|
||||
|
||||
RSpec.describe CertifiedTagNameTranslations do
|
||||
let!(:language) { Language.create!(code: 'ain', name: 'ain') }
|
||||
let!(:script) { Script.create!(code: 'Kana', name: 'Kana') }
|
||||
let!(:tag) { create(:tag, primary_name: 'source') }
|
||||
let(:entries) { [{ 'ja' => 'source', 'ain-Kana' => 'レ_ハイタ' }] }
|
||||
let(:document) do
|
||||
{ 'format' => described_class::FORMAT,
|
||||
'source_locale' => 'ja', 'target_locale' => 'ain-Kana', 'entries' => entries }
|
||||
end
|
||||
let(:locale) do
|
||||
Locale.new(code: 'ain-Kana', language_code: 'ain', script_code: 'Kana',
|
||||
region_code: 392, variants: '', name: 'Ainu')
|
||||
end
|
||||
|
||||
around do |example|
|
||||
Tempfile.create(['certified-names', '.json']) do |file|
|
||||
@path = file.path
|
||||
example.run
|
||||
end
|
||||
end
|
||||
|
||||
def write_document
|
||||
File.write(@path, JSON.generate(document))
|
||||
locale.certified_tag_names_path = @path
|
||||
end
|
||||
|
||||
it 'registers certified names before automatic names and records their provenance' do
|
||||
other = create(:tag, primary_name: 'レ_ハイタ')
|
||||
write_document
|
||||
|
||||
locale.save!
|
||||
|
||||
expect(tag.reload.tag_name('ain')).to have_attributes(
|
||||
name: 'レ_ハイタ', primary_flg: true, auto_generated: false)
|
||||
expect(other.reload.tag_name('ain')).to have_attributes(
|
||||
name: "Tag_##{ other.id }", auto_generated: true)
|
||||
version = tag.tag_versions.order(:version_no).last
|
||||
expect(version.created_by_user_id).to be_nil
|
||||
expect(version.names.fetch('ain')).to include(
|
||||
'name' => 'レ_ハイタ', 'auto_generated' => false)
|
||||
end
|
||||
|
||||
it 'skips missing sources without rolling back the locale or matching entries' do
|
||||
entries.unshift({ 'ja' => 'missing', 'ain-Kana' => 'unused' })
|
||||
write_document
|
||||
|
||||
locale.save!
|
||||
|
||||
expect(locale).to be_persisted
|
||||
expect(tag.reload.name('ain')).to eq('レ_ハイタ')
|
||||
expect(TagName.exists?(language_code: 'ain', name: 'unused')).to be(false)
|
||||
end
|
||||
|
||||
it 'matches source names exactly rather than using a case-insensitive collation' do
|
||||
entries.first['ja'] = 'SOURCE'
|
||||
write_document
|
||||
|
||||
expect(described_class.load!(@path, locale:)).to eq({})
|
||||
end
|
||||
|
||||
it 'rejects ambiguous primary matches' do
|
||||
write_document
|
||||
relation = instance_double(ActiveRecord::Relation)
|
||||
allow(TagName).to receive(:where).with(
|
||||
language_code: 'ja', primary_flg: true, name: ['source']).and_return(relation)
|
||||
allow(relation).to receive(:pluck).with(:name, :tag_id)
|
||||
.and_return([['source', tag.id], ['source', tag.id + 1]])
|
||||
|
||||
expect { described_class.load!(@path, locale:) }
|
||||
.to raise_error(described_class::Error, /source.*exactly one tag/)
|
||||
end
|
||||
|
||||
it 'rejects duplicate sources and identifies the offending name' do
|
||||
entries.push({ 'ja' => 'source', 'ain-Kana' => 'another' })
|
||||
write_document
|
||||
|
||||
expect { locale.save! }.to raise_error(described_class::Error, /duplicate source.*source/)
|
||||
expect(Locale.exists?(code: 'ain-Kana')).to be(false)
|
||||
end
|
||||
|
||||
it 'rejects duplicate targets even when a source is missing' do
|
||||
entries.push({ 'ja' => 'missing', 'ain-Kana' => 'レ_ハイタ' })
|
||||
write_document
|
||||
|
||||
expect { locale.save! }.to raise_error(described_class::Error, /duplicate target.*レ_ハイタ/)
|
||||
expect(Locale.exists?(code: 'ain-Kana')).to be(false)
|
||||
end
|
||||
|
||||
it 'rolls back names and histories if a later certified name is invalid' do
|
||||
create(:tag, primary_name: 'second')
|
||||
entries.push({ 'ja' => 'second', 'ain-Kana' => 'nico:invalid' })
|
||||
write_document
|
||||
original_versions = TagVersion.order(:id).map(&:attributes)
|
||||
|
||||
expect { locale.save! }.to raise_error(described_class::Error, /nico:invalid/)
|
||||
|
||||
expect(Locale.exists?(code: 'ain-Kana')).to be(false)
|
||||
expect(TagName.where(language_code: 'ain')).to be_empty
|
||||
expect(TagVersion.order(:id).map(&:attributes)).to eq(original_versions)
|
||||
end
|
||||
|
||||
it 'does not add names or versions on repeated completion' do
|
||||
write_document
|
||||
locale.save!
|
||||
original_names = TagName.order(:id).map(&:attributes)
|
||||
original_versions = TagVersion.order(:id).map(&:attributes)
|
||||
|
||||
TagNameCompletion.for_locale!(locale)
|
||||
|
||||
expect(TagName.order(:id).map(&:attributes)).to eq(original_names)
|
||||
expect(TagVersion.order(:id).map(&:attributes)).to eq(original_versions)
|
||||
end
|
||||
end
|
||||
新しいイシューから参照
ユーザーをブロックする