rubocop-view_component 0.8.0 → 0.9.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 +4 -4
- data/AGENTS.md +4 -4
- data/Appraisals +2 -0
- data/README.md +1 -1
- data/gemfiles/rubocop_minimum.gemfile +2 -0
- data/gemfiles/rubocop_minimum.gemfile.lock +13 -1
- data/lib/rubocop/cop/view_component/template_analyzer.rb +61 -19
- data/lib/rubocop/view_component/version.rb +1 -1
- data/script/verify +2 -0
- data/spec/fixtures/components/haml_method_component.html.haml +2 -0
- data/spec/fixtures/components/haml_method_component.rb +15 -0
- data/spec/fixtures/components/slim_method_component.html.slim +2 -0
- data/spec/fixtures/components/slim_method_component.rb +15 -0
- data/spec/rubocop/cop/view_component/prefer_composition_spec.rb +48 -0
- data/spec/rubocop/cop/view_component/prefer_private_methods_spec.rb +50 -0
- data/spec/rubocop/cop/view_component/template_analyzer_spec.rb +93 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7ae5d788e931ed620494da128b9d5d971b8b6278841b11037a9594cf9da7cadf
|
|
4
|
+
data.tar.gz: e4202f7c094efe88eb925802022d6a7abebede5886ae5d381d2ae8eb44cd4c49
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d4a8f3314b13a36463adaa1545e747b120c430cfddba098e79af01083d906d126bea6714674084109a11a2c577e6a835c3bd7f6ca1ddd5c4b4a3289bedf430c
|
|
7
|
+
data.tar.gz: b2f22476fcda3172a5a33326ae2e09246df2377b2baaf5071433a5e7ef15c09285151a98b1093c294ea281b5b034d92e321fc8956443275a9d3642416649281e
|
data/AGENTS.md
CHANGED
|
@@ -47,10 +47,10 @@ All cops inherit from `RuboCop::Cop::Base` and are located in `lib/rubocop/cop/v
|
|
|
47
47
|
- Provides `inside_view_component?(node)` - Checks if code is within a ViewComponent
|
|
48
48
|
|
|
49
49
|
**`TemplateAnalyzer`** (`lib/rubocop/cop/view_component/template_analyzer.rb`)
|
|
50
|
-
- Used by PreferPrivateMethods cop to analyze ERB templates
|
|
50
|
+
- Used by PreferPrivateMethods cop to analyze ERB, Haml, and Slim templates
|
|
51
51
|
- Extracts method calls from templates to avoid flagging template-used methods as private candidates
|
|
52
|
-
- Handles both sibling templates (`component.html.erb`) and sidecar templates (`component/component.html.erb`)
|
|
53
|
-
- Uses the `herb` gem to parse ERB and
|
|
52
|
+
- Handles both sibling templates (`component.html.erb`) and sidecar templates (`component/component.html.erb`), including format-less templates (`component.erb`)
|
|
53
|
+
- Uses the `herb` gem to parse ERB and the `haml` (6+) and `slim` engines to compile Haml and Slim templates to Ruby
|
|
54
54
|
|
|
55
55
|
### Verification System
|
|
56
56
|
|
|
@@ -59,6 +59,6 @@ The `script/verify` script downloads real component libraries, runs all ViewComp
|
|
|
59
59
|
## Implementation Notes
|
|
60
60
|
|
|
61
61
|
- When adding a new cop, use `rake new_cop[ViewComponent/CopName]` to generate the boilerplate
|
|
62
|
-
- Template analysis is performance-sensitive - `PreferPrivateMethods` uses `herb` gem for efficient ERB parsing
|
|
62
|
+
- Template analysis is performance-sensitive - `PreferPrivateMethods` uses `herb` gem for efficient ERB parsing, while Haml and Slim rely on their template engines to compile to Ruby
|
|
63
63
|
- Cops must handle graceful degradation when templates can't be parsed
|
|
64
64
|
- All cops should include `ViewComponent::Base` module to get detection helpers
|
data/Appraisals
CHANGED
data/README.md
CHANGED
|
@@ -33,7 +33,7 @@ This gem provides several cops to enforce ViewComponent best practices:
|
|
|
33
33
|
|
|
34
34
|
- **ViewComponent/ComponentSuffix** - Enforce `-Component` suffix for ViewComponent classes
|
|
35
35
|
- **ViewComponent/NoGlobalState** - Prevent direct access to `params`, `request`, `session`, etc.
|
|
36
|
-
- **ViewComponent/PreferPrivateMethods** - Suggest making helper methods private (analyzes ERB templates to avoid flagging methods used in views)
|
|
36
|
+
- **ViewComponent/PreferPrivateMethods** - Suggest making helper methods private (analyzes ERB, Haml, and Slim templates to avoid flagging methods used in views)
|
|
37
37
|
- **ViewComponent/PreferSlots** - Detect HTML parameters that should be slots
|
|
38
38
|
- **ViewComponent/PreferComposition** - Avoid inheriting one ViewComponent from another (prefer composition). Abstract bases without their own template, such as `ApplicationComponent`, are allowed
|
|
39
39
|
- **ViewComponent/TestRenderedOutput** - Encourage testing rendered output over private methods. Supports Minitest and RSpec styles, including components built via `described_class.new` or a `let`/`subject` helper
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ..
|
|
3
3
|
specs:
|
|
4
|
-
rubocop-view_component (0.
|
|
4
|
+
rubocop-view_component (0.8.0)
|
|
5
5
|
activesupport
|
|
6
6
|
herb
|
|
7
7
|
lint_roller (~> 1.1)
|
|
@@ -37,6 +37,11 @@ GEM
|
|
|
37
37
|
diff-lcs (1.6.2)
|
|
38
38
|
drb (2.2.3)
|
|
39
39
|
erb (6.0.7)
|
|
40
|
+
haml (7.5.1)
|
|
41
|
+
prism (>= 1.1.0)
|
|
42
|
+
temple (>= 0.8.2)
|
|
43
|
+
thor
|
|
44
|
+
tilt
|
|
40
45
|
herb (0.10.3)
|
|
41
46
|
herb (0.10.3-aarch64-linux-gnu)
|
|
42
47
|
herb (0.10.3-aarch64-linux-musl)
|
|
@@ -126,7 +131,12 @@ GEM
|
|
|
126
131
|
rubydex (0.3.0-x86_64-darwin)
|
|
127
132
|
rubydex (0.3.0-x86_64-linux)
|
|
128
133
|
securerandom (0.4.1)
|
|
134
|
+
slim (5.2.2)
|
|
135
|
+
temple (~> 0.10.0)
|
|
136
|
+
tilt (>= 2.1.0)
|
|
137
|
+
temple (0.10.7)
|
|
129
138
|
thor (1.5.0)
|
|
139
|
+
tilt (2.9.0)
|
|
130
140
|
tsort (0.2.0)
|
|
131
141
|
tzinfo (2.0.6)
|
|
132
142
|
concurrent-ruby (~> 1.0)
|
|
@@ -150,6 +160,7 @@ PLATFORMS
|
|
|
150
160
|
|
|
151
161
|
DEPENDENCIES
|
|
152
162
|
appraisal
|
|
163
|
+
haml (>= 6)
|
|
153
164
|
irb
|
|
154
165
|
rake (~> 13.4)
|
|
155
166
|
rspec
|
|
@@ -157,6 +168,7 @@ DEPENDENCIES
|
|
|
157
168
|
rubocop-rake
|
|
158
169
|
rubocop-rspec
|
|
159
170
|
rubocop-view_component!
|
|
171
|
+
slim (>= 4)
|
|
160
172
|
|
|
161
173
|
BUNDLED WITH
|
|
162
174
|
2.7.2
|
|
@@ -5,8 +5,13 @@ require "herb"
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
7
7
|
module ViewComponent
|
|
8
|
-
# Helper module for analyzing ViewComponent
|
|
8
|
+
# Helper module for analyzing ViewComponent templates.
|
|
9
|
+
#
|
|
10
|
+
# Supports ERB, Haml (6+) and Slim templates.
|
|
9
11
|
module TemplateAnalyzer
|
|
12
|
+
TEMPLATE_EXTENSIONS = %w[erb haml slim].freeze
|
|
13
|
+
TEMPLATE_GLOB = "{#{TEMPLATE_EXTENSIONS.join(",")}}".freeze
|
|
14
|
+
|
|
10
15
|
# Find template file paths for a component
|
|
11
16
|
# @param component_path [String] Path to the component Ruby file
|
|
12
17
|
# @return [Array<String>] Array of template file paths
|
|
@@ -18,38 +23,28 @@ module RuboCop
|
|
|
18
23
|
component_name = File.basename(component_path, ".rb")
|
|
19
24
|
sidecar_dir = File.join(component_dir, component_name)
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
paths.uniq
|
|
26
|
+
(sibling_templates(base_path) + sidecar_templates(sidecar_dir, component_name)).uniq
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def sibling_templates(base_path)
|
|
26
|
-
|
|
27
|
-
sibling = "#{base_path}.html.erb"
|
|
28
|
-
paths << sibling if File.exist?(sibling)
|
|
29
|
-
paths.concat(Dir.glob("#{base_path}.*.html.erb"))
|
|
30
|
-
paths
|
|
30
|
+
template_paths(base_path)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def sidecar_templates(sidecar_dir, component_name)
|
|
34
|
-
|
|
35
|
-
sidecar = File.join(sidecar_dir, "#{component_name}.html.erb")
|
|
36
|
-
paths << sidecar if File.exist?(sidecar)
|
|
37
|
-
paths.concat(Dir.glob(File.join(sidecar_dir, "#{component_name}.*.html.erb")))
|
|
38
|
-
paths
|
|
34
|
+
template_paths(File.join(sidecar_dir, component_name))
|
|
39
35
|
end
|
|
40
36
|
|
|
41
|
-
# Extract method calls from
|
|
42
|
-
# @param template_path [String] Path to the
|
|
37
|
+
# Extract method calls from a template
|
|
38
|
+
# @param template_path [String] Path to the template file
|
|
43
39
|
# @return [Set<Symbol>] Set of method names called in the template
|
|
44
40
|
def extract_method_calls(template_path)
|
|
45
41
|
return Set.new unless File.exist?(template_path)
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
ruby_code = extract_template_ruby(template_path)
|
|
44
|
+
return Set.new unless ruby_code
|
|
49
45
|
|
|
50
|
-
# Parse the extracted Ruby code
|
|
51
46
|
parse_ruby_for_method_calls(ruby_code)
|
|
52
|
-
rescue StandardError => e
|
|
47
|
+
rescue LoadError, StandardError => e
|
|
53
48
|
# Graceful degradation on parse errors
|
|
54
49
|
warn "Warning: Failed to parse template #{template_path}: #{e.message}" if ENV["RUBOCOP_DEBUG"]
|
|
55
50
|
Set.new
|
|
@@ -57,6 +52,53 @@ module RuboCop
|
|
|
57
52
|
|
|
58
53
|
private
|
|
59
54
|
|
|
55
|
+
def template_paths(base_path)
|
|
56
|
+
exact_paths = TEMPLATE_EXTENSIONS.flat_map do |extension|
|
|
57
|
+
["#{base_path}.#{extension}", "#{base_path}.html.#{extension}"].select { |path| File.exist?(path) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
exact_paths + Dir.glob("#{base_path}.*.#{TEMPLATE_GLOB}")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def extract_template_ruby(template_path)
|
|
64
|
+
source = File.read(template_path)
|
|
65
|
+
|
|
66
|
+
case File.extname(template_path)
|
|
67
|
+
when ".erb"
|
|
68
|
+
Herb.extract_ruby(source)
|
|
69
|
+
when ".haml"
|
|
70
|
+
haml_to_ruby(source)
|
|
71
|
+
when ".slim"
|
|
72
|
+
slim_to_ruby(source)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def haml_to_ruby(source)
|
|
77
|
+
require "haml"
|
|
78
|
+
return unless supported_haml?
|
|
79
|
+
|
|
80
|
+
::Haml::Engine.new.call(source)
|
|
81
|
+
rescue LoadError
|
|
82
|
+
nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def supported_haml?
|
|
86
|
+
return true if ::Haml::VERSION.to_i >= 6
|
|
87
|
+
|
|
88
|
+
if ENV["RUBOCOP_DEBUG"]
|
|
89
|
+
warn "Warning: Haml #{::Haml::VERSION} is not supported; " \
|
|
90
|
+
"Haml 6 or later is required"
|
|
91
|
+
end
|
|
92
|
+
false
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def slim_to_ruby(source)
|
|
96
|
+
require "slim"
|
|
97
|
+
::Slim::Engine.new.call(source)
|
|
98
|
+
rescue LoadError
|
|
99
|
+
nil
|
|
100
|
+
end
|
|
101
|
+
|
|
60
102
|
# Parse Ruby code and extract method calls (send nodes with nil receiver)
|
|
61
103
|
def parse_ruby_for_method_calls(ruby_code)
|
|
62
104
|
# Use RuboCop's ProcessedSource to parse Ruby code
|
data/script/verify
CHANGED
|
@@ -114,8 +114,10 @@ def replace_gemfile
|
|
|
114
114
|
File.write("Gemfile", <<~RUBY)
|
|
115
115
|
source "https://rubygems.org"
|
|
116
116
|
|
|
117
|
+
gem "haml", ">= 6"
|
|
117
118
|
gem "rubocop"
|
|
118
119
|
gem "rubocop-view_component", path: "#{GEM_DIR}"
|
|
120
|
+
gem "slim", ">= 4"
|
|
119
121
|
gem "view_component"
|
|
120
122
|
RUBY
|
|
121
123
|
end
|
|
@@ -72,6 +72,34 @@ RSpec.describe RuboCop::Cop::ViewComponent::PreferComposition, :config do
|
|
|
72
72
|
end
|
|
73
73
|
RUBY
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
it "registers an offense for a Haml template" do
|
|
77
|
+
allow(File).to receive(:exist?).and_call_original
|
|
78
|
+
allow(File).to receive(:exist?).with("/test_source.html.haml").and_return(true)
|
|
79
|
+
|
|
80
|
+
expect_offense(<<~RUBY)
|
|
81
|
+
class BaseCardComponent < ViewComponent::Base
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class UserCardComponent < BaseCardComponent
|
|
85
|
+
^^^^^^^^^^^^^^^^^ ViewComponent/PreferComposition: Avoid inheriting from another ViewComponent.
|
|
86
|
+
end
|
|
87
|
+
RUBY
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "registers an offense for a Slim template" do
|
|
91
|
+
allow(File).to receive(:exist?).and_call_original
|
|
92
|
+
allow(File).to receive(:exist?).with("/test_source.html.slim").and_return(true)
|
|
93
|
+
|
|
94
|
+
expect_offense(<<~RUBY)
|
|
95
|
+
class BaseCardComponent < ViewComponent::Base
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class UserCardComponent < BaseCardComponent
|
|
99
|
+
^^^^^^^^^^^^^^^^^ ViewComponent/PreferComposition: Avoid inheriting from another ViewComponent.
|
|
100
|
+
end
|
|
101
|
+
RUBY
|
|
102
|
+
end
|
|
75
103
|
end
|
|
76
104
|
|
|
77
105
|
context "when the parent is a resolvable component without a template" do
|
|
@@ -185,6 +213,26 @@ RSpec.describe RuboCop::Cop::ViewComponent::PreferComposition, :config do
|
|
|
185
213
|
RUBY
|
|
186
214
|
end
|
|
187
215
|
|
|
216
|
+
it "flags a parent with a Haml template" do
|
|
217
|
+
File.write(File.join(engine_dir, "app", "components", "engine_card", "component.html.haml"), "%div\n")
|
|
218
|
+
|
|
219
|
+
expect_offense(<<~RUBY)
|
|
220
|
+
class UserCardComponent < EngineCard::Component
|
|
221
|
+
^^^^^^^^^^^^^^^^^^^^^ Avoid inheriting from another ViewComponent.
|
|
222
|
+
end
|
|
223
|
+
RUBY
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "flags a parent with a Slim template" do
|
|
227
|
+
File.write(File.join(engine_dir, "app", "components", "engine_card", "component.html.slim"), "div\n")
|
|
228
|
+
|
|
229
|
+
expect_offense(<<~RUBY)
|
|
230
|
+
class UserCardComponent < EngineCard::Component
|
|
231
|
+
^^^^^^^^^^^^^^^^^^^^^ Avoid inheriting from another ViewComponent.
|
|
232
|
+
end
|
|
233
|
+
RUBY
|
|
234
|
+
end
|
|
235
|
+
|
|
188
236
|
it "does not flag a parent resolved through the additional paths without a template" do
|
|
189
237
|
expect_no_offenses(<<~RUBY)
|
|
190
238
|
class UserCardComponent < EngineBase::Component
|
|
@@ -382,6 +382,56 @@ RSpec.describe RuboCop::Cop::ViewComponent::PreferPrivateMethods, :config do
|
|
|
382
382
|
end
|
|
383
383
|
end
|
|
384
384
|
|
|
385
|
+
context "with Haml template files" do
|
|
386
|
+
let(:component_file) { "spec/fixtures/components/haml_method_component.rb" }
|
|
387
|
+
|
|
388
|
+
it "flags methods not called in the Haml template" do
|
|
389
|
+
expect_offense(<<~RUBY, component_file)
|
|
390
|
+
# frozen_string_literal: true
|
|
391
|
+
|
|
392
|
+
class HamlMethodComponent < ViewComponent::Base
|
|
393
|
+
def initialize(title)
|
|
394
|
+
@title = title
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def formatted_title
|
|
398
|
+
@title.upcase
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def helper_not_used
|
|
402
|
+
^^^^^^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making `helper_not_used` private. Only ViewComponent interface methods should be public.
|
|
403
|
+
"not used"
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
RUBY
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
context "with Slim template files" do
|
|
411
|
+
let(:component_file) { "spec/fixtures/components/slim_method_component.rb" }
|
|
412
|
+
|
|
413
|
+
it "flags methods not called in the Slim template" do
|
|
414
|
+
expect_offense(<<~RUBY, component_file)
|
|
415
|
+
# frozen_string_literal: true
|
|
416
|
+
|
|
417
|
+
class SlimMethodComponent < ViewComponent::Base
|
|
418
|
+
def initialize(title)
|
|
419
|
+
@title = title
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def formatted_title
|
|
423
|
+
@title.upcase
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def helper_not_used
|
|
427
|
+
^^^^^^^^^^^^^^^^^^^ ViewComponent/PreferPrivateMethods: Consider making `helper_not_used` private. Only ViewComponent interface methods should be public.
|
|
428
|
+
"not used"
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
RUBY
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
385
435
|
context "with template files" do
|
|
386
436
|
let(:component_file) { "spec/fixtures/components/template_method_component.rb" }
|
|
387
437
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "tmpdir"
|
|
5
|
+
|
|
6
|
+
RSpec.describe RuboCop::Cop::ViewComponent::TemplateAnalyzer do
|
|
7
|
+
subject(:analyzer) { Object.new.extend(described_class) }
|
|
8
|
+
|
|
9
|
+
let(:directory) { Dir.mktmpdir("template_analyzer") }
|
|
10
|
+
|
|
11
|
+
after { FileUtils.remove_entry(directory) }
|
|
12
|
+
|
|
13
|
+
describe "#template_paths_for" do
|
|
14
|
+
let(:component_path) { File.join(directory, "example_component.rb") }
|
|
15
|
+
|
|
16
|
+
before do
|
|
17
|
+
File.write(component_path, "")
|
|
18
|
+
%w[
|
|
19
|
+
example_component.erb
|
|
20
|
+
example_component.html.erb
|
|
21
|
+
example_component.en.html.haml
|
|
22
|
+
example_component.html.slim
|
|
23
|
+
].each do |name|
|
|
24
|
+
File.write(File.join(directory, name), "")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
sidecar_directory = File.join(directory, "example_component")
|
|
28
|
+
FileUtils.mkdir_p(sidecar_directory)
|
|
29
|
+
File.write(File.join(sidecar_directory, "example_component.html.haml"), "")
|
|
30
|
+
File.write(File.join(sidecar_directory, "unrelated.rb"), "")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "finds sibling and sidecar templates in every supported language" do
|
|
34
|
+
expect(analyzer.template_paths_for(component_path)).to contain_exactly(
|
|
35
|
+
File.join(directory, "example_component.erb"),
|
|
36
|
+
File.join(directory, "example_component.html.erb"),
|
|
37
|
+
File.join(directory, "example_component.en.html.haml"),
|
|
38
|
+
File.join(directory, "example_component.html.slim"),
|
|
39
|
+
File.join(directory, "example_component", "example_component.html.haml")
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#extract_method_calls" do
|
|
45
|
+
it "extracts method calls from ERB" do
|
|
46
|
+
path = write_template("example.html.erb", "<h1><%= formatted_title %></h1>\n")
|
|
47
|
+
|
|
48
|
+
expect(analyzer.extract_method_calls(path)).to eq(Set[:formatted_title])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "extracts method calls from Haml" do
|
|
52
|
+
path = write_template("example.html.haml", "%h1{title: tooltip_text}= formatted_title\n")
|
|
53
|
+
|
|
54
|
+
expect(analyzer.extract_method_calls(path)).to eq(Set[:tooltip_text, :formatted_title])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "extracts method calls from Slim" do
|
|
58
|
+
path = write_template("example.html.slim", "h1 title=tooltip_text = formatted_title\n")
|
|
59
|
+
|
|
60
|
+
expect(analyzer.extract_method_calls(path)).to eq(Set[:tooltip_text, :formatted_title])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "extracts method calls from Haml control flow and blocks" do
|
|
64
|
+
path = write_template("example.html.haml", <<~HAML)
|
|
65
|
+
.card
|
|
66
|
+
- if show_icon?
|
|
67
|
+
= render IconComponent.new(name: icon_name) { helper_block }
|
|
68
|
+
HAML
|
|
69
|
+
|
|
70
|
+
expect(analyzer.extract_method_calls(path)).to include(
|
|
71
|
+
:show_icon?,
|
|
72
|
+
:icon_name,
|
|
73
|
+
:helper_block
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "returns an empty set for an unsupported template language" do
|
|
78
|
+
path = write_template("example.txt", "formatted_title\n")
|
|
79
|
+
|
|
80
|
+
expect(analyzer.extract_method_calls(path)).to eq(Set.new)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "returns an empty set when the template does not exist" do
|
|
84
|
+
expect(analyzer.extract_method_calls(File.join(directory, "missing.html.haml"))).to eq(Set.new)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def write_template(name, content)
|
|
89
|
+
path = File.join(directory, name)
|
|
90
|
+
File.write(path, content)
|
|
91
|
+
path
|
|
92
|
+
end
|
|
93
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-view_component
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andy Waite
|
|
@@ -132,6 +132,10 @@ files:
|
|
|
132
132
|
- spec/expected_govuk_failures.yml
|
|
133
133
|
- spec/expected_polaris_failures.yml
|
|
134
134
|
- spec/expected_primer_failures.yml
|
|
135
|
+
- spec/fixtures/components/haml_method_component.html.haml
|
|
136
|
+
- spec/fixtures/components/haml_method_component.rb
|
|
137
|
+
- spec/fixtures/components/slim_method_component.html.slim
|
|
138
|
+
- spec/fixtures/components/slim_method_component.rb
|
|
135
139
|
- spec/fixtures/components/template_method_component.html.erb
|
|
136
140
|
- spec/fixtures/components/template_method_component.rb
|
|
137
141
|
- spec/rubocop/cop/view_component/base_spec.rb
|
|
@@ -141,6 +145,7 @@ files:
|
|
|
141
145
|
- spec/rubocop/cop/view_component/prefer_composition_spec.rb
|
|
142
146
|
- spec/rubocop/cop/view_component/prefer_private_methods_spec.rb
|
|
143
147
|
- spec/rubocop/cop/view_component/prefer_slots_spec.rb
|
|
148
|
+
- spec/rubocop/cop/view_component/template_analyzer_spec.rb
|
|
144
149
|
- spec/rubocop/cop/view_component/test_rendered_output_spec.rb
|
|
145
150
|
- spec/spec_helper.rb
|
|
146
151
|
- spec/support/project_index_helpers.rb
|