require "test_helper" class EntryRequestFlowTest < ActionDispatch::IntegrationTest test "complete flow: request -> admin approve -> user accepts -> entry active" do # Step 1: Public user submits entry request assert_difference([ "User.count", "Entry.count" ], 1) do post requests_path, params: { entry: { name: "Flow Test User", email: "flowtest@example.com", category: "word", fi: "testi", en: "test", notes: "Testing complete flow" } } end assert_redirected_to root_path follow_redirect! assert_response :success entry = Entry.last user = User.last assert_equal "requested", entry.status assert_equal user, entry.requested_by assert_nil user.invitation_token # Step 2: Admin reviews and approves request admin = users(:admin_user) login_as(admin) get admin_requests_path assert_response :success assert_select "td", text: entry.fi # View the request get admin_request_path(entry) assert_response :success assert_select "div", text: entry.fi # Approve the request assert_enqueued_emails 1 do post approve_admin_request_path(entry) end entry.reload user.reload assert_equal "approved", entry.status assert_not_nil user.invitation_token assert_not_nil user.invitation_sent_at assert_equal admin, user.invited_by # Verify the invitation email includes entry information perform_enqueued_jobs sent_email = ActionMailer::Base.deliveries.last assert_match "Your entry request has been approved", sent_email.subject assert_match entry.fi, sent_email.body.encoded assert_match entry.en, sent_email.body.encoded logout # Step 3: User accepts invitation get invitation_path(user.invitation_token) assert_response :success patch accept_invitation_path(user.invitation_token), params: { user: { password: "securepassword123", password_confirmation: "securepassword123" } } entry.reload user.reload # Entry should now be active assert_equal "active", entry.status assert_not_nil user.invitation_accepted_at assert_nil user.invitation_token assert_equal user.id, session[:user_id] # Step 4: Verify entry is visible on public site get root_path assert_response :success # Entry should be in search results end test "rejected request removes entry and user" do # Create a request post requests_path, params: { entry: { name: "To Be Rejected", email: "rejected@example.com", category: "word", fi: "hylätty", en: "rejected" } } assert_redirected_to root_path entry = Entry.last user = User.last entry_id = entry.id user_id = user.id # Admin rejects it login_as(users(:admin_user)) assert_difference([ "User.count", "Entry.count" ], -1) do delete reject_admin_request_path(entry) end assert_not Entry.exists?(entry_id) assert_not User.exists?(user_id) end test "requested and approved entries not visible on public site" do requested = entries(:requested_entry) approved = entries(:approved_entry) active = entries(:one) get root_path assert_response :success # Active entry should be counted assert_select "div", text: "#{Entry.active_entries.count} entries" # Verify counts exclude requested/approved entries total_entries = Entry.count active_entries = Entry.active_entries.count assert total_entries > active_entries, "Should have non-active entries in fixtures" end test "multiple entries by same requester all activated on invitation acceptance" do # Create user with multiple approved entries user = User.create!( name: "Multi Entry User", email: "multi@example.com", password: SecureRandom.alphanumeric(32), role: :contributor, invitation_token: "multi_token_123", invitation_sent_at: 1.day.ago, invited_by: users(:admin_user) ) entry1 = Entry.create!( category: :word, fi: "sana1", en: "word1", status: :approved, requested_by: user ) entry2 = Entry.create!( category: :phrase, fi: "fraasi1", en: "phrase1", status: :approved, requested_by: user ) # User accepts invitation patch accept_invitation_path("multi_token_123"), params: { user: { password: "securepassword123", password_confirmation: "securepassword123" } } entry1.reload entry2.reload assert_equal "active", entry1.status assert_equal "active", entry2.status end test "admin can edit entry details before approval" do # Create a request post requests_path, params: { entry: { name: "Needs Editing", email: "edit@example.com", category: "word", fi: "väärin kirjoitettu", en: "wrong spelling" } } assert_redirected_to root_path entry = Entry.last # Admin edits the entry login_as(users(:admin_user)) get edit_admin_request_path(entry) assert_response :success patch admin_request_path(entry), params: { entry: { fi: "oikein kirjoitettu", en: "correct spelling", category: "phrase" } } entry.reload assert_equal "oikein kirjoitettu", entry.fi assert_equal "correct spelling", entry.en assert_equal "phrase", entry.category # Then approve with corrected details post approve_admin_request_path(entry) entry.reload assert_equal "approved", entry.status assert_equal "oikein kirjoitettu", entry.fi end test "cannot submit request with existing user email" do existing_user = users(:contributor_user) post requests_path, params: { entry: { name: "Test", email: existing_user.email, category: "word", fi: "test" } } assert_redirected_to login_path assert_match(/already exists/i, flash[:alert]) end end