-
-
Notifications
You must be signed in to change notification settings - Fork 268
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
238 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,8 @@ rdoc | |
doc | ||
.yardoc | ||
|
||
tmp | ||
|
||
# bundler | ||
.bundle | ||
Gemfile.lock | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* [#654](https://github.com/rubocop/rubocop-rails/issues/654): Add new `Rails/MailerPreviews` cop. ([@fatkodima][]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
# A mixin with predefined parent classes matchers | ||
module ParentClassMatchers | ||
extend NodePattern::Macros | ||
|
||
def_node_matcher :mailer_base_class?, <<~PATTERN | ||
{ | ||
(const (const {nil? cbase} :ActionMailer) :Base) | ||
(const {nil? cbase} :ApplicationMailer) | ||
} | ||
PATTERN | ||
|
||
def_node_matcher :mailer_preview_base_class?, <<~PATTERN | ||
(const (const nil? :ActionMailer) :Preview) | ||
PATTERN | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
# A mixin with helpers related to source code parsing | ||
module ParsingHelper | ||
def parse(path, target_ruby_version) | ||
klass_name = :"Ruby#{target_ruby_version.to_s.sub('.', '')}" | ||
klass = ::Parser.const_get(klass_name) | ||
parser = klass.new(RuboCop::AST::Builder.new) | ||
|
||
buffer = Parser::Source::Buffer.new(path, 1) | ||
buffer.source = path.read | ||
|
||
parser.parse(buffer) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Rails | ||
# Enforces the existence of mailer previews. | ||
# | ||
# @example | ||
# # bad | ||
# # app/mailer/user_mailer.rb | ||
# class UserMailer < ApplicationMailer | ||
# def welcome_email | ||
# end | ||
# end | ||
# | ||
# # No file exists in mailer previews directory. | ||
# | ||
# # good | ||
# # app/mailer/user_mailer.rb | ||
# class UserMailer < ApplicationMailer | ||
# def welcome_email | ||
# end | ||
# end | ||
# | ||
# # test/mailers/previews/user_mailer_preview.rb | ||
# class UserMailer < ActionMailer::Preview | ||
# def welcome_email | ||
# end | ||
# end | ||
# | ||
class MailerPreviews < Base | ||
include ParentClassMatchers | ||
include ClassElementsHelper | ||
include ParsingHelper | ||
include VisibilityHelp | ||
|
||
MSG = 'Add a mailer preview for `%<action_name>s`.' | ||
|
||
def on_class(node) | ||
return unless mailer_base_class?(node.parent_class) | ||
|
||
actions(node).each do |action_node| | ||
mailer_name = node.identifier.source | ||
action_name = action_node.method_name | ||
message = format(MSG, action_name: action_name) | ||
|
||
add_offense(action_node, message: message) unless preview_action_exists?(mailer_name, action_name) | ||
end | ||
end | ||
|
||
private | ||
|
||
def preview_action_exists?(mailer_name, action_name) | ||
preview_files(mailer_name).any? do |preview_path| | ||
if preview_path.exist? | ||
node = parse(preview_path, target_ruby_version) | ||
|
||
node&.class_type? && | ||
mailer_preview_base_class?(node.parent_class) && | ||
actions(node).map(&:method_name).include?(action_name) | ||
end | ||
end | ||
end | ||
|
||
def actions(class_node) | ||
class_def_nodes(class_node).select { |def_node| node_visibility(def_node) == :public } | ||
end | ||
|
||
def preview_files(class_name) | ||
path = Pathname.pwd | ||
Array(cop_config['PreviewPaths']).map do |preview_path| | ||
path.join(preview_path, "#{class_name.underscore}_preview.rb") | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Rails::MailerPreviews, :config do | ||
include FileHelper | ||
|
||
let(:cop_config) { { 'PreviewPaths' => 'tmp/mailers/previews' } } | ||
|
||
after { FileUtils.rm_rf('tmp') } | ||
|
||
it 'registers an offense when there is no mailer preview file' do | ||
expect_offense(<<~RUBY) | ||
class UserMailer < ApplicationMailer | ||
def welcome_email | ||
^^^^^^^^^^^^^^^^^ Add a mailer preview for `welcome_email`. | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when there is no mailer preview method' do | ||
create_preview(<<~RUBY) | ||
class UserMailerPreview < ActionMailer::Preview | ||
end | ||
RUBY | ||
|
||
expect_offense(<<~RUBY) | ||
class UserMailer < ApplicationMailer | ||
def welcome_email | ||
^^^^^^^^^^^^^^^^^ Add a mailer preview for `welcome_email`. | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when there is a private mailer preview method' do | ||
create_preview(<<~RUBY) | ||
class UserMailerPreview < ActionMailer::Preview | ||
private | ||
def welcome_email | ||
end | ||
end | ||
RUBY | ||
|
||
expect_offense(<<~RUBY) | ||
class UserMailer < ApplicationMailer | ||
def welcome_email | ||
^^^^^^^^^^^^^^^^^ Add a mailer preview for `welcome_email`. | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when there is no mailer preview in the file' do | ||
create_preview | ||
|
||
expect_offense(<<~RUBY) | ||
class UserMailer < ApplicationMailer | ||
def welcome_email | ||
^^^^^^^^^^^^^^^^^ Add a mailer preview for `welcome_email`. | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when there is mailer preview' do | ||
create_preview(<<~RUBY) | ||
class UserMailerPreview < ActionMailer::Preview | ||
def welcome_email | ||
end | ||
end | ||
RUBY | ||
|
||
expect_no_offenses(<<~RUBY) | ||
class UserMailer < ApplicationMailer | ||
def welcome_email | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
private | ||
|
||
def create_preview(content = '') | ||
create_file('tmp/mailers/previews/user_mailer_preview.rb', content) | ||
end | ||
end |