mocktail 2.0.0 → 3.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 (288) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +2 -2
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +3 -2
  5. data/Gemfile.lock +76 -82
  6. data/README.md +2 -0
  7. data/docs/code_of_conduct.md +8 -0
  8. data/docs/configuring_minitest.md +20 -0
  9. data/docs/configuring_rspec.md +19 -0
  10. data/docs/example_test.md +594 -0
  11. data/docs/faq/existing_tests.md +47 -0
  12. data/docs/faq/mocking_http.md +151 -0
  13. data/docs/faq/mocking_the_subject.md +161 -0
  14. data/docs/faq/mocking_time.md +34 -0
  15. data/docs/faq/partial_mocks.md +34 -0
  16. data/docs/faq/verifying_real_interactions.md +52 -0
  17. data/docs/img/delegator_tree.png +0 -0
  18. data/docs/img/example_test.png +0 -0
  19. data/docs/img/extract_transform_load.png +0 -0
  20. data/docs/img/mocktail_sorbet.jpg +0 -0
  21. data/docs/img/mocktail_untyped.jpg +0 -0
  22. data/docs/img/spacer.png +0 -0
  23. data/docs/installation_sorbet.md +99 -0
  24. data/docs/installation_untyped.md +29 -0
  25. data/docs/other_uses.md +32 -0
  26. data/docs/stubbing_and_verifying.md +515 -0
  27. data/docs/support/api.md +819 -0
  28. data/docs/support/example_test.rb +94 -0
  29. data/docs/support/glossary.md +426 -0
  30. data/docs/tdd/class_methods.md +44 -0
  31. data/docs/tdd/poro/dependency_inception.md +136 -0
  32. data/docs/tdd/poro/dependency_injection.md +82 -0
  33. data/docs/tdd/poro.md +15 -0
  34. data/docs/tdd/third_party.md +220 -0
  35. data/docs/tdd.md +15 -0
  36. data/lib/mocktail/debug.rb +5 -4
  37. data/lib/mocktail/handles_dry_call/validates_arguments.rb +6 -3
  38. data/lib/mocktail/handles_dry_new_call.rb +5 -0
  39. data/lib/mocktail/replaces_type/redefines_singleton_methods.rb +5 -0
  40. data/lib/mocktail/share/folds_keywords_into_options_hash.rb +22 -0
  41. data/lib/mocktail/share/stringifies_call.rb +0 -1
  42. data/lib/mocktail/simulates_argument_error/transforms_params.rb +2 -2
  43. data/lib/mocktail/sorbet/mocktail/debug.rb +5 -4
  44. data/lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb +6 -3
  45. data/lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb +5 -0
  46. data/lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb +5 -0
  47. data/lib/mocktail/sorbet/mocktail/share/folds_keywords_into_options_hash.rb +25 -0
  48. data/lib/mocktail/sorbet/mocktail/share/stringifies_call.rb +0 -1
  49. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/transforms_params.rb +2 -2
  50. data/lib/mocktail/sorbet/mocktail/value/call.rb +1 -1
  51. data/lib/mocktail/sorbet/mocktail/version.rb +1 -1
  52. data/lib/mocktail/value/call.rb +1 -1
  53. data/lib/mocktail/version.rb +1 -1
  54. data/mocktail.gemspec +2 -2
  55. data/rbi/mocktail-pregenerated.rbi +54 -45
  56. data/script/build +47 -0
  57. data/script/setup +17 -0
  58. data/script/spoom_me +7 -0
  59. data/script/strip_sigils +17 -0
  60. data/script/test +33 -0
  61. data/script/test_double_require_warnings +46 -0
  62. data/script/update +21 -0
  63. data/sorbet/config +12 -0
  64. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  65. data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  66. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1083 -0
  67. data/sorbet/rbi/gems/docile@1.4.0.rbi +376 -0
  68. data/sorbet/rbi/gems/json@2.6.3.rbi +1533 -0
  69. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14237 -0
  70. data/sorbet/rbi/gems/lint_roller@1.0.0.rbi +230 -0
  71. data/sorbet/rbi/gems/m@1.6.1.rbi +257 -0
  72. data/sorbet/rbi/gems/method_source@1.0.0.rbi +272 -0
  73. data/sorbet/rbi/gems/minitest@5.18.0.rbi +1491 -0
  74. data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  75. data/sorbet/rbi/gems/parallel@1.23.0.rbi +273 -0
  76. data/sorbet/rbi/gems/parser@3.2.2.1.rbi +7253 -0
  77. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
  78. data/sorbet/rbi/gems/rake@13.0.6.rbi +3024 -0
  79. data/sorbet/rbi/gems/rbi@0.0.16.rbi +3049 -0
  80. data/sorbet/rbi/gems/regexp_parser@2.8.0.rbi +3748 -0
  81. data/sorbet/rbi/gems/rexml@3.2.5.rbi +4717 -0
  82. data/sorbet/rbi/gems/rubocop-ast@1.29.0.rbi +7003 -0
  83. data/sorbet/rbi/gems/rubocop-performance@1.18.0.rbi +8 -0
  84. data/sorbet/rbi/gems/rubocop-sorbet@0.7.0.rbi +1043 -0
  85. data/sorbet/rbi/gems/rubocop@1.52.0.rbi +55500 -0
  86. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1317 -0
  87. data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +216 -0
  88. data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2148 -0
  89. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +8 -0
  90. data/sorbet/rbi/gems/spoom@1.2.1.rbi +2536 -0
  91. data/sorbet/rbi/gems/standard-custom@1.0.1.rbi +63 -0
  92. data/sorbet/rbi/gems/standard-performance@1.1.0.rbi +8 -0
  93. data/sorbet/rbi/gems/standard@1.29.0.rbi +850 -0
  94. data/sorbet/rbi/gems/tapioca@0.11.6.rbi +3301 -0
  95. data/sorbet/rbi/gems/thor@1.2.2.rbi +3965 -0
  96. data/sorbet/rbi/gems/unicode-display_width@2.4.2.rbi +65 -0
  97. data/sorbet/rbi/gems/unparser@0.6.7.rbi +4524 -0
  98. data/sorbet/rbi/gems/yard-sorbet@0.8.1.rbi +428 -0
  99. data/sorbet/rbi/gems/yard@0.9.34.rbi +18219 -0
  100. data/sorbet/tapioca/config.yml +13 -0
  101. data/sorbet/tapioca/require.rb +4 -0
  102. data/spoom_data/05f0c49.json +1 -0
  103. data/spoom_data/1657012.json +1 -0
  104. data/spoom_data/167434b.json +1 -0
  105. data/spoom_data/1d0ba5b.json +1 -0
  106. data/spoom_data/1ffa724.json +1 -0
  107. data/spoom_data/2129b3d.json +1 -0
  108. data/spoom_data/24b1c92.json +1 -0
  109. data/spoom_data/2c46aee.json +1 -0
  110. data/spoom_data/305ec0b.json +1 -0
  111. data/spoom_data/30e9528.json +1 -0
  112. data/spoom_data/4638cd5.json +1 -0
  113. data/spoom_data/47c7dad.json +1 -0
  114. data/spoom_data/4b1edef.json +1 -0
  115. data/spoom_data/4de157f.json +1 -0
  116. data/spoom_data/526e7db.json +1 -0
  117. data/spoom_data/5d093b9.json +1 -0
  118. data/spoom_data/5db3b43.json +1 -0
  119. data/spoom_data/5fe2a65.json +1 -0
  120. data/spoom_data/6891312.json +1 -0
  121. data/spoom_data/6b0fef4.json +1 -0
  122. data/spoom_data/6b83d12.json +1 -0
  123. data/spoom_data/74c83c2.json +1 -0
  124. data/spoom_data/7644ff4.json +1 -0
  125. data/spoom_data/79054db.json +1 -0
  126. data/spoom_data/814e515.json +1 -0
  127. data/spoom_data/88c3b60.json +1 -0
  128. data/spoom_data/8bd4b6e.json +1 -0
  129. data/spoom_data/93f8153.json +1 -0
  130. data/spoom_data/95242fe.json +1 -0
  131. data/spoom_data/97f4c09.json +1 -0
  132. data/spoom_data/a13d150.json +1 -0
  133. data/spoom_data/a17f215.json +1 -0
  134. data/spoom_data/b705a9d.json +1 -0
  135. data/spoom_data/ba19195.json +1 -0
  136. data/spoom_data/bef51ca.json +1 -0
  137. data/spoom_data/dbb595a.json +1 -0
  138. data/spoom_data/e8fab92.json +1 -0
  139. data/spoom_data/f166c87.json +1 -0
  140. data/spoom_data/f57992d.json +1 -0
  141. data/spoom_data/f5a1e40.json +1 -0
  142. data/spoom_data/f6d6431.json +1 -0
  143. data/spoom_data/f72b67c.json +1 -0
  144. data/spoom_data/fc2f231.json +1 -0
  145. data/src/mocktail/collects_calls.rb +18 -0
  146. data/src/mocktail/debug.rb +55 -0
  147. data/src/mocktail/dsl.rb +46 -0
  148. data/src/mocktail/errors.rb +19 -0
  149. data/src/mocktail/explains_nils.rb +41 -0
  150. data/src/mocktail/explains_thing.rb +137 -0
  151. data/src/mocktail/grabs_original_method_parameters.rb +33 -0
  152. data/src/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +27 -0
  153. data/src/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +24 -0
  154. data/src/mocktail/handles_dry_call/fulfills_stubbing.rb +45 -0
  155. data/src/mocktail/handles_dry_call/logs_call.rb +12 -0
  156. data/src/mocktail/handles_dry_call/validates_arguments.rb +48 -0
  157. data/src/mocktail/handles_dry_call.rb +25 -0
  158. data/src/mocktail/handles_dry_new_call.rb +47 -0
  159. data/src/mocktail/imitates_type/ensures_imitation_support.rb +16 -0
  160. data/src/mocktail/imitates_type/makes_double/declares_dry_class/reconstructs_call.rb +73 -0
  161. data/src/mocktail/imitates_type/makes_double/declares_dry_class.rb +136 -0
  162. data/src/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +28 -0
  163. data/src/mocktail/imitates_type/makes_double.rb +29 -0
  164. data/src/mocktail/imitates_type.rb +29 -0
  165. data/src/mocktail/initialize_based_on_type_system_mode_switching.rb +11 -0
  166. data/src/mocktail/initializes_mocktail.rb +25 -0
  167. data/src/mocktail/matcher_presentation.rb +21 -0
  168. data/src/mocktail/matchers/any.rb +27 -0
  169. data/src/mocktail/matchers/base.rb +39 -0
  170. data/src/mocktail/matchers/captor.rb +76 -0
  171. data/src/mocktail/matchers/includes.rb +32 -0
  172. data/src/mocktail/matchers/includes_hash.rb +12 -0
  173. data/src/mocktail/matchers/includes_key.rb +12 -0
  174. data/src/mocktail/matchers/includes_string.rb +12 -0
  175. data/src/mocktail/matchers/is_a.rb +17 -0
  176. data/src/mocktail/matchers/matches.rb +19 -0
  177. data/src/mocktail/matchers/not.rb +17 -0
  178. data/src/mocktail/matchers/numeric.rb +27 -0
  179. data/src/mocktail/matchers/that.rb +32 -0
  180. data/src/mocktail/matchers.rb +19 -0
  181. data/src/mocktail/raises_neato_no_method_error.rb +93 -0
  182. data/src/mocktail/records_demonstration.rb +43 -0
  183. data/src/mocktail/registers_matcher.rb +65 -0
  184. data/src/mocktail/registers_stubbing.rb +31 -0
  185. data/src/mocktail/replaces_next.rb +55 -0
  186. data/src/mocktail/replaces_type/redefines_new.rb +32 -0
  187. data/src/mocktail/replaces_type/redefines_singleton_methods.rb +85 -0
  188. data/src/mocktail/replaces_type/runs_sorbet_sig_blocks_before_replacement.rb +39 -0
  189. data/src/mocktail/replaces_type.rb +36 -0
  190. data/src/mocktail/resets_state.rb +14 -0
  191. data/src/mocktail/share/bind.rb +18 -0
  192. data/src/mocktail/share/cleans_backtrace.rb +22 -0
  193. data/src/mocktail/share/creates_identifier.rb +39 -0
  194. data/src/mocktail/share/determines_matching_calls.rb +72 -0
  195. data/src/mocktail/share/folds_keywords_into_options_hash.rb +25 -0
  196. data/src/mocktail/share/stringifies_call.rb +84 -0
  197. data/src/mocktail/share/stringifies_method_name.rb +16 -0
  198. data/src/mocktail/simulates_argument_error/reconciles_args_with_params.rb +27 -0
  199. data/src/mocktail/simulates_argument_error/recreates_message.rb +34 -0
  200. data/src/mocktail/simulates_argument_error/transforms_params.rb +58 -0
  201. data/src/mocktail/simulates_argument_error.rb +36 -0
  202. data/src/mocktail/sorbet.rb +3 -0
  203. data/src/mocktail/stringifies_method_signature.rb +53 -0
  204. data/src/mocktail/typed.rb +5 -0
  205. data/src/mocktail/value/cabinet.rb +91 -0
  206. data/src/mocktail/value/call.rb +51 -0
  207. data/src/mocktail/value/demo_config.rb +10 -0
  208. data/src/mocktail/value/double.rb +10 -0
  209. data/src/mocktail/value/double_data.rb +15 -0
  210. data/src/mocktail/value/explanation.rb +68 -0
  211. data/src/mocktail/value/explanation_data.rb +19 -0
  212. data/src/mocktail/value/fake_method_data.rb +11 -0
  213. data/src/mocktail/value/matcher_registry.rb +27 -0
  214. data/src/mocktail/value/no_explanation_data.rb +20 -0
  215. data/src/mocktail/value/signature.rb +35 -0
  216. data/src/mocktail/value/stubbing.rb +26 -0
  217. data/src/mocktail/value/top_shelf.rb +79 -0
  218. data/src/mocktail/value/type_replacement.rb +11 -0
  219. data/src/mocktail/value/type_replacement_data.rb +19 -0
  220. data/src/mocktail/value/unsatisfying_call.rb +9 -0
  221. data/src/mocktail/value/unsatisfying_call_explanation.rb +24 -0
  222. data/src/mocktail/value.rb +19 -0
  223. data/src/mocktail/verifies_call/finds_verifiable_calls.rb +21 -0
  224. data/src/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +15 -0
  225. data/src/mocktail/verifies_call/raises_verification_error.rb +74 -0
  226. data/src/mocktail/verifies_call.rb +37 -0
  227. data/src/mocktail/version.rb +12 -0
  228. data/src/mocktail.rb +154 -0
  229. data/sub_projects/rbi_generator/Gemfile +4 -0
  230. data/sub_projects/rbi_generator/Gemfile.lock +63 -0
  231. data/sub_projects/rbi_generator/sorbet/rbi/gems/.gitattributes +1 -0
  232. data/sub_projects/sorbet_user/Gemfile +13 -0
  233. data/sub_projects/sorbet_user/Gemfile.lock +126 -0
  234. data/sub_projects/sorbet_user/Rakefile +10 -0
  235. data/sub_projects/sorbet_user/bin/tapioca +27 -0
  236. data/sub_projects/sorbet_user/rbi/mocktail.rbi +9 -0
  237. data/sub_projects/sorbet_user/script/test +13 -0
  238. data/sub_projects/sorbet_user/sorbet/config +4 -0
  239. data/sub_projects/sorbet_user/sorbet/rbi/gems/.gitattributes +1 -0
  240. data/sub_projects/sorbet_user/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
  241. data/sub_projects/sorbet_user/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
  242. data/sub_projects/sorbet_user/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  243. data/sub_projects/sorbet_user/sorbet/rbi/gems/json@2.21.2.rbi +2140 -0
  244. data/sub_projects/sorbet_user/sorbet/rbi/gems/language_server-protocol@3.17.0.4.rbi +14244 -0
  245. data/sub_projects/sorbet_user/sorbet/rbi/gems/lint_roller@1.1.0.rbi +239 -0
  246. data/sub_projects/sorbet_user/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
  247. data/sub_projects/sorbet_user/sorbet/rbi/gems/m@1.6.2.rbi +258 -0
  248. data/sub_projects/sorbet_user/sorbet/rbi/gems/method_source@1.1.0.rbi +9 -0
  249. data/sub_projects/sorbet_user/sorbet/rbi/gems/minitest@5.27.0.rbi +1549 -0
  250. data/sub_projects/sorbet_user/sorbet/rbi/gems/mocktail@3.0.1.rbi +1930 -0
  251. data/sub_projects/sorbet_user/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  252. data/sub_projects/sorbet_user/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  253. data/sub_projects/sorbet_user/sorbet/rbi/gems/parser@3.3.7.4.rbi +5451 -0
  254. data/sub_projects/sorbet_user/sorbet/rbi/gems/prism@1.4.0.rbi +41732 -0
  255. data/sub_projects/sorbet_user/sorbet/rbi/gems/racc@1.8.1.rbi +164 -0
  256. data/sub_projects/sorbet_user/sorbet/rbi/gems/rainbow@3.1.1.rbi +402 -0
  257. data/sub_projects/sorbet_user/sorbet/rbi/gems/rake@13.2.1.rbi +3028 -0
  258. data/sub_projects/sorbet_user/sorbet/rbi/gems/rbi@0.3.1.rbi +6599 -0
  259. data/sub_projects/sorbet_user/sorbet/rbi/gems/rbs@3.9.2.rbi +6976 -0
  260. data/sub_projects/sorbet_user/sorbet/rbi/gems/regexp_parser@2.10.0.rbi +3795 -0
  261. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop-ast@1.43.0.rbi +7717 -0
  262. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop-performance@1.24.0.rbi +9 -0
  263. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop-sorbet@0.9.0.rbi +9 -0
  264. data/sub_projects/sorbet_user/sorbet/rbi/gems/rubocop@1.73.2.rbi +61306 -0
  265. data/sub_projects/sorbet_user/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1317 -0
  266. data/sub_projects/sorbet_user/sorbet/rbi/gems/sorbet-eraser@0.3.1.rbi +8 -0
  267. data/sub_projects/sorbet_user/sorbet/rbi/gems/spoom@1.6.1.rbi +7274 -0
  268. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard-custom@1.0.2.rbi +8 -0
  269. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard-performance@1.7.0.rbi +9 -0
  270. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard-sorbet@0.0.3.rbi +53 -0
  271. data/sub_projects/sorbet_user/sorbet/rbi/gems/standard@1.47.0.rbi +935 -0
  272. data/sub_projects/sorbet_user/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
  273. data/sub_projects/sorbet_user/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  274. data/sub_projects/sorbet_user/sorbet/rbi/gems/unicode-display_width@3.1.4.rbi +132 -0
  275. data/sub_projects/sorbet_user/sorbet/rbi/gems/unicode-emoji@4.2.0.rbi +254 -0
  276. data/sub_projects/sorbet_user/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  277. data/sub_projects/sorbet_user/sorbet/rbi/gems/yard@0.9.45.rbi +18916 -0
  278. data/sub_projects/sorbet_user/sorbet/tapioca/config.yml +13 -0
  279. data/sub_projects/sorbet_user/sorbet/tapioca/require.rb +4 -0
  280. data/sub_projects/sorbet_user/test/ensure_type_safety_test.rb +21 -0
  281. data/sub_projects/sorbet_user/test/paint_by_number_test.rb +113 -0
  282. data/sub_projects/sorbet_user/test/sorbet_test.rb +289 -0
  283. data/sub_projects/sorbet_user/test/test_helper.rb +35 -0
  284. data/sub_projects/untyped_user/Gemfile +4 -0
  285. data/sub_projects/untyped_user/Gemfile.lock +25 -0
  286. data/sub_projects/untyped_user/antitype_test.rb +54 -0
  287. data/sub_projects/untyped_user/script/test +5 -0
  288. metadata +267 -8
@@ -1,5 +1,7 @@
1
1
  # typed: strict
2
2
 
3
+ require_relative "../share/folds_keywords_into_options_hash"
4
+
3
5
  module Mocktail
4
6
  class RedefinesSingletonMethods
5
7
  extend T::Sig
@@ -7,6 +9,7 @@ module Mocktail
7
9
  sig { void }
8
10
  def initialize
9
11
  @handles_dry_call = T.let(HandlesDryCall.new, HandlesDryCall)
12
+ @folds_keywords_into_options_hash = T.let(FoldsKeywordsIntoOptionsHash.new, FoldsKeywordsIntoOptionsHash)
10
13
  end
11
14
 
12
15
  sig { params(type: T.any(T::Class[T.anything], Module)).void }
@@ -20,10 +23,12 @@ module Mocktail
20
23
 
21
24
  declare_singleton_method_missing_errors!(type)
22
25
  handles_dry_call = @handles_dry_call
26
+ folds_keywords_into_options_hash = @folds_keywords_into_options_hash
23
27
  type_replacement.replacement_methods = type_replacement.original_methods&.map { |original_method|
24
28
  type.singleton_class.send(:undef_method, original_method.name)
25
29
  type.define_singleton_method original_method.name, ->(*args, **kwargs, &block) {
26
30
  if TopShelf.instance.singleton_methods_replaced?(type)
31
+ args, kwargs = folds_keywords_into_options_hash.fold(original_method, args, kwargs)
27
32
  handles_dry_call.handle(Call.new(
28
33
  singleton: true,
29
34
  double: type,
@@ -0,0 +1,25 @@
1
+ # typed: strict
2
+
3
+ module Mocktail
4
+ class FoldsKeywordsIntoOptionsHash
5
+ extend T::Sig
6
+
7
+ KEYWORD_PARAM_TYPES = T.let([:key, :keyreq, :keyrest, :nokey].freeze, T::Array[Symbol])
8
+
9
+ sig { void }
10
+ def initialize
11
+ @grabs_original_method_parameters = T.let(GrabsOriginalMethodParameters.new, GrabsOriginalMethodParameters)
12
+ end
13
+
14
+ # Ruby 3 passes keywords to a method with no keyword params as a trailing
15
+ # positional hash, but our generic (*args, **kwargs) lambdas always split
16
+ # them out, so fold them back in to match what the real method would see
17
+ sig { params(original_method: T.nilable(T.any(UnboundMethod, Method)), args: T::Array[T.anything], kwargs: T::Hash[Symbol, T.anything]).returns([T::Array[T.anything], T::Hash[Symbol, T.anything]]) }
18
+ def fold(original_method, args, kwargs)
19
+ return [args, kwargs] if kwargs.empty? || original_method.nil?
20
+ return [args, kwargs] if @grabs_original_method_parameters.grab(original_method).any? { |type, _| KEYWORD_PARAM_TYPES.include?(type) }
21
+
22
+ [[*args, kwargs], {}]
23
+ end
24
+ end
25
+ end
@@ -12,7 +12,6 @@ module Mocktail
12
12
  sig { params(calls: T::Array[Call], nonzero_message: String, zero_message: String, anonymous_blocks: T::Boolean, always_parens: T::Boolean).returns(String) }
13
13
  def stringify_multiple(calls, nonzero_message:, zero_message:,
14
14
  anonymous_blocks: false, always_parens: false)
15
-
16
15
  if calls.empty?
17
16
  "#{zero_message}.\n"
18
17
  else
@@ -28,7 +28,7 @@ module Mocktail
28
28
  positional_args: dry_call.args,
29
29
 
30
30
  keyword_params: Params.new(
31
- all: params.select { |type, _|
31
+ all: params.select { |type, _| # standard:disable Style/HashSlice
32
32
  [:keyreq, :key, :keyrest].include?(type)
33
33
  }.map { |pair| pair.fetch(1) },
34
34
  required: params.select { |t, _| Bind.call(t, :==, :keyreq) }.map { |pair| pair.fetch(1) },
@@ -48,7 +48,7 @@ module Mocktail
48
48
  def name_unnamed_params(params)
49
49
  params.map.with_index { |param, i|
50
50
  if param.size == 1
51
- param + ["unnamed_arg_#{i + 1}".to_sym]
51
+ param + [:"unnamed_arg_#{i + 1}"]
52
52
  else
53
53
  param
54
54
  end
@@ -36,7 +36,7 @@ module Mocktail
36
36
  :singleton, :double, :original_type, :dry_type,
37
37
  :method, :original_method, :args, :kwargs, :block
38
38
  ].all? { |attr|
39
- instance_variable_get("@#{attr}") == other.send(attr)
39
+ instance_variable_get(:"@#{attr}") == other.send(attr)
40
40
  }
41
41
  else
42
42
  false
@@ -8,5 +8,5 @@ module Mocktail
8
8
  Mocktail.send(:remove_const, :VERSION)
9
9
  end
10
10
 
11
- VERSION = "2.0.0"
11
+ VERSION = "3.0.1"
12
12
  end
@@ -32,7 +32,7 @@ module Mocktail
32
32
  :singleton, :double, :original_type, :dry_type,
33
33
  :method, :original_method, :args, :kwargs, :block
34
34
  ].all? { |attr|
35
- instance_variable_get("@#{attr}") == other.send(attr)
35
+ instance_variable_get(:"@#{attr}") == other.send(attr)
36
36
  }
37
37
  else
38
38
  false
@@ -6,5 +6,5 @@ module Mocktail
6
6
  Mocktail.send(:remove_const, :VERSION)
7
7
  end
8
8
 
9
- VERSION = "2.0.0"
9
+ VERSION = "3.0.1"
10
10
  end
data/mocktail.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = "Take your objects, and make them a double"
14
14
  spec.homepage = "https://github.com/testdouble/mocktail"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = spec.homepage
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  # Specify which files should be added to the gem when it is released.
23
23
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
24
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features|src|sub_projects|spoom_data|sorbet|script|docs)/}) }
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
26
  end
27
27
  spec.bindir = "exe"
28
28
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
@@ -4,17 +4,13 @@
4
4
  # This is an autogenerated file for types exported from the `mocktail` gem.
5
5
  # Please instead update this file by running `bin/tapioca gem mocktail`.
6
6
 
7
- # typed: true
8
7
 
9
- # DO NOT EDIT MANUALLY
10
- # This is an autogenerated file for types exported from the `mocktail` gem.
11
- # Please instead update this file by running `bin/tapioca gem mocktail`.
8
+ # typed: true
12
9
 
13
10
  # The Cabinet stores all thread-local state, so anything that goes here
14
11
  # is guaranteed by Mocktail to be local to the currently-running thread
15
12
  #
16
13
  # source://mocktail//lib/mocktail/sorbet/mocktail/typed.rb#3
17
- # The Cabinet stores all thread-local state, so anything that goes here
18
14
  module Mocktail
19
15
  extend ::Mocktail::DSL
20
16
 
@@ -212,7 +208,7 @@ class Mocktail::Call < ::T::Struct
212
208
  def hash; end
213
209
 
214
210
  class << self
215
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
211
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
216
212
  def inherited(s); end
217
213
  end
218
214
  end
@@ -372,7 +368,7 @@ class Mocktail::DemoConfig < ::T::Struct
372
368
  const :times, T.nilable(::Integer), default: T.unsafe(nil)
373
369
 
374
370
  class << self
375
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
371
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
376
372
  def inherited(s); end
377
373
  end
378
374
  end
@@ -445,7 +441,7 @@ class Mocktail::Double < ::T::Struct
445
441
  const :dry_methods, T::Array[::Symbol]
446
442
 
447
443
  class << self
448
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
444
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
449
445
  def inherited(s); end
450
446
  end
451
447
  end
@@ -460,7 +456,7 @@ class Mocktail::DoubleData < ::T::Struct
460
456
  const :stubbings, T::Array[Mocktail::Stubbing[T.anything]]
461
457
 
462
458
  class << self
463
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
459
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
464
460
  def inherited(s); end
465
461
  end
466
462
  end
@@ -592,7 +588,7 @@ class Mocktail::FakeMethodData < ::T::Struct
592
588
  const :stubbings, T::Array[Mocktail::Stubbing[T.anything]]
593
589
 
594
590
  class << self
595
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
591
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
596
592
  def inherited(s); end
597
593
  end
598
594
  end
@@ -630,6 +626,30 @@ class Mocktail::FindsVerifiableCalls
630
626
  def find(recording, demo_config); end
631
627
  end
632
628
 
629
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/folds_keywords_into_options_hash.rb#4
630
+ class Mocktail::FoldsKeywordsIntoOptionsHash
631
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/folds_keywords_into_options_hash.rb#10
632
+ sig { void }
633
+ def initialize; end
634
+
635
+ # Ruby 3 passes keywords to a method with no keyword params as a trailing
636
+ # positional hash, but our generic (*args, **kwargs) lambdas always split
637
+ # them out, so fold them back in to match what the real method would see
638
+ #
639
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/folds_keywords_into_options_hash.rb#18
640
+ sig do
641
+ params(
642
+ original_method: T.nilable(T.any(::Method, ::UnboundMethod)),
643
+ args: T::Array[T.anything],
644
+ kwargs: T::Hash[::Symbol, T.anything]
645
+ ).returns([T::Array[T.anything], T::Hash[::Symbol, T.anything]])
646
+ end
647
+ def fold(original_method, args, kwargs); end
648
+ end
649
+
650
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/folds_keywords_into_options_hash.rb#7
651
+ Mocktail::FoldsKeywordsIntoOptionsHash::KEYWORD_PARAM_TYPES = T.let(T.unsafe(nil), Array)
652
+
633
653
  # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing.rb#7
634
654
  class Mocktail::FulfillsStubbing
635
655
  # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing.rb#11
@@ -704,13 +724,13 @@ class Mocktail::HandlesDryCall
704
724
  def handle(dry_call); end
705
725
  end
706
726
 
707
- # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb#4
727
+ # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb#6
708
728
  class Mocktail::HandlesDryNewCall
709
- # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb#8
729
+ # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb#10
710
730
  sig { void }
711
731
  def initialize; end
712
732
 
713
- # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb#16
733
+ # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb#19
714
734
  sig do
715
735
  params(
716
736
  type: T::Class[T.all(::Object, ::T)],
@@ -915,15 +935,6 @@ end
915
935
  # https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Captor.html
916
936
  #
917
937
  # source://mocktail//lib/mocktail/sorbet/mocktail/matchers/captor.rb#17
918
- # Captors are conceptually complex implementations, but with a simple usage/purpose:
919
- # They are values the user can create and hold onto that will return a matcher
920
- # and then "capture" the value made by the real call, for later analysis & assertion.
921
- # Unlike other matchers, these don't make any useful sense for stubbing, but are
922
- # very useful when asserting complication call verifications
923
- # The fact the user will need the reference outside the verification call is
924
- # why this is a top-level method on Mocktail, and not included in the |m| block
925
- # arg to stubs/verify
926
- # See Mockito, which is the earliest implementation I know of:
927
938
  class Mocktail::Matchers::Captor
928
939
  # source://mocktail//lib/mocktail/sorbet/mocktail/matchers/captor.rb#62
929
940
  sig { void }
@@ -1139,7 +1150,7 @@ class Mocktail::NoExplanationData < ::T::Struct
1139
1150
  def stubbings; end
1140
1151
 
1141
1152
  class << self
1142
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1153
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1143
1154
  def inherited(s); end
1144
1155
  end
1145
1156
  end
@@ -1160,7 +1171,7 @@ class Mocktail::Params < ::T::Struct
1160
1171
  def rest?; end
1161
1172
 
1162
1173
  class << self
1163
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1174
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1164
1175
  def inherited(s); end
1165
1176
  end
1166
1177
  end
@@ -1338,23 +1349,23 @@ class Mocktail::RedefinesNew
1338
1349
  def redefine(type); end
1339
1350
  end
1340
1351
 
1341
- # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#4
1352
+ # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#6
1342
1353
  class Mocktail::RedefinesSingletonMethods
1343
- # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#8
1354
+ # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#10
1344
1355
  sig { void }
1345
1356
  def initialize; end
1346
1357
 
1347
- # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#47
1358
+ # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#52
1348
1359
  sig { params(type: T.any(::Module, T::Class[T.anything])).void }
1349
1360
  def declare_singleton_method_missing_errors!(type); end
1350
1361
 
1351
- # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#13
1362
+ # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#16
1352
1363
  sig { params(type: T.any(::Module, T::Class[T.anything])).void }
1353
1364
  def redefine(type); end
1354
1365
 
1355
1366
  private
1356
1367
 
1357
- # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#72
1368
+ # source://mocktail//lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb#77
1358
1369
  sig { params(method: ::Method).returns(T::Boolean) }
1359
1370
  def sorbet_method_hook?(method); end
1360
1371
  end
@@ -1498,7 +1509,7 @@ class Mocktail::Signature < ::T::Struct
1498
1509
  const :block_arg, T.nilable(::Proc), default: T.unsafe(nil)
1499
1510
 
1500
1511
  class << self
1501
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1512
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1502
1513
  def inherited(s); end
1503
1514
  end
1504
1515
  end
@@ -1543,31 +1554,31 @@ class Mocktail::StringifiesCall
1543
1554
 
1544
1555
  private
1545
1556
 
1546
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#47
1557
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#46
1547
1558
  sig { params(args: T::Array[::Object]).returns(T.nilable(::String)) }
1548
1559
  def argify(args); end
1549
1560
 
1550
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#30
1561
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#29
1551
1562
  sig { params(call: ::Mocktail::Call, parens: T::Boolean).returns(T.nilable(::String)) }
1552
1563
  def args_to_s(call, parens: T.unsafe(nil)); end
1553
1564
 
1554
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#65
1565
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#64
1555
1566
  sig { params(block: T.nilable(::Proc), anonymous: T::Boolean).returns(T.nilable(::String)) }
1556
1567
  def blockify(block, anonymous:); end
1557
1568
 
1558
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#53
1569
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#52
1559
1570
  sig { params(kwargs: T::Hash[::Symbol, ::Object]).returns(T.nilable(::String)) }
1560
1571
  def kwargify(kwargs); end
1561
1572
 
1562
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#59
1573
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#58
1563
1574
  sig { params(block: T.nilable(::Proc)).returns(T.nilable(::String)) }
1564
1575
  def lambdafy(block); end
1565
1576
 
1566
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#76
1577
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#75
1567
1578
  sig { params(block: ::Proc).returns(::String) }
1568
1579
  def source_locationify(block); end
1569
1580
 
1570
- # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#81
1581
+ # source://mocktail//lib/mocktail/sorbet/mocktail/share/stringifies_call.rb#80
1571
1582
  sig { params(path: ::String).returns(::String) }
1572
1583
  def strip_pwd(path); end
1573
1584
  end
@@ -1621,7 +1632,7 @@ class Mocktail::Stubbing < ::T::Struct
1621
1632
  def with(&block); end
1622
1633
 
1623
1634
  class << self
1624
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1635
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1625
1636
  def inherited(s); end
1626
1637
  end
1627
1638
  end
@@ -1634,8 +1645,6 @@ Mocktail::TYPED = T.let(T.unsafe(nil), TrueClass)
1634
1645
  # method replacements carried out with Mocktail.replace(ClassOrModule)
1635
1646
  #
1636
1647
  # source://mocktail//lib/mocktail/sorbet/mocktail/value/top_shelf.rb#7
1637
- # The TopShelf is where we keep all the more global, dangerous state.
1638
- # In particular, this is where Mocktail manages state related to singleton
1639
1648
  class Mocktail::TopShelf
1640
1649
  # source://mocktail//lib/mocktail/sorbet/mocktail/value/top_shelf.rb#19
1641
1650
  sig { void }
@@ -1722,7 +1731,7 @@ class Mocktail::TypeReplacement < ::T::Struct
1722
1731
  prop :replacement_new, T.nilable(::Method)
1723
1732
 
1724
1733
  class << self
1725
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1734
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1726
1735
  def inherited(s); end
1727
1736
  end
1728
1737
  end
@@ -1741,7 +1750,7 @@ class Mocktail::TypeReplacementData < ::T::Struct
1741
1750
  def double; end
1742
1751
 
1743
1752
  class << self
1744
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1753
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1745
1754
  def inherited(s); end
1746
1755
  end
1747
1756
  end
@@ -1756,7 +1765,7 @@ class Mocktail::UnsatisfyingCall < ::T::Struct
1756
1765
  const :backtrace, T::Array[::String]
1757
1766
 
1758
1767
  class << self
1759
- # source://sorbet-runtime/0.5.10983/lib/types/struct.rb#13
1768
+ # source://sorbet-runtime/0.5.11971/lib/types/struct.rb#13
1760
1769
  def inherited(s); end
1761
1770
  end
1762
1771
  end
@@ -1788,11 +1797,11 @@ Mocktail::VERSION = T.let(T.unsafe(nil), String)
1788
1797
 
1789
1798
  # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb#4
1790
1799
  class Mocktail::ValidatesArguments
1791
- # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb#32
1800
+ # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb#35
1792
1801
  sig { void }
1793
1802
  def initialize; end
1794
1803
 
1795
- # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb#37
1804
+ # source://mocktail//lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb#40
1796
1805
  sig { params(dry_call: ::Mocktail::Call).returns(::NilClass) }
1797
1806
  def validate(dry_call); end
1798
1807
 
data/script/build ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -xeuo pipefail
4
+
5
+ echo "-----> Deleting lib/ and copying src/ to lib/"
6
+ rm -rf lib
7
+ cp -r src/ lib
8
+
9
+ echo "-----> Erasing sorbet sigs from lib/ (for non-Sorbet users)"
10
+ bundle exec sorbet-eraser "lib/**/*.rb"
11
+ echo "-----> Overwriting Mocktail::TYPED constant for lib/"
12
+ cat << RUBY > lib/mocktail/typed.rb
13
+ module Mocktail
14
+ TYPED = false
15
+ end
16
+ RUBY
17
+
18
+ echo "-----> Erasing sorbet 'typed: ' sigils from lib/mocktail"
19
+ ./script/strip_sigils
20
+
21
+ echo "-----> Copying src/ to lib/mocktail/sorbet/ (for Sorbet users)"
22
+ cp -r src/ lib/mocktail/sorbet
23
+
24
+ echo "-----> Running Standard against all code"
25
+ bundle exec rake standard:fix
26
+
27
+ echo "-----> Generating RBIs to publish with the gems"
28
+
29
+ echo "----------> ❶ Faking out mocktail.rb and pointing it to mocktail/sorbet"
30
+ mv lib/mocktail.rb lib/mocktail.rb.nope
31
+ cat << RUBY > lib/mocktail.rb
32
+ require_relative "mocktail/sorbet"
33
+ RUBY
34
+
35
+ echo "----------> ❷ Generating sorbet sigs via tapioca in sub_projects/rbi_generator"
36
+ rm -f rbi/mocktail-pregenerated.rbi
37
+ cd sub_projects/rbi_generator
38
+ rm -f sorbet/rbi/gems/mocktail@*.rbi
39
+ bundle
40
+ bundle exec tapioca gem --all --exclude=tapioca ast diff-lcs erubi netrc parser prettier_print racc rbi spoom syntax_tree thor unparser sorbet yard parallel yard-sorbet
41
+ cd ../..
42
+
43
+ echo "----------> ❸ Moving the generated RBI to rbi/mocktail-pregenerated.rbi"
44
+ cp sub_projects/rbi_generator/sorbet/rbi/gems/mocktail@*.rbi rbi/mocktail-pregenerated.rbi
45
+ mv lib/mocktail.rb.nope lib/mocktail.rb
46
+
47
+
data/script/setup ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -xeuo pipefail
4
+
5
+ bundle
6
+
7
+ cd sub_projects/rbi_generator/
8
+ bundle
9
+ cd ../..
10
+
11
+ cd sub_projects/sorbet_user/
12
+ bundle
13
+ cd ../..
14
+
15
+ cd sub_projects/untyped_user/
16
+ bundle
17
+ cd ../..
data/script/spoom_me ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -xeuo pipefail
4
+
5
+ bundle exec spoom coverage --save
6
+ bundle exec spoom coverage report
7
+ bundle exec spoom coverage open
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+
3
+ # Removes all the sigil comments from the top of our sorbet-free code
4
+
5
+ # Find all files that start with "# typed" in the first line
6
+ files=$(grep -rl '^# typed' --exclude-dir=lib/mocktail/sorbet lib/*)
7
+
8
+ # Loop through each file and delete the first line
9
+ for file in $files
10
+ do
11
+ # Check if we're on a Mac
12
+ if [[ "$OSTYPE" == "darwin"* ]]; then
13
+ sed -i '' '1d' $file
14
+ else
15
+ sed -i '1d' $file
16
+ fi
17
+ done
data/script/test ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -xeuo pipefail
4
+
5
+ echo "-----> Running Mocktail's test against src"
6
+ COVER=true bundle exec rake
7
+
8
+ echo "-----> Type-checking Mocktail source"
9
+ bundle exec srb tc
10
+
11
+ echo "-----> Building src/mocktail into lib/mocktail and lib/mocktail/sorbet"
12
+ ./script/build
13
+
14
+ echo "-----> Running Mocktail's test against lib"
15
+ MOCKTAIL_TEST_SRC_DIRECTORY="lib" bundle exec rake
16
+
17
+ echo "-----> Running Mocktail's test against lib/mocktail/sorbet"
18
+ MOCKTAIL_TEST_SRC_DIRECTORY="lib/mocktail/sorbet" bundle exec rake
19
+
20
+ echo "-----> Ensuring that double-requiring Mocktail produces the right warning and bails out of redefining constants"
21
+ script/test_double_require_warnings
22
+
23
+ echo "-----> Type-checking the copy of Mocktail in lib/mocktail/sorbet"
24
+ bundle exec srb tc --ignore src/ --dir lib/mocktail/sorbet
25
+
26
+ echo "-----> Running sample project tests"
27
+ cd sub_projects/sorbet_user
28
+ ./script/test
29
+ cd ../..
30
+
31
+ cd sub_projects/untyped_user
32
+ ./script/test
33
+ cd ../..
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "open3"
4
+
5
+ def assert_warning(command:, warning:)
6
+ stdout, stderr, status = Open3.capture3(command)
7
+ # Ignore incidental Ruby/RubyGems/Bundler runtime warnings (e.g. from a
8
+ # Ruby version shipping a newer RubyGems than an older pinned Bundler
9
+ # expects) -- they always follow Ruby's "path:line: warning: message"
10
+ # format, unlike Mocktail's own warning below.
11
+ relevant_stderr = stderr.lines.reject { |line| line.match?(/\A\S+:\d+: warning: /) }.join
12
+ if relevant_stderr != warning
13
+ fail <<~MSG
14
+ Expected the correct error message on STDERR but it was wrong"
15
+
16
+ Expected:
17
+ #{warning}
18
+
19
+ Actual:
20
+ #{stderr}
21
+ MSG
22
+
23
+ end
24
+ fail "Expected empty STDOUT, but was #{stdout.inspect}" unless stdout.empty?
25
+ fail "Expected command to exit 0, but was #{status.exitstatus}" unless status.success?
26
+ end
27
+
28
+ puts "Test requiring 'mocktail' and then 'mocktail/sorbet' gives the right warning"
29
+ assert_warning(
30
+ command: <<~CMD,
31
+ bundle exec ruby -e 'require "#{Dir.pwd}/lib/mocktail/sorbet"; require "#{Dir.pwd}/lib/mocktail"'
32
+ CMD
33
+ warning: <<~WARN
34
+ `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'.
35
+ WARN
36
+ )
37
+
38
+ puts "Test requiring 'mocktail/sorbet' and then 'mocktail' gives the right warning"
39
+ assert_warning(
40
+ command: <<~CMD,
41
+ bundle exec ruby -e 'require "#{Dir.pwd}/lib/mocktail"; require "#{Dir.pwd}/lib/mocktail/sorbet"'
42
+ CMD
43
+ warning: <<~WARN
44
+ `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'.
45
+ WARN
46
+ )
data/script/update ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -xeuo pipefail
4
+
5
+ echo "-----> Updating root gems"
6
+ bundle update
7
+
8
+ echo "-----> Updating 'sub_projects/rbi_generator' gems"
9
+ cd sub_projects/rbi_generator
10
+ bundle update
11
+ cd ../..
12
+
13
+ echo "-----> Updating 'sub_projects/sorbet_user' gems"
14
+ cd sub_projects/sorbet_user
15
+ bundle update
16
+ cd ../..
17
+
18
+ echo "-----> Updating 'sub_projects/untyped_user' gems"
19
+ cd sub_projects/untyped_user
20
+ bundle update
21
+ cd ../..
data/sorbet/config ADDED
@@ -0,0 +1,12 @@
1
+ --dir
2
+ .
3
+ --ignore=tmp/
4
+ --ignore=Rakefile
5
+ --ignore=vendor/
6
+ --ignore=sub_projects/sorbet_user/
7
+ --ignore=sub_projects/rbi_generator/
8
+ --ignore=lib/
9
+ # Ignore b/c these stubs will confuse the typechecker and generate a bunch of errors, even tho #typed: false
10
+ --ignore=test/support/sorbet_stubs.rb
11
+ # Ignore b/c this pregenerated rbi is for consumers of the gem, not the gem itself
12
+ --ignore=rbi/mocktail-pregenerated.rbi