/
memoized_helpers_in_example_group.rb
136 lines (126 loc) · 3.35 KB
/
memoized_helpers_in_example_group.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# frozen_string_literal: true
module RuboCop
module Cop
module RSpec
# Checks if example groups contain too many `let` and `subject` calls.
#
# This cop is configurable using the `Max` option and the `AllowSubject`
# which will configure the cop to only register offenses on calls to
# `let` and not calls to `subject`.
#
# @example
# # bad
# describe MyClass do
# let(:foo) { [] }
# let(:bar) { [] }
# let!(:booger) { [] }
# subject { {} }
# subject(:wat) { {} }
# subject!(:boo) { {} }
# end
#
# describe MyClass do
# let(:foo) { [] }
# let(:bar) { [] }
#
# context 'when stuff' do
# let!(:booger) { [] }
# subject { {} }
# subject(:wat) { {} }
# subject!(:boo) { {} }
# end
# end
#
# # good
# describe MyClass do
# let(:foo) { [] }
# let!(:booger) { [] }
# subject { {} }
# subject(:wat) { {} }
# subject!(:boo) { {} }
# end
#
# describe MyClass do
# context 'when stuff' do
# let(:foo) { [] }
# let(:bar) { [] }
# let!(:booger) { [] }
# end
#
# context 'when other stuff' do
# subject { {} }
# subject(:wat) { {} }
# subject!(:boo) { {} }
# end
# end
#
# @example with AllowSubject configuration
#
# # rubocop.yml
# # RSpec/MemoizedHelpersInExampleGroup:
# # AllowSubject: true
#
# # bad
# describe MyClass do
# let(:foo) { [] }
# let(:bar) { [] }
# let!(:booger) { [] }
# let(:subject) { {} }
# let(:wat) { {} }
# let!(:boo) { {} }
# end
#
# # good
# describe MyClass do
# let(:foo) { [] }
# let(:bar) { [] }
# let!(:booger) { [] }
# subject { {} }
# subject(:wat) { {} }
# subject!(:boo) { {} }
# end
#
# @example with Max configuration
#
# # rubocop.yml
# # RSpec/MemoizedHelpersInExampleGroup:
# # Max: 0
#
# # bad
# describe MyClass do
# let(:foo) { [] }
# end
#
# # good
# describe MyClass do
# def foo; []; end
# end
#
class MemoizedHelpersInExampleGroup < Cop
MSG = 'Example has too many memoized helpers [%<count>d/%<max>d]'
def on_block(node)
return unless spec_group?(node)
count = count_helpers(node)
node.each_ancestor(:block) do |ancestor|
count += count_helpers(ancestor)
end
return if count <= max
add_offense(node, message: format(MSG, count: count, max: max))
end
private
def count_helpers(node)
example_group = RuboCop::RSpec::ExampleGroup.new(node)
count = example_group.lets.count
count += example_group.subjects.count unless allow_subject?
count
end
def max
cop_config['Max']
end
def allow_subject?
cop_config['AllowSubject']
end
end
end
end
end