mocktail 1.2.3 → 3.0.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.
Files changed (443) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +6 -5
  3. data/.gitignore +3 -0
  4. data/.standard.yml +8 -0
  5. data/CHANGELOG.md +19 -0
  6. data/Gemfile +8 -2
  7. data/Gemfile.lock +105 -38
  8. data/README.md +20 -922
  9. data/Rakefile +0 -1
  10. data/bin/console +1 -2
  11. data/bin/tapioca +29 -0
  12. data/docs/code_of_conduct.md +8 -0
  13. data/docs/configuring_minitest.md +20 -0
  14. data/docs/configuring_rspec.md +19 -0
  15. data/docs/example_test.md +594 -0
  16. data/docs/faq/existing_tests.md +47 -0
  17. data/docs/faq/mocking_http.md +151 -0
  18. data/docs/faq/mocking_the_subject.md +161 -0
  19. data/docs/faq/mocking_time.md +34 -0
  20. data/docs/faq/partial_mocks.md +34 -0
  21. data/docs/faq/verifying_real_interactions.md +52 -0
  22. data/docs/img/delegator_tree.png +0 -0
  23. data/docs/img/example_test.png +0 -0
  24. data/docs/img/extract_transform_load.png +0 -0
  25. data/docs/img/mocktail_sorbet.jpg +0 -0
  26. data/docs/img/mocktail_untyped.jpg +0 -0
  27. data/docs/img/spacer.png +0 -0
  28. data/docs/installation_sorbet.md +99 -0
  29. data/docs/installation_untyped.md +29 -0
  30. data/docs/other_uses.md +32 -0
  31. data/docs/stubbing_and_verifying.md +515 -0
  32. data/docs/support/api.md +819 -0
  33. data/docs/support/example_test.rb +94 -0
  34. data/docs/support/glossary.md +426 -0
  35. data/docs/tdd/class_methods.md +44 -0
  36. data/docs/tdd/poro/dependency_inception.md +136 -0
  37. data/docs/tdd/poro/dependency_injection.md +82 -0
  38. data/docs/tdd/poro.md +15 -0
  39. data/docs/tdd/third_party.md +220 -0
  40. data/docs/tdd.md +15 -0
  41. data/lib/mocktail/collects_calls.rb +2 -0
  42. data/lib/mocktail/debug.rb +16 -12
  43. data/lib/mocktail/dsl.rb +2 -0
  44. data/lib/mocktail/errors.rb +2 -0
  45. data/lib/mocktail/explains_nils.rb +2 -0
  46. data/lib/mocktail/explains_thing.rb +7 -4
  47. data/lib/mocktail/grabs_original_method_parameters.rb +30 -0
  48. data/lib/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +3 -1
  49. data/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +5 -1
  50. data/lib/mocktail/handles_dry_call/fulfills_stubbing.rb +2 -0
  51. data/lib/mocktail/handles_dry_call/logs_call.rb +2 -0
  52. data/lib/mocktail/handles_dry_call/validates_arguments.rb +6 -4
  53. data/lib/mocktail/handles_dry_call.rb +2 -0
  54. data/lib/mocktail/handles_dry_new_call.rb +2 -0
  55. data/lib/mocktail/imitates_type/ensures_imitation_support.rb +2 -0
  56. data/lib/mocktail/imitates_type/makes_double/declares_dry_class/reconstructs_call.rb +4 -1
  57. data/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb +32 -20
  58. data/lib/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +2 -0
  59. data/lib/mocktail/imitates_type/makes_double.rb +3 -0
  60. data/lib/mocktail/imitates_type.rb +3 -1
  61. data/lib/mocktail/initialize_based_on_type_system_mode_switching.rb +9 -0
  62. data/lib/mocktail/initializes_mocktail.rb +5 -0
  63. data/lib/mocktail/matcher_presentation.rb +4 -2
  64. data/lib/mocktail/matchers/any.rb +4 -3
  65. data/lib/mocktail/matchers/base.rb +10 -2
  66. data/lib/mocktail/matchers/captor.rb +9 -0
  67. data/lib/mocktail/matchers/includes.rb +2 -0
  68. data/lib/mocktail/matchers/includes_hash.rb +9 -0
  69. data/lib/mocktail/matchers/includes_key.rb +9 -0
  70. data/lib/mocktail/matchers/includes_string.rb +9 -0
  71. data/lib/mocktail/matchers/is_a.rb +2 -0
  72. data/lib/mocktail/matchers/matches.rb +2 -0
  73. data/lib/mocktail/matchers/not.rb +2 -0
  74. data/lib/mocktail/matchers/numeric.rb +5 -4
  75. data/lib/mocktail/matchers/that.rb +2 -0
  76. data/lib/mocktail/matchers.rb +3 -0
  77. data/lib/mocktail/raises_neato_no_method_error.rb +2 -0
  78. data/lib/mocktail/records_demonstration.rb +2 -0
  79. data/lib/mocktail/registers_matcher.rb +8 -3
  80. data/lib/mocktail/registers_stubbing.rb +2 -0
  81. data/lib/mocktail/replaces_next.rb +7 -1
  82. data/lib/mocktail/replaces_type/redefines_new.rb +3 -1
  83. data/lib/mocktail/replaces_type/redefines_singleton_methods.rb +14 -2
  84. data/lib/mocktail/replaces_type/runs_sorbet_sig_blocks_before_replacement.rb +37 -0
  85. data/lib/mocktail/replaces_type.rb +6 -0
  86. data/lib/mocktail/resets_state.rb +2 -0
  87. data/lib/mocktail/share/bind.rb +7 -5
  88. data/lib/mocktail/share/cleans_backtrace.rb +3 -5
  89. data/lib/mocktail/share/creates_identifier.rb +16 -9
  90. data/lib/mocktail/share/determines_matching_calls.rb +4 -2
  91. data/lib/mocktail/share/stringifies_call.rb +6 -3
  92. data/lib/mocktail/share/stringifies_method_name.rb +3 -1
  93. data/lib/mocktail/simulates_argument_error/reconciles_args_with_params.rb +2 -0
  94. data/lib/mocktail/simulates_argument_error/recreates_message.rb +2 -0
  95. data/lib/mocktail/simulates_argument_error/transforms_params.rb +16 -9
  96. data/lib/mocktail/simulates_argument_error.rb +2 -0
  97. data/lib/mocktail/sorbet/mocktail/collects_calls.rb +18 -0
  98. data/lib/mocktail/sorbet/mocktail/debug.rb +55 -0
  99. data/lib/mocktail/sorbet/mocktail/dsl.rb +46 -0
  100. data/lib/mocktail/sorbet/mocktail/errors.rb +19 -0
  101. data/lib/mocktail/sorbet/mocktail/explains_nils.rb +41 -0
  102. data/lib/mocktail/sorbet/mocktail/explains_thing.rb +137 -0
  103. data/lib/mocktail/sorbet/mocktail/grabs_original_method_parameters.rb +33 -0
  104. data/lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +27 -0
  105. data/lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +24 -0
  106. data/lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing.rb +45 -0
  107. data/lib/mocktail/sorbet/mocktail/handles_dry_call/logs_call.rb +12 -0
  108. data/lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb +45 -0
  109. data/lib/mocktail/sorbet/mocktail/handles_dry_call.rb +25 -0
  110. data/lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb +42 -0
  111. data/lib/mocktail/sorbet/mocktail/imitates_type/ensures_imitation_support.rb +16 -0
  112. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double/declares_dry_class/reconstructs_call.rb +73 -0
  113. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double/declares_dry_class.rb +136 -0
  114. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +28 -0
  115. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double.rb +29 -0
  116. data/lib/mocktail/sorbet/mocktail/imitates_type.rb +29 -0
  117. data/lib/mocktail/sorbet/mocktail/initialize_based_on_type_system_mode_switching.rb +11 -0
  118. data/lib/mocktail/sorbet/mocktail/initializes_mocktail.rb +25 -0
  119. data/lib/mocktail/sorbet/mocktail/matcher_presentation.rb +21 -0
  120. data/lib/mocktail/sorbet/mocktail/matchers/any.rb +27 -0
  121. data/lib/mocktail/sorbet/mocktail/matchers/base.rb +39 -0
  122. data/lib/mocktail/sorbet/mocktail/matchers/captor.rb +76 -0
  123. data/lib/mocktail/sorbet/mocktail/matchers/includes.rb +32 -0
  124. data/lib/mocktail/sorbet/mocktail/matchers/includes_hash.rb +12 -0
  125. data/lib/mocktail/sorbet/mocktail/matchers/includes_key.rb +12 -0
  126. data/lib/mocktail/sorbet/mocktail/matchers/includes_string.rb +12 -0
  127. data/lib/mocktail/sorbet/mocktail/matchers/is_a.rb +17 -0
  128. data/lib/mocktail/sorbet/mocktail/matchers/matches.rb +19 -0
  129. data/lib/mocktail/sorbet/mocktail/matchers/not.rb +17 -0
  130. data/lib/mocktail/sorbet/mocktail/matchers/numeric.rb +27 -0
  131. data/lib/mocktail/sorbet/mocktail/matchers/that.rb +32 -0
  132. data/lib/mocktail/sorbet/mocktail/matchers.rb +19 -0
  133. data/lib/mocktail/sorbet/mocktail/raises_neato_no_method_error.rb +93 -0
  134. data/lib/mocktail/sorbet/mocktail/records_demonstration.rb +43 -0
  135. data/lib/mocktail/sorbet/mocktail/registers_matcher.rb +65 -0
  136. data/lib/mocktail/sorbet/mocktail/registers_stubbing.rb +31 -0
  137. data/lib/mocktail/sorbet/mocktail/replaces_next.rb +55 -0
  138. data/lib/mocktail/sorbet/mocktail/replaces_type/redefines_new.rb +32 -0
  139. data/lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb +80 -0
  140. data/lib/mocktail/sorbet/mocktail/replaces_type/runs_sorbet_sig_blocks_before_replacement.rb +39 -0
  141. data/lib/mocktail/sorbet/mocktail/replaces_type.rb +36 -0
  142. data/lib/mocktail/sorbet/mocktail/resets_state.rb +14 -0
  143. data/lib/mocktail/sorbet/mocktail/share/bind.rb +18 -0
  144. data/lib/mocktail/sorbet/mocktail/share/cleans_backtrace.rb +22 -0
  145. data/lib/mocktail/sorbet/mocktail/share/creates_identifier.rb +39 -0
  146. data/lib/mocktail/sorbet/mocktail/share/determines_matching_calls.rb +72 -0
  147. data/lib/mocktail/sorbet/mocktail/share/stringifies_call.rb +84 -0
  148. data/lib/mocktail/sorbet/mocktail/share/stringifies_method_name.rb +16 -0
  149. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/reconciles_args_with_params.rb +27 -0
  150. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/recreates_message.rb +34 -0
  151. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/transforms_params.rb +58 -0
  152. data/lib/mocktail/sorbet/mocktail/simulates_argument_error.rb +36 -0
  153. data/lib/mocktail/sorbet/mocktail/sorbet.rb +3 -0
  154. data/lib/mocktail/sorbet/mocktail/stringifies_method_signature.rb +53 -0
  155. data/lib/mocktail/sorbet/mocktail/typed.rb +5 -0
  156. data/lib/mocktail/sorbet/mocktail/value/cabinet.rb +91 -0
  157. data/lib/mocktail/sorbet/mocktail/value/call.rb +51 -0
  158. data/lib/mocktail/sorbet/mocktail/value/demo_config.rb +10 -0
  159. data/lib/mocktail/sorbet/mocktail/value/double.rb +10 -0
  160. data/lib/mocktail/sorbet/mocktail/value/double_data.rb +15 -0
  161. data/lib/mocktail/sorbet/mocktail/value/explanation.rb +68 -0
  162. data/lib/mocktail/sorbet/mocktail/value/explanation_data.rb +19 -0
  163. data/lib/mocktail/sorbet/mocktail/value/fake_method_data.rb +11 -0
  164. data/lib/mocktail/sorbet/mocktail/value/matcher_registry.rb +27 -0
  165. data/lib/mocktail/sorbet/mocktail/value/no_explanation_data.rb +20 -0
  166. data/lib/mocktail/sorbet/mocktail/value/signature.rb +35 -0
  167. data/lib/mocktail/sorbet/mocktail/value/stubbing.rb +26 -0
  168. data/lib/mocktail/sorbet/mocktail/value/top_shelf.rb +79 -0
  169. data/lib/mocktail/sorbet/mocktail/value/type_replacement.rb +11 -0
  170. data/lib/mocktail/sorbet/mocktail/value/type_replacement_data.rb +19 -0
  171. data/lib/mocktail/sorbet/mocktail/value/unsatisfying_call.rb +9 -0
  172. data/lib/mocktail/sorbet/mocktail/value/unsatisfying_call_explanation.rb +24 -0
  173. data/lib/mocktail/sorbet/mocktail/value.rb +19 -0
  174. data/lib/mocktail/sorbet/mocktail/verifies_call/finds_verifiable_calls.rb +21 -0
  175. data/lib/mocktail/sorbet/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +15 -0
  176. data/lib/mocktail/sorbet/mocktail/verifies_call/raises_verification_error.rb +74 -0
  177. data/lib/mocktail/sorbet/mocktail/verifies_call.rb +37 -0
  178. data/lib/mocktail/sorbet/mocktail/version.rb +12 -0
  179. data/lib/mocktail/sorbet/mocktail.rb +154 -0
  180. data/lib/mocktail/sorbet.rb +1 -0
  181. data/lib/mocktail/stringifies_method_signature.rb +2 -0
  182. data/lib/mocktail/typed.rb +3 -0
  183. data/lib/mocktail/value/cabinet.rb +8 -1
  184. data/lib/mocktail/value/call.rb +44 -12
  185. data/lib/mocktail/value/demo_config.rb +6 -7
  186. data/lib/mocktail/value/double.rb +6 -7
  187. data/lib/mocktail/value/double_data.rb +11 -7
  188. data/lib/mocktail/value/explanation.rb +28 -3
  189. data/lib/mocktail/value/explanation_data.rb +14 -0
  190. data/lib/mocktail/value/fake_method_data.rb +7 -6
  191. data/lib/mocktail/value/matcher_registry.rb +2 -0
  192. data/lib/mocktail/value/no_explanation_data.rb +16 -0
  193. data/lib/mocktail/value/signature.rb +19 -27
  194. data/lib/mocktail/value/stubbing.rb +11 -12
  195. data/lib/mocktail/value/top_shelf.rb +5 -0
  196. data/lib/mocktail/value/type_replacement.rb +7 -8
  197. data/lib/mocktail/value/type_replacement_data.rb +10 -7
  198. data/lib/mocktail/value/unsatisfying_call.rb +5 -6
  199. data/lib/mocktail/value/unsatisfying_call_explanation.rb +18 -0
  200. data/lib/mocktail/value.rb +5 -2
  201. data/lib/mocktail/verifies_call/finds_verifiable_calls.rb +2 -0
  202. data/lib/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +2 -0
  203. data/lib/mocktail/verifies_call/raises_verification_error.rb +2 -0
  204. data/lib/mocktail/verifies_call.rb +3 -0
  205. data/lib/mocktail/version.rb +8 -1
  206. data/lib/mocktail.rb +46 -5
  207. data/mocktail.gemspec +8 -4
  208. data/rbi/mocktail-pregenerated.rbi +1923 -0
  209. data/rbi/mocktail.rbi +77 -0
  210. data/rbi/sorbet-runtime.rbi +29 -0
  211. data/script/build +47 -0
  212. data/script/setup +17 -0
  213. data/script/spoom_me +7 -0
  214. data/script/strip_sigils +17 -0
  215. data/script/test +33 -0
  216. data/script/test_double_require_warnings +46 -0
  217. data/script/update +21 -0
  218. data/sorbet/config +12 -0
  219. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  220. data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  221. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1083 -0
  222. data/sorbet/rbi/gems/docile@1.4.0.rbi +376 -0
  223. data/sorbet/rbi/gems/json@2.6.3.rbi +1533 -0
  224. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14237 -0
  225. data/sorbet/rbi/gems/lint_roller@1.0.0.rbi +230 -0
  226. data/sorbet/rbi/gems/m@1.6.1.rbi +257 -0
  227. data/sorbet/rbi/gems/method_source@1.0.0.rbi +272 -0
  228. data/sorbet/rbi/gems/minitest@5.18.0.rbi +1491 -0
  229. data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  230. data/sorbet/rbi/gems/parallel@1.23.0.rbi +273 -0
  231. data/sorbet/rbi/gems/parser@3.2.2.1.rbi +7253 -0
  232. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
  233. data/sorbet/rbi/gems/rake@13.0.6.rbi +3024 -0
  234. data/sorbet/rbi/gems/rbi@0.0.16.rbi +3049 -0
  235. data/sorbet/rbi/gems/regexp_parser@2.8.0.rbi +3748 -0
  236. data/sorbet/rbi/gems/rexml@3.2.5.rbi +4717 -0
  237. data/sorbet/rbi/gems/rubocop-ast@1.29.0.rbi +7003 -0
  238. data/sorbet/rbi/gems/rubocop-performance@1.18.0.rbi +8 -0
  239. data/sorbet/rbi/gems/rubocop-sorbet@0.7.0.rbi +1043 -0
  240. data/sorbet/rbi/gems/rubocop@1.52.0.rbi +55500 -0
  241. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1317 -0
  242. data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +216 -0
  243. data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2148 -0
  244. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +8 -0
  245. data/sorbet/rbi/gems/spoom@1.2.1.rbi +2536 -0
  246. data/sorbet/rbi/gems/standard-custom@1.0.1.rbi +63 -0
  247. data/sorbet/rbi/gems/standard-performance@1.1.0.rbi +8 -0
  248. data/sorbet/rbi/gems/standard@1.29.0.rbi +850 -0
  249. data/sorbet/rbi/gems/tapioca@0.11.6.rbi +3301 -0
  250. data/sorbet/rbi/gems/thor@1.2.2.rbi +3965 -0
  251. data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +65 -0
  252. data/sorbet/rbi/gems/unparser@0.6.7.rbi +4524 -0
  253. data/sorbet/rbi/gems/yard-sorbet@0.8.1.rbi +428 -0
  254. data/sorbet/rbi/gems/yard@0.9.34.rbi +18219 -0
  255. data/sorbet/tapioca/config.yml +13 -0
  256. data/sorbet/tapioca/require.rb +4 -0
  257. data/spoom_data/05f0c49.json +1 -0
  258. data/spoom_data/1657012.json +1 -0
  259. data/spoom_data/167434b.json +1 -0
  260. data/spoom_data/1d0ba5b.json +1 -0
  261. data/spoom_data/1ffa724.json +1 -0
  262. data/spoom_data/2129b3d.json +1 -0
  263. data/spoom_data/24b1c92.json +1 -0
  264. data/spoom_data/2c46aee.json +1 -0
  265. data/spoom_data/305ec0b.json +1 -0
  266. data/spoom_data/30e9528.json +1 -0
  267. data/spoom_data/4638cd5.json +1 -0
  268. data/spoom_data/47c7dad.json +1 -0
  269. data/spoom_data/4b1edef.json +1 -0
  270. data/spoom_data/4de157f.json +1 -0
  271. data/spoom_data/526e7db.json +1 -0
  272. data/spoom_data/5d093b9.json +1 -0
  273. data/spoom_data/5db3b43.json +1 -0
  274. data/spoom_data/5fe2a65.json +1 -0
  275. data/spoom_data/6891312.json +1 -0
  276. data/spoom_data/6b0fef4.json +1 -0
  277. data/spoom_data/6b83d12.json +1 -0
  278. data/spoom_data/74c83c2.json +1 -0
  279. data/spoom_data/7644ff4.json +1 -0
  280. data/spoom_data/79054db.json +1 -0
  281. data/spoom_data/814e515.json +1 -0
  282. data/spoom_data/88c3b60.json +1 -0
  283. data/spoom_data/8bd4b6e.json +1 -0
  284. data/spoom_data/93f8153.json +1 -0
  285. data/spoom_data/95242fe.json +1 -0
  286. data/spoom_data/97f4c09.json +1 -0
  287. data/spoom_data/a13d150.json +1 -0
  288. data/spoom_data/a17f215.json +1 -0
  289. data/spoom_data/b705a9d.json +1 -0
  290. data/spoom_data/ba19195.json +1 -0
  291. data/spoom_data/bef51ca.json +1 -0
  292. data/spoom_data/dbb595a.json +1 -0
  293. data/spoom_data/e8fab92.json +1 -0
  294. data/spoom_data/f166c87.json +1 -0
  295. data/spoom_data/f57992d.json +1 -0
  296. data/spoom_data/f5a1e40.json +1 -0
  297. data/spoom_data/f6d6431.json +1 -0
  298. data/spoom_data/f72b67c.json +1 -0
  299. data/spoom_data/fc2f231.json +1 -0
  300. data/spoom_report.html +1248 -0
  301. data/src/mocktail/collects_calls.rb +18 -0
  302. data/src/mocktail/debug.rb +55 -0
  303. data/src/mocktail/dsl.rb +46 -0
  304. data/src/mocktail/errors.rb +19 -0
  305. data/src/mocktail/explains_nils.rb +41 -0
  306. data/src/mocktail/explains_thing.rb +137 -0
  307. data/src/mocktail/grabs_original_method_parameters.rb +33 -0
  308. data/src/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +27 -0
  309. data/src/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +24 -0
  310. data/src/mocktail/handles_dry_call/fulfills_stubbing.rb +45 -0
  311. data/src/mocktail/handles_dry_call/logs_call.rb +12 -0
  312. data/src/mocktail/handles_dry_call/validates_arguments.rb +45 -0
  313. data/src/mocktail/handles_dry_call.rb +25 -0
  314. data/src/mocktail/handles_dry_new_call.rb +42 -0
  315. data/src/mocktail/imitates_type/ensures_imitation_support.rb +16 -0
  316. data/src/mocktail/imitates_type/makes_double/declares_dry_class/reconstructs_call.rb +73 -0
  317. data/src/mocktail/imitates_type/makes_double/declares_dry_class.rb +136 -0
  318. data/src/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +28 -0
  319. data/src/mocktail/imitates_type/makes_double.rb +29 -0
  320. data/src/mocktail/imitates_type.rb +29 -0
  321. data/src/mocktail/initialize_based_on_type_system_mode_switching.rb +11 -0
  322. data/src/mocktail/initializes_mocktail.rb +25 -0
  323. data/src/mocktail/matcher_presentation.rb +21 -0
  324. data/src/mocktail/matchers/any.rb +27 -0
  325. data/src/mocktail/matchers/base.rb +39 -0
  326. data/src/mocktail/matchers/captor.rb +76 -0
  327. data/src/mocktail/matchers/includes.rb +32 -0
  328. data/src/mocktail/matchers/includes_hash.rb +12 -0
  329. data/src/mocktail/matchers/includes_key.rb +12 -0
  330. data/src/mocktail/matchers/includes_string.rb +12 -0
  331. data/src/mocktail/matchers/is_a.rb +17 -0
  332. data/src/mocktail/matchers/matches.rb +19 -0
  333. data/src/mocktail/matchers/not.rb +17 -0
  334. data/src/mocktail/matchers/numeric.rb +27 -0
  335. data/src/mocktail/matchers/that.rb +32 -0
  336. data/src/mocktail/matchers.rb +19 -0
  337. data/src/mocktail/raises_neato_no_method_error.rb +93 -0
  338. data/src/mocktail/records_demonstration.rb +43 -0
  339. data/src/mocktail/registers_matcher.rb +65 -0
  340. data/src/mocktail/registers_stubbing.rb +31 -0
  341. data/src/mocktail/replaces_next.rb +55 -0
  342. data/src/mocktail/replaces_type/redefines_new.rb +32 -0
  343. data/src/mocktail/replaces_type/redefines_singleton_methods.rb +80 -0
  344. data/src/mocktail/replaces_type/runs_sorbet_sig_blocks_before_replacement.rb +39 -0
  345. data/src/mocktail/replaces_type.rb +36 -0
  346. data/src/mocktail/resets_state.rb +14 -0
  347. data/src/mocktail/share/bind.rb +18 -0
  348. data/src/mocktail/share/cleans_backtrace.rb +22 -0
  349. data/src/mocktail/share/creates_identifier.rb +39 -0
  350. data/src/mocktail/share/determines_matching_calls.rb +72 -0
  351. data/src/mocktail/share/stringifies_call.rb +84 -0
  352. data/src/mocktail/share/stringifies_method_name.rb +16 -0
  353. data/src/mocktail/simulates_argument_error/reconciles_args_with_params.rb +27 -0
  354. data/src/mocktail/simulates_argument_error/recreates_message.rb +34 -0
  355. data/src/mocktail/simulates_argument_error/transforms_params.rb +58 -0
  356. data/src/mocktail/simulates_argument_error.rb +36 -0
  357. data/src/mocktail/sorbet.rb +3 -0
  358. data/src/mocktail/stringifies_method_signature.rb +53 -0
  359. data/src/mocktail/typed.rb +5 -0
  360. data/src/mocktail/value/cabinet.rb +91 -0
  361. data/src/mocktail/value/call.rb +51 -0
  362. data/src/mocktail/value/demo_config.rb +10 -0
  363. data/src/mocktail/value/double.rb +10 -0
  364. data/src/mocktail/value/double_data.rb +15 -0
  365. data/src/mocktail/value/explanation.rb +68 -0
  366. data/src/mocktail/value/explanation_data.rb +19 -0
  367. data/src/mocktail/value/fake_method_data.rb +11 -0
  368. data/src/mocktail/value/matcher_registry.rb +27 -0
  369. data/src/mocktail/value/no_explanation_data.rb +20 -0
  370. data/src/mocktail/value/signature.rb +35 -0
  371. data/src/mocktail/value/stubbing.rb +26 -0
  372. data/src/mocktail/value/top_shelf.rb +79 -0
  373. data/src/mocktail/value/type_replacement.rb +11 -0
  374. data/src/mocktail/value/type_replacement_data.rb +19 -0
  375. data/src/mocktail/value/unsatisfying_call.rb +9 -0
  376. data/src/mocktail/value/unsatisfying_call_explanation.rb +24 -0
  377. data/src/mocktail/value.rb +19 -0
  378. data/src/mocktail/verifies_call/finds_verifiable_calls.rb +21 -0
  379. data/src/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +15 -0
  380. data/src/mocktail/verifies_call/raises_verification_error.rb +74 -0
  381. data/src/mocktail/verifies_call.rb +37 -0
  382. data/src/mocktail/version.rb +12 -0
  383. data/src/mocktail.rb +154 -0
  384. data/sub_projects/rbi_generator/Gemfile +4 -0
  385. data/sub_projects/rbi_generator/Gemfile.lock +63 -0
  386. data/sub_projects/rbi_generator/sorbet/rbi/gems/.gitattributes +1 -0
  387. data/sub_projects/sorbet_user/Gemfile +13 -0
  388. data/sub_projects/sorbet_user/Gemfile.lock +126 -0
  389. data/sub_projects/sorbet_user/Rakefile +10 -0
  390. data/sub_projects/sorbet_user/bin/tapioca +27 -0
  391. data/sub_projects/sorbet_user/rbi/mocktail.rbi +9 -0
  392. data/sub_projects/sorbet_user/script/test +13 -0
  393. data/sub_projects/sorbet_user/sorbet/config +4 -0
  394. data/sub_projects/sorbet_user/sorbet/rbi/gems/.gitattributes +1 -0
  395. data/sub_projects/sorbet_user/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
  396. data/sub_projects/sorbet_user/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
  397. data/sub_projects/sorbet_user/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  398. data/sub_projects/sorbet_user/sorbet/rbi/gems/json@2.21.2.rbi +2140 -0
  399. data/sub_projects/sorbet_user/sorbet/rbi/gems/language_server-protocol@3.17.0.4.rbi +14244 -0
  400. data/sub_projects/sorbet_user/sorbet/rbi/gems/lint_roller@1.1.0.rbi +239 -0
  401. data/sub_projects/sorbet_user/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
  402. data/sub_projects/sorbet_user/sorbet/rbi/gems/m@1.6.2.rbi +258 -0
  403. data/sub_projects/sorbet_user/sorbet/rbi/gems/method_source@1.1.0.rbi +9 -0
  404. data/sub_projects/sorbet_user/sorbet/rbi/gems/minitest@5.27.0.rbi +1549 -0
  405. data/sub_projects/sorbet_user/sorbet/rbi/gems/mocktail@3.0.0.rbi +1923 -0
  406. data/sub_projects/sorbet_user/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  407. data/sub_projects/sorbet_user/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  408. data/sub_projects/sorbet_user/sorbet/rbi/gems/parser@3.3.7.4.rbi +5451 -0
  409. data/sub_projects/sorbet_user/sorbet/rbi/gems/prism@1.4.0.rbi +41732 -0
  410. data/sub_projects/sorbet_user/sorbet/rbi/gems/racc@1.8.1.rbi +164 -0
  411. data/sub_projects/sorbet_user/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
  412. data/sub_projects/sorbet_user/sorbet/rbi/gems/rake@13.2.1.rbi +3028 -0
  413. data/sub_projects/sorbet_user/sorbet/rbi/gems/rbi@0.3.1.rbi +6599 -0
  414. data/sub_projects/sorbet_user/sorbet/rbi/gems/rbs@3.9.2.rbi +6976 -0
  415. data/sub_projects/sorbet_user/sorbet/rbi/gems/regexp_parser@2.10.0.rbi +3795 -0
  416. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop-ast@1.43.0.rbi +7717 -0
  417. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop-performance@1.24.0.rbi +9 -0
  418. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop-sorbet@0.9.0.rbi +9 -0
  419. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop@1.73.2.rbi +61306 -0
  420. data/sub_projects/sorbet_user/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1317 -0
  421. data/sub_projects/sorbet_user/sorbet/rbi/gems/sorbet-eraser@0.3.1.rbi +8 -0
  422. data/sub_projects/sorbet_user/sorbet/rbi/gems/spoom@1.6.1.rbi +7274 -0
  423. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard-custom@1.0.2.rbi +8 -0
  424. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard-performance@1.7.0.rbi +9 -0
  425. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard-sorbet@0.0.3.rbi +53 -0
  426. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard@1.47.0.rbi +935 -0
  427. data/sub_projects/sorbet_user/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
  428. data/sub_projects/sorbet_user/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  429. data/sub_projects/sorbet_user/sorbet/rbi/gems/unicode-display_width@3.1.4.rbi +132 -0
  430. data/sub_projects/sorbet_user/sorbet/rbi/gems/unicode-emoji@4.2.0.rbi +254 -0
  431. data/sub_projects/sorbet_user/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  432. data/sub_projects/sorbet_user/sorbet/rbi/gems/yard@0.9.45.rbi +18916 -0
  433. data/sub_projects/sorbet_user/sorbet/tapioca/config.yml +13 -0
  434. data/sub_projects/sorbet_user/sorbet/tapioca/require.rb +4 -0
  435. data/sub_projects/sorbet_user/test/ensure_type_safety_test.rb +21 -0
  436. data/sub_projects/sorbet_user/test/paint_by_number_test.rb +113 -0
  437. data/sub_projects/sorbet_user/test/sorbet_test.rb +289 -0
  438. data/sub_projects/sorbet_user/test/test_helper.rb +35 -0
  439. data/sub_projects/untyped_user/Gemfile +4 -0
  440. data/sub_projects/untyped_user/Gemfile.lock +25 -0
  441. data/sub_projects/untyped_user/antitype_test.rb +54 -0
  442. data/sub_projects/untyped_user/script/test +5 -0
  443. metadata +392 -9
@@ -0,0 +1,154 @@
1
+ # typed: strict
2
+
3
+ require "pathname"
4
+
5
+ if defined?(Mocktail::TYPED)
6
+ if eval("Mocktail::TYPED", binding, __FILE__, __LINE__)
7
+ warn "`require \"mocktail\"' was called, but Mocktail was already required as `require \"mocktail/sorbet\"', so we're NOT going to load it to avoid constants from being redefined. If you want to use Mocktail WITHOUT sorbet runtime checks, remove whatever is requiring `mocktail/sorbet'."
8
+ else
9
+ warn "`require \"mocktail/sorbet\"' was called, but Mocktail was already required as `require \"mocktail\"', so we're NOT going to load it to avoid constants from being redefined. If you want to use Mocktail WITH sorbet runtime checks, remove whatever is requiring `mocktail'."
10
+ end
11
+ return
12
+ end
13
+
14
+ require_relative "mocktail/initialize_based_on_type_system_mode_switching"
15
+
16
+ require_relative "mocktail/collects_calls"
17
+ require_relative "mocktail/debug"
18
+ require_relative "mocktail/dsl"
19
+ require_relative "mocktail/errors"
20
+ require_relative "mocktail/explains_thing"
21
+ require_relative "mocktail/explains_nils"
22
+ require_relative "mocktail/grabs_original_method_parameters"
23
+ require_relative "mocktail/handles_dry_call"
24
+ require_relative "mocktail/handles_dry_new_call"
25
+ require_relative "mocktail/imitates_type"
26
+ require_relative "mocktail/initializes_mocktail"
27
+ require_relative "mocktail/matcher_presentation"
28
+ require_relative "mocktail/matchers"
29
+ require_relative "mocktail/raises_neato_no_method_error"
30
+ require_relative "mocktail/registers_matcher"
31
+ require_relative "mocktail/registers_stubbing"
32
+ require_relative "mocktail/replaces_next"
33
+ require_relative "mocktail/replaces_type"
34
+ require_relative "mocktail/resets_state"
35
+ require_relative "mocktail/simulates_argument_error"
36
+ require_relative "mocktail/stringifies_method_signature"
37
+ require_relative "mocktail/value"
38
+ require_relative "mocktail/verifies_call"
39
+ require_relative "mocktail/version"
40
+
41
+ module Mocktail
42
+ extend T::Sig
43
+ extend DSL
44
+ BASE_PATH = T.let((Pathname.new(__FILE__) + "..").to_s, String)
45
+
46
+ # Returns an instance of `type` whose implementation is mocked out
47
+ sig {
48
+ type_parameters(:T)
49
+ .params(type: T::Class[T.all(T.type_parameter(:T), Object)])
50
+ .returns(T.all(T.type_parameter(:T), Object))
51
+ }
52
+ def self.of(type)
53
+ ImitatesType.new.imitate(type)
54
+ end
55
+
56
+ # Returns an instance of `klass` whose implementation is mocked out AND
57
+ # stubs its constructor to return that fake the next time klass.new is called
58
+ sig {
59
+ type_parameters(:T)
60
+ .params(type: T::Class[T.all(T.type_parameter(:T), Object)], count: T.nilable(Integer))
61
+ .returns(T.type_parameter(:T))
62
+ }
63
+ def self.of_next(type, count: 1)
64
+ count ||= 1
65
+ if count == 1
66
+ ReplacesNext.new.replace_once(type)
67
+ elsif !T.unsafe(Mocktail::TYPED) || T::Private::RuntimeLevels.default_checked_level == :never
68
+ T.unsafe(ReplacesNext.new).replace(type, count)
69
+ else
70
+ raise TypeCheckingError.new <<~MSG
71
+ Calling `Mocktail.of_next()' with a `count' value other than 1 is not supported when
72
+ type checking is enabled. There are two ways to fix this:
73
+
74
+ 1. Use `Mocktail.of_next_with_count(type, count)' instead, which will always return
75
+ an array of fake objects.
76
+
77
+ 2. Disable runtime type checking by setting `T::Private::RuntimeLevels.default_checked_level = :never'
78
+ or by setting the envronment variable `SORBET_RUNTIME_DEFAULT_CHECKED_LEVEL=never'
79
+ MSG
80
+ end
81
+ end
82
+
83
+ # An alias of of_next that always returns an array of fakes
84
+ sig {
85
+ type_parameters(:T)
86
+ .params(type: T::Class[T.all(T.type_parameter(:T), Object)], count: Integer)
87
+ .returns(T::Array[T.type_parameter(:T)])
88
+ }
89
+ def self.of_next_with_count(type, count)
90
+ ReplacesNext.new.replace(type, count)
91
+ end
92
+
93
+ sig { returns(Mocktail::MatcherPresentation) }
94
+ def self.matchers
95
+ MatcherPresentation.new
96
+ end
97
+
98
+ sig { returns(Mocktail::Matchers::Captor) }
99
+ def self.captor
100
+ Matchers::Captor.new
101
+ end
102
+
103
+ sig { params(matcher: T.class_of(Mocktail::Matchers::Base)).void }
104
+ def self.register_matcher(matcher)
105
+ RegistersMatcher.new.register(matcher)
106
+ end
107
+
108
+ # Replaces every singleton method on `type` with a fake, and when instantiated
109
+ # or included will also fake instance methods
110
+ sig { params(type: T.any(T::Class[T.anything], Module)).void }
111
+ def self.replace(type)
112
+ ReplacesType.new.replace(type)
113
+ nil
114
+ end
115
+
116
+ sig { void }
117
+ def self.reset
118
+ ResetsState.new.reset
119
+ end
120
+
121
+ sig {
122
+ params(thing: Object)
123
+ .returns(Explanation)
124
+ }
125
+ def self.explain(thing)
126
+ ExplainsThing.new.explain(thing)
127
+ end
128
+
129
+ sig { returns(T::Array[Mocktail::UnsatisfyingCallExplanation]) }
130
+ def self.explain_nils
131
+ ExplainsNils.new.explain
132
+ end
133
+
134
+ # An alias for Mocktail.explain(double).reference.calls
135
+ # Takes an optional second parameter of the method name to filter only
136
+ # calls to that method
137
+ sig {
138
+ params(double: Object, method_name: T.nilable(T.any(String, Symbol)))
139
+ .returns(T::Array[Mocktail::Call])
140
+ }
141
+ def self.calls(double, method_name = nil)
142
+ CollectsCalls.new.collect(double, method_name&.to_sym)
143
+ end
144
+
145
+ # Stores most transactional state about calls & stubbing configurations
146
+ # Anything returned by this is undocumented and could change at any time, so
147
+ # don't commit code that relies on it!
148
+ sig { returns Cabinet }
149
+ def self.cabinet
150
+ Thread.current[:mocktail_store] ||= Cabinet.new
151
+ end
152
+ end
153
+
154
+ Mocktail::InitializesMocktail.new.init
@@ -0,0 +1 @@
1
+ require_relative "sorbet/mocktail"
@@ -1,5 +1,7 @@
1
1
  module Mocktail
2
2
  class StringifiesMethodSignature
3
+ extend T::Sig
4
+
3
5
  def stringify(signature)
4
6
  positional_params = positional(signature)
5
7
  keyword_params = keyword(signature)
@@ -0,0 +1,3 @@
1
+ module Mocktail
2
+ TYPED = false
3
+ end
@@ -4,8 +4,15 @@ require_relative "../share/bind"
4
4
  # is guaranteed by Mocktail to be local to the currently-running thread
5
5
  module Mocktail
6
6
  class Cabinet
7
+ extend T::Sig
8
+
7
9
  attr_writer :demonstration_in_progress
8
- attr_reader :calls, :stubbings, :unsatisfying_calls
10
+
11
+ attr_reader :calls
12
+
13
+ attr_reader :stubbings
14
+
15
+ attr_reader :unsatisfying_calls
9
16
 
10
17
  def initialize
11
18
  @doubles = []
@@ -1,14 +1,46 @@
1
1
  module Mocktail
2
- Call = Struct.new(
3
- :singleton,
4
- :double,
5
- :original_type,
6
- :dry_type,
7
- :method,
8
- :original_method,
9
- :args,
10
- :kwargs,
11
- :block,
12
- keyword_init: true
13
- )
2
+ class Call < T::Struct
3
+ extend T::Sig
4
+
5
+ const :singleton
6
+ const :double, default: nil
7
+ const :original_type
8
+ const :dry_type
9
+ const :method, without_accessors: true
10
+ const :original_method
11
+ const :args, default: []
12
+ const :kwargs, default: {}
13
+ # At present, there's no way to type optional/variadic params in blocks
14
+ # (i.e. `T.proc.params(*T.untyped).returns(T.untyped)` doesn't work)
15
+ #
16
+ # See: https://github.com/sorbet/sorbet/issues/1142#issuecomment-1586195730
17
+ const :block
18
+
19
+ attr_reader :method
20
+
21
+ # Because T::Struct compares with referential equality, we need
22
+ # to redefine the equality methods to compare the values of the attributes.
23
+
24
+ def ==(other)
25
+ eql?(other)
26
+ end
27
+
28
+ def eql?(other)
29
+ case other
30
+ when Call
31
+ [
32
+ :singleton, :double, :original_type, :dry_type,
33
+ :method, :original_method, :args, :kwargs, :block
34
+ ].all? { |attr|
35
+ instance_variable_get(:"@#{attr}") == other.send(attr)
36
+ }
37
+ else
38
+ false
39
+ end
40
+ end
41
+
42
+ def hash
43
+ [@singleton, @double, @original_type, @dry_type, @method, @original_method, @args, @kwargs, @block].hash
44
+ end
45
+ end
14
46
  end
@@ -1,9 +1,8 @@
1
1
  module Mocktail
2
- DemoConfig = Struct.new(
3
- :ignore_block,
4
- :ignore_extra_args,
5
- :ignore_arity,
6
- :times,
7
- keyword_init: true
8
- )
2
+ class DemoConfig < T::Struct
3
+ const :ignore_block, default: false
4
+ const :ignore_extra_args, default: false
5
+ const :ignore_arity, default: false
6
+ const :times, default: nil
7
+ end
9
8
  end
@@ -1,9 +1,8 @@
1
1
  module Mocktail
2
- Double = Struct.new(
3
- :original_type,
4
- :dry_type,
5
- :dry_instance,
6
- :dry_methods,
7
- keyword_init: true
8
- )
2
+ class Double < T::Struct
3
+ const :original_type
4
+ const :dry_type
5
+ const :dry_instance
6
+ const :dry_methods
7
+ end
9
8
  end
@@ -1,9 +1,13 @@
1
+ require_relative "call"
2
+ require_relative "stubbing"
3
+
1
4
  module Mocktail
2
- DoubleData = Struct.new(
3
- :type,
4
- :double,
5
- :calls,
6
- :stubbings,
7
- keyword_init: true
8
- )
5
+ class DoubleData < T::Struct
6
+ include ExplanationData
7
+
8
+ const :type
9
+ const :double
10
+ const :calls
11
+ const :stubbings
12
+ end
9
13
  end
@@ -1,6 +1,10 @@
1
1
  module Mocktail
2
2
  class Explanation
3
- attr_reader :reference, :message
3
+ extend T::Sig
4
+
5
+ attr_reader :reference
6
+
7
+ attr_reader :message
4
8
 
5
9
  def initialize(reference, message)
6
10
  @reference = reference
@@ -13,17 +17,38 @@ module Mocktail
13
17
  end
14
18
 
15
19
  class NoExplanation < Explanation
16
- end
20
+ attr_reader :reference
17
21
 
18
- class UnsatisfyingCallExplanation < Explanation
22
+ def initialize(reference, message)
23
+ @reference = reference
24
+ @message = message
25
+ end
19
26
  end
20
27
 
21
28
  class DoubleExplanation < Explanation
29
+ attr_reader :reference
30
+
31
+ def initialize(reference, message)
32
+ @reference = reference
33
+ @message = message
34
+ end
22
35
  end
23
36
 
24
37
  class ReplacedTypeExplanation < Explanation
38
+ attr_reader :reference
39
+
40
+ def initialize(reference, message)
41
+ @reference = reference
42
+ @message = message
43
+ end
25
44
  end
26
45
 
27
46
  class FakeMethodExplanation < Explanation
47
+ attr_reader :reference
48
+
49
+ def initialize(reference, message)
50
+ @reference = reference
51
+ @message = message
52
+ end
28
53
  end
29
54
  end
@@ -0,0 +1,14 @@
1
+ module Mocktail
2
+ module ExplanationData
3
+ extend T::Helpers
4
+ extend T::Sig
5
+
6
+ include Kernel
7
+
8
+ def calls
9
+ end
10
+
11
+ def stubbings
12
+ end
13
+ end
14
+ end
@@ -1,8 +1,9 @@
1
1
  module Mocktail
2
- FakeMethodData = Struct.new(
3
- :receiver,
4
- :calls,
5
- :stubbings,
6
- keyword_init: true
7
- )
2
+ class FakeMethodData < T::Struct
3
+ include ExplanationData
4
+
5
+ const :receiver
6
+ const :calls
7
+ const :stubbings
8
+ end
8
9
  end
@@ -1,5 +1,7 @@
1
1
  module Mocktail
2
2
  class MatcherRegistry
3
+ extend T::Sig
4
+
3
5
  def self.instance
4
6
  @matcher_registry ||= new
5
7
  end
@@ -0,0 +1,16 @@
1
+ module Mocktail
2
+ class NoExplanationData < T::Struct
3
+ extend T::Sig
4
+ include ExplanationData
5
+
6
+ const :thing
7
+
8
+ def calls
9
+ raise Error.new("No calls have been recorded for #{thing.inspect}, because Mocktail doesn't know what it is.")
10
+ end
11
+
12
+ def stubbings
13
+ raise Error.new("No stubbings exist on #{thing.inspect}, because Mocktail doesn't know what it is.")
14
+ end
15
+ end
16
+ end
@@ -1,32 +1,11 @@
1
1
  module Mocktail
2
- Signature = Struct.new(
3
- :positional_params,
4
- :positional_args,
5
- :keyword_params,
6
- :keyword_args,
7
- :block_param,
8
- :block_arg,
9
- keyword_init: true
10
- )
11
- class Signature
12
- DEFAULT_REST_ARGS = "args"
13
- DEFAULT_REST_KWARGS = "kwargs"
14
- DEFAULT_BLOCK_PARAM = "blk"
15
- end
2
+ class Params < T::Struct
3
+ extend T::Sig
16
4
 
17
- Params = Struct.new(
18
- :all,
19
- :required,
20
- :optional,
21
- :rest,
22
- keyword_init: true
23
- ) do
24
- def initialize(**params)
25
- super
26
- self.all ||= []
27
- self.required ||= []
28
- self.optional ||= []
29
- end
5
+ prop :all, default: []
6
+ prop :required, default: []
7
+ prop :optional, default: []
8
+ prop :rest
30
9
 
31
10
  def allowed
32
11
  all.select { |name| required.include?(name) || optional.include?(name) }
@@ -36,4 +15,17 @@ module Mocktail
36
15
  !!rest
37
16
  end
38
17
  end
18
+
19
+ class Signature < T::Struct
20
+ const :positional_params
21
+ const :positional_args
22
+ const :keyword_params
23
+ const :keyword_args
24
+ const :block_param
25
+ const :block_arg, default: nil
26
+
27
+ DEFAULT_REST_ARGS = "args"
28
+ DEFAULT_REST_KWARGS = "kwargs"
29
+ DEFAULT_BLOCK_PARAM = "blk"
30
+ end
39
31
  end
@@ -1,16 +1,14 @@
1
1
  module Mocktail
2
- Stubbing = Struct.new(
3
- :demonstration,
4
- :demo_config,
5
- :satisfaction_count,
6
- :recording,
7
- :effect,
8
- keyword_init: true
9
- ) do
10
- def initialize(**kwargs)
11
- super
12
- self.satisfaction_count ||= 0
13
- end
2
+ class Stubbing < T::Struct
3
+ extend T::Sig
4
+ extend T::Generic
5
+ MethodReturnType = type_member
6
+
7
+ const :demonstration
8
+ const :demo_config
9
+ prop :satisfaction_count, default: 0
10
+ const :recording
11
+ prop :effect
14
12
 
15
13
  def satisfied!
16
14
  self.satisfaction_count += 1
@@ -18,6 +16,7 @@ module Mocktail
18
16
 
19
17
  def with(&block)
20
18
  self.effect = block
19
+ nil
21
20
  end
22
21
  end
23
22
  end
@@ -1,5 +1,10 @@
1
1
  module Mocktail
2
+ # The TopShelf is where we keep all the more global, dangerous state.
3
+ # In particular, this is where Mocktail manages state related to singleton
4
+ # method replacements carried out with Mocktail.replace(ClassOrModule)
2
5
  class TopShelf
6
+ extend T::Sig
7
+
3
8
  def self.instance
4
9
  Thread.current[:mocktail_top_shelf] ||= new
5
10
  end
@@ -1,10 +1,9 @@
1
1
  module Mocktail
2
- TypeReplacement = Struct.new(
3
- :type,
4
- :original_methods,
5
- :replacement_methods,
6
- :original_new,
7
- :replacement_new,
8
- keyword_init: true
9
- )
2
+ class TypeReplacement < T::Struct
3
+ const :type
4
+ prop :original_methods
5
+ prop :replacement_methods
6
+ prop :original_new
7
+ prop :replacement_new
8
+ end
10
9
  end
@@ -1,11 +1,14 @@
1
1
  module Mocktail
2
- TypeReplacementData = Struct.new(
3
- :type,
4
- :replaced_method_names,
5
- :calls,
6
- :stubbings,
7
- keyword_init: true
8
- ) do
2
+ class TypeReplacementData < T::Struct
3
+ extend T::Sig
4
+
5
+ const :type
6
+ const :replaced_method_names
7
+ const :calls
8
+ const :stubbings
9
+
10
+ include ExplanationData
11
+
9
12
  def double
10
13
  type
11
14
  end
@@ -1,8 +1,7 @@
1
1
  module Mocktail
2
- UnsatisfyingCall = Struct.new(
3
- :call,
4
- :other_stubbings,
5
- :backtrace,
6
- keyword_init: true
7
- )
2
+ class UnsatisfyingCall < T::Struct
3
+ const :call
4
+ const :other_stubbings
5
+ const :backtrace
6
+ end
8
7
  end
@@ -0,0 +1,18 @@
1
+ module Mocktail
2
+ class UnsatisfyingCallExplanation
3
+ extend T::Sig
4
+
5
+ attr_reader :reference
6
+
7
+ attr_reader :message
8
+
9
+ def initialize(reference, message)
10
+ @reference = reference
11
+ @message = message
12
+ end
13
+
14
+ def type
15
+ self.class
16
+ end
17
+ end
18
+ end
@@ -1,14 +1,17 @@
1
1
  require_relative "value/cabinet"
2
2
  require_relative "value/call"
3
3
  require_relative "value/demo_config"
4
+ require_relative "value/explanation"
5
+ require_relative "value/explanation_data"
4
6
  require_relative "value/double"
5
7
  require_relative "value/double_data"
6
- require_relative "value/explanation"
7
8
  require_relative "value/fake_method_data"
8
9
  require_relative "value/matcher_registry"
10
+ require_relative "value/no_explanation_data"
9
11
  require_relative "value/signature"
10
12
  require_relative "value/stubbing"
11
- require_relative "value/top_shelf"
12
13
  require_relative "value/type_replacement"
13
14
  require_relative "value/type_replacement_data"
15
+ require_relative "value/unsatisfying_call_explanation"
14
16
  require_relative "value/unsatisfying_call"
17
+ require_relative "value/top_shelf"
@@ -2,6 +2,8 @@ require_relative "../share/determines_matching_calls"
2
2
 
3
3
  module Mocktail
4
4
  class FindsVerifiableCalls
5
+ extend T::Sig
6
+
5
7
  def initialize
6
8
  @determines_matching_calls = DeterminesMatchingCalls.new
7
9
  end
@@ -1,5 +1,7 @@
1
1
  module Mocktail
2
2
  class GathersCallsOfMethod
3
+ extend T::Sig
4
+
3
5
  def gather(dry_call)
4
6
  Mocktail.cabinet.calls.select { |call|
5
7
  call.double == dry_call.double &&
@@ -4,6 +4,8 @@ require_relative "../share/stringifies_call"
4
4
 
5
5
  module Mocktail
6
6
  class RaisesVerificationError
7
+ extend T::Sig
8
+
7
9
  def initialize
8
10
  @gathers_calls_of_method = GathersCallsOfMethod.new
9
11
  @stringifies_method_name = StringifiesMethodName.new
@@ -4,6 +4,8 @@ require_relative "verifies_call/raises_verification_error"
4
4
 
5
5
  module Mocktail
6
6
  class VerifiesCall
7
+ extend T::Sig
8
+
7
9
  def initialize
8
10
  @records_demonstration = RecordsDemonstration.new
9
11
  @finds_verifiable_calls = FindsVerifiableCalls.new
@@ -17,6 +19,7 @@ module Mocktail
17
19
  unless verification_satisfied?(verifiable_calls.size, demo_config)
18
20
  @raises_verification_error.raise(recording, verifiable_calls, demo_config)
19
21
  end
22
+ nil
20
23
  end
21
24
 
22
25
  private
@@ -1,3 +1,10 @@
1
1
  module Mocktail
2
- VERSION = "1.2.3"
2
+ # The gemspec will define Module::VERSION as loaded from lib/, but if the
3
+ # user loads mocktail/sorbet, its version file will be effectively redefining
4
+ # it. Undef it first to ensure we don't spew warnings
5
+ if defined?(VERSION)
6
+ Mocktail.send(:remove_const, :VERSION)
7
+ end
8
+
9
+ VERSION = "3.0.0"
3
10
  end