add entry requests, invite new users
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
require "test_helper"
|
||||
|
||||
class Admin::RequestsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@admin = users(:admin_user)
|
||||
@requested_entry = entries(:requested_entry)
|
||||
@approved_entry = entries(:approved_entry)
|
||||
login_as(@admin)
|
||||
end
|
||||
|
||||
test "should require admin authentication" do
|
||||
logout
|
||||
get admin_requests_path
|
||||
assert_redirected_to login_path
|
||||
end
|
||||
|
||||
test "should show requests index" do
|
||||
get admin_requests_path
|
||||
|
||||
assert_response :success
|
||||
assert_select "h1", "Entry Requests"
|
||||
assert_select "h2", /Pending Review/
|
||||
assert_select "h2", /Approved/
|
||||
end
|
||||
|
||||
test "should list requested entries" do
|
||||
get admin_requests_path
|
||||
|
||||
assert_response :success
|
||||
assert_select "td", text: @requested_entry.fi
|
||||
assert_select "a[href=?]", admin_request_path(@requested_entry)
|
||||
end
|
||||
|
||||
test "should list approved entries" do
|
||||
get admin_requests_path
|
||||
|
||||
assert_response :success
|
||||
assert_select "td", text: @approved_entry.fi
|
||||
end
|
||||
|
||||
test "should show request details" do
|
||||
get admin_request_path(@requested_entry)
|
||||
|
||||
assert_response :success
|
||||
assert_select "h1", "Entry Request Details"
|
||||
assert_match @requested_entry.fi, response.body
|
||||
assert_match @requested_entry.en, response.body
|
||||
assert_match @requested_entry.requested_by.name, response.body
|
||||
end
|
||||
|
||||
test "should show edit form for requested entry" do
|
||||
get edit_admin_request_path(@requested_entry)
|
||||
|
||||
assert_response :success
|
||||
assert_select "h1", "Edit Entry Request"
|
||||
assert_select "form[action=?]", admin_request_path(@requested_entry)
|
||||
assert_select "input[name='entry[fi]'][value=?]", @requested_entry.fi
|
||||
end
|
||||
|
||||
test "should update entry details" do
|
||||
patch admin_request_path(@requested_entry), params: {
|
||||
entry: {
|
||||
category: "phrase",
|
||||
fi: "päivitetty sana",
|
||||
en: "updated word",
|
||||
notes: "Updated notes"
|
||||
}
|
||||
}
|
||||
|
||||
@requested_entry.reload
|
||||
assert_equal "phrase", @requested_entry.category
|
||||
assert_equal "päivitetty sana", @requested_entry.fi
|
||||
assert_equal "updated word", @requested_entry.en
|
||||
assert_equal "Updated notes", @requested_entry.notes
|
||||
assert_redirected_to admin_request_path(@requested_entry)
|
||||
assert_equal "Request updated successfully.", flash[:notice]
|
||||
end
|
||||
|
||||
test "should not update with invalid data" do
|
||||
patch admin_request_path(@requested_entry), params: {
|
||||
entry: {
|
||||
fi: "",
|
||||
en: "",
|
||||
sv: "",
|
||||
no: "",
|
||||
ru: "",
|
||||
de: ""
|
||||
}
|
||||
}
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
@requested_entry.reload
|
||||
assert_equal "testisana", @requested_entry.fi # Unchanged
|
||||
end
|
||||
|
||||
test "should approve request and send invitation" do
|
||||
user = @requested_entry.requested_by
|
||||
assert_nil user.invitation_token
|
||||
assert_nil user.invitation_sent_at
|
||||
|
||||
assert_enqueued_emails 1 do
|
||||
post approve_admin_request_path(@requested_entry)
|
||||
end
|
||||
|
||||
user.reload
|
||||
@requested_entry.reload
|
||||
|
||||
assert_equal "approved", @requested_entry.status
|
||||
assert_not_nil user.invitation_token
|
||||
assert_not_nil user.invitation_sent_at
|
||||
assert_equal @admin, user.invited_by
|
||||
assert_redirected_to admin_requests_path
|
||||
assert_match(/invitation sent/i, flash[:notice])
|
||||
end
|
||||
|
||||
test "should not approve already approved entry" do
|
||||
# Try to approve an already approved entry
|
||||
user = @approved_entry.requested_by
|
||||
|
||||
post approve_admin_request_path(@approved_entry)
|
||||
|
||||
@approved_entry.reload
|
||||
assert_equal "approved", @approved_entry.status
|
||||
end
|
||||
|
||||
test "should reject request and delete entry and user" do
|
||||
user = @requested_entry.requested_by
|
||||
entry_id = @requested_entry.id
|
||||
user_id = user.id
|
||||
|
||||
assert_difference("Entry.count", -1) do
|
||||
assert_difference("User.count", -1) do
|
||||
delete reject_admin_request_path(@requested_entry)
|
||||
end
|
||||
end
|
||||
|
||||
assert_not Entry.exists?(entry_id)
|
||||
assert_not User.exists?(user_id)
|
||||
assert_redirected_to admin_requests_path
|
||||
assert_match(/rejected and deleted/i, flash[:notice])
|
||||
end
|
||||
|
||||
test "should reject but not delete user with multiple entries" do
|
||||
user = @requested_entry.requested_by
|
||||
|
||||
# Create another entry for the same user
|
||||
another_entry = Entry.create!(
|
||||
category: :word,
|
||||
fi: "toinen sana",
|
||||
en: "another word",
|
||||
status: :requested,
|
||||
requested_by: user
|
||||
)
|
||||
|
||||
assert_difference("Entry.count", -1) do
|
||||
assert_no_difference("User.count") do
|
||||
delete reject_admin_request_path(@requested_entry)
|
||||
end
|
||||
end
|
||||
|
||||
assert User.exists?(user.id)
|
||||
assert Entry.exists?(another_entry.id)
|
||||
end
|
||||
|
||||
test "contributors should not access admin requests" do
|
||||
logout
|
||||
contributor = users(:contributor_user)
|
||||
login_as(contributor)
|
||||
|
||||
get admin_requests_path
|
||||
assert_redirected_to root_path
|
||||
assert_match(/administrator/i, flash[:alert])
|
||||
end
|
||||
|
||||
test "reviewers should not access admin requests" do
|
||||
logout
|
||||
reviewer = users(:reviewer_user)
|
||||
login_as(reviewer)
|
||||
|
||||
get admin_requests_path
|
||||
assert_redirected_to root_path
|
||||
assert_match(/administrator/i, flash[:alert])
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,223 @@
|
||||
require "test_helper"
|
||||
|
||||
class RequestsControllerTest < ActionDispatch::IntegrationTest
|
||||
test "should show new request form for anonymous users" do
|
||||
get new_request_path
|
||||
|
||||
assert_response :success
|
||||
assert_select "h1", "Request a New Entry"
|
||||
assert_select "form"
|
||||
assert_select "input[name='entry[name]']"
|
||||
assert_select "input[name='entry[email]']"
|
||||
assert_select "select[name='entry[category]']"
|
||||
end
|
||||
|
||||
test "should show new request form for logged-in users without name/email fields" do
|
||||
login_as(users(:contributor_user))
|
||||
get new_request_path
|
||||
|
||||
assert_response :success
|
||||
assert_select "h1", "Request a New Entry"
|
||||
assert_select "form"
|
||||
assert_select "input[name='entry[name]']", count: 0
|
||||
assert_select "input[name='entry[email]']", count: 0
|
||||
assert_select ".bg-blue-50", text: /Submitting as/
|
||||
end
|
||||
|
||||
test "should create entry request with valid data" do
|
||||
assert_difference(["User.count", "Entry.count"], 1) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
name: "New Requester",
|
||||
email: "newrequester@example.com",
|
||||
category: "word",
|
||||
fi: "uusi sana",
|
||||
en: "new word",
|
||||
notes: "Please add this word"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
entry = Entry.last
|
||||
user = User.last
|
||||
|
||||
assert_equal "requested", entry.status
|
||||
assert_equal user, entry.requested_by
|
||||
assert_equal "New Requester", user.name
|
||||
assert_equal "newrequester@example.com", user.email
|
||||
assert_equal "contributor", user.role
|
||||
assert_nil user.invitation_token
|
||||
assert_redirected_to root_path
|
||||
assert_match(/thank you for your request/i, flash[:notice])
|
||||
end
|
||||
|
||||
test "should require at least one translation" do
|
||||
assert_no_difference(["User.count", "Entry.count"]) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
name: "New Requester",
|
||||
email: "newrequester@example.com",
|
||||
category: "word",
|
||||
notes: "No translations provided"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_select ".bg-red-50", text: /At least one language translation is required/
|
||||
end
|
||||
|
||||
test "should redirect to login if email already exists" do
|
||||
existing_user = users(:contributor_user)
|
||||
|
||||
assert_no_difference(["User.count", "Entry.count"]) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
name: "Test User",
|
||||
email: existing_user.email,
|
||||
category: "word",
|
||||
fi: "sana",
|
||||
en: "word"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to login_path
|
||||
assert_equal "An account with this email already exists. Please log in.", flash[:alert]
|
||||
end
|
||||
|
||||
test "should show pending count for email with existing requests" do
|
||||
requester = users(:requester_user)
|
||||
get new_request_path, params: { email: requester.email }
|
||||
|
||||
assert_response :success
|
||||
# User has one requested entry from fixtures
|
||||
assert_select ".bg-blue-50", text: /1 pending request/
|
||||
end
|
||||
|
||||
test "should create entry with only one translation" do
|
||||
assert_difference(["User.count", "Entry.count"], 1) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
name: "Single Translation",
|
||||
email: "single@example.com",
|
||||
category: "word",
|
||||
fi: "vain suomeksi"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
entry = Entry.last
|
||||
assert_equal "vain suomeksi", entry.fi
|
||||
assert_nil entry.en
|
||||
assert_nil entry.sv
|
||||
assert_redirected_to root_path
|
||||
end
|
||||
|
||||
test "should create entry with multiple translations" do
|
||||
assert_difference(["User.count", "Entry.count"], 1) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
name: "Multi Lingual",
|
||||
email: "multilingual@example.com",
|
||||
category: "phrase",
|
||||
fi: "hyvää päivää",
|
||||
en: "good day",
|
||||
sv: "god dag",
|
||||
no: "god dag",
|
||||
ru: "добрый день",
|
||||
de: "guten Tag"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
entry = Entry.last
|
||||
assert_equal "hyvää päivää", entry.fi
|
||||
assert_equal "good day", entry.en
|
||||
assert_equal "god dag", entry.sv
|
||||
assert_equal "god dag", entry.no
|
||||
assert_equal "добрый день", entry.ru
|
||||
assert_equal "guten Tag", entry.de
|
||||
assert_redirected_to root_path
|
||||
end
|
||||
|
||||
test "logged-in user can submit request without providing name/email" do
|
||||
user = users(:contributor_user)
|
||||
login_as(user)
|
||||
|
||||
assert_no_difference("User.count") do
|
||||
assert_difference("Entry.count", 1) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
category: "word",
|
||||
fi: "kirjautunut käyttäjä",
|
||||
en: "logged in user"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
entry = Entry.last
|
||||
assert_equal user, entry.requested_by
|
||||
assert_equal "requested", entry.status
|
||||
assert_redirected_to root_path
|
||||
assert_match(/thank you for your request/i, flash[:notice])
|
||||
end
|
||||
|
||||
test "should not modify existing user when they submit request" do
|
||||
user = users(:contributor_user)
|
||||
original_name = user.name
|
||||
original_updated_at = user.updated_at
|
||||
login_as(user)
|
||||
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
category: "word",
|
||||
fi: "testi"
|
||||
}
|
||||
}
|
||||
|
||||
user.reload
|
||||
assert_equal original_name, user.name
|
||||
assert_equal original_updated_at.to_i, user.updated_at.to_i
|
||||
end
|
||||
|
||||
test "should reuse existing pending user without modifying them" do
|
||||
# Create a user without accepted invitation
|
||||
existing_user = User.create!(
|
||||
name: "Pending User",
|
||||
email: "pending_test@example.com",
|
||||
password: SecureRandom.alphanumeric(32),
|
||||
role: :contributor
|
||||
)
|
||||
original_name = existing_user.name
|
||||
original_updated_at = existing_user.updated_at
|
||||
|
||||
# Create first entry
|
||||
Entry.create!(
|
||||
category: :word,
|
||||
fi: "first",
|
||||
status: :requested,
|
||||
requested_by: existing_user
|
||||
)
|
||||
|
||||
# Submit second request with same email but different name
|
||||
assert_no_difference("User.count") do
|
||||
assert_difference("Entry.count", 1) do
|
||||
post requests_path, params: {
|
||||
entry: {
|
||||
name: "Different Name", # This should be ignored
|
||||
email: existing_user.email,
|
||||
category: "word",
|
||||
fi: "second"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
existing_user.reload
|
||||
assert_equal original_name, existing_user.name # Name should not change
|
||||
assert_equal original_updated_at.to_i, existing_user.updated_at.to_i # Should not be updated
|
||||
assert_equal 2, existing_user.requested_entries.count
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user