rubocop-vicenzo 0.5.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a18abf5413cb9807bf31adf6adeb6ac47e3fd0e7ec8cb2d47217db9b1617ed40
4
- data.tar.gz: 871b1cb1de89c418517b67919402004ea95044aad2b1a8a0602ceb29953d1093
3
+ metadata.gz: 4f2fb87b8d1bfd10a66d52fcd5ede5f1eea78c7c2a8b7b8ea8a692d0efce54b6
4
+ data.tar.gz: aa25bb974ce70ab9ef752a1e36b83d779abded472022258a86ff8c2fdc483d77
5
5
  SHA512:
6
- metadata.gz: c629161e84a929d57e0ef7fdec80d17a21742adc08c7f1bafb601356815e99862d987806bfced0e88fb5d1c085af35a4f0e6039dde7cdd664c635a51e9984110
7
- data.tar.gz: 05ddcb76888e50820eda315fa63087c12a01ace730090bd5250f363a2a01b46e8277342ff903d371a5b5d6a0d8c9abcf28023a88caca421c7bfca558acbae110
6
+ metadata.gz: 57918353d578d8c2a5840617ccfefe7a996aad212dbce8921ae18a1bf302bf89fb6a5e40f6b9cdd97d082c4fb74d2e26fb2a9148d92e83fbb074e6c094da996b
7
+ data.tar.gz: be26bf4c722a8e351112c02d58bba96d06fd62fa230e8feb20e3f80675c82f6ca377875a53281df99d39ccabf8fc5de2822f9eff985a6c7a3cbe188dedd3ff6d
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.7.0"
3
+ }
data/CHANGELOG.md CHANGED
@@ -1,4 +1,19 @@
1
- ## [Unreleased]
1
+ # Changelog
2
+
3
+ ## [0.7.0](https://github.com/bvicenzo/rubocop-vicenzo/compare/v0.6.0...v0.7.0) (2026-08-31)
4
+
5
+
6
+ ### Features
7
+
8
+ * add RSpec cops against subjects hidden in lets ([#30](https://github.com/bvicenzo/rubocop-vicenzo/issues/30)) ([9daf259](https://github.com/bvicenzo/rubocop-vicenzo/commit/9daf25972252fdfdb92a51bba9cfe70e63446d17))
9
+ * add Vicenzo/RSpec/SubjectIsMethodResult cop ([#28](https://github.com/bvicenzo/rubocop-vicenzo/issues/28)) ([b69245a](https://github.com/bvicenzo/rubocop-vicenzo/commit/b69245af973f3341bbe62bca628333c5acb909d7))
10
+
11
+ ## [0.6.0](https://github.com/bvicenzo/rubocop-vicenzo/compare/v0.5.0...v0.6.0) (2026-08-19)
12
+
13
+
14
+ ### Features
15
+
16
+ * add RSpec cops against mutated and derived premises ([#26](https://github.com/bvicenzo/rubocop-vicenzo/issues/26)) ([b138dd0](https://github.com/bvicenzo/rubocop-vicenzo/commit/b138dd00a76e1bcd62e95c1f2c51dca5b4232319))
2
17
 
3
18
  ## [0.5.0] - 2026-06-29
4
19
 
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,100 @@
1
+ # Contributing
2
+
3
+ ## Development setup
4
+
5
+ Run `bin/setup` once after cloning. It installs dependencies and points
6
+ `core.hooksPath` at `.githooks/`, enabling a `commit-msg` hook that enforces
7
+ Conventional Commits locally.
8
+
9
+ Run the test suite and the linter with the default task — the same one CI runs:
10
+
11
+ ```bash
12
+ bundle exec rake
13
+ ```
14
+
15
+ ## Commit messages — Conventional Commits
16
+
17
+ This project follows [Conventional Commits](https://www.conventionalcommits.org/).
18
+ The version bump and the `CHANGELOG.md` are generated automatically from commit
19
+ messages, so the prefix matters:
20
+
21
+ | Type | When to use | Release effect |
22
+ |------|-------------|----------------|
23
+ | `feat:` | New cop or user-facing capability | minor bump |
24
+ | `fix:` | Bug fix in a cop or in the config | patch bump |
25
+ | `feat!:` or a `BREAKING CHANGE:` footer | Backwards-incompatible change | minor bump while `0.x`, major from `1.0` on |
26
+ | `chore:` `ci:` `docs:` `style:` `test:` `refactor:` | Maintenance | no release |
27
+
28
+ Title format: `type: short description` (e.g.
29
+ `feat: add Vicenzo/Style/JsonParseSymbolizeNames cop`).
30
+
31
+ Pull requests are squash-merged, so **the PR title becomes the commit message
32
+ release-please reads**. Get the title right even when the individual commits are
33
+ messy.
34
+
35
+ ## Adding a new cop
36
+
37
+ Generate the cop, its spec and its `config/default.yml` entry with:
38
+
39
+ ```bash
40
+ bundle exec rake 'new_cop[Vicenzo/Department/CopName]'
41
+ ```
42
+
43
+ The generator writes `VersionAdded: '<<next>>'` into `config/default.yml`. Leave
44
+ that placeholder alone — never replace it with a version by hand. The release
45
+ workflow fills it in with the version being released (see below).
46
+
47
+ ## Releasing (release-please)
48
+
49
+ Releases are automated with [release-please](https://github.com/googleapis/release-please):
50
+
51
+ 1. Every push to `master` creates or updates a **release PR** titled
52
+ `chore(master): release X.Y.Z`. It bumps
53
+ `lib/rubocop/vicenzo/version.rb`, `.release-please-manifest.json`,
54
+ `Gemfile.lock` and the version in the `README.md` install snippet, and updates
55
+ `CHANGELOG.md` from the Conventional Commits made since the last release.
56
+ 2. New cops are added with `VersionAdded: '<<next>>'`. The release workflow
57
+ replaces every `<<next>>` in `config/default.yml` with the version being
58
+ released, directly on the release PR — no manual editing needed. This matters
59
+ because `rake docs:generate` reads `VersionAdded` to build the "Version Added"
60
+ column of the documentation site.
61
+ 3. **Merging the release PR** creates the git tag `vX.Y.Z` and a GitHub Release.
62
+ That in turn triggers two things automatically:
63
+ - `.github/workflows/publish.yml` publishes the gem to RubyGems via
64
+ [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) (OIDC,
65
+ no API key stored in the repository).
66
+ - `.github/workflows/docs.yml` rebuilds and deploys the documentation site to
67
+ GitHub Pages, because `lib/rubocop/vicenzo/version.rb` changed.
68
+ 4. The release PR always reflects **everything on `master` since the last
69
+ release**. Cut releases promptly: merge the release PR before landing
70
+ unrelated new work you don't want included in that release.
71
+
72
+ Nothing about a release is done by hand — there is no `rake release` to run
73
+ locally and no version to edit yourself.
74
+
75
+ ## If the release PR is failing
76
+
77
+ release-please only rebuilds the release branch when a **releasable** commit
78
+ (`feat:` / `fix:`) lands on `master`. Non-releasable fixes (`chore:`, `style:`,
79
+ `ci:`, `docs:`, `test:`) do **not** rebuild it, so the release branch can fall
80
+ behind `master` and its CI can run stale code.
81
+
82
+ When the release PR's CI is red:
83
+
84
+ 1. Push the fix to `master` through a normal PR. **Never** push directly to the
85
+ `release-please--…` branch — release-please overwrites it.
86
+ 2. If those fix commits are non-releasable (so the release PR won't refresh on
87
+ its own), **close the release PR and delete its branch**. On the next push to
88
+ `master`, release-please recreates the release PR from the current `master`
89
+ (now including the fix) and its CI passes.
90
+ 3. Merge the freshly recreated release PR.
91
+
92
+ Never manually rebase or force-push the release-please branch.
93
+
94
+ ## If the gem was not published
95
+
96
+ The tag and the GitHub Release already exist, so publishing is retryable: fix the
97
+ cause and use **Re-run jobs** on the failed `Publish gem` workflow run. An
98
+ authentication failure points at the trusted publisher registration on RubyGems
99
+ (the repository or the workflow filename must match `publish.yml`), not at the
100
+ workflow itself.
data/README.md CHANGED
@@ -6,7 +6,20 @@
6
6
 
7
7
  ## Installation
8
8
 
9
- Install the gem and add to the application's Gemfile by executing:
9
+ Add it to the `development`/`test` group of your `Gemfile`:
10
+
11
+ <!-- x-release-please-start-version -->
12
+ ```ruby
13
+ group :development, :test do
14
+ gem 'rubocop-vicenzo', '~> 0.7.0', require: false
15
+ end
16
+ ```
17
+ <!-- x-release-please-end-version -->
18
+
19
+ > The version above is kept current automatically on every release; pin to
20
+ > whichever version you prefer.
21
+
22
+ Or let Bundler add the latest version for you:
10
23
 
11
24
  ```bash
12
25
  bundle add rubocop-vicenzo --group=development --require=false
@@ -55,7 +68,13 @@ rubocop --plugin rubocop-vicenzo
55
68
 
56
69
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
57
70
 
58
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
71
+ To install this gem onto your local machine, run `bundle exec rake install`.
72
+
73
+ Releases are automated: the version, the `CHANGELOG.md`, the git tag and the push
74
+ to [rubygems.org](https://rubygems.org) are all derived from
75
+ [Conventional Commits](https://www.conventionalcommits.org/) by release-please.
76
+ There is no version to edit and no release command to run by hand — see
77
+ [CONTRIBUTING.md](CONTRIBUTING.md).
59
78
 
60
79
  ### Documentation
61
80
 
@@ -92,7 +111,7 @@ bundle exec rake 'new_cop[Vicenzo/OptionalNamespace/CopName]'
92
111
 
93
112
  ## Contributing
94
113
 
95
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rubocop-vicenzo. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/rubocop-vicenzo/blob/master/CODE_OF_CONDUCT.md).
114
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bvicenzo/rubocop-vicenzo. Read [CONTRIBUTING.md](CONTRIBUTING.md) first — it covers the commit conventions the release automation depends on. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/bvicenzo/rubocop-vicenzo/blob/master/CODE_OF_CONDUCT.md).
96
115
 
97
116
  ## License
98
117
 
@@ -100,4 +119,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
100
119
 
101
120
  ## Code of Conduct
102
121
 
103
- Everyone interacting in the Rubocop::Vicenzo project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rubocop-vicenzo/blob/master/CODE_OF_CONDUCT.md).
122
+ Everyone interacting in the Rubocop::Vicenzo project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bvicenzo/rubocop-vicenzo/blob/master/CODE_OF_CONDUCT.md).
data/config/default.yml CHANGED
@@ -11,6 +11,18 @@ Vicenzo/Rails/EnumInclusionOfValidation:
11
11
  Severity: convention
12
12
  VersionAdded: '0.1.0'
13
13
 
14
+ Vicenzo/RSpec/CompetingSubjects:
15
+ Description: 'Definitions the expectations assert on, two or more in a group declaring no subject, are either hidden contexts or a premise that belongs in a before.'
16
+ Enabled: true
17
+ Severity: convention
18
+ AllowedMethods: []
19
+ Include:
20
+ - '**/spec/**/*_spec.rb'
21
+ Exclude:
22
+ - '**/spec/support/**/*'
23
+ - '**/spec/factories/**/*'
24
+ VersionAdded: '0.7.0'
25
+
14
26
  Vicenzo/RSpec/ConditionalInSpec:
15
27
  Description: 'Do not use conditional logic in specs. Extract each branch into an explicit context instead.'
16
28
  Enabled: true
@@ -22,6 +34,17 @@ Vicenzo/RSpec/ConditionalInSpec:
22
34
  - '**/spec/factories/**/*'
23
35
  VersionAdded: '0.4.0'
24
36
 
37
+ Vicenzo/RSpec/DerivedPremises:
38
+ Description: 'Do not derive a premise from another premise; declare the complete value where it is needed.'
39
+ Enabled: true
40
+ Severity: warning
41
+ Include:
42
+ - '**/spec/**/*_spec.rb'
43
+ Exclude:
44
+ - '**/spec/support/**/*'
45
+ - '**/spec/factories/**/*'
46
+ VersionAdded: '0.6.0'
47
+
25
48
  Vicenzo/RSpec/DynamicExampleGeneration:
26
49
  Description: 'Do not use iteration to dynamically generate example groups or examples.'
27
50
  Enabled: true
@@ -40,6 +63,17 @@ Vicenzo/RSpec/IterationInsideExample:
40
63
  Severity: warning
41
64
  VersionAdded: '0.4.0'
42
65
 
66
+ Vicenzo/RSpec/MutatedPremises:
67
+ Description: 'Do not mutate the premises (let, let_it_be, subject) an example starts from.'
68
+ Enabled: true
69
+ Severity: warning
70
+ Include:
71
+ - '**/spec/**/*_spec.rb'
72
+ Exclude:
73
+ - '**/spec/support/**/*'
74
+ - '**/spec/factories/**/*'
75
+ VersionAdded: '0.6.0'
76
+
43
77
  Vicenzo/RSpec/NestedContextImproperStart:
44
78
  Description: 'Check if the nested context does not start as a root one.'
45
79
  Enabled: true
@@ -69,6 +103,42 @@ Vicenzo/RSpec/LeakyDefinition:
69
103
  - '**/spec/support/**/*'
70
104
  - '**/spec/factories/**/*'
71
105
 
106
+ Vicenzo/RSpec/LetIsMethodResult:
107
+ Description: 'A let under an example group describing a method must not hold the result of calling that method on the subject.'
108
+ Enabled: true
109
+ Severity: convention
110
+ AllowedMethods: []
111
+ Include:
112
+ - '**/spec/**/*_spec.rb'
113
+ Exclude:
114
+ - '**/spec/support/**/*'
115
+ - '**/spec/factories/**/*'
116
+ VersionAdded: '0.7.0'
117
+
118
+ Vicenzo/RSpec/SubjectDefinedAsLet:
119
+ Description: 'A let the expectations assert on, in a group declaring no subject, must be declared as the subject.'
120
+ Enabled: true
121
+ Severity: convention
122
+ AllowedMethods: []
123
+ Include:
124
+ - '**/spec/**/*_spec.rb'
125
+ Exclude:
126
+ - '**/spec/support/**/*'
127
+ - '**/spec/factories/**/*'
128
+ VersionAdded: '0.7.0'
129
+
130
+ Vicenzo/RSpec/SubjectIsMethodResult:
131
+ Description: 'The subject of an example group describing a method must be the object under test, not the method result.'
132
+ Enabled: true
133
+ Severity: convention
134
+ AllowedMethods: []
135
+ Include:
136
+ - '**/spec/**/*_spec.rb'
137
+ Exclude:
138
+ - '**/spec/support/**/*'
139
+ - '**/spec/factories/**/*'
140
+ VersionAdded: '0.7.0'
141
+
72
142
  Vicenzo/Style/JsonParseSymbolizeNames:
73
143
  Description: 'Enforces passing `symbolize_names: true` to `JSON.parse` so keys are symbols.'
74
144
  Enabled: true
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'mixin/described_method'
4
+ require_relative 'mixin/expectation_target'
5
+ require_relative 'mixin/premise_tracking'
6
+
7
+ module RuboCop
8
+ module Cop
9
+ module Vicenzo
10
+ module RSpec
11
+ # Two or more definitions the expectations assert on, in a group that declares no subject, are
12
+ # contexts that were never written.
13
+ #
14
+ # A group speaks about one subject. When its examples each assert on a different definition, the
15
+ # group is not one scenario with several facts: it is several scenarios sharing a roof, and the
16
+ # circumstance that tells them apart - the one a `context` would have named - lives only in the
17
+ # definitions' names and in the reader's head.
18
+ #
19
+ # The fix is structural, and it is never to pick one of them to promote. Which shape it takes
20
+ # depends on what the definitions are to this group, and working that out is the whole job -
21
+ # which is why the offense names what was found rather than prescribing a repair:
22
+ #
23
+ # 1. They are different scenarios. Give each its own `context`, saying out loud the circumstance
24
+ # it stands for, and let each declare the subject it is about. What was encoded in
25
+ # `record_1` / `record_2` becomes a sentence, and the example shrinks to the outcome alone.
26
+ # 2. One outcome covers them all. Then they were never subjects: they are the premise. Move them
27
+ # into a `before`, unnamed, and assert on the collection they belong to.
28
+ #
29
+ # Both are corrections to the spec. Neither is silencing the cop: a definition named
30
+ # `record_1` is the shape this smell takes, so renaming it settles nothing, and an inline
31
+ # disable directive keeps the hidden scenario hidden - which is the cost being paid here.
32
+ #
33
+ # A group that already declares a subject is left alone - there the subject is settled and the
34
+ # other definitions are premises, whatever their names suggest.
35
+ #
36
+ # @example
37
+ # # bad - two subjects under one roof; the circumstances are only in the names
38
+ # describe '#approved?' do
39
+ # let!(:reviewed_post) { create(:post, reviewed_at: Time.current) }
40
+ # let!(:draft_post) { create(:post) }
41
+ #
42
+ # it { expect(reviewed_post).to be_approved }
43
+ # it { expect(draft_post).not_to be_approved }
44
+ # end
45
+ #
46
+ # # good - one context per scenario, each with its own subject
47
+ # describe '#approved?' do
48
+ # context 'when the post has been reviewed' do
49
+ # subject(:post) { create(:post, reviewed_at: Time.current) }
50
+ #
51
+ # it { is_expected.to be_approved }
52
+ # end
53
+ #
54
+ # context 'without a review' do
55
+ # subject(:post) { create(:post) }
56
+ #
57
+ # it { is_expected.not_to be_approved }
58
+ # end
59
+ # end
60
+ #
61
+ # @example when one outcome covers every record, they are the premise
62
+ # # bad - two records named as if each were a subject
63
+ # describe '#deactivate' do
64
+ # let!(:pending_alert) { create(:alert, :pending) }
65
+ # let!(:firing_alert) { create(:alert, :firing) }
66
+ #
67
+ # it 'dismisses every alert', :aggregate_failures do
68
+ # monitor.deactivate
69
+ #
70
+ # expect(pending_alert.reload).to be_dismissed
71
+ # expect(firing_alert.reload).to be_dismissed
72
+ # end
73
+ # end
74
+ #
75
+ # # good - the records are the premise, and the outcome is about the collection
76
+ # describe '#deactivate' do
77
+ # before do
78
+ # create(:alert, :pending)
79
+ # create(:alert, :firing)
80
+ # end
81
+ #
82
+ # it 'dismisses every alert' do
83
+ # monitor.deactivate
84
+ #
85
+ # expect(monitor.alerts).to contain_exactly(be_dismissed, be_dismissed)
86
+ # end
87
+ # end
88
+ #
89
+ # @example records a single expectation compares are not competing subjects
90
+ # # good - both records build the one answer the example is about
91
+ # describe '.recent' do
92
+ # let!(:recent_order) { create(:order, created_at: 1.day.ago) }
93
+ # let!(:old_order) { create(:order, created_at: 1.year.ago) }
94
+ #
95
+ # it { expect(described_class.recent).to contain_exactly(recent_order) }
96
+ # end
97
+ class CompetingSubjects < RuboCop::Cop::RSpec::Base
98
+ include DescribedMethod
99
+ include ExpectationTarget
100
+ include PremiseTracking
101
+
102
+ MSG = 'The expectations here are about %<names>s, so this group has no one subject. Work out ' \
103
+ 'what these definitions are to it, and let the structure say so.'
104
+
105
+ def on_block(node)
106
+ return unless example_group?(node)
107
+
108
+ names = competing_names(node)
109
+
110
+ return if names.size < 2
111
+
112
+ add_offense(node.send_node, message: format(MSG, names: names.join(', ')))
113
+ end
114
+
115
+ alias on_numblock on_block
116
+ alias on_itblock on_block
117
+
118
+ private
119
+
120
+ def competing_names(group)
121
+ return [] if declares_subject?(group)
122
+
123
+ asserted_definitions(group).reject { |name| exempt?(group, name) }.map { |name| "`:#{name}`" }
124
+ end
125
+
126
+ def exempt?(group, name)
127
+ return false if allowed_methods.empty?
128
+
129
+ definition = definition_named(group, name)
130
+
131
+ !definition.nil? && !call_in_chain(definition.body) do |call|
132
+ allowed_methods.include?(call.method_name.to_s)
133
+ end.nil?
134
+ end
135
+
136
+ def definition_named(group, name)
137
+ found = nil
138
+
139
+ each_child_block(group) do |child|
140
+ found ||= child if premise?(child) && premise_name(child)&.to_sym == name
141
+ end
142
+
143
+ found
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'mixin/premise_tracking'
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Vicenzo
8
+ module RSpec
9
+ # Do not derive a premise from another premise.
10
+ #
11
+ # `let(:params) { base_params.merge(age: 10) }` does not mutate anything, but it splits a single premise
12
+ # across two definitions: to know what `params` holds in a context you have to read another `let` — usually
13
+ # one that exists only to be modified. Declare the complete value in the context that needs it.
14
+ #
15
+ # Only premise definitions (`let`, `let_it_be`, `subject`) are inspected, and only when the copy starts from
16
+ # another premise: deriving from a factory or from a literal is untouched.
17
+ #
18
+ # @example
19
+ # # bad
20
+ #
21
+ # let(:base_params) { { name: 'Ada' } }
22
+ # let(:params) { base_params.merge(age: 10) }
23
+ #
24
+ # # good
25
+ #
26
+ # context 'when the age is informed' do
27
+ # let(:params) { { name: 'Ada', age: 10 } }
28
+ # end
29
+ #
30
+ # context 'when the age is unknown' do
31
+ # let(:params) { { name: 'Ada' } }
32
+ # end
33
+ #
34
+ # @example
35
+ # # good — the source is a factory, not another premise
36
+ #
37
+ # let(:params) { attributes_for(:order).merge(value: 10) }
38
+ class DerivedPremises < RuboCop::Cop::RSpec::Base
39
+ include PremiseTracking
40
+
41
+ MSG = 'Do not derive the premise `%<name>s` from `%<source>s`. ' \
42
+ 'Declare the complete value in the context that needs it.'
43
+
44
+ DERIVING_METHODS = %i[merge deep_merge reverse_merge dup clone except slice].freeze
45
+
46
+ def on_block(node)
47
+ return unless example_group?(node) && outermost_example_group?(node)
48
+
49
+ walk_example_group(node, all_premises(node))
50
+ end
51
+
52
+ alias on_numblock on_block
53
+
54
+ private
55
+
56
+ def on_premise(node, premises)
57
+ name = premise_name(node)
58
+
59
+ mutating_calls(node).each do |call|
60
+ next unless DERIVING_METHODS.include?(call.method_name)
61
+
62
+ source = premise_receiver(call, premises)
63
+
64
+ next if source.nil?
65
+
66
+ add_offense(call, message: format(MSG, name:, source:))
67
+ end
68
+ end
69
+
70
+ def on_setup_hook(node, premises); end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -14,7 +14,7 @@ module RuboCop
14
14
  # @example
15
15
  # # bad
16
16
  #
17
- # [:admin, :driver].each do |role|
17
+ # [:admin, :editor].each do |role|
18
18
  # context "when role is #{role}" do
19
19
  # it 'does something' do
20
20
  # ...
@@ -32,8 +32,8 @@ module RuboCop
32
32
  # end
33
33
  # end
34
34
  #
35
- # context 'when role is driver' do
36
- # let(:role) { :driver }
35
+ # context 'when role is editor' do
36
+ # let(:role) { :editor }
37
37
  #
38
38
  # it 'does something' do
39
39
  # ...
@@ -16,27 +16,27 @@ module RuboCop
16
16
  # @example
17
17
  # # bad — expect is called inside the iteration
18
18
  #
19
- # it 'returns vehicle costs general values' do
20
- # response_body[:vehicle_costs].first.each do |attribute, value|
21
- # expect(value).to eq(vehicle_cost.send(attribute).to_s)
19
+ # it 'returns product prices general values' do
20
+ # response_body[:product_prices].first.each do |attribute, value|
21
+ # expect(value).to eq(product_price.send(attribute).to_s)
22
22
  # end
23
23
  # end
24
24
  #
25
25
  # # good — iteration builds data, expect is called once outside
26
26
  #
27
27
  # it 'returns the expected column names' do
28
- # columns = VehicleCost.column_names.map { |column| column.gsub('_centavos', '') }
29
- # expect(response_body[:vehicle_costs].first.keys).to match_array(columns.map(&:to_sym))
28
+ # columns = ProductPrice.column_names.map { |column| column.gsub('_cents', '') }
29
+ # expect(response_body[:product_prices].first.keys).to match_array(columns.map(&:to_sym))
30
30
  # end
31
31
  #
32
32
  # # good — each attribute has an explicit example
33
33
  #
34
34
  # it 'returns the correct name' do
35
- # expect(response_body[:vehicle_costs].first[:name]).to eq(vehicle_cost.name)
35
+ # expect(response_body[:product_prices].first[:name]).to eq(product_price.name)
36
36
  # end
37
37
  #
38
38
  # it 'returns the correct value' do
39
- # expect(response_body[:vehicle_costs].first[:value]).to eq(vehicle_cost.value.to_s)
39
+ # expect(response_body[:product_prices].first[:value]).to eq(product_price.value.to_s)
40
40
  # end
41
41
  class IterationInsideExample < RuboCop::Cop::RSpec::Base
42
42
  MSG = 'Do not call `expect` inside an iteration. ' \