このコミットが含まれているのは:
@@ -4,7 +4,8 @@ RSpec.describe TagGroup, type: :model do
|
||||
let(:actor) { create_member_user! }
|
||||
|
||||
def create_group name:, members: [], placements: []
|
||||
TagGroupOperation.create!(name:, description: nil, members:, placements:, actor:)
|
||||
TagGroupOperation.create!(
|
||||
Locale.nipponese, name:, description: nil, members:, placements:, actor:)
|
||||
end
|
||||
|
||||
it 'retains version IDs and snapshots after destroying an empty group' do
|
||||
@@ -16,7 +17,8 @@ RSpec.describe TagGroup, type: :model do
|
||||
|
||||
expect(TagGroupVersion.where(tag_group_id: group.id).order(:version_no).map(&:attributes))
|
||||
.to eq(versions)
|
||||
expect(TagGroupRepr.historical(TagGroupVersion.find(versions.first.fetch('id'))))
|
||||
expect(TagGroupRepr.historical(
|
||||
Locale.nipponese, TagGroupVersion.find(versions.first.fetch('id'))))
|
||||
.to include('id' => group.id, 'name' => 'history owner', 'members' => [])
|
||||
end
|
||||
|
||||
@@ -26,14 +28,8 @@ RSpec.describe TagGroup, type: :model do
|
||||
parent = create_group(
|
||||
name: 'parent group',
|
||||
members: [{ 'tag_group_id' => child.id }],
|
||||
placements: [{
|
||||
'section_name' => 'section',
|
||||
'description' => nil,
|
||||
'children' => [{
|
||||
'tag_group_id' => child.id,
|
||||
'children' => []
|
||||
}]
|
||||
}])
|
||||
placements: [{ 'section_name' => 'section', 'description' => nil,
|
||||
'children' => [{ 'tag_group_id' => child.id, 'children' => [] }] }])
|
||||
|
||||
versions = parent.versions.order(:version_no).map(&:attributes)
|
||||
|
||||
|
||||
@@ -34,6 +34,66 @@ RSpec.describe TagNameSanitisationRule, type: :model do
|
||||
described_class.create!(priority: 10, source_pattern: 'foo_', replacement: 'foo')
|
||||
end
|
||||
|
||||
[:primary, :alias].each do |source_kind|
|
||||
it "keeps the primary identity when a #{ source_kind } collides within its Tag" do
|
||||
tag = create(:tag, primary_name: source_kind == :primary ? 'temporary' : 'foobar')
|
||||
primary = tag.tag_name('ja')
|
||||
alias_name = create(:tag_name, :alias, tag:,
|
||||
name: source_kind == :primary ? 'foobar' : 'temporary_alias')
|
||||
source = source_kind == :primary ? primary : alias_name
|
||||
source.update_columns(name: 'foo_bar')
|
||||
|
||||
expect { described_class.apply! }.to change(TagName, :count).by(-1)
|
||||
.and change(Tag, :count).by(0)
|
||||
|
||||
expect(primary.reload).to have_attributes(
|
||||
name: 'foobar', primary_flg: true, tag_id: tag.id)
|
||||
expect(TagName.exists?(alias_name.id)).to be(false)
|
||||
expect(TagName.where(tag:, language_code: 'ja', primary_flg: true))
|
||||
.to contain_exactly(primary)
|
||||
expect(tag.tag_versions.order(:version_no).last.names.fetch('ja'))
|
||||
.to include('name' => 'foobar', 'aliases' => [])
|
||||
end
|
||||
end
|
||||
|
||||
it 'deduplicates colliding aliases without changing the primary name' do
|
||||
tag = create(:tag, primary_name: 'primary')
|
||||
primary = tag.tag_name('ja')
|
||||
kept = create(:tag_name, :alias, tag:, name: 'foobar')
|
||||
removed = create(:tag_name, :alias, tag:, name: 'temporary_alias')
|
||||
removed.update_columns(name: 'foo_bar')
|
||||
|
||||
described_class.apply!
|
||||
|
||||
expect(primary.reload).to have_attributes(name: 'primary', primary_flg: true)
|
||||
expect(kept.reload.tag_id).to eq(tag.id)
|
||||
expect(TagName.exists?(removed.id)).to be(false)
|
||||
expect(tag.tag_versions.order(:version_no).last.names.fetch('ja').fetch('aliases'))
|
||||
.to eq([{ 'name' => 'foobar', 'script_code' => 'Jpan' }])
|
||||
end
|
||||
|
||||
it 'rolls back a collision merge when the source owns a description' do
|
||||
user = create_member_user!
|
||||
target = create(:tag, primary_name: 'foobar')
|
||||
source = create(:tag, primary_name: 'temporary')
|
||||
TagDescriptionOperation.create!(
|
||||
Locale.nipponese, tag: source, body: 'retained', created_by_user: user)
|
||||
source.tag_name('ja').update_columns(name: 'foo_bar')
|
||||
post = create(:post)
|
||||
PostTag.create!(post:, tag: source)
|
||||
models = [Tag, TagName, TagVersion, TagDescription, TagDescriptionVersion, PostTag]
|
||||
snapshots = models.map { |model| model.order(*Array(model.primary_key)).map(&:attributes) }
|
||||
|
||||
expect { described_class.apply! }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
|
||||
after_state = models.map do |model|
|
||||
model.order(*Array(model.primary_key)).map(&:attributes)
|
||||
end
|
||||
expect(after_state).to eq(snapshots)
|
||||
expect(post.reload.tags).to contain_exactly(source)
|
||||
expect(target.reload.name('ja')).to eq('foobar')
|
||||
end
|
||||
|
||||
context 'when only another language has the sanitised name' do
|
||||
include_context 'English locale'
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe User, type: :model do
|
||||
it 'nullifies description authorship without deleting native content or history' do
|
||||
author = create_member_user!
|
||||
editor = create_member_user!
|
||||
tag = create(:tag)
|
||||
description = TagDescriptionOperation.create!(
|
||||
Locale.nipponese, tag:, body: 'initial', created_by_user: author)
|
||||
TagDescriptionOperation.update!(
|
||||
Locale.nipponese, tag:, body: 'edited', updated_by_user: editor)
|
||||
versions = TagDescriptionVersion.where(tag_id: tag.id).order(:version_no)
|
||||
snapshots = versions.map(&:attributes)
|
||||
|
||||
expect(author.created_tag_descriptions).to contain_exactly(description)
|
||||
expect(editor.updated_tag_descriptions).to contain_exactly(description)
|
||||
expect { author.destroy! }.to change(TagDescription, :count).by(0)
|
||||
.and change(TagDescriptionVersion, :count).by(0)
|
||||
expect(description.reload).to have_attributes(
|
||||
body: 'edited', created_by_user_id: nil, updated_by_user_id: editor.id)
|
||||
expect { editor.destroy! }.not_to change(TagDescription, :count)
|
||||
expect(description.reload.updated_by_user_id).to be_nil
|
||||
expect(versions.reload.map(&:attributes)).to eq(snapshots)
|
||||
end
|
||||
end
|
||||
新しいイシューから参照
ユーザーをブロックする