このコミットが含まれているのは:
2026-10-01 23:21:03 +09:00
コミット 860cd82175
17個のファイルの変更、485行の追加、79行の削除
+36
ファイルの表示
@@ -0,0 +1,36 @@
require 'rails_helper'
RSpec.describe 'TagName database invariants' do
def insert_name!(**attributes)
TagName.insert_all!([{ name: 'constraint_name', language_code: 'ja',
script_code: 'Jpan', primary_flg: true,
created_at: Time.current, updated_at: Time.current,
**attributes }])
end
it 'defaults persisted names to human-confirmed provenance' do
insert_name!
expect(TagName.find_by!(name: 'constraint_name').auto_generated).to be(false)
end
[[true, true], [true, false], [false, false]].each do |primary_flg, auto_generated|
it "allows primary=#{ primary_flg }, auto_generated=#{ auto_generated }" do
expect { insert_name!(primary_flg:, auto_generated:) }
.to change(TagName, :count).by(1)
end
end
it 'rejects auto-generated aliases at the database boundary' do
expect { insert_name!(primary_flg: false, auto_generated: true) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
it 'rejects a second primary for the same tag and language' do
tag = create(:tag)
expect { insert_name!(tag_id: tag.id, auto_generated: false) }
.to raise_error(ActiveRecord::RecordNotUnique)
expect(TagName.where(tag:, language_code: 'ja', primary_flg: true).count).to eq(1)
end
end
+91
ファイルの表示
@@ -0,0 +1,91 @@
require 'rails_helper'
RSpec.describe 'TagVersion names database constraint' do
let(:tag) { create(:tag) }
let(:names) do
{ 'ja' => { 'name' => 'snapshot_name', 'script_code' => 'Jpan',
'auto_generated' => false, 'aliases' => [] } }
end
let(:alias_name) { { 'name' => 'snapshot_alias', 'script_code' => 'Jpan' } }
def insert_snapshot!(snapshot)
TagVersion.insert_all!([{ tag_id: tag.id, version_no: 1, event_type: 'create',
name: 'snapshot_name', category: 'general',
aliases: '', parent_tag_ids: '', names: snapshot,
created_at: Time.current }])
end
it 'accepts grouped Nipponese names with an empty alias list' do
expect { insert_snapshot!(names) }.to change(TagVersion, :count).by(1)
expect(TagVersion.find_by!(tag_id: tag.id).names).to eq(names)
end
it 'accepts aliases containing only their name and script' do
names['ja']['aliases'] = [alias_name]
expect { insert_snapshot!(names) }.to change(TagVersion, :count).by(1)
end
it 'rejects a flat array root' do
expect { insert_snapshot!([names.fetch('ja')]) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
it 'rejects an empty object root' do
expect { insert_snapshot!({ }) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
it 'rejects a language entry that is not an object' do
expect { insert_snapshot!({ 'ja' => 'not an object' }) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
['name', 'script_code', 'auto_generated', 'aliases'].each do |field|
it "rejects a primary entry missing #{ field }" do
names['ja'].delete(field)
expect { insert_snapshot!(names) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
end
it 'rejects an empty primary name' do
names['ja']['name'] = ''
expect { insert_snapshot!(names) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
it 'rejects incorrect script casing' do
names['ja']['script_code'] = 'JPAN'
expect { insert_snapshot!(names) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
['unknown', 'primary_flg', 'language_code'].each do |field|
it "rejects the extra primary field #{ field }" do
names['ja'][field] = true
expect { insert_snapshot!(names) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
end
['unknown', 'primary_flg', 'auto_generated'].each do |field|
it "rejects the extra alias field #{ field }" do
names['ja']['aliases'] = [alias_name.merge(field => true)]
expect { insert_snapshot!(names) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
end
it 'rejects duplicate alias objects' do
names['ja']['aliases'] = [alias_name, alias_name.deep_dup]
expect { insert_snapshot!(names) }
.to raise_error(ActiveRecord::StatementInvalid, /check constraint/i)
end
end
+13 -4
ファイルの表示
@@ -1,8 +1,15 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Language, type: :model do RSpec.describe Language, type: :model do
it 'accepts supported language codes' do it 'accepts Nipponese as the current supported language' do
expect(described_class.new(code: 'en', name: 'English')).to be_valid expect(described_class.find('ja')).to be_valid
expect(described_class.where(deprecated_at: nil).pluck(:code)).to eq(['ja'])
end
it 'accepts English when multilingual support is enabled' do
pending '日本語以外の Language 有効化は別課題で実装する'
expect { described_class.create!(code: 'en', name: 'English') }
.to change(described_class, :count).by(1)
end end
it 'rejects an unsupported language code' do it 'rejects an unsupported language code' do
@@ -13,11 +20,13 @@ RSpec.describe Language, type: :model do
} }
end end
it 'does not treat French as a supported language' do ['en', 'fr'].each do |code|
it "does not register #{ code } as a currently supported language" do
expect { expect {
described_class.create!(code: 'fr', name: 'French') described_class.create!(code:, name: 'Unsupported')
}.to raise_error { |error| }.to raise_error { |error|
expect(error).to be_a(ArgumentError).or be_a(ActiveRecord::RecordInvalid) expect(error).to be_a(ArgumentError).or be_a(ActiveRecord::RecordInvalid)
} }
end end
end end
end
+37 -7
ファイルの表示
@@ -1,18 +1,33 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Locale, type: :model do RSpec.describe Locale, type: :model do
def prepare_english_reference! include_context 'English locale'
Language.find_or_create_by!(code: 'en') { _1.name = 'English' }
Script.find_or_create_by!(code: 'Latn') { _1.name = 'Latin' }
end
def create_english_locale! def create_english_locale!
prepare_english_reference! prepare_english_reference!
described_class.create!(code: 'en', language_code: 'en', described_class.create!(code: 'en', language_code: 'en',
script_code: 'Latn', name: 'English') script_code: 'Latn', region_code: 826,
variants: '', name: 'English')
end
it 'keeps the active Nipponese locale consistent with its identity tuple' do
expect(described_class.where(deprecated_at: nil).pluck(:code)).to eq(['ja'])
expect(described_class.nipponese).to have_attributes(
code: 'ja', language_code: 'ja', script_code: 'Jpan',
region_code: 392, variants: '')
end
it 'rejects a duplicate locale identity tuple at the database boundary' do
expect {
described_class.insert_all!([{ code: 'ja-duplicate', language_code: 'ja',
script_code: 'Jpan', region_code: 392,
variants: '', name: '日本語',
created_at: Time.current }])
}.to raise_error(ActiveRecord::RecordNotUnique)
end end
it 'generates a primary name for every existing tag using the name generator' do it 'generates a primary name for every existing tag using the name generator' do
pending '日本語以外の Locale 有効化は別課題で実装する'
first = create(:tag, primary_name: 'first_existing_tag') first = create(:tag, primary_name: 'first_existing_tag')
second = create(:tag, primary_name: 'second_existing_tag') second = create(:tag, primary_name: 'second_existing_tag')
allow(TagName).to receive(:generate_name).and_call_original allow(TagName).to receive(:generate_name).and_call_original
@@ -39,6 +54,7 @@ RSpec.describe Locale, type: :model do
end end
it 'does not duplicate an existing primary name in the new language' do it 'does not duplicate an existing primary name in the new language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_reference! prepare_english_reference!
tag = create(:tag, primary_name: 'already_named') tag = create(:tag, primary_name: 'already_named')
existing = create(:tag_name, name: 'existing_english', tag:, existing = create(:tag_name, name: 'existing_english', tag:,
@@ -54,6 +70,7 @@ RSpec.describe Locale, type: :model do
end end
it 'creates a primary name when the language has only an alias' do it 'creates a primary name when the language has only an alias' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_reference! prepare_english_reference!
tag = create(:tag, primary_name: 'alias_only_tag') tag = create(:tag, primary_name: 'alias_only_tag')
alias_name = create(:tag_name, :alias, name: 'alias_en', alias_name = create(:tag_name, :alias, name: 'alias_en',
@@ -73,6 +90,7 @@ RSpec.describe Locale, type: :model do
end end
it 'rolls back the locale and all generated names when backfill fails' do it 'rolls back the locale and all generated names when backfill fails' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_reference! prepare_english_reference!
first = create(:tag, primary_name: 'atomic_first') first = create(:tag, primary_name: 'atomic_first')
second = create(:tag, primary_name: 'atomic_second') second = create(:tag, primary_name: 'atomic_second')
@@ -88,12 +106,24 @@ RSpec.describe Locale, type: :model do
end end
it 'accepts a stable locale code outside the historical enum values' do it 'accepts a stable locale code outside the historical enum values' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_reference! prepare_english_reference!
locale = described_class.create!( locale = described_class.create!(
code: 'en-x-rspec', language_code: 'en', code: 'en-x-rspec', language_code: 'en',
script_code: 'Latn', name: 'English') script_code: 'Latn', region_code: 826,
variants: 'x-rspec', name: 'English')
expect(locale.reload).to have_attributes(code: 'en-x-rspec', language_code: 'en') expect(locale.reload).to have_attributes(
code: 'en-x-rspec', language_code: 'en', script_code: 'Latn',
region_code: 826, variants: 'x-rspec')
end
it 'registers the future British English locale tuple' do
pending '日本語以外の Locale 有効化は別課題で実装する'
expect(locale).to have_attributes(code: 'en', language_code: 'en',
script_code: 'Latn', region_code: 826,
variants: '')
end end
end end
+19 -4
ファイルの表示
@@ -4,17 +4,32 @@ RSpec.describe Script, type: :model do
include_context 'English locale' include_context 'English locale'
it 'selects locales by script code, not language code' do it 'selects locales by script code, not language code' do
expect(described_class.find('Latn').locales).to include(locale) expect(described_class.find('Jpan').locales).to contain_exactly(Locale.nipponese)
expect(described_class.find('Jpan').locales).to include(Locale.nipponese)
expect(described_class.find('Jpan').locales).not_to include(locale)
end end
it 'accepts supported script codes and rejects unsupported ones' do it 'accepts supported script codes and rejects unsupported ones' do
expect(described_class.new(code: 'Latn', name: 'Latin')).to be_valid expect(described_class.find('Jpan')).to be_valid
expect(described_class.where(deprecated_at: nil).pluck(:code)).to eq(['Jpan'])
expect { expect {
described_class.create!(code: 'Zzzz', name: 'Unsupported') described_class.create!(code: 'Zzzz', name: 'Unsupported')
}.to raise_error { |error| }.to raise_error { |error|
expect(error).to be_a(ArgumentError).or be_a(ActiveRecord::RecordInvalid) expect(error).to be_a(ArgumentError).or be_a(ActiveRecord::RecordInvalid)
} }
end end
it 'does not register Latin as a currently supported script' do
expect {
described_class.create!(code: 'Latn', name: 'Latin')
}.to raise_error { |error|
expect(error).to be_a(ArgumentError).or be_a(ActiveRecord::RecordInvalid)
}
end
it 'selects Latin locales when multilingual support is enabled' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
expect(described_class.find('Latn').locales).to contain_exactly(locale)
expect(described_class.find('Jpan').locales).not_to include(locale)
end
end end
+4
ファイルの表示
@@ -38,6 +38,8 @@ RSpec.describe TagNameSanitisationRule, type: :model do
include_context 'English locale' include_context 'English locale'
it 'keeps both names when sanitisation produces a cross-language match' do it 'keeps both names when sanitisation produces a cross-language match' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = create(:tag_name, name: 'foobar') nipponese = create(:tag_name, name: 'foobar')
english = create(:tag_name, name: 'temporary', english = create(:tag_name, name: 'temporary',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
@@ -50,6 +52,8 @@ RSpec.describe TagNameSanitisationRule, type: :model do
end end
it 'renames without merging tags or deleting either language identity' do it 'renames without merging tags or deleting either language identity' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = create(:tag, primary_name: 'foobar') nipponese = create(:tag, primary_name: 'foobar')
english_name = create(:tag_name, name: 'temporary', english_name = create(:tag_name, name: 'temporary',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
+23 -2
ファイルの表示
@@ -4,6 +4,8 @@ RSpec.describe TagName, type: :model do
include_context 'English locale' include_context 'English locale'
it 'allows the same name in different languages' do it 'allows the same name in different languages' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
create(:tag_name, name: 'shared_name') create(:tag_name, name: 'shared_name')
english = build(:tag_name, name: 'shared_name', english = build(:tag_name, name: 'shared_name',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
@@ -24,7 +26,15 @@ RSpec.describe TagName, type: :model do
name = create(:tag_name) name = create(:tag_name)
expect(name.reload).to have_attributes( expect(name.reload).to have_attributes(
language_code: 'ja', script_code: 'Jpan', primary_flg: true, tag_id: nil) language_code: 'ja', script_code: 'Jpan', primary_flg: true,
auto_generated: false, tag_id: nil)
end
it 'defaults ordinary persisted human names to confirmed provenance' do
name = described_class.create!(name: 'ordinary_human_name', language_code: 'ja',
script_code: 'Jpan', primary_flg: true)
expect(name.reload.auto_generated).to be(false)
end end
it 'persists both sides of the representative tag factory association' do it 'persists both sides of the representative tag factory association' do
@@ -39,7 +49,7 @@ RSpec.describe TagName, type: :model do
expect(tag.reload.tag_name_id).to eq(name.id) expect(tag.reload.tag_name_id).to eq(name.id)
end end
it 'creates a complete ordinary tag factory under every active language' do it 'creates a complete ordinary tag factory under the active Nipponese language' do
tag = create(:tag, primary_name: 'factory_multilingual') tag = create(:tag, primary_name: 'factory_multilingual')
Locale.where(deprecated_at: nil).distinct.pluck(:language_code).each do |language_code| Locale.where(deprecated_at: nil).distinct.pluck(:language_code).each do |language_code|
@@ -47,6 +57,13 @@ RSpec.describe TagName, type: :model do
end end
expect(TagName.where(tag:, language_code: 'ja', primary_flg: true)) expect(TagName.where(tag:, language_code: 'ja', primary_flg: true))
.to contain_exactly(have_attributes(auto_generated: false)) .to contain_exactly(have_attributes(auto_generated: false))
end
it 'completes an ordinary tag factory under future active languages' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
tag = create(:tag, primary_name: 'future_factory')
expect(TagName.where(tag:, language_code: 'en', primary_flg: true)) expect(TagName.where(tag:, language_code: 'en', primary_flg: true))
.to contain_exactly(have_attributes(auto_generated: true)) .to contain_exactly(have_attributes(auto_generated: true))
end end
@@ -95,6 +112,8 @@ RSpec.describe TagName, type: :model do
end end
it 'resolves the primary name of the alias language on the same tag' do it 'resolves the primary name of the alias language on the same tag' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
tag = create(:tag, primary_name: '日本語正本') tag = create(:tag, primary_name: '日本語正本')
english_primary = primary_tag_name_for(tag, 'en') english_primary = primary_tag_name_for(tag, 'en')
english_primary.update!(name: 'english_primary', auto_generated: false) english_primary.update!(name: 'english_primary', auto_generated: false)
@@ -113,6 +132,8 @@ RSpec.describe TagName, type: :model do
end end
it 'resolves only aliases in the requested language' do it 'resolves only aliases in the requested language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = create(:tag, primary_name: 'nipponese_canonical') nipponese = create(:tag, primary_name: 'nipponese_canonical')
english_name = create(:tag_name, name: 'english_canonical', english_name = create(:tag_name, name: 'english_canonical',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
+49 -13
ファイルの表示
@@ -25,17 +25,18 @@ RSpec.describe Tag, type: :model do
end end
describe '.normalise_tags!' do describe '.normalise_tags!' do
include_context 'English locale'
it 'canonicalises aliases in the supplied language only' do it 'canonicalises aliases in the supplied language only' do
Language.find_or_create_by!(code: 'en') { _1.name = 'English' } pending '日本語以外の Locale 有効化は別課題で実装する'
Script.find_or_create_by!(code: 'Latn') { _1.name = 'Latin' } prepare_english_reference!
nipponese = create(:tag, primary_name: 'nipponese_canonical') nipponese = create(:tag, primary_name: 'nipponese_canonical')
english_name = create(:tag_name, name: 'english_canonical', english_name = create(:tag_name, name: 'english_canonical',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
english = create(:tag, primary_tag_name: english_name) english = create(:tag, primary_tag_name: english_name)
primary_tag_name_for(english, 'ja').update!( primary_tag_name_for(english, 'ja').update!(
name: 'english_in_nipponese', auto_generated: false) name: 'english_in_nipponese', auto_generated: false)
english_locale = Locale.create!( english_locale = locale
code: 'en', language_code: 'en', script_code: 'Latn', name: 'English')
nipponese_alias = create(:tag_name, :alias, name: 'shared_alias', nipponese_alias = create(:tag_name, :alias, name: 'shared_alias',
tag: nipponese) tag: nipponese)
english_alias = create(:tag_name, :alias, name: 'shared_alias', english_alias = create(:tag_name, :alias, name: 'shared_alias',
@@ -219,6 +220,8 @@ RSpec.describe Tag, type: :model do
include_context 'English locale' include_context 'English locale'
it 'creates the representative name with locale attributes and ownership' do it 'creates the representative name with locale attributes and ownership' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
tag = described_class.find_or_create_by_tag_name!( tag = described_class.find_or_create_by_tag_name!(
locale, 'english_name', category: :character) locale, 'english_name', category: :character)
@@ -229,6 +232,8 @@ RSpec.describe Tag, type: :model do
end end
it 'uses the English primary as the source for a generated Nipponese name' do it 'uses the English primary as the source for a generated Nipponese name' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
allow(TagName).to receive(:generate_name).and_return('generated_nipponese') allow(TagName).to receive(:generate_name).and_return('generated_nipponese')
tag = described_class.find_or_create_by_tag_name!( tag = described_class.find_or_create_by_tag_name!(
@@ -246,6 +251,8 @@ RSpec.describe Tag, type: :model do
end end
it 'gives a new tag one primary name for every active language' do it 'gives a new tag one primary name for every active language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
tag = described_class.find_or_create_by_tag_name!( tag = described_class.find_or_create_by_tag_name!(
Locale.nipponese, 'new_multilingual_tag', category: :general) Locale.nipponese, 'new_multilingual_tag', category: :general)
@@ -254,10 +261,13 @@ RSpec.describe Tag, type: :model do
end end
it 'creates one primary per language when multiple locales use English' do it 'creates one primary per language when multiple locales use English' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
described_class.find_or_create_by_tag_name!( described_class.find_or_create_by_tag_name!(
locale, 'before_second_english_locale', category: :general) locale, 'before_second_english_locale', category: :general)
Locale.create!(code: 'en-x-rspec', language_code: 'en', Locale.create!(code: 'en-x-rspec', language_code: 'en',
script_code: 'Latn', name: 'English') script_code: 'Latn', region_code: 826,
variants: 'x-rspec', name: 'English')
tag = described_class.find_or_create_by_tag_name!( tag = described_class.find_or_create_by_tag_name!(
locale, 'one_english_primary', category: :general) locale, 'one_english_primary', category: :general)
@@ -267,6 +277,8 @@ RSpec.describe Tag, type: :model do
end end
it 'rolls back a new tag and requested name if name generation fails' do it 'rolls back a new tag and requested name if name generation fails' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
original_tag_count = described_class.count original_tag_count = described_class.count
allow(TagName).to receive(:generate_name).and_raise('generation failed') allow(TagName).to receive(:generate_name).and_raise('generation failed')
@@ -282,6 +294,8 @@ RSpec.describe Tag, type: :model do
end end
it 'keeps a detached requested name detached if generation fails' do it 'keeps a detached requested name detached if generation fails' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
detached = create(:tag_name, :alias, name: 'atomic_detached', detached = create(:tag_name, :alias, name: 'atomic_detached',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
original_tag_count = described_class.count original_tag_count = described_class.count
@@ -297,6 +311,8 @@ RSpec.describe Tag, type: :model do
end end
it 'promotes a detached alias into the requested primary name' do it 'promotes a detached alias into the requested primary name' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
detached = create(:tag_name, :alias, name: 'detached_english', detached = create(:tag_name, :alias, name: 'detached_english',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
@@ -311,6 +327,8 @@ RSpec.describe Tag, type: :model do
end end
it 'creates separate tag identities for the same name in different languages' do it 'creates separate tag identities for the same name in different languages' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = described_class.find_or_create_by_tag_name!( nipponese = described_class.find_or_create_by_tag_name!(
Locale.nipponese, 'same_name', category: :general) Locale.nipponese, 'same_name', category: :general)
english = described_class.find_or_create_by_tag_name!( english = described_class.find_or_create_by_tag_name!(
@@ -328,6 +346,8 @@ RSpec.describe Tag, type: :model do
end end
it 'preserves the V1 representative when looking up another primary language' do it 'preserves the V1 representative when looking up another primary language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
tag = create(:tag, primary_name: '日本語代表名') tag = create(:tag, primary_name: '日本語代表名')
representative_id = tag.tag_name_id representative_id = tag.tag_name_id
english = primary_tag_name_for(tag, 'en') english = primary_tag_name_for(tag, 'en')
@@ -342,6 +362,8 @@ RSpec.describe Tag, type: :model do
end end
it 'normalises names using the supplied locale' do it 'normalises names using the supplied locale' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
tags = described_class.normalise_tags!( tags = described_class.normalise_tags!(
locale, ['character:normalised_english'], locale, ['character:normalised_english'],
with_tagme: false, with_no_deerjikist: false) with_tagme: false, with_no_deerjikist: false)
@@ -363,6 +385,21 @@ RSpec.describe Tag, type: :model do
expect(primary_tag_name_for(tag, 'ja').name).to eq('lookup_new') expect(primary_tag_name_for(tag, 'ja').name).to eq('lookup_new')
expect(tag.category).to eq('character') expect(tag.category).to eq('character')
expect(TagName.where(tag:, language_code: 'ja', primary_flg: true).count).to eq(1)
expect(primary_tag_name_for(tag, 'ja').auto_generated).to be(false)
end
it 'promotes a detached Nipponese alias into a human-confirmed primary' do
detached = create(:tag_name, :alias, name: 'detached_nipponese')
tag = described_class.find_or_create_by_tag_name!(
Locale.nipponese, detached.name, category: :general)
expect(detached.reload).to have_attributes(
tag_id: tag.id, primary_flg: true, canonical_id: nil,
auto_generated: false)
expect(TagName.where(tag:, language_code: 'ja', primary_flg: true))
.to contain_exactly(detached)
end end
it 'reuses the owning tag for an alias without changing its category' do it 'reuses the owning tag for an alias without changing its category' do
@@ -417,6 +454,8 @@ RSpec.describe Tag, type: :model do
include_context 'English locale' include_context 'English locale'
it 'keeps the target primary and moves source names as aliases' do it 'keeps the target primary and moves source names as aliases' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_primary = primary_tag_name_for(target_tag, 'en') english_primary = primary_tag_name_for(target_tag, 'en')
source_primary = primary_tag_name_for(source_tag, 'en') source_primary = primary_tag_name_for(source_tag, 'en')
source_alias = create(:tag_name, :alias, tag: source_tag, source_alias = create(:tag_name, :alias, tag: source_tag,
@@ -497,18 +536,15 @@ RSpec.describe Tag, type: :model do
.to eq([[1, 'create'], [2, 'discard']]) .to eq([[1, 'create'], [2, 'discard']])
expect(versions.first).to eq(original_version) expect(versions.first).to eq(original_version)
expect(versions.last.created_by_user).to eq(user) expect(versions.last.created_by_user).to eq(user)
expect(versions.last.names).to include( expect(versions.last.names.fetch('ja')).to eq(
hash_including('language_code' => 'ja', 'name' => source_name, 'name' => source_name, 'script_code' => 'Jpan',
'primary_flg' => true, 'auto_generated' => false), 'auto_generated' => false,
hash_including('language_code' => 'ja', 'name' => source_alias.name, 'aliases' => [{ 'name' => source_alias.name, 'script_code' => 'Jpan' }])
'primary_flg' => false, 'auto_generated' => false))
expect(Tag.unscoped.exists?(source_tag.id)).to be(false) expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
target_versions = target_tag.tag_versions.order(:version_no) target_versions = target_tag.tag_versions.order(:version_no)
expect(target_versions.pluck(:event_type)).to eq(['create', 'update']) expect(target_versions.pluck(:event_type)).to eq(['create', 'update'])
target_aliases = target_versions.last.names.filter_map { |name| target_aliases = target_versions.last.names.fetch('ja').fetch('aliases').pluck('name')
name['name'] if name['language_code'] == 'ja' && !name['primary_flg']
}
expect(target_aliases).to contain_exactly('merge_alias', source_name) expect(target_aliases).to contain_exactly('merge_alias', source_name)
end end
+6 -8
ファイルの表示
@@ -12,12 +12,11 @@ RSpec.describe VersionRecord, type: :model do
name: primary_tag_name_for(tag, 'ja').name, name: primary_tag_name_for(tag, 'ja').name,
category: tag.category, category: tag.category,
aliases: '', aliases: '',
names: [{ language_code: 'ja', name: primary_tag_name_for(tag, 'ja').name, names: { ja: { name: primary_tag_name_for(tag, 'ja').name,
script_code: 'Jpan', primary_flg: true }], script_code: 'Jpan', auto_generated: false, aliases: [] } },
parent_tag_ids: '', parent_tag_ids: '',
created_at: Time.current, created_at: Time.current,
created_by_user: nil created_by_user: nil)
)
expect { expect {
version.update!(name: 'changed') version.update!(name: 'changed')
@@ -32,12 +31,11 @@ RSpec.describe VersionRecord, type: :model do
name: primary_tag_name_for(tag, 'ja').name, name: primary_tag_name_for(tag, 'ja').name,
category: tag.category, category: tag.category,
aliases: '', aliases: '',
names: [{ language_code: 'ja', name: primary_tag_name_for(tag, 'ja').name, names: { ja: { name: primary_tag_name_for(tag, 'ja').name,
script_code: 'Jpan', primary_flg: true }], script_code: 'Jpan', auto_generated: false, aliases: [] } },
parent_tag_ids: '', parent_tag_ids: '',
created_at: Time.current, created_at: Time.current,
created_by_user: nil created_by_user: nil)
)
expect { expect {
version.destroy! version.destroy!
+86 -5
ファイルの表示
@@ -17,12 +17,51 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
tag_name.tag tag_name.tag
end end
it 'confirms a generated Nipponese primary when a human renames it' do
tag = create(:tag, primary_name: 'generated_source')
primary = primary_tag_name_for(tag, 'ja')
primary.update!(name: "Tag_##{ tag.id }", auto_generated: true)
patch "/tags/#{ tag.id }", params: { locale: 'ja', name: '人間が確定した名称' }
expect(response).to have_http_status(:ok), response.body
expect(primary.reload).to have_attributes(
name: '人間が確定した名称', auto_generated: false)
end
it 'rolls back Nipponese edits when an alias conflicts with another primary' do
tag = create(:tag, primary_name: 'target_before_collision')
create(:tag_name, :alias, tag:, name: 'existing_alias')
other_tag = create(:tag, primary_name: 'other_primary')
other_primary = primary_tag_name_for(other_tag, 'ja')
primary_name_before = primary_tag_name_for(tag, 'ja').name
aliases_before = tag.tag_names.where(primary_flg: false).order(:name).pluck(:name)
category_before = tag.category
put "/tags/#{ tag.id }", params: {
locale: 'ja', name: 'renamed_before_collision', category: 'character',
deprecated: false, aliases: 'other_primary', parent_tags: '' }
aggregate_failures do
expect(response).to have_http_status(:unprocessable_entity)
expect(other_primary.reload).to have_attributes(tag_id: other_tag.id, primary_flg: true)
expect(TagName.where(tag: other_tag, language_code: 'ja', primary_flg: true))
.to contain_exactly(other_primary)
expect(primary_tag_name_for(tag.reload, 'ja').name).to eq(primary_name_before)
expect(tag.category).to eq(category_before)
expect(tag.tag_names.where(primary_flg: false).order(:name).pluck(:name))
.to eq(aliases_before)
end
end
['en', nil].each do |requested_locale| ['en', nil].each do |requested_locale|
context "with locale #{ requested_locale.inspect }" do context "with locale #{ requested_locale.inspect }" do
let(:locale_params) { requested_locale ? { locale: requested_locale } : { } } let(:locale_params) { requested_locale ? { locale: requested_locale } : { } }
let(:expected_locale) { requested_locale ? locale : Locale.nipponese } let(:expected_locale) { requested_locale ? locale : Locale.nipponese }
it 'creates post tags in the requested language or Nipponese fallback' do it 'creates post tags in the requested language or Nipponese fallback' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
post '/posts', params: locale_params.merge( post '/posts', params: locale_params.merge(
title: 'Locale post', url: 'https://example.com/locale-post', title: 'Locale post', url: 'https://example.com/locale-post',
tags: 'locale_post_tag', parent_post_ids: '') tags: 'locale_post_tag', parent_post_ids: '')
@@ -33,6 +72,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'updates post tags in the requested language or Nipponese fallback' do it 'updates post tags in the requested language or Nipponese fallback' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
record = create(:post) record = create(:post)
PostVersionRecorder.record!(post: record, event_type: :create, created_by_user: member) PostVersionRecorder.record!(post: record, event_type: :create, created_by_user: member)
@@ -46,6 +87,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'passes the resolved locale to bulk creation' do it 'passes the resolved locale to bulk creation' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
# Worker propagation is exercised in post_bulk_creator_spec. # Worker propagation is exercised in post_bulk_creator_spec.
expect_any_instance_of(PostBulkCreator).to receive(:run) expect_any_instance_of(PostBulkCreator).to receive(:run)
.with(expected_locale).and_return(results: []) .with(expected_locale).and_return(results: [])
@@ -59,6 +102,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'creates materials with tags in the resolved locale' do it 'creates materials with tags in the resolved locale' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
post '/materials', params: locale_params.merge( post '/materials', params: locale_params.merge(
tag: 'locale_material', url: 'https://example.com/material') tag: 'locale_material', url: 'https://example.com/material')
@@ -68,6 +113,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'updates materials with tags in the resolved locale' do it 'updates materials with tags in the resolved locale' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
tag = create(:tag, category: :material) tag = create(:tag, category: :material)
material = Material.create!(tag:, url: 'https://example.com/material') material = Material.create!(tag:, url: 'https://example.com/material')
@@ -80,6 +127,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'links Nico external tags to internal tags in the resolved locale' do it 'links Nico external tags to internal tags in the resolved locale' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
external = create(:external_tag) external = create(:external_tag)
NicoTagVersionRecorder.record!( NicoTagVersionRecorder.record!(
external_tag: external, event_type: :create, created_by_user: member) external_tag: external, event_type: :create, created_by_user: member)
@@ -92,6 +141,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'creates parent tags in the resolved locale' do it 'creates parent tags in the resolved locale' do
pending '日本語以外の Locale 有効化は別課題で実装する' if requested_locale
locale if requested_locale
tag = create(:tag) tag = create(:tag)
put "/tags/#{ tag.id }", params: locale_params.merge( put "/tags/#{ tag.id }", params: locale_params.merge(
@@ -106,11 +157,11 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
context 'with existing names in both languages' do context 'with existing names in both languages' do
let!(:english_name) do let(:english_name) do
create(:tag_name, name: 'shared_name', language_code: 'en', script_code: 'Latn') create(:tag_name, name: 'shared_name', language_code: 'en', script_code: 'Latn')
end end
let!(:english_tag) { create(:tag, primary_tag_name: english_name, category: :material) } let(:english_tag) { create(:tag, primary_tag_name: english_name, category: :material) }
let!(:nipponese_tag) do let(:nipponese_tag) do
create(:tag, primary_name: 'temporary_nipponese', category: :general).tap do |tag| create(:tag, primary_name: 'temporary_nipponese', category: :general).tap do |tag|
# Isolate lookup from the separately tested uniqueness validation. # Isolate lookup from the separately tested uniqueness validation.
primary_tag_name_for(tag, 'ja').update_columns(name: 'shared_name') primary_tag_name_for(tag, 'ja').update_columns(name: 'shared_name')
@@ -118,6 +169,10 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'plans and creates the post using the English identity and category' do it 'plans and creates the post using the English identity and category' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_tag
nipponese_tag
post '/posts', params: { post '/posts', params: {
locale: 'en', title: 'English identity', locale: 'en', title: 'English identity',
url: 'https://example.com/english-identity', tags: 'shared_name', parent_post_ids: '' } url: 'https://example.com/english-identity', tags: 'shared_name', parent_post_ids: '' }
@@ -131,6 +186,10 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'updates the post using the English identity' do it 'updates the post using the English identity' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_tag
nipponese_tag
record = create(:post) record = create(:post)
PostVersionRecorder.record!(post: record, event_type: :create, created_by_user: member) PostVersionRecorder.record!(post: record, event_type: :create, created_by_user: member)
@@ -144,6 +203,10 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'resolves the English material tag' do it 'resolves the English material tag' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_tag
nipponese_tag
post '/materials', params: { post '/materials', params: {
locale: 'en', tag: 'shared_name', url: 'https://example.com/english-material' } locale: 'en', tag: 'shared_name', url: 'https://example.com/english-material' }
@@ -153,6 +216,10 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'resolves the English parent tag' do it 'resolves the English parent tag' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_tag
nipponese_tag
child = create(:tag) child = create(:tag)
put "/tags/#{ child.id }", params: { put "/tags/#{ child.id }", params: {
@@ -165,6 +232,10 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'resolves the English internal tag for a Nico link' do it 'resolves the English internal tag for a Nico link' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_tag
nipponese_tag
external = create(:external_tag) external = create(:external_tag)
NicoTagVersionRecorder.record!( NicoTagVersionRecorder.record!(
external_tag: external, event_type: :create, created_by_user: member) external_tag: external, event_type: :create, created_by_user: member)
@@ -177,12 +248,14 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
context 'when renaming or updating aliases in English' do context 'when renaming or updating aliases in English' do
let!(:english_name) do let(:english_name) do
create(:tag_name, name: 'english_original', language_code: 'en', script_code: 'Latn') create(:tag_name, name: 'english_original', language_code: 'en', script_code: 'Latn')
end end
let!(:tag) { create(:tag, primary_tag_name: english_name) } let(:tag) { create(:tag, primary_tag_name: english_name) }
it 'marks a human-renamed generated primary as no longer auto-generated' do it 'marks a human-renamed generated primary as no longer auto-generated' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
generated_tag = create(:tag, primary_name: 'rename_generated_source') generated_tag = create(:tag, primary_name: 'rename_generated_source')
generated_name = primary_tag_name_for(generated_tag, 'en') generated_name = primary_tag_name_for(generated_tag, 'en')
expect(generated_name.auto_generated).to be(true) expect(generated_name.auto_generated).to be(true)
@@ -196,6 +269,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'does not steal another tag primary for an alias' do it 'does not steal another tag primary for an alias' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
other_tag = create(:tag, primary_name: 'other_nipponese') other_tag = create(:tag, primary_name: 'other_nipponese')
other_primary = primary_tag_name_for(other_tag, 'en') other_primary = primary_tag_name_for(other_tag, 'en')
other_primary.update!(name: 'other_english_primary', auto_generated: false) other_primary.update!(name: 'other_english_primary', auto_generated: false)
@@ -228,6 +303,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'allows a rename to a name already used in Nipponese' do it 'allows a rename to a name already used in Nipponese' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = create(:tag, primary_name: 'rename_target') nipponese = create(:tag, primary_name: 'rename_target')
patch "/tags/#{ tag.id }", params: { locale: 'en', name: 'rename_target' } patch "/tags/#{ tag.id }", params: { locale: 'en', name: 'rename_target' }
@@ -240,6 +317,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'creates aliases in the requested language' do it 'creates aliases in the requested language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
put "/tags/#{ tag.id }", params: { put "/tags/#{ tag.id }", params: {
locale: 'en', name: english_name.name, locale: 'en', name: english_name.name,
category: tag.category, deprecated: false, category: tag.category, deprecated: false,
@@ -255,6 +334,8 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
end end
it 'does not take an alias from another language' do it 'does not take an alias from another language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = create(:tag, primary_name: 'nipponese_owner') nipponese = create(:tag, primary_name: 'nipponese_owner')
nipponese_alias = create(:tag_name, :alias, name: 'shared_alias', nipponese_alias = create(:tag_name, :alias, name: 'shared_alias',
tag: nipponese) tag: nipponese)
+4 -6
ファイルの表示
@@ -36,12 +36,10 @@ RSpec.describe 'TagVersions API', type: :request do
category: category, category: category,
deprecated_at: deprecated_at, deprecated_at: deprecated_at,
aliases: Array(aliases).join(' '), aliases: Array(aliases).join(' '),
names: [{ language_code: 'ja', name:, script_code: 'Jpan', names: { ja: { name:, script_code: 'Jpan', auto_generated: false,
primary_flg: true, aliases: Array(aliases).sort.map { |alias_name|
auto_generated: false }] + Array(aliases).map { |alias_name| { name: alias_name, script_code: 'Jpan' }
{ language_code: 'ja', name: alias_name, script_code: 'Jpan', } } },
primary_flg: false, auto_generated: false }
},
parent_tag_ids: Array(parent_tags).map(&:id).join(' '), parent_tag_ids: Array(parent_tags).map(&:id).join(' '),
created_by_user: created_by_user, created_by_user: created_by_user,
created_at: created_at) created_at: created_at)
+2 -6
ファイルの表示
@@ -19,15 +19,11 @@ RSpec.describe 'Tags API', type: :request do
end end
def version_primary_name(version, language_code) def version_primary_name(version, language_code)
version.names.find { |name| version.names.fetch(language_code).fetch('name')
name['language_code'] == language_code && name['primary_flg']
}.fetch('name')
end end
def version_alias_names(version, language_code) def version_alias_names(version, language_code)
version.names.filter_map { |name| version.names.fetch(language_code).fetch('aliases').pluck('name')
name['name'] if name['language_code'] == language_code && !name['primary_flg']
}
end end
def dummy_material_upload(filename: 'dummy.png', type: 'image/png', body: 'dummy') def dummy_material_upload(filename: 'dummy.png', type: 'image/png', body: 'dummy')
+23
ファイルの表示
@@ -4,6 +4,7 @@ RSpec.describe PostBulkCreator do
include_context 'English locale' include_context 'English locale'
it 'limits workers to two and keeps failures in their request slots' do it 'limits workers to two and keeps failures in their request slots' do
locale = Locale.nipponese
actor = instance_double(User, id: 123) actor = instance_double(User, id: 123)
allow(User).to receive(:find).with(123) { allow(User).to receive(:find).with(123) {
instance_double(User, id: 123) instance_double(User, id: 123)
@@ -65,4 +66,26 @@ RSpec.describe PostBulkCreator do
expect(results[2].dig(:post, :id)).to eq(3) expect(results[2].dig(:post, :id)).to eq(3)
expect(results[3].dig(:post, :id)).to eq(4) expect(results[3].dig(:post, :id)).to eq(4)
end end
it 'passes a future English locale to preflight and creation in every worker' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
actor = instance_double(User, id: 123)
allow(User).to receive(:find).with(123).and_return(actor)
preflight = instance_double(PostCreatePreflight)
creator = instance_double(PostCreator)
post = instance_double(Post, id: 1)
allow(PostCreatePreflight).to receive(:new).and_return(preflight)
allow(preflight).to receive(:run).with(locale).and_return(existing_post_id: nil)
allow(PostCreator).to receive(:new).and_return(creator)
allow(creator).to receive(:create!).with(locale).and_return(post)
results = described_class.new(
actor:, posts: [{ title: 'future post' }], thumbnails: { }).run(locale)
expect(results.fetch(:results)).to contain_exactly(
hash_including(status: 'created', post: { id: 1 }))
expect(preflight).to have_received(:run).with(locale).once
expect(creator).to have_received(:create!).with(locale).once
end
end end
+4
ファイルの表示
@@ -14,6 +14,8 @@ RSpec.describe PostCreatePlan do
include_context 'English locale' include_context 'English locale'
it 'resolves the matching language identity and its parents' do it 'resolves the matching language identity and its parents' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
english_name = create(:tag_name, name: 'shared_name', english_name = create(:tag_name, name: 'shared_name',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
english = create(:tag, primary_tag_name: english_name, category: :character) english = create(:tag, primary_tag_name: english_name, category: :character)
@@ -39,6 +41,8 @@ RSpec.describe PostCreatePlan do
end end
it 'resolves aliases within the requested language' do it 'resolves aliases within the requested language' do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
nipponese = create(:tag, primary_name: 'nipponese_canonical') nipponese = create(:tag, primary_name: 'nipponese_canonical')
english_name = create(:tag_name, name: 'english_canonical', english_name = create(:tag_name, name: 'english_canonical',
language_code: 'en', script_code: 'Latn') language_code: 'en', script_code: 'Latn')
+2
ファイルの表示
@@ -81,6 +81,8 @@ RSpec.describe PostCreator do
[false, true].each do |planned| [false, true].each do |planned|
it "passes locale to tag creation with planned attributes: #{ planned }" do it "passes locale to tag creation with planned attributes: #{ planned }" do
pending '日本語以外の Locale 有効化は別課題で実装する'
locale
attributes = { attributes = {
title: 'Locale propagation', title: 'Locale propagation',
url: 'https://example.com/locale-post', url: 'https://example.com/locale-post',
+70 -19
ファイルの表示
@@ -1,45 +1,96 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe TagVersionRecorder do RSpec.describe TagVersionRecorder do
let(:user) { create_member_user! }
let!(:tag) { create(:tag, primary_name: '日本語名') }
include_context 'English locale' include_context 'English locale'
let(:user) { create_member_user! }
let!(:tag) { create(:tag, primary_name: '日本語名') }
before do before do
create(:tag_name, :alias, tag:, name: '別名') create(:tag_name, :alias, tag:, name: 'alias_z')
create(:tag_name, :alias, tag:, name: 'alias_a')
end
def nipponese_snapshot
{ 'name' => '日本語名', 'script_code' => 'Jpan', 'auto_generated' => false,
'aliases' => [{ 'name' => 'alias_a', 'script_code' => 'Jpan' },
{ 'name' => 'alias_z', 'script_code' => 'Jpan' }] }
end
def prepare_english_names!
locale
primary_tag_name_for(tag, 'en').update!(name: 'English name', auto_generated: false) primary_tag_name_for(tag, 'en').update!(name: 'English name', auto_generated: false)
create(:tag_name, :alias, tag:, language_code: 'en', script_code: 'Latn', create(:tag_name, :alias, tag:, language_code: 'en', script_code: 'Latn',
name: 'English alias') name: 'English alias')
end end
it 'snapshots every language primary name and alias deterministically' do it 'snapshots the Nipponese primary and sorted aliases in grouped names' do
version = described_class.record!(tag:, event_type: :create, created_by_user: user) version = described_class.record!(tag:, event_type: :create, created_by_user: user)
expect(version.names).to eq([ expect(version.reload.names).to eq('ja' => nipponese_snapshot)
{ 'language_code' => 'en', 'name' => 'English name', 'script_code' => 'Latn',
'primary_flg' => true, 'auto_generated' => false },
{ 'language_code' => 'en', 'name' => 'English alias', 'script_code' => 'Latn',
'primary_flg' => false, 'auto_generated' => false },
{ 'language_code' => 'ja', 'name' => '日本語名', 'script_code' => 'Jpan',
'primary_flg' => true, 'auto_generated' => false },
{ 'language_code' => 'ja', 'name' => '別名', 'script_code' => 'Jpan',
'primary_flg' => false, 'auto_generated' => false }
])
end end
it 'creates a version for an English-only name change and preserves prior names' do it 'does not create a version for an unchanged Nipponese snapshot' do
original = described_class.record!(tag:, event_type: :create, created_by_user: user) original = described_class.record!(tag:, event_type: :create, created_by_user: user)
TagName.find_by!(tag:, language_code: 'en', primary_flg: true).update!(name: 'Renamed')
unchanged = described_class.record!(tag:, event_type: :update, created_by_user: user)
expect(unchanged.version_no).to eq(original.version_no)
expect(tag.reload.tag_versions.count).to eq(1)
end
it 'snapshots an unconfirmed system primary with auto_generated true' do
primary_tag_name_for(tag, 'ja').update!(auto_generated: true)
version = described_class.record!(tag:, event_type: :create, created_by_user: user)
expect(version.names.fetch('ja')).to eq(nipponese_snapshot.merge('auto_generated' => true))
end
it 'keeps a past snapshot after current primary and alias changes' do
original = described_class.record!(tag:, event_type: :create, created_by_user: user)
primary_tag_name_for(tag, 'ja').update!(name: '改名後')
tag.tag_names.find_by!(name: 'alias_z').destroy!
updated = described_class.record!(tag:, event_type: :update, created_by_user: user)
expect(original.reload.names).to eq('ja' => nipponese_snapshot)
expect(updated.names.fetch('ja')).to include('name' => '改名後')
expect(updated.names.fetch('ja').fetch('aliases'))
.to eq([{ 'name' => 'alias_a', 'script_code' => 'Jpan' }])
expect(updated.version_no).to eq(2)
end
it 'snapshots future languages together without a request locale argument' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_names!
version = described_class.record!(tag:, event_type: :create, created_by_user: user)
expect(version.names).to eq(
'ja' => nipponese_snapshot,
'en' => { 'name' => 'English name', 'script_code' => 'Latn',
'auto_generated' => false,
'aliases' => [{ 'name' => 'English alias', 'script_code' => 'Latn' }] })
end
it 'creates a version for an English-only change and preserves prior names' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_names!
original = described_class.record!(tag:, event_type: :create, created_by_user: user)
primary_tag_name_for(tag, 'en').update!(name: 'Renamed')
updated = described_class.record!(tag:, event_type: :update, created_by_user: user) updated = described_class.record!(tag:, event_type: :update, created_by_user: user)
expect(updated.version_no).to eq(2) expect(updated.version_no).to eq(2)
expect(original.reload.names).to include( expect(original.reload.names.fetch('en')).to include('name' => 'English name')
hash_including('language_code' => 'en', 'name' => 'English name')) expect(updated.names.fetch('en')).to include('name' => 'Renamed')
expect(updated.names).to include(hash_including('language_code' => 'en', 'name' => 'Renamed')) expect(updated.names.fetch('ja')).to eq(nipponese_snapshot)
end end
it 'does not create a version for an unchanged multilingual snapshot' do it 'does not create a version for an unchanged multilingual snapshot' do
pending '日本語以外の Locale 有効化は別課題で実装する'
prepare_english_names!
described_class.record!(tag:, event_type: :create, created_by_user: user) described_class.record!(tag:, event_type: :create, created_by_user: user)
unchanged = described_class.record!(tag:, event_type: :update, created_by_user: user) unchanged = described_class.record!(tag:, event_type: :update, created_by_user: user)
+12 -1
ファイルの表示
@@ -1,10 +1,21 @@
RSpec.shared_context 'English locale' do RSpec.shared_context 'English locale' do
let!(:locale) do def prepare_english_reference!
Language.find_or_create_by!(code: 'en') { _1.name = 'English' } Language.find_or_create_by!(code: 'en') { _1.name = 'English' }
Script.find_or_create_by!(code: 'Latn') { _1.name = 'Latin' } Script.find_or_create_by!(code: 'Latn') { _1.name = 'Latin' }
region_class = Class.new(ApplicationRecord) { self.table_name = 'regions' }
region_class.find_or_create_by!(code: 826) do |record|
record.alpha_code = 'GB'
record.name = 'United Kingdom'
end
end
let(:locale) do
prepare_english_reference!
Locale.find_or_create_by!(code: 'en') do |record| Locale.find_or_create_by!(code: 'en') do |record|
record.language_code = 'en' record.language_code = 'en'
record.script_code = 'Latn' record.script_code = 'Latn'
record.region_code = 826
record.variants = ''
record.name = 'English' record.name = 'English'
end end
end end