From c4b67ec56b443563fb1dc3237364a663ff5763a9 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Fri, 4 Aug 2023 13:07:00 -0400 Subject: [PATCH] Action Mailer Preview empty states When an application defines mailers without any corresponding previews, requests to `GET /rails/mailers` return a page with a blank `` element. This entirely empty page can be confusing, since it's difficult to distinguish the "success" state with an empty list and a "failure" state with swallowed errors. Similarly, when an `ActionMailer::Preview` subclass is defined, but doesn't declare any actions, the response contains a mostly empty page. This commit renders empty-state messaging for both scenarios, and links to the [Action Mailer Basics][] guides. To effectively cover that behavior, this commit also expands the Mailer Preview test coverage to utilize [rails-dom-testing][] assertions. [Action Mailer Basics]: https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails [rails-dom-testing]: http://github.com/rails/rails-dom-testing --- railties/lib/rails/mailers_controller.rb | 4 +- .../templates/rails/mailers/index.html.erb | 21 ++++-- .../templates/rails/mailers/mailer.html.erb | 16 +++-- .../test/application/mailer_previews_test.rb | 68 +++++++++++++++++++ 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb index 5e0ffa918b761..059a095ba892a 100644 --- a/railties/lib/rails/mailers_controller.rb +++ b/railties/lib/rails/mailers_controller.rb @@ -15,7 +15,7 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc: def index @previews = ActionMailer::Preview.all - @page_title = "Mailer Previews" + @page_title = "Action Mailer Previews" end def download @@ -30,7 +30,7 @@ def download def preview if params[:path] == @preview.preview_name - @page_title = "Mailer Previews for #{@preview.preview_name}" + @page_title = "Action Mailer Previews for #{@preview.preview_name}" render action: "mailer" else @email_action = File.basename(params[:path]) diff --git a/railties/lib/rails/templates/rails/mailers/index.html.erb b/railties/lib/rails/templates/rails/mailers/index.html.erb index 000930c039001..0df1ec161df28 100644 --- a/railties/lib/rails/templates/rails/mailers/index.html.erb +++ b/railties/lib/rails/templates/rails/mailers/index.html.erb @@ -1,8 +1,15 @@ -<% @previews.each do |preview| %> -

<%= link_to preview.preview_name.titleize, url_for(controller: "rails/mailers", action: "preview", path: preview.preview_name) %>

- +

<%= @page_title %>

+ +<% if @previews.any? %> + <% @previews.each do |preview| %> +

<%= link_to preview.preview_name.titleize, url_for(controller: "rails/mailers", action: "preview", path: preview.preview_name) %>

+ + <% end %> +<% else %> +

You have not defined any Action Mailer Previews.

+

Read <%= link_to "Action Mailer Basics", "https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails" %> to learn how to define your first.

<% end %> diff --git a/railties/lib/rails/templates/rails/mailers/mailer.html.erb b/railties/lib/rails/templates/rails/mailers/mailer.html.erb index c12ead0f90b92..b726b136ba763 100644 --- a/railties/lib/rails/templates/rails/mailers/mailer.html.erb +++ b/railties/lib/rails/templates/rails/mailers/mailer.html.erb @@ -1,6 +1,12 @@ -

<%= @preview.preview_name.titleize %>

- diff --git a/railties/test/application/mailer_previews_test.rb b/railties/test/application/mailer_previews_test.rb index cb8366295e918..4c29539aa96a3 100644 --- a/railties/test/application/mailer_previews_test.rb +++ b/railties/test/application/mailer_previews_test.rb @@ -3,12 +3,14 @@ require "isolation/abstract_unit" require "rack/test" require "base64" +require "rails-dom-testing" module ApplicationTests class MailerPreviewsTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include Rack::Test::Methods include ERB::Util + include Rails::Dom::Testing::Assertions def setup build_app @@ -55,6 +57,18 @@ def teardown assert_equal 200, last_response.status end + test "request without mailer previews links to documentation" do + app("development") + + get "/rails/mailers" + assert_select "title", text: "Action Mailer Previews" + assert_select "h1", text: "Action Mailer Previews" + assert_select "p", text: "You have not defined any Action Mailer Previews." + assert_select "p", text: "Read Action Mailer Basics to learn how to define your first." do + assert_select "a[href=?]", "https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails", text: "Action Mailer Basics" + end + end + test "mailer previews are loaded from the default preview_paths" do mailer "notifier", <<-RUBY class Notifier < ActionMailer::Base @@ -81,6 +95,8 @@ def foo app("development") get "/rails/mailers" + assert_select "title", text: "Action Mailer Previews" + assert_select "h1", text: "Action Mailer Previews" assert_match '

Notifier

', last_response.body assert_match '
  • foo
  • ', last_response.body end @@ -320,6 +336,54 @@ def foo assert_no_match '

    Notifier

    ', last_response.body end + test "mailer without previews" do + mailer "notifier", <<-RUBY + class Notifier < ActionMailer::Base + end + RUBY + + mailer_preview "notifier", <<-RUBY + class NotifierPreview < ActionMailer::Preview + end + RUBY + + app("development") + get "/rails/mailers/notifier" + + assert_predicate last_response, :ok? + assert_select "title", text: "Action Mailer Previews for notifier" + assert_select "h1", text: "Action Mailer Previews for notifier" + assert_select "p", text: "You have not defined any actions for NotifierPreview." + assert_select "p", text: "Read Action Mailer Basics to learn how to define your first." do + assert_select "a[href=?]", "https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails", text: "Action Mailer Basics" + end + end + + test "mailer with previews" do + mailer "notifier", <<-RUBY + class Notifier < ActionMailer::Base + def foo + end + end + RUBY + + mailer_preview "notifier", <<-RUBY + class NotifierPreview < ActionMailer::Preview + def foo + Notifier.foo + end + end + RUBY + + app("development") + get "/rails/mailers/notifier" + + assert_predicate last_response, :ok? + assert_select "title", text: "Action Mailer Previews for notifier" + assert_select "h1", text: "Action Mailer Previews for notifier" + assert_select "ul li a[href=?]", "/rails/mailers/notifier/foo" + end + test "mailer preview not found" do app("development") get "/rails/mailers/notifier" @@ -967,6 +1031,10 @@ def build_app app_dir "test/mailers/previews" end + def document_root_element + Nokogiri::HTML5.parse(last_response.body) + end + def mailer(name, contents) app_file("app/mailers/#{name}.rb", contents) end