diff --git a/backend/app/controllers/posts_controller.rb b/backend/app/controllers/posts_controller.rb index 2bf91cf..74d720c 100644 --- a/backend/app/controllers/posts_controller.rb +++ b/backend/app/controllers/posts_controller.rb @@ -185,6 +185,7 @@ class PostsController < ApplicationController def changes id = params[:id].presence + tag_id = params[:tag].presence page = (params[:page].presence || 1).to_i limit = (params[:limit].presence || 20).to_i @@ -195,6 +196,7 @@ class PostsController < ApplicationController pts = PostTag.with_discarded pts = pts.where(post_id: id) if id.present? + pts = pts.where(tag_id:) if tag_id.present? pts = pts.includes(:post, :created_user, :deleted_user, tag: { tag_name: :wiki_page }) diff --git a/backend/spec/requests/posts_spec.rb b/backend/spec/requests/posts_spec.rb index ee4fcc5..120a221 100644 --- a/backend/spec/requests/posts_spec.rb +++ b/backend/spec/requests/posts_spec.rb @@ -667,6 +667,93 @@ RSpec.describe 'Posts API', type: :request do expect(types).to include('add') expect(types).to include('remove') end + + it 'filters history by tag' do + tn2 = TagName.create!(name: 'history_tag_hit') + tag2 = Tag.create!(tag_name: tn2, category: :general) + + tn3 = TagName.create!(name: 'history_tag_miss') + tag3 = Tag.create!(tag_name: tn3, category: :general) + + other_post = Post.create!( + title: 'other post', + url: 'https://example.com/history-other' + ) + + # hit: add + PostTag.create!(post: post_record, tag: tag2, created_user: member) + + # hit: add + remove + pt2 = PostTag.create!(post: other_post, tag: tag2, created_user: member) + pt2.discard_by!(member) + + # miss: add + remove + pt3 = PostTag.create!(post: post_record, tag: tag3, created_user: member) + pt3.discard_by!(member) + + get '/posts/changes', params: { tag: tag2.id } + + expect(response).to have_http_status(:ok) + expect(json).to include('changes', 'count') + expect(json['count']).to eq(3) + + changes = json.fetch('changes') + + expect(changes.map { |e| e.dig('tag', 'id') }.uniq).to eq([tag2.id]) + expect(changes.map { |e| e['change_type'] }).to match_array(%w[add add remove]) + expect(changes.map { |e| e.dig('post', 'id') }).to match_array([ + post_record.id, + other_post.id, + other_post.id + ]) + end + + it 'filters history by post and tag together' do + tn2 = TagName.create!(name: 'history_tag_combo_hit') + tag2 = Tag.create!(tag_name: tn2, category: :general) + + tn3 = TagName.create!(name: 'history_tag_combo_miss') + tag3 = Tag.create!(tag_name: tn3, category: :general) + + other_post = Post.create!( + title: 'other combo post', + url: 'https://example.com/history-combo-other' + ) + + # hit + PostTag.create!(post: post_record, tag: tag2, created_user: member) + + # miss by post + pt2 = PostTag.create!(post: other_post, tag: tag2, created_user: member) + pt2.discard_by!(member) + + # miss by tag + pt3 = PostTag.create!(post: post_record, tag: tag3, created_user: member) + pt3.discard_by!(member) + + get '/posts/changes', params: { id: post_record.id, tag: tag2.id } + + expect(response).to have_http_status(:ok) + expect(json).to include('changes', 'count') + expect(json['count']).to eq(1) + + changes = json.fetch('changes') + expect(changes.size).to eq(1) + expect(changes[0]['change_type']).to eq('add') + expect(changes[0].dig('post', 'id')).to eq(post_record.id) + expect(changes[0].dig('tag', 'id')).to eq(tag2.id) + end + + it 'returns empty history when tag does not match' do + tn2 = TagName.create!(name: 'history_tag_no_hit') + tag2 = Tag.create!(tag_name: tn2, category: :general) + + get '/posts/changes', params: { tag: tag2.id } + + expect(response).to have_http_status(:ok) + expect(json.fetch('changes')).to eq([]) + expect(json.fetch('count')).to eq(0) + end end describe 'POST /posts/:id/viewed' do