diff --git a/backend/app/controllers/posts_controller.rb b/backend/app/controllers/posts_controller.rb index fb0d8b5..e4dbb04 100644 --- a/backend/app/controllers/posts_controller.rb +++ b/backend/app/controllers/posts_controller.rb @@ -44,7 +44,11 @@ class PostsController < ApplicationController nil end end - }, count: filtered_posts.count(:id), next_cursor: } + }, count: if filtered_posts.group_values.present? + filtered_posts.count.size + else + filtered_posts.count + end, next_cursor: } end def random @@ -181,7 +185,7 @@ class PostsController < ApplicationController private def filtered_posts - tag_names = params[:tags]&.split(' ') + tag_names = params[:tags].to_s.split(' ') match_type = params[:match] if tag_names.present? filter_posts_by_tags(tag_names, match_type) diff --git a/backend/spec/requests/posts_spec.rb b/backend/spec/requests/posts_spec.rb index 7480812..4e0cf11 100644 --- a/backend/spec/requests/posts_spec.rb +++ b/backend/spec/requests/posts_spec.rb @@ -23,23 +23,68 @@ RSpec.describe 'Posts API', type: :request do end end - describe 'GET /posts' do - it 'returns posts with tag name in JSON' do - get '/posts' + describe "GET /posts" do + let!(:user) { create_member_user! } + + let!(:tag_name) { TagName.create!(name: "spec_tag") } + let!(:tag) { Tag.create!(tag_name:, category: "general") } + let!(:tag_name2) { TagName.create!(name: 'unko') } + let!(:tag2) { Tag.create!(tag_name: tag_name2, category: 'deerjikist') } + + let!(:hit_post) do + Post.create!(uploaded_user: user, title: "hello spec world", + url: 'https://example.com/spec').tap do |p| + PostTag.create!(post: p, tag:) + end + end + + let!(:miss_post) do + Post.create!(uploaded_user: user, title: "unrelated title", + url: 'https://example.com/spec2').tap do |p| + PostTag.create!(post: p, tag: tag2) + end + end + + it "returns posts with tag name in JSON" do + get "/posts" expect(response).to have_http_status(:ok) - expect(json).to have_key('posts') - expect(json['posts']).to be_an(Array) - expect(json['posts']).not_to be_empty + posts = json.fetch("posts") + + # 全postの全tagが name を含むこと + expect(posts).not_to be_empty + posts.each do |p| + expect(p["tags"]).to be_an(Array) + p["tags"].each do |t| + expect(t).to include("name", "category") + end + end + expect(json['count']).to be_an(Integer) + + # spec_tag を含む投稿が存在すること + all_tag_names = posts.flat_map { |p| p["tags"].map { |t| t["name"] } } + expect(all_tag_names).to include("spec_tag") + end + + context "when q is provided" do + it "filters posts by q (hit case)" do + get "/posts", params: { tags: "spec_tag" } + + expect(response).to have_http_status(:ok) + ids = json.fetch("posts").map { |p| p["id"] } - tags = json['posts'][0]['tags'] - expect(tags).to be_an(Array) - expect(tags).not_to be_empty + expect(ids).to include(hit_post.id) + expect(ids).not_to include(miss_post.id) + expect(json['count']).to be_an(Integer) + end + + it "returns empty posts when nothing matches" do + get "/posts", params: { tags: "no_such_keyword_12345" } - # Tag は name カラムを持たないので、API 側が methods: [:name] 等で出す必要がある - expect(tags[0]).to have_key('name') - expect(tags.map { |t| t['name'] }).to include('spec_tag') - expect(tags[0]).to include('category') + expect(response).to have_http_status(:ok) + expect(json.fetch("posts")).to eq([]) + expect(json.fetch('count')).to eq(0) + end end end @@ -211,7 +256,7 @@ RSpec.describe 'Posts API', type: :request do end end - describe 'DELETE /posts/:id/unviewed' do + describe 'DELETE /posts/:id/viewed' do let(:user) { create(:user) } it '401 when not logged in' do