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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +19 -1
- data/README.md +17 -10
- data/doc/images/3rd_party_matchers.png +0 -0
- data/doc/images/one_liners_demo.gif +0 -0
- data/doc/images/vim_demo.gif +0 -0
- data/doc/images/vscode_demo.gif +0 -0
- data/lib/solargraph/rspec/annotations.rb +7 -0
- data/lib/solargraph/rspec/convention.rb +20 -17
- data/lib/solargraph/rspec/correctors/subject_method_corrector.rb +42 -2
- data/lib/solargraph/rspec/test_helpers.rb +93 -0
- data/lib/solargraph/rspec/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f674511062484768d92fcae50b6f005a941e62933e08d8d0e1bd7d90ebb6751f
|
4
|
+
data.tar.gz: 84ca708c2c86a22cc6345763c4232a550298b1f65bb958f361aeee5e217adda4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5cb45cfec11d259c0ffd0d45b52027c64879115b34b8d857dbacfca12dbbd2a9c31ff2d68570dc9c269b3bfd1063e8dd799715250b172ac06685a732f85d4f2
|
7
|
+
data.tar.gz: 8a036f8b0c0fa38ebdde162df6715230edcc6b54d001daaaddc13e1793313a63dbdab2e968355c9eb16eef50b169b5543d583480ac49d23a25d60515f40cbb3f
|
data/.rubocop.yml
CHANGED
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
|
-
|
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
|
12
|
-
- memoized `let` and `let!` methods
|
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
|
-
- `
|
16
|
-
-
|
17
|
-
- and
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
@@ -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
|
-
|
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: [
|
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
|
-
|
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
|
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
|
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.
|
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-
|
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
|