test: cover MailerUrlForTest, welcome and MessageEncryptorTest
This commit is contained in:
1 parent
e1ef112db8
commit
9445c0b35f
2 files changed
+145
No files matched your search
@@ -0,0 +1,86 @@
|
||||
require 'minitest/autorun'
|
||||
require 'prism'
|
||||
require 'tmpdir'
|
||||
require 'fileutils'
|
||||
|
||||
class MailerUrlForTest < Minitest::Test
|
||||
def setup
|
||||
@dir = Dir.mktmpdir('prism-mailer-url-for')
|
||||
FileUtils.mkdir_p(File.join(@dir, 'url_for'))
|
||||
write('url_for/welcome.text.erb', "Click here: <%= url_for(:confirmation, id: user_id) %>\n")
|
||||
|
||||
@router = Prism::Router.new
|
||||
@router.add('get', '/confirmations/:id', name: :confirmation)
|
||||
|
||||
mailer_dir = @dir
|
||||
@mailer_class = Class.new(Prism::Mailer::Base) do
|
||||
self.template_roots = [mailer_dir]
|
||||
|
||||
def welcome(user_id)
|
||||
@user_id = user_id
|
||||
mail(to: 'someone@example.com', subject: 'Welcome!')
|
||||
end
|
||||
end
|
||||
Object.const_set(:UrlForMailer, @mailer_class)
|
||||
end
|
||||
|
||||
def teardown
|
||||
Object.send(:remove_const, :UrlForMailer) if Object.const_defined?(:UrlForMailer)
|
||||
FileUtils.remove_entry(@dir)
|
||||
Prism::Mailer.router = nil
|
||||
Prism::Mailer.default_url_options = nil
|
||||
end
|
||||
|
||||
def write(relative, source)
|
||||
File.write(File.join(@dir, relative), source)
|
||||
end
|
||||
|
||||
def test_url_for_raises_without_a_configured_router
|
||||
Prism::Mailer.router = nil
|
||||
error = assert_raises(RuntimeError) { UrlForMailer.welcome(42) }
|
||||
assert_match(/no router configured/, error.message)
|
||||
end
|
||||
|
||||
def test_url_for_raises_without_a_host
|
||||
Prism::Mailer.router = @router
|
||||
error = assert_raises(ArgumentError) { UrlForMailer.welcome(42) }
|
||||
assert_match(/:host/, error.message)
|
||||
end
|
||||
|
||||
def test_url_for_builds_an_absolute_url_from_global_default_url_options
|
||||
Prism::Mailer.router = @router
|
||||
Prism::Mailer.default_url_options = { host: 'example.com' }
|
||||
|
||||
body = UrlForMailer.welcome(42).message.text_body
|
||||
assert_equal "Click here: http://example.com/confirmations/42\n", body
|
||||
end
|
||||
|
||||
def test_per_mailer_class_default_url_options_win_over_the_global_ones
|
||||
Prism::Mailer.router = @router
|
||||
Prism::Mailer.default_url_options = { host: 'example.com', protocol: 'http' }
|
||||
UrlForMailer.default_url_options(host: 'mail.example.com', protocol: 'https')
|
||||
|
||||
body = UrlForMailer.welcome(42).message.text_body
|
||||
assert_equal "Click here: https://mail.example.com/confirmations/42\n", body
|
||||
end
|
||||
|
||||
def test_port_is_included_when_given
|
||||
Prism::Mailer.router = @router
|
||||
Prism::Mailer.default_url_options = { host: 'example.com', port: 3000 }
|
||||
|
||||
body = UrlForMailer.welcome(42).message.text_body
|
||||
assert_equal "Click here: http://example.com:3000/confirmations/42\n", body
|
||||
end
|
||||
|
||||
def test_application_enable_mailer_wires_router_and_default_url_options
|
||||
app_class = Class.new(Prism::Application)
|
||||
app_class.router.add('get', '/confirmations/:id', name: :confirmation)
|
||||
app_class.enable_mailer(host: 'app.example.com', protocol: 'https')
|
||||
|
||||
assert_same app_class.router, Prism::Mailer.router
|
||||
assert_equal({ host: 'app.example.com', protocol: 'https' }, Prism::Mailer.default_url_options)
|
||||
|
||||
body = UrlForMailer.welcome(7).message.text_body
|
||||
assert_equal "Click here: https://app.example.com/confirmations/7\n", body
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
require 'minitest/autorun'
|
||||
require 'prism'
|
||||
|
||||
class MessageEncryptorTest < Minitest::Test
|
||||
def setup
|
||||
@key = Prism::MessageEncryptor.derive_key('super-secret-app-key')
|
||||
@encryptor = Prism::MessageEncryptor.new(@key)
|
||||
end
|
||||
|
||||
def test_derived_key_has_correct_length
|
||||
assert_equal 32, @key.bytesize
|
||||
end
|
||||
|
||||
def test_derive_key_is_deterministic_for_same_secret_and_salt
|
||||
assert_equal @key, Prism::MessageEncryptor.derive_key('super-secret-app-key')
|
||||
end
|
||||
|
||||
def test_derive_key_differs_per_salt
|
||||
other = Prism::MessageEncryptor.derive_key('super-secret-app-key', salt: 'other-salt')
|
||||
refute_equal @key, other
|
||||
end
|
||||
|
||||
def test_round_trips_a_hash
|
||||
token = @encryptor.encrypt_and_sign('admin' => true, 'user_id' => 7)
|
||||
assert_equal({ 'admin' => true, 'user_id' => 7 }, @encryptor.decrypt_and_verify(token))
|
||||
end
|
||||
|
||||
def test_ciphertext_does_not_contain_plaintext
|
||||
token = @encryptor.encrypt_and_sign('super-secret-value-xyz')
|
||||
refute_includes token, 'super-secret-value-xyz'
|
||||
end
|
||||
|
||||
def test_two_encryptions_of_same_value_differ
|
||||
first = @encryptor.encrypt_and_sign('same value')
|
||||
second = @encryptor.encrypt_and_sign('same value')
|
||||
refute_equal first, second
|
||||
end
|
||||
|
||||
def test_tampered_ciphertext_fails_to_decrypt
|
||||
token = @encryptor.encrypt_and_sign('user_id' => 1)
|
||||
encrypted, iv, tag = token.split('--', 3)
|
||||
tampered = "#{encrypted}AA--#{iv}--#{tag}"
|
||||
assert_raises(Prism::MessageEncryptor::InvalidMessage) { @encryptor.decrypt_and_verify(tampered) }
|
||||
end
|
||||
|
||||
def test_wrong_key_cannot_decrypt
|
||||
token = @encryptor.encrypt_and_sign('user_id' => 1)
|
||||
other = Prism::MessageEncryptor.new(Prism::MessageEncryptor.derive_key('a-completely-different-key'))
|
||||
assert_raises(Prism::MessageEncryptor::InvalidMessage) { other.decrypt_and_verify(token) }
|
||||
end
|
||||
|
||||
def test_malformed_message_raises
|
||||
assert_raises(Prism::MessageEncryptor::InvalidMessage) { @encryptor.decrypt_and_verify('garbage') }
|
||||
end
|
||||
|
||||
def test_rejects_key_of_wrong_length
|
||||
assert_raises(ArgumentError) { Prism::MessageEncryptor.new('too-short') }
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user