mocktail 0.0.1 → 0.0.5

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +9 -3
  3. data/CHANGELOG.md +38 -0
  4. data/Gemfile.lock +2 -1
  5. data/README.md +242 -65
  6. data/bin/console +47 -1
  7. data/lib/mocktail/explains_thing.rb +132 -0
  8. data/lib/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +13 -0
  9. data/lib/mocktail/handles_dry_call/fulfills_stubbing.rb +4 -0
  10. data/lib/mocktail/handles_dry_call/validates_arguments.rb +2 -23
  11. data/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb +29 -23
  12. data/lib/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +21 -0
  13. data/lib/mocktail/imitates_type/makes_double.rb +8 -4
  14. data/lib/mocktail/raises_neato_no_method_error.rb +81 -0
  15. data/lib/mocktail/share/creates_identifier.rb +28 -0
  16. data/lib/mocktail/{verifies_call/raises_verification_error → share}/stringifies_call.rb +16 -7
  17. data/lib/mocktail/share/stringifies_method_name.rb +11 -0
  18. data/lib/mocktail/simulates_argument_error/cleans_backtrace.rb +15 -0
  19. data/lib/mocktail/simulates_argument_error/reconciles_args_with_params.rb +20 -0
  20. data/lib/mocktail/simulates_argument_error/recreates_message.rb +29 -0
  21. data/lib/mocktail/simulates_argument_error/transforms_params.rb +32 -0
  22. data/lib/mocktail/simulates_argument_error.rb +30 -0
  23. data/lib/mocktail/value/cabinet.rb +12 -0
  24. data/lib/mocktail/value/double.rb +7 -8
  25. data/lib/mocktail/value/double_data.rb +10 -0
  26. data/lib/mocktail/value/explanation.rb +26 -0
  27. data/lib/mocktail/value/signature.rb +36 -0
  28. data/lib/mocktail/value/stub_returned_nil.rb +26 -0
  29. data/lib/mocktail/value/top_shelf.rb +24 -25
  30. data/lib/mocktail/value/type_replacement_data.rb +13 -0
  31. data/lib/mocktail/value/unsatisfied_stubbing.rb +8 -0
  32. data/lib/mocktail/value.rb +6 -0
  33. data/lib/mocktail/verifies_call/raises_verification_error.rb +4 -2
  34. data/lib/mocktail/version.rb +1 -1
  35. data/lib/mocktail.rb +9 -0
  36. data/mocktail.gemspec +2 -2
  37. metadata +22 -6
  38. data/lib/mocktail/share/simulates_argument_error.rb +0 -28
@@ -1,61 +1,60 @@
1
- # The top shelf stores all cross-thread & thread-aware state, so anything that
2
- # goes here is on its own when it comes to ensuring thread safety.
3
1
  module Mocktail
4
2
  class TopShelf
5
3
  def self.instance
6
- @self ||= new
4
+ Thread.current[:mocktail_top_shelf] ||= new
7
5
  end
8
6
 
7
+ @@type_replacements = {}
8
+ @@type_replacements_mutex = Mutex.new
9
+
9
10
  def initialize
10
- @type_replacements = {}
11
- @new_registrations = {}
12
- @of_next_registrations = {}
13
- @singleton_method_registrations = {}
11
+ @new_registrations = []
12
+ @of_next_registrations = []
13
+ @singleton_method_registrations = []
14
14
  end
15
15
 
16
16
  def type_replacement_for(type)
17
- @type_replacements[type] ||= TypeReplacement.new(type: type)
17
+ @@type_replacements_mutex.synchronize {
18
+ @@type_replacements[type] ||= TypeReplacement.new(type: type)
19
+ }
20
+ end
21
+
22
+ def type_replacement_if_exists_for(type)
23
+ @@type_replacements_mutex.synchronize {
24
+ @@type_replacements[type]
25
+ }
18
26
  end
19
27
 
20
28
  def reset_current_thread!
21
- @new_registrations[Thread.current] = []
22
- @of_next_registrations[Thread.current] = []
23
- @singleton_method_registrations[Thread.current] = []
29
+ Thread.current[:mocktail_top_shelf] = self.class.new
24
30
  end
25
31
 
26
32
  def register_new_replacement!(type)
27
- @new_registrations[Thread.current] ||= []
28
- @new_registrations[Thread.current] |= [type]
33
+ @new_registrations |= [type]
29
34
  end
30
35
 
31
36
  def new_replaced?(type)
32
- @new_registrations[Thread.current] ||= []
33
- @new_registrations[Thread.current].include?(type)
37
+ @new_registrations.include?(type)
34
38
  end
35
39
 
36
40
  def register_of_next_replacement!(type)
37
- @of_next_registrations[Thread.current] ||= []
38
- @of_next_registrations[Thread.current] |= [type]
41
+ @of_next_registrations |= [type]
39
42
  end
40
43
 
41
44
  def of_next_registered?(type)
42
- @of_next_registrations[Thread.current] ||= []
43
- @of_next_registrations[Thread.current].include?(type)
45
+ @of_next_registrations.include?(type)
44
46
  end
45
47
 
46
48
  def unregister_of_next_replacement!(type)
47
- @of_next_registrations[Thread.current] ||= []
48
- @of_next_registrations[Thread.current] -= [type]
49
+ @of_next_registrations -= [type]
49
50
  end
50
51
 
51
52
  def register_singleton_method_replacement!(type)
52
- @singleton_method_registrations[Thread.current] ||= []
53
- @singleton_method_registrations[Thread.current] |= [type]
53
+ @singleton_method_registrations |= [type]
54
54
  end
55
55
 
56
56
  def singleton_methods_replaced?(type)
57
- @singleton_method_registrations[Thread.current] ||= []
58
- @singleton_method_registrations[Thread.current].include?(type)
57
+ @singleton_method_registrations.include?(type)
59
58
  end
60
59
  end
61
60
  end
@@ -0,0 +1,13 @@
1
+ module Mocktail
2
+ class TypeReplacementData < Struct.new(
3
+ :type,
4
+ :replaced_method_names,
5
+ :calls,
6
+ :stubbings,
7
+ keyword_init: true
8
+ )
9
+ def double
10
+ type
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module Mocktail
2
+ class UnsatisfiedStubbing < Struct.new(
3
+ :call,
4
+ :other_stubbings,
5
+ keyword_init: true
6
+ )
7
+ end
8
+ end
@@ -2,7 +2,13 @@ require_relative "value/cabinet"
2
2
  require_relative "value/call"
3
3
  require_relative "value/demo_config"
4
4
  require_relative "value/double"
5
+ require_relative "value/double_data"
6
+ require_relative "value/explanation"
5
7
  require_relative "value/matcher_registry"
8
+ require_relative "value/signature"
6
9
  require_relative "value/stubbing"
10
+ require_relative "value/stub_returned_nil"
7
11
  require_relative "value/top_shelf"
8
12
  require_relative "value/type_replacement"
13
+ require_relative "value/type_replacement_data"
14
+ require_relative "value/unsatisfied_stubbing"
@@ -1,16 +1,18 @@
1
1
  require_relative "raises_verification_error/gathers_calls_of_method"
2
- require_relative "raises_verification_error/stringifies_call"
2
+ require_relative "../share/stringifies_method_name"
3
+ require_relative "../share/stringifies_call"
3
4
 
4
5
  module Mocktail
5
6
  class RaisesVerificationError
6
7
  def initialize
7
8
  @gathers_calls_of_method = GathersCallsOfMethod.new
9
+ @stringifies_method_name = StringifiesMethodName.new
8
10
  @stringifies_call = StringifiesCall.new
9
11
  end
10
12
 
11
13
  def raise(recording, verifiable_calls, demo_config)
12
14
  Kernel.raise VerificationError.new <<~MSG
13
- Expected mocktail of #{recording.original_type.name}##{recording.method} to be called like:
15
+ Expected mocktail of `#{@stringifies_method_name.stringify(recording)}' to be called like:
14
16
 
15
17
  #{@stringifies_call.stringify(recording)}#{[
16
18
  (" [#{demo_config.times} #{pl("time", demo_config.times)}]" unless demo_config.times.nil?),
@@ -1,3 +1,3 @@
1
1
  module Mocktail
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/mocktail.rb CHANGED
@@ -1,16 +1,19 @@
1
1
  require_relative "mocktail/dsl"
2
2
  require_relative "mocktail/errors"
3
+ require_relative "mocktail/explains_thing"
3
4
  require_relative "mocktail/handles_dry_call"
4
5
  require_relative "mocktail/handles_dry_new_call"
5
6
  require_relative "mocktail/imitates_type"
6
7
  require_relative "mocktail/initializes_mocktail"
7
8
  require_relative "mocktail/matcher_presentation"
8
9
  require_relative "mocktail/matchers"
10
+ require_relative "mocktail/raises_neato_no_method_error"
9
11
  require_relative "mocktail/registers_matcher"
10
12
  require_relative "mocktail/registers_stubbing"
11
13
  require_relative "mocktail/replaces_next"
12
14
  require_relative "mocktail/replaces_type"
13
15
  require_relative "mocktail/resets_state"
16
+ require_relative "mocktail/simulates_argument_error"
14
17
  require_relative "mocktail/value"
15
18
  require_relative "mocktail/verifies_call"
16
19
  require_relative "mocktail/version"
@@ -54,7 +57,13 @@ module Mocktail
54
57
  ResetsState.new.reset
55
58
  end
56
59
 
60
+ def self.explain(thing)
61
+ ExplainsThing.new.explain(thing)
62
+ end
63
+
57
64
  # Stores most transactional state about calls & stubbing configurations
65
+ # Anything returned by this is undocumented and could change at any time, so
66
+ # don't commit code that relies on it!
58
67
  def self.cabinet
59
68
  Thread.current[:mocktail_store] ||= Cabinet.new
60
69
  end
data/mocktail.gemspec CHANGED
@@ -6,9 +6,9 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Justin Searls"]
7
7
  spec.email = ["searls@gmail.com"]
8
8
 
9
- spec.summary = "your objects, less potency"
9
+ spec.summary = "Take your objects, and make them a double"
10
10
  spec.homepage = "https://github.com/testdouble/mocktail"
11
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
11
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
12
12
 
13
13
  spec.metadata["homepage_uri"] = spec.homepage
14
14
  spec.metadata["source_code_uri"] = spec.homepage
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mocktail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-22 00:00:00.000000000 Z
11
+ date: 2021-10-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -31,8 +31,10 @@ files:
31
31
  - lib/mocktail.rb
32
32
  - lib/mocktail/dsl.rb
33
33
  - lib/mocktail/errors.rb
34
+ - lib/mocktail/explains_thing.rb
34
35
  - lib/mocktail/handles_dry_call.rb
35
36
  - lib/mocktail/handles_dry_call/fulfills_stubbing.rb
37
+ - lib/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb
36
38
  - lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb
37
39
  - lib/mocktail/handles_dry_call/logs_call.rb
38
40
  - lib/mocktail/handles_dry_call/validates_arguments.rb
@@ -41,6 +43,7 @@ files:
41
43
  - lib/mocktail/imitates_type/ensures_imitation_support.rb
42
44
  - lib/mocktail/imitates_type/makes_double.rb
43
45
  - lib/mocktail/imitates_type/makes_double/declares_dry_class.rb
46
+ - lib/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb
44
47
  - lib/mocktail/initializes_mocktail.rb
45
48
  - lib/mocktail/matcher_presentation.rb
46
49
  - lib/mocktail/matchers.rb
@@ -53,6 +56,7 @@ files:
53
56
  - lib/mocktail/matchers/not.rb
54
57
  - lib/mocktail/matchers/numeric.rb
55
58
  - lib/mocktail/matchers/that.rb
59
+ - lib/mocktail/raises_neato_no_method_error.rb
56
60
  - lib/mocktail/records_demonstration.rb
57
61
  - lib/mocktail/registers_matcher.rb
58
62
  - lib/mocktail/registers_stubbing.rb
@@ -61,22 +65,34 @@ files:
61
65
  - lib/mocktail/replaces_type/redefines_new.rb
62
66
  - lib/mocktail/replaces_type/redefines_singleton_methods.rb
63
67
  - lib/mocktail/resets_state.rb
68
+ - lib/mocktail/share/creates_identifier.rb
64
69
  - lib/mocktail/share/determines_matching_calls.rb
65
- - lib/mocktail/share/simulates_argument_error.rb
70
+ - lib/mocktail/share/stringifies_call.rb
71
+ - lib/mocktail/share/stringifies_method_name.rb
72
+ - lib/mocktail/simulates_argument_error.rb
73
+ - lib/mocktail/simulates_argument_error/cleans_backtrace.rb
74
+ - lib/mocktail/simulates_argument_error/reconciles_args_with_params.rb
75
+ - lib/mocktail/simulates_argument_error/recreates_message.rb
76
+ - lib/mocktail/simulates_argument_error/transforms_params.rb
66
77
  - lib/mocktail/value.rb
67
78
  - lib/mocktail/value/cabinet.rb
68
79
  - lib/mocktail/value/call.rb
69
80
  - lib/mocktail/value/demo_config.rb
70
81
  - lib/mocktail/value/double.rb
82
+ - lib/mocktail/value/double_data.rb
83
+ - lib/mocktail/value/explanation.rb
71
84
  - lib/mocktail/value/matcher_registry.rb
85
+ - lib/mocktail/value/signature.rb
86
+ - lib/mocktail/value/stub_returned_nil.rb
72
87
  - lib/mocktail/value/stubbing.rb
73
88
  - lib/mocktail/value/top_shelf.rb
74
89
  - lib/mocktail/value/type_replacement.rb
90
+ - lib/mocktail/value/type_replacement_data.rb
91
+ - lib/mocktail/value/unsatisfied_stubbing.rb
75
92
  - lib/mocktail/verifies_call.rb
76
93
  - lib/mocktail/verifies_call/finds_verifiable_calls.rb
77
94
  - lib/mocktail/verifies_call/raises_verification_error.rb
78
95
  - lib/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb
79
- - lib/mocktail/verifies_call/raises_verification_error/stringifies_call.rb
80
96
  - lib/mocktail/version.rb
81
97
  - mocktail.gemspec
82
98
  homepage: https://github.com/testdouble/mocktail
@@ -93,7 +109,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
93
109
  requirements:
94
110
  - - ">="
95
111
  - !ruby/object:Gem::Version
96
- version: 2.7.0
112
+ version: 3.0.0
97
113
  required_rubygems_version: !ruby/object:Gem::Requirement
98
114
  requirements:
99
115
  - - ">="
@@ -103,5 +119,5 @@ requirements: []
103
119
  rubygems_version: 3.2.15
104
120
  signing_key:
105
121
  specification_version: 4
106
- summary: your objects, less potency
122
+ summary: Take your objects, and make them a double
107
123
  test_files: []
@@ -1,28 +0,0 @@
1
- module Mocktail
2
- class SimulatesArgumentError
3
- def simulate(arg_params, args, kwarg_params, kwargs)
4
- req_args = arg_params.count { |type, _| type == :req }
5
- opt_args = arg_params.count { |type, _| type == :opt }
6
- rest_args = arg_params.any? { |type, _| type == :rest }
7
- req_kwargs = kwarg_params.select { |type, _| type == :keyreq }
8
-
9
- allowed_args = req_args + opt_args
10
- msg = if args.size < req_args || (!rest_args && args.size > allowed_args)
11
- expected_desc = if rest_args
12
- "#{req_args}+"
13
- elsif allowed_args != req_args
14
- "#{req_args}..#{allowed_args}"
15
- else
16
- req_args.to_s
17
- end
18
-
19
- "wrong number of arguments (given #{args.size}, expected #{expected_desc}#{"; required keyword#{"s" if req_kwargs.size > 1}: #{req_kwargs.map { |_, name| name }.join(", ")}" unless req_kwargs.empty?})"
20
-
21
- elsif !(missing_kwargs = req_kwargs.reject { |_, name| kwargs.key?(name) }).empty?
22
- "missing keyword#{"s" if missing_kwargs.size > 1}: #{missing_kwargs.map { |_, name| name.inspect }.join(", ")}"
23
- end
24
-
25
- ArgumentError.new(msg)
26
- end
27
- end
28
- end