arachni 1.2.1 → 1.3

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 (373) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/Gemfile +1 -1
  4. data/README.md +16 -5
  5. data/components/checks/active/ldap_injection/errors.txt +1 -0
  6. data/components/checks/active/source_code_disclosure.rb +1 -1
  7. data/components/checks/active/unvalidated_redirect.rb +6 -6
  8. data/components/checks/active/unvalidated_redirect_dom.rb +10 -7
  9. data/components/checks/passive/grep/captcha.rb +14 -5
  10. data/components/checks/passive/grep/form_upload.rb +7 -3
  11. data/components/checks/passive/grep/hsts.rb +3 -3
  12. data/components/checks/passive/grep/html_objects.rb +2 -3
  13. data/components/checks/passive/grep/http_only_cookies.rb +2 -3
  14. data/components/checks/passive/grep/insecure_cookies.rb +1 -1
  15. data/components/checks/passive/grep/password_autocomplete.rb +2 -2
  16. data/components/checks/passive/grep/unencrypted_password_forms.rb +7 -7
  17. data/components/checks/passive/grep/x_frame_options.rb +2 -2
  18. data/components/checks/passive/http_put.rb +2 -3
  19. data/components/path_extractors/comments.rb +3 -3
  20. data/components/path_extractors/scripts.rb +10 -1
  21. data/components/plugins/defaults/autothrottle.rb +27 -18
  22. data/components/plugins/defaults/meta/remedies/discovery.rb +30 -33
  23. data/components/plugins/defaults/meta/remedies/timing_attacks.rb +7 -11
  24. data/components/plugins/login_script.rb +9 -3
  25. data/components/plugins/proxy.rb +4 -3
  26. data/components/reporters/html.rb +11 -14
  27. data/components/reporters/html/default/issue.erb +13 -38
  28. data/components/reporters/html/default/issue/info.erb +1 -1
  29. data/components/reporters/html/default/summary/issues/by_name.erb +3 -3
  30. data/components/reporters/stdout.rb +62 -71
  31. data/components/reporters/xml.rb +26 -40
  32. data/components/reporters/xml/schema.xsd +43 -89
  33. data/lib/arachni/browser.rb +52 -3
  34. data/lib/arachni/browser/javascript.rb +3 -3
  35. data/lib/arachni/browser/javascript/scripts/taint_tracer.js +46 -25
  36. data/lib/arachni/browser_cluster.rb +61 -0
  37. data/lib/arachni/browser_cluster/job.rb +21 -1
  38. data/lib/arachni/browser_cluster/jobs/browser_provider.rb +3 -1
  39. data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +2 -1
  40. data/lib/arachni/browser_cluster/jobs/resource_exploration/event_trigger.rb +2 -1
  41. data/lib/arachni/browser_cluster/jobs/taint_trace.rb +3 -2
  42. data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger.rb +1 -1
  43. data/lib/arachni/browser_cluster/worker.rb +5 -0
  44. data/lib/arachni/check/auditor.rb +22 -12
  45. data/lib/arachni/data/framework.rb +13 -1
  46. data/lib/arachni/data/issues.rb +9 -25
  47. data/lib/arachni/element/base.rb +9 -3
  48. data/lib/arachni/element/capabilities/analyzable.rb +2 -6
  49. data/lib/arachni/element/capabilities/analyzable/differential.rb +24 -7
  50. data/lib/arachni/element/capabilities/analyzable/{taint.rb → signature.rb} +23 -23
  51. data/lib/arachni/element/capabilities/auditable.rb +0 -6
  52. data/lib/arachni/element/capabilities/dom_only.rb +61 -0
  53. data/lib/arachni/element/capabilities/with_dom.rb +3 -1
  54. data/lib/arachni/element/cookie.rb +35 -5
  55. data/lib/arachni/element/cookie/dom.rb +13 -4
  56. data/lib/arachni/element/{capabilities/auditable/dom.rb → dom.rb} +20 -68
  57. data/lib/arachni/element/dom/capabilities/auditable.rb +29 -0
  58. data/lib/arachni/element/dom/capabilities/inputtable.rb +27 -0
  59. data/lib/arachni/element/dom/capabilities/mutable.rb +21 -0
  60. data/lib/arachni/element/dom/capabilities/submittable.rb +52 -0
  61. data/lib/arachni/element/form.rb +12 -1
  62. data/lib/arachni/element/form/capabilities/mutable.rb +2 -1
  63. data/lib/arachni/element/form/capabilities/with_dom.rb +0 -1
  64. data/lib/arachni/element/form/dom.rb +9 -3
  65. data/lib/arachni/element/header.rb +14 -33
  66. data/lib/arachni/element/header/capabilities/inputtable.rb +29 -0
  67. data/lib/arachni/element/header/capabilities/mutable.rb +51 -0
  68. data/lib/arachni/element/input/dom.rb +71 -0
  69. data/lib/arachni/element/json.rb +2 -0
  70. data/lib/arachni/element/link.rb +3 -0
  71. data/lib/arachni/element/link/capabilities/with_dom.rb +0 -1
  72. data/lib/arachni/element/link/dom.rb +16 -3
  73. data/lib/arachni/element/link/dom/capabilities/submittable.rb +29 -0
  74. data/lib/arachni/element/link_template.rb +3 -5
  75. data/lib/arachni/element/link_template/capabilities/inputtable.rb +5 -0
  76. data/lib/arachni/element/link_template/capabilities/with_dom.rb +0 -1
  77. data/lib/arachni/element/link_template/dom.rb +16 -3
  78. data/lib/arachni/element/link_template/dom/capabilities/submittable.rb +29 -0
  79. data/lib/arachni/element/server.rb +3 -5
  80. data/lib/arachni/element/ui_form.rb +106 -0
  81. data/lib/arachni/element/ui_form/dom.rb +107 -0
  82. data/lib/arachni/element/ui_input.rb +62 -0
  83. data/lib/arachni/element/xml.rb +2 -1
  84. data/lib/arachni/framework.rb +7 -5
  85. data/lib/arachni/framework/parts/audit.rb +0 -1
  86. data/lib/arachni/framework/parts/check.rb +1 -0
  87. data/lib/arachni/framework/parts/data.rb +4 -0
  88. data/lib/arachni/framework/parts/state.rb +0 -2
  89. data/lib/arachni/http/client.rb +17 -6
  90. data/lib/arachni/http/proxy_server.rb +52 -5
  91. data/lib/arachni/http/request.rb +1 -1
  92. data/lib/arachni/issue.rb +34 -179
  93. data/lib/arachni/issue/severity.rb +2 -0
  94. data/lib/arachni/option_groups/audit.rb +22 -2
  95. data/lib/arachni/option_groups/browser_cluster.rb +15 -0
  96. data/lib/arachni/page.rb +3 -2
  97. data/lib/arachni/parser.rb +24 -5
  98. data/lib/arachni/platform/manager.rb +1 -2
  99. data/lib/arachni/rpc/server/framework.rb +3 -4
  100. data/lib/arachni/rpc/server/framework/multi_instance.rb +2 -1
  101. data/lib/arachni/session.rb +1 -1
  102. data/lib/arachni/trainer.rb +4 -7
  103. data/lib/arachni/watir/element.rb +12 -1
  104. data/lib/version +1 -1
  105. data/spec/arachni/browser/element_locator_spec.rb +43 -43
  106. data/spec/arachni/browser/javascript/dom_monitor_spec.rb +44 -44
  107. data/spec/arachni/browser/javascript/proxy/stub_spec.rb +17 -14
  108. data/spec/arachni/browser/javascript/proxy_spec.rb +24 -24
  109. data/spec/arachni/browser/javascript/taint_tracer/frame/called_function_spec.rb +11 -11
  110. data/spec/arachni/browser/javascript/taint_tracer/frame_spec.rb +7 -7
  111. data/spec/arachni/browser/javascript/taint_tracer/sink/data_flow_spec.rb +13 -13
  112. data/spec/arachni/browser/javascript/taint_tracer/sink/execution_flow_spec.rb +7 -7
  113. data/spec/arachni/browser/javascript/taint_tracer_spec.rb +568 -558
  114. data/spec/arachni/browser/javascript_spec.rb +73 -63
  115. data/spec/arachni/browser_cluster/job/result_spec.rb +3 -3
  116. data/spec/arachni/browser_cluster/job_spec.rb +68 -48
  117. data/spec/arachni/browser_cluster/jobs/resource_exploration/event_trigger/result_spec.rb +2 -2
  118. data/spec/arachni/browser_cluster/jobs/resource_exploration/event_trigger_spec.rb +5 -4
  119. data/spec/arachni/browser_cluster/jobs/resource_exploration/result_spec.rb +2 -2
  120. data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +5 -5
  121. data/spec/arachni/browser_cluster/worker_spec.rb +87 -70
  122. data/spec/arachni/browser_cluster_spec.rb +64 -39
  123. data/spec/arachni/browser_spec.rb +692 -527
  124. data/spec/arachni/check/auditor_spec.rb +177 -147
  125. data/spec/arachni/check/base_spec.rb +33 -33
  126. data/spec/arachni/check/manager_spec.rb +15 -15
  127. data/spec/arachni/component/base_spec.rb +8 -8
  128. data/spec/arachni/component/manager_spec.rb +100 -99
  129. data/spec/arachni/component/options/address_spec.rb +3 -3
  130. data/spec/arachni/component/options/base_spec.rb +7 -7
  131. data/spec/arachni/component/options/bool_spec.rb +9 -9
  132. data/spec/arachni/component/options/float_spec.rb +6 -6
  133. data/spec/arachni/component/options/int_spec.rb +5 -5
  134. data/spec/arachni/component/options/multiple_choice_spec.rb +12 -12
  135. data/spec/arachni/component/options/object_spec.rb +2 -2
  136. data/spec/arachni/component/options/path_spec.rb +3 -3
  137. data/spec/arachni/component/options/port_spec.rb +5 -5
  138. data/spec/arachni/component/options/string_spec.rb +3 -3
  139. data/spec/arachni/component/options/url_spec.rb +4 -4
  140. data/spec/arachni/component/utilities_spec.rb +2 -2
  141. data/spec/arachni/data/framework/rpc_spec.rb +10 -9
  142. data/spec/arachni/data/framework_spec.rb +65 -46
  143. data/spec/arachni/data/issues_spec.rb +39 -77
  144. data/spec/arachni/data/plugins_spec.rb +11 -11
  145. data/spec/arachni/data/session_spec.rb +6 -6
  146. data/spec/arachni/data_spec.rb +8 -8
  147. data/spec/arachni/element/body_spec.rb +10 -10
  148. data/spec/arachni/element/capabilities/analyzable/differential_spec.rb +39 -21
  149. data/spec/arachni/element/capabilities/analyzable/{taint_spec.rb → signature_spec.rb} +63 -63
  150. data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +51 -51
  151. data/spec/arachni/element/capabilities/with_scope/scope_spec.rb +5 -5
  152. data/spec/arachni/element/cookie/dom_spec.rb +37 -18
  153. data/spec/arachni/element/cookie_spec.rb +206 -139
  154. data/spec/arachni/element/form/dom_spec.rb +36 -19
  155. data/spec/arachni/element/form_spec.rb +210 -187
  156. data/spec/arachni/element/generic_dom_spec.rb +14 -14
  157. data/spec/arachni/element/header_spec.rb +35 -17
  158. data/spec/arachni/element/json_spec.rb +53 -31
  159. data/spec/arachni/element/link/dom_spec.rb +46 -28
  160. data/spec/arachni/element/link_spec.rb +58 -40
  161. data/spec/arachni/element/link_template/dom_spec.rb +47 -29
  162. data/spec/arachni/element/link_template_spec.rb +79 -61
  163. data/spec/arachni/element/path_spec.rb +1 -1
  164. data/spec/arachni/element/server_spec.rb +33 -32
  165. data/spec/arachni/element/ui_form/ui_form_dom_spec.rb +164 -0
  166. data/spec/arachni/element/ui_form_spec.rb +242 -0
  167. data/spec/arachni/element/ui_input/dom_spec.rb +157 -0
  168. data/spec/arachni/element/ui_input_spec.rb +136 -0
  169. data/spec/arachni/element/xml_spec.rb +42 -24
  170. data/spec/arachni/element_filter_spec.rb +49 -48
  171. data/spec/arachni/error_spec.rb +3 -3
  172. data/spec/arachni/framework/parts/audit_spec.rb +64 -63
  173. data/spec/arachni/framework/parts/browser_spec.rb +16 -16
  174. data/spec/arachni/framework/parts/check_spec.rb +3 -3
  175. data/spec/arachni/framework/parts/data_spec.rb +48 -48
  176. data/spec/arachni/framework/parts/platform_spec.rb +3 -3
  177. data/spec/arachni/framework/parts/plugin_spec.rb +7 -6
  178. data/spec/arachni/framework/parts/report_spec.rb +7 -7
  179. data/spec/arachni/framework/parts/scope_spec.rb +16 -16
  180. data/spec/arachni/framework/parts/state_spec.rb +68 -69
  181. data/spec/arachni/framework_spec.rb +39 -31
  182. data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +32 -32
  183. data/spec/arachni/http/client_spec.rb +219 -208
  184. data/spec/arachni/http/cookie_jar_spec.rb +72 -72
  185. data/spec/arachni/http/headers_spec.rb +14 -14
  186. data/spec/arachni/http/proxy_server_spec.rb +43 -42
  187. data/spec/arachni/http/request_spec.rb +105 -103
  188. data/spec/arachni/http/response/scope_spec.rb +24 -24
  189. data/spec/arachni/http/response_spec.rb +50 -49
  190. data/spec/arachni/issue/severity_spec.rb +10 -9
  191. data/spec/arachni/issue_spec.rb +71 -369
  192. data/spec/arachni/option_groups/audit_spec.rb +114 -114
  193. data/spec/arachni/option_groups/browser_cluster_spec.rb +20 -3
  194. data/spec/arachni/option_groups/datastore_spec.rb +6 -6
  195. data/spec/arachni/option_groups/dispatcher_spec.rb +19 -19
  196. data/spec/arachni/option_groups/http_spec.rb +11 -11
  197. data/spec/arachni/option_groups/input_spec.rb +31 -27
  198. data/spec/arachni/option_groups/output_spec.rb +2 -2
  199. data/spec/arachni/option_groups/paths_spec.rb +17 -17
  200. data/spec/arachni/option_groups/rpc_spec.rb +2 -2
  201. data/spec/arachni/option_groups/scope_spec.rb +40 -40
  202. data/spec/arachni/option_groups/session_spec.rb +6 -5
  203. data/spec/arachni/option_groups/snapshot_spec.rb +4 -4
  204. data/spec/arachni/options_spec.rb +46 -45
  205. data/spec/arachni/page/dom/transition_spec.rb +74 -72
  206. data/spec/arachni/page/dom_spec.rb +35 -35
  207. data/spec/arachni/page/scope_spec.rb +15 -15
  208. data/spec/arachni/page_spec.rb +217 -217
  209. data/spec/arachni/parser_spec.rb +106 -104
  210. data/spec/arachni/platform/fingerprinter_spec.rb +17 -14
  211. data/spec/arachni/platform/list_spec.rb +33 -33
  212. data/spec/arachni/platform/manager_spec.rb +67 -64
  213. data/spec/arachni/plugin/base_spec.rb +10 -10
  214. data/spec/arachni/plugin/manager_spec.rb +38 -37
  215. data/spec/arachni/report_spec.rb +43 -40
  216. data/spec/arachni/reporter/base_spec.rb +15 -15
  217. data/spec/arachni/reporter/manager_spec.rb +4 -4
  218. data/spec/arachni/reporter/options_spec.rb +6 -6
  219. data/spec/arachni/rpc/client/base_spec.rb +6 -6
  220. data/spec/arachni/rpc/client/dispatcher_spec.rb +2 -2
  221. data/spec/arachni/rpc/client/instance_spec.rb +6 -6
  222. data/spec/arachni/rpc/server/active_options_spec.rb +11 -8
  223. data/spec/arachni/rpc/server/base_spec.rb +5 -5
  224. data/spec/arachni/rpc/server/checks/manager_spec.rb +8 -8
  225. data/spec/arachni/rpc/server/dispatcher/node_spec.rb +37 -37
  226. data/spec/arachni/rpc/server/dispatcher/service_spec.rb +15 -14
  227. data/spec/arachni/rpc/server/dispatcher_spec.rb +36 -35
  228. data/spec/arachni/rpc/server/framework/distributor_spec.rb +36 -36
  229. data/spec/arachni/rpc/server/framework_multi_spec.rb +340 -336
  230. data/spec/arachni/rpc/server/framework_spec.rb +90 -85
  231. data/spec/arachni/rpc/server/instance_spec.rb +126 -107
  232. data/spec/arachni/rpc/server/output_spec.rb +1 -1
  233. data/spec/arachni/rpc/server/plugin/manager_spec.rb +6 -6
  234. data/spec/arachni/ruby/array_spec.rb +42 -42
  235. data/spec/arachni/ruby/hash_spec.rb +20 -18
  236. data/spec/arachni/ruby/io_spec.rb +2 -2
  237. data/spec/arachni/ruby/object_spec.rb +1 -1
  238. data/spec/arachni/ruby/set_spec.rb +3 -3
  239. data/spec/arachni/ruby/string_spec.rb +30 -30
  240. data/spec/arachni/ruby/webrick_spec.rb +2 -2
  241. data/spec/arachni/scope_spec.rb +1 -1
  242. data/spec/arachni/session_spec.rb +67 -64
  243. data/spec/arachni/snapshot_spec.rb +15 -15
  244. data/spec/arachni/state/audit_spec.rb +11 -11
  245. data/spec/arachni/state/element_filter_spec.rb +6 -6
  246. data/spec/arachni/state/framework/rpc_spec.rb +12 -12
  247. data/spec/arachni/state/framework_spec.rb +125 -121
  248. data/spec/arachni/state/http_spec.rb +7 -7
  249. data/spec/arachni/state/options_spec.rb +7 -7
  250. data/spec/arachni/state/plugins_spec.rb +8 -8
  251. data/spec/arachni/state_spec.rb +10 -10
  252. data/spec/arachni/support/buffer/autoflush_spec.rb +16 -16
  253. data/spec/arachni/support/buffer/base_spec.rb +39 -39
  254. data/spec/arachni/support/cache/least_cost_replacement_spec.rb +18 -18
  255. data/spec/arachni/support/cache/least_recently_pushed_spec.rb +24 -24
  256. data/spec/arachni/support/cache/least_recently_used_spec.rb +20 -20
  257. data/spec/arachni/support/cache/preference_spec.rb +4 -4
  258. data/spec/arachni/support/cache/random_replacement_spec.rb +8 -8
  259. data/spec/arachni/support/crypto/rsa_aes_cbc_spec.rb +1 -1
  260. data/spec/arachni/support/database/hash_spec.rb +44 -43
  261. data/spec/arachni/support/database/queue_spec.rb +27 -27
  262. data/spec/arachni/support/lookup/hash_set_spec.rb +8 -8
  263. data/spec/arachni/support/lookup/moolb_spec.rb +3 -3
  264. data/spec/arachni/support/mixins/observable_spec.rb +6 -6
  265. data/spec/arachni/support/signature_spec.rb +19 -19
  266. data/spec/arachni/trainer_spec.rb +39 -39
  267. data/spec/arachni/typhoeus/hydra_spec.rb +2 -2
  268. data/spec/arachni/uri/scope_spec.rb +66 -66
  269. data/spec/arachni/uri_spec.rb +107 -105
  270. data/spec/arachni/utilities_spec.rb +40 -40
  271. data/spec/components/checks/active/csrf_spec.rb +8 -8
  272. data/spec/components/checks/active/no_sql_injection_spec.rb +1 -1
  273. data/spec/components/checks/active/sql_injection_spec.rb +16 -16
  274. data/spec/components/checks/active/trainer_spec.rb +4 -4
  275. data/spec/components/checks/active/unvalidated_redirect_dom_spec.rb +4 -2
  276. data/spec/components/checks/active/xpath_injection_spec.rb +1 -1
  277. data/spec/components/checks/active/xss_dom_script_context_spec.rb +51 -21
  278. data/spec/components/checks/active/xss_dom_spec.rb +46 -24
  279. data/spec/components/checks/passive/allowed_methods_spec.rb +1 -1
  280. data/spec/components/checks/passive/grep/cookie_set_for_parent_domain_spec.rb +1 -1
  281. data/spec/components/checks/passive/grep/hsts_spec.rb +2 -2
  282. data/spec/components/checks/passive/grep/http_only_cookies_spec.rb +1 -1
  283. data/spec/components/checks/passive/grep/insecure_cookies_spec.rb +1 -1
  284. data/spec/components/checks/passive/grep/insecure_cors_policy_spec.rb +2 -2
  285. data/spec/components/checks/passive/grep/password_autocomplete_spec.rb +1 -1
  286. data/spec/components/checks/passive/grep/private_ip_spec.rb +3 -3
  287. data/spec/components/checks/passive/grep/unencrypted_password_forms_spec.rb +1 -1
  288. data/spec/components/checks/passive/grep/x_frame_options_spec.rb +2 -2
  289. data/spec/components/checks/passive/interesting_responses_spec.rb +2 -2
  290. data/spec/components/checks/passive/webdav_spec.rb +1 -1
  291. data/spec/components/checks/passive/xst_spec.rb +1 -1
  292. data/spec/components/fingerprinters/servers/apache_spec.rb +2 -2
  293. data/spec/components/path_extractors/comments_spec.rb +5 -1
  294. data/spec/components/path_extractors/scripts_spec.rb +5 -2
  295. data/spec/components/plugins/autologin_spec.rb +22 -22
  296. data/spec/components/plugins/autothrottle_spec.rb +6 -5
  297. data/spec/components/plugins/content_types_spec.rb +4 -4
  298. data/spec/components/plugins/cookie_collector_spec.rb +5 -5
  299. data/spec/components/plugins/exec_spec.rb +12 -12
  300. data/spec/components/plugins/form_dicattack_spec.rb +3 -3
  301. data/spec/components/plugins/headers_collector_spec.rb +8 -8
  302. data/spec/components/plugins/healthmap_spec.rb +3 -3
  303. data/spec/components/plugins/http_dicattack_spec.rb +3 -3
  304. data/spec/components/plugins/login_script_spec.rb +79 -22
  305. data/spec/components/plugins/meta/remedies/discovery_spec.rb +3 -2
  306. data/spec/components/plugins/meta/remedies/timing_attacks_spec.rb +3 -3
  307. data/spec/components/plugins/meta/uniformity_spec.rb +2 -2
  308. data/spec/components/plugins/restrict_to_dom_state_spec.rb +1 -1
  309. data/spec/components/plugins/script_spec.rb +1 -1
  310. data/spec/components/plugins/uncommon_headers_spec.rb +2 -2
  311. data/spec/components/plugins/vector_collector_spec.rb +2 -2
  312. data/spec/components/plugins/vector_feed_spec.rb +40 -40
  313. data/spec/components/plugins/waf_detector_spec.rb +6 -6
  314. data/spec/components/reporters/json_spec.rb +4 -4
  315. data/spec/components/reporters/marshal_spec.rb +2 -2
  316. data/spec/components/reporters/yaml_spec.rb +3 -2
  317. data/spec/external/wavsep/active/sqli_spec.rb +1 -3
  318. data/spec/spec_helper.rb +4 -0
  319. data/spec/support/factories/element/ui_form.rb +14 -0
  320. data/spec/support/factories/element/ui_input.rb +13 -0
  321. data/spec/support/factories/issue.rb +0 -13
  322. data/spec/support/fixtures/report.afr +0 -0
  323. data/spec/support/fixtures/{taint_check/taint.rb → signature_check/signature.rb} +2 -2
  324. data/spec/support/helpers/browser_cluster/jobs/taint_tracer.rb +11 -11
  325. data/spec/support/helpers/framework.rb +1 -1
  326. data/spec/support/helpers/pages.rb +2 -2
  327. data/spec/support/servers/arachni/browser.rb +139 -0
  328. data/spec/support/servers/arachni/browser/javascript/taint_tracer.rb +40 -0
  329. data/spec/support/servers/arachni/element/capabilities/analyzable/{taint.rb → signature.rb} +0 -0
  330. data/spec/support/servers/arachni/element/input/input_dom.rb +102 -0
  331. data/spec/support/servers/arachni/element/ui_form/ui_form_dom.rb +238 -0
  332. data/spec/support/servers/checks/active/trainer_check.rb +7 -7
  333. data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +22 -6
  334. data/spec/support/servers/checks/active/xss_dom.rb +50 -0
  335. data/spec/support/servers/checks/active/xss_dom_script_context.rb +53 -0
  336. data/spec/support/shared/browser/javascript/taint_tracer/sink/base.rb +6 -6
  337. data/spec/support/shared/check.rb +10 -12
  338. data/spec/support/shared/component/options/base.rb +24 -24
  339. data/spec/support/shared/element/base.rb +25 -25
  340. data/spec/support/shared/element/capabilities/auditable.rb +116 -140
  341. data/spec/support/shared/element/capabilities/dom_only.rb +65 -0
  342. data/spec/support/shared/element/capabilities/inputtable.rb +71 -86
  343. data/spec/support/shared/element/capabilities/mutable.rb +122 -111
  344. data/spec/support/shared/element/capabilities/refreshable.rb +10 -10
  345. data/spec/support/shared/element/capabilities/{submitable.rb → submittable.rb} +26 -26
  346. data/spec/support/shared/element/capabilities/with_auditor.rb +10 -10
  347. data/spec/support/shared/element/capabilities/with_dom.rb +8 -8
  348. data/spec/support/shared/element/capabilities/with_node.rb +4 -6
  349. data/spec/support/shared/element/capabilities/with_scope.rb +2 -2
  350. data/spec/support/shared/element/capabilities/with_source.rb +6 -8
  351. data/spec/support/shared/element/dom.rb +144 -0
  352. data/spec/support/shared/element/dom/auditable.rb +42 -0
  353. data/spec/support/shared/element/dom/inputtable.rb +5 -0
  354. data/spec/support/shared/element/dom/mutable.rb +3 -0
  355. data/spec/support/shared/element/dom/submittable.rb +119 -0
  356. data/spec/support/shared/external/wavsep.rb +3 -3
  357. data/spec/support/shared/fingerprinter.rb +2 -2
  358. data/spec/support/shared/framework.rb +1 -1
  359. data/spec/support/shared/http/message.rb +9 -9
  360. data/spec/support/shared/option_group.rb +17 -17
  361. data/spec/support/shared/path_extractor.rb +1 -1
  362. data/spec/support/shared/plugin.rb +2 -2
  363. data/spec/support/shared/support/cache.rb +57 -57
  364. data/spec/support/shared/support/lookup.rb +25 -25
  365. data/ui/cli/framework.rb +22 -11
  366. data/ui/cli/framework/option_parser.rb +15 -0
  367. data/ui/cli/option_parser.rb +8 -1
  368. data/ui/cli/output.rb +2 -1
  369. metadata +54 -20
  370. data/components/checks/active/xss_dom_inputs.rb +0 -236
  371. data/spec/components/checks/active/xss_dom_inputs_spec.rb +0 -30
  372. data/spec/support/servers/checks/active/xss_dom_inputs.rb +0 -59
  373. data/spec/support/shared/element/capabilities/auditable/dom.rb +0 -322
@@ -1,5 +1,16 @@
1
1
  shared_examples_for 'mutable' do |options = {}|
2
2
 
3
+ before :each do
4
+ begin
5
+ Arachni::Options.audit.elements described_class.type
6
+ rescue Arachni::OptionGroups::Audit::Error => e
7
+ end
8
+ end
9
+
10
+ after :each do
11
+ reset_options
12
+ end
13
+
3
14
  let(:opts) do
4
15
  {
5
16
  single_input: false,
@@ -37,7 +48,7 @@ shared_examples_for 'mutable' do |options = {}|
37
48
  end
38
49
 
39
50
  it "supports #{Arachni::RPC::Serializer}" do
40
- mutation.should == Arachni::RPC::Serializer.deep_clone( mutation )
51
+ expect(mutation).to eq(Arachni::RPC::Serializer.deep_clone( mutation ))
41
52
  end
42
53
 
43
54
  describe '#to_rpc_data' do
@@ -45,7 +56,7 @@ shared_examples_for 'mutable' do |options = {}|
45
56
 
46
57
  %w(seed format affected_input_name).each do |attribute|
47
58
  it "includes '#{attribute}'" do
48
- data[attribute].should == mutation.send( attribute )
59
+ expect(data[attribute]).to eq(mutation.send( attribute ))
49
60
  end
50
61
  end
51
62
  end
@@ -56,7 +67,7 @@ shared_examples_for 'mutable' do |options = {}|
56
67
 
57
68
  %w(seed format affected_input_name).each do |attribute|
58
69
  it "restores '#{attribute}'" do
59
- restored.send( attribute ).should == mutation.send( attribute )
70
+ expect(restored.send( attribute )).to eq(mutation.send( attribute ))
60
71
  end
61
72
  end
62
73
  end
@@ -64,12 +75,12 @@ shared_examples_for 'mutable' do |options = {}|
64
75
  describe '#mutation?' do
65
76
  context 'when the element has not been mutated' do
66
77
  it 'returns true' do
67
- mutable.mutation?.should be_false
78
+ expect(mutable.mutation?).to be_falsey
68
79
  end
69
80
  end
70
81
  context 'when the element has been mutated' do
71
82
  it 'returns false' do
72
- mutable.mutations( seed ).first.mutation?.should be_true
83
+ expect(mutable.mutations( seed ).first.mutation?).to be_truthy
73
84
  end
74
85
  end
75
86
  end
@@ -77,12 +88,12 @@ shared_examples_for 'mutable' do |options = {}|
77
88
  describe '#affected_input_value' do
78
89
  it 'returns the value of the affected_input_name input' do
79
90
  elem = mutable.mutations( seed ).first
80
- elem.affected_input_value.should == seed
91
+ expect(elem.affected_input_value).to eq(seed)
81
92
  end
82
93
 
83
94
  context 'when no input has been affected_input_name' do
84
95
  it 'returns nil' do
85
- mutable.affected_input_value.should be_nil
96
+ expect(mutable.affected_input_value).to be_nil
86
97
  end
87
98
  end
88
99
  end
@@ -91,8 +102,8 @@ shared_examples_for 'mutable' do |options = {}|
91
102
  it 'sets the value of the affected_input_name input' do
92
103
  elem = mutable.mutations( seed ).first
93
104
  elem.affected_input_value = 'stuff'
94
- elem.affected_input_value.should == 'stuff'
95
- elem.inputs.values.first.should == 'stuff'
105
+ expect(elem.affected_input_value).to eq('stuff')
106
+ expect(elem.inputs.values.first).to eq('stuff')
96
107
  end
97
108
  end
98
109
 
@@ -101,44 +112,45 @@ shared_examples_for 'mutable' do |options = {}|
101
112
  input = mutable.inputs.keys.first
102
113
 
103
114
  mutable.immutables << input
104
- mutable.mutations( seed ).
105
- reject { |e| e.affected_input_name != input }.
106
- should be_empty
115
+ expect(mutable.mutations( seed ).
116
+ reject { |e| e.affected_input_name != input }).
117
+ to be_empty
107
118
 
108
119
  mutable.immutables.clear
109
- mutable.mutations( seed ).
110
- reject { |e| e.affected_input_name != input }.
111
- should be_any
120
+ expect(mutable.mutations( seed ).
121
+ reject { |e| e.affected_input_name != input }).
122
+ to be_any
112
123
  end
113
124
  end
114
125
 
115
126
  describe '#mutations' do
116
127
  it 'mutates #inputs' do
117
128
  mutable.mutations( seed, skip_original: true ).each do |m|
118
- mutable.url.should == m.url
119
- mutable.action.should == m.action
120
- mutable.inputs.should_not == m.inputs
129
+ expect(mutable.url).to eq(m.url)
130
+ expect(mutable.action).to eq(m.action)
131
+ expect(mutable.inputs).not_to eq(m.inputs)
121
132
  end
122
133
  end
123
134
 
124
135
  it 'sets #affected_input_name to the name of the fuzzed input' do
125
136
  checked = false
126
137
  mutable.mutations( seed, skip_original: true ).each do |m|
127
- mutable.url.should == m.url
128
- mutable.action.should == m.action
129
- mutable.affected_input_name.should_not == m.affected_input_name
130
- m.inputs[m.affected_input_name].should include seed
138
+ expect(mutable.url).to eq(m.url)
139
+ expect(mutable.action).to eq(m.action)
140
+ expect(mutable.affected_input_name).not_to eq(m.affected_input_name)
141
+ expect(m.inputs[m.affected_input_name]).to include seed
131
142
 
132
143
  checked = true
133
144
  end
134
145
 
135
- checked.should be_true
146
+ expect(checked).to be_truthy
136
147
  end
137
148
 
138
149
  context 'with no options' do
139
150
  it 'returns all combinations' do
140
- mutable.mutations( seed, skip_original: true ).size.should ==
151
+ expect(mutable.mutations( seed, skip_original: true ).size).to eq(
141
152
  (inputs.size * 4) / (opts[:supports_nulls] ? 1 : 2)
153
+ )
142
154
  end
143
155
  end
144
156
 
@@ -146,44 +158,44 @@ shared_examples_for 'mutable' do |options = {}|
146
158
  describe :parameter_values do
147
159
  describe true do
148
160
  it 'injects the payload into parameter values' do
149
- mutable.mutations( seed, parameter_values: true ).
150
- find { |m| m.affected_input_value.include? seed }.
151
- should be_true
161
+ expect(mutable.mutations( seed, parameter_values: true ).
162
+ find { |m| m.affected_input_value.include? seed }).
163
+ to be_truthy
152
164
  end
153
165
  end
154
166
  describe false do
155
167
  it 'does not inject the payload into parameter values' do
156
- mutable.mutations( seed, parameter_values: false ).
157
- find { |m| m.affected_input_value.include? seed }.
158
- should be_false
168
+ expect(mutable.mutations( seed, parameter_values: false ).
169
+ find { |m| m.affected_input_value.include? seed }).
170
+ to be_falsey
159
171
  end
160
172
  end
161
173
  describe 'nil' do
162
174
  it 'injects the payload into parameter names' do
163
- mutable.mutations( seed ).
164
- find { |m| m.affected_input_value.include? seed }.
165
- should be_true
175
+ expect(mutable.mutations( seed ).
176
+ find { |m| m.affected_input_value.include? seed }).
177
+ to be_truthy
166
178
  end
167
179
  end
168
180
 
169
181
  describe "#{Arachni::OptionGroups::Audit}#parameter_values" do
170
182
  it 'serves as the default value of :parameter_values' do
171
183
  Arachni::Options.audit.parameter_values = true
172
- mutable.mutations( seed ).
173
- find { |m| m.affected_input_value.include? seed }.
174
- should be_true
184
+ expect(mutable.mutations( seed ).
185
+ find { |m| m.affected_input_value.include? seed }).
186
+ to be_truthy
175
187
 
176
188
  Arachni::Options.audit.parameter_values = false
177
- mutable.mutations( seed ).
178
- find { |m| m.affected_input_value.include? seed }.
179
- should be_false
189
+ expect(mutable.mutations( seed ).
190
+ find { |m| m.affected_input_value.include? seed }).
191
+ to be_falsey
180
192
  end
181
193
  end
182
194
  end
183
195
 
184
196
  describe :with_extra_parameter,
185
197
  if: !described_class.ancestors.include?(
186
- Arachni::Element::Capabilities::Auditable::DOM
198
+ Arachni::Element::DOM
187
199
  ) && described_class != Arachni::Element::LinkTemplate &&
188
200
  described_class != Arachni::Element::XML do
189
201
 
@@ -191,119 +203,118 @@ shared_examples_for 'mutable' do |options = {}|
191
203
 
192
204
  describe true do
193
205
  it 'injects the payload into an extra parameter' do
194
- mutable.mutations( seed, with_extra_parameter: true ).
195
- find { |m| m[extra_name].to_s.include? seed }.should be_true
206
+ expect(mutable.mutations( seed, with_extra_parameter: true ).
207
+ find { |m| m[extra_name].to_s.include? seed }).to be_truthy
196
208
  end
197
209
  end
198
210
  describe false do
199
211
  it 'does not inject the payload into an extra parameter' do
200
- mutable.mutations( seed, with_extra_parameter: false ).
201
- find { |m| m[extra_name].to_s.include? seed }.should be_false
212
+ expect(mutable.mutations( seed, with_extra_parameter: false ).
213
+ find { |m| m[extra_name].to_s.include? seed }).to be_falsey
202
214
  end
203
215
  end
204
216
  describe 'nil' do
205
217
  it 'does not inject the payload into an extra parameter' do
206
- mutable.mutations( seed ).
207
- find { |m| m[extra_name].to_s.include? seed }.should be_false
218
+ expect(mutable.mutations( seed ).
219
+ find { |m| m[extra_name].to_s.include? seed }).to be_falsey
208
220
  end
209
221
  end
210
222
 
211
223
  describe "#{Arachni::OptionGroups::Audit}#with_extra_parameter" do
212
224
  it 'serves as the default value of :with_extra_parameter' do
213
225
  Arachni::Options.audit.with_extra_parameter = true
214
- mutable.mutations( seed ).
215
- find { |m| m[extra_name].to_s.include? seed }.should be_true
226
+ expect(mutable.mutations( seed ).
227
+ find { |m| m[extra_name].to_s.include? seed }).to be_truthy
216
228
 
217
229
  Arachni::Options.audit.with_extra_parameter = false
218
- mutable.mutations( seed ).
219
- find { |m| m[extra_name].to_s.include? seed }.should be_false
230
+ expect(mutable.mutations( seed ).
231
+ find { |m| m[extra_name].to_s.include? seed }).to be_falsey
220
232
  end
221
233
  end
222
234
  end
223
235
 
224
236
  describe :with_both_http_methods,
225
237
  if: !described_class.ancestors.include?(
226
- Arachni::Element::Capabilities::Auditable::DOM
238
+ Arachni::Element::DOM
227
239
  ) && described_class != Arachni::Element::JSON &&
228
240
  described_class != Arachni::Element::XML do
229
241
 
230
242
  describe false do
231
243
  it 'does not fuzz methods' do
232
- mutable.mutations( seed, with_both_http_methods: false ).
233
- map(&:method).uniq.should eq [mutable.method]
244
+ expect(mutable.mutations( seed, with_both_http_methods: false ).
245
+ map(&:method).uniq).to eq [mutable.method]
234
246
  end
235
247
  end
236
248
  describe true do
237
249
  it 'fuzzes methods' do
238
- mutable.mutations( seed, with_both_http_methods: true ).
239
- map(&:method).uniq.should eq [:get, :post]
250
+ expect(mutable.mutations( seed, with_both_http_methods: true ).
251
+ map(&:method).uniq).to eq [:get, :post]
240
252
  end
241
253
  end
242
254
  describe 'nil' do
243
255
  it 'does not fuzz methods' do
244
- mutable.mutations( seed ).map(&:method).uniq.
245
- should == [mutable.method]
256
+ expect(mutable.mutations( seed ).map(&:method).uniq).
257
+ to eq([mutable.method])
246
258
  end
247
259
  end
248
260
 
249
261
  describe "#{Arachni::OptionGroups::Audit}#with_both_http_methods" do
250
262
  it 'serves as the default value of :with_both_http_methods' do
251
263
  Arachni::Options.audit.with_both_http_methods = true
252
- mutable.mutations( seed ).map(&:method).uniq.
253
- should eq [:get, :post]
264
+ expect(mutable.mutations( seed ).map(&:method).uniq).
265
+ to eq [:get, :post]
254
266
 
255
267
  Arachni::Options.audit.with_both_http_methods = false
256
- mutable.mutations( seed ).map(&:method).uniq.
257
- should == [mutable.method]
268
+ expect(mutable.mutations( seed ).map(&:method).uniq).
269
+ to eq([mutable.method])
258
270
  end
259
271
  end
260
272
  end
261
273
 
262
274
  describe :parameter_names,
263
- if: !described_class.ancestors.include?(
264
- Arachni::Element::Capabilities::Auditable::DOM
265
- ) && described_class != Arachni::Element::LinkTemplate &&
275
+ if: !described_class.ancestors.include?( Arachni::Element::DOM) &&
276
+ described_class != Arachni::Element::LinkTemplate &&
266
277
  described_class != Arachni::Element::XML do
267
278
 
268
279
  describe true do
269
280
  it 'uses the seed as a parameter name' do
270
- mutable.mutations( seed, parameter_names: true ).
271
- find { |m| m.inputs.keys.include? seed }.
272
- should be_true
281
+ expect(mutable.mutations( seed, parameter_names: true ).
282
+ find { |m| m.inputs.keys.include? seed }).
283
+ to be_truthy
273
284
  end
274
285
  end
275
286
  describe false do
276
287
  it 'does not use the seed as a parameter name' do
277
- mutable.class.any_instance.
278
- stub(:valid_input_name_data?) { |name| name != seed }
288
+ allow_any_instance_of(mutable.class).
289
+ to receive(:valid_input_name_data?) { |instance, name| name != seed }
279
290
 
280
- mutable.mutations( seed, parameter_names: false ).
281
- find { |m| m.inputs.keys.include? seed }.
282
- should be_false
291
+ expect(mutable.mutations( seed, parameter_names: false ).
292
+ find { |m| m.inputs.keys.include? seed }).
293
+ to be_falsey
283
294
  end
284
295
  end
285
296
  describe 'nil' do
286
297
  it 'does not use the seed as a parameter name' do
287
- described_class.any_instance.
288
- stub(:valid_input_name_data?) { |name| name != seed }
298
+ allow_any_instance_of(described_class).
299
+ to receive(:valid_input_name_data?) { |instance, name| name != seed }
289
300
 
290
- mutable.mutations( seed ).
291
- find { |m| m.inputs.keys.include? seed }.
292
- should be_false
301
+ expect(mutable.mutations( seed ).
302
+ find { |m| m.inputs.keys.include? seed }).
303
+ to be_falsey
293
304
  end
294
305
  end
295
306
 
296
307
  describe "#{Arachni::OptionGroups::Audit}#parameter_names" do
297
308
  it 'serves as the default value of :parameter_names' do
298
309
  Arachni::Options.audit.parameter_names = true
299
- mutable.mutations( seed ).
300
- find { |m| m.inputs.keys.include? seed }.
301
- should be_true
310
+ expect(mutable.mutations( seed ).
311
+ find { |m| m.inputs.keys.include? seed }).
312
+ to be_truthy
302
313
 
303
314
  Arachni::Options.audit.parameter_names = false
304
- mutable.mutations( seed ).
305
- find { |m| m.inputs.keys.include? seed }.
306
- should be_false
315
+ expect(mutable.mutations( seed ).
316
+ find { |m| m.inputs.keys.include? seed }).
317
+ to be_falsey
307
318
  end
308
319
  end
309
320
  end
@@ -320,7 +331,7 @@ shared_examples_for 'mutable' do |options = {}|
320
331
  m = mutable.mutations( seed,
321
332
  format: [Arachni::Element::Capabilities::Mutable::Format::STRAIGHT],
322
333
  skip_original: true ).first
323
- m[m.affected_input_name].should == seed
334
+ expect(m[m.affected_input_name]).to eq(seed)
324
335
  end
325
336
  end
326
337
  describe 'Format::APPEND' do
@@ -328,18 +339,18 @@ shared_examples_for 'mutable' do |options = {}|
328
339
  m = mutable.mutations( seed,
329
340
  format: [Arachni::Element::Capabilities::Mutable::Format::APPEND],
330
341
  skip_original: true ).first
331
- m[m.affected_input_name].should == inputs[m.affected_input_name] + seed
342
+ expect(m[m.affected_input_name]).to eq(inputs[m.affected_input_name] + seed)
332
343
  end
333
344
  end
334
345
  describe 'Format::NULL' do
335
346
  it 'terminates the string with a null character',
336
347
  if: described_class != Arachni::Element::Header &&
337
- described_class.is_a?( Arachni::Element::Capabilities::Auditable::DOM ) do
348
+ described_class.is_a?( Arachni::Element::DOM ) do
338
349
 
339
350
  m = mutable.mutations( seed,
340
351
  format: [Arachni::Element::Capabilities::Mutable::Format::NULL],
341
352
  skip_original: true ).first
342
- m[m.affected_input_name].should == seed + "\0"
353
+ expect(m[m.affected_input_name]).to eq(seed + "\0")
343
354
  end
344
355
  end
345
356
  describe 'Format::SEMICOLON' do
@@ -347,18 +358,18 @@ shared_examples_for 'mutable' do |options = {}|
347
358
  m = mutable.mutations( seed,
348
359
  format: [Arachni::Element::Capabilities::Mutable::Format::SEMICOLON],
349
360
  skip_original: true ).first
350
- m[m.affected_input_name].should == ';' + seed
361
+ expect(m[m.affected_input_name]).to eq(';' + seed)
351
362
  end
352
363
  end
353
364
  describe 'Format::APPEND | Format::NULL' do
354
365
  it 'appends the seed and terminate the string with a null character',
355
366
  if: described_class != Arachni::Element::Header &&
356
- described_class.is_a?( Arachni::Element::Capabilities::Auditable::DOM ) do
367
+ described_class.is_a?( Arachni::Element::DOM ) do
357
368
 
358
369
  format = [Arachni::Element::Capabilities::Mutable::Format::APPEND |
359
370
  Arachni::Element::Capabilities::Mutable::Format::NULL]
360
371
  m = mutable.mutations( seed, format: format, skip_original: true ).first
361
- m[m.affected_input_name].should == inputs[m.affected_input_name] + seed + "\0"
372
+ expect(m[m.affected_input_name]).to eq(inputs[m.affected_input_name] + seed + "\0")
362
373
  end
363
374
  end
364
375
  end
@@ -367,23 +378,23 @@ shared_examples_for 'mutable' do |options = {}|
367
378
  context 'when the payload is not supported' do
368
379
  it 'returns an empty array' do
369
380
  mutable
370
- mutable.class.any_instance.stub(:valid_input_data?) { |i| i != '1' }
381
+ allow_any_instance_of(mutable.class).to receive(:valid_input_data?) { |instance, i| i != '1' }
371
382
 
372
- mutable.mutations('1', skip_original: true ).size.should == 0
383
+ expect(mutable.mutations('1', skip_original: true ).size).to eq(0)
373
384
  end
374
385
 
375
386
  context 'as a value' do
376
387
  it 'skips the mutation' do
377
- mutable.mutations(seed).
388
+ expect(mutable.mutations(seed).
378
389
  select { |m| m.affected_input_value.include? seed }.
379
- size.should > 0
390
+ size).to be > 0
380
391
 
381
- mutable.class.any_instance.
382
- stub(:valid_input_value_data?) { |value| value.include? seed }
392
+ allow_any_instance_of(mutable.class).
393
+ to receive(:valid_input_value_data?) { |instance, value| value.include? seed }
383
394
 
384
- mutable.mutations('1').
395
+ expect(mutable.mutations('1').
385
396
  select { |m| m.affected_input_value.include? seed }.
386
- size.should == 0
397
+ size).to eq(0)
387
398
  end
388
399
  end
389
400
  end
@@ -394,12 +405,12 @@ shared_examples_for 'mutable' do |options = {}|
394
405
  m = mutable.mutations( seed,
395
406
  format: [Arachni::Element::Capabilities::Mutable::Format::STRAIGHT],
396
407
  skip_original: true ).first
397
- m.inputs[m.affected_input_name].should_not == inputs[m.affected_input_name]
408
+ expect(m.inputs[m.affected_input_name]).not_to eq(inputs[m.affected_input_name])
398
409
  end
399
410
 
400
411
  context 'when no input has been affected_input_name' do
401
412
  it 'returns nil' do
402
- mutable.affected_input_name.should be_nil
413
+ expect(mutable.affected_input_name).to be_nil
403
414
  end
404
415
  end
405
416
  end
@@ -414,7 +425,7 @@ shared_examples_for 'mutable' do |options = {}|
414
425
  values << m.affected_input_value
415
426
  end
416
427
 
417
- seeds.sort.uniq.should == %w(my_seed)
428
+ expect(seeds.sort.uniq).to eq(%w(my_seed))
418
429
  end
419
430
  end
420
431
 
@@ -422,34 +433,34 @@ shared_examples_for 'mutable' do |options = {}|
422
433
  let(:dupped) { mutation.dup }
423
434
 
424
435
  it 'preserves #seed' do
425
- dupped.seed.should == mutation.seed
436
+ expect(dupped.seed).to eq(mutation.seed)
426
437
  end
427
438
  it 'preserves #affected_input_name' do
428
- dupped.affected_input_name.should == mutation.affected_input_name
439
+ expect(dupped.affected_input_name).to eq(mutation.affected_input_name)
429
440
  end
430
441
  it 'preserves #format' do
431
- dupped.format.should == mutation.format
442
+ expect(dupped.format).to eq(mutation.format)
432
443
  end
433
444
  it 'preserves #immutables' do
434
445
  mutation.immutables << 'stuff'
435
- dupped.immutables.should == mutation.immutables
446
+ expect(dupped.immutables).to eq(mutation.immutables)
436
447
  end
437
448
  end
438
449
 
439
450
  describe '#to_h' do
440
451
  it 'returns a hash representation of self' do
441
452
  hash = mutation.to_h
442
- hash[:affected_input_name].should == mutation.affected_input_name
443
- hash[:affected_input_value].should == mutation.affected_input_value
444
- hash[:seed].should == mutation.seed
453
+ expect(hash[:affected_input_name]).to eq(mutation.affected_input_name)
454
+ expect(hash[:affected_input_value]).to eq(mutation.affected_input_value)
455
+ expect(hash[:seed]).to eq(mutation.seed)
445
456
  end
446
457
 
447
458
  context 'when the element is not a mutation' do
448
459
  it 'does not include mutation related data' do
449
460
  hash = mutable.to_h
450
- hash.should_not include :affected_input_name
451
- hash.should_not include :affected_input_value
452
- hash.should_not include :seed
461
+ expect(hash).not_to include :affected_input_name
462
+ expect(hash).not_to include :affected_input_value
463
+ expect(hash).not_to include :seed
453
464
  end
454
465
  end
455
466
  end