rubocop-view_component 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +7 -0
- data/IMPLEMENTATION_SUMMARY.md +172 -0
- data/LICENSE.txt +21 -0
- data/PLAN.md +625 -0
- data/README.md +53 -0
- data/Rakefile +35 -0
- data/config/default.yml +33 -0
- data/lib/rubocop/cop/view_component/base.rb +41 -0
- data/lib/rubocop/cop/view_component/component_suffix.rb +33 -0
- data/lib/rubocop/cop/view_component/no_global_state.rb +58 -0
- data/lib/rubocop/cop/view_component/prefer_private_methods.rb +73 -0
- data/lib/rubocop/cop/view_component/prefer_slots.rb +105 -0
- data/lib/rubocop/cop/view_component_cops.rb +7 -0
- data/lib/rubocop/view_component/plugin.rb +31 -0
- data/lib/rubocop/view_component/version.rb +7 -0
- data/lib/rubocop/view_component.rb +10 -0
- data/lib/rubocop-view_component.rb +9 -0
- data/spec/rubocop/cop/view_component/component_suffix_spec.rb +86 -0
- data/spec/rubocop/cop/view_component/no_global_state_spec.rb +119 -0
- data/spec/rubocop/cop/view_component/prefer_private_methods_spec.rb +136 -0
- data/spec/rubocop/cop/view_component/prefer_slots_spec.rb +119 -0
- data/spec/spec_helper.rb +14 -0
- metadata +108 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe RuboCop::Cop::ViewComponent::PreferPrivateMethods, :config do
|
|
4
|
+
let(:config) { RuboCop::Config.new }
|
|
5
|
+
|
|
6
|
+
context "when component has public helper methods" do
|
|
7
|
+
it "registers offense for public helper method" do
|
|
8
|
+
expect_offense(<<~RUBY)
|
|
9
|
+
class CardComponent < ViewComponent::Base
|
|
10
|
+
def initialize(title)
|
|
11
|
+
@title = title
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def formatted_title
|
|
15
|
+
^^^^^^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making this method private. Only ViewComponent interface methods should be public.
|
|
16
|
+
@title.upcase
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
RUBY
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "registers offense for multiple public helpers" do
|
|
23
|
+
expect_offense(<<~RUBY)
|
|
24
|
+
class CardComponent < ViewComponent::Base
|
|
25
|
+
def helper_one
|
|
26
|
+
^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making this method private. Only ViewComponent interface methods should be public.
|
|
27
|
+
'one'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def helper_two
|
|
31
|
+
^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making this method private. Only ViewComponent interface methods should be public.
|
|
32
|
+
'two'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
RUBY
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "when helper methods are already private" do
|
|
40
|
+
it "does not register offense" do
|
|
41
|
+
expect_no_offenses(<<~RUBY)
|
|
42
|
+
class CardComponent < ViewComponent::Base
|
|
43
|
+
def initialize(title)
|
|
44
|
+
@title = title
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def formatted_title
|
|
50
|
+
@title.upcase
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
RUBY
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "with allowed public interface methods" do
|
|
58
|
+
it "allows initialize" do
|
|
59
|
+
expect_no_offenses(<<~RUBY)
|
|
60
|
+
class CardComponent < ViewComponent::Base
|
|
61
|
+
def initialize(title)
|
|
62
|
+
@title = title
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
RUBY
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "allows call" do
|
|
69
|
+
expect_no_offenses(<<~RUBY)
|
|
70
|
+
class CardComponent < ViewComponent::Base
|
|
71
|
+
def call
|
|
72
|
+
'rendered'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
RUBY
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "allows before_render" do
|
|
79
|
+
expect_no_offenses(<<~RUBY)
|
|
80
|
+
class CardComponent < ViewComponent::Base
|
|
81
|
+
def before_render
|
|
82
|
+
@computed = true
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
RUBY
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "allows render?" do
|
|
89
|
+
expect_no_offenses(<<~RUBY)
|
|
90
|
+
class CardComponent < ViewComponent::Base
|
|
91
|
+
def render?
|
|
92
|
+
@show
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
RUBY
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "with mixed visibility" do
|
|
100
|
+
it "only flags public methods" do
|
|
101
|
+
expect_offense(<<~RUBY)
|
|
102
|
+
class CardComponent < ViewComponent::Base
|
|
103
|
+
def public_helper
|
|
104
|
+
^^^^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making this method private. Only ViewComponent interface methods should be public.
|
|
105
|
+
'public'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def private_helper
|
|
111
|
+
'private'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
public
|
|
115
|
+
|
|
116
|
+
def another_public
|
|
117
|
+
^^^^^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making this method private. Only ViewComponent interface methods should be public.
|
|
118
|
+
'public'
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
RUBY
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context "when not a ViewComponent" do
|
|
126
|
+
it "does not register offense" do
|
|
127
|
+
expect_no_offenses(<<~RUBY)
|
|
128
|
+
class RegularClass
|
|
129
|
+
def public_method
|
|
130
|
+
'public'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
RUBY
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe RuboCop::Cop::ViewComponent::PreferSlots, :config do
|
|
4
|
+
let(:config) { RuboCop::Config.new }
|
|
5
|
+
|
|
6
|
+
context "when initialize has HTML parameter names" do
|
|
7
|
+
it "registers offense for _html suffix" do
|
|
8
|
+
expect_offense(<<~RUBY)
|
|
9
|
+
class ModalComponent < ViewComponent::Base
|
|
10
|
+
def initialize(title:, body_html:)
|
|
11
|
+
^^^^^^^^^^ ViewComponent/PreferSlots: Consider using `renders_one :body` instead of passing HTML as a parameter. This maintains Rails' automatic HTML escaping.
|
|
12
|
+
@title = title
|
|
13
|
+
@body_html = body_html
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
RUBY
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "registers offense for _content suffix" do
|
|
20
|
+
expect_offense(<<~RUBY)
|
|
21
|
+
class ModalComponent < ViewComponent::Base
|
|
22
|
+
def initialize(title:, body_content:)
|
|
23
|
+
^^^^^^^^^^^^^ ViewComponent/PreferSlots: Consider using `renders_one :body` instead of passing HTML as a parameter. This maintains Rails' automatic HTML escaping.
|
|
24
|
+
@title = title
|
|
25
|
+
@body_content = body_content
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
RUBY
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "registers offense for html_ prefix" do
|
|
32
|
+
expect_offense(<<~RUBY)
|
|
33
|
+
class ModalComponent < ViewComponent::Base
|
|
34
|
+
def initialize(title:, html_body:)
|
|
35
|
+
^^^^^^^^^^ ViewComponent/PreferSlots: Consider using `renders_one :body` instead of passing HTML as a parameter. This maintains Rails' automatic HTML escaping.
|
|
36
|
+
@title = title
|
|
37
|
+
@html_body = html_body
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
RUBY
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "registers offense for content parameter" do
|
|
44
|
+
expect_offense(<<~RUBY)
|
|
45
|
+
class ModalComponent < ViewComponent::Base
|
|
46
|
+
def initialize(title:, content:)
|
|
47
|
+
^^^^^^^^ ViewComponent/PreferSlots: Consider using `renders_one :content` instead of passing HTML as a parameter. This maintains Rails' automatic HTML escaping.
|
|
48
|
+
@title = title
|
|
49
|
+
@content = content
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
RUBY
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "when parameter has html_safe default value" do
|
|
57
|
+
it "registers offense" do
|
|
58
|
+
expect_offense(<<~RUBY)
|
|
59
|
+
class ModalComponent < ViewComponent::Base
|
|
60
|
+
def initialize(title:, body: "".html_safe)
|
|
61
|
+
^^^^^^^^^^^^^^^^^^ ViewComponent/PreferSlots: Consider using `renders_one :body` instead of passing HTML as a parameter. This maintains Rails' automatic HTML escaping.
|
|
62
|
+
@title = title
|
|
63
|
+
@body = body
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
RUBY
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "when parameters are not HTML-related" do
|
|
71
|
+
it "does not register offense for regular parameters" do
|
|
72
|
+
expect_no_offenses(<<~RUBY)
|
|
73
|
+
class CardComponent < ViewComponent::Base
|
|
74
|
+
def initialize(title:, description:)
|
|
75
|
+
@title = title
|
|
76
|
+
@description = description
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
RUBY
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "does not register offense for html_class" do
|
|
83
|
+
expect_no_offenses(<<~RUBY)
|
|
84
|
+
class CardComponent < ViewComponent::Base
|
|
85
|
+
def initialize(title:, html_class:)
|
|
86
|
+
@title = title
|
|
87
|
+
@html_class = html_class
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
RUBY
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context "when not a ViewComponent" do
|
|
95
|
+
it "does not register offense" do
|
|
96
|
+
expect_no_offenses(<<~RUBY)
|
|
97
|
+
class RegularClass
|
|
98
|
+
def initialize(body_html:)
|
|
99
|
+
@body_html = body_html
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
RUBY
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context "when component uses slots" do
|
|
107
|
+
it "does not register offense" do
|
|
108
|
+
expect_no_offenses(<<~RUBY)
|
|
109
|
+
class ModalComponent < ViewComponent::Base
|
|
110
|
+
renders_one :body
|
|
111
|
+
|
|
112
|
+
def initialize(title:)
|
|
113
|
+
@title = title
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
RUBY
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rubocop-view_component"
|
|
4
|
+
require "rubocop/rspec/support"
|
|
5
|
+
|
|
6
|
+
RSpec.configure do |config|
|
|
7
|
+
config.disable_monkey_patching!
|
|
8
|
+
config.raise_errors_for_deprecations!
|
|
9
|
+
config.raise_on_warning = true
|
|
10
|
+
config.fail_if_no_examples = true
|
|
11
|
+
|
|
12
|
+
config.order = :random
|
|
13
|
+
Kernel.srand config.seed
|
|
14
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rubocop-view_component
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Andy Waite
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lint_roller
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: parser
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rubocop
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 1.72.2
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 1.72.2
|
|
54
|
+
description: A RuboCop extension that enforces ViewComponent best practices and conventions
|
|
55
|
+
email:
|
|
56
|
+
- andyw8@users.noreply.github.com
|
|
57
|
+
executables: []
|
|
58
|
+
extensions: []
|
|
59
|
+
extra_rdoc_files: []
|
|
60
|
+
files:
|
|
61
|
+
- ".rspec"
|
|
62
|
+
- ".rubocop.yml"
|
|
63
|
+
- IMPLEMENTATION_SUMMARY.md
|
|
64
|
+
- LICENSE.txt
|
|
65
|
+
- PLAN.md
|
|
66
|
+
- README.md
|
|
67
|
+
- Rakefile
|
|
68
|
+
- config/default.yml
|
|
69
|
+
- lib/rubocop-view_component.rb
|
|
70
|
+
- lib/rubocop/cop/view_component/base.rb
|
|
71
|
+
- lib/rubocop/cop/view_component/component_suffix.rb
|
|
72
|
+
- lib/rubocop/cop/view_component/no_global_state.rb
|
|
73
|
+
- lib/rubocop/cop/view_component/prefer_private_methods.rb
|
|
74
|
+
- lib/rubocop/cop/view_component/prefer_slots.rb
|
|
75
|
+
- lib/rubocop/cop/view_component_cops.rb
|
|
76
|
+
- lib/rubocop/view_component.rb
|
|
77
|
+
- lib/rubocop/view_component/plugin.rb
|
|
78
|
+
- lib/rubocop/view_component/version.rb
|
|
79
|
+
- spec/rubocop/cop/view_component/component_suffix_spec.rb
|
|
80
|
+
- spec/rubocop/cop/view_component/no_global_state_spec.rb
|
|
81
|
+
- spec/rubocop/cop/view_component/prefer_private_methods_spec.rb
|
|
82
|
+
- spec/rubocop/cop/view_component/prefer_slots_spec.rb
|
|
83
|
+
- spec/spec_helper.rb
|
|
84
|
+
homepage: https://github.com/andyw8/rubocop-view_component
|
|
85
|
+
licenses:
|
|
86
|
+
- MIT
|
|
87
|
+
metadata:
|
|
88
|
+
homepage_uri: https://github.com/andyw8/rubocop-view_component
|
|
89
|
+
source_code_uri: https://github.com/andyw8/rubocop-view_component
|
|
90
|
+
default_lint_roller_plugin: RuboCop::ViewComponent::Plugin
|
|
91
|
+
rdoc_options: []
|
|
92
|
+
require_paths:
|
|
93
|
+
- lib
|
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - ">="
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: 2.7.0
|
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
requirements: []
|
|
105
|
+
rubygems_version: 3.6.9
|
|
106
|
+
specification_version: 4
|
|
107
|
+
summary: RuboCop extension for ViewComponent best practices
|
|
108
|
+
test_files: []
|