このコミットが含まれているのは:
@@ -1,7 +1,7 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe PostBulkCreator do
|
||||
include_context 'English locale'
|
||||
include_context 'Ainu locale'
|
||||
|
||||
it 'limits workers to two and keeps failures in their request slots' do
|
||||
locale = Locale.nipponese
|
||||
@@ -67,8 +67,7 @@ RSpec.describe PostBulkCreator do
|
||||
expect(results[3].dig(:post, :id)).to eq(4)
|
||||
end
|
||||
|
||||
it 'passes a future English locale to preflight and creation in every worker' do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
it 'passes a future Ainu locale to preflight and creation in every worker' do
|
||||
locale
|
||||
actor = instance_double(User, id: 123)
|
||||
allow(User).to receive(:find).with(123).and_return(actor)
|
||||
|
||||
@@ -11,23 +11,22 @@ RSpec.describe PostCreatePlan do
|
||||
end
|
||||
|
||||
context 'with an explicit locale' do
|
||||
include_context 'English locale'
|
||||
include_context 'Ainu locale'
|
||||
|
||||
it 'resolves the matching language identity and its parents' do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
locale
|
||||
english_name = create(:tag_name, name: 'shared_name',
|
||||
language_code: 'en', script_code: 'Latn')
|
||||
english = create(:tag, primary_tag_name: english_name, category: :character)
|
||||
ainu_name = create(:tag_name, name: 'shared_name',
|
||||
language_code: 'ain', script_code: 'Kana')
|
||||
ainu = create(:tag, primary_tag_name: ainu_name, category: :character)
|
||||
nipponese = create(:tag, primary_name: 'temporary_nipponese', category: :general)
|
||||
# The DB permits this identity; validation has its own contract spec.
|
||||
primary_tag_name_for(nipponese, 'ja').update_columns(name: 'shared_name')
|
||||
english_parent_name = create(:tag_name, name: 'english_parent',
|
||||
language_code: 'en', script_code: 'Latn')
|
||||
english_parent = create(:tag, primary_tag_name: english_parent_name,
|
||||
ainu_parent_name = create(:tag_name, name: 'ainu_parent',
|
||||
language_code: 'ain', script_code: 'Kana')
|
||||
ainu_parent = create(:tag, primary_tag_name: ainu_parent_name,
|
||||
category: :material)
|
||||
nipponese_parent = create(:tag, primary_name: 'nipponese_parent', category: :general)
|
||||
TagImplication.create!(tag: english, parent_tag: english_parent)
|
||||
TagImplication.create!(tag: ainu, parent_tag: ainu_parent)
|
||||
TagImplication.create!(tag: nipponese, parent_tag: nipponese_parent)
|
||||
|
||||
plan = described_class.new(attributes: { tags: 'shared_name' }).build!(locale)
|
||||
@@ -35,35 +34,34 @@ RSpec.describe PostCreatePlan do
|
||||
expect(plan[:direct_tag_specs]).to eq(
|
||||
[{ name: 'shared_name', category: :character }])
|
||||
expect(plan[:post_tag_specs]).to include(
|
||||
{ name: primary_tag_name_for(english_parent, 'en').name, category: :material })
|
||||
{ name: primary_tag_name_for(ainu_parent, 'ain').name, category: :material })
|
||||
expect(plan[:post_tag_specs].pluck(:name))
|
||||
.not_to include(primary_tag_name_for(nipponese_parent, 'ja').name)
|
||||
end
|
||||
|
||||
it 'resolves aliases within the requested language' do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
locale
|
||||
nipponese = create(:tag, primary_name: 'nipponese_canonical')
|
||||
english_name = create(:tag_name, name: 'english_canonical',
|
||||
language_code: 'en', script_code: 'Latn')
|
||||
english = create(:tag, primary_tag_name: english_name, category: :character)
|
||||
ainu_name = create(:tag_name, name: 'ainu_canonical',
|
||||
language_code: 'ain', script_code: 'Kana')
|
||||
ainu = create(:tag, primary_tag_name: ainu_name, category: :character)
|
||||
nipponese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||
tag: nipponese)
|
||||
english_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||
tag: english,
|
||||
language_code: 'en', script_code: 'Latn')
|
||||
ainu_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||
tag: ainu,
|
||||
language_code: 'ain', script_code: 'Kana')
|
||||
|
||||
expect(nipponese_alias.reload).to have_attributes(
|
||||
tag_id: nipponese.id,
|
||||
primary_flg: false, language_code: 'ja')
|
||||
expect(english_alias.reload).to have_attributes(
|
||||
tag_id: english.id,
|
||||
primary_flg: false, language_code: 'en')
|
||||
expect(ainu_alias.reload).to have_attributes(
|
||||
tag_id: ainu.id,
|
||||
primary_flg: false, language_code: 'ain')
|
||||
|
||||
plan = described_class.new(attributes: { tags: 'shared_alias' }).build!(locale)
|
||||
|
||||
expect(plan[:direct_tag_specs]).to eq(
|
||||
[{ name: english_name.name, category: :character }])
|
||||
[{ name: ainu_name.name, category: :character }])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -77,11 +77,10 @@ RSpec.describe PostCreator do
|
||||
end
|
||||
|
||||
context 'with an explicit locale' do
|
||||
include_context 'English locale'
|
||||
include_context 'Ainu locale'
|
||||
|
||||
[false, true].each do |planned|
|
||||
it "passes locale to tag creation with planned attributes: #{ planned }" do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
locale
|
||||
attributes = {
|
||||
title: 'Locale propagation',
|
||||
@@ -97,8 +96,8 @@ RSpec.describe PostCreator do
|
||||
|
||||
expect(Tag).to have_received(:find_or_create_by_tag_name!)
|
||||
.with(locale, 'locale_character', category: :character).at_least(:once)
|
||||
tag_name = TagName.find_by!(language_code: 'en', name: 'locale_character')
|
||||
expect(tag_name).to have_attributes(script_code: 'Latn', primary_flg: true)
|
||||
tag_name = TagName.find_by!(language_code: 'ain', name: 'locale_character')
|
||||
expect(tag_name).to have_attributes(script_code: 'Kana', primary_flg: true)
|
||||
expect(post.tags).to include(tag_name.tag)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TagNameCompletion do
|
||||
let!(:language) { Language.create!(code: 'ain', name: 'ain') }
|
||||
let!(:script) { Script.create!(code: 'Kana', name: 'Kana') }
|
||||
let(:locale) do
|
||||
Locale.create!(code: 'ain-Kana', language_code: 'ain', script_code: 'Kana',
|
||||
region_code: 392, variants: '', name: 'ain-Kana')
|
||||
end
|
||||
|
||||
it 'generates a phonetic primary with the required identity and provenance' do
|
||||
tag = create(:tag, primary_name: '漢字あカ')
|
||||
|
||||
locale
|
||||
|
||||
expect(tag.reload.tag_name('ain')).to have_attributes(
|
||||
name: 'カンチ_ア_カ', language_code: 'ain', script_code: 'Kana',
|
||||
primary_flg: true, auto_generated: true, tag_id: tag.id)
|
||||
end
|
||||
|
||||
it 'uses the exact fallback when the input cannot be converted' do
|
||||
tag = create(:tag, primary_name: '😀')
|
||||
|
||||
locale
|
||||
|
||||
expect(tag.reload.name('ain')).to eq("Tag_##{ tag.id }")
|
||||
end
|
||||
|
||||
it 'uses the exact fallback when a generated name collides with a human name' do
|
||||
other = create(:tag, primary_name: 'other')
|
||||
create(:tag_name, tag: other, name: 'AbC', language_code: 'ain', script_code: 'Kana')
|
||||
tag = create(:tag, primary_name: 'AbC')
|
||||
|
||||
locale
|
||||
|
||||
expect(tag.reload.name('ain')).to eq("Tag_##{ tag.id }")
|
||||
expect(other.reload.name('ain')).to eq('AbC')
|
||||
end
|
||||
|
||||
it 'uses the exact fallback for a transcription that fails name validation' do
|
||||
tag = create(:tag, primary_name: 'base')
|
||||
source = TagName.new(name: 'nico:invalid', language_code: 'ja')
|
||||
|
||||
expect(TagName.generate_name(locale, tag, source)).to eq("Tag_##{ tag.id }")
|
||||
end
|
||||
|
||||
it 'preserves human confirmation and is idempotent across repeated completion' do
|
||||
locale
|
||||
tag = Tag.find_or_create_by_tag_name!(Locale.nipponese, 'あいぬ', category: :general)
|
||||
primary = tag.tag_name('ain')
|
||||
primary.update!(name: 'human_confirmed', auto_generated: false)
|
||||
snapshot = tag.tag_names.order(:id).map(&:attributes)
|
||||
|
||||
2.times { described_class.for_tag!(tag) }
|
||||
|
||||
expect(tag.tag_names.order(:id).map(&:attributes)).to eq(snapshot)
|
||||
end
|
||||
|
||||
it 'creates one primary per active language through the production creation path' do
|
||||
locale
|
||||
|
||||
tag = Tag.find_or_create_by_tag_name!(Locale.nipponese, 'アイヌ', category: :general)
|
||||
|
||||
expect(tag.tag_names.where(primary_flg: true).pluck(:language_code, :name))
|
||||
.to contain_exactly(['ja', 'アイヌ'], ['ain', 'アイヌ'])
|
||||
expect(Tag.find_or_create_by_tag_name!(locale, 'アイヌ', category: :general)).to eq(tag)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TagNameTranscription do
|
||||
{
|
||||
'AbCdXYZ' => 'AbCdXYZ',
|
||||
'あいぬ' => 'アイヌ',
|
||||
'アイヌ' => 'アイヌ',
|
||||
'日本語' => 'ニチホンコ',
|
||||
'漢字' => 'カンチ',
|
||||
'漢あカ' => 'カン_ア_カ',
|
||||
'漢字あいうカナ' => 'カンチ_アイウ_カナ',
|
||||
'Ab漢あカZ' => 'Abカン_ア_カZ',
|
||||
'りゃリュリョ' => 'リヤ_リユリヨ',
|
||||
'キャット' => 'キヤット',
|
||||
'コーヒー' => 'コヒ',
|
||||
'コウコオケイケエカア' => 'コウコオケイケエカア',
|
||||
'ガギグゲゴダヂヅデド' => 'カキクケコタチチュテト',
|
||||
'バビブベボパピプペポ' => 'パピプペポパピプペポ',
|
||||
'ザジズゼゾ' => 'チャチチュチェチョ',
|
||||
'ジャジュジョ' => 'チヤチユチヨ',
|
||||
'アㇰアㇱアッアンアㇺアㇷ゚' => 'アㇰアㇱアッアンアㇺアㇷ゚',
|
||||
'アㇻイㇼウㇽエㇾオㇿ' => 'アㇻイㇼウㇽエㇾオㇿ',
|
||||
'漢Aあ' => 'カンAア' }.each do |source, expected|
|
||||
it "transcribes #{ source } as #{ expected }" do
|
||||
expect(described_class.ainu(source)).to eq(expected)
|
||||
end
|
||||
end
|
||||
|
||||
['😀', 'ヴ', 'ティ', 'ㇵ', '魑', '𠮷', 'ー', '々'].each do |source|
|
||||
it "rejects unsupported input #{ source }" do
|
||||
expect { described_class.ainu(source) }.to raise_error(described_class::Unconvertible)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TagVersionRecorder do
|
||||
include_context 'English locale'
|
||||
include_context 'Ainu locale'
|
||||
|
||||
let(:user) { create_member_user! }
|
||||
let!(:tag) { create(:tag, primary_name: '日本語名') }
|
||||
@@ -17,11 +17,11 @@ RSpec.describe TagVersionRecorder do
|
||||
{ 'name' => 'alias_z', 'script_code' => 'Jpan' }] }
|
||||
end
|
||||
|
||||
def prepare_english_names!
|
||||
def prepare_ainu_names!
|
||||
locale
|
||||
primary_tag_name_for(tag, 'en').update!(name: 'English name', auto_generated: false)
|
||||
create(:tag_name, :alias, tag:, language_code: 'en', script_code: 'Latn',
|
||||
name: 'English alias')
|
||||
primary_tag_name_for(tag, 'ain').update!(name: 'Ainu name', auto_generated: false)
|
||||
create(:tag_name, :alias, tag:, language_code: 'ain', script_code: 'Kana',
|
||||
name: 'Ainu alias')
|
||||
end
|
||||
|
||||
it 'snapshots the Nipponese primary and sorted aliases in grouped names' do
|
||||
@@ -62,35 +62,32 @@ RSpec.describe TagVersionRecorder do
|
||||
end
|
||||
|
||||
it 'snapshots future languages together without a request locale argument' do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
prepare_english_names!
|
||||
prepare_ainu_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',
|
||||
'ain' => { 'name' => 'Ainu name', 'script_code' => 'Kana',
|
||||
'auto_generated' => false,
|
||||
'aliases' => [{ 'name' => 'English alias', 'script_code' => 'Latn' }] })
|
||||
'aliases' => [{ 'name' => 'Ainu alias', 'script_code' => 'Kana' }] })
|
||||
end
|
||||
|
||||
it 'creates a version for an English-only change and preserves prior names' do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
prepare_english_names!
|
||||
it 'creates a version for an Ainu-only change and preserves prior names' do
|
||||
prepare_ainu_names!
|
||||
original = described_class.record!(tag:, event_type: :create, created_by_user: user)
|
||||
primary_tag_name_for(tag, 'en').update!(name: 'Renamed')
|
||||
primary_tag_name_for(tag, 'ain').update!(name: 'Renamed')
|
||||
|
||||
updated = described_class.record!(tag:, event_type: :update, created_by_user: user)
|
||||
|
||||
expect(updated.version_no).to eq(2)
|
||||
expect(original.reload.names.fetch('en')).to include('name' => 'English name')
|
||||
expect(updated.names.fetch('en')).to include('name' => 'Renamed')
|
||||
expect(original.reload.names.fetch('ain')).to include('name' => 'Ainu name')
|
||||
expect(updated.names.fetch('ain')).to include('name' => 'Renamed')
|
||||
expect(updated.names.fetch('ja')).to eq(nipponese_snapshot)
|
||||
end
|
||||
|
||||
it 'does not create a version for an unchanged multilingual snapshot' do
|
||||
pending '日本語以外の Locale 有効化は別課題で実装する'
|
||||
prepare_english_names!
|
||||
prepare_ainu_names!
|
||||
described_class.record!(tag:, event_type: :create, created_by_user: user)
|
||||
|
||||
unchanged = described_class.record!(tag:, event_type: :update, created_by_user: user)
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする