From fca160ae42a36a5c02222625e2d380f770113fa5 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Mon, 4 May 2026 03:35:45 +0900 Subject: [PATCH] #63 --- .../spec/requests/tags_deerjikists_spec.rb | 244 ++++++++++++++++-- 1 file changed, 227 insertions(+), 17 deletions(-) diff --git a/backend/spec/requests/tags_deerjikists_spec.rb b/backend/spec/requests/tags_deerjikists_spec.rb index 4825f36..c599f17 100644 --- a/backend/spec/requests/tags_deerjikists_spec.rb +++ b/backend/spec/requests/tags_deerjikists_spec.rb @@ -8,23 +8,35 @@ RSpec.describe 'Tags deerjikists API', type: :request do let!(:tag) { create(:tag, category: :deerjikist) } + let(:member) { create(:user, :member) } + let(:guest) { create(:user, role: :guest) } + before do - # show_by_name / deerjikists_by_name 用に名前を固定 tag.tag_name.update!(name: 'deerjika') end describe 'GET /tags/:id/deerjikists' do subject(:do_request) do - get "/tags/#{ tag_id }/deerjikists" + get "/tags/#{tag_id}/deerjikists" end let(:tag_id) { tag.id } context 'when tag exists and has no deerjikists' do - it 'returns 200 and empty array' do + it 'returns 200 with tag and empty deerjikists array' do do_request + expect(response).to have_http_status(:ok) - expect(json).to eq([]) + + expect(json).to be_a(Hash) + + expect(json['tag']).to be_a(Hash) + expect(json['tag']['id']).to eq(tag.id) + expect(json['tag']['name']).to eq('deerjika') + expect(json['tag']['category']).to eq('deerjikist') + expect(json['tag']['has_deerjikists']).to eq(false) + + expect(json['deerjikists']).to eq([]) end end @@ -34,17 +46,27 @@ RSpec.describe 'Tags deerjikists API', type: :request do Deerjikist.create!(platform: platform2, code: code2, tag: tag) end - it 'returns 200 and deerjikists array' do + it 'returns 200 with tag and deerjikists array' do do_request + expect(response).to have_http_status(:ok) - expect(json).to be_a(Array) - expect(json.size).to eq(2) + expect(json).to be_a(Hash) - expect(json.map { |h| [h['platform'], h['code']] }).to contain_exactly( - [platform1, code1], - [platform2, code2], - ) + expect(json['tag']).to be_a(Hash) + expect(json['tag']['id']).to eq(tag.id) + expect(json['tag']['name']).to eq('deerjika') + expect(json['tag']['category']).to eq('deerjikist') + expect(json['tag']['has_deerjikists']).to eq(true) + + expect(json['deerjikists']).to be_a(Array) + expect(json['deerjikists'].size).to eq(2) + + expect(json['deerjikists'].map { |h| [h['platform'], h['code']] }) + .to contain_exactly( + [platform1, code1], + [platform2, code2], + ) end end @@ -53,6 +75,7 @@ RSpec.describe 'Tags deerjikists API', type: :request do it 'returns 404' do do_request + expect(response).to have_http_status(:not_found) end end @@ -60,7 +83,7 @@ RSpec.describe 'Tags deerjikists API', type: :request do describe 'GET /tags/name/:name/deerjikists' do subject(:do_request) do - get "/tags/name/#{ name }/deerjikists" + get "/tags/name/#{name}/deerjikists" end let(:name) { 'deerjika' } @@ -70,6 +93,7 @@ RSpec.describe 'Tags deerjikists API', type: :request do it 'returns 400' do do_request + expect(response).to have_http_status(:bad_request) end end @@ -79,23 +103,209 @@ RSpec.describe 'Tags deerjikists API', type: :request do it 'returns 404' do do_request + expect(response).to have_http_status(:not_found) end end + context 'when tag exists and has no deerjikists' do + it 'returns 200 with tag and empty deerjikists array' do + do_request + + expect(response).to have_http_status(:ok) + + expect(json).to be_a(Hash) + + expect(json['tag']).to be_a(Hash) + expect(json['tag']['id']).to eq(tag.id) + expect(json['tag']['name']).to eq('deerjika') + expect(json['tag']['category']).to eq('deerjikist') + expect(json['tag']['has_deerjikists']).to eq(false) + + expect(json['deerjikists']).to eq([]) + end + end + context 'when tag exists and has deerjikists' do before do Deerjikist.create!(platform: platform1, code: code1, tag: tag) end - it 'returns 200 and deerjikists array' do + it 'returns 200 with tag and deerjikists array' do do_request + expect(response).to have_http_status(:ok) - expect(json).to be_a(Array) - expect(json.size).to eq(1) - expect(json[0]['platform']).to eq(platform1) - expect(json[0]['code']).to eq(code1) + expect(json).to be_a(Hash) + + expect(json['tag']).to be_a(Hash) + expect(json['tag']['id']).to eq(tag.id) + expect(json['tag']['name']).to eq('deerjika') + expect(json['tag']['category']).to eq('deerjikist') + expect(json['tag']['has_deerjikists']).to eq(true) + + expect(json['deerjikists']).to be_a(Array) + expect(json['deerjikists'].size).to eq(1) + + expect(json['deerjikists'][0]['platform']).to eq(platform1) + expect(json['deerjikists'][0]['code']).to eq(code1) + end + end + end + + describe 'PUT /tags/:id/deerjikists' do + subject(:do_request) do + put "/tags/#{tag_id}/deerjikists", params: payload, as: :json + end + + let(:tag_id) { tag.id } + let(:payload) do + [ + { platform: platform1, code: code1 }, + { platform: platform2, code: code2 }, + ] + end + + context 'when not logged in' do + it 'returns 401' do + do_request + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when logged in but not member' do + before do + sign_in_as guest + end + + it 'returns 403' do + do_request + + expect(response).to have_http_status(:forbidden) + end + end + + context 'when tag does not exist' do + let(:tag_id) { 9_999_999 } + + before do + sign_in_as member + end + + it 'returns 404' do + do_request + + expect(response).to have_http_status(:not_found) + end + end + + context 'when logged in as member' do + before do + sign_in_as member + end + + context 'when tag has no deerjikists' do + it 'creates deerjikists and returns deerjikists array' do + expect { + do_request + }.to change { Deerjikist.where(tag: tag).count }.from(0).to(2) + + expect(response).to have_http_status(:ok) + + expect(json).to be_a(Array) + expect(json.map { |h| [h['platform'], h['code']] }) + .to contain_exactly( + [platform1, code1], + [platform2, code2], + ) + + expect(Deerjikist.where(tag: tag).map { |d| [d.platform, d.code] }) + .to contain_exactly( + [platform1, code1], + [platform2, code2], + ) + end + end + + context 'when tag already has deerjikists' do + before do + Deerjikist.create!(platform: platform1, code: 'old-code-1', tag: tag) + Deerjikist.create!(platform: platform2, code: 'old-code-2', tag: tag) + end + + it 'replaces deerjikists and returns deerjikists array' do + do_request + + expect(response).to have_http_status(:ok) + + expect(Deerjikist.where(tag: tag).map { |d| [d.platform, d.code] }) + .to contain_exactly( + [platform1, code1], + [platform2, code2], + ) + + expect(Deerjikist.exists?(platform: platform1, code: 'old-code-1')).to eq(false) + expect(Deerjikist.exists?(platform: platform2, code: 'old-code-2')).to eq(false) + + expect(json).to be_a(Array) + expect(json.map { |h| [h['platform'], h['code']] }) + .to contain_exactly( + [platform1, code1], + [platform2, code2], + ) + end + end + + context 'when payload is empty array' do + let(:payload) { [] } + + before do + Deerjikist.create!(platform: platform1, code: code1, tag: tag) + Deerjikist.create!(platform: platform2, code: code2, tag: tag) + end + + it 'clears deerjikists and returns empty array' do + expect { + do_request + }.to change { Deerjikist.where(tag: tag).count }.from(2).to(0) + + expect(response).to have_http_status(:ok) + expect(json).to eq([]) + end + end + + context 'when youtube code is handle' do + let(:channel_id) { 'UCabcdefghijklmnopqrstuv' } + let(:payload) do + [ + { platform: 'youtube', code: '@deerjika' }, + ] + end + + before do + allow(Net::HTTP).to receive(:get).and_return( + %(), + ) + end + + it 'normalises youtube handle to channel id' do + expect { + do_request + }.to change { Deerjikist.where(tag: tag).count }.from(0).to(1) + + expect(response).to have_http_status(:ok) + + expect(Net::HTTP).to have_received(:get) + + expect(Deerjikist.exists?(platform: 'youtube', code: channel_id, tag: tag)) + .to eq(true) + + expect(json).to be_a(Array) + expect(json.size).to eq(1) + expect(json[0]['platform']).to eq('youtube') + expect(json[0]['code']).to eq(channel_id) + end end end end