This commit is contained in:
@@ -302,10 +302,9 @@ class TagsController < ApplicationController
|
|||||||
NicoTagVersionRecorder.record!(tag:, event_type:, created_by_user:)
|
NicoTagVersionRecorder.record!(tag:, event_type:, created_by_user:)
|
||||||
else
|
else
|
||||||
TagVersionRecorder.record!(tag:, event_type:, created_by_user:)
|
TagVersionRecorder.record!(tag:, event_type:, created_by_user:)
|
||||||
if tag.has_wiki
|
wiki_page = tag.tag_name.wiki_page
|
||||||
WikiVersionRecorder.record!(page: tag.tag_name.wiki_page,
|
if wiki_page&.wiki_versions&.exists?
|
||||||
event_type: :update,
|
WikiVersionRecorder.record!(page: wiki_page, event_type: :update, created_by_user:)
|
||||||
created_by_user:)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class WikiPage < ApplicationRecord
|
|||||||
|
|
||||||
belongs_to :tag_name
|
belongs_to :tag_name
|
||||||
validates :tag_name, presence: true
|
validates :tag_name, presence: true
|
||||||
|
validates :body, presence: true
|
||||||
|
|
||||||
def title = tag_name.name
|
def title = tag_name.name
|
||||||
|
|
||||||
@@ -26,11 +27,6 @@ class WikiPage < ApplicationRecord
|
|||||||
|
|
||||||
def current_revision = wiki_revisions.order(id: :desc).first
|
def current_revision = wiki_revisions.order(id: :desc).first
|
||||||
|
|
||||||
def body
|
|
||||||
rev = current_revision
|
|
||||||
rev.body if rev&.content?
|
|
||||||
end
|
|
||||||
|
|
||||||
def resolve_redirect limit: 10
|
def resolve_redirect limit: 10
|
||||||
page = self
|
page = self
|
||||||
visited = Set.new
|
visited = Set.new
|
||||||
|
|||||||
@@ -7,6 +7,31 @@ module Wiki
|
|||||||
;
|
;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.create_content! tag_name:, body:, created_by_user:, message: nil
|
||||||
|
normalised = normalise_body(body)
|
||||||
|
|
||||||
|
page = WikiPage.new(tag_name:,
|
||||||
|
body: normalised,
|
||||||
|
created_user: created_by_user,
|
||||||
|
updated_user: created_by_user)
|
||||||
|
|
||||||
|
if normalised.blank?
|
||||||
|
page.errors.add(:body, :blank)
|
||||||
|
raise ActiveRecord::RecordInvalid, page
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
page.save!
|
||||||
|
|
||||||
|
new(page:, created_user: created_by_user).content!(
|
||||||
|
body: normalised,
|
||||||
|
message:,
|
||||||
|
base_revision_id: nil)
|
||||||
|
|
||||||
|
page
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.content! page:, body:, created_user:, message: nil, base_revision_id: nil
|
def self.content! page:, body:, created_user:, message: nil, base_revision_id: nil
|
||||||
new(page:, created_user:).content!(body:, message:, base_revision_id:)
|
new(page:, created_user:).content!(body:, message:, base_revision_id:)
|
||||||
end
|
end
|
||||||
@@ -21,7 +46,12 @@ module Wiki
|
|||||||
end
|
end
|
||||||
|
|
||||||
def content! body:, message:, base_revision_id:
|
def content! body:, message:, base_revision_id:
|
||||||
normalised = normalise_body(body).gsub(/\n+$/, '')
|
normalised = self.class.normalise_body(body)
|
||||||
|
if normalised.blank?
|
||||||
|
@page.errors.add(:body, :blank)
|
||||||
|
raise ActiveRecord::RecordInvalid, @page
|
||||||
|
end
|
||||||
|
|
||||||
lines = split_lines(normalised)
|
lines = split_lines(normalised)
|
||||||
|
|
||||||
line_shas = lines.map { |line| Digest::SHA256.hexdigest(line) }
|
line_shas = lines.map { |line| Digest::SHA256.hexdigest(line) }
|
||||||
@@ -45,11 +75,12 @@ module Wiki
|
|||||||
@page.update!(body: normalised)
|
@page.update!(body: normalised)
|
||||||
|
|
||||||
WikiVersionRecorder.record!(
|
WikiVersionRecorder.record!(
|
||||||
page: { title: @page.title, body: normalised },
|
page: @page,
|
||||||
event_type: @page.wiki_versions.exists? ? :update : :create,
|
event_type: @page.wiki_versions.exists? ? :update : :create,
|
||||||
|
reason: message,
|
||||||
created_by_user: @created_user)
|
created_by_user: @created_user)
|
||||||
tag = @page.tag_name.tag
|
tag = @page.tag_name.tag
|
||||||
if tag
|
if tag&.tag_versions&.exists?
|
||||||
TagVersionRecorder.record!(tag:, event_type: :update, created_by_user: @created_user)
|
TagVersionRecorder.record!(tag:, event_type: :update, created_by_user: @created_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -74,14 +105,15 @@ module Wiki
|
|||||||
|
|
||||||
def redirect!(redirect_page:, message:, base_revision_id:) = raise '廃止しました.'
|
def redirect!(redirect_page:, message:, base_revision_id:) = raise '廃止しました.'
|
||||||
|
|
||||||
private
|
def self.normalise_body body
|
||||||
|
|
||||||
def normalise_body body
|
|
||||||
s = body.to_s
|
s = body.to_s
|
||||||
s.gsub!(/\r\n?/, "\n")
|
s.gsub!(/\r\n?/, "\n")
|
||||||
s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '🖕')
|
s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '🖕')
|
||||||
|
s.gsub(/\n+$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def split_lines(body) = body.split("\n")
|
def split_lines(body) = body.split("\n")
|
||||||
|
|
||||||
def upsert_lines! lines, line_shas
|
def upsert_lines! lines, line_shas
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
class WikiVersionRecorder < VersionRecorder
|
class WikiVersionRecorder < VersionRecorder
|
||||||
def self.record! page:, event_type:, created_by_user:
|
def self.record! page:, event_type:, reason: nil, created_by_user:
|
||||||
new(page:, event_type:, created_by_user:).record!
|
new(page:, event_type:, created_by_user:).record!
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize page:, event_type:, created_by_user:
|
def initialize page:, event_type:, reason: nil, created_by_user:
|
||||||
|
@reason = reason
|
||||||
super(record: page, event_type:, created_by_user:)
|
super(record: page, event_type:, created_by_user:)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -13,5 +14,8 @@ class WikiVersionRecorder < VersionRecorder
|
|||||||
def version_association = :wiki_versions
|
def version_association = :wiki_versions
|
||||||
def record_key = :wiki_page
|
def record_key = :wiki_page
|
||||||
|
|
||||||
def snapshot_attributes = { title: @record.title, body: @record.body }
|
def snapshot_attributes = {
|
||||||
|
title: @record.title,
|
||||||
|
body: @record.body,
|
||||||
|
reason: @reason }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,5 +3,7 @@ FactoryBot.define do
|
|||||||
title { "TestPage" }
|
title { "TestPage" }
|
||||||
association :created_user, factory: :user
|
association :created_user, factory: :user
|
||||||
association :updated_user, factory: :user
|
association :updated_user, factory: :user
|
||||||
|
|
||||||
|
body { ' ' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -107,11 +107,13 @@ RSpec.describe Tag, type: :model do
|
|||||||
context 'when the source tag_name has a wiki_page' do
|
context 'when the source tag_name has a wiki_page' do
|
||||||
let!(:source_post_tag) { PostTag.create!(post: post_record, tag: source_tag) }
|
let!(:source_post_tag) { PostTag.create!(post: post_record, tag: source_tag) }
|
||||||
let!(:wiki_page) do
|
let!(:wiki_page) do
|
||||||
WikiPage.create!(
|
admin = create_admin_user!
|
||||||
tag_name: source_tag_name,
|
|
||||||
created_user: create_admin_user!,
|
Wiki::Commit.create_content!(
|
||||||
updated_user: create_admin_user!
|
tag_name: source_tag_name,
|
||||||
)
|
body: 'source wiki body',
|
||||||
|
created_by_user: admin,
|
||||||
|
message: 'init')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rolls back the transaction' do
|
it 'rolls back the transaction' do
|
||||||
|
|||||||
@@ -214,5 +214,34 @@ RSpec.describe 'TagVersions API', type: :request do
|
|||||||
expect(versions.size).to eq(1)
|
expect(versions.size).to eq(1)
|
||||||
expect(versions.first['version_no']).to eq(2)
|
expect(versions.first['version_no']).to eq(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'includes tag versions created by wiki updates' do
|
||||||
|
wiki_tag_name = TagName.create!(name: 'tag_versions_from_wiki')
|
||||||
|
wiki_tag = Tag.create!(tag_name: wiki_tag_name, category: :general)
|
||||||
|
|
||||||
|
wiki_page =
|
||||||
|
Wiki::Commit.create_content!(
|
||||||
|
tag_name: wiki_tag_name,
|
||||||
|
body: 'before',
|
||||||
|
created_by_user: member,
|
||||||
|
message: 'init')
|
||||||
|
|
||||||
|
Wiki::Commit.content!(
|
||||||
|
page: wiki_page,
|
||||||
|
body: 'after',
|
||||||
|
created_user: member,
|
||||||
|
message: 'edit',
|
||||||
|
base_revision_id: wiki_page.current_revision.id)
|
||||||
|
|
||||||
|
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'])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -876,6 +876,105 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
expect(system_tag.reload.name).to eq(old_name)
|
expect(system_tag.reload.name).to eq(old_name)
|
||||||
expect(system_tag.category).to eq(old_category)
|
expect(system_tag.category).to eq(old_category)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'wiki を持つ tag を更新すると 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')
|
||||||
|
|
||||||
|
Wiki::Commit.content!(
|
||||||
|
page: wiki_page,
|
||||||
|
body: 'wiki body before',
|
||||||
|
created_user: member_user,
|
||||||
|
message: 'init'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
put "/tags/#{ tag.id }", params: {
|
||||||
|
name: 'put_wiki_version_tag',
|
||||||
|
category: 'meme',
|
||||||
|
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_version_tag',
|
||||||
|
body: 'wiki body before',
|
||||||
|
created_by_user_id: member_user.id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it '別名を他 tag から奪った場合、奪はれた側の tag version も作成する' do
|
||||||
|
pending '#329 で対応予定'
|
||||||
|
|
||||||
|
old_owner = Tag.create!(
|
||||||
|
tag_name: TagName.create!(name: 'put_alias_old_owner'),
|
||||||
|
category: :general
|
||||||
|
)
|
||||||
|
stolen_alias = TagName.create!(
|
||||||
|
name: 'put_stolen_alias',
|
||||||
|
canonical: old_owner.tag_name
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(old_owner.tag_name.aliases.map(&:name)).to include('put_stolen_alias')
|
||||||
|
|
||||||
|
expect {
|
||||||
|
put "/tags/#{ tag.id }", params: {
|
||||||
|
name: 'spec_tag',
|
||||||
|
category: 'general',
|
||||||
|
aliases: 'unko put_stolen_alias',
|
||||||
|
parent_tags: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.to change { tag.reload.tag_versions.count }.by(2)
|
||||||
|
.and change { old_owner.reload.tag_versions.count }.by(2)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
|
expect(stolen_alias.reload.canonical).to eq(tag.tag_name)
|
||||||
|
expect(old_owner.reload.tag_name.aliases.map(&:name)).not_to include('put_stolen_alias')
|
||||||
|
|
||||||
|
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(old_owner_versions.second.event_type).to eq('update')
|
||||||
|
expect(old_owner_versions.second.aliases.split).not_to include('put_stolen_alias')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'parent_tags に指定すると循環する tag は 422 にする' do
|
||||||
|
pending '#332 で対応予定'
|
||||||
|
|
||||||
|
child = Tag.create!(
|
||||||
|
tag_name: TagName.create!(name: 'put_cycle_child'),
|
||||||
|
category: :general
|
||||||
|
)
|
||||||
|
|
||||||
|
TagImplication.create!(tag: child, parent_tag: tag)
|
||||||
|
|
||||||
|
put "/tags/#{ tag.id }", params: {
|
||||||
|
name: 'spec_tag',
|
||||||
|
category: 'general',
|
||||||
|
aliases: 'unko',
|
||||||
|
parent_tags: child.name,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unprocessable_entity)
|
||||||
|
|
||||||
|
expect(TagImplication.where(tag:, parent_tag: child)).not_to exist
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
|
|
||||||
let!(:tn) { TagName.create!(name: 'spec_wiki_title') }
|
let!(:tn) { TagName.create!(name: 'spec_wiki_title') }
|
||||||
let!(:page) do
|
let!(:page) do
|
||||||
WikiPage.create!(tag_name: tn, created_user: user, updated_user: user).tap do |p|
|
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')
|
Wiki::Commit.content!(page: p, body: 'init', created_user: user, message: 'init')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -99,6 +104,17 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
end
|
end
|
||||||
.to change(WikiPage, :count).by(1)
|
.to change(WikiPage, :count).by(1)
|
||||||
.and change(WikiRevision, :count).by(1)
|
.and change(WikiRevision, :count).by(1)
|
||||||
|
.and change(WikiVersion, :count).by(1)
|
||||||
|
|
||||||
|
version = page.wiki_versions.order(:version_no).last
|
||||||
|
|
||||||
|
expect(version).to have_attributes(
|
||||||
|
version_no: 1,
|
||||||
|
event_type: 'create',
|
||||||
|
title: 'TestPage',
|
||||||
|
body: "a\nb\nc",
|
||||||
|
created_by_user_id: member.id
|
||||||
|
)
|
||||||
|
|
||||||
expect(response).to have_http_status(:created)
|
expect(response).to have_http_status(:created)
|
||||||
|
|
||||||
@@ -135,6 +151,41 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
# "a" の WikiLine が増殖しない(1行のはず)
|
# "a" の WikiLine が増殖しない(1行のはず)
|
||||||
expect(WikiLine.where(body: 'a').count).to eq(1)
|
expect(WikiLine.where(body: 'a').count).to eq(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'deduplicates duplicated new lines before upsert' do
|
||||||
|
duplicated = 'duplicated_line_for_wiki_line_upsert_spec'
|
||||||
|
|
||||||
|
post endpoint,
|
||||||
|
params: { title: 'DuplicateNewLine', body: "#{ duplicated }\n#{ duplicated }" },
|
||||||
|
headers: auth_headers(member)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:created)
|
||||||
|
|
||||||
|
page = WikiPage.find(json.fetch('id'))
|
||||||
|
rev = page.current_revision
|
||||||
|
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'normalises CRLF and strips trailing newlines' do
|
||||||
|
post endpoint,
|
||||||
|
params: { title: 'NormalisedBody', body: "a\r\nb\r\n\r\n", message: 'normalise' },
|
||||||
|
headers: auth_headers(member)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:created)
|
||||||
|
|
||||||
|
page = WikiPage.find(json.fetch('id'))
|
||||||
|
rev = page.current_revision
|
||||||
|
version = page.wiki_versions.order(:version_no).last
|
||||||
|
|
||||||
|
expect(page.body).to eq("a\nb")
|
||||||
|
expect(version.body).to eq("a\nb")
|
||||||
|
expect(rev.lines_count).to eq(2)
|
||||||
|
expect(rev.wiki_lines.order('wiki_revision_lines.position').map(&:body)).to eq(['a', 'b'])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -146,17 +197,14 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
{ 'X-Transfer-Code' => user.inheritance_code }
|
{ 'X-Transfer-Code' => user.inheritance_code }
|
||||||
end
|
end
|
||||||
|
|
||||||
#let!(:page) { create(:wiki_page, title: 'TestPage') }
|
let!(:test_tag_name) { TagName.create!(name: 'TestPage') }
|
||||||
let!(:page) do
|
|
||||||
build(:wiki_page, title: 'TestPage').tap do |p|
|
|
||||||
puts p.errors.full_messages unless p.valid?
|
|
||||||
p.save!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
let!(:page) do
|
||||||
# 初期版を 1 つ作っておく(更新が“2版目”になるように)
|
Wiki::Commit.create_content!(
|
||||||
Wiki::Commit.content!(page: page, body: "a\nb", created_user: member, message: 'init')
|
tag_name: test_tag_name,
|
||||||
|
body: "a\nb",
|
||||||
|
created_by_user: member,
|
||||||
|
message: 'init')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when not logged in' do
|
context 'when not logged in' do
|
||||||
@@ -200,7 +248,18 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
put "/wiki/#{page.id}",
|
put "/wiki/#{page.id}",
|
||||||
params: { title: 'TestPage', body: "x\ny", message: 'edit', base_revision_id: current_id },
|
params: { title: 'TestPage', body: "x\ny", message: 'edit', base_revision_id: current_id },
|
||||||
headers: auth_headers(member)
|
headers: auth_headers(member)
|
||||||
end.to change(WikiRevision, :count).by(1)
|
end
|
||||||
|
.to change(WikiRevision, :count).by(1)
|
||||||
|
.and change(WikiVersion, :count).by(1)
|
||||||
|
|
||||||
|
version = page.wiki_versions.order(:version_no).last
|
||||||
|
|
||||||
|
expect(version).to have_attributes(
|
||||||
|
event_type: 'update',
|
||||||
|
title: 'TestPage',
|
||||||
|
body: "x\ny",
|
||||||
|
created_by_user_id: member.id
|
||||||
|
)
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
@@ -211,6 +270,48 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
expect(page.body).to eq("x\ny")
|
expect(page.body).to eq("x\ny")
|
||||||
expect(rev.base_revision_id).to eq(current_id)
|
expect(rev.base_revision_id).to eq(current_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'wiki page に対応する tag があれば 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 = 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'
|
||||||
|
)
|
||||||
|
|
||||||
|
current_id = linked_page.wiki_revisions.maximum(:id)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
put "/wiki/#{ linked_page.id }",
|
||||||
|
params: {
|
||||||
|
title: 'wiki_linked_tag_for_version',
|
||||||
|
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(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)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: コンフリクト未実装のため,実装したらコメント外す.
|
# TODO: コンフリクト未実装のため,実装したらコメント外す.
|
||||||
@@ -263,11 +364,11 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
before do
|
before do
|
||||||
# 追加で検索ヒット用
|
# 追加で検索ヒット用
|
||||||
TagName.create!(name: 'spec_wiki_title_2')
|
TagName.create!(name: 'spec_wiki_title_2')
|
||||||
WikiPage.create!(tag_name: TagName.find_by!(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)
|
created_user: user, updated_user: user)
|
||||||
|
|
||||||
TagName.create!(name: 'unrelated_title')
|
TagName.create!(name: 'unrelated_title')
|
||||||
WikiPage.create!(tag_name: TagName.find_by!(name: 'unrelated_title'),
|
WikiPage.create!(tag_name: TagName.find_by!(name: 'unrelated_title'), body: 'init',
|
||||||
created_user: user, updated_user: user)
|
created_user: user, updated_user: user)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -329,7 +430,7 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
it 'returns empty array when page has no revisions and filtered by id' do
|
it 'returns empty array when page has no revisions and filtered by id' do
|
||||||
# 別ページを作って revision 無し
|
# 別ページを作って revision 無し
|
||||||
tn2 = TagName.create!(name: 'spec_no_rev')
|
tn2 = TagName.create!(name: 'spec_no_rev')
|
||||||
p2 = WikiPage.create!(tag_name: tn2, created_user: user, updated_user: user)
|
p2 = WikiPage.create!(tag_name: tn2, body: 'init', created_user: user, updated_user: user)
|
||||||
|
|
||||||
get "/wiki/changes?id=#{p2.id}"
|
get "/wiki/changes?id=#{p2.id}"
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
@@ -398,29 +499,27 @@ RSpec.describe 'Wiki API', type: :request do
|
|||||||
expect(json['older_revision_id']).to eq(rev_a.id)
|
expect(json['older_revision_id']).to eq(rev_a.id)
|
||||||
expect(json['newer_revision_id']).to eq(page.current_revision.id)
|
expect(json['newer_revision_id']).to eq(page.current_revision.id)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns 422 when "to" is redirect revision' do
|
describe 'Wiki::Commit.redirect!' do
|
||||||
# redirect revision を作る
|
it 'raises because redirect revisions are deprecated' do
|
||||||
tn2 = TagName.create!(name: 'redirect_target')
|
target_tag_name = TagName.create!(name: 'redirect_deprecated_target')
|
||||||
target = WikiPage.create!(tag_name: tn2, created_user: user, updated_user: user)
|
target = WikiPage.create!(
|
||||||
|
tag_name: target_tag_name,
|
||||||
|
body: 'target',
|
||||||
|
created_user: user,
|
||||||
|
updated_user: user
|
||||||
|
)
|
||||||
|
|
||||||
Wiki::Commit.redirect!(page: page, redirect_page: target, created_user: user, message: 'redir')
|
expect {
|
||||||
redirect_rev = page.current_revision
|
Wiki::Commit.redirect!(
|
||||||
expect(redirect_rev).to be_redirect
|
page: page,
|
||||||
|
redirect_page: target,
|
||||||
get "/wiki/#{page.id}/diff?from=#{rev_a.id}&to=#{redirect_rev.id}"
|
created_user: user,
|
||||||
expect(response).to have_http_status(:unprocessable_entity)
|
message: 'redirect',
|
||||||
end
|
base_revision_id: page.current_revision.id
|
||||||
|
)
|
||||||
it 'returns 422 when "from" is redirect revision' do
|
}.to raise_error(RuntimeError, '廃止しました.')
|
||||||
tn2 = TagName.create!(name: 'redirect_target2')
|
|
||||||
target = WikiPage.create!(tag_name: tn2, created_user: user, updated_user: user)
|
|
||||||
|
|
||||||
Wiki::Commit.redirect!(page: page, redirect_page: target, created_user: user, message: 'redir2')
|
|
||||||
redirect_rev = page.current_revision
|
|
||||||
|
|
||||||
get "/wiki/#{page.id}/diff?from=#{redirect_rev.id}&to=#{rev_b.id}"
|
|
||||||
expect(response).to have_http_status(:unprocessable_entity)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Wiki::Commit do
|
||||||
|
let(:user) { create_member_user! }
|
||||||
|
|
||||||
|
def create_page(title: 'commit_spec_page', body: 'initial body')
|
||||||
|
tag_name = TagName.create!(name: title)
|
||||||
|
|
||||||
|
Wiki::Commit.create_content!(
|
||||||
|
tag_name:,
|
||||||
|
body:,
|
||||||
|
created_by_user: user,
|
||||||
|
message: 'init')
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.content!' do
|
||||||
|
it 'stores normalised body in wiki_pages and wiki_versions' do
|
||||||
|
page = create_page(title: 'commit_normalised_page')
|
||||||
|
|
||||||
|
described_class.content!(
|
||||||
|
page:,
|
||||||
|
body: "a\r\nb\r\n\r\n",
|
||||||
|
created_user: user,
|
||||||
|
message: 'init'
|
||||||
|
)
|
||||||
|
|
||||||
|
page.reload
|
||||||
|
version = page.wiki_versions.order(:version_no).last
|
||||||
|
|
||||||
|
expect(page.body).to eq("a\nb")
|
||||||
|
expect(version.body).to eq("a\nb")
|
||||||
|
expect(page.current_revision.lines_count).to eq(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deduplicates duplicated missing wiki lines before upsert' do
|
||||||
|
page = create_page(title: 'commit_duplicate_line_page')
|
||||||
|
duplicated = 'commit_duplicate_line'
|
||||||
|
|
||||||
|
described_class.content!(
|
||||||
|
page:,
|
||||||
|
body: "#{ duplicated }\n#{ duplicated }",
|
||||||
|
created_user: user,
|
||||||
|
message: 'init'
|
||||||
|
)
|
||||||
|
|
||||||
|
page.reload
|
||||||
|
|
||||||
|
expect(WikiLine.where(body: duplicated).count).to eq(1)
|
||||||
|
expect(page.current_revision.lines_count).to eq(2)
|
||||||
|
expect(page.current_revision.wiki_revision_lines.count).to eq(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises conflict when base_revision_id is stale' do
|
||||||
|
page = create_page(title: 'commit_conflict_page')
|
||||||
|
|
||||||
|
first = described_class.content!(
|
||||||
|
page:,
|
||||||
|
body: 'first',
|
||||||
|
created_user: user,
|
||||||
|
message: 'first'
|
||||||
|
)
|
||||||
|
|
||||||
|
described_class.content!(
|
||||||
|
page:,
|
||||||
|
body: 'second',
|
||||||
|
created_user: user,
|
||||||
|
message: 'second',
|
||||||
|
base_revision_id: first.id
|
||||||
|
)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
described_class.content!(
|
||||||
|
page:,
|
||||||
|
body: 'third',
|
||||||
|
created_user: user,
|
||||||
|
message: 'third',
|
||||||
|
base_revision_id: first.id
|
||||||
|
)
|
||||||
|
}.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')
|
||||||
|
tag = Tag.create!(tag_name:, category: :general)
|
||||||
|
page = WikiPage.create!(
|
||||||
|
tag_name:,
|
||||||
|
body: '',
|
||||||
|
created_user: user,
|
||||||
|
updated_user: user
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.redirect!' do
|
||||||
|
it 'raises because redirect revisions are deprecated' do
|
||||||
|
page = create_page(title: 'commit_redirect_source')
|
||||||
|
target = create_page(title: 'commit_redirect_target')
|
||||||
|
|
||||||
|
expect {
|
||||||
|
described_class.redirect!(
|
||||||
|
page:,
|
||||||
|
redirect_page: target,
|
||||||
|
created_user: user,
|
||||||
|
message: 'redirect'
|
||||||
|
)
|
||||||
|
}.to raise_error(RuntimeError, '廃止しました.')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user