Browse Source

#317

feature/317
みてるぞ 1 week ago
parent
commit
5f0c1953ce
6 changed files with 319 additions and 99 deletions
  1. +14
    -3
      backend/app/controllers/wiki_pages_controller.rb
  2. +0
    -4
      backend/app/services/wiki/commit.rb
  3. +3
    -7
      backend/spec/requests/tag_versions_spec.rb
  4. +79
    -0
      backend/spec/requests/tags_spec.rb
  5. +177
    -69
      backend/spec/requests/wiki_spec.rb
  6. +46
    -16
      backend/spec/services/wiki/commit_spec.rb

+ 14
- 3
backend/app/controllers/wiki_pages_controller.rb View File

@@ -91,7 +91,7 @@ class WikiPagesController < ApplicationController
return head :unprocessable_entity if name.blank? || body.blank?

tag_name = TagName.find_undiscard_or_create_by!(name:)
page = WikiPage.new(tag_name:, created_user: current_user, updated_user: current_user)
page = WikiPage.new(tag_name:, body:, created_user: current_user, updated_user: current_user)
if page.save
message = params[:message].presence
Wiki::Commit.content!(page:, body:, created_user: current_user, message:)
@@ -115,10 +115,16 @@ class WikiPagesController < ApplicationController
page = WikiPage.find(params[:id])
base_revision_id = page.current_revision.id

if params[:title].present? && params[:title].strip != page.title
return head :unprocessable_entity
old_title = page.title

tag = Tag.find_by(tag_name_id: page.tag_name_id)

if tag && title != old_title
TagVersioning.ensure_snapshot!(tag, created_by_user: current_user)
end

page.tag_name.update!(name: title) if title != old_title

message = params[:message].presence
Wiki::Commit.content!(page:,
body:,
@@ -126,6 +132,11 @@ class WikiPagesController < ApplicationController
message:,
base_revision_id:)

if tag && title != old_title
tag.reload
TagVersionRecorder.record!(tag:, event_type: :update, created_by_user: current_user)
end

head :ok
end



+ 0
- 4
backend/app/services/wiki/commit.rb View File

@@ -79,10 +79,6 @@ module Wiki
event_type: @page.wiki_versions.exists? ? :update : :create,
reason: message,
created_by_user: @created_user)
tag = @page.tag_name.tag
if tag&.tag_versions&.exists?
TagVersionRecorder.record!(tag:, event_type: :update, created_by_user: @created_user)
end

rev = WikiRevision.create!(
wiki_page: @page,


+ 3
- 7
backend/spec/requests/tag_versions_spec.rb View File

@@ -215,7 +215,7 @@ RSpec.describe 'TagVersions API', type: :request do
expect(versions.first['version_no']).to eq(2)
end

it 'includes tag versions created by wiki updates' do
it 'does not create tag versions by wiki updates when tag has no versions yet' do
wiki_tag_name = TagName.create!(name: 'tag_versions_from_wiki')
wiki_tag = Tag.create!(tag_name: wiki_tag_name, category: :general)

@@ -236,12 +236,8 @@ RSpec.describe 'TagVersions API', type: :request do
get '/tags/versions', params: { id: wiki_tag.id }

expect(response).to have_http_status(:ok)

versions = json.fetch('versions')

expect(json.fetch('count')).to eq(2)
expect(versions.map { |v| v['event_type'] }).to eq(['update', 'create'])
expect(versions.map { |v| v['name']['current'] }.uniq).to eq(['tag_versions_from_wiki'])
expect(json.fetch('versions')).to eq([])
expect(json.fetch('count')).to eq(0)
end
end
end

+ 79
- 0
backend/spec/requests/tags_spec.rb View File

@@ -472,6 +472,54 @@ RSpec.describe 'Tags API', type: :request do
expect(nico_tag.reload.category).to eq('nico')
end
end

it 'PATCH で tag の name を変更すると対応する wiki version を作成する' do
wiki_page =
Wiki::Commit.create_content!(
tag_name: tag.tag_name,
body: 'wiki body before',
created_by_user: member_user,
message: 'init')

expect {
patch "/tags/#{ tag.id }", params: {
name: 'patch_wiki_renamed_tag',
}
}
.to change(TagVersion, :count).by(2)
.and change(WikiVersion, :count).by(1)

expect(response).to have_http_status(:ok)

version = wiki_page.reload.wiki_versions.order(:version_no).last

expect(version).to have_attributes(
event_type: 'update',
title: 'patch_wiki_renamed_tag',
body: 'wiki body before',
created_by_user_id: member_user.id
)
end

it 'tag の category だけを変更しても wiki version は作成しない' do
wiki_page =
Wiki::Commit.create_content!(
tag_name: tag.tag_name,
body: 'wiki body before',
created_by_user: member_user,
message: 'init')

before_count = wiki_page.reload.wiki_versions.count

expect {
patch "/tags/#{ tag.id }", params: {
category: 'meme',
}
}.to change(TagVersion, :count).by(2)

expect(response).to have_http_status(:ok)
expect(wiki_page.reload.wiki_versions.count).to eq(before_count)
end
end

describe 'GET /tags/with-depth' do
@@ -976,5 +1024,36 @@ RSpec.describe 'Tags API', type: :request do
expect(TagImplication.where(tag:, parent_tag: child)).not_to exist
end
end

it 'tag の name を変更すると対応する wiki version を作成する' do
wiki_page =
Wiki::Commit.create_content!(
tag_name: tag.tag_name,
body: 'wiki body before',
created_by_user: member_user,
message: 'init')

expect {
put "/tags/#{ tag.id }", params: {
name: 'put_wiki_renamed_tag',
category: 'general',
aliases: 'unko',
parent_tags: '',
}
}
.to change(TagVersion, :count).by(2)
.and change(WikiVersion, :count).by(1)

expect(response).to have_http_status(:ok)

version = wiki_page.reload.wiki_versions.order(:version_no).last

expect(version).to have_attributes(
event_type: 'update',
title: 'put_wiki_renamed_tag',
body: 'wiki body before',
created_by_user_id: member_user.id
)
end
end
end

+ 177
- 69
backend/spec/requests/wiki_spec.rb View File

@@ -4,18 +4,19 @@ require 'securerandom'


RSpec.describe 'Wiki API', type: :request do
def auth_headers(user)
{ 'X-Transfer-Code' => user.inheritance_code }
end

let!(:user) { create_member_user! }

let!(:tn) { TagName.create!(name: 'spec_wiki_title') }
let!(:page) do
WikiPage.create!(
tag_name: tn,
body: 'init',
created_user: user,
updated_user: user
).tap do |p|
Wiki::Commit.content!(page: p, body: 'init', created_user: user, message: 'init')
end
Wiki::Commit.create_content!(
tag_name: tn,
body: 'init',
created_by_user: user,
message: 'init')
end

describe 'GET /wiki' do
@@ -42,11 +43,12 @@ RSpec.describe 'Wiki API', type: :request do
context 'when wiki page exists' do
it 'returns wiki page with title' do
request

expect(response).to have_http_status(:ok)

expect(json).to include(
'id' => page.id,
'title' => 'spec_wiki_title')
'id' => page.id,
'title' => 'spec_wiki_title')
end
end

@@ -55,6 +57,7 @@ RSpec.describe 'Wiki API', type: :request do

it 'returns 404' do
request

expect(response).to have_http_status(:not_found)
end
end
@@ -106,7 +109,13 @@ RSpec.describe 'Wiki API', type: :request do
.and change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)

version = page.wiki_versions.order(:version_no).last
expect(response).to have_http_status(:created)

page_id = json.fetch('id')
expect(json.fetch('title')).to eq('TestPage')

created_page = WikiPage.find(page_id)
version = created_page.wiki_versions.order(:version_no).last

expect(version).to have_attributes(
version_no: 1,
@@ -116,24 +125,16 @@ RSpec.describe 'Wiki API', type: :request do
created_by_user_id: member.id
)

expect(response).to have_http_status(:created)

page_id = json.fetch('id')
expect(json.fetch('title')).to eq('TestPage')

page = WikiPage.find(page_id)
rev = page.current_revision
rev = created_page.current_revision
expect(rev).to be_present
expect(rev).to be_content
expect(rev.message).to eq('init')

# body が復元できること
expect(page.body).to eq("a\nb\nc")
expect(created_page.body).to eq("a\nb\nc")

# 行数とリレーションの整合
expect(rev.lines_count).to eq(3)
expect(rev.wiki_revision_lines.order(:position).pluck(:position)).to eq([0, 1, 2])
expect(rev.wiki_lines.pluck(:body)).to match_array(%w[a b c])
expect(rev.wiki_lines.pluck(:body)).to match_array(['a', 'b', 'c'])
end

it 'reuses existing WikiLine rows by sha256' do
@@ -166,8 +167,8 @@ RSpec.describe 'Wiki API', type: :request do

expect(rev.lines_count).to eq(2)
expect(WikiLine.where(body: duplicated).count).to eq(1)
expect(rev.wiki_lines.where(body: duplicated).count).to eq(1)
expect(rev.wiki_revision_lines.count).to eq(2)
expect(rev.wiki_revision_lines.pluck(:wiki_line_id).uniq.size).to eq(1)
end

it 'normalises CRLF and strips trailing newlines' do
@@ -230,14 +231,6 @@ RSpec.describe 'Wiki API', type: :request do
headers: auth_headers(member)
expect(response).to have_http_status(:unprocessable_entity)
end

it 'returns 422 when title mismatched (if you forbid rename here)' do
put "/wiki/#{page.id}",
params: { title: 'OtherTitle', body: 'x' },
headers: auth_headers(member)
# 君の controller 例だと title 変更は 422 にしてた
expect(response).to have_http_status(:unprocessable_entity)
end
end

context 'when success' do
@@ -271,29 +264,29 @@ RSpec.describe 'Wiki API', type: :request do
expect(rev.base_revision_id).to eq(current_id)
end

it 'wiki page に対応する tag があれば tag version も作成する' do
linked_tag_name = TagName.create!(name: 'wiki_linked_tag_for_version')
it 'wiki body だけを変更しても tag version は作成しない' do
linked_tag_name = TagName.create!(name: 'wiki_body_only_tag')
linked_tag = Tag.create!(tag_name: linked_tag_name, category: :general)
linked_page = WikiPage.create!(
tag_name: linked_tag_name,
body: 'before',
created_user: member,
updated_user: member
)

Wiki::Commit.content!(
page: linked_page,
body: 'before',
created_user: member,
message: 'init'
)
TagVersionRecorder.record!(
tag: linked_tag,
event_type: :create,
created_by_user: member)

linked_page =
Wiki::Commit.create_content!(
tag_name: linked_tag_name,
body: 'before',
created_by_user: member,
message: 'init')

current_id = linked_page.wiki_revisions.maximum(:id)
current_id = linked_page.current_revision.id
before_count = linked_tag.reload.tag_versions.count

expect {
put "/wiki/#{ linked_page.id }",
params: {
title: 'wiki_linked_tag_for_version',
title: 'wiki_body_only_tag',
body: 'after',
message: 'edit',
base_revision_id: current_id,
@@ -302,15 +295,9 @@ RSpec.describe 'Wiki API', type: :request do
}
.to change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)
.and change { linked_tag.reload.tag_versions.count }.by(1)

expect(response).to have_http_status(:ok)

version = linked_tag.reload.tag_versions.order(:version_no).last

expect(version.event_type).to eq('update')
expect(version.name).to eq('wiki_linked_tag_for_version')
expect(version.created_by_user_id).to eq(member.id)
expect(linked_tag.reload.tag_versions.count).to eq(before_count)
end
end

@@ -362,14 +349,17 @@ RSpec.describe 'Wiki API', type: :request do

describe 'GET /wiki/search' do
before do
# 追加で検索ヒット用
TagName.create!(name: 'spec_wiki_title_2')
WikiPage.create!(tag_name: TagName.find_by!(name: 'spec_wiki_title_2'), body: 'init',
created_user: user, updated_user: user)
Wiki::Commit.create_content!(
tag_name: TagName.create!(name: 'spec_wiki_title_2'),
body: 'search body 2',
created_by_user: user,
message: 'init')

TagName.create!(name: 'unrelated_title')
WikiPage.create!(tag_name: TagName.find_by!(name: 'unrelated_title'), body: 'init',
created_user: user, updated_user: user)
Wiki::Commit.create_content!(
tag_name: TagName.create!(name: 'unrelated_title'),
body: 'unrelated body',
created_by_user: user,
message: 'init')
end

it 'returns up to 20 pages filtered by title like' do
@@ -379,7 +369,9 @@ RSpec.describe 'Wiki API', type: :request do
expect(json).to be_an(Array)

titles = json.map { |p| p['title'] }
expect(titles).to include('spec_wiki_title', 'spec_wiki_title_2')

expect(titles).to include('spec_wiki_title')
expect(titles).to include('spec_wiki_title_2')
expect(titles).not_to include('unrelated_title')
end

@@ -430,7 +422,12 @@ RSpec.describe 'Wiki API', type: :request do
it 'returns empty array when page has no revisions and filtered by id' do
# 別ページを作って revision 無し
tn2 = TagName.create!(name: 'spec_no_rev')
p2 = WikiPage.create!(tag_name: tn2, body: 'init', created_user: user, updated_user: user)
# 異常データ: revision 無し WikiPage を直接作る
p2 = WikiPage.create!(
tag_name: tn2,
body: 'init',
created_user: user,
updated_user: user)

get "/wiki/changes?id=#{p2.id}"
expect(response).to have_http_status(:ok)
@@ -504,12 +501,12 @@ RSpec.describe 'Wiki API', type: :request do
describe 'Wiki::Commit.redirect!' do
it 'raises because redirect revisions are deprecated' do
target_tag_name = TagName.create!(name: 'redirect_deprecated_target')
target = WikiPage.create!(
tag_name: target_tag_name,
body: 'target',
created_user: user,
updated_user: user
)
target =
Wiki::Commit.create_content!(
tag_name: target_tag_name,
body: 'target',
created_by_user: user,
message: 'init')

expect {
Wiki::Commit.redirect!(
@@ -522,4 +519,115 @@ RSpec.describe 'Wiki API', type: :request do
}.to raise_error(RuntimeError, '廃止しました.')
end
end

it 'wiki title を変更すると対応する tag の version を作成する' do
linked_tag_name = TagName.create!(name: 'wiki_linked_tag_for_version')
linked_tag = Tag.create!(tag_name: linked_tag_name, category: :general)

linked_page =
Wiki::Commit.create_content!(
tag_name: linked_tag_name,
body: 'before',
created_by_user: user,
message: 'init')

current_id = linked_page.current_revision.id

expect {
put "/wiki/#{ linked_page.id }",
params: {
title: 'wiki_linked_tag_for_version_renamed',
body: 'after',
message: 'edit',
base_revision_id: current_id,
},
headers: auth_headers(member)
}
.to change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)
.and change { linked_tag.reload.tag_versions.count }.by(2)

expect(response).to have_http_status(:ok)

linked_tag.reload
expect(linked_tag.name).to eq('wiki_linked_tag_for_version_renamed')

versions = linked_tag.tag_versions.order(:version_no)

expect(versions.first.event_type).to eq('create')
expect(versions.first.name).to eq('wiki_linked_tag_for_version')

expect(versions.second.event_type).to eq('update')
expect(versions.second.name).to eq('wiki_linked_tag_for_version_renamed')
end

it 'wiki body だけを変更しても tag version は作成しない' do
linked_tag_name = TagName.create!(name: 'wiki_body_only_tag')
linked_tag = Tag.create!(tag_name: linked_tag_name, category: :general)

linked_page =
Wiki::Commit.create_content!(
tag_name: linked_tag_name,
body: 'before',
created_by_user: user,
message: 'init')

current_id = linked_page.current_revision.id

expect {
put "/wiki/#{ linked_page.id }",
params: {
title: 'wiki_body_only_tag',
body: 'after',
message: 'edit',
base_revision_id: current_id,
},
headers: auth_headers(member)
}
.to change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)

expect(linked_tag.reload.tag_versions.count).to eq(0)
end

it 'wiki title を変更すると対応する tag の version を作成する' do
linked_tag_name = TagName.create!(name: 'wiki_linked_tag_for_version')
linked_tag = Tag.create!(tag_name: linked_tag_name, category: :general)

linked_page =
Wiki::Commit.create_content!(
tag_name: linked_tag_name,
body: 'before',
created_by_user: user,
message: 'init')

current_id = linked_page.current_revision.id

expect {
put "/wiki/#{ linked_page.id }",
params: {
title: 'wiki_linked_tag_for_version_renamed',
body: 'after',
message: 'rename',
base_revision_id: current_id,
},
headers: auth_headers(user)
}
.to change(WikiRevision, :count).by(1)
.and change(WikiVersion, :count).by(1)
.and change { linked_tag.reload.tag_versions.count }.by(2)

expect(response).to have_http_status(:ok)

linked_tag.reload
expect(linked_tag.name).to eq('wiki_linked_tag_for_version_renamed')

versions = linked_tag.tag_versions.order(:version_no)

expect(versions.first.event_type).to eq('create')
expect(versions.first.name).to eq('wiki_linked_tag_for_version')

expect(versions.second.event_type).to eq('update')
expect(versions.second.name).to eq('wiki_linked_tag_for_version_renamed')
end
end

+ 46
- 16
backend/spec/services/wiki/commit_spec.rb View File

@@ -79,26 +79,56 @@ RSpec.describe Wiki::Commit do
}.to raise_error(Wiki::Commit::Conflict)
end

it 'records tag version when page has corresponding tag' do
tag_name = TagName.create!(name: 'commit_linked_tag')
it 'does not record tag version when corresponding tag has no versions' do
tag_name = TagName.create!(name: 'commit_linked_tag_without_versions')
tag = Tag.create!(tag_name:, category: :general)
page = WikiPage.create!(
tag_name:,
body: '',
created_user: user,
updated_user: user
)

page =
described_class.create_content!(
tag_name:,
body: 'before',
created_by_user: user,
message: 'init')

expect(tag.reload.tag_versions.count).to eq(0)

current_revision_id = page.current_revision.id

expect {
described_class.content!(
page:,
body: 'body',
created_user: user,
message: 'init'
)
}
.to change(WikiVersion, :count).by(1)
.and change { tag.reload.tag_versions.count }.by(1)
page:,
body: 'after',
created_user: user,
message: 'edit',
base_revision_id: current_revision_id)
}.to change(WikiVersion, :count).by(1)

expect(tag.reload.tag_versions.count).to eq(0)
end

it 'does not record tag version when corresponding tag has no versions' do
tag_name = TagName.create!(name: 'commit_linked_tag_without_versions')
tag = Tag.create!(tag_name:, category: :general)

page =
described_class.create_content!(
tag_name:,
body: 'before',
created_by_user: user,
message: 'init')

current_revision_id = page.current_revision.id

expect {
described_class.content!(
page:,
body: 'after',
created_user: user,
message: 'edit',
base_revision_id: current_revision_id)
}.to change(WikiVersion, :count).by(1)

expect(tag.reload.tag_versions.count).to eq(0)
end
end



Loading…
Cancel
Save