diff --git a/backend/spec/models/tag_name_sanitisation_rule_spec.rb b/backend/spec/models/tag_name_sanitisation_rule_spec.rb index 558869e..dcecd06 100644 --- a/backend/spec/models/tag_name_sanitisation_rule_spec.rb +++ b/backend/spec/models/tag_name_sanitisation_rule_spec.rb @@ -62,7 +62,7 @@ RSpec.describe TagNameSanitisationRule, type: :model do name: 'foobar', language_code: 'en', tag_id: english.id) expect(primary_tag_name_for(japanese.reload, 'ja')).to have_attributes( name: 'foobar', language_code: 'ja', tag_id: japanese.id) - expect(english.reload.tag_name_id).to eq(english_name.id) + expect(primary_tag_name_for(english.reload, 'en')).to eq(english_name) end end @@ -109,7 +109,7 @@ RSpec.describe TagNameSanitisationRule, type: :model do expect(existing.reload).to have_attributes( tag_id: source_tag.id, language_code: 'ja', primary_flg: true) expect(primary_tag_name_for(source_tag, 'ja')).to eq(existing) - expect(source_tag.reload.tag_name_id).to eq(existing.id) + expect(primary_tag_name_for(source_tag.reload, 'ja')).to eq(existing) expect(TagName.unscoped.exists?(source_tag_name_id)).to be(false) end end diff --git a/backend/spec/models/tag_name_spec.rb b/backend/spec/models/tag_name_spec.rb index 37107cc..aabcf0a 100644 --- a/backend/spec/models/tag_name_spec.rb +++ b/backend/spec/models/tag_name_spec.rb @@ -67,6 +67,22 @@ RSpec.describe TagName, type: :model do end describe '.canonicalise' do + it 'leaves detached aliases unchanged' do + create(:tag_name, :alias, name: 'detached_alias') + + expect(described_class.canonicalise(Locale.nipponese, ['detached_alias'])) + .to eq(['detached_alias']) + end + + it 'leaves an alias unchanged when its language has no primary' do + tag = create(:tag, primary_name: '日本語のみ') + create(:tag_name, :alias, tag:, name: 'orphan_english_alias', + language_code: 'en', script_code: 'Latn') + + expect(described_class.canonicalise(locale, ['orphan_english_alias'])) + .to eq(['orphan_english_alias']) + end + it 'resolves the primary name of the alias language on the same tag' do tag = create(:tag, primary_name: '日本語正本') english_primary = create(:tag_name, tag:, name: 'english_primary', diff --git a/backend/spec/models/tag_spec.rb b/backend/spec/models/tag_spec.rb index d900053..27c8565 100644 --- a/backend/spec/models/tag_spec.rb +++ b/backend/spec/models/tag_spec.rb @@ -331,6 +331,40 @@ RSpec.describe Tag, type: :model do Post.create!(url: 'https://example.com/posts/1', title: 'test post') end + context 'with names in multiple languages' do + include_context 'English locale' + + it 'keeps the target primary and moves source names as aliases' do + english_primary = create(:tag_name, tag: target_tag, + name: 'target_english', language_code: 'en', script_code: 'Latn') + source_primary = create(:tag_name, tag: source_tag, + name: 'source_english', language_code: 'en', script_code: 'Latn') + source_alias = create(:tag_name, :alias, tag: source_tag, + name: 'source_english_alias', language_code: 'en', script_code: 'Latn') + + described_class.merge_tags!(target_tag, [source_tag]) + + expect(primary_tag_name_for(target_tag.reload, 'en')).to eq(english_primary) + expect([source_primary.reload, source_alias.reload]).to all(have_attributes( + tag_id: target_tag.id, language_code: 'en', primary_flg: false)) + end + + it 'inherits a source primary when the target has no name in that language' do + source_primary = create(:tag_name, tag: source_tag, + name: 'inherited_english', language_code: 'en', script_code: 'Latn') + source_alias = create(:tag_name, :alias, tag: source_tag, + name: 'inherited_alias', language_code: 'en', script_code: 'Latn') + + described_class.merge_tags!(target_tag, [source_tag]) + + expect(primary_tag_name_for(target_tag.reload, 'en')).to eq(source_primary) + expect(source_primary.reload).to have_attributes( + tag_id: target_tag.id, language_code: 'en', primary_flg: true) + expect(source_alias.reload).to have_attributes( + tag_id: target_tag.id, language_code: 'en', primary_flg: false) + end + end + context 'when merging a simple source tag' do let!(:source_post_tag) { PostTag.create!(post: post_record, tag: source_tag) } @@ -388,13 +422,20 @@ RSpec.describe Tag, type: :model do expect(versions.pluck(:version_no, :event_type)) .to eq([[1, 'create'], [2, 'discard']]) expect(versions.first).to eq(original_version) - expect(versions.last).to have_attributes( - name: source_name, aliases: source_alias.name, created_by_user: user) + expect(versions.last.created_by_user).to eq(user) + expect(versions.last.names).to include( + hash_including('language_code' => 'ja', 'name' => source_name, + 'primary_flg' => true, 'auto_generated' => false), + hash_including('language_code' => 'ja', 'name' => source_alias.name, + 'primary_flg' => false, 'auto_generated' => false)) expect(Tag.unscoped.exists?(source_tag.id)).to be(false) target_versions = target_tag.tag_versions.order(:version_no) expect(target_versions.pluck(:event_type)).to eq(['create', 'update']) - expect(target_versions.last.aliases.split).to contain_exactly('merge_alias', source_name) + target_aliases = target_versions.last.names.filter_map { |name| + name['name'] if name['language_code'] == 'ja' && !name['primary_flg'] + } + expect(target_aliases).to contain_exactly('merge_alias', source_name) end it 'deletes source relationships while preserving unrelated relationships' do diff --git a/backend/spec/requests/locale_write_paths_spec.rb b/backend/spec/requests/locale_write_paths_spec.rb index 6c0ef8f..fa3b032 100644 --- a/backend/spec/requests/locale_write_paths_spec.rb +++ b/backend/spec/requests/locale_write_paths_spec.rb @@ -14,7 +14,6 @@ RSpec.describe 'Locale propagation on write paths', type: :request do expect(tag_name).to have_attributes( script_code: expected_locale.script_code, primary_flg: true) expect(tag_name.tag_id).to be_present - expect(tag_name.tag.tag_name_id).to eq(tag_name.id) tag_name.tag end @@ -206,7 +205,6 @@ RSpec.describe 'Locale propagation on write paths', type: :request do .to have_attributes( script_code: 'Latn', tag_id: tag.id, primary_flg: false, language_code: 'en') - expect(tag.reload.tag_name_id).to eq(english_name.id) primary = TagName.find_by!(tag_id: tag.id, language_code: 'en', primary_flg: true) expect(primary).to have_attributes(name: 'english_original', script_code: 'Latn') end diff --git a/backend/spec/requests/tag_versions_spec.rb b/backend/spec/requests/tag_versions_spec.rb index 3a6383a..eebeca1 100644 --- a/backend/spec/requests/tag_versions_spec.rb +++ b/backend/spec/requests/tag_versions_spec.rb @@ -36,10 +36,11 @@ RSpec.describe 'TagVersions API', type: :request do category: category, deprecated_at: deprecated_at, aliases: Array(aliases).join(' '), - names: [{ language_code: 'ja', name: name, script_code: 'Jpan', - primary_flg: true }] + Array(aliases).map { |alias_name| + names: [{ language_code: 'ja', name:, script_code: 'Jpan', + primary_flg: true, + auto_generated: false }] + Array(aliases).map { |alias_name| { language_code: 'ja', name: alias_name, script_code: 'Jpan', - primary_flg: false } + primary_flg: false, auto_generated: false } }, parent_tag_ids: Array(parent_tags).map(&:id).join(' '), created_by_user: created_by_user, diff --git a/backend/spec/requests/tags_spec.rb b/backend/spec/requests/tags_spec.rb index 07478a0..be64b53 100644 --- a/backend/spec/requests/tags_spec.rb +++ b/backend/spec/requests/tags_spec.rb @@ -18,6 +18,18 @@ RSpec.describe 'Tags API', type: :request do response_tags.map { |t| t.fetch('name') } end + def version_primary_name(version, language_code) + version.names.find { |name| + name['language_code'] == language_code && name['primary_flg'] + }.fetch('name') + end + + def version_alias_names(version, language_code) + version.names.filter_map { |name| + name['name'] if name['language_code'] == language_code && !name['primary_flg'] + } + end + def dummy_material_upload(filename: 'dummy.png', type: 'image/png', body: 'dummy') Rack::Test::UploadedFile.new(StringIO.new(body), type, original_filename: filename) end @@ -687,11 +699,11 @@ RSpec.describe 'Tags API', type: :request do expect(versions.map(&:event_type)).to eq(['create', 'update']) - expect(versions.first.name).to eq('spec_tag') + expect(version_primary_name(versions.first, 'ja')).to eq('spec_tag') expect(versions.first.category).to eq('general') - expect(versions.first.aliases.split).to include('unko') + expect(version_alias_names(versions.first, 'ja')).to include('unko') - expect(versions.second.name).to eq('new_tag_name') + expect(version_primary_name(versions.second, 'ja')).to eq('new_tag_name') expect(versions.second.category).to eq('meme') expect(versions.second.created_by_user_id).to eq(member_user.id) end @@ -1261,13 +1273,13 @@ RSpec.describe 'Tags API', type: :request do expect(versions.map(&:event_type)).to eq(['create', 'update']) - expect(versions.first.name).to eq('spec_tag') + expect(version_primary_name(versions.first, 'ja')).to eq('spec_tag') expect(versions.first.category).to eq('general') - expect(versions.first.aliases.split).to include('unko') + expect(version_alias_names(versions.first, 'ja')).to include('unko') - expect(versions.second.name).to eq('put_versioned_tag') + expect(version_primary_name(versions.second, 'ja')).to eq('put_versioned_tag') expect(versions.second.category).to eq('meta') - expect(versions.second.aliases.split).to include('spec_tag') + expect(version_alias_names(versions.second, 'ja')).to include('spec_tag') expect(versions.second.created_by_user_id).to eq(member_user.id) end @@ -1307,8 +1319,8 @@ RSpec.describe 'Tags API', type: :request do version = tag.tag_versions.order(:version_no).last expect(version.event_type).to eq('update') - expect(version.name).to eq('spec_tag') - expect(version.aliases.split).to contain_exactly('put_roundtrip_b', 'unko') + expect(version_primary_name(version, 'ja')).to eq('spec_tag') + expect(version_alias_names(version, 'ja')).to contain_exactly('put_roundtrip_b', 'unko') end it 'parent tag の snapshot も作成する' do @@ -1490,10 +1502,11 @@ RSpec.describe 'Tags API', type: :request do old_owner_versions = old_owner.tag_versions.order(:version_no) expect(old_owner_versions.first.event_type).to eq('create') - expect(old_owner_versions.first.aliases.split).to include('put_stolen_alias') + expect(version_alias_names(old_owner_versions.first, 'ja')).to include('put_stolen_alias') expect(old_owner_versions.second.event_type).to eq('update') - expect(old_owner_versions.second.aliases.split).not_to include('put_stolen_alias') + expect(version_alias_names(old_owner_versions.second, 'ja')) + .not_to include('put_stolen_alias') end it '別 tag の alias 名を rename で奪へる' do @@ -1536,7 +1549,8 @@ RSpec.describe 'Tags API', type: :request do old_owner_versions = old_owner.tag_versions.order(:version_no) expect(old_owner_versions.last.event_type).to eq('update') - expect(old_owner_versions.last.aliases.split).not_to include('put_alias_collision_name') + expect(version_alias_names(old_owner_versions.last, 'ja')) + .not_to include('put_alias_collision_name') expect(wiki_page.reload.tag_name).to eq(primary_tag_name_for(tag, 'ja')) end diff --git a/backend/spec/services/tag_version_recorder_spec.rb b/backend/spec/services/tag_version_recorder_spec.rb index f97562c..c556d87 100644 --- a/backend/spec/services/tag_version_recorder_spec.rb +++ b/backend/spec/services/tag_version_recorder_spec.rb @@ -9,13 +9,10 @@ RSpec.describe TagVersionRecorder do Script.insert_all!([{ code: 'Latn', name: 'Latin', created_at: Time.current }]) Locale.insert_all!([{ code: 'en', language_code: 'en', script_code: 'Latn', name: 'English', created_at: Time.current }]) - TagName.create!(tag:, language_code: 'ja', script_code: 'Jpan', name: '別名', - primary_flg: false, - canonical_id: tag.tag_name_id) - TagName.create!(tag:, language_code: 'en', script_code: 'Latn', name: 'English name', - primary_flg: true) - TagName.create!(tag:, language_code: 'en', script_code: 'Latn', name: 'English alias', - primary_flg: false) + create(:tag_name, :alias, tag:, name: '別名') + create(:tag_name, tag:, language_code: 'en', script_code: 'Latn', name: 'English name') + create(:tag_name, :alias, tag:, language_code: 'en', script_code: 'Latn', + name: 'English alias') end it 'snapshots every language primary name and alias deterministically' do