rspec-sorbet 1.0.0 → 1.1.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: dfa6e3ee8be246791457ead7ccfadfb915bc17def59dec8f615287e8cbda3aba
4
- data.tar.gz: 34c42b3831bc5712a67e544bc56d768c8617e917ede3f2251ad5a22000e50629
3
+ metadata.gz: 5658116844f34d4b596c0f46bbdcefa667a82d3186905f0acf0961d3654ec660
4
+ data.tar.gz: 38d680e034afe8cd469882f210efec1e7fb23c3ef4f3b3ec40f027069864451d
5
5
  SHA512:
6
- metadata.gz: a1b97aa16c1923938827dc55a7e2b8574dd116ed5c88c43530ff47758bee34f9e8b401275b743fb5cd667427307cf0791218d2c33315605da6478798a4f11d48
7
- data.tar.gz: 831e6e1f418ac631a7ec9ffc774a682e70ffe7908600d3c20253d6612b4d8d58368e53bcc7c912c10f5b153edab7c9e3825790d7eebb2cb29b0de5b2d0baec95
6
+ metadata.gz: 2377abcbc26c8d5925a868bb6ff2ca4f675769bc5a3522f253eb001f3e5d4f5e85cca4d669da2adde281eca7487a7405a2ea5b344c221ad154f8d62d62f24e26
7
+ data.tar.gz: d3ba0390f07496a8b1e9d06f344f701f66e1dcb4c3b47d378c8420d0e9e36b748c9e020e03836a08aaeda6053f811b626de0784f4dec98a41f25ee2097d3de48
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ 1.1.0
2
+
3
+ * Add basic `instance_double` verification to help check the type of an instance double.
4
+
1
5
  1.0.0
2
6
 
3
7
  * Initial release
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # RSpec Sorbet
1
+ ![rspec-sorbet](https://user-images.githubusercontent.com/2643026/63100456-02c12c00-bf6f-11e9-8430-630a27bc6e42.png)
2
+
3
+ # RSpec Sorbet [![Gem Version](https://badge.fury.io/rb/rspec-sorbet.svg)](https://badge.fury.io/rb/rspec-sorbet)
2
4
 
3
5
  A small gem consisting of helpers for using Sorbet & RSpec together.
4
6
 
@@ -15,7 +17,7 @@ require 'rspec/sorbet'
15
17
 
16
18
  ### Allowing Instance Doubles
17
19
 
18
- Out of the box if your using `instance_double`'s in your tests you'll encounter errors such as the following:
20
+ Out of the box if you're using `instance_double`'s in your tests you'll encounter errors such as the following:
19
21
 
20
22
  ```
21
23
  TypeError:
@@ -23,7 +25,7 @@ Out of the box if your using `instance_double`'s in your tests you'll encounter
23
25
  Caller: /Users/samuelgiles/Documents/Projects/Clients/Bellroy/bellroy/spec/lib/checkout/use_cases/my_use_case.rb:9
24
26
  ```
25
27
 
26
- Drop the following into your `spec_helper.rb` to allow instance doubles to be used:
28
+ Drop the following into your `spec_helper.rb` to allow `instance_double` to be used without breaking type checking:
27
29
 
28
30
  ```ruby
29
31
  RSpec::Sorbet.allow_instance_doubles!
@@ -5,11 +5,6 @@ require 'sorbet-runtime'
5
5
  module RSpec
6
6
  module Sorbet
7
7
  module InstanceDoubles
8
- WHITELISTED_ERROR_MESSAGES = [
9
- 'RSpec::Mocks::InstanceVerifyingDouble',
10
- 'InstanceDouble'
11
- ].freeze
12
-
13
8
  def allow_instance_doubles!
14
9
  T::Configuration.inline_type_error_handler = proc do |error|
15
10
  inline_type_error_handler(error)
@@ -22,18 +17,73 @@ module RSpec
22
17
 
23
18
  private
24
19
 
20
+ INLINE_INSTANCE_DOUBLE_REGEX =
21
+ /T.let: Expected type (T.any\()?(?<expected_classes>[a-zA-Z:: ,]*)(\))?, got type (.*) with value #<InstanceDouble\((?<doubled_module>[a-zA-Z:: ,]*)\)/.freeze
22
+
25
23
  def inline_type_error_handler(error)
26
- raise error unless error.is_a?(TypeError) && message_is_whitelisted?(error.message)
24
+ case error
25
+ when TypeError
26
+ message = error.message
27
+ return if instance_double_message_with_ellipsis?(message) || typed_array_message?(message)
28
+
29
+ _, expected_types_string, doubled_module_string = (message.match(INLINE_INSTANCE_DOUBLE_REGEX) || [])[0..2]
30
+ raise error unless expected_types_string && doubled_module_string
31
+
32
+ expected_types = expected_types_string.split(',').map do |expected_type_string|
33
+ Object.const_get(expected_type_string.strip)
34
+ end
35
+ doubled_module = Object.const_get(doubled_module_string)
36
+
37
+ valid = expected_types.any? do |expected_type|
38
+ doubled_module.ancestors.include?(expected_type)
39
+ end
40
+
41
+ raise error unless valid
42
+ else
43
+ raise error
44
+ end
27
45
  end
28
46
 
29
- def call_validation_error_handler(_signature, opts)
30
- raise TypeError, opts[:pretty_message] unless message_is_whitelisted?(opts[:message])
47
+ INSTANCE_VERIFYING_DOUBLE_OR_INSTANCE_DOUBLE =
48
+ /(RSpec::Mocks::InstanceVerifyingDouble|InstanceDouble)/.freeze
49
+
50
+ def instance_double_message_with_ellipsis?(message)
51
+ message.include?('...') && message.match?(INSTANCE_VERIFYING_DOUBLE_OR_INSTANCE_DOUBLE)
31
52
  end
32
53
 
33
- def message_is_whitelisted?(message)
34
- WHITELISTED_ERROR_MESSAGES.any? do |whitelisted_message|
35
- message.include?(whitelisted_message)
54
+ TYPED_ARRAY_MESSAGE = /got T::Array/.freeze
55
+
56
+ def typed_array_message?(message)
57
+ message.match?(TYPED_ARRAY_MESSAGE)
58
+ end
59
+
60
+ def call_validation_error_handler(_signature, opts)
61
+ should_raise = true
62
+
63
+ if opts[:pretty_message].match?(INSTANCE_VERIFYING_DOUBLE_OR_INSTANCE_DOUBLE)
64
+ typing = opts[:type]
65
+ value = opts[:value].is_a?(Array) ? opts[:value].first : opts[:value]
66
+ target = value.instance_variable_get(:@doubled_module).target
67
+
68
+ case typing
69
+ when T::Types::TypedArray
70
+ typing = typing.type
71
+ end
72
+
73
+ case typing
74
+ when T::Types::Simple
75
+ should_raise = !target.ancestors.include?(typing.raw_type)
76
+ when T::Types::Union
77
+ valid = typing.types.map(&:raw_type).any? do |type|
78
+ target.ancestors.include?(type)
79
+ end
80
+ should_raise = !valid
81
+ else
82
+ should_raise = !target.ancestors.include?(typing)
83
+ end
36
84
  end
85
+
86
+ raise TypeError, opts[:pretty_message] if should_raise
37
87
  end
38
88
  end
39
89
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Sorbet
5
- VERSION = '1.0.0'
5
+ VERSION = '1.1.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-sorbet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Giles
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-15 00:00:00.000000000 Z
11
+ date: 2019-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet