diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3d08f..6752c4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +### Fixed + +- Route generation with :as option (#174) +- Test helper route generation (#174) + ## 1.0.1 ### Fixed diff --git a/app/mailers/passwordless/mailer.rb b/app/mailers/passwordless/mailer.rb index 4ca3fc6..0bbe859 100644 --- a/app/mailers/passwordless/mailer.rb +++ b/app/mailers/passwordless/mailer.rb @@ -12,7 +12,16 @@ class Mailer < Passwordless.config.parent_mailer.constantize # is still in memory (optional) def sign_in(session, token = nil) @token = token || session.token - @magic_link = send(:"confirm_#{session.authenticatable_type.tableize}_sign_in_url", session, token) + @magic_link = url_for( + { + controller: "passwordless/sessions", + action: "confirm", + id: session.id, + token: token, + authenticatable: "user", + resource: "users" + } + ) email_field = session.authenticatable.class.passwordless_email_field mail( diff --git a/lib/passwordless/router_helpers.rb b/lib/passwordless/router_helpers.rb index 8e0ebd7..b734de0 100644 --- a/lib/passwordless/router_helpers.rb +++ b/lib/passwordless/router_helpers.rb @@ -23,14 +23,16 @@ module RouterHelpers # (Default: 'passwordless/sessions') def passwordless_for(resource, at: :na, as: :na, controller: "passwordless/sessions") at == :na && at = "/#{resource.to_s}" - as == :na && as = "#{resource.to_s}_" + as == :na && as = resource.to_s + + as = as.to_s + "_" unless !as || as.to_s.end_with?("_") plural = resource.to_s singular = plural.singularize defaults = { authenticatable: singular, - resource: resource, + resource: resource } scope(defaults: defaults) do diff --git a/lib/passwordless/test_helpers.rb b/lib/passwordless/test_helpers.rb index 6b5a8ab..813034d 100644 --- a/lib/passwordless/test_helpers.rb +++ b/lib/passwordless/test_helpers.rb @@ -1,17 +1,32 @@ module Passwordless module TestHelpers module TestCase - def passwordless_sign_out - delete(Passwordless::Engine.routes.url_helpers.sign_out_path) + def passwordless_sign_out(cls = nil) + cls ||= "User".constantize + dest = url_for( + { + controller: "passwordless/sessions", + action: "destroy", + authenticatable: cls.model_name.singular, + resource: cls.model_name.to_s.tableize + } + ) + delete(dest) follow_redirect! end def passwordless_sign_in(resource) + cls = resource.class session = Passwordless::Session.create!(authenticatable: resource) - magic_link = Passwordless::Engine.routes.url_helpers.send( - :"confirm_#{session.authenticatable_type.tableize}_sign_in_url", - session, - session.token + magic_link = url_for( + { + controller: "passwordless/sessions", + action: "confirm", + id: session.id, + token: session.token, + authenticatable: cls.model_name.singular, + resource: cls.model_name.to_s.tableize + } ) get(magic_link) follow_redirect! @@ -19,16 +34,32 @@ def passwordless_sign_in(resource) end module SystemTestCase - def passwordless_sign_out - visit(Passwordless::Engine.routes.url_helpers.sign_out_path) + def passwordless_sign_out(cls = nil) + cls ||= "User".constantize + visit( + url_for( + { + controller: "passwordless/sessions", + action: "destroy", + authenticatable: cls.model_name.singular, + resource: cls.model_name.to_s.tableize + } + ) + ) end def passwordless_sign_in(resource) + cls = resource.class session = Passwordless::Session.create!(authenticatable: resource) - magic_link = Passwordless::Engine.routes.url_helpers.send( - :"confirm_#{session.authenticatable_type.tableize}_sign_in_url", - session, - session.token + magic_link = url_for( + { + controller: "passwordless/sessions", + action: "confirm", + id: session.id, + token: session.token, + authenticatable: cls.model_name.singular, + resource: cls.model_name.to_s.tableize + } ) visit(magic_link) end diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb index 14ea2e2..82982cc 100644 --- a/test/dummy/config/routes.rb +++ b/test/dummy/config/routes.rb @@ -2,7 +2,8 @@ Rails.application.routes.draw do passwordless_for(:users) - passwordless_for(:admins, controller: 'admin/sessions') + passwordless_for(:admins, controller: "admin/sessions") + passwordless_for(:devs, as: :auth, at: "/") resources(:users) resources(:registrations, only: %i[new create]) diff --git a/test/passwordless/router_helpers_test.rb b/test/passwordless/router_helpers_test.rb index 2602827..bf684be 100644 --- a/test/passwordless/router_helpers_test.rb +++ b/test/passwordless/router_helpers_test.rb @@ -51,6 +51,8 @@ class RouterHelpersTest < ActionDispatch::IntegrationTest {method: :get, path: "/users/sign_out"}, defaults ) + + assert_equal "/users/sign_in", url_helpers.users_sign_in_path end test("map sign in for admin") do @@ -100,7 +102,25 @@ class RouterHelpersTest < ActionDispatch::IntegrationTest {method: :get, path: "/admins/sign_out"}, defaults ) + + assert_equal "/admins/sign_in", url_helpers.admins_sign_in_path end + test(":as option") do + defaults = {authenticatable: "dev", resource: "devs"} + assert_recognizes( + {controller: "passwordless/sessions", action: "new"}.merge(defaults), + {method: :get, path: "/sign_in"}, + defaults + ) + + assert_equal "/sign_in", url_helpers.auth_sign_in_path + end + + private + + def url_helpers + Rails.application.routes.url_helpers + end end end diff --git a/test/passwordless/test_helpers_test.rb b/test/passwordless/test_helpers_test.rb new file mode 100644 index 0000000..85fc16f --- /dev/null +++ b/test/passwordless/test_helpers_test.rb @@ -0,0 +1,82 @@ +require "test_helper" +require "passwordless/test_helpers" + +module Passwordless + class MockTest + include Rails.application.routes.url_helpers + + def initialize + @actions = [] + end + + attr_reader :actions + end + + class MockUnitTest < MockTest + include Passwordless::TestHelpers::TestCase + + def get(*args) + @actions << [:get, args] + end + + def delete(*args) + @actions << [:delete, args] + end + + def follow_redirect! + @actions << [:follow_redirect!] + end + end + + class MockSystemTest < MockTest + include Passwordless::TestHelpers::SystemTestCase + + def visit(*args) + @actions << [:visit, args] + end + end + + class PasswordlessTestHelpersTest < ActiveSupport::TestCase + test("unit test") do + alice = users(:alice) + controller = MockUnitTest.new + + controller.passwordless_sign_in(alice) + + assert 1, Session.count + assert alice, Session.last!.authenticatable + assert_match( + %r{^http://.*/users/sign_in/[a-z0-9]+/[a-z0-9]+}i, + controller.actions.first.last.first + ) + + controller.passwordless_sign_out + + assert_match( + %r{^http://.*/users/sign_out}, + controller.actions[-2].last.first + ) + end + + test("system test") do + alice = users(:alice) + controller = MockSystemTest.new + + controller.passwordless_sign_in(alice) + + assert 1, Session.count + assert alice, Session.last!.authenticatable + assert_match( + %r{^http://.*/users/sign_in/[a-z0-9]+/[a-z0-9]+}i, + controller.actions.last.last.first + ) + + controller.passwordless_sign_out + + assert_match( + %r{^http://.*/users/sign_out}, + controller.actions.last.last.first + ) + end + end +end