solargraph-rspec 0.3.0 β†’ 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb5a5e8955a55b4b936e0f7ac8b75daeddd08cc5eed9230b5706054398384480
4
- data.tar.gz: bb897224942929755a8b9aebbc224bed114393f05b66115299b545a401b4bcdf
3
+ metadata.gz: f674511062484768d92fcae50b6f005a941e62933e08d8d0e1bd7d90ebb6751f
4
+ data.tar.gz: 84ca708c2c86a22cc6345763c4232a550298b1f65bb958f361aeee5e217adda4
5
5
  SHA512:
6
- metadata.gz: 60902200d9a6574fe1313b51e270e568273fca41200e9dfbfdcd1f5529f6e95d3cda1e23b1eb303ab1be524048b23c435958590b29f2a9aab6083c0db788d55f
7
- data.tar.gz: 405dce9b2d8b0621a66486d6840969cc635754bdbb40e0d1ec2b142cd48c11afa863f0e463afc47c3387f4ed264a607fec981d2df2fe0f15de9f37cc450445e0
6
+ metadata.gz: a5cb45cfec11d259c0ffd0d45b52027c64879115b34b8d857dbacfca12dbbd2a9c31ff2d68570dc9c269b3bfd1063e8dd799715250b172ac06685a732f85d4f2
7
+ data.tar.gz: 8a036f8b0c0fa38ebdde162df6715230edcc6b54d001daaaddc13e1793313a63dbdab2e968355c9eb16eef50b169b5543d583480ac49d23a25d60515f40cbb3f
data/.rubocop.yml CHANGED
@@ -13,6 +13,9 @@ Style/StringLiteralsInInterpolation:
13
13
  Style/Documentation:
14
14
  Enabled: false
15
15
 
16
+ Style/StructInheritance:
17
+ Enabled: false
18
+
16
19
  Layout/LineLength:
17
20
  Max: 120
18
21
 
data/CHANGELOG.md CHANGED
@@ -7,7 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- Add here...
10
+ ## v.0.4.0 - 2024-08-25
11
+
12
+ ### Added
13
+
14
+ - Support for 3rd party helpers from most known RSpec extension libraries.
15
+ - [rspec-mocks](https://github.com/rspec/rspec-mocks)
16
+ - [rspec-rails](https://github.com/rspec/rspec-rails)
17
+ - [webmock](https://github.com/bblimke/webmock)
18
+ - [shoulda-matchers](https://matchers.shoulda.io/)
19
+ - [rspec-sidekiq](https://github.com/wspurgin/rspec-sidekiq)
20
+ - [airborne](https://github.com/brooklynDev/airborne)
21
+ - <details><summary>πŸ“Έ</summary>
22
+ <img src="./doc/images/3rd_party_matchers.png" width="600" alt="3rd party matchers completion">
23
+ </details>
24
+
25
+ - Implement RSpec [one-liner syntax](https://rspec.info/features/3-12/rspec-core/subject/one-liner-syntax/) helpers: `is_expected`, `should` and `should_not`
26
+ - <details><summary>πŸ“Ή</summary>
27
+ <img src="./doc/images/one_liners_demo.gif" width="600" alt="One-liner syntax completion">
28
+ </details>
11
29
 
12
30
  ## v0.3.0 - 2024-07-10
13
31
 
data/README.md CHANGED
@@ -7,17 +7,24 @@
7
7
 
8
8
  RSpec is a testing framework of choice for many Ruby developers. But at the same time is highly dynamic and heavily relying on metaprogramming making it hard to provide accurate code completion and type inference.
9
9
 
10
- This gem aims to provide better support for RSpec in Solargraph and it supports the following features:
11
- - `describe` and `it` methods completion
12
- - memoized `let` and `let!` methods completion
13
- - implicit and explicit `subject` methods
10
+ This gem aims to provide better support for RSpec in Solargraph and it supports the following features (completion, jump to definition and type inference πŸš€):
11
+ - `describe` and `it` methods
12
+ - memoized `let` and `let!` methods
14
13
  - `described_class` with appropriate type inference
15
- - `RSpec::Matchers` methods completion
16
- - type inference πŸš€
17
- - and more to come...
18
-
19
- ![solargraph-rspec-with-types](https://github.com/lekemula/solargraph-rspec/assets/9197495/077e74f8-a800-4e90-8922-fa5351adcda3)
20
- ![solargraph-rspec-with-types-vs-code](https://github.com/lekemula/solargraph-rspec/assets/9197495/6a942460-256d-46ca-82de-9869a65309ec)
14
+ - implicit and explicit `subject` methods
15
+ - one liner syntax helpers `is_expected`, `should` and `should_not` linked to the appropriate subject
16
+ - Core and 3rd party spec helpers & matchers
17
+ - [rspec-mocks](https://github.com/rspec/rspec-mocks)
18
+ - [rspec-rails](https://github.com/rspec/rspec-rails)
19
+ - [webmock](https://github.com/bblimke/webmock)
20
+ - [shoulda-matchers](https://matchers.shoulda.io/)
21
+ - [rspec-sidekiq](https://github.com/wspurgin/rspec-sidekiq)
22
+ - [airborne](https://github.com/brooklynDev/airborne)
23
+ - Custom DSL extensions support (see [Configuration](#configuration) section)
24
+ - and more to come... ⏲️
25
+
26
+ ![solargraph-rspec-with-types](./doc/images/vim_demo.gif)
27
+ ![solargraph-rspec-with-types-vs-code](./doc/images/vscode_demo.gif)
21
28
 
22
29
 
23
30
  ## Installation
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @!override ActionController::TestCase::Behavior#request
4
+ # @return [ActionDispatch::Request]
5
+ #
6
+ # @!override ActionController::TestCase::Behavior#response
7
+ # @return [ActionDispatch::Response]
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'config'
4
4
  require_relative 'spec_walker'
5
+ require_relative 'annotations'
5
6
  require_relative 'correctors/context_block_namespace_corrector'
6
7
  require_relative 'correctors/example_and_hook_blocks_binding_corrector'
7
8
  require_relative 'correctors/described_class_corrector'
@@ -9,12 +10,12 @@ require_relative 'correctors/let_methods_corrector'
9
10
  require_relative 'correctors/subject_method_corrector'
10
11
  require_relative 'correctors/context_block_methods_corrector'
11
12
  require_relative 'correctors/dsl_methods_corrector'
13
+ require_relative 'test_helpers'
12
14
  require_relative 'pin_factory'
13
15
 
14
16
  module Solargraph
15
17
  module Rspec
16
18
  ROOT_NAMESPACE = 'RSpec::ExampleGroups'
17
- HELPER_MODULES = ['RSpec::Matchers'].freeze
18
19
  HOOK_METHODS = %w[before after around].freeze
19
20
  LET_METHODS = %w[let let!].freeze
20
21
  SUBJECT_METHODS = %w[subject subject!].freeze
@@ -83,7 +84,12 @@ module Solargraph
83
84
  # @return [Environ]
84
85
  def global(_yard_map)
85
86
  pins = []
86
- pins += include_helper_pins
87
+ pins += Solargraph::Rspec::TestHelpers.include_helper_pins(
88
+ root_example_group_namespace_pin: root_example_group_namespace_pin
89
+ )
90
+ pins += annotation_pins
91
+ # TODO: Include gem requires conditionally based on Gemfile definition
92
+ requires = Solargraph::Rspec::TestHelpers.gem_names
87
93
 
88
94
  if pins.any?
89
95
  Solargraph.logger.debug(
@@ -91,7 +97,9 @@ module Solargraph
91
97
  )
92
98
  end
93
99
 
94
- Environ.new(pins: pins)
100
+ Solargraph.logger.debug "[RSpec] added requires #{requires}"
101
+
102
+ Environ.new(requires: requires, pins: pins)
95
103
  rescue StandardError => e
96
104
  raise e if ENV['SOLARGRAPH_DEBUG']
97
105
 
@@ -132,7 +140,7 @@ module Solargraph
132
140
  )
133
141
  end
134
142
 
135
- Environ.new(requires: ['rspec'], pins: pins)
143
+ Environ.new(requires: [], pins: pins)
136
144
  rescue StandardError => e
137
145
  raise e if ENV['SOLARGRAPH_DEBUG']
138
146
 
@@ -144,19 +152,6 @@ module Solargraph
144
152
 
145
153
  private
146
154
 
147
- # @param helper_modules [Array<String>]
148
- # @param source_map [SourceMap]
149
- # @return [Array<Pin::Base>]
150
- def include_helper_pins(helper_modules: HELPER_MODULES)
151
- helper_modules.map do |helper_module|
152
- PinFactory.build_module_include(
153
- root_example_group_namespace_pin,
154
- helper_module,
155
- root_example_group_namespace_pin.location
156
- )
157
- end
158
- end
159
-
160
155
  # @return [Config]
161
156
  def config
162
157
  self.class.config
@@ -169,6 +164,14 @@ module Solargraph
169
164
  location: PinFactory.dummy_location('lib/rspec/core/example_group.rb')
170
165
  )
171
166
  end
167
+
168
+ # @return [Array<Pin::Base>]
169
+ def annotation_pins
170
+ ann = File.read("#{File.dirname(__FILE__)}/annotations.rb")
171
+ source = Solargraph::Source.load_string(ann, 'rspec-annotations.rb')
172
+ map = Solargraph::SourceMap.map(source)
173
+ map.pins
174
+ end
172
175
  end
173
176
  end
174
177
  end
@@ -16,6 +16,7 @@ module Solargraph
16
16
 
17
17
  subject_pin = rspec_subject_method(namespace_pin, subject_name, location_range, fake_method_ast)
18
18
  add_pin(subject_pin)
19
+ add_pins(one_liner_expectation_pins(subject_pin))
19
20
  end
20
21
 
21
22
  rspec_walker.after_walk do
@@ -23,7 +24,11 @@ module Solargraph
23
24
 
24
25
  namespace_pin = closest_namespace_pin(namespace_pins, described_class_pin.location.range.start.line)
25
26
 
26
- add_pin(implicit_subject_pin(described_class_pin, namespace_pin)) if namespace_pin
27
+ if namespace_pin
28
+ implicit_subject_pin = implicit_subject_method(described_class_pin, namespace_pin)
29
+ add_pin(implicit_subject_pin)
30
+ add_pins(one_liner_expectation_pins(implicit_subject_pin))
31
+ end
27
32
  end
28
33
  end
29
34
 
@@ -47,7 +52,7 @@ module Solargraph
47
52
  # @param described_class_pin [Pin::Method]
48
53
  # @param namespace_pin [Pin::Namespace]
49
54
  # @return [Pin::Method]
50
- def implicit_subject_pin(described_class_pin, namespace_pin)
55
+ def implicit_subject_method(described_class_pin, namespace_pin)
51
56
  described_class = described_class_pin.return_type.first.subtypes.first.name
52
57
 
53
58
  PinFactory.build_public_method(
@@ -58,6 +63,41 @@ module Solargraph
58
63
  scope: :instance
59
64
  )
60
65
  end
66
+
67
+ # @param subject_pin [Pin::Method]
68
+ # @return [Array<Pin::Method>]
69
+ def one_liner_expectation_pins(subject_pin)
70
+ [
71
+ one_liner_expectation_pin(subject_pin.closure, :is_expected, subject_pin.location),
72
+ one_liner_expectation_pin(subject_pin.closure, :should, subject_pin.location),
73
+ one_liner_expectation_pin(subject_pin.closure, :should_not, subject_pin.location)
74
+ ]
75
+ end
76
+
77
+ # @param namespace_pin [Pin::Namespace]
78
+ # @param method_name [:is_expected, :should, :should_not]
79
+ # @param location [Solargraph::Location]
80
+ # @return [Pin::Method]
81
+ def one_liner_expectation_pin(namespace_pin, method_name, location)
82
+ return_type = case method_name
83
+ when :is_expected
84
+ ['::RSpec::Expectations::ExpectationTarget']
85
+ when :should
86
+ ['::RSpec::Matchers::BuiltIn::PositiveOperatorMatcher']
87
+ when :should_not
88
+ ['::RSpec::Matchers::BuiltIn::NegativeOperatorMatcher']
89
+ else
90
+ raise ArgumentError, "Unknown inline expectation method: #{method_name}"
91
+ end
92
+
93
+ PinFactory.build_public_method(
94
+ namespace_pin,
95
+ method_name.to_s,
96
+ types: [return_type],
97
+ location: location,
98
+ scope: :instance
99
+ )
100
+ end
61
101
  end
62
102
  end
63
103
  end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Rspec
5
+ class TestHelpers
6
+ class GemHelpers < Struct.new(:required_gems, :helper_modules, keyword_init: true)
7
+ # @!attribute [r] required_gems
8
+ # @return [Array<String>]
9
+ # @!attribute [r] helper_modules
10
+ # @return [Array<String>]
11
+ end
12
+
13
+ class << self
14
+ # @return [String]
15
+ def gem_names
16
+ GEM_HELPERS.flat_map(&:required_gems)
17
+ end
18
+
19
+ # @return [Array<String>]
20
+ def helper_module_names
21
+ GEM_HELPERS.flat_map(&:helper_modules)
22
+ end
23
+
24
+ # @param root_example_group_namespace_pin [Pin::Namespace]
25
+ # @return [Array<Pin::Reference::Include>]
26
+ def include_helper_pins(root_example_group_namespace_pin:)
27
+ Solargraph.logger.debug "[RSpec] adding helper modules #{helper_module_names}"
28
+ helper_module_names.map do |helper_module|
29
+ PinFactory.build_module_include(
30
+ root_example_group_namespace_pin,
31
+ helper_module,
32
+ root_example_group_namespace_pin.location
33
+ )
34
+ end
35
+ end
36
+ end
37
+
38
+ GEM_HELPERS = [
39
+ GemHelpers.new(
40
+ required_gems: %w[rspec],
41
+ helper_modules: %w[RSpec::Matchers]
42
+ ),
43
+ # https://github.com/rspec/rspec-mocks
44
+ GemHelpers.new(
45
+ required_gems: %w[rspec-mocks],
46
+ helper_modules: %w[RSpec::Mocks::ExampleMethods]
47
+ ),
48
+ # @see https://github.com/rspec/rspec-rails#what-tests-should-i-write
49
+ # @see https://github.com/rspec/rspec-rails#helpful-rails-matchers
50
+ GemHelpers.new(
51
+ required_gems: %w[rspec-rails actionmailer activesupport activerecord],
52
+ helper_modules: [
53
+ 'RSpec::Rails::Matchers',
54
+ 'ActionController::TestCase::Behavior',
55
+ 'ActionMailer::TestCase::Behavior',
56
+ 'ActiveSupport::Testing::Assertions',
57
+ 'ActiveSupport::Testing::TimeHelpers',
58
+ 'ActiveSupport::Testing::FileFixtures',
59
+ 'ActiveRecord::TestFixtures',
60
+ 'ActionDispatch::Integration::Runner',
61
+ 'ActionDispatch::Routing::UrlFor',
62
+ 'ActionController::TemplateAssertions'
63
+ ]
64
+ ),
65
+ # @see https://matchers.shoulda.io/docs/v6.2.0/#matchers
66
+ GemHelpers.new(
67
+ required_gems: %w[shoulda-matchers],
68
+ helper_modules: [
69
+ 'Shoulda::Matchers::ActiveModel',
70
+ 'Shoulda::Matchers::ActiveRecord',
71
+ 'Shoulda::Matchers::ActionController',
72
+ 'Shoulda::Matchers::Routing'
73
+ ]
74
+ ),
75
+ # @see https://github.com/wspurgin/rspec-sidekiq#matchers
76
+ GemHelpers.new(
77
+ required_gems: %w[rspec-sidekiq],
78
+ helper_modules: %w[RSpec::Sidekiq::Matchers]
79
+ ),
80
+ # @see https://github.com/bblimke/webmock#examples
81
+ GemHelpers.new(
82
+ required_gems: %w[webmock],
83
+ helper_modules: %w[WebMock::API WebMock::Matchers]
84
+ ),
85
+ # @see https://github.com/brooklynDev/airborne
86
+ GemHelpers.new(
87
+ required_gems: %w[airborne],
88
+ helper_modules: %w[Airborne]
89
+ )
90
+ ].freeze
91
+ end
92
+ end
93
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Solargraph
4
4
  module Rspec
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LekΓ« Mula
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-10 00:00:00.000000000 Z
11
+ date: 2024-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solargraph
@@ -46,7 +46,12 @@ files:
46
46
  - README.md
47
47
  - Rakefile
48
48
  - codecov.yml
49
+ - doc/images/3rd_party_matchers.png
50
+ - doc/images/one_liners_demo.gif
51
+ - doc/images/vim_demo.gif
52
+ - doc/images/vscode_demo.gif
49
53
  - lib/solargraph-rspec.rb
54
+ - lib/solargraph/rspec/annotations.rb
50
55
  - lib/solargraph/rspec/config.rb
51
56
  - lib/solargraph/rspec/convention.rb
52
57
  - lib/solargraph/rspec/correctors/base.rb
@@ -63,6 +68,7 @@ files:
63
68
  - lib/solargraph/rspec/spec_walker/full_constant_name.rb
64
69
  - lib/solargraph/rspec/spec_walker/node_types.rb
65
70
  - lib/solargraph/rspec/spec_walker/rspec_context_namespace.rb
71
+ - lib/solargraph/rspec/test_helpers.rb
66
72
  - lib/solargraph/rspec/version.rb
67
73
  - lib/solargraph/rspec/walker.rb
68
74
  - lib/solargraph_rspec.rb