invitation emails

This commit is contained in:
2026-01-23 13:49:56 +01:00
parent 35c29749fb
commit 396e649960
14 changed files with 531 additions and 7 deletions
@@ -22,6 +22,18 @@ class Admin::InvitationsControllerTest < ActionDispatch::IntegrationTest
login_as(users(:admin_user))
get new_admin_invitation_path
assert_response :success
assert_select "form"
assert_select "input[name='user[email]']"
assert_select "input[name='user[name]']"
assert_select "select[name='user[role]']"
assert_select "select[name='user[primary_language]']"
end
test "should display pending invitations on index page" do
login_as(users(:admin_user))
get admin_invitations_path
assert_response :success
assert_select "h1,h2", /Invitations/
end
test "should create invitation when logged in as admin" do
@@ -48,6 +60,21 @@ class Admin::InvitationsControllerTest < ActionDispatch::IntegrationTest
assert_equal users(:admin_user).id, new_user.invited_by_id
end
test "should send invitation email when creating invitation" do
login_as(users(:admin_user))
assert_enqueued_emails 1 do
post admin_invitations_path, params: {
user: {
email: "newuser@example.com",
name: "New User",
role: "contributor",
primary_language: "en"
}
}
end
end
test "should not create invitation with invalid data" do
login_as(users(:admin_user))
@@ -0,0 +1,93 @@
require "test_helper"
class InvitationsControllerTest < ActionDispatch::IntegrationTest
test "should show invitation acceptance page with valid token" do
user = users(:pending_invitation)
get invitation_path(user.invitation_token)
assert_response :success
assert_select "h1", "Accept Invitation"
assert_select "input[type=password]", count: 2
end
test "should redirect with invalid token" do
get invitation_path("invalid_token")
assert_redirected_to root_path
assert_equal "Invalid or expired invitation link.", flash[:alert]
end
test "should redirect with expired token" do
user = users(:pending_invitation)
user.update(invitation_sent_at: 15.days.ago)
get invitation_path(user.invitation_token)
assert_redirected_to root_path
assert_equal "Invalid or expired invitation link.", flash[:alert]
end
test "should accept invitation with valid password" do
user = users(:pending_invitation)
patch accept_invitation_path(user.invitation_token), params: {
user: {
password: "securepassword123",
password_confirmation: "securepassword123"
}
}
user.reload
assert_not_nil user.invitation_accepted_at
assert_nil user.invitation_token
assert_equal user.id, session[:user_id]
assert_redirected_to root_path
end
test "should not accept invitation with short password" do
user = users(:pending_invitation)
patch accept_invitation_path(user.invitation_token), params: {
user: {
password: "short",
password_confirmation: "short"
}
}
user.reload
assert_nil user.invitation_accepted_at
assert_not_nil user.invitation_token
assert_response :unprocessable_entity
end
test "should not accept invitation with mismatched passwords" do
user = users(:pending_invitation)
patch accept_invitation_path(user.invitation_token), params: {
user: {
password: "securepassword123",
password_confirmation: "differentpassword"
}
}
user.reload
assert_nil user.invitation_accepted_at
assert_response :unprocessable_entity
end
test "should not accept expired invitation" do
user = users(:pending_invitation)
user.update(invitation_sent_at: 15.days.ago)
patch accept_invitation_path(user.invitation_token), params: {
user: {
password: "securepassword123",
password_confirmation: "securepassword123"
}
}
assert_redirected_to root_path
assert_equal "Invalid or expired invitation link.", flash[:alert]
end
end
+38
View File
@@ -0,0 +1,38 @@
require "test_helper"
class InvitationMailerTest < ActionMailer::TestCase
test "invite sends email with correct details" do
user = users(:pending_invitation)
mail = InvitationMailer.invite(user)
assert_equal "You've been invited to join Sanasto Wiki", mail.subject
assert_equal [ user.email ], mail.to
assert_match user.name, mail.body.encoded
assert_match user.email, mail.body.encoded
assert_match user.role.titleize, mail.body.encoded
end
test "invite includes invitation link" do
user = users(:pending_invitation)
mail = InvitationMailer.invite(user)
assert_match "invitations/#{user.invitation_token}", mail.body.encoded
end
test "invite includes expiry date" do
user = users(:pending_invitation)
mail = InvitationMailer.invite(user)
expires_at = user.invitation_sent_at + User::INVITATION_TOKEN_EXPIRY
assert_match expires_at.strftime("%B"), mail.body.encoded
end
test "invite has both HTML and text parts" do
user = users(:pending_invitation)
mail = InvitationMailer.invite(user)
assert_equal 2, mail.parts.size
assert_equal "text/plain", mail.text_part.content_type.split(";").first
assert_equal "text/html", mail.html_part.content_type.split(";").first
end
end
@@ -0,0 +1,7 @@
# Preview all emails at http://localhost:3000/rails/mailers/invitation_mailer
class InvitationMailerPreview < ActionMailer::Preview
# Preview this email at http://localhost:3000/rails/mailers/invitation_mailer/invite
def invite
InvitationMailer.invite
end
end