spec for showing users faving post
This commit is contained in:
@@ -14,7 +14,11 @@ dependencies: []
|
|||||||
Users need to quickly see how many files are contained in each post when browsing the gallery view, without having to click into each post to see the details.
|
Users need to quickly see how many files are contained in each post when browsing the gallery view, without having to click into each post to see the details.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
<!-- AC:BEGIN -->
|
<!-- AC:BEGIN -->
|
||||||
- [ ] #1 File count is visually displayed on each post in gallery view,Count accurately reflects the actual number of files in the post,Count is clearly visible and doesn't interfere with existing UI elements,Count updates dynamically when post files are added or removed
|
|
||||||
- [ ] #2 File count is visually displayed on each post in gallery view,Count accurately reflects the actual number of files in the post,Count is clearly visible and doesn't interfere with existing UI elements,Count updates dynamically when post files are added or removed
|
- [ ] #1 File count is visually displayed on each post in gallery view
|
||||||
|
- [ ] #2 Count accurately reflects the actual number of files in the post
|
||||||
|
- [ ] #3 Count is clearly visible and doesn't interfere with existing UI elements
|
||||||
|
- [ ] #4 Count updates dynamically when post files are added or removed
|
||||||
<!-- AC:END -->
|
<!-- AC:END -->
|
||||||
|
|||||||
@@ -14,7 +14,13 @@ dependencies: []
|
|||||||
Clean up duplicate post files that have the same file_order value within a post by keeping only the most recent file with a successful 200 HTTP response code. This addresses data inconsistencies from multiple scraping attempts of the same file.
|
Clean up duplicate post files that have the same file_order value within a post by keeping only the most recent file with a successful 200 HTTP response code. This addresses data inconsistencies from multiple scraping attempts of the same file.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
<!-- AC:BEGIN -->
|
<!-- AC:BEGIN -->
|
||||||
- [ ] #1 System identifies posts with multiple files having same file_order,System merges duplicates keeping most recent file with 200 status code,Duplicate files are properly deleted with cascading cleanup,File associations and metadata are preserved for kept files,Process handles edge cases like no files with 200 status,Data integrity is maintained throughout merge process
|
|
||||||
- [ ] #2 System identifies posts with multiple files having same file_order,System merges duplicates keeping most recent file with 200 status code,Duplicate files are properly deleted with cascading cleanup,File associations and metadata are preserved for kept files,Process handles edge cases like no files with 200 status code,Data integrity is maintained throughout merge process
|
- [ ] #1 System identifies posts with multiple files having same file_order
|
||||||
|
- [ ] #2 System merges duplicates keeping most recent file with 200 status code
|
||||||
|
- [ ] #3 Duplicate files are properly deleted with cascading cleanup
|
||||||
|
- [ ] #4 File associations and metadata are preserved for kept files
|
||||||
|
- [ ] #5 Process handles edge cases like no files with 200 status code
|
||||||
|
- [ ] #6 Data integrity is maintained throughout merge process
|
||||||
<!-- AC:END -->
|
<!-- AC:END -->
|
||||||
|
|||||||
@@ -103,4 +103,213 @@ RSpec.describe Domain::UsersController, type: :controller do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "GET #users_faving_post" do
|
||||||
|
before do
|
||||||
|
# Mock authorization to allow all actions for these tests
|
||||||
|
allow(controller).to receive(:authorize).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Shared examples for common users_faving_post behavior across all post types
|
||||||
|
shared_examples "users_faving_post action for post type" do |post_factory, param_prefix, param_attr|
|
||||||
|
let(:domain_post) { create(post_factory) }
|
||||||
|
let(:composite_param) do
|
||||||
|
"#{param_prefix}@#{domain_post.send(param_attr)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when post exists" do
|
||||||
|
context "with no faving users" do
|
||||||
|
it "returns a successful response" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
expect(response).to be_successful
|
||||||
|
end
|
||||||
|
|
||||||
|
it "renders the index template" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
expect(response).to render_template(:index)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the @post instance variable" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
expect(assigns(:post)).to eq(domain_post)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets the @index_type to users_faving_post" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
expect(assigns(:index_type)).to eq(:users_faving_post)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets empty @users collection" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
expect(assigns(:users)).to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "authorizes the post" do
|
||||||
|
expect(controller).to receive(:authorize).with(domain_post)
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with faving users" do
|
||||||
|
before { setup_faving_users }
|
||||||
|
|
||||||
|
it "returns users who have faved the post" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
expect(assigns(:users)).to match_array(expected_faving_users)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "includes avatar associations" do
|
||||||
|
get :users_faving_post, params: { domain_post_id: composite_param }
|
||||||
|
# Test that the query includes avatar associations (won't cause N+1)
|
||||||
|
expect(assigns(:users).first.association(:avatar)).to be_loaded
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when post does not exist" do
|
||||||
|
let(:invalid_param) { "#{param_prefix}@999999" }
|
||||||
|
|
||||||
|
it "raises ActiveRecord::RecordNotFound" do
|
||||||
|
expect {
|
||||||
|
get :users_faving_post, params: { domain_post_id: invalid_param }
|
||||||
|
}.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with invalid composite parameter format" do
|
||||||
|
it "raises ActionController::BadRequest for malformed param" do
|
||||||
|
expect {
|
||||||
|
get :users_faving_post, params: { domain_post_id: "invalid_format" }
|
||||||
|
}.to raise_error(ActionController::BadRequest, /invalid id/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises ActionController::BadRequest for unknown model type" do
|
||||||
|
expect {
|
||||||
|
get :users_faving_post, params: { domain_post_id: "unknown@test" }
|
||||||
|
}.to raise_error(ActionController::BadRequest, /unknown model type/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for Domain::Post::FaPost" do
|
||||||
|
let(:faving_user1) { create(:domain_user_fa_user) }
|
||||||
|
let(:faving_user2) { create(:domain_user_fa_user) }
|
||||||
|
let(:expected_faving_users) { [faving_user1, faving_user2] }
|
||||||
|
|
||||||
|
def setup_faving_users
|
||||||
|
# Create FA-specific user-post-fav relationships
|
||||||
|
Domain::UserPostFav::FaUserPostFav.create!(
|
||||||
|
user: faving_user1,
|
||||||
|
post: domain_post,
|
||||||
|
)
|
||||||
|
Domain::UserPostFav::FaUserPostFav.create!(
|
||||||
|
user: faving_user2,
|
||||||
|
post: domain_post,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples "users_faving_post action for post type",
|
||||||
|
:domain_post_fa_post,
|
||||||
|
"fa",
|
||||||
|
:fa_id
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for Domain::Post::E621Post" do
|
||||||
|
let(:faving_user1) { create(:domain_user_e621_user) }
|
||||||
|
let(:faving_user2) { create(:domain_user_e621_user) }
|
||||||
|
let(:expected_faving_users) { [faving_user1, faving_user2] }
|
||||||
|
|
||||||
|
def setup_faving_users
|
||||||
|
# Create E621-specific user-post-fav relationships
|
||||||
|
Domain::UserPostFav.create!(user: faving_user1, post: domain_post)
|
||||||
|
Domain::UserPostFav.create!(user: faving_user2, post: domain_post)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples "users_faving_post action for post type",
|
||||||
|
:domain_post_e621_post,
|
||||||
|
"e621",
|
||||||
|
:e621_id
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for Domain::Post::InkbunnyPost" do
|
||||||
|
let(:faving_user1) { create(:domain_user_inkbunny_user) }
|
||||||
|
let(:faving_user2) { create(:domain_user_inkbunny_user) }
|
||||||
|
let(:expected_faving_users) { [faving_user1, faving_user2] }
|
||||||
|
|
||||||
|
def setup_faving_users
|
||||||
|
# Create Inkbunny-specific user-post-fav relationships
|
||||||
|
Domain::UserPostFav.create!(user: faving_user1, post: domain_post)
|
||||||
|
Domain::UserPostFav.create!(user: faving_user2, post: domain_post)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples "users_faving_post action for post type",
|
||||||
|
:domain_post_inkbunny_post,
|
||||||
|
"ib",
|
||||||
|
:ib_id
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for Domain::Post::BlueskyPost" do
|
||||||
|
let(:faving_user_with_display_name) do
|
||||||
|
create(:domain_user_bluesky_user, display_name: "Cool Artist")
|
||||||
|
end
|
||||||
|
let(:faving_user_without_display_name) do
|
||||||
|
create(:domain_user_bluesky_user, display_name: nil)
|
||||||
|
end
|
||||||
|
let(:expected_faving_users) do
|
||||||
|
[faving_user_with_display_name, faving_user_without_display_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_faving_users
|
||||||
|
# Create Bluesky-specific user-post-fav relationships
|
||||||
|
Domain::UserPostFav.create!(
|
||||||
|
user: faving_user_with_display_name,
|
||||||
|
post: domain_post,
|
||||||
|
)
|
||||||
|
Domain::UserPostFav.create!(
|
||||||
|
user: faving_user_without_display_name,
|
||||||
|
post: domain_post,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples "users_faving_post action for post type",
|
||||||
|
:domain_post_bluesky_post,
|
||||||
|
"bsky",
|
||||||
|
:rkey
|
||||||
|
|
||||||
|
context "with display name variations" do
|
||||||
|
before do
|
||||||
|
# Create Bluesky-specific user-post-fav relationships
|
||||||
|
Domain::UserPostFav.create!(
|
||||||
|
user: faving_user_with_display_name,
|
||||||
|
post: domain_post,
|
||||||
|
)
|
||||||
|
Domain::UserPostFav.create!(
|
||||||
|
user: faving_user_without_display_name,
|
||||||
|
post: domain_post,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "includes users with display names" do
|
||||||
|
get :users_faving_post,
|
||||||
|
params: {
|
||||||
|
domain_post_id: "bsky@#{domain_post.rkey}",
|
||||||
|
}
|
||||||
|
users = assigns(:users)
|
||||||
|
user_with_display = users.find { |u| u.display_name.present? }
|
||||||
|
expect(user_with_display.display_name).to eq("Cool Artist")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "includes users without display names" do
|
||||||
|
get :users_faving_post,
|
||||||
|
params: {
|
||||||
|
domain_post_id: "bsky@#{domain_post.rkey}",
|
||||||
|
}
|
||||||
|
users = assigns(:users)
|
||||||
|
user_without_display = users.find { |u| u.display_name.blank? }
|
||||||
|
expect(user_without_display.display_name).to be_blank
|
||||||
|
expect(user_without_display.handle).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user