From 3469c58b53d51b6d75c6ef0c3c9531ea76bf8532 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Sat, 21 Mar 2026 04:57:46 +0900 Subject: [PATCH] #297 --- backend/spec/factories/theatre_comments.rb | 8 + backend/spec/factories/theatres.rb | 11 ++ .../spec/requests/theatre_comments_spec.rb | 150 ++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 backend/spec/factories/theatre_comments.rb create mode 100644 backend/spec/factories/theatres.rb create mode 100644 backend/spec/requests/theatre_comments_spec.rb diff --git a/backend/spec/factories/theatre_comments.rb b/backend/spec/factories/theatre_comments.rb new file mode 100644 index 0000000..a45cec4 --- /dev/null +++ b/backend/spec/factories/theatre_comments.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :theatre_comment do + association :theatre + association :user + sequence (:no) { |n| n } + content { 'test comment' } + end +end diff --git a/backend/spec/factories/theatres.rb b/backend/spec/factories/theatres.rb new file mode 100644 index 0000000..47366ea --- /dev/null +++ b/backend/spec/factories/theatres.rb @@ -0,0 +1,11 @@ +FactoryBot.define do + factory :theatre do + name { 'Test Theatre' } + kind { 1 } + opens_at { Time.current } + closes_at { 1.day.from_now } + next_comment_no { 1 } + + association :created_by_user, factory: :user + end +end diff --git a/backend/spec/requests/theatre_comments_spec.rb b/backend/spec/requests/theatre_comments_spec.rb new file mode 100644 index 0000000..a9f04a0 --- /dev/null +++ b/backend/spec/requests/theatre_comments_spec.rb @@ -0,0 +1,150 @@ +require 'rails_helper' + +RSpec.describe 'TheatreComments', type: :request do + def sign_in_as(user) + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) + end + + describe 'GET /theatres/:theatre_id/comments' do + let(:theatre) { create(:theatre) } + let(:other_theatre) { create(:theatre) } + let(:alice) { create(:user, name: 'Alice') } + let(:bob) { create(:user, name: 'Bob') } + + let!(:comment_3) do + create( + :theatre_comment, + theatre: theatre, + no: 3, + user: alice, + content: 'third comment' + ) + end + + let!(:comment_1) do + create( + :theatre_comment, + theatre: theatre, + no: 1, + user: alice, + content: 'first comment' + ) + end + + let!(:comment_2) do + create( + :theatre_comment, + theatre: theatre, + no: 2, + user: bob, + content: 'second comment' + ) + end + + let!(:other_comment) do + create( + :theatre_comment, + theatre: other_theatre, + no: 1, + user: bob, + content: 'other theatre comment' + ) + end + + it 'theatre_id で絞り込み、no_gt より大きいものを no 昇順で返す' do + get "/theatres/#{theatre.id}/comments", params: { no_gt: 1 } + + expect(response).to have_http_status(:ok) + expect(response.parsed_body.map { |row| row['no'] }).to eq([2, 3]) + expect(response.parsed_body.map { |row| row['content'] }).to eq([ + 'second comment', + 'third comment' + ]) + end + + it 'user は id と name だけを含む' do + get "/theatres/#{theatre.id}/comments", params: { no_gt: 1 } + + expect(response).to have_http_status(:ok) + + expect(response.parsed_body.first['user']).to eq({ + 'id' => bob.id, + 'name' => 'Bob' + }) + expect(response.parsed_body.first['user'].keys).to contain_exactly('id', 'name') + end + + it 'no_gt が負数なら 0 として扱う' do + get "/theatres/#{theatre.id}/comments", params: { no_gt: -100 } + + expect(response).to have_http_status(:ok) + expect(response.parsed_body.map { |row| row['no'] }).to eq([1, 2, 3]) + end + end + + describe 'POST /theatres/:theatre_id/comments' do + let(:user) { create(:user, name: 'Alice') } + let(:theatre) { create(:theatre, next_comment_no: 2) } + + before do + create( + :theatre_comment, + theatre: theatre, + no: 1, + user: user, + content: 'existing comment' + ) + end + + it '未ログインなら 401 を返す' do + expect { + post "/theatres/#{theatre.id}/comments", params: { content: 'hello' } + }.not_to change(TheatreComment, :count) + + expect(response).to have_http_status(:unauthorized) + end + + it 'content が blank なら 422 を返す' do + sign_in_as(user) + + expect { + post "/theatres/#{theatre.id}/comments", params: { content: ' ' } + }.not_to change(TheatreComment, :count) + + expect(response).to have_http_status(:unprocessable_entity) + end + + it 'theatre が存在しなければ 404 を返す' do + sign_in_as(user) + + expect { + post '/theatres/999999/comments', params: { content: 'hello' } + }.not_to change(TheatreComment, :count) + + expect(response).to have_http_status(:not_found) + end + + it 'コメントを作成し、user を紐づけ、next_comment_no を進める' do + sign_in_as(user) + + expect { + post "/theatres/#{theatre.id}/comments", params: { content: 'new comment' } + }.to change(TheatreComment, :count).by(1) + + expect(response).to have_http_status(:created) + + comment = TheatreComment.find_by!(theatre: theatre, no: 2) + + expect(comment.user).to eq(user) + expect(comment.content).to eq('new comment') + expect(theatre.reload.next_comment_no).to eq(3) + + expect(response.parsed_body.slice('theatre_id', 'no', 'user_id', 'content')).to eq({ + 'theatre_id' => theatre.id, + 'no' => 2, + 'user_id' => user.id, + 'content' => 'new comment' + }) + end + end +end