logstash-output-scalyr 0.1.8 → 0.1.13

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 (320) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Gemfile +5 -0
  4. data/README.md +3 -2
  5. data/lib/logstash/outputs/scalyr.rb +226 -138
  6. data/lib/scalyr/common/client.rb +76 -50
  7. data/lib/scalyr/common/util.rb +7 -0
  8. data/lib/scalyr/constants.rb +2 -0
  9. data/logstash-output-scalyr.gemspec +1 -1
  10. data/spec/logstash/outputs/scalyr_integration_spec.rb +148 -8
  11. data/spec/logstash/outputs/scalyr_spec.rb +12 -6
  12. data/vendor/bundle/jruby/2.5.0/bin/htmldiff +1 -1
  13. data/vendor/bundle/jruby/2.5.0/bin/ldiff +1 -1
  14. data/vendor/bundle/jruby/2.5.0/cache/addressable-2.7.0.gem +0 -0
  15. data/vendor/bundle/jruby/2.5.0/cache/crack-0.4.5.gem +0 -0
  16. data/vendor/bundle/jruby/2.5.0/cache/hashdiff-1.0.1.gem +0 -0
  17. data/vendor/bundle/jruby/2.5.0/cache/public_suffix-4.0.6.gem +0 -0
  18. data/vendor/bundle/jruby/2.5.0/cache/rexml-3.2.5.gem +0 -0
  19. data/vendor/bundle/jruby/2.5.0/cache/webmock-3.13.0.gem +0 -0
  20. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/CHANGELOG.md +235 -0
  21. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/Gemfile +32 -0
  22. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/LICENSE.txt +202 -0
  23. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/README.md +121 -0
  24. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/Rakefile +34 -0
  25. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/data/unicode.data +0 -0
  26. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable.rb +4 -0
  27. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable/idna.rb +27 -0
  28. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable/idna/native.rb +61 -0
  29. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable/idna/pure.rb +676 -0
  30. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable/template.rb +1045 -0
  31. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable/uri.rb +2529 -0
  32. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/lib/addressable/version.rb +32 -0
  33. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/addressable/idna_spec.rb +300 -0
  34. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/addressable/net_http_compat_spec.rb +30 -0
  35. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/addressable/rack_mount_compat_spec.rb +106 -0
  36. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/addressable/security_spec.rb +59 -0
  37. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/addressable/template_spec.rb +1451 -0
  38. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/addressable/uri_spec.rb +6603 -0
  39. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/spec/spec_helper.rb +24 -0
  40. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/tasks/clobber.rake +4 -0
  41. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/tasks/gem.rake +93 -0
  42. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/tasks/git.rake +47 -0
  43. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/tasks/metrics.rake +24 -0
  44. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/tasks/rspec.rake +23 -0
  45. data/vendor/bundle/jruby/2.5.0/gems/addressable-2.7.0/tasks/yard.rake +29 -0
  46. data/vendor/bundle/jruby/2.5.0/gems/crack-0.4.5/lib/crack.rb +7 -0
  47. data/vendor/bundle/jruby/2.5.0/gems/crack-0.4.5/lib/crack/json.rb +98 -0
  48. data/vendor/bundle/jruby/2.5.0/gems/crack-0.4.5/lib/crack/util.rb +17 -0
  49. data/vendor/bundle/jruby/2.5.0/gems/crack-0.4.5/lib/crack/version.rb +3 -0
  50. data/vendor/bundle/jruby/2.5.0/gems/crack-0.4.5/lib/crack/xml.rb +238 -0
  51. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/Gemfile +8 -0
  52. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/LICENSE +19 -0
  53. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/README.md +276 -0
  54. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/Rakefile +18 -0
  55. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/changelog.md +100 -0
  56. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/hashdiff.gemspec +39 -0
  57. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff.rb +10 -0
  58. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/compare_hashes.rb +69 -0
  59. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/diff.rb +177 -0
  60. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/lcs.rb +66 -0
  61. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/lcs_compare_arrays.rb +32 -0
  62. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/linear_compare_array.rb +159 -0
  63. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/patch.rb +88 -0
  64. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/util.rb +155 -0
  65. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/lib/hashdiff/version.rb +5 -0
  66. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/best_diff_spec.rb +75 -0
  67. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/diff_array_spec.rb +60 -0
  68. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/diff_spec.rb +360 -0
  69. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/lcs_spec.rb +76 -0
  70. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/linear_compare_array_spec.rb +50 -0
  71. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/patch_spec.rb +185 -0
  72. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/readme_spec.rb +15 -0
  73. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/hashdiff/util_spec.rb +116 -0
  74. data/vendor/bundle/jruby/2.5.0/gems/hashdiff-1.0.1/spec/spec_helper.rb +15 -0
  75. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/2.0-Upgrade.md +52 -0
  76. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/CHANGELOG.md +406 -0
  77. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/Gemfile +15 -0
  78. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/LICENSE.txt +22 -0
  79. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/README.md +207 -0
  80. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/Rakefile +51 -0
  81. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/SECURITY.md +104 -0
  82. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/bin/console +15 -0
  83. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/codecov.yml +12 -0
  84. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/data/list.txt +13380 -0
  85. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/lib/public_suffix.rb +179 -0
  86. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/lib/public_suffix/domain.rb +235 -0
  87. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/lib/public_suffix/errors.rb +41 -0
  88. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/lib/public_suffix/list.rb +247 -0
  89. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/lib/public_suffix/rule.rb +350 -0
  90. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/lib/public_suffix/version.rb +13 -0
  91. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/public_suffix.gemspec +29 -0
  92. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/acceptance_test.rb +131 -0
  93. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/benchmarks/bm_find.rb +66 -0
  94. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/benchmarks/bm_find_all.rb +102 -0
  95. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/benchmarks/bm_names.rb +91 -0
  96. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/benchmarks/bm_select.rb +26 -0
  97. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/benchmarks/bm_select_incremental.rb +25 -0
  98. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/benchmarks/bm_valid.rb +101 -0
  99. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/profilers/domain_profiler.rb +12 -0
  100. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/profilers/find_profiler.rb +12 -0
  101. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/profilers/find_profiler_jp.rb +12 -0
  102. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/profilers/initialization_profiler.rb +11 -0
  103. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/profilers/list_profsize.rb +11 -0
  104. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/profilers/object_binsize.rb +57 -0
  105. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/psl_test.rb +52 -0
  106. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/test_helper.rb +18 -0
  107. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/tests.txt +98 -0
  108. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/unit/domain_test.rb +106 -0
  109. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/unit/errors_test.rb +25 -0
  110. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/unit/list_test.rb +241 -0
  111. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/unit/public_suffix_test.rb +188 -0
  112. data/vendor/bundle/jruby/2.5.0/gems/public_suffix-4.0.6/test/unit/rule_test.rb +222 -0
  113. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/LICENSE.txt +22 -0
  114. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/NEWS.md +178 -0
  115. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/README.md +48 -0
  116. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/context.rdoc +143 -0
  117. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/rdoc/child.rdoc +87 -0
  118. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/rdoc/document.rdoc +276 -0
  119. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/rdoc/element.rdoc +602 -0
  120. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/rdoc/node.rdoc +97 -0
  121. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/rdoc/parent.rdoc +267 -0
  122. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/tocs/child_toc.rdoc +12 -0
  123. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/tocs/document_toc.rdoc +30 -0
  124. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/tocs/element_toc.rdoc +55 -0
  125. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/tocs/master_toc.rdoc +135 -0
  126. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/tocs/node_toc.rdoc +16 -0
  127. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/doc/rexml/tasks/tocs/parent_toc.rdoc +25 -0
  128. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml.rb +3 -0
  129. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/attlistdecl.rb +63 -0
  130. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/attribute.rb +205 -0
  131. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/cdata.rb +68 -0
  132. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/child.rb +97 -0
  133. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/comment.rb +80 -0
  134. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/doctype.rb +311 -0
  135. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/document.rb +451 -0
  136. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/dtd/attlistdecl.rb +11 -0
  137. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/dtd/dtd.rb +47 -0
  138. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/dtd/elementdecl.rb +18 -0
  139. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/dtd/entitydecl.rb +57 -0
  140. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/dtd/notationdecl.rb +40 -0
  141. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/element.rb +2599 -0
  142. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/encoding.rb +51 -0
  143. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/entity.rb +171 -0
  144. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/formatters/default.rb +116 -0
  145. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +142 -0
  146. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/formatters/transitive.rb +58 -0
  147. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/functions.rb +447 -0
  148. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/instruction.rb +79 -0
  149. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/light/node.rb +188 -0
  150. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/namespace.rb +59 -0
  151. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/node.rb +76 -0
  152. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/output.rb +30 -0
  153. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parent.rb +166 -0
  154. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parseexception.rb +52 -0
  155. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +694 -0
  156. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/lightparser.rb +59 -0
  157. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb +197 -0
  158. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb +273 -0
  159. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb +61 -0
  160. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb +101 -0
  161. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/ultralightparser.rb +57 -0
  162. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb +689 -0
  163. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/quickpath.rb +266 -0
  164. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/rexml.rb +37 -0
  165. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/sax2listener.rb +98 -0
  166. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/security.rb +28 -0
  167. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/source.rb +298 -0
  168. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/streamlistener.rb +93 -0
  169. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/text.rb +424 -0
  170. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/undefinednamespaceexception.rb +9 -0
  171. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/validation/relaxng.rb +539 -0
  172. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/validation/validation.rb +144 -0
  173. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/validation/validationexception.rb +10 -0
  174. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/xmldecl.rb +130 -0
  175. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/xmltokens.rb +85 -0
  176. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/xpath.rb +81 -0
  177. data/vendor/bundle/jruby/2.5.0/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb +974 -0
  178. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/CHANGELOG.md +1894 -0
  179. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/Gemfile +9 -0
  180. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/LICENSE +20 -0
  181. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/README.md +1176 -0
  182. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/Rakefile +38 -0
  183. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock.rb +59 -0
  184. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/api.rb +109 -0
  185. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/assertion_failure.rb +11 -0
  186. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/callback_registry.rb +35 -0
  187. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/config.rb +18 -0
  188. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/cucumber.rb +10 -0
  189. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/deprecation.rb +9 -0
  190. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/errors.rb +17 -0
  191. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +216 -0
  192. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/curb_adapter.rb +351 -0
  193. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +231 -0
  194. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/excon_adapter.rb +165 -0
  195. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
  196. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
  197. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_rb/client.rb +17 -0
  198. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
  199. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_rb/response.rb +64 -0
  200. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
  201. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  202. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  203. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/httpclient_adapter.rb +259 -0
  204. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/manticore_adapter.rb +145 -0
  205. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/net_http.rb +385 -0
  206. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
  207. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/patron_adapter.rb +130 -0
  208. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +174 -0
  209. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  210. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  211. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  212. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/matchers/hash_including_matcher.rb +17 -0
  213. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/minitest.rb +41 -0
  214. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/rack_response.rb +69 -0
  215. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_body_diff.rb +64 -0
  216. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_execution_verifier.rb +77 -0
  217. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_pattern.rb +405 -0
  218. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_registry.rb +35 -0
  219. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_signature.rb +54 -0
  220. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_signature_snippet.rb +61 -0
  221. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/request_stub.rb +100 -0
  222. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/response.rb +159 -0
  223. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/responses_sequence.rb +40 -0
  224. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/rspec.rb +42 -0
  225. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/rspec/matchers.rb +27 -0
  226. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/rspec/matchers/request_pattern_matcher.rb +78 -0
  227. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/rspec/matchers/webmock_matcher.rb +67 -0
  228. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/stub_registry.rb +82 -0
  229. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/stub_request_snippet.rb +38 -0
  230. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/test_unit.rb +20 -0
  231. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/hash_counter.rb +39 -0
  232. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/hash_keys_stringifier.rb +25 -0
  233. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/hash_validator.rb +17 -0
  234. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/headers.rb +64 -0
  235. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/json.rb +67 -0
  236. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/query_mapper.rb +281 -0
  237. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/uri.rb +111 -0
  238. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/values_stringifier.rb +20 -0
  239. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/util/version_checker.rb +111 -0
  240. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/version.rb +3 -0
  241. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/lib/webmock/webmock.rb +163 -0
  242. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/minitest/test_helper.rb +34 -0
  243. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/minitest/test_webmock.rb +9 -0
  244. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/minitest/webmock_spec.rb +60 -0
  245. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/async_http_client/async_http_client_spec.rb +375 -0
  246. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  247. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/curb/curb_spec.rb +499 -0
  248. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/curb/curb_spec_helper.rb +147 -0
  249. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/em_http_request/em_http_request_spec.rb +462 -0
  250. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +77 -0
  251. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/excon/excon_spec.rb +77 -0
  252. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/excon/excon_spec_helper.rb +52 -0
  253. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/http_rb/http_rb_spec.rb +93 -0
  254. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
  255. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/httpclient/httpclient_spec.rb +217 -0
  256. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/httpclient/httpclient_spec_helper.rb +57 -0
  257. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/manticore/manticore_spec.rb +107 -0
  258. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  259. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/net_http/net_http_shared.rb +153 -0
  260. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/net_http/net_http_spec.rb +369 -0
  261. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/net_http/net_http_spec_helper.rb +64 -0
  262. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
  263. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/patron/patron_spec.rb +125 -0
  264. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/patron/patron_spec_helper.rb +54 -0
  265. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +313 -0
  266. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/callbacks.rb +148 -0
  267. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
  268. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
  269. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
  270. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/request_expectations.rb +930 -0
  271. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/returning_declared_responses.rb +409 -0
  272. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/shared/stubbing_requests.rb +678 -0
  273. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +135 -0
  274. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +60 -0
  275. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/acceptance/webmock_shared.rb +41 -0
  276. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/fixtures/test.txt +1 -0
  277. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/quality_spec.rb +84 -0
  278. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/spec_helper.rb +48 -0
  279. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/support/example_curl_output.txt +22 -0
  280. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/support/failures.rb +9 -0
  281. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/support/my_rack_app.rb +53 -0
  282. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/support/network_connection.rb +19 -0
  283. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/support/webmock_server.rb +70 -0
  284. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/api_spec.rb +175 -0
  285. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/errors_spec.rb +129 -0
  286. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
  287. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
  288. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  289. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  290. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/rack_response_spec.rb +112 -0
  291. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_body_diff_spec.rb +90 -0
  292. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_execution_verifier_spec.rb +208 -0
  293. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_pattern_spec.rb +736 -0
  294. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_registry_spec.rb +95 -0
  295. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_signature_snippet_spec.rb +89 -0
  296. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_signature_spec.rb +155 -0
  297. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/request_stub_spec.rb +199 -0
  298. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/response_spec.rb +286 -0
  299. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/stub_registry_spec.rb +103 -0
  300. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/stub_request_snippet_spec.rb +115 -0
  301. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/hash_counter_spec.rb +39 -0
  302. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
  303. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/headers_spec.rb +28 -0
  304. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/json_spec.rb +33 -0
  305. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/query_mapper_spec.rb +157 -0
  306. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/uri_spec.rb +371 -0
  307. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/util/version_checker_spec.rb +65 -0
  308. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/spec/unit/webmock_spec.rb +60 -0
  309. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/test/http_request.rb +24 -0
  310. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/test/shared_test.rb +108 -0
  311. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/test/test_helper.rb +23 -0
  312. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/test/test_webmock.rb +12 -0
  313. data/vendor/bundle/jruby/2.5.0/gems/webmock-3.13.0/webmock.gemspec +54 -0
  314. data/vendor/bundle/jruby/2.5.0/specifications/addressable-2.7.0.gemspec +39 -0
  315. data/vendor/bundle/jruby/2.5.0/specifications/crack-0.4.5.gemspec +32 -0
  316. data/vendor/bundle/jruby/2.5.0/specifications/hashdiff-1.0.1.gemspec +46 -0
  317. data/vendor/bundle/jruby/2.5.0/specifications/public_suffix-4.0.6.gemspec +24 -0
  318. data/vendor/bundle/jruby/2.5.0/specifications/rexml-3.2.5.gemspec +42 -0
  319. data/vendor/bundle/jruby/2.5.0/specifications/webmock-3.13.0.gemspec +85 -0
  320. metadata +309 -2
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # This module provides methods to diff two hash, patch and unpatch hash
5
+ #
6
+ module Hashdiff
7
+ # Apply patch to object
8
+ #
9
+ # @param [Hash, Array] obj the object to be patched, can be an Array or a Hash
10
+ # @param [Array] changes e.g. [[ '+', 'a.b', '45' ], [ '-', 'a.c', '5' ], [ '~', 'a.x', '45', '63']]
11
+ # @param [Hash] options supports following keys:
12
+ # * :delimiter (String) ['.'] delimiter string for representing nested keys in changes array
13
+ #
14
+ # @return the object after patch
15
+ #
16
+ # @since 0.0.1
17
+ def self.patch!(obj, changes, options = {})
18
+ delimiter = options[:delimiter] || '.'
19
+
20
+ changes.each do |change|
21
+ parts = change[1]
22
+ parts = decode_property_path(parts, delimiter) unless parts.is_a?(Array)
23
+
24
+ last_part = parts.last
25
+
26
+ parent_node = node(obj, parts[0, parts.size - 1])
27
+
28
+ if change[0] == '+'
29
+ if parent_node.is_a?(Array)
30
+ parent_node.insert(last_part, change[2])
31
+ else
32
+ parent_node[last_part] = change[2]
33
+ end
34
+ elsif change[0] == '-'
35
+ if parent_node.is_a?(Array)
36
+ parent_node.delete_at(last_part)
37
+ else
38
+ parent_node.delete(last_part)
39
+ end
40
+ elsif change[0] == '~'
41
+ parent_node[last_part] = change[3]
42
+ end
43
+ end
44
+
45
+ obj
46
+ end
47
+
48
+ # Unpatch an object
49
+ #
50
+ # @param [Hash, Array] obj the object to be unpatched, can be an Array or a Hash
51
+ # @param [Array] changes e.g. [[ '+', 'a.b', '45' ], [ '-', 'a.c', '5' ], [ '~', 'a.x', '45', '63']]
52
+ # @param [Hash] options supports following keys:
53
+ # * :delimiter (String) ['.'] delimiter string for representing nested keys in changes array
54
+ #
55
+ # @return the object after unpatch
56
+ #
57
+ # @since 0.0.1
58
+ def self.unpatch!(obj, changes, options = {})
59
+ delimiter = options[:delimiter] || '.'
60
+
61
+ changes.reverse_each do |change|
62
+ parts = change[1]
63
+ parts = decode_property_path(parts, delimiter) unless parts.is_a?(Array)
64
+
65
+ last_part = parts.last
66
+
67
+ parent_node = node(obj, parts[0, parts.size - 1])
68
+
69
+ if change[0] == '+'
70
+ if parent_node.is_a?(Array)
71
+ parent_node.delete_at(last_part)
72
+ else
73
+ parent_node.delete(last_part)
74
+ end
75
+ elsif change[0] == '-'
76
+ if parent_node.is_a?(Array)
77
+ parent_node.insert(last_part, change[2])
78
+ else
79
+ parent_node[last_part] = change[2]
80
+ end
81
+ elsif change[0] == '~'
82
+ parent_node[last_part] = change[2]
83
+ end
84
+ end
85
+
86
+ obj
87
+ end
88
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hashdiff
4
+ # @private
5
+ #
6
+ # judge whether two objects are similar
7
+ def self.similar?(obja, objb, options = {})
8
+ return compare_values(obja, objb, options) if !options[:comparison] && !any_hash_or_array?(obja, objb)
9
+
10
+ count_a = count_nodes(obja)
11
+ count_b = count_nodes(objb)
12
+
13
+ return true if (count_a + count_b).zero?
14
+
15
+ opts = { similarity: 0.8 }.merge!(options)
16
+
17
+ diffs = count_diff diff(obja, objb, opts)
18
+
19
+ (1 - diffs / (count_a + count_b).to_f) >= opts[:similarity]
20
+ end
21
+
22
+ # @private
23
+ #
24
+ # count node differences
25
+ def self.count_diff(diffs)
26
+ diffs.inject(0) do |sum, item|
27
+ old_change_count = count_nodes(item[2])
28
+ new_change_count = count_nodes(item[3])
29
+ sum + (old_change_count + new_change_count)
30
+ end
31
+ end
32
+
33
+ # @private
34
+ #
35
+ # count total nodes for an object
36
+ def self.count_nodes(obj)
37
+ return 0 unless obj
38
+
39
+ count = 0
40
+ if obj.is_a?(Array)
41
+ obj.each { |e| count += count_nodes(e) }
42
+ elsif obj.is_a?(Hash)
43
+ obj.each_value { |v| count += count_nodes(v) }
44
+ else
45
+ return 1
46
+ end
47
+
48
+ count
49
+ end
50
+
51
+ # @private
52
+ #
53
+ # decode property path into an array
54
+ # @param [String] path Property-string
55
+ # @param [String] delimiter Property-string delimiter
56
+ #
57
+ # e.g. "a.b[3].c" => ['a', 'b', 3, 'c']
58
+ def self.decode_property_path(path, delimiter = '.')
59
+ path.split(delimiter).inject([]) do |memo, part|
60
+ if part =~ /^(.*)\[(\d+)\]$/
61
+ if !Regexp.last_match(1).empty?
62
+ memo + [Regexp.last_match(1), Regexp.last_match(2).to_i]
63
+ else
64
+ memo + [Regexp.last_match(2).to_i]
65
+ end
66
+ else
67
+ memo + [part]
68
+ end
69
+ end
70
+ end
71
+
72
+ # @private
73
+ #
74
+ # get the node of hash by given path parts
75
+ def self.node(hash, parts)
76
+ temp = hash
77
+ parts.each do |part|
78
+ temp = temp[part]
79
+ end
80
+ temp
81
+ end
82
+
83
+ # @private
84
+ #
85
+ # check for equality or "closeness" within given tolerance
86
+ def self.compare_values(obj1, obj2, options = {})
87
+ if options[:numeric_tolerance].is_a?(Numeric) &&
88
+ obj1.is_a?(Numeric) && obj2.is_a?(Numeric)
89
+ return (obj1 - obj2).abs <= options[:numeric_tolerance]
90
+ end
91
+
92
+ if options[:strip] == true
93
+ obj1 = obj1.strip if obj1.respond_to?(:strip)
94
+ obj2 = obj2.strip if obj2.respond_to?(:strip)
95
+ end
96
+
97
+ if options[:case_insensitive] == true
98
+ obj1 = obj1.downcase if obj1.respond_to?(:downcase)
99
+ obj2 = obj2.downcase if obj2.respond_to?(:downcase)
100
+ end
101
+
102
+ obj1 == obj2
103
+ end
104
+
105
+ # @private
106
+ #
107
+ # check if objects are comparable
108
+ def self.comparable?(obj1, obj2, strict = true)
109
+ return true if (obj1.is_a?(Array) || obj1.is_a?(Hash)) && obj2.is_a?(obj1.class)
110
+ return true if (obj2.is_a?(Array) || obj2.is_a?(Hash)) && obj1.is_a?(obj2.class)
111
+ return true if !strict && obj1.is_a?(Numeric) && obj2.is_a?(Numeric)
112
+
113
+ obj1.is_a?(obj2.class) && obj2.is_a?(obj1.class)
114
+ end
115
+
116
+ # @private
117
+ #
118
+ # try custom comparison
119
+ def self.custom_compare(method, key, obj1, obj2)
120
+ return unless method
121
+
122
+ res = method.call(key, obj1, obj2)
123
+
124
+ # nil != false here
125
+ return [['~', key, obj1, obj2]] if res == false
126
+ return [] if res == true
127
+ end
128
+
129
+ def self.prefix_append_key(prefix, key, opts)
130
+ if opts[:array_path]
131
+ prefix + [key]
132
+ else
133
+ prefix.empty? ? key.to_s : "#{prefix}#{opts[:delimiter]}#{key}"
134
+ end
135
+ end
136
+
137
+ def self.prefix_append_array_index(prefix, array_index, opts)
138
+ if opts[:array_path]
139
+ prefix + [array_index]
140
+ else
141
+ "#{prefix}[#{array_index}]"
142
+ end
143
+ end
144
+
145
+ class << self
146
+ private
147
+
148
+ # @private
149
+ #
150
+ # checks if both objects are Arrays or Hashes
151
+ def any_hash_or_array?(obja, objb)
152
+ obja.is_a?(Array) || obja.is_a?(Hash) || objb.is_a?(Array) || objb.is_a?(Hash)
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hashdiff
4
+ VERSION = '1.0.1'.freeze
5
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Hashdiff do
6
+ it 'is able to best diff' do
7
+ a = { 'x' => [{ 'a' => 1, 'c' => 3, 'e' => 5 }, { 'y' => 3 }] }
8
+ b = { 'x' => [{ 'a' => 1, 'b' => 2, 'e' => 5 }] }
9
+
10
+ diff = described_class.best_diff(a, b)
11
+ diff.should == [['-', 'x[0].c', 3], ['+', 'x[0].b', 2], ['-', 'x[1]', { 'y' => 3 }]]
12
+ end
13
+
14
+ it 'uses custom delimiter when provided' do
15
+ a = { 'x' => [{ 'a' => 1, 'c' => 3, 'e' => 5 }, { 'y' => 3 }] }
16
+ b = { 'x' => [{ 'a' => 1, 'b' => 2, 'e' => 5 }] }
17
+
18
+ diff = described_class.best_diff(a, b, delimiter: "\t")
19
+ diff.should == [['-', "x[0]\tc", 3], ['+', "x[0]\tb", 2], ['-', 'x[1]', { 'y' => 3 }]]
20
+ end
21
+
22
+ it 'uses custom comparison when provided' do
23
+ a = { 'x' => [{ 'a' => 'foo', 'c' => 'goat', 'e' => 'snake' }, { 'y' => 'baz' }] }
24
+ b = { 'x' => [{ 'a' => 'bar', 'b' => 'cow', 'e' => 'puppy' }] }
25
+
26
+ diff = described_class.best_diff(a, b) do |path, obj1, obj2|
27
+ case path
28
+ when /^x\[.\]\..$/
29
+ obj1.length == obj2.length if obj1 && obj2
30
+ end
31
+ end
32
+
33
+ diff.should == [['-', 'x[0].c', 'goat'], ['+', 'x[0].b', 'cow'], ['-', 'x[1]', { 'y' => 'baz' }]]
34
+ end
35
+
36
+ it 'is able to best diff array in hash' do
37
+ a = { 'menu' => {
38
+ 'id' => 'file',
39
+ 'value' => 'File',
40
+ 'popup' => {
41
+ 'menuitem' => [
42
+ { 'value' => 'New', 'onclick' => 'CreateNewDoc()' },
43
+ { 'value' => 'Close', 'onclick' => 'CloseDoc()' }
44
+ ]
45
+ }
46
+ } }
47
+
48
+ b = { 'menu' => {
49
+ 'id' => 'file 2',
50
+ 'value' => 'File',
51
+ 'popup' => {
52
+ 'menuitem' => [
53
+ { 'value' => 'New1', 'onclick' => 'CreateNewDoc()' },
54
+ { 'value' => 'Open', 'onclick' => 'OpenDoc()' },
55
+ { 'value' => 'Close', 'onclick' => 'CloseDoc()' }
56
+ ]
57
+ }
58
+ } }
59
+
60
+ diff = described_class.best_diff(a, b)
61
+ diff.should == [
62
+ ['~', 'menu.id', 'file', 'file 2'],
63
+ ['~', 'menu.popup.menuitem[0].value', 'New', 'New1'],
64
+ ['+', 'menu.popup.menuitem[1]', { 'value' => 'Open', 'onclick' => 'OpenDoc()' }]
65
+ ]
66
+ end
67
+
68
+ it 'is able to have an array_path specified' do
69
+ a = { 'x' => [{ 'a' => 1, 'c' => 3, 'e' => 5 }, { 'y' => 3 }] }
70
+ b = { 'x' => [{ 'a' => 1, 'b' => 2, 'e' => 5 }] }
71
+
72
+ diff = described_class.best_diff(a, b, array_path: true)
73
+ diff.should == [['-', ['x', 0, 'c'], 3], ['+', ['x', 0, 'b'], 2], ['-', ['x', 1], { 'y' => 3 }]]
74
+ end
75
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Hashdiff do
6
+ it 'is able to diff two equal array' do
7
+ a = [1, 2, 3]
8
+ b = [1, 2, 3]
9
+
10
+ diff = described_class.diff_array_lcs(a, b)
11
+ diff.should == []
12
+ end
13
+
14
+ it 'is able to diff two arrays with one element in common' do
15
+ a = [1, 2, 3]
16
+ b = [1, 8, 7]
17
+
18
+ diff = described_class.diff_array_lcs(a, b)
19
+ diff.should == [['-', 2, 3], ['-', 1, 2], ['+', 1, 8], ['+', 2, 7]]
20
+ end
21
+
22
+ it 'is able to diff two arrays with nothing in common' do
23
+ a = [1, 2]
24
+ b = []
25
+
26
+ diff = described_class.diff_array_lcs(a, b)
27
+ diff.should == [['-', 1, 2], ['-', 0, 1]]
28
+ end
29
+
30
+ it 'is able to diff an empty array with an non-empty array' do
31
+ a = []
32
+ b = [1, 2]
33
+
34
+ diff = described_class.diff_array_lcs(a, b)
35
+ diff.should == [['+', 0, 1], ['+', 1, 2]]
36
+ end
37
+
38
+ it 'is able to diff two arrays with two elements in common' do
39
+ a = [1, 3, 5, 7]
40
+ b = [2, 3, 7, 5]
41
+
42
+ diff = described_class.diff_array_lcs(a, b)
43
+ diff.should == [['-', 0, 1], ['+', 0, 2], ['+', 2, 7], ['-', 4, 7]]
44
+ end
45
+
46
+ it 'is able to test two arrays with two common elements in different order' do
47
+ a = [1, 3, 4, 7]
48
+ b = [2, 3, 7, 5]
49
+
50
+ diff = described_class.diff_array_lcs(a, b)
51
+ diff.should == [['-', 0, 1], ['+', 0, 2], ['-', 2, 4], ['+', 3, 5]]
52
+ end
53
+
54
+ it 'is able to diff two arrays with similar elements' do
55
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
56
+ b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
57
+ diff = described_class.diff_array_lcs(a, b)
58
+ diff.should == [['+', 0, 1], ['-', 2, 3]]
59
+ end
60
+ end
@@ -0,0 +1,360 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Hashdiff do
6
+ it 'is able to diff two empty hashes' do
7
+ diff = described_class.diff({}, {})
8
+ diff.should == []
9
+ end
10
+
11
+ it 'is able to diff an hash with an empty hash' do
12
+ a = { 'a' => 3, 'b' => 2 }
13
+ b = {}
14
+
15
+ diff = described_class.diff(a, b)
16
+ expect(diff).to eq([['-', 'a', 3], ['-', 'b', 2]])
17
+
18
+ diff = described_class.diff(b, a)
19
+ diff.should == [['+', 'a', 3], ['+', 'b', 2]]
20
+ end
21
+
22
+ it 'is able to diff two equal hashes' do
23
+ diff = described_class.diff({ 'a' => 2, 'b' => 2 }, 'a' => 2, 'b' => 2)
24
+ diff.should == []
25
+ end
26
+
27
+ it 'is able to diff two equal hashes with mixed key types' do
28
+ a = { 'a' => 1, :b => 1 }
29
+ diff = described_class.diff(a, a)
30
+ diff.should == []
31
+ end
32
+
33
+ it 'is able to diff if mixed key types are removed' do
34
+ a = { 'a' => 1, :b => 1 }
35
+ b = {}
36
+ diff = described_class.diff(a, b)
37
+ diff.should == [['-', 'a', 1], ['-', 'b', 1]]
38
+ end
39
+
40
+ it 'is able to diff if mixed key types are added' do
41
+ a = { 'a' => 1, :b => 1 }
42
+ b = {}
43
+ diff = described_class.diff(b, a)
44
+ diff.should == [['+', 'a', 1], ['+', 'b', 1]]
45
+ end
46
+
47
+ it 'is able to diff two hashes with equivalent numerics, when strict is false' do
48
+ diff = described_class.diff({ 'a' => 2.0, 'b' => 2 }, { 'a' => 2, 'b' => 2.0 }, strict: false)
49
+ diff.should == []
50
+ end
51
+
52
+ it 'ignores string vs symbol differences, when indifferent is true' do
53
+ diff = described_class.diff({ 'a' => 2, :b => 2 }, { :a => 2, 'b' => 2, :c => 3 }, indifferent: true)
54
+ diff.should == [['+', 'c', 3]]
55
+ end
56
+
57
+ it 'is able to diff changes in hash value' do
58
+ diff = described_class.diff({ 'a' => 2, 'b' => 3, 'c' => ' hello' }, 'a' => 2, 'b' => 4, 'c' => 'hello')
59
+ diff.should == [['~', 'b', 3, 4], ['~', 'c', ' hello', 'hello']]
60
+ end
61
+
62
+ it 'is able to diff changes in hash value which is array' do
63
+ diff = described_class.diff({ 'a' => 2, 'b' => [1, 2, 3] }, 'a' => 2, 'b' => [1, 3, 4])
64
+ diff.should == [['-', 'b[1]', 2], ['+', 'b[2]', 4]]
65
+ end
66
+
67
+ it 'is able to diff changes in hash value which is hash' do
68
+ diff = described_class.diff({ 'a' => { 'x' => 2, 'y' => 3, 'z' => 4 }, 'b' => { 'x' => 3, 'z' => 45 } },
69
+ 'a' => { 'y' => 3 }, 'b' => { 'y' => 3, 'z' => 30 })
70
+ diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
71
+ end
72
+
73
+ it 'is able to best diff similar objects in array' do
74
+ diff = described_class.best_diff({ 'a' => [{ 'x' => 2, 'y' => 3, 'z' => 4 }, { 'x' => 11, 'y' => 22, 'z' => 33 }], 'b' => { 'x' => 3, 'z' => 45 } },
75
+ 'a' => [{ 'y' => 3 }, { 'x' => 11, 'z' => 33 }], 'b' => { 'y' => 22 })
76
+ diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]
77
+ end
78
+
79
+ it 'is able to diff addition of key value pair' do
80
+ a = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200 }
81
+ b = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200, 'g' => 300 }
82
+
83
+ diff = described_class.diff(a, b)
84
+ expect(diff).to eq([['+', 'g', 300]])
85
+
86
+ diff = described_class.diff(b, a)
87
+ diff.should == [['-', 'g', 300]]
88
+ end
89
+
90
+ it 'is able to diff value type changes' do
91
+ a = { 'a' => 3 }
92
+ b = { 'a' => { 'a1' => 1, 'a2' => 2 } }
93
+
94
+ diff = described_class.diff(a, b)
95
+ expect(diff).to eq([['~', 'a', 3, { 'a1' => 1, 'a2' => 2 }]])
96
+
97
+ diff = described_class.diff(b, a)
98
+ diff.should == [['~', 'a', { 'a1' => 1, 'a2' => 2 }, 3]]
99
+ end
100
+
101
+ it 'is able to diff value changes: array <=> []' do
102
+ a = { 'a' => 1, 'b' => [1, 2] }
103
+ b = { 'a' => 1, 'b' => [] }
104
+
105
+ diff = described_class.diff(a, b)
106
+ diff.should == [['-', 'b[1]', 2], ['-', 'b[0]', 1]]
107
+ end
108
+
109
+ it 'is able to diff value changes: array <=> nil' do
110
+ a = { 'a' => 1, 'b' => [1, 2] }
111
+ b = { 'a' => 1, 'b' => nil }
112
+
113
+ diff = described_class.diff(a, b)
114
+ diff.should == [['~', 'b', [1, 2], nil]]
115
+ end
116
+
117
+ it 'is able to diff value chagnes: remove array completely' do
118
+ a = { 'a' => 1, 'b' => [1, 2] }
119
+ b = { 'a' => 1 }
120
+
121
+ diff = described_class.diff(a, b)
122
+ diff.should == [['-', 'b', [1, 2]]]
123
+ end
124
+
125
+ it 'is able to diff value changes: remove whole hash' do
126
+ a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
127
+ b = { 'a' => 1 }
128
+
129
+ diff = described_class.diff(a, b)
130
+ diff.should == [['-', 'b', { 'b1' => 1, 'b2' => 2 }]]
131
+ end
132
+
133
+ it 'is able to diff value changes: hash <=> {}' do
134
+ a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
135
+ b = { 'a' => 1, 'b' => {} }
136
+
137
+ diff = described_class.diff(a, b)
138
+ diff.should == [['-', 'b.b1', 1], ['-', 'b.b2', 2]]
139
+ end
140
+
141
+ it 'is able to diff value changes: hash <=> nil' do
142
+ a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
143
+ b = { 'a' => 1, 'b' => nil }
144
+
145
+ diff = described_class.diff(a, b)
146
+ diff.should == [['~', 'b', { 'b1' => 1, 'b2' => 2 }, nil]]
147
+ end
148
+
149
+ it 'is able to diff similar objects in array' do
150
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
151
+ b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
152
+
153
+ diff = described_class.diff(a, b)
154
+ diff.should == [['-', '[0].d', 4], ['+', '[0]', 1], ['-', '[2]', 3]]
155
+ end
156
+
157
+ it 'is able to diff similar & equal objects in array' do
158
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 3]
159
+ b = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }, 3]
160
+
161
+ diff = described_class.diff(a, b)
162
+ diff.should == [['-', '[0].d', 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
163
+ end
164
+
165
+ it 'uses custom delimiter when provided' do
166
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 3]
167
+ b = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }, 3]
168
+
169
+ diff = described_class.diff(a, b, similarity: 0.8, delimiter: "\t")
170
+ diff.should == [['-', "[0]\td", 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
171
+ end
172
+
173
+ context 'when :numeric_tolerance requested' do
174
+ it 'is able to diff changes in hash value' do
175
+ a = { 'a' => 0.558, 'b' => 0.0, 'c' => 0.65, 'd' => 'fin' }
176
+ b = { 'a' => 0.557, 'b' => 'hats', 'c' => 0.67, 'd' => 'fin' }
177
+
178
+ diff = described_class.diff(a, b, numeric_tolerance: 0.01)
179
+ expect(diff).to eq([['~', 'b', 0.0, 'hats'], ['~', 'c', 0.65, 0.67]])
180
+
181
+ diff = described_class.diff(b, a, numeric_tolerance: 0.01)
182
+ diff.should == [['~', 'b', 'hats', 0.0], ['~', 'c', 0.67, 0.65]]
183
+ end
184
+
185
+ it 'is able to diff changes in nested values' do
186
+ a = { 'a' => { 'x' => 0.4, 'y' => 0.338 }, 'b' => [13, 68.03] }
187
+ b = { 'a' => { 'x' => 0.6, 'y' => 0.341 }, 'b' => [14, 68.025] }
188
+
189
+ diff = described_class.diff(a, b, numeric_tolerance: 0.01)
190
+ expect(diff).to eq([['~', 'a.x', 0.4, 0.6], ['-', 'b[0]', 13], ['+', 'b[0]', 14]])
191
+
192
+ diff = described_class.diff(b, a, numeric_tolerance: 0.01)
193
+ diff.should == [['~', 'a.x', 0.6, 0.4], ['-', 'b[0]', 14], ['+', 'b[0]', 13]]
194
+ end
195
+ end
196
+
197
+ context 'when :strip requested' do
198
+ it 'strips strings before comparing' do
199
+ a = { 'a' => ' foo', 'b' => 'fizz buzz' }
200
+ b = { 'a' => 'foo', 'b' => 'fizzbuzz' }
201
+ diff = described_class.diff(a, b, strip: true)
202
+ diff.should == [['~', 'b', 'fizz buzz', 'fizzbuzz']]
203
+ end
204
+
205
+ it 'strips nested strings before comparing' do
206
+ a = { 'a' => { 'x' => ' foo' }, 'b' => ['fizz buzz', 'nerf'] }
207
+ b = { 'a' => { 'x' => 'foo' }, 'b' => %w[fizzbuzz nerf] }
208
+ diff = described_class.diff(a, b, strip: true)
209
+ diff.should == [['-', 'b[0]', 'fizz buzz'], ['+', 'b[0]', 'fizzbuzz']]
210
+ end
211
+ end
212
+
213
+ context 'when :case_insensitive requested' do
214
+ it 'strips strings before comparing' do
215
+ a = { 'a' => 'Foo', 'b' => 'fizz buzz' }
216
+ b = { 'a' => 'foo', 'b' => 'fizzBuzz' }
217
+ diff = described_class.diff(a, b, case_insensitive: true)
218
+ diff.should == [['~', 'b', 'fizz buzz', 'fizzBuzz']]
219
+ end
220
+
221
+ it 'ignores case on nested strings before comparing' do
222
+ a = { 'a' => { 'x' => 'Foo' }, 'b' => ['fizz buzz', 'nerf'] }
223
+ b = { 'a' => { 'x' => 'foo' }, 'b' => %w[fizzbuzz nerf] }
224
+ diff = described_class.diff(a, b, case_insensitive: true)
225
+ diff.should == [['-', 'b[0]', 'fizz buzz'], ['+', 'b[0]', 'fizzbuzz']]
226
+ end
227
+ end
228
+
229
+ context 'when both :strip and :numeric_tolerance requested' do
230
+ it 'applies filters to proper object types' do
231
+ a = { 'a' => ' foo', 'b' => 35, 'c' => 'bar', 'd' => 'baz' }
232
+ b = { 'a' => 'foo', 'b' => 35.005, 'c' => 'bar', 'd' => 18.5 }
233
+ diff = described_class.diff(a, b, strict: false, numeric_tolerance: 0.01, strip: true)
234
+ diff.should == [['~', 'd', 'baz', 18.5]]
235
+ end
236
+ end
237
+
238
+ context 'when both :strip and :case_insensitive requested' do
239
+ it 'applies both filters to strings' do
240
+ a = { 'a' => ' Foo', 'b' => 'fizz buzz' }
241
+ b = { 'a' => 'foo', 'b' => 'fizzBuzz' }
242
+ diff = described_class.diff(a, b, case_insensitive: true, strip: true)
243
+ diff.should == [['~', 'b', 'fizz buzz', 'fizzBuzz']]
244
+ end
245
+ end
246
+
247
+ context 'with custom comparison' do
248
+ let(:a) { { 'a' => 'car', 'b' => 'boat', 'c' => 'plane' } }
249
+ let(:b) { { 'a' => 'bus', 'b' => 'truck', 'c' => ' plan' } }
250
+
251
+ it 'compares using proc specified in block' do
252
+ diff = described_class.diff(a, b) do |prefix, obj1, obj2|
253
+ case prefix
254
+ when /a|b|c/
255
+ obj1.length == obj2.length
256
+ end
257
+ end
258
+ diff.should == [['~', 'b', 'boat', 'truck']]
259
+ end
260
+
261
+ it 'yields added keys' do
262
+ x = { 'a' => 'car', 'b' => 'boat' }
263
+ y = { 'a' => 'car' }
264
+
265
+ diff = described_class.diff(x, y) do |prefix, _obj1, _obj2|
266
+ case prefix
267
+ when /b/
268
+ true
269
+ end
270
+ end
271
+ diff.should == []
272
+ end
273
+
274
+ it 'compares with both proc and :strip when both provided' do
275
+ diff = described_class.diff(a, b, strip: true) do |prefix, obj1, obj2|
276
+ case prefix
277
+ when 'a'
278
+ obj1.length == obj2.length
279
+ end
280
+ end
281
+ diff.should == [['~', 'b', 'boat', 'truck'], ['~', 'c', 'plane', ' plan']]
282
+ end
283
+
284
+ it 'compares nested arrays using proc specified in block' do
285
+ a = { a: 'car', b: %w[boat plane] }
286
+ b = { a: 'bus', b: ['truck', ' plan'] }
287
+
288
+ diff = described_class.diff(a, b) do |path, obj1, obj2|
289
+ case path
290
+ when 'b[*]'
291
+ obj1.length == obj2.length
292
+ end
293
+ end
294
+
295
+ expect(diff).to eq [['~', 'a', 'car', 'bus'], ['~', 'b[1]', 'plane', ' plan'], ['-', 'b[0]', 'boat'], ['+', 'b[0]', 'truck']]
296
+ end
297
+ end
298
+
299
+ context 'when :array_path is true' do
300
+ it 'returns the diff path in an array rather than a string' do
301
+ x = { 'a' => 'foo' }
302
+ y = { 'a' => 'bar' }
303
+ diff = described_class.diff(x, y, array_path: true)
304
+
305
+ diff.should == [['~', ['a'], 'foo', 'bar']]
306
+ end
307
+
308
+ it 'shows array indexes in paths' do
309
+ x = { 'a' => [0, 1, 2] }
310
+ y = { 'a' => [0, 1, 2, 3] }
311
+
312
+ diff = described_class.diff(x, y, array_path: true)
313
+
314
+ diff.should == [['+', ['a', 3], 3]]
315
+ end
316
+
317
+ it 'shows differences with string and symbol keys' do
318
+ x = { 'a' => 'foo' }
319
+ y = { a: 'bar' }
320
+
321
+ diff = described_class.diff(x, y, array_path: true)
322
+ diff.should == [['-', ['a'], 'foo'], ['+', [:a], 'bar']]
323
+ end
324
+
325
+ it 'supports other key types' do
326
+ time = Time.now
327
+ x = { time => 'foo' }
328
+ y = { 0 => 'bar' }
329
+
330
+ diff = described_class.diff(x, y, array_path: true)
331
+ diff.should == [['-', [time], 'foo'], ['+', [0], 'bar']]
332
+ end
333
+ end
334
+
335
+ context 'when :use_lcs is false' do
336
+ it 'shows items in an array as changed' do
337
+ x = %i[a b]
338
+ y = %i[c d]
339
+ diff = described_class.diff(x, y, use_lcs: false)
340
+
341
+ diff.should == [['~', '[0]', :a, :c], ['~', '[1]', :b, :d]]
342
+ end
343
+
344
+ it 'shows additions to arrays' do
345
+ x = { a: [0] }
346
+ y = { a: [0, 1] }
347
+ diff = described_class.diff(x, y, use_lcs: false)
348
+
349
+ diff.should == [['+', 'a[1]', 1]]
350
+ end
351
+
352
+ it 'shows changes to nested arrays' do
353
+ x = { a: [[0, 1]] }
354
+ y = { a: [[1, 2]] }
355
+ diff = described_class.diff(x, y, use_lcs: false)
356
+
357
+ diff.should == [['~', 'a[0][0]', 0, 1], ['~', 'a[0][1]', 1, 2]]
358
+ end
359
+ end
360
+ end