Browse Source

#318

feature/318
みてるぞ 1 week ago
parent
commit
bce04488ed
2 changed files with 323 additions and 14 deletions
  1. +4
    -2
      backend/app/controllers/tags_controller.rb
  2. +319
    -12
      backend/spec/requests/tags_spec.rb

+ 4
- 2
backend/app/controllers/tags_controller.rb View File

@@ -325,10 +325,12 @@ class TagsController < ApplicationController
with_no_deerjikist: false,
deny_nico: true)

TagVersioning.record_tag_snapshots!((tag.parents.to_a + parent_tags).uniq,
old_parent_tags = tag.parents.to_a

TagVersioning.record_tag_snapshots!((old_parent_tags + parent_tags).uniq,
created_by_user: current_user)

tag.tag_implications.destroy_all
tag.reversed_tag_implications.destroy_all

parent_tags.each do |parent_tag|
next if parent_tag == tag


+ 319
- 12
backend/spec/requests/tags_spec.rb View File

@@ -1,7 +1,6 @@
require 'cgi'
require 'rails_helper'


RSpec.describe 'Tags API', type: :request do
let!(:tn) { TagName.create!(name: 'spec_tag') }
let!(:tag) { Tag.create!(tag_name: tn, category: :general) }
@@ -197,6 +196,30 @@ RSpec.describe 'Tags API', type: :request do
expect(response_tags.size).to eq(1)
expect(response_names).to eq(['norm_a'])
end

it 'returns aliases and parent tags' do
parent_tag = Tag.create!(
tag_name: TagName.create!(name: 'index_parent_tag'),
category: :meme
)
TagImplication.create!(tag:, parent_tag:)

get '/tags', params: { name: 'spec_tag' }

expect(response).to have_http_status(:ok)

row = response_tags.find { |t| t['name'] == 'spec_tag' }

expect(row['aliases']).to include('unko')
expect(row['parents'].map { |t| t['name'] }).to include('index_parent_tag')

parent = row['parents'].find { |t| t['name'] == 'index_parent_tag' }
expect(parent).to include(
'id' => parent_tag.id,
'name' => 'index_parent_tag',
'category' => 'meme'
)
end
end

describe 'GET /tags/:id' do
@@ -220,6 +243,28 @@ RSpec.describe 'Tags API', type: :request do
expect(json).to have_key('created_at')
expect(json).to have_key('updated_at')
end

it 'returns aliases and parent tags' do
parent_tag = Tag.create!(
tag_name: TagName.create!(name: 'show_parent_tag'),
category: :character
)
TagImplication.create!(tag:, parent_tag:)

request

expect(response).to have_http_status(:ok)

expect(json['aliases']).to include('unko')
expect(json['parents'].map { |t| t['name'] }).to include('show_parent_tag')

parent = json['parents'].find { |t| t['name'] == 'show_parent_tag' }
expect(parent).to include(
'id' => parent_tag.id,
'name' => 'show_parent_tag',
'category' => 'character'
)
end
end

context 'when tag does not exist' do
@@ -359,9 +404,9 @@ RSpec.describe 'Tags API', type: :request do
expect(tag.category).to eq('meta')
end

it '存在しない id だと RecordNotFound になる(通常は 404)' do
it '存在しない id なら 404 を返す' do
patch '/tags/999999999', params: { name: 'x' }
expect(response.status).to be_in([404, 500])
expect(response).to have_http_status(:not_found)
end

it 'nico category への変更は 422 を返す' do
@@ -401,21 +446,18 @@ RSpec.describe 'Tags API', type: :request do
expect(tag.reload.category).to eq('general')
end

it 'creates nico tag versions when updating nico tag name' do
it 'returns 422 when updating nico tag name' do
nico_tag_name = TagName.create!(name: 'nico:tags_spec_source')
nico_tag = Tag.create!(tag_name: nico_tag_name, category: :nico)

expect {
patch "/tags/#{nico_tag.id}", params: { name: 'nico:tags_spec_renamed' }
}.to change(NicoTagVersion, :count).by(2)
patch "/tags/#{ nico_tag.id }", params: { name: 'nico:tags_spec_renamed' }
}.not_to change(NicoTagVersion, :count)

expect(response).to have_http_status(:ok)
expect(response).to have_http_status(:unprocessable_entity)

versions = nico_tag.reload.nico_tag_versions.order(:version_no)
expect(versions.map(&:event_type)).to eq(['create', 'update'])
expect(versions.first.name).to eq('nico:tags_spec_source')
expect(versions.second.name).to eq('nico:tags_spec_renamed')
expect(versions.second.created_by_user_id).to eq(member_user.id)
expect(nico_tag.reload.name).to eq('nico:tags_spec_source')
expect(nico_tag.category).to eq('nico')
end

it 'returns 422 when changing nico tag category to normal category' do
@@ -571,4 +613,269 @@ RSpec.describe 'Tags API', type: :request do
expect(response).to have_http_status(:not_found)
end
end

describe 'PUT /tags/:id' do
context '未ログイン' do
before { stub_current_user(nil) }

it '401 を返す' do
put "/tags/#{ tag.id }", params: {
name: 'new',
category: 'general',
aliases: '',
parent_tags: '',
}

expect(response).to have_http_status(:unauthorized)
end
end

context 'ログインしてゐるが member でない' do
before { stub_current_user(non_member_user) }

it '403 を返す' do
put "/tags/#{ tag.id }", params: {
name: 'new',
category: 'general',
aliases: '',
parent_tags: '',
}

expect(response).to have_http_status(:forbidden)
end
end

context 'member' do
before { stub_current_user(member_user) }

it '存在しない id なら 404 を返す' do
put '/tags/999999999', params: {
name: 'new',
category: 'general',
aliases: '',
parent_tags: '',
}

expect(response).to have_http_status(:not_found)
end

it 'name が空なら 422 を返す' do
put "/tags/#{ tag.id }", params: {
name: '',
category: 'general',
aliases: '',
parent_tags: '',
}

expect(response).to have_http_status(:unprocessable_entity)
expect(tag.reload.name).to eq('spec_tag')
end

it 'category が空なら 422 を返す' do
put "/tags/#{ tag.id }", params: {
name: 'new',
category: '',
aliases: '',
parent_tags: '',
}

expect(response).to have_http_status(:unprocessable_entity)
expect(tag.reload.name).to eq('spec_tag')
expect(tag.category).to eq('general')
end

it 'name, category, aliases, parent tags をまとめて更新できる' do
old_parent = Tag.create!(
tag_name: TagName.create!(name: 'put_old_parent'),
category: :general
)
kept_parent = Tag.create!(
tag_name: TagName.create!(name: 'put_kept_parent'),
category: :general
)
TagImplication.create!(tag:, parent_tag: old_parent)
TagImplication.create!(tag:, parent_tag: kept_parent)

put "/tags/#{ tag.id }", params: {
name: 'put_renamed_tag',
category: 'meme',
aliases: 'put_alias_a put_alias_b put_alias_a',
parent_tags: 'put_kept_parent put_new_parent',
}

expect(response).to have_http_status(:ok)

tag.reload

expect(tag.name).to eq('put_renamed_tag')
expect(tag.category).to eq('meme')

expect(TagName.find_by(name: 'put_alias_a').canonical).to eq(tag.tag_name)
expect(TagName.find_by(name: 'put_alias_b').canonical).to eq(tag.tag_name)

old_name_alias = TagName.find_by(name: 'spec_tag')
expect(old_name_alias).to be_present
expect(old_name_alias.canonical).to eq(tag.tag_name)

expect(alias_tn.reload.canonical).to be_nil

expect(tag.parents.map(&:name)).to contain_exactly(
'put_kept_parent',
'put_new_parent'
)

expect(TagImplication.where(tag:, parent_tag: old_parent)).not_to exist

expect(json['name']).to eq('put_renamed_tag')
expect(json['category']).to eq('meme')
expect(json['aliases']).to contain_exactly(
'put_alias_a',
'put_alias_b',
'spec_tag'
)
expect(json['parents'].map { |t| t['name'] }).to contain_exactly(
'put_kept_parent',
'put_new_parent'
)
end

it 'aliases に現在名を指定しても alias には残さない' do
put "/tags/#{ tag.id }", params: {
name: 'spec_tag',
category: 'general',
aliases: 'spec_tag put_alias_self_test',
parent_tags: '',
}

expect(response).to have_http_status(:ok)

tag.reload

expect(TagName.find_by(name: 'put_alias_self_test').canonical).to eq(tag.tag_name)
expect(json['aliases']).to include('put_alias_self_test')
expect(json['aliases']).not_to include('spec_tag')
end

it 'parent_tags に自分自身を指定しても自己参照は作らない' do
put "/tags/#{ tag.id }", params: {
name: 'spec_tag',
category: 'general',
aliases: 'unko',
parent_tags: 'spec_tag',
}

expect(response).to have_http_status(:ok)

expect(TagImplication.where(tag:, parent_tag: tag)).not_to exist
expect(tag.reload.parents).to eq([])
end

it 'initial and update tag versions を作成する' do
expect {
put "/tags/#{ tag.id }", params: {
name: 'put_versioned_tag',
category: 'meta',
aliases: '',
parent_tags: '',
}
}.to change(TagVersion, :count).by(2)

expect(response).to have_http_status(:ok)

versions = tag.reload.tag_versions.order(:version_no)

expect(versions.map(&:event_type)).to eq(['create', 'update'])

expect(versions.first.name).to eq('spec_tag')
expect(versions.first.category).to eq('general')
expect(versions.first.aliases.split).to include('unko')

expect(versions.second.name).to eq('put_versioned_tag')
expect(versions.second.category).to eq('meta')
expect(versions.second.aliases.split).to include('spec_tag')
expect(versions.second.created_by_user_id).to eq(member_user.id)
end

it 'parent tag の snapshot も作成する' do
old_parent = Tag.create!(
tag_name: TagName.create!(name: 'put_snapshot_old_parent'),
category: :general
)
new_parent = Tag.create!(
tag_name: TagName.create!(name: 'put_snapshot_new_parent'),
category: :general
)
TagImplication.create!(tag:, parent_tag: old_parent)

put "/tags/#{ tag.id }", params: {
name: 'spec_tag',
category: 'general',
aliases: 'unko',
parent_tags: new_parent.name,
}

expect(response).to have_http_status(:ok)

expect(old_parent.reload.tag_versions.map(&:event_type)).to include('create')
expect(new_parent.reload.tag_versions.map(&:event_type)).to include('create')
end

it 'normal tag を nico category には変更できない' do
expect {
put "/tags/#{ tag.id }", params: {
name: 'spec_tag',
category: 'nico',
aliases: '',
parent_tags: '',
}
}.not_to change(TagVersion, :count)

expect(response).to have_http_status(:unprocessable_entity)

expect(tag.reload.name).to eq('spec_tag')
expect(tag.category).to eq('general')
end

it 'nico tag は更新できない' do
nico_tag = Tag.create!(
tag_name: TagName.create!(name: 'nico:put_update_all_ng'),
category: :nico
)

expect {
put "/tags/#{ nico_tag.id }", params: {
name: 'nico:put_update_all_renamed',
category: 'nico',
aliases: '',
parent_tags: '',
}
}.not_to change(NicoTagVersion, :count)

expect(response).to have_http_status(:unprocessable_entity)

expect(nico_tag.reload.name).to eq('nico:put_update_all_ng')
expect(nico_tag.category).to eq('nico')
end

it 'system tag の name は変更できない' do
system_tag = Tag.tagme
old_name = system_tag.name
old_category = system_tag.category

expect {
put "/tags/#{ system_tag.id }", params: {
name: 'put_system_tag_renamed',
category: old_category,
aliases: '',
parent_tags: '',
}
}.not_to change(TagVersion, :count)

expect(response).to have_http_status(:unprocessable_entity)

expect(system_tag.reload.name).to eq(old_name)
expect(system_tag.category).to eq(old_category)
end
end
end
end

Loading…
Cancel
Save