mocktail 0.0.1

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +18 -0
  3. data/.gitignore +8 -0
  4. data/.standard.yml +1 -0
  5. data/CHANGELOG.md +3 -0
  6. data/Gemfile +10 -0
  7. data/Gemfile.lock +62 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.md +557 -0
  10. data/Rakefile +11 -0
  11. data/bin/console +35 -0
  12. data/bin/setup +8 -0
  13. data/lib/mocktail/dsl.rb +21 -0
  14. data/lib/mocktail/errors.rb +15 -0
  15. data/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +16 -0
  16. data/lib/mocktail/handles_dry_call/fulfills_stubbing.rb +21 -0
  17. data/lib/mocktail/handles_dry_call/logs_call.rb +7 -0
  18. data/lib/mocktail/handles_dry_call/validates_arguments.rb +57 -0
  19. data/lib/mocktail/handles_dry_call.rb +19 -0
  20. data/lib/mocktail/handles_dry_new_call.rb +36 -0
  21. data/lib/mocktail/imitates_type/ensures_imitation_support.rb +11 -0
  22. data/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb +95 -0
  23. data/lib/mocktail/imitates_type/makes_double.rb +18 -0
  24. data/lib/mocktail/imitates_type.rb +19 -0
  25. data/lib/mocktail/initializes_mocktail.rb +17 -0
  26. data/lib/mocktail/matcher_presentation.rb +15 -0
  27. data/lib/mocktail/matchers/any.rb +18 -0
  28. data/lib/mocktail/matchers/base.rb +25 -0
  29. data/lib/mocktail/matchers/captor.rb +52 -0
  30. data/lib/mocktail/matchers/includes.rb +24 -0
  31. data/lib/mocktail/matchers/is_a.rb +11 -0
  32. data/lib/mocktail/matchers/matches.rb +13 -0
  33. data/lib/mocktail/matchers/not.rb +11 -0
  34. data/lib/mocktail/matchers/numeric.rb +18 -0
  35. data/lib/mocktail/matchers/that.rb +24 -0
  36. data/lib/mocktail/matchers.rb +14 -0
  37. data/lib/mocktail/records_demonstration.rb +32 -0
  38. data/lib/mocktail/registers_matcher.rb +52 -0
  39. data/lib/mocktail/registers_stubbing.rb +19 -0
  40. data/lib/mocktail/replaces_next.rb +36 -0
  41. data/lib/mocktail/replaces_type/redefines_new.rb +26 -0
  42. data/lib/mocktail/replaces_type/redefines_singleton_methods.rb +39 -0
  43. data/lib/mocktail/replaces_type.rb +26 -0
  44. data/lib/mocktail/resets_state.rb +9 -0
  45. data/lib/mocktail/share/determines_matching_calls.rb +60 -0
  46. data/lib/mocktail/share/simulates_argument_error.rb +28 -0
  47. data/lib/mocktail/value/cabinet.rb +41 -0
  48. data/lib/mocktail/value/call.rb +15 -0
  49. data/lib/mocktail/value/demo_config.rb +10 -0
  50. data/lib/mocktail/value/double.rb +11 -0
  51. data/lib/mocktail/value/matcher_registry.rb +19 -0
  52. data/lib/mocktail/value/stubbing.rb +24 -0
  53. data/lib/mocktail/value/top_shelf.rb +61 -0
  54. data/lib/mocktail/value/type_replacement.rb +11 -0
  55. data/lib/mocktail/value.rb +8 -0
  56. data/lib/mocktail/verifies_call/finds_verifiable_calls.rb +15 -0
  57. data/lib/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +10 -0
  58. data/lib/mocktail/verifies_call/raises_verification_error/stringifies_call.rb +47 -0
  59. data/lib/mocktail/verifies_call/raises_verification_error.rb +63 -0
  60. data/lib/mocktail/verifies_call.rb +29 -0
  61. data/lib/mocktail/version.rb +3 -0
  62. data/lib/mocktail.rb +63 -0
  63. data/mocktail.gemspec +31 -0
  64. metadata +107 -0
@@ -0,0 +1,63 @@
1
+ require_relative "raises_verification_error/gathers_calls_of_method"
2
+ require_relative "raises_verification_error/stringifies_call"
3
+
4
+ module Mocktail
5
+ class RaisesVerificationError
6
+ def initialize
7
+ @gathers_calls_of_method = GathersCallsOfMethod.new
8
+ @stringifies_call = StringifiesCall.new
9
+ end
10
+
11
+ def raise(recording, verifiable_calls, demo_config)
12
+ Kernel.raise VerificationError.new <<~MSG
13
+ Expected mocktail of #{recording.original_type.name}##{recording.method} to be called like:
14
+
15
+ #{@stringifies_call.stringify(recording)}#{[
16
+ (" [#{demo_config.times} #{pl("time", demo_config.times)}]" unless demo_config.times.nil?),
17
+ (" [ignoring extra args]" if demo_config.ignore_extra_args),
18
+ (" [ignoring blocks]" if demo_config.ignore_block)
19
+ ].compact.join(" ")}
20
+
21
+ #{[
22
+ describe_verifiable_times_called(demo_config, verifiable_calls.size),
23
+ describe_other_calls(recording, verifiable_calls, demo_config)
24
+ ].compact.join("\n\n")}
25
+ MSG
26
+ end
27
+
28
+ private
29
+
30
+ def describe_verifiable_times_called(demo_config, count)
31
+ return if demo_config.times.nil?
32
+
33
+ if count == 0
34
+ "But it was never called this way."
35
+ else
36
+ "But it was actually called this way #{count} #{pl("time", count)}."
37
+ end
38
+ end
39
+
40
+ def describe_other_calls(recording, verifiable_calls, demo_config)
41
+ calls_of_method = @gathers_calls_of_method.gather(recording) - verifiable_calls
42
+ if calls_of_method.size == 0
43
+ if demo_config.times.nil?
44
+ "But it was never called."
45
+ end
46
+ else
47
+ <<~MSG
48
+ It was called differently #{calls_of_method.size} #{pl("time", calls_of_method.size)}:
49
+
50
+ #{calls_of_method.map { |call| " " + @stringifies_call.stringify(call) }.join("\n\n")}
51
+ MSG
52
+ end
53
+ end
54
+
55
+ def pl(s, count)
56
+ if count == 1
57
+ s
58
+ else
59
+ s + "s"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "records_demonstration"
2
+ require_relative "verifies_call/finds_verifiable_calls"
3
+ require_relative "verifies_call/raises_verification_error"
4
+
5
+ module Mocktail
6
+ class VerifiesCall
7
+ def initialize
8
+ @records_demonstration = RecordsDemonstration.new
9
+ @finds_verifiable_calls = FindsVerifiableCalls.new
10
+ @raises_verification_error = RaisesVerificationError.new
11
+ end
12
+
13
+ def verify(demo, demo_config)
14
+ recording = @records_demonstration.record(demo, demo_config)
15
+ verifiable_calls = @finds_verifiable_calls.find(recording, demo_config)
16
+
17
+ unless verification_satisfied?(verifiable_calls.size, demo_config)
18
+ @raises_verification_error.raise(recording, verifiable_calls, demo_config)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def verification_satisfied?(verifiable_call_count, demo_config)
25
+ (demo_config.times.nil? && verifiable_call_count > 0) ||
26
+ (demo_config.times == verifiable_call_count)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Mocktail
2
+ VERSION = "0.0.1"
3
+ end
data/lib/mocktail.rb ADDED
@@ -0,0 +1,63 @@
1
+ require_relative "mocktail/dsl"
2
+ require_relative "mocktail/errors"
3
+ require_relative "mocktail/handles_dry_call"
4
+ require_relative "mocktail/handles_dry_new_call"
5
+ require_relative "mocktail/imitates_type"
6
+ require_relative "mocktail/initializes_mocktail"
7
+ require_relative "mocktail/matcher_presentation"
8
+ require_relative "mocktail/matchers"
9
+ require_relative "mocktail/registers_matcher"
10
+ require_relative "mocktail/registers_stubbing"
11
+ require_relative "mocktail/replaces_next"
12
+ require_relative "mocktail/replaces_type"
13
+ require_relative "mocktail/resets_state"
14
+ require_relative "mocktail/value"
15
+ require_relative "mocktail/verifies_call"
16
+ require_relative "mocktail/version"
17
+
18
+ module Mocktail
19
+ # Returns an instance of `type` whose implementation is mocked out
20
+ def self.of(type)
21
+ ImitatesType.new.imitate(type)
22
+ end
23
+
24
+ # Returns an instance of `klass` whose implementation is mocked out AND
25
+ # stubs its constructor to return that fake the next time klass.new is called
26
+ def self.of_next(type, count: 1)
27
+ ReplacesNext.new.replace(type, count)
28
+ end
29
+
30
+ # See lib/mocktail/dsl.rb
31
+ define_singleton_method :stubs, DSL.instance_method(:stubs)
32
+ define_singleton_method :verify, DSL.instance_method(:verify)
33
+
34
+ def self.matchers
35
+ MatcherPresentation.new
36
+ end
37
+
38
+ def self.captor
39
+ Matchers::Captor.new
40
+ end
41
+
42
+ def self.register_matcher(matcher)
43
+ RegistersMatcher.new.register(matcher)
44
+ end
45
+
46
+ # Replaces every singleton method on `type` with a fake, and when instantiated
47
+ # or included will also fake instance methods
48
+ def self.replace(type)
49
+ ReplacesType.new.replace(type)
50
+ nil
51
+ end
52
+
53
+ def self.reset
54
+ ResetsState.new.reset
55
+ end
56
+
57
+ # Stores most transactional state about calls & stubbing configurations
58
+ def self.cabinet
59
+ Thread.current[:mocktail_store] ||= Cabinet.new
60
+ end
61
+ end
62
+
63
+ Mocktail::InitializesMocktail.new.init
data/mocktail.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ require_relative "lib/mocktail/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "mocktail"
5
+ spec.version = Mocktail::VERSION
6
+ spec.authors = ["Justin Searls"]
7
+ spec.email = ["searls@gmail.com"]
8
+
9
+ spec.summary = "your objects, less potency"
10
+ spec.homepage = "https://github.com/testdouble/mocktail"
11
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
12
+
13
+ spec.metadata["homepage_uri"] = spec.homepage
14
+ spec.metadata["source_code_uri"] = spec.homepage
15
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ # Uncomment to register a new dependency of your gem
27
+ # spec.add_dependency "example-gem", "~> 1.0"
28
+
29
+ # For more information and examples about making a new gem, checkout our
30
+ # guide at: https://bundler.io/guides/creating_gem.html
31
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mocktail
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Justin Searls
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-09-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - searls@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/workflows/main.yml"
21
+ - ".gitignore"
22
+ - ".standard.yml"
23
+ - CHANGELOG.md
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - bin/console
30
+ - bin/setup
31
+ - lib/mocktail.rb
32
+ - lib/mocktail/dsl.rb
33
+ - lib/mocktail/errors.rb
34
+ - lib/mocktail/handles_dry_call.rb
35
+ - lib/mocktail/handles_dry_call/fulfills_stubbing.rb
36
+ - lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb
37
+ - lib/mocktail/handles_dry_call/logs_call.rb
38
+ - lib/mocktail/handles_dry_call/validates_arguments.rb
39
+ - lib/mocktail/handles_dry_new_call.rb
40
+ - lib/mocktail/imitates_type.rb
41
+ - lib/mocktail/imitates_type/ensures_imitation_support.rb
42
+ - lib/mocktail/imitates_type/makes_double.rb
43
+ - lib/mocktail/imitates_type/makes_double/declares_dry_class.rb
44
+ - lib/mocktail/initializes_mocktail.rb
45
+ - lib/mocktail/matcher_presentation.rb
46
+ - lib/mocktail/matchers.rb
47
+ - lib/mocktail/matchers/any.rb
48
+ - lib/mocktail/matchers/base.rb
49
+ - lib/mocktail/matchers/captor.rb
50
+ - lib/mocktail/matchers/includes.rb
51
+ - lib/mocktail/matchers/is_a.rb
52
+ - lib/mocktail/matchers/matches.rb
53
+ - lib/mocktail/matchers/not.rb
54
+ - lib/mocktail/matchers/numeric.rb
55
+ - lib/mocktail/matchers/that.rb
56
+ - lib/mocktail/records_demonstration.rb
57
+ - lib/mocktail/registers_matcher.rb
58
+ - lib/mocktail/registers_stubbing.rb
59
+ - lib/mocktail/replaces_next.rb
60
+ - lib/mocktail/replaces_type.rb
61
+ - lib/mocktail/replaces_type/redefines_new.rb
62
+ - lib/mocktail/replaces_type/redefines_singleton_methods.rb
63
+ - lib/mocktail/resets_state.rb
64
+ - lib/mocktail/share/determines_matching_calls.rb
65
+ - lib/mocktail/share/simulates_argument_error.rb
66
+ - lib/mocktail/value.rb
67
+ - lib/mocktail/value/cabinet.rb
68
+ - lib/mocktail/value/call.rb
69
+ - lib/mocktail/value/demo_config.rb
70
+ - lib/mocktail/value/double.rb
71
+ - lib/mocktail/value/matcher_registry.rb
72
+ - lib/mocktail/value/stubbing.rb
73
+ - lib/mocktail/value/top_shelf.rb
74
+ - lib/mocktail/value/type_replacement.rb
75
+ - lib/mocktail/verifies_call.rb
76
+ - lib/mocktail/verifies_call/finds_verifiable_calls.rb
77
+ - lib/mocktail/verifies_call/raises_verification_error.rb
78
+ - lib/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb
79
+ - lib/mocktail/verifies_call/raises_verification_error/stringifies_call.rb
80
+ - lib/mocktail/version.rb
81
+ - mocktail.gemspec
82
+ homepage: https://github.com/testdouble/mocktail
83
+ licenses: []
84
+ metadata:
85
+ homepage_uri: https://github.com/testdouble/mocktail
86
+ source_code_uri: https://github.com/testdouble/mocktail
87
+ changelog_uri: https://github.com/testdouble/mocktail/blob/main/CHANGELOG.md
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.7.0
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubygems_version: 3.2.15
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: your objects, less potency
107
+ test_files: []