96.99% test coverage
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
require "application_system_test_case"
|
||||
|
||||
class AdminWorkflowTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
@admin = users(:admin_user)
|
||||
@admin.update!(invitation_accepted_at: Time.current)
|
||||
end
|
||||
|
||||
test "admin can access dashboard" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
assert_text "Dashboard"
|
||||
assert_text "Total Users"
|
||||
assert_text "Total Entries"
|
||||
end
|
||||
|
||||
test "admin sees admin button in header" do
|
||||
login_as(@admin)
|
||||
visit root_path
|
||||
|
||||
within "header" do
|
||||
assert_link "Admin"
|
||||
end
|
||||
end
|
||||
|
||||
test "admin can send invitation" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_invitations_path
|
||||
click_link "Send New Invitation"
|
||||
|
||||
assert_current_path new_admin_invitation_path
|
||||
|
||||
fill_in "Name", with: "New User"
|
||||
fill_in "Email", with: "newuser@example.com"
|
||||
select "Contributor", from: "Role"
|
||||
|
||||
click_button "Send Invitation"
|
||||
|
||||
assert_current_path admin_invitations_path
|
||||
assert_text "Invitation sent"
|
||||
assert_text "newuser@example.com"
|
||||
end
|
||||
|
||||
test "admin can view users list" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_users_path
|
||||
|
||||
assert_text "Users"
|
||||
assert_selector "table"
|
||||
assert_text @admin.email
|
||||
end
|
||||
|
||||
test "admin can edit user role" do
|
||||
user = users(:contributor_user)
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_users_path
|
||||
within "#user_#{user.id}" do
|
||||
click_link "Edit"
|
||||
end
|
||||
|
||||
assert_current_path edit_admin_user_path(user)
|
||||
|
||||
select "Reviewer", from: "Role"
|
||||
click_button "Update User"
|
||||
|
||||
assert_current_path admin_users_path
|
||||
assert_text "User updated"
|
||||
|
||||
user.reload
|
||||
assert_equal "reviewer", user.role
|
||||
end
|
||||
|
||||
test "admin can delete user" do
|
||||
user = users(:contributor_user)
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_users_path
|
||||
|
||||
within "#user_#{user.id}" do
|
||||
click_button "Delete"
|
||||
end
|
||||
|
||||
assert_current_path admin_users_path
|
||||
assert_text "User deleted"
|
||||
assert_no_text user.email
|
||||
end
|
||||
|
||||
test "admin can view entry requests" do
|
||||
requested_entry = Entry.create!(
|
||||
fi: "Requested Entry",
|
||||
category: :word,
|
||||
status: :requested,
|
||||
requested_by: users(:contributor_user)
|
||||
)
|
||||
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_requests_path
|
||||
|
||||
assert_text "Requested Entry"
|
||||
assert_link "View"
|
||||
assert_link "Edit"
|
||||
assert_button "Approve"
|
||||
end
|
||||
|
||||
test "admin can approve entry request" do
|
||||
requester = users(:contributor_user)
|
||||
requested_entry = Entry.create!(
|
||||
fi: "Requested Entry",
|
||||
category: :word,
|
||||
status: :requested,
|
||||
requested_by: requester
|
||||
)
|
||||
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_requests_path
|
||||
|
||||
within "#entry_#{requested_entry.id}" do
|
||||
click_button "Approve"
|
||||
end
|
||||
|
||||
assert_current_path admin_requests_path
|
||||
assert_text "approved"
|
||||
|
||||
requested_entry.reload
|
||||
assert_equal "approved", requested_entry.status
|
||||
end
|
||||
|
||||
test "admin can edit entry request before approval" do
|
||||
requested_entry = Entry.create!(
|
||||
fi: "Requested Entry",
|
||||
category: :word,
|
||||
status: :requested,
|
||||
requested_by: users(:contributor_user)
|
||||
)
|
||||
|
||||
login_as(@admin)
|
||||
|
||||
visit edit_admin_request_path(requested_entry)
|
||||
|
||||
fill_in "Finnish", with: "Edited Finnish"
|
||||
fill_in "English", with: "Added English"
|
||||
click_button "Save Changes"
|
||||
|
||||
assert_current_path admin_requests_path
|
||||
requested_entry.reload
|
||||
assert_equal "Edited Finnish", requested_entry.fi
|
||||
assert_equal "Added English", requested_entry.en
|
||||
end
|
||||
|
||||
test "admin can reject entry request" do
|
||||
requested_entry = Entry.create!(
|
||||
fi: "Requested Entry",
|
||||
category: :word,
|
||||
status: :requested,
|
||||
requested_by: users(:contributor_user)
|
||||
)
|
||||
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_requests_path
|
||||
|
||||
within "#entry_#{requested_entry.id}" do
|
||||
click_button "Reject"
|
||||
end
|
||||
|
||||
assert_current_path admin_requests_path
|
||||
assert_text "rejected"
|
||||
assert_nil Entry.find_by(id: requested_entry.id)
|
||||
end
|
||||
|
||||
test "admin can resend invitation" do
|
||||
pending_user = users(:pending_invitation)
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_invitations_path
|
||||
|
||||
within "#invitation_#{pending_user.id}" do
|
||||
click_button "Resend"
|
||||
end
|
||||
|
||||
assert_current_path admin_invitations_path
|
||||
assert_text "Invitation resent"
|
||||
end
|
||||
|
||||
test "admin can cancel invitation" do
|
||||
pending_user = users(:pending_invitation)
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_invitations_path
|
||||
|
||||
within "#invitation_#{pending_user.id}" do
|
||||
click_button "Cancel"
|
||||
end
|
||||
|
||||
assert_current_path admin_invitations_path
|
||||
assert_text "deleted"
|
||||
assert_nil User.find_by(id: pending_user.id)
|
||||
end
|
||||
|
||||
test "admin sees request count badge" do
|
||||
Entry.create!(
|
||||
fi: "Requested Entry 1",
|
||||
category: :word,
|
||||
status: :requested,
|
||||
requested_by: users(:contributor_user)
|
||||
)
|
||||
Entry.create!(
|
||||
fi: "Requested Entry 2",
|
||||
category: :word,
|
||||
status: :requested,
|
||||
requested_by: users(:contributor_user)
|
||||
)
|
||||
|
||||
login_as(@admin)
|
||||
visit admin_root_path
|
||||
|
||||
within "header" do
|
||||
assert_text "2"
|
||||
end
|
||||
end
|
||||
|
||||
test "admin navigation is responsive" do
|
||||
login_as(@admin)
|
||||
visit admin_root_path
|
||||
|
||||
# Test mobile menu if visible
|
||||
if page.has_selector?("#admin-mobile-menu-button", visible: true)
|
||||
click_button id: "admin-mobile-menu-button"
|
||||
assert_selector "#admin-mobile-menu", visible: true
|
||||
assert_link "Dashboard"
|
||||
assert_link "Users"
|
||||
assert_link "Invitations"
|
||||
end
|
||||
end
|
||||
|
||||
test "admin cannot delete themselves" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_users_path
|
||||
|
||||
within "#user_#{@admin.id}" do
|
||||
click_button "Delete"
|
||||
end
|
||||
|
||||
assert_text "cannot delete yourself"
|
||||
assert User.exists?(@admin.id)
|
||||
end
|
||||
|
||||
test "admin can view dashboard statistics" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_dashboard_path
|
||||
|
||||
assert_text "Total Users"
|
||||
assert_text "Total Entries"
|
||||
assert_text "Pending Invitations"
|
||||
assert_text "Entry Requests"
|
||||
end
|
||||
|
||||
test "admin can navigate between admin sections" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
click_link "Users"
|
||||
assert_current_path admin_users_path
|
||||
|
||||
click_link "Invitations"
|
||||
assert_current_path admin_invitations_path
|
||||
|
||||
click_link "Requests"
|
||||
assert_current_path admin_requests_path
|
||||
|
||||
click_link "Dashboard"
|
||||
assert_current_path admin_dashboard_path
|
||||
end
|
||||
|
||||
test "admin can return to main site from admin" do
|
||||
login_as(@admin)
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
# On mobile, click hamburger menu first
|
||||
if page.has_selector?("#admin-mobile-menu-button", visible: true)
|
||||
click_button id: "admin-mobile-menu-button"
|
||||
end
|
||||
|
||||
click_link "Back to Site"
|
||||
|
||||
assert_current_path root_path
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,185 @@
|
||||
require "application_system_test_case"
|
||||
|
||||
class ContributorWorkflowTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
@contributor = users(:contributor_user)
|
||||
@contributor.update!(invitation_accepted_at: Time.current)
|
||||
end
|
||||
|
||||
test "contributor can sign in" do
|
||||
visit login_path
|
||||
|
||||
fill_in "Email", with: @contributor.email
|
||||
fill_in "Password", with: "password123456"
|
||||
click_button "Sign In"
|
||||
|
||||
assert_text "Welcome back"
|
||||
within "header" do
|
||||
assert_text @contributor.name.split.first
|
||||
end
|
||||
end
|
||||
|
||||
test "contributor can edit entry" do
|
||||
entry = entries(:one)
|
||||
login_as(@contributor)
|
||||
|
||||
visit entry_path(entry)
|
||||
click_link "Edit"
|
||||
|
||||
assert_current_path edit_entry_path(entry)
|
||||
|
||||
fill_in "Finnish", with: "Updated Finnish Text"
|
||||
fill_in "English", with: "Updated English Text"
|
||||
select "Phrase", from: "Category"
|
||||
fill_in "Additional Notes", with: "Updated notes"
|
||||
|
||||
click_button "Save Changes"
|
||||
|
||||
assert_current_path entry_path(entry)
|
||||
assert_text "Entry updated"
|
||||
assert_text "Updated Finnish Text"
|
||||
assert_text "Updated English Text"
|
||||
end
|
||||
|
||||
test "contributor can add comment to entry" do
|
||||
entry = entries(:one)
|
||||
login_as(@contributor)
|
||||
|
||||
visit entry_path(entry)
|
||||
|
||||
click_button "Add Comment"
|
||||
|
||||
within "#comment_form_modal" do
|
||||
select "Finnish (FI)", from: "Language"
|
||||
fill_in "Comment", with: "This is my comment on the Finnish translation"
|
||||
click_button "Submit"
|
||||
end
|
||||
|
||||
assert_text "This is my comment on the Finnish translation"
|
||||
assert_text @contributor.name
|
||||
end
|
||||
|
||||
test "contributor sees signed in status in header" do
|
||||
login_as(@contributor)
|
||||
visit root_path
|
||||
|
||||
within "header" do
|
||||
assert_text @contributor.name.split.first
|
||||
assert_button "Sign Out", visible: :all
|
||||
end
|
||||
end
|
||||
|
||||
test "contributor can sign out" do
|
||||
login_as(@contributor)
|
||||
visit root_path
|
||||
|
||||
# On mobile, click hamburger menu first
|
||||
if page.has_selector?("#mobile-menu-button", visible: true)
|
||||
click_button id: "mobile-menu-button"
|
||||
end
|
||||
|
||||
click_link "Sign Out"
|
||||
|
||||
assert_current_path root_path
|
||||
assert_text "You have been logged out"
|
||||
within "header" do
|
||||
assert_link "Sign In"
|
||||
end
|
||||
end
|
||||
|
||||
test "contributor cannot access admin pages" do
|
||||
login_as(@contributor)
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
assert_current_path root_path
|
||||
assert_text "administrator"
|
||||
end
|
||||
|
||||
test "contributor can request password reset" do
|
||||
visit login_path
|
||||
|
||||
click_link "Forgot password?"
|
||||
|
||||
assert_current_path new_password_reset_path
|
||||
|
||||
fill_in "Email", with: @contributor.email
|
||||
click_button "Send Reset Instructions"
|
||||
|
||||
assert_current_path login_path
|
||||
assert_text "password reset instructions"
|
||||
end
|
||||
|
||||
test "contributor session persists across page loads" do
|
||||
login_as(@contributor)
|
||||
|
||||
visit root_path
|
||||
assert_text @contributor.name.split.first
|
||||
|
||||
visit entries_path
|
||||
within "header" do
|
||||
assert_text @contributor.name.split.first
|
||||
end
|
||||
end
|
||||
|
||||
test "contributor can use remember me" do
|
||||
visit login_path
|
||||
|
||||
fill_in "Email", with: @contributor.email
|
||||
fill_in "Password", with: "password123456"
|
||||
check "Remember me for 2 weeks"
|
||||
click_button "Sign In"
|
||||
|
||||
assert_text "Welcome back"
|
||||
end
|
||||
|
||||
test "contributor sees validation errors when editing entry incorrectly" do
|
||||
entry = entries(:one)
|
||||
login_as(@contributor)
|
||||
|
||||
visit edit_entry_path(entry)
|
||||
|
||||
# Clear all translations (should fail validation)
|
||||
fill_in "Finnish", with: ""
|
||||
fill_in "English", with: ""
|
||||
fill_in "Swedish", with: ""
|
||||
fill_in "Norwegian", with: ""
|
||||
fill_in "Russian", with: ""
|
||||
fill_in "German", with: ""
|
||||
|
||||
click_button "Save Changes"
|
||||
|
||||
assert_text "At least one language translation is required"
|
||||
end
|
||||
|
||||
test "contributor can filter comments by language tab" do
|
||||
entry = entries(:one)
|
||||
login_as(@contributor)
|
||||
|
||||
# Create comments in different languages
|
||||
Comment.create!(
|
||||
commentable: entry,
|
||||
user: @contributor,
|
||||
body: "Finnish comment",
|
||||
language_code: "fi"
|
||||
)
|
||||
Comment.create!(
|
||||
commentable: entry,
|
||||
user: @contributor,
|
||||
body: "English comment",
|
||||
language_code: "en"
|
||||
)
|
||||
|
||||
visit entry_path(entry)
|
||||
|
||||
click_link "Finnish"
|
||||
assert_text "Finnish comment"
|
||||
|
||||
click_link "English"
|
||||
assert_text "English comment"
|
||||
|
||||
click_link "All languages"
|
||||
assert_text "Finnish comment"
|
||||
assert_text "English comment"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,114 @@
|
||||
require "application_system_test_case"
|
||||
|
||||
class PublicBrowsingTest < ApplicationSystemTestCase
|
||||
test "visitor can browse entries without logging in" do
|
||||
visit root_path
|
||||
|
||||
assert_selector "h1", text: "Sanasto Wiki"
|
||||
assert_selector ".entry-row", minimum: 1
|
||||
end
|
||||
|
||||
test "visitor can search entries" do
|
||||
entry = entries(:one)
|
||||
visit root_path
|
||||
|
||||
fill_in "q", with: entry.fi
|
||||
click_button "Search"
|
||||
|
||||
assert_text entry.fi
|
||||
end
|
||||
|
||||
test "visitor can filter by language" do
|
||||
visit root_path
|
||||
|
||||
click_button "Finnish"
|
||||
|
||||
assert_current_path entries_path(language: "fi")
|
||||
end
|
||||
|
||||
test "visitor can filter by category" do
|
||||
visit root_path
|
||||
|
||||
select "Word", from: "category"
|
||||
|
||||
assert_current_path entries_path(category: "word")
|
||||
end
|
||||
|
||||
test "visitor can view entry details" do
|
||||
entry = entries(:one)
|
||||
visit root_path
|
||||
|
||||
click_link entry.fi
|
||||
|
||||
assert_text entry.fi
|
||||
assert_text entry.en if entry.en.present?
|
||||
end
|
||||
|
||||
test "visitor can browse alphabetically" do
|
||||
visit root_path
|
||||
|
||||
click_button "Finnish"
|
||||
click_link "A"
|
||||
|
||||
assert_current_path entries_path(language: "fi", starts_with: "a")
|
||||
end
|
||||
|
||||
test "visitor can download XLSX" do
|
||||
visit root_path
|
||||
|
||||
click_link "Download XLSX"
|
||||
|
||||
assert_equal "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
page.response_headers["Content-Type"]
|
||||
end
|
||||
|
||||
test "visitor sees sign in link in header" do
|
||||
visit root_path
|
||||
|
||||
within "header" do
|
||||
assert_link "Sign In"
|
||||
end
|
||||
end
|
||||
|
||||
test "visitor can request new entry" do
|
||||
visit root_path
|
||||
|
||||
click_link "Request Entry"
|
||||
|
||||
assert_current_path new_request_path
|
||||
assert_field "Name"
|
||||
assert_field "Email"
|
||||
end
|
||||
|
||||
test "search results show no results message when nothing matches" do
|
||||
visit root_path
|
||||
|
||||
fill_in "q", with: "nonexistentword12345xyz"
|
||||
click_button "Search"
|
||||
|
||||
assert_text "No entries matched your filters"
|
||||
end
|
||||
|
||||
test "visitor can paginate through results" do
|
||||
# Create enough entries to require pagination
|
||||
26.times do |i|
|
||||
Entry.create!(
|
||||
fi: "Test Entry #{i}",
|
||||
category: :word,
|
||||
status: :active
|
||||
)
|
||||
end
|
||||
|
||||
visit root_path
|
||||
|
||||
assert_selector ".entry-row", count: 25
|
||||
assert_link "2"
|
||||
end
|
||||
|
||||
test "visitor sees entry statistics" do
|
||||
visit root_path
|
||||
|
||||
assert_text "Total Entries"
|
||||
assert_text "Verified"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user