このコミットが含まれているのは:
2026-10-04 17:57:46 +09:00
コミット d5b5fc1646
2個のファイルの変更、124行の追加、68行の削除
+87 -42
ファイルの表示
@@ -70,27 +70,12 @@ RSpec.describe 'Tag description Wiki dual writes', type: :request do
tag_name:, body: 'before', created_by_user: user)
end
let!(:first_revision) { page.current_revision }
let!(:current_revision) do
# Repeated bodies create revisions, but no extra WikiVersion snapshot.
Wiki::Commit.content!(page:, body: 'before', created_user: user,
base_revision_id: first_revision.id)
end
let!(:description) do
TagDescription.create!(
id: page.id, tag:, language_code: 'ja', body: 'before', version_no: 2,
created_by_user_id: user.id, updated_by_user_id: user.id)
TagDescription.find_by!(tag_id: tag.id, language_code: 'ja')
end
before do
[first_revision, current_revision].each_with_index do |revision, index|
TagDescriptionVersion.create!(
id: revision.id, tag_id: tag.id, language_code: 'ja', version_no: index + 1,
body: 'before', event_type: index.zero? ? 'create' : 'update',
created_by_user_id: user.id, created_at: revision.created_at)
end
end
def update_description body: 'after', title: tag_name.name, base: current_revision.id
def update_description body: 'after', title: tag_name.name, base: first_revision.id
put "/wiki/#{ page.id }",
params: { title:, body:, message: 'edit', base_revision_id: base },
headers: headers
@@ -98,7 +83,7 @@ RSpec.describe 'Tag description Wiki dual writes', type: :request do
it 'increments the independent description sequence and shares revision identity' do
expect(page.reload.version_no).to eq(1)
expect(description.version_no).to eq(2)
expect(description.version_no).to eq(1)
expect { update_description }
.to change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)
@@ -107,56 +92,116 @@ RSpec.describe 'Tag description Wiki dual writes', type: :request do
revision = page.reload.current_revision
version = TagDescriptionVersion.find(revision.id)
expect(description.reload).to have_attributes(body: 'after', version_no: 3)
expect(description.reload).to have_attributes(body: 'after', version_no: 2)
expect(version).to have_attributes(
body: 'after', version_no: 3, event_type: 'update', created_by_user_id: user.id)
body: 'after', version_no: 2, event_type: 'update', created_by_user_id: user.id)
expect(page).to have_attributes(body: 'after', version_no: 2)
expect(revision.body).to eq(version.body)
expect(page.wiki_versions.order(:version_no).last.body).to eq(version.body)
end
it 'mirrors the Wiki revision for a title-only update despite identical bodies' do
expect { update_description(body: 'before', title: 'description_renamed') }
.to change(WikiRevision, :count).by(1)
.and change(TagDescriptionVersion, :count).by(1)
it 'does not add body history for a title-only update' do
revision_count = WikiRevision.count
wiki_version_count = WikiVersion.count
description_version_count = TagDescriptionVersion.count
wiki_version_no = page.reload.version_no
description_version_no = description.version_no
current_revision_id = page.current_revision.id
page_state = page.attributes
description_state = description.attributes
update_description(body: 'before', title: 'description_renamed')
expect(response).to have_http_status(:ok)
expect(tag_name.reload.name).to eq('description_renamed')
expect(description.reload).to have_attributes(body: 'before', version_no: 3)
revision = page.reload.current_revision
version = TagDescriptionVersion.find(revision.id)
expect(revision.body).to eq('before')
expect(version).to have_attributes(
tag_id: tag.id, language_code: 'ja', body: 'before', version_no: 3,
event_type: 'update', created_by_user_id: user.id)
expect(TagDescriptionVersion.where(tag_id: tag.id, language_code: 'ja').order(:id).ids)
.to eq(page.wiki_revisions.order(:id).ids)
expect(WikiRevision.count).to eq(revision_count)
expect(WikiVersion.count).to eq(wiki_version_count)
expect(TagDescriptionVersion.count).to eq(description_version_count)
expect(page.reload).to have_attributes(body: 'before', version_no: wiki_version_no)
expect(page.current_revision.id).to eq(current_revision_id)
expect(page.reload.attributes).to eq(page_state)
expect(description.reload).to have_attributes(
body: 'before', version_no: description_version_no)
expect(description.reload.attributes).to eq(description_state)
end
it 'does not add a description version for a TagName rename through tags' do
expect do
patch "/tags/#{ tag.id }", params: { name: 'description_tag_renamed' }, headers: headers
end.not_to change(TagDescriptionVersion, :count)
it 'does not add body history for a TagName rename through tags' do
revision_count = WikiRevision.count
wiki_version_count = WikiVersion.count
description_version_count = TagDescriptionVersion.count
page_version_no = page.reload.version_no
current_revision_id = page.current_revision.id
patch "/tags/#{ tag.id }",
params: { name: 'description_tag_renamed' },
headers:
expect(response).to have_http_status(:ok)
expect(tag_name.reload.name).to eq('description_tag_renamed')
expect(description.reload).to have_attributes(body: 'before', version_no: 2)
expect(WikiRevision.count).to eq(revision_count)
expect(WikiVersion.count).to eq(wiki_version_count)
expect(TagDescriptionVersion.count).to eq(description_version_count)
expect(page.reload.version_no).to eq(page_version_no)
expect(page.current_revision.id).to eq(current_revision_id)
expect(description.reload).to have_attributes(
body: 'before', version_no: 1)
end
it 'keeps both systems and the title unchanged on a stale revision conflict' do
update_description(body: 'current body', base: first_revision.id)
expect(response).to have_http_status(:ok)
stale_revision_id = first_revision.id
before_state = stored_state
update_description(title: 'conflicting_rename', base: first_revision.id)
update_description(
body: 'conflicting body',
title: 'conflicting_rename',
base: stale_revision_id)
expect(response).to have_http_status(:conflict)
expect(stored_state).to eq(before_state)
expect(tag_name.reload.name).not_to eq('conflicting_rename')
end
[WikiPage, WikiRevision, WikiVersion, TagDescription, TagDescriptionVersion].each do |model|
it "rolls back both systems when #{ model.name } persistence fails" do
before_state = stored_state
aggregate_failures do
fail_save(model) { update_description(title: 'rollback_rename') }
fail_save(model) do
update_description(body: 'rollback body', title: 'rollback_rename')
end
expect(stored_state).to eq(before_state)
end
end
end
[['identical body', 'before'],
['normalised-equivalent body', "before\n\n"]].each do |label, body|
it "does not write histories for #{ label }" do
before_state = stored_state
page_state = page.reload.attributes
description_state = description.reload.attributes
current_revision_id = page.current_revision.id
wiki_lines = WikiLine.order(:id).map(&:attributes)
revision_lines = WikiRevisionLine.order(:id).map(&:attributes)
page_version_no = page.version_no
description_version_no = description.version_no
update_description(body:)
expect(response).to have_http_status(:ok)
expect(WikiRevision.count).to eq(before_state[1].length)
expect(WikiVersion.count).to eq(before_state[2].length)
expect(TagDescriptionVersion.count).to eq(before_state[4].length)
expect(page.reload.version_no).to eq(page_version_no)
expect(description.reload.version_no).to eq(description_version_no)
expect(page.current_revision.id).to eq(current_revision_id)
expect(page.reload.attributes).to eq(page_state)
expect(description.reload.attributes).to eq(description_state)
expect(WikiLine.order(:id).map(&:attributes)).to eq(wiki_lines)
expect(WikiRevisionLine.order(:id).map(&:attributes)).to eq(revision_lines)
end
end
end
end
+37 -26
ファイルの表示
@@ -264,38 +264,49 @@ RSpec.describe 'Tag description native API', type: :request do
tag
Wiki::Commit.create_content!(tag_name:, body: 'before', created_by_user: author)
end
let!(:second_revision) do
Wiki::Commit.content!(page:, body: 'before', created_user: author)
end
let!(:description) do
TagDescription.find_by!(tag_id: tag.id, language_code: 'ja')
end
['after', 'before'].each do |body|
it "appends matching revisions for body '#{ body }'" do
history = TagDescriptionVersion.where(tag_id: tag.id).order(:version_no).map(&:attributes)
expect(page.reload.version_no).to eq(1)
expect(description.version_no).to eq(2)
expect { native_write(:put, body:) }
.to change(WikiRevision, :count).by(1)
.and change(TagDescriptionVersion, :count).by(1)
expect(response).to have_http_status(:ok)
expect(description.reload).to have_attributes(
body:, version_no: 3, created_by_user_id: author.id, updated_by_user_id: editor.id)
expect(page.reload.body).to eq(body)
revision = page.current_revision
version = TagDescriptionVersion.find(revision.id)
expect(version).to have_attributes(
tag_id: tag.id, language_code: 'ja', version_no: 3, event_type: 'update',
body:, created_by_user_id: editor.id)
expect(revision.body).to eq(body)
expect(page.wiki_versions.order(:version_no).last.body).to eq(body)
expect(TagDescriptionVersion.where(id: history.pluck('id')).order(:version_no)
.map(&:attributes)).to eq(history)
it 'writes matching histories when the body changes' do
expect(page.reload.version_no).to eq(1)
expect(description.version_no).to eq(1)
expect { native_write(:put, body: 'after') }
.to change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)
.and change(TagDescriptionVersion, :count).by(1)
expect(response).to have_http_status(:ok)
expect(description.reload).to have_attributes(
body: 'after', version_no: 2,
created_by_user_id: author.id, updated_by_user_id: editor.id)
expect(page.reload).to have_attributes(body: 'after', version_no: 2)
revision = page.current_revision
version = TagDescriptionVersion.find(revision.id)
expect(version).to have_attributes(
tag_id: tag.id, language_code: 'ja', version_no: 2, event_type: 'update',
body: 'after', created_by_user_id: editor.id)
expect(revision.body).to eq(version.body)
expect(page.wiki_versions.order(:version_no).last.body).to eq(version.body)
get "/wiki/#{ description.id }"
expect(response).to have_http_status(:ok)
expect(json).to include('body' => 'after', 'revision_id' => version.id)
end
['before', "before\n\n"].each do |body|
it 'does not write histories when the normalised body is unchanged' do
before_state = stored_state
page_state = page.reload.attributes
description_state = description.reload.attributes
current_revision_id = page.current_revision.id
native_write(:put, body:)
get "/wiki/#{ description.id }"
expect(response).to have_http_status(:ok)
expect(json).to include('body' => body, 'revision_id' => version.id)
expect(stored_state).to eq(before_state)
expect(page.reload.attributes).to eq(page_state)
expect(description.reload.attributes).to eq(description_state)
expect(page.current_revision.id).to eq(current_revision_id)
end
end