Add mailer specs #336

Merged
merged 3 commits into from Nov 14, 2012
Jump to file
+188 −139
Split
View
24 lib/draper.rb
@@ -1,7 +1,6 @@
require 'action_view'
require 'draper/version'
-require 'draper/system'
require 'draper/view_helpers'
require 'draper/finders'
require 'draper/decorator'
@@ -20,6 +19,29 @@
require 'draper/test/minitest_integration' if defined?(MiniTest::Rails)
module Draper
+ def self.setup_action_controller(base)
+ base.class_eval do
+ include Draper::ViewContext
+ extend Draper::HelperSupport
+ before_filter ->(controller) {
+ Draper::ViewContext.current = nil
+ Draper::ViewContext.current_controller = controller
+ }
+ end
+ end
+
+ def self.setup_action_mailer(base)
+ base.class_eval do
+ include Draper::ViewContext
+ end
+ end
+
+ def self.setup_active_record(base)
+ base.class_eval do
+ include Draper::Decoratable
+ end
+ end
+
class UninferrableDecoratorError < NameError
def initialize(klass)
super("Could not infer a decorator for #{klass}.")
View
6 lib/draper/railtie.rb
@@ -24,19 +24,19 @@ class Railtie < Rails::Railtie
initializer "draper.extend_action_controller_base" do |app|
ActiveSupport.on_load(:action_controller) do
- Draper::System.setup_action_controller(self)
+ Draper.setup_action_controller(self)
end
end
initializer "draper.extend_action_mailer_base" do |app|
ActiveSupport.on_load(:action_mailer) do
- Draper::System.setup_action_mailer(self)
+ Draper.setup_action_mailer(self)
end
end
initializer "draper.extend_active_record_base" do |app|
ActiveSupport.on_load(:active_record) do
- self.send(:include, Draper::Decoratable)
+ Draper.setup_active_record(self)
end
end
View
8 lib/draper/security.rb
@@ -6,19 +6,19 @@ def initialize
end
def denies(*methods)
- raise ArgumentError, "Specify at least one method (as a symbol) to exclude when using denies" if methods.empty?
+ raise ArgumentError, "Specify at least one method to blacklist when using denies" if methods.empty?
self.strategy = :denies
- @denied += methods
+ @denied += methods.map(&:to_sym)
end
def denies_all
self.strategy = :denies_all
end
def allows(*methods)
- raise ArgumentError, "Specify at least one method (as a symbol) to allow when using allows" if methods.empty?
+ raise ArgumentError, "Specify at least one method to whitelist when using allows" if methods.empty?
self.strategy = :allows
- @allowed += methods
+ @allowed += methods.map(&:to_sym)
end
def allow?(method)
View
20 lib/draper/system.rb
@@ -1,20 +0,0 @@
-module Draper
- class System
- def self.setup_action_controller(component)
- component.class_eval do
- include Draper::ViewContext
- extend Draper::HelperSupport
- before_filter lambda {|controller|
- Draper::ViewContext.current = nil
- Draper::ViewContext.current_controller = controller
- }
- end
- end
-
- def self.setup_action_mailer(component)
- component.class_eval do
- include Draper::ViewContext
- end
- end
- end
-end
View
56 spec/draper/security_spec.rb
@@ -1,11 +1,17 @@
require 'spec_helper'
+RSpec::Matchers.define :allow do |method|
+ match do |subject|
+ subject.allow?(method)
+ end
+end
+
describe Draper::Security do
subject(:security) { Draper::Security.new }
context "when newly initialized" do
it "allows any method" do
- security.allow?(:foo).should be_true
+ security.should allow :foo
end
end
@@ -19,12 +25,12 @@
before { security.denies :foo, :bar }
it "denies the listed methods" do
- security.allow?(:foo).should be_false
- security.allow?(:bar).should be_false
+ security.should_not allow :foo
+ security.should_not allow :bar
end
it "allows other methods" do
- security.allow?(:baz).should be_true
+ security.should allow :baz
end
it "accepts multiple denies" do
@@ -43,16 +49,24 @@
before { security.denies :baz }
it "still denies the original methods" do
- security.allow?(:foo).should be_false
- security.allow?(:bar).should be_false
+ security.should_not allow :foo
+ security.should_not allow :bar
end
it "denies the additional methods" do
- security.allow?(:baz).should be_false
+ security.should_not allow :baz
end
it "allows other methods" do
- security.allow?(:qux).should be_true
+ security.should allow :qux
+ end
+ end
+
+ context "with strings" do
+ before { security.denies "baz" }
+
+ it "denies the method" do
+ security.should_not allow :baz
end
end
end
@@ -61,7 +75,7 @@
before { security.denies_all }
it "denies all methods" do
- security.allow?(:foo).should be_false
+ security.should_not allow :foo
end
it "accepts multiple denies_all" do
@@ -80,7 +94,7 @@
before { security.denies_all }
it "still denies all methods" do
- security.allow?(:foo).should be_false
+ security.should_not allow :foo
end
end
end
@@ -95,12 +109,12 @@
before { security.allows :foo, :bar }
it "allows the listed methods" do
- security.allow?(:foo).should be_true
- security.allow?(:bar).should be_true
+ security.should allow :foo
+ security.should allow :bar
end
it "denies other methods" do
- security.allow?(:baz).should be_false
+ security.should_not allow :baz
end
it "accepts multiple allows" do
@@ -119,16 +133,24 @@
before { security.allows :baz }
it "still allows the original methods" do
- security.allow?(:foo).should be_true
- security.allow?(:bar).should be_true
+ security.should allow :foo
+ security.should allow :bar
end
it "allows the additional methods" do
- security.allow?(:baz).should be_true
+ security.should allow :baz
end
it "denies other methods" do
- security.allow?(:qux).should be_false
+ security.should_not allow :qux
+ end
+ end
+
+ context "with strings" do
+ before { security.allows "baz" }
+
+ it "allows the method" do
+ security.should allow :baz
end
end
end
View
13 spec/dummy/app/assets/javascripts/application.js
@@ -1,13 +0,0 @@
-// This is a manifest file that'll be compiled into application.js, which will include all the files
-// listed below.
-//
-// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
-// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
-//
-// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
-// the compiled file.
-//
-// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
-// GO AFTER THE REQUIRES BELOW.
-//
-//= require_tree .
View
13 spec/dummy/app/assets/stylesheets/application.css
@@ -1,13 +0,0 @@
-/*
- * This is a manifest file that'll be compiled into application.css, which will include all the files
- * listed below.
- *
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
- * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
- *
- * You're free to add application-wide styles to this file and they'll appear at the top of the
- * compiled file, but it's generally better to create a new file per style scope.
- *
- *= require_self
- *= require_tree .
- */
View
5 spec/dummy/app/controllers/application_controller.rb
@@ -1,7 +1,4 @@
class ApplicationController < ActionController::Base
+ include LocalizedUrls
protect_from_forgery
-
- def default_url_options(options = {})
- {locale: I18n.locale, host: "www.example.com", port: nil}
- end
end
View
5 spec/dummy/app/controllers/localized_urls.rb
@@ -0,0 +1,5 @@
+module LocalizedUrls
+ def default_url_options(options = {})
+ {locale: I18n.locale, host: "www.example.com", port: nil}
+ end
+end
View
12 spec/dummy/app/controllers/posts_controller.rb
@@ -1,5 +1,17 @@
class PostsController < ApplicationController
def show
+ fetch_post
+ end
+
+ def mail
+ fetch_post
+ email = PostMailer.decorated_email(@post).deliver
+ render text: email.body
+ end
+
+ private
+
+ def fetch_post
@post = Post.find(params[:id]).decorate
end
end
View
0 spec/dummy/app/mailers/.gitkeep
No changes.
View
3 spec/dummy/app/mailers/application_mailer.rb
@@ -0,0 +1,3 @@
+class ApplicationMailer < ActionMailer::Base
+ include LocalizedUrls
+end
View
9 spec/dummy/app/mailers/post_mailer.rb
@@ -0,0 +1,9 @@
+class PostMailer < ApplicationMailer
+ default from: "from@example.com"
+ layout "application"
+
+ def decorated_email(post)
+ @post = post.decorate
+ mail to: "to@example.com", subject: "A decorated post"
+ end
+end
View
0 spec/dummy/app/models/.gitkeep
No changes.
View
3 spec/dummy/app/views/layouts/application.html.erb
@@ -2,9 +2,6 @@
<html>
<head>
<title>Dummy</title>
- <%= stylesheet_link_tag "application", :media => "all" %>
- <%= javascript_include_tag "application" %>
- <%= csrf_meta_tags %>
</head>
<body>
View
1 spec/dummy/app/views/post_mailer/decorated_email.html.erb
@@ -0,0 +1 @@
+<%= render @post %>
View
19 spec/dummy/app/views/posts/_post.html.erb
@@ -0,0 +1,19 @@
+<dl>
+ <dt>Environment:</dt>
+ <dd id="environment"><%= Rails.env %></dd>
+
+ <dt>Posted:</dt>
+ <dd id="posted_date"><%= post.posted_date %></dd>
+
+ <dt>Path with model:</dt>
+ <dd id="path_with_model"><%= post.path_with_model %></dd>
+
+ <dt>Path with id:</dt>
+ <dd id="path_with_id"><%= post.path_with_id %></dd>
+
+ <dt>URL with model:</dt>
+ <dd id="url_with_model"><%= post.url_with_model %></dd>
+
+ <dt>URL with id:</dt>
+ <dd id="url_with_id"><%= post.url_with_id %></dd>
+</dl>
View
20 spec/dummy/app/views/posts/show.html.erb
@@ -1,19 +1 @@
-<dl>
- <dt>Environment:</dt>
- <dd id="environment"><%= Rails.env %></dd>
-
- <dt>Posted:</dt>
- <dd id="posted_date"><%= @post.posted_date %></dd>
-
- <dt>Path with model:</dt>
- <dd id="path_with_model"><%= @post.path_with_model %></dd>
-
- <dt>Path with id:</dt>
- <dd id="path_with_id"><%= @post.path_with_id %></dd>
-
- <dt>URL with model:</dt>
- <dd id="url_with_model"><%= @post.url_with_model %></dd>
-
- <dt>URL with id:</dt>
- <dd id="url_with_id"><%= @post.url_with_id %></dd>
-</dl>
+<%= render @post %>
View
5 spec/dummy/config/application.rb
@@ -54,6 +54,11 @@ class Application < Rails::Application
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
end
end
View
3 spec/dummy/config/environments/development.rb
@@ -13,9 +13,6 @@
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
- # Don't care if the mailer can't send
- config.action_mailer.raise_delivery_errors = false
-
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
View
3 spec/dummy/config/environments/production.rb
@@ -39,9 +39,6 @@
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
- # Disable delivery errors, bad email addresses will be ignored
- # config.action_mailer.raise_delivery_errors = false
-
# Enable threaded mode
# config.threadsafe!
View
5 spec/dummy/config/environments/test.rb
@@ -24,11 +24,6 @@
# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false
- # Tell Action Mailer not to deliver emails to the real world.
- # The :test delivery method accumulates sent emails in the
- # ActionMailer::Base.deliveries array.
- config.action_mailer.delivery_method = :test
-
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
View
4 spec/dummy/config/routes.rb
@@ -1,5 +1,7 @@
Dummy::Application.routes.draw do
scope "(:locale)", locale: /en|zh/ do
- resources :posts, only: [:show]
+ resources :posts, only: [:show] do
+ get "mail", on: :member
+ end
end
end
View
29 spec/dummy/spec/mailers/post_mailer_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe PostMailer do
+ describe "#decorated_email" do
+ subject { Capybara.string(email.body.to_s) }
+ let(:email) { PostMailer.decorated_email(post).deliver }
+ let(:post) { Post.create }
+
+ it "decorates" do
+ subject.should have_content "Today"
+ end
+
+ it "can use path helpers with a model" do
+ subject.should have_css "#path_with_model", text: "/en/posts/#{post.id}"
+ end
+
+ it "can use path helpers with an id" do
+ subject.should have_css "#path_with_id", text: "/en/posts/#{post.id}"
+ end
+
+ it "can use url helpers with a model" do
+ subject.should have_css "#url_with_model", text: "http://www.example.com/en/posts/#{post.id}"
+ end
+
+ it "can use url helpers with an id" do
+ subject.should have_css "#url_with_id", text: "http://www.example.com/en/posts/#{post.id}"
+ end
+ end
+end
View
59 spec/integration/integration_spec.rb
@@ -1,48 +1,49 @@
require 'spec_helper'
require 'support/dummy_app'
+shared_examples_for "a decorator in a view" do
+ it "works" do
+ # it runs in the correct environment
+ page.should have_css "#environment", text: environment
+
+ # it can use path helpers with a model
+ page.should have_css "#path_with_model", text: "/en/posts/1"
+
+ # it can use path helpers with an id
+ page.should have_css "#path_with_id", text: "/en/posts/1"
+
+ # it can use url helpers with a model
+ page.should have_css "#url_with_model", text: "http://www.example.com/en/posts/1"
+
+ # it can use url helpers with an id
+ page.should have_css "#url_with_id", text: "http://www.example.com/en/posts/1"
+ end
+end
+
describe "integration" do
include Capybara::DSL
- environment = ENV["RAILS_ENV"].to_s
- raise ArgumentError, "RAILS_ENV must be development or production" unless ["development", "production"].include?(environment)
+ rails_env = ENV["RAILS_ENV"].to_s
+ raise ArgumentError, "RAILS_ENV must be development or production" unless ["development", "production"].include?(rails_env)
- app = DummyApp.new(environment)
+ app = DummyApp.new(rails_env)
app.start_server do
- describe "in #{environment}" do
+ describe "in #{rails_env}" do
+ let(:environment) { rails_env }
before { Capybara.app_host = app.url }
- it "runs in the correct environment" do
- visit("/posts/1")
- page.should have_css "#environment", text: environment
- end
-
- it "decorates" do
- visit("/posts/1")
- page.should have_content "Today"
- end
+ context "in a view" do
+ before { visit("/posts/1") }
- it "can use path helpers with a model" do
- visit("/posts/1")
- page.should have_css "#path_with_model", text: "/en/posts/1"
+ it_behaves_like "a decorator in a view"
end
- it "can use path helpers with an id" do
- visit("/posts/1")
- page.should have_css "#path_with_id", text: "/en/posts/1"
- end
+ context "in a mailer" do
+ before { visit("/posts/1/mail") }
- it "can use url helpers with a model" do
- visit("/posts/1")
- page.should have_css "#url_with_model", text: "http://www.example.com/en/posts/1"
+ it_behaves_like "a decorator in a view"
end
-
- it "can use url helpers with an id" do
- visit("/posts/1")
- page.should have_css "#url_with_id", text: "http://www.example.com/en/posts/1"
- end
-
end
end
View
2 spec/support/action_controller.rb
@@ -1,6 +1,6 @@
module ActionController
class Base
- Draper::System.setup_action_controller(self)
+ Draper.setup_action_controller(self)
end
end