pact 0.1.28 → 1.3.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.
- data/.gitignore +2 -1
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +374 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +58 -55
- data/README.md +214 -139
- data/Rakefile +4 -28
- data/bin/pact +2 -2
- data/config.ru +3 -0
- data/documentation/README.md +13 -0
- data/documentation/configuration.md +166 -0
- data/documentation/diff_formatter_embedded.png +0 -0
- data/documentation/diff_formatter_list.png +0 -0
- data/documentation/diff_formatter_unix.png +0 -0
- data/example/animal-service/Gemfile +14 -0
- data/example/animal-service/Gemfile.lock +69 -0
- data/example/animal-service/Rakefile +5 -0
- data/example/animal-service/config.ru +3 -0
- data/example/animal-service/db/animal_db.sqlite3 +0 -0
- data/example/animal-service/lib/animal_service/animal_repository.rb +12 -0
- data/example/animal-service/lib/animal_service/api.rb +28 -0
- data/example/animal-service/lib/animal_service/db.rb +5 -0
- data/example/animal-service/spec/service_consumers/pact_helper.rb +11 -0
- data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +26 -0
- data/example/zoo-app/Gemfile +12 -0
- data/example/zoo-app/Gemfile.lock +63 -0
- data/example/zoo-app/Rakefile +5 -0
- data/example/zoo-app/doc/pacts/markdown/README.md +3 -0
- data/example/zoo-app/doc/pacts/markdown/Zoo App - Animal Service.md +75 -0
- data/example/zoo-app/lib/zoo_app/animal_service_client.rb +40 -0
- data/example/zoo-app/lib/zoo_app/models/alligator.rb +15 -0
- data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +67 -0
- data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +71 -0
- data/example/zoo-app/spec/service_providers/pact_helper.rb +15 -0
- data/example/zoo-app/spec/spec_helper.rb +6 -0
- data/lib/pact/cli.rb +138 -0
- data/lib/pact/configuration.rb +169 -28
- data/lib/pact/consumer/app_manager.rb +10 -29
- data/lib/pact/consumer/configuration/configuration_extensions.rb +15 -0
- data/lib/pact/consumer/configuration/dsl.rb +12 -0
- data/lib/pact/consumer/configuration/mock_service.rb +91 -0
- data/lib/pact/consumer/configuration/service_consumer.rb +51 -0
- data/lib/pact/consumer/configuration/service_provider.rb +40 -0
- data/lib/pact/consumer/configuration.rb +11 -0
- data/lib/pact/consumer/consumer_contract_builder.rb +44 -47
- data/lib/pact/consumer/interaction_builder.rb +41 -0
- data/lib/pact/consumer/interactions_filter.rb +48 -0
- data/lib/pact/consumer/mock_service/app.rb +82 -0
- data/lib/pact/consumer/mock_service/interaction_delete.rb +33 -0
- data/lib/pact/consumer/mock_service/interaction_list.rb +76 -0
- data/lib/pact/consumer/mock_service/interaction_mismatch.rb +73 -0
- data/lib/pact/consumer/mock_service/interaction_post.rb +31 -0
- data/lib/pact/consumer/mock_service/interaction_replay.rb +139 -0
- data/lib/pact/consumer/mock_service/log_get.rb +28 -0
- data/lib/pact/consumer/mock_service/missing_interactions_get.rb +30 -0
- data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +31 -0
- data/lib/pact/consumer/mock_service/pact_post.rb +33 -0
- data/lib/pact/consumer/mock_service/rack_request_helper.rb +51 -0
- data/lib/pact/consumer/mock_service/verification_get.rb +68 -0
- data/lib/pact/consumer/mock_service.rb +1 -339
- data/lib/pact/consumer/mock_service_client.rb +65 -0
- data/lib/pact/consumer/mock_service_interaction_expectation.rb +37 -0
- data/lib/pact/consumer/request.rb +27 -0
- data/lib/pact/consumer/rspec.rb +9 -19
- data/lib/pact/consumer/server.rb +90 -0
- data/lib/pact/consumer/spec_hooks.rb +38 -0
- data/lib/pact/consumer/world.rb +37 -0
- data/lib/pact/consumer.rb +10 -7
- data/lib/pact/consumer_contract/consumer_contract.rb +115 -0
- data/lib/pact/consumer_contract/consumer_contract_writer.rb +84 -0
- data/lib/pact/consumer_contract/file_name.rb +19 -0
- data/lib/pact/consumer_contract/headers.rb +51 -0
- data/lib/pact/consumer_contract/interaction.rb +67 -0
- data/lib/pact/consumer_contract/pact_file.rb +24 -0
- data/lib/pact/consumer_contract/request.rb +73 -0
- data/lib/pact/consumer_contract/service_consumer.rb +28 -0
- data/lib/pact/consumer_contract/service_provider.rb +28 -0
- data/lib/pact/consumer_contract.rb +1 -110
- data/lib/pact/doc/doc_file.rb +40 -0
- data/lib/pact/doc/generate.rb +11 -0
- data/lib/pact/doc/generator.rb +82 -0
- data/lib/pact/doc/interaction_view_model.rb +114 -0
- data/lib/pact/doc/markdown/consumer_contract_renderer.rb +56 -0
- data/lib/pact/doc/markdown/generator.rb +26 -0
- data/lib/pact/doc/markdown/index_renderer.rb +41 -0
- data/lib/pact/doc/markdown/interaction.erb +14 -0
- data/lib/pact/doc/markdown/interaction_renderer.rb +38 -0
- data/lib/pact/doc/sort_interactions.rb +17 -0
- data/lib/pact/matchers/actual_type.rb +16 -0
- data/lib/pact/matchers/base_difference.rb +37 -0
- data/lib/pact/matchers/differ.rb +153 -0
- data/lib/pact/matchers/difference.rb +13 -0
- data/lib/pact/matchers/difference_indicator.rb +26 -0
- data/lib/pact/matchers/embedded_diff_formatter.rb +62 -0
- data/lib/pact/matchers/expected_type.rb +35 -0
- data/lib/pact/matchers/index_not_found.rb +15 -0
- data/lib/pact/matchers/list_diff_formatter.rb +101 -0
- data/lib/pact/matchers/matchers.rb +91 -37
- data/lib/pact/matchers/no_diff_indicator.rb +18 -0
- data/lib/pact/matchers/regexp_difference.rb +13 -0
- data/lib/pact/matchers/type_difference.rb +16 -0
- data/lib/pact/matchers/unexpected_index.rb +11 -0
- data/lib/pact/matchers/unexpected_key.rb +11 -0
- data/lib/pact/matchers/unix_diff_formatter.rb +114 -0
- data/lib/pact/project_root.rb +7 -0
- data/lib/pact/provider/configuration/configuration_extension.rb +58 -0
- data/lib/pact/provider/configuration/dsl.rb +13 -0
- data/lib/pact/provider/configuration/pact_verification.rb +46 -0
- data/lib/pact/provider/configuration/service_provider_config.rb +16 -0
- data/lib/pact/provider/configuration/service_provider_dsl.rb +59 -0
- data/lib/pact/provider/configuration.rb +7 -0
- data/lib/pact/provider/context.rb +0 -0
- data/lib/pact/provider/matchers/messages.rb +45 -0
- data/lib/pact/provider/pact_helper_locator.rb +22 -0
- data/lib/pact/provider/pact_spec_runner.rb +123 -0
- data/lib/pact/provider/pact_verification.rb +17 -0
- data/lib/pact/provider/print_missing_provider_states.rb +30 -0
- data/lib/pact/provider/request.rb +70 -0
- data/lib/pact/provider/rspec/backtrace_formatter.rb +43 -0
- data/lib/pact/provider/rspec/custom_options_file +0 -0
- data/lib/pact/provider/rspec/formatter_rspec_2.rb +65 -0
- data/lib/pact/provider/rspec/formatter_rspec_3.rb +96 -0
- data/lib/pact/provider/rspec/matchers.rb +97 -0
- data/lib/pact/provider/rspec.rb +181 -0
- data/lib/pact/provider/state/provider_state.rb +181 -0
- data/lib/pact/provider/state/provider_state_configured_modules.rb +13 -0
- data/lib/pact/provider/state/provider_state_manager.rb +42 -0
- data/lib/pact/provider/state/provider_state_proxy.rb +39 -0
- data/lib/pact/provider/test_methods.rb +47 -0
- data/lib/pact/provider/verification_report.rb +36 -0
- data/lib/pact/provider/world.rb +23 -0
- data/lib/pact/provider.rb +3 -0
- data/lib/pact/reification.rb +6 -4
- data/lib/pact/rspec.rb +53 -0
- data/lib/pact/shared/active_support_support.rb +51 -0
- data/lib/pact/shared/dsl.rb +76 -0
- data/lib/pact/shared/jruby_support.rb +18 -0
- data/lib/pact/shared/json_differ.rb +15 -0
- data/lib/pact/shared/key_not_found.rb +15 -0
- data/lib/pact/shared/null_expectation.rb +31 -0
- data/lib/pact/shared/request.rb +80 -0
- data/lib/pact/shared/text_differ.rb +14 -0
- data/lib/pact/something_like.rb +49 -0
- data/lib/pact/symbolize_keys.rb +12 -0
- data/lib/pact/tasks/task_helper.rb +36 -0
- data/lib/pact/tasks/verification_task.rb +87 -0
- data/lib/pact/tasks.rb +2 -0
- data/lib/pact/templates/provider_state.erb +14 -0
- data/lib/pact/term.rb +47 -2
- data/lib/pact/version.rb +1 -1
- data/lib/pact.rb +1 -1
- data/lib/tasks/pact.rake +25 -2
- data/pact.gemspec +13 -11
- data/{scratchpad.txt → scratchpad.rb} +18 -2
- data/spec/features/consumption_spec.rb +24 -56
- data/spec/features/production_spec.rb +19 -24
- data/spec/features/{producer_states → provider_states}/zebras.rb +3 -3
- data/spec/integration/consumer_spec.rb +212 -0
- data/spec/integration/pact/consumer_configuration_spec.rb +66 -0
- data/spec/integration/pact/provider_configuration_spec.rb +25 -0
- data/spec/lib/pact/cli_spec.rb +47 -0
- data/spec/lib/pact/configuration_spec.rb +269 -7
- data/spec/lib/pact/consumer/app_manager_spec.rb +3 -3
- data/spec/lib/pact/consumer/configuration_spec.rb +57 -0
- data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +52 -70
- data/spec/lib/pact/consumer/interaction_builder_spec.rb +91 -0
- data/spec/lib/pact/consumer/interactions_spec.rb +64 -0
- data/spec/lib/pact/consumer/mock_service/app_spec.rb +52 -0
- data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +78 -0
- data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +70 -0
- data/spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb +12 -0
- data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +88 -0
- data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +142 -0
- data/spec/lib/pact/consumer/mock_service_client_spec.rb +88 -0
- data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +54 -0
- data/spec/lib/pact/consumer/request_spec.rb +24 -0
- data/spec/lib/pact/consumer/service_consumer_spec.rb +1 -1
- data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +58 -0
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +180 -0
- data/spec/lib/pact/consumer_contract/consumer_contract_writer_spec.rb +111 -0
- data/spec/lib/pact/consumer_contract/headers_spec.rb +107 -0
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +107 -0
- data/spec/lib/pact/{request_spec.rb → consumer_contract/request_spec.rb} +80 -67
- data/spec/lib/pact/doc/generator_spec.rb +84 -0
- data/spec/lib/pact/doc/interaction_view_model_spec.rb +132 -0
- data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +29 -0
- data/spec/lib/pact/doc/markdown/index_renderer_spec.rb +29 -0
- data/spec/lib/pact/matchers/differ_spec.rb +214 -0
- data/spec/lib/pact/matchers/difference_spec.rb +22 -0
- data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +90 -0
- data/spec/lib/pact/matchers/index_not_found_spec.rb +21 -0
- data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +114 -0
- data/spec/lib/pact/matchers/matchers_spec.rb +400 -254
- data/spec/lib/pact/matchers/regexp_difference_spec.rb +20 -0
- data/spec/lib/pact/matchers/type_difference_spec.rb +34 -0
- data/spec/lib/pact/matchers/unexpected_index_spec.rb +20 -0
- data/spec/lib/pact/matchers/unexpected_key_spec.rb +20 -0
- data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +216 -0
- data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +30 -0
- data/spec/lib/pact/provider/configuration/pact_verification_spec.rb +43 -0
- data/spec/lib/pact/provider/configuration/service_provider_config_spec.rb +21 -0
- data/spec/lib/pact/provider/configuration/service_provider_dsl_spec.rb +108 -0
- data/spec/lib/pact/provider/configuration_spec.rb +50 -0
- data/spec/lib/pact/provider/matchers/messages_spec.rb +116 -0
- data/spec/lib/pact/provider/pact_helper_locator_spec.rb +54 -0
- data/spec/lib/pact/provider/print_missing_provider_states_spec.rb +19 -0
- data/spec/lib/pact/provider/request_spec.rb +78 -0
- data/spec/lib/pact/provider/rspec/formatter_rspec_2_spec.rb +68 -0
- data/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb +72 -0
- data/spec/lib/pact/provider/rspec_spec.rb +55 -0
- data/spec/lib/pact/provider/state/provider_state_manager_spec.rb +89 -0
- data/spec/lib/pact/provider/state/provider_state_proxy_spec.rb +80 -0
- data/spec/lib/pact/provider/state/provider_state_spec.rb +213 -0
- data/spec/lib/pact/provider/world_spec.rb +41 -0
- data/spec/lib/pact/reification_spec.rb +24 -0
- data/spec/lib/pact/shared/dsl_spec.rb +86 -0
- data/spec/lib/pact/shared/json_differ_spec.rb +36 -0
- data/spec/lib/pact/shared/key_not_found_spec.rb +20 -0
- data/spec/lib/pact/shared/request_spec.rb +111 -0
- data/spec/lib/pact/shared/text_differ_spec.rb +54 -0
- data/spec/lib/pact/something_like_spec.rb +21 -0
- data/spec/lib/pact/tasks/task_helper_spec.rb +74 -0
- data/spec/lib/pact/tasks/verification_task_spec.rb +75 -0
- data/spec/lib/pact/term_spec.rb +57 -4
- data/spec/pact_specification/compliance-1.0.0.rb +47 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/standalone/consumer_fail_test.rb +55 -0
- data/spec/standalone/consumer_pass_test.rb +51 -0
- data/spec/support/a_consumer-a_producer.json +2 -4
- data/spec/support/a_consumer-a_provider.json +32 -0
- data/spec/support/active_support_if_configured.rb +6 -0
- data/spec/support/app_for_config_ru.rb +4 -0
- data/spec/support/consumer_contract_template.json +24 -0
- data/spec/support/dsl_spec_support.rb +7 -0
- data/spec/support/factories.rb +82 -0
- data/spec/support/generated_index.md +4 -0
- data/spec/support/generated_markdown.md +55 -0
- data/spec/support/interaction_view_model.json +63 -0
- data/spec/support/interaction_view_model_with_terms.json +50 -0
- data/spec/support/markdown_pact.json +48 -0
- data/spec/support/missing_provider_states_output.txt +25 -0
- data/spec/support/options.json +21 -0
- data/spec/support/options_app.rb +15 -0
- data/spec/support/pact_helper.rb +57 -0
- data/spec/support/shared_examples_for_request.rb +94 -0
- data/spec/support/spec_support.rb +20 -0
- data/spec/support/stubbing.json +22 -0
- data/spec/support/stubbing_using_allow.rb +29 -0
- data/spec/support/term.json +48 -0
- data/spec/support/test_app_fail.json +41 -2
- data/spec/support/test_app_pass.json +19 -2
- data/spec/support/test_app_with_right_content_type_differ.json +23 -0
- data/tasks/pact-test.rake +98 -8
- data/tasks/spec.rake +8 -0
- metadata +393 -95
- data/lib/pact/app.rb +0 -32
- data/lib/pact/consumer/configuration_dsl.rb +0 -71
- data/lib/pact/consumer/dsl.rb +0 -98
- data/lib/pact/consumer/interaction.rb +0 -70
- data/lib/pact/consumer/run_condor.rb +0 -4
- data/lib/pact/consumer/run_mock_contract_service.rb +0 -13
- data/lib/pact/consumer/service_consumer.rb +0 -22
- data/lib/pact/consumer/service_producer.rb +0 -23
- data/lib/pact/json_warning.rb +0 -23
- data/lib/pact/producer/configuration_dsl.rb +0 -62
- data/lib/pact/producer/matchers.rb +0 -22
- data/lib/pact/producer/pact_spec_runner.rb +0 -57
- data/lib/pact/producer/producer_state.rb +0 -81
- data/lib/pact/producer/rspec.rb +0 -127
- data/lib/pact/producer/test_methods.rb +0 -89
- data/lib/pact/producer.rb +0 -1
- data/lib/pact/rake_task.rb +0 -64
- data/lib/pact/request.rb +0 -109
- data/lib/pact/verification_task.rb +0 -57
- data/spec/integration/pact/configuration_spec.rb +0 -65
- data/spec/lib/pact/consumer/dsl_spec.rb +0 -52
- data/spec/lib/pact/consumer/interaction_spec.rb +0 -108
- data/spec/lib/pact/consumer/mock_service_spec.rb +0 -147
- data/spec/lib/pact/consumer_contract_spec.rb +0 -125
- data/spec/lib/pact/producer/configuration_dsl_spec.rb +0 -101
- data/spec/lib/pact/producer/producer_state_spec.rb +0 -103
- data/spec/lib/pact/producer/rspec_spec.rb +0 -48
- data/spec/lib/pact/verification_task_spec.rb +0 -64
- data/spec/support/pact_rake_support.rb +0 -41
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
module ActiveSupportSupport
|
|
3
|
+
|
|
4
|
+
extend self
|
|
5
|
+
|
|
6
|
+
def fix_all_the_things thing
|
|
7
|
+
if thing.is_a?(Regexp)
|
|
8
|
+
fix_regexp(thing)
|
|
9
|
+
elsif thing.is_a?(Array)
|
|
10
|
+
thing.each{ | it | fix_all_the_things it }
|
|
11
|
+
elsif thing.is_a?(Hash)
|
|
12
|
+
thing.values.each{ | it | fix_all_the_things it }
|
|
13
|
+
elsif thing.class.name.start_with?("Pact")
|
|
14
|
+
thing.instance_variables.collect{ | iv_name | thing.instance_variable_get(iv_name)}.each do | iv |
|
|
15
|
+
fix_all_the_things iv
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
thing
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# ActiveSupport JSON overwrites (i.e. TRAMPLES) the json methods of the Regexp class directly
|
|
22
|
+
# (beneath its destructive hooves of destruction).
|
|
23
|
+
# This does not seem to be able to be undone without affecting the JSON serialisation in the
|
|
24
|
+
# calling project, so the best way I've found to fix this issue is to reattach the
|
|
25
|
+
# original as_json to the Regexp instances in the ConsumerContract before we write them to the
|
|
26
|
+
# pact file. If anyone can find a better way, please submit a pull request ASAP!
|
|
27
|
+
def fix_regexp regexp
|
|
28
|
+
def regexp.as_json options = {}
|
|
29
|
+
{:json_class => 'Regexp', "o" => self.options, "s" => self.source }
|
|
30
|
+
end
|
|
31
|
+
regexp
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Having Active Support JSON loaded somehow kills the formatting of pretty_generate for objects.
|
|
35
|
+
# Don't ask me why, but it still seems to work for hashes, so the hacky work around is to
|
|
36
|
+
# reparse the generated JSON into a hash and pretty_generate that... sigh...
|
|
37
|
+
# Oh ActiveSupport, why....
|
|
38
|
+
def fix_json_formatting json
|
|
39
|
+
if json.include?("\n")
|
|
40
|
+
json
|
|
41
|
+
else
|
|
42
|
+
JSON.pretty_generate(JSON.parse(json, create_additions: false))
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def remove_unicode json
|
|
47
|
+
json.gsub(/\\u([0-9A-Za-z]{4})/) {|s| [$1.to_i(16)].pack("U")}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
|
|
3
|
+
class DslDelegator
|
|
4
|
+
|
|
5
|
+
def initialize delegation_target
|
|
6
|
+
@delegation_target = delegation_target
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def instance_eval_with_previous_context_available(*args, &block)
|
|
10
|
+
with_previous_context_available(block.binding) do
|
|
11
|
+
bind_block_as_instance_method_on_self(&block).call(*args)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
protected
|
|
16
|
+
|
|
17
|
+
def method_missing(method, *args, &block)
|
|
18
|
+
if delegation_target_responds_to? method
|
|
19
|
+
delegation_target.send(method, *args, &block)
|
|
20
|
+
else
|
|
21
|
+
previous_context.send(method, *args, &block)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
attr_accessor :delegation_target, :previous_context
|
|
28
|
+
|
|
29
|
+
def bind_block_as_instance_method_on_self(&block)
|
|
30
|
+
create_instance_method_from_block(&block).bind(self)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def create_instance_method_from_block &block
|
|
35
|
+
meth = self.class.class_eval do
|
|
36
|
+
define_method :block_as_instance_method_, &block
|
|
37
|
+
meth = instance_method :block_as_instance_method_
|
|
38
|
+
remove_method :block_as_instance_method_
|
|
39
|
+
meth
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def with_previous_context_available(binding, &block)
|
|
44
|
+
@previous_context = binding.eval('self')
|
|
45
|
+
result = block.call
|
|
46
|
+
@previous_context = nil
|
|
47
|
+
result
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def delegation_target_responds_to?(method)
|
|
51
|
+
delegation_target.respond_to? method
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Ripped from http://blog.joecorcoran.co.uk/2013/09/04/simple-pattern-ruby-dsl
|
|
58
|
+
# and then fixed up by using http://www.skorks.com/2013/03/a-closure-is-not-always-a-closure-in-ruby/
|
|
59
|
+
# to access variables and methods defined in the calling scope.
|
|
60
|
+
module DSL
|
|
61
|
+
def build(*args, &block)
|
|
62
|
+
new_instance_of_delegation_target_class = self.new(*args)
|
|
63
|
+
dsl_delegator_class = self.const_get('DSL_DELEGATOR_CLASS')
|
|
64
|
+
dsl_delegator = dsl_delegator_class.new(new_instance_of_delegation_target_class)
|
|
65
|
+
dsl_delegator.instance_eval_with_previous_context_available(&block)
|
|
66
|
+
new_instance_of_delegation_target_class.finalize
|
|
67
|
+
new_instance_of_delegation_target_class
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def dsl(&block)
|
|
71
|
+
dsl_delegator_class = Class.new(DslDelegator, &block)
|
|
72
|
+
self.const_set('DSL_DELEGATOR_CLASS', dsl_delegator_class)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
module JRubySupport
|
|
3
|
+
|
|
4
|
+
# Under jruby, JSON.pretty_generate inserts a blank new line between the opening and closing
|
|
5
|
+
# brackets of an empty hash, like so:
|
|
6
|
+
# {
|
|
7
|
+
# "empty": {
|
|
8
|
+
#
|
|
9
|
+
# }
|
|
10
|
+
# }
|
|
11
|
+
# This screws up the UnixDiffFormatter, so we need to remove the blank lines.
|
|
12
|
+
|
|
13
|
+
def fix_blank_lines_in_empty_hashes json
|
|
14
|
+
json.gsub(/({\n)\n(\s*})/,'\1\2')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
class NullExpectation
|
|
3
|
+
def to_s
|
|
4
|
+
"<No expectation>"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def ==(other_object)
|
|
8
|
+
other_object.is_a? NullExpectation
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ===(other_object)
|
|
12
|
+
other_object.is_a? NullExpectation
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def eql?(other_object)
|
|
16
|
+
self == other_object
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def hash
|
|
20
|
+
2934820948209428748274238642672
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def empty?
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def nil?
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'pact/matchers'
|
|
2
|
+
require 'pact/symbolize_keys'
|
|
3
|
+
require 'pact/consumer_contract/headers'
|
|
4
|
+
|
|
5
|
+
module Pact
|
|
6
|
+
|
|
7
|
+
module Request
|
|
8
|
+
|
|
9
|
+
class Base
|
|
10
|
+
include Pact::Matchers
|
|
11
|
+
include Pact::SymbolizeKeys
|
|
12
|
+
extend Pact::Matchers
|
|
13
|
+
|
|
14
|
+
attr_reader :method, :path, :headers, :body, :query, :options
|
|
15
|
+
|
|
16
|
+
def initialize(method, path, headers, body, query)
|
|
17
|
+
@method = method.to_s
|
|
18
|
+
@path = path.chomp('/')
|
|
19
|
+
@headers = Hash === headers ? Headers.new(headers) : headers # Could be a NullExpectation - TODO make this more elegant
|
|
20
|
+
@body = body
|
|
21
|
+
@query = query
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_json(options = {})
|
|
25
|
+
as_json.to_json(options)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def as_json options = {}
|
|
29
|
+
to_hash
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_hash
|
|
33
|
+
hash = {
|
|
34
|
+
method: method,
|
|
35
|
+
path: path,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
hash.merge!(query: query) unless query.is_a? self.class.key_not_found.class
|
|
39
|
+
hash.merge!(headers: headers) unless headers.is_a? self.class.key_not_found.class
|
|
40
|
+
hash.merge!(body: body) unless body.is_a? self.class.key_not_found.class
|
|
41
|
+
hash
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def method_and_path
|
|
45
|
+
"#{method.upcase} #{full_path}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def full_path
|
|
49
|
+
display_path + display_query
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def content_type
|
|
53
|
+
return nil if headers.is_a? self.class.key_not_found.class
|
|
54
|
+
headers['Content-Type']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
def self.key_not_found
|
|
60
|
+
raise NotImplementedError
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_hash_without_body
|
|
64
|
+
keep_keys = [:method, :path, :headers, :query]
|
|
65
|
+
as_json.reject{ |key, value| !keep_keys.include? key }.tap do | hash |
|
|
66
|
+
hash[:method] = method.upcase
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def display_path
|
|
71
|
+
path.empty? ? "/" : path
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def display_query
|
|
75
|
+
(query.nil? || query.empty?) ? '' : "?#{Pact::Reification.from_term(query)}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'pact/symbolize_keys'
|
|
2
|
+
module Pact
|
|
3
|
+
|
|
4
|
+
# Specifies that the actual object should be considered a match if
|
|
5
|
+
# it includes the same keys, and the values of the keys are of the same class.
|
|
6
|
+
|
|
7
|
+
class SomethingLike
|
|
8
|
+
include SymbolizeKeys
|
|
9
|
+
|
|
10
|
+
attr_reader :contents
|
|
11
|
+
|
|
12
|
+
def initialize contents
|
|
13
|
+
@contents = contents
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_hash
|
|
17
|
+
{
|
|
18
|
+
:json_class => self.class.name,
|
|
19
|
+
:contents => contents
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def as_json
|
|
24
|
+
to_hash
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_json opts = {}
|
|
28
|
+
as_json.to_json opts
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.json_create hash
|
|
32
|
+
new(symbolize_keys(hash)[:contents])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def eq other
|
|
36
|
+
self == other
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def == other
|
|
40
|
+
other.is_a?(SomethingLike) && other.contents == self.contents
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def generate
|
|
44
|
+
contents
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'pact/provider/pact_helper_locator'
|
|
2
|
+
require 'rake/file_utils'
|
|
3
|
+
require 'shellwords'
|
|
4
|
+
|
|
5
|
+
module Pact
|
|
6
|
+
module TaskHelper
|
|
7
|
+
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
def execute_pact_verify pact_uri = nil, pact_helper = nil, rspec_opts = nil
|
|
11
|
+
execute_cmd verify_command(pact_helper || Pact::Provider::PactHelperLocater.pact_helper_path, pact_uri, rspec_opts)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def handle_verification_failure
|
|
15
|
+
exit_status = yield
|
|
16
|
+
abort if exit_status != 0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def verify_command pact_helper, pact_uri, rspec_opts
|
|
20
|
+
command_parts = []
|
|
21
|
+
# Clear SPEC_OPTS, otherwise we can get extra formatters, creating duplicate output eg. CI Reporting.
|
|
22
|
+
# Allow deliberate configuration using rspec_opts in VerificationTask.
|
|
23
|
+
command_parts << "SPEC_OPTS=#{Shellwords.escape(rspec_opts || '')}"
|
|
24
|
+
command_parts << FileUtils::RUBY
|
|
25
|
+
command_parts << "-S pact verify"
|
|
26
|
+
command_parts << "-h" << (pact_helper.end_with?(".rb") ? pact_helper : pact_helper + ".rb")
|
|
27
|
+
(command_parts << "-p" << pact_uri) if pact_uri
|
|
28
|
+
command_parts.flatten.join(" ")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def execute_cmd command
|
|
32
|
+
system(command) ? 0 : 1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'rake/tasklib'
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
To create a rake pact:verify:<something> task
|
|
5
|
+
|
|
6
|
+
Pact::VerificationTask.new(:head) do | pact |
|
|
7
|
+
pact.uri 'http://master.cd.vpc.realestate.com.au/browse/BIQ-MAS/latestSuccessful/artifact/JOB2/Pacts/mas-contract_transaction_service.json'
|
|
8
|
+
pact.uri 'http://master.cd.vpc.realestate.com.au/browse/BIQ-IMAGINARY-CONSUMER/latestSuccessful/artifact/JOB2/Pacts/imaginary_consumer-contract_transaction_service.json'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
The pact.uri may be a local file system path or a remote URL.
|
|
12
|
+
|
|
13
|
+
To run a pact:verify:xxx task you need to define a pact_helper.rb, ideally in spec/service_consumers.
|
|
14
|
+
It should contain your service_provider definition, and load any provider state definition files.
|
|
15
|
+
It should also load all your app's dependencies (eg by calling out to spec_helper)
|
|
16
|
+
|
|
17
|
+
Eg.
|
|
18
|
+
|
|
19
|
+
require 'spec_helper'
|
|
20
|
+
require 'provider_states_for_my_consumer'
|
|
21
|
+
|
|
22
|
+
Pact.service_provider "My Provider" do
|
|
23
|
+
app { TestApp.new }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
=end
|
|
27
|
+
|
|
28
|
+
module Pact
|
|
29
|
+
class VerificationTask < ::Rake::TaskLib
|
|
30
|
+
|
|
31
|
+
attr_reader :pact_spec_configs
|
|
32
|
+
attr_accessor :rspec_opts
|
|
33
|
+
|
|
34
|
+
def initialize(name)
|
|
35
|
+
@rspec_opts = nil
|
|
36
|
+
@pact_spec_configs = []
|
|
37
|
+
@name = name
|
|
38
|
+
yield self
|
|
39
|
+
rake_task
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def uri(uri, options = {})
|
|
43
|
+
@pact_spec_configs << {uri: uri, pact_helper: options[:pact_helper]}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
attr_reader :name
|
|
49
|
+
|
|
50
|
+
# def parse_pactfile config
|
|
51
|
+
# Pact::ConsumerContract.from_uri config[:uri]
|
|
52
|
+
# end
|
|
53
|
+
|
|
54
|
+
# def publish_report config, output, result, provider_ref, reports_dir
|
|
55
|
+
# consumer_contract = parse_pactfile config
|
|
56
|
+
# #TODO - when checking out a historical version, provider ref will be prod, however it will think it is head. Fix this!!!!
|
|
57
|
+
# report = Provider::VerificationReport.new(
|
|
58
|
+
# :result => result,
|
|
59
|
+
# :output => output,
|
|
60
|
+
# :consumer => {:name => consumer_contract.consumer.name, :ref => name},
|
|
61
|
+
# :provider => {:name => consumer_contract.provider.name, :ref => provider_ref}
|
|
62
|
+
# )
|
|
63
|
+
|
|
64
|
+
# FileUtils.mkdir_p reports_dir
|
|
65
|
+
# File.open("#{reports_dir}/#{report.report_file_name}", "w") { |file| file << JSON.pretty_generate(report) }
|
|
66
|
+
# end
|
|
67
|
+
|
|
68
|
+
def rake_task
|
|
69
|
+
namespace :pact do
|
|
70
|
+
|
|
71
|
+
desc "Verify provider against the consumer pacts for #{name}"
|
|
72
|
+
task "verify:#{name}" do |t, args|
|
|
73
|
+
|
|
74
|
+
require 'pact/tasks/task_helper'
|
|
75
|
+
|
|
76
|
+
exit_statuses = pact_spec_configs.collect do | config |
|
|
77
|
+
Pact::TaskHelper.execute_pact_verify config[:uri], config[:pact_helper], rspec_opts
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
Pact::TaskHelper.handle_verification_failure do
|
|
81
|
+
exit_statuses.count{ | status | status != 0 }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
data/lib/pact/tasks.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Could not find one or more provider states.
|
|
2
|
+
Have you required the provider states file for this consumer in your pact_helper.rb?
|
|
3
|
+
If you have not yet defined these states, here is a template:
|
|
4
|
+
<% consumers.keys.each do | consumer_name | %>
|
|
5
|
+
Pact.provider_states_for "<%= consumer_name %>" do
|
|
6
|
+
<% consumers[consumer_name].each do | provider_state | %>
|
|
7
|
+
provider_state "<%= provider_state %>" do
|
|
8
|
+
set_up do
|
|
9
|
+
# Your set up code goes here
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
<% end %>
|
|
13
|
+
end
|
|
14
|
+
<% end %>
|
data/lib/pact/term.rb
CHANGED
|
@@ -1,19 +1,46 @@
|
|
|
1
|
+
require 'pact/shared/active_support_support'
|
|
2
|
+
require 'json/add/regexp'
|
|
3
|
+
|
|
1
4
|
module Pact
|
|
2
5
|
class Term
|
|
3
6
|
|
|
7
|
+
include Pact::ActiveSupportSupport
|
|
8
|
+
|
|
4
9
|
attr_reader :generate, :matcher
|
|
5
10
|
|
|
6
11
|
def self.json_create(obj)
|
|
7
12
|
new(generate: obj['data']['generate'], matcher: obj['data']['matcher'])
|
|
8
13
|
end
|
|
9
14
|
|
|
15
|
+
def self.unpack_regexps source
|
|
16
|
+
case source
|
|
17
|
+
when Pact::Term then source.matcher
|
|
18
|
+
when Array then unpack_regexps_from_array source
|
|
19
|
+
when Hash then unpack_regexps_from_hash source
|
|
20
|
+
else
|
|
21
|
+
source
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
10
25
|
def initialize(attributes = {})
|
|
11
26
|
@generate = attributes[:generate]
|
|
12
27
|
@matcher = attributes[:matcher]
|
|
28
|
+
raise "Please specify a matcher for the Term" unless @matcher != nil
|
|
29
|
+
raise "Please specify a value to generate for the Term" unless @generate != nil
|
|
30
|
+
raise "Value to generate \"#{@generate}\" does not match regular expression #{@matcher}" unless @generate =~ @matcher
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_hash
|
|
34
|
+
{ json_class: self.class.name, data: { generate: generate, matcher: fix_regexp(matcher)} }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def as_json(options = {})
|
|
38
|
+
to_hash
|
|
13
39
|
end
|
|
14
40
|
|
|
41
|
+
|
|
15
42
|
def to_json(options = {})
|
|
16
|
-
|
|
43
|
+
as_json.to_json(options)
|
|
17
44
|
end
|
|
18
45
|
|
|
19
46
|
def match(literal)
|
|
@@ -26,7 +53,7 @@ module Pact
|
|
|
26
53
|
end
|
|
27
54
|
|
|
28
55
|
def to_s
|
|
29
|
-
"Pact::Term matcher: #{matcher.
|
|
56
|
+
"Pact::Term matcher: #{matcher.inspect}" + (generate.nil? ? "" : " generate: \"#{generate}\"")
|
|
30
57
|
end
|
|
31
58
|
|
|
32
59
|
def diff_with_actual(actual)
|
|
@@ -36,5 +63,23 @@ module Pact
|
|
|
36
63
|
}
|
|
37
64
|
end
|
|
38
65
|
|
|
66
|
+
def empty?
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def self.unpack_regexps_from_array source
|
|
73
|
+
source.each_with_object([]) do | item, destination |
|
|
74
|
+
destination << unpack_regexps(item)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.unpack_regexps_from_hash source
|
|
79
|
+
source.keys.each_with_object({}) do | key, destination |
|
|
80
|
+
destination[key] = unpack_regexps source[key]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
39
84
|
end
|
|
40
85
|
end
|
data/lib/pact/version.rb
CHANGED
data/lib/pact.rb
CHANGED
data/lib/tasks/pact.rake
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
|
+
|
|
1
2
|
namespace :pact do
|
|
2
|
-
|
|
3
|
+
|
|
4
|
+
desc "Verifies the pact files configured in the pact_helper.rb against this service provider."
|
|
3
5
|
task :verify do
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
require 'pact/tasks/task_helper'
|
|
8
|
+
|
|
9
|
+
include Pact::TaskHelper
|
|
10
|
+
|
|
11
|
+
handle_verification_failure do
|
|
12
|
+
execute_pact_verify
|
|
13
|
+
end
|
|
5
14
|
end
|
|
15
|
+
|
|
16
|
+
desc "Verifies the pact at the given URI against this service provider."
|
|
17
|
+
task 'verify:at', :pact_uri do | t, args |
|
|
18
|
+
require 'term/ansicolor'
|
|
19
|
+
require 'pact/tasks/task_helper'
|
|
20
|
+
|
|
21
|
+
include Pact::TaskHelper
|
|
22
|
+
|
|
23
|
+
abort(::Term::ANSIColor.red("Please provide a pact URI. eg. rake pact:verify:at[../my-consumer/spec/pacts/my_consumer-my_provider.json]")) unless args[:pact_uri]
|
|
24
|
+
handle_verification_failure do
|
|
25
|
+
execute_pact_verify args[:pact_uri]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
6
29
|
end
|
data/pact.gemspec
CHANGED
|
@@ -6,11 +6,11 @@ require 'pact/version'
|
|
|
6
6
|
Gem::Specification.new do |gem|
|
|
7
7
|
gem.name = "pact"
|
|
8
8
|
gem.version = Pact::VERSION
|
|
9
|
-
gem.authors = ["James Fraser", "Sergei Matheson", "Brent Snook", "Ronald Holshausen", "
|
|
9
|
+
gem.authors = ["James Fraser", "Sergei Matheson", "Brent Snook", "Ronald Holshausen", "Beth Skurrie"]
|
|
10
10
|
gem.email = ["james.fraser@alumni.swinburne.edu", "sergei.matheson@gmail.com", "brent@fuglylogic.com", "uglyog@gmail.com", "bskurrie@dius.com.au"]
|
|
11
|
-
gem.description = %q{
|
|
12
|
-
gem.summary = %q{
|
|
13
|
-
gem.homepage = "https://github.com/
|
|
11
|
+
gem.description = %q{Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.}
|
|
12
|
+
gem.summary = %q{Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.}
|
|
13
|
+
gem.homepage = "https://github.com/realestate-com-au/pact"
|
|
14
14
|
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
@@ -19,18 +19,20 @@ Gem::Specification.new do |gem|
|
|
|
19
19
|
gem.license = 'MIT'
|
|
20
20
|
|
|
21
21
|
gem.add_runtime_dependency 'randexp', '~> 0.1.7'
|
|
22
|
-
gem.add_runtime_dependency '
|
|
23
|
-
gem.add_runtime_dependency 'rspec', '~> 2.12'
|
|
22
|
+
gem.add_runtime_dependency 'rspec', '>=2.14'
|
|
24
23
|
gem.add_runtime_dependency 'find_a_port', '~> 1.0.1'
|
|
25
24
|
gem.add_runtime_dependency 'rack-test', '~> 0.6.2'
|
|
26
|
-
gem.add_runtime_dependency 'awesome_print', '~> 1.1
|
|
27
|
-
gem.add_runtime_dependency 'capybara', '~> 2.1.0'
|
|
25
|
+
gem.add_runtime_dependency 'awesome_print', '~> 1.1'
|
|
28
26
|
gem.add_runtime_dependency 'thor'
|
|
29
|
-
gem.add_runtime_dependency 'thin'
|
|
30
27
|
gem.add_runtime_dependency 'json' #Not locking down a version because buncher gem requires 1.6, while other projects use 1.7.
|
|
28
|
+
gem.add_runtime_dependency 'webrick'
|
|
29
|
+
gem.add_runtime_dependency 'term-ansicolor', '~> 1.0'
|
|
31
30
|
|
|
32
|
-
gem.add_development_dependency 'geminabox-client'
|
|
33
31
|
gem.add_development_dependency 'rake', '~> 10.0.3'
|
|
34
|
-
gem.add_development_dependency 'webmock', '~> 1.
|
|
32
|
+
gem.add_development_dependency 'webmock', '~> 1.18.0'
|
|
35
33
|
gem.add_development_dependency 'pry'
|
|
34
|
+
gem.add_development_dependency 'fakefs', '~> 0.4'
|
|
35
|
+
gem.add_development_dependency 'hashie', '~> 2.0'
|
|
36
|
+
gem.add_development_dependency 'activesupport'
|
|
37
|
+
gem.add_development_dependency 'faraday'
|
|
36
38
|
end
|