diff --git a/test/controllers/errors_controller_test.rb b/test/controllers/errors_controller_test.rb new file mode 100644 index 0000000..e21275e --- /dev/null +++ b/test/controllers/errors_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +class ErrorsControllerTest < ActionController::TestCase + tests ErrorsController + + test "not_found responds with 404 JSON when content-type is JSON" do + @request.headers["Content-Type"] = "application/json" + get :not_found + + assert_response :not_found + body = JSON.parse(response.body) + assert_equal 404, body["code"] + assert_equal "Not found.", body["error_message"] + end + + test "not_found responds with 404 HTML when content-type is not JSON" do + get :not_found + + assert_response :not_found + assert_match(/text\/html/, response.media_type) + end + + test "internal_server_error responds with 500 JSON when content-type is JSON" do + @request.headers["Content-Type"] = "application/json" + get :internal_server_error + + assert_response :internal_server_error + body = JSON.parse(response.body) + assert_equal 500, body["code"] + assert_equal "Internal server error.", body["error_message"] + end + + test "internal_server_error responds with 500 HTML when content-type is not JSON" do + get :internal_server_error + + assert_response :internal_server_error + assert_match(/text\/html/, response.media_type) + end +end diff --git a/test/controllers/shopkeeper_auth/confirmation_results_controller_test.rb b/test/controllers/shopkeeper_auth/confirmation_results_controller_test.rb new file mode 100644 index 0000000..af04e8a --- /dev/null +++ b/test/controllers/shopkeeper_auth/confirmation_results_controller_test.rb @@ -0,0 +1,17 @@ +require "test_helper" + +class ShopkeeperAuth::ConfirmationResultsControllerTest < ActionDispatch::IntegrationTest + test "show renders the success page" do + get shopkeeper_auth_confirmation_result_url + + assert_response :success + assert_match I18n.t("devise_token_auth.confirmations.successfully_confirmed"), response.body + end + + test "show uses the minimal layout" do + get shopkeeper_auth_confirmation_result_url + + assert_response :success + assert_match(/text\/html/, response.media_type) + end +end diff --git a/test/controllers/shopkeeper_auth/reset_passwords_controller_test.rb b/test/controllers/shopkeeper_auth/reset_passwords_controller_test.rb new file mode 100644 index 0000000..a996580 --- /dev/null +++ b/test/controllers/shopkeeper_auth/reset_passwords_controller_test.rb @@ -0,0 +1,25 @@ +require "test_helper" + +class ShopkeeperAuth::ResetPasswordsControllerTest < ActionDispatch::IntegrationTest + test "show renders the success page" do + get shopkeeper_auth_reset_password_url + + assert_response :success + assert_match I18n.t("devise_token_auth.passwords.successfully_updated"), response.body + end + + test "edit renders the password change form with minimum password length" do + get edit_shopkeeper_auth_reset_password_url(reset_password_token: "abc123") + + assert_response :success + assert_match I18n.t("change_your_password"), response.body + assert_match ConfigSettings.minimum_password_length.to_s, response.body + end + + test "edit includes the reset_password_token in the form" do + get edit_shopkeeper_auth_reset_password_url(reset_password_token: "tok-xyz") + + assert_response :success + assert_match "tok-xyz", response.body + end +end diff --git a/test/mailers/shopkeeper/notification_mailer_test.rb b/test/mailers/shopkeeper/notification_mailer_test.rb new file mode 100644 index 0000000..d9fe870 --- /dev/null +++ b/test/mailers/shopkeeper/notification_mailer_test.rb @@ -0,0 +1,67 @@ +require "test_helper" + +class Shopkeeper::NotificationMailerTest < ActionMailer::TestCase + setup do + @shopkeeper = shopkeepers(:one) + @shopkeeper.create_default_account + @account = @shopkeeper.accounts.first + @invitation = AccountsInvitation.create!( + account: @account, + name: "Invited User", + email: "invited@example.com", + member: true, + invited_by: @shopkeeper + ) + end + + test "invited renders the expected subject, recipient, and body" do + mail = Shopkeeper::NotificationMailer.with(accounts_invitation: @invitation).invited + + expected_subject = I18n.t( + "shopkeeper.notification_mailer.invited.subject", + inviter: @shopkeeper.name, + account: @account.name + ) + assert_equal expected_subject, mail.subject + assert_equal [@invitation.email], mail.to + assert_equal [ConfigSettings.email.default_from], mail.from + assert_match @invitation.token, mail.body.encoded + assert_match @account.name, mail.body.encoded + end + + test "confirmation_instructions renders the expected subject, recipient, and body" do + mail = Shopkeeper::NotificationMailer.with( + resource: @shopkeeper, + token: "confirm-token-123", + opts: {redirect_url: "http://example.com/confirm", client_config: "default"} + ).confirmation_instructions + + assert_equal I18n.t("shopkeeper.notification_mailer.confirmation_instructions.subject"), mail.subject + assert_equal [@shopkeeper.email], mail.to + assert_match "confirm-token-123", mail.body.encoded + assert_match @shopkeeper.email, mail.body.encoded + end + + test "confirmation_instructions uses opts[:to] when provided" do + mail = Shopkeeper::NotificationMailer.with( + resource: @shopkeeper, + token: "tok", + opts: {to: "override@example.com", redirect_url: "http://example.com/confirm", client_config: "default"} + ).confirmation_instructions + + assert_equal ["override@example.com"], mail.to + assert_match "override@example.com", mail.body.encoded + end + + test "reset_password_instructions renders the expected subject, recipient, and body" do + mail = Shopkeeper::NotificationMailer.with( + resource: @shopkeeper, + token: "reset-token-xyz", + opts: {redirect_url: "http://example.com/reset", client_config: "default"} + ).reset_password_instructions + + assert_equal I18n.t("shopkeeper.notification_mailer.reset_password_instructions.subject"), mail.subject + assert_equal [@shopkeeper.email], mail.to + assert_match "reset-token-xyz", mail.body.encoded + end +end diff --git a/test/mailers/shopkeeper_mailer_test.rb b/test/mailers/shopkeeper_mailer_test.rb new file mode 100644 index 0000000..afe40a3 --- /dev/null +++ b/test/mailers/shopkeeper_mailer_test.rb @@ -0,0 +1,15 @@ +require "test_helper" + +class ShopkeeperMailerTest < ActionMailer::TestCase + test "inherits from ApplicationMailer" do + assert_operator ShopkeeperMailer, :<, ApplicationMailer + end + + test "uses the application default_from address" do + assert_equal ConfigSettings.email.default_from_with_name, ShopkeeperMailer.default[:from] + end + + test "uses the mailer layout" do + assert_equal "mailer", ShopkeeperMailer._layout + end +end diff --git a/test/models/admin_user_test.rb b/test/models/admin_user_test.rb new file mode 100644 index 0000000..db8f030 --- /dev/null +++ b/test/models/admin_user_test.rb @@ -0,0 +1,51 @@ +require "test_helper" + +class AdminUserTest < ActiveSupport::TestCase + def valid_attributes + { + name: "Admin", + email: "admin@example.com", + password: "password" + } + end + + test "should be valid with valid attributes" do + admin_user = AdminUser.new(valid_attributes) + assert admin_user.valid? + end + + test "should require email" do + admin_user = AdminUser.new(valid_attributes.merge(email: nil)) + assert_not admin_user.valid? + assert_includes admin_user.errors[:email], "can't be blank" + end + + test "should require unique email" do + AdminUser.create!(valid_attributes) + duplicate = AdminUser.new(valid_attributes) + assert_not duplicate.valid? + assert_includes duplicate.errors[:email], "has already been taken" + end + + test "should reject invalid email format" do + admin_user = AdminUser.new(valid_attributes.merge(email: "not-an-email")) + assert_not admin_user.valid? + assert_not_empty admin_user.errors[:email] + end + + test "should hash password using has_secure_password" do + admin_user = AdminUser.create!(valid_attributes) + assert_not_nil admin_user.password_digest + assert_not_equal "password", admin_user.password_digest + end + + test "authenticate returns admin_user when password matches" do + admin_user = AdminUser.create!(valid_attributes) + assert_equal admin_user, admin_user.authenticate("password") + end + + test "authenticate returns false when password does not match" do + admin_user = AdminUser.create!(valid_attributes) + assert_equal false, admin_user.authenticate("wrong-password") + end +end