pact-support 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +80 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +4 -0
  10. data/Rakefile +4 -0
  11. data/lib/pact/configuration.rb +164 -0
  12. data/lib/pact/consumer/request.rb +27 -0
  13. data/lib/pact/consumer_contract.rb +1 -0
  14. data/lib/pact/consumer_contract/consumer_contract.rb +114 -0
  15. data/lib/pact/consumer_contract/file_name.rb +19 -0
  16. data/lib/pact/consumer_contract/headers.rb +51 -0
  17. data/lib/pact/consumer_contract/interaction.rb +73 -0
  18. data/lib/pact/consumer_contract/pact_file.rb +24 -0
  19. data/lib/pact/consumer_contract/request.rb +73 -0
  20. data/lib/pact/consumer_contract/response.rb +51 -0
  21. data/lib/pact/consumer_contract/service_consumer.rb +28 -0
  22. data/lib/pact/consumer_contract/service_provider.rb +28 -0
  23. data/lib/pact/logging.rb +14 -0
  24. data/lib/pact/matchers.rb +1 -0
  25. data/lib/pact/matchers/actual_type.rb +16 -0
  26. data/lib/pact/matchers/base_difference.rb +37 -0
  27. data/lib/pact/matchers/differ.rb +153 -0
  28. data/lib/pact/matchers/difference.rb +13 -0
  29. data/lib/pact/matchers/difference_indicator.rb +26 -0
  30. data/lib/pact/matchers/embedded_diff_formatter.rb +62 -0
  31. data/lib/pact/matchers/expected_type.rb +35 -0
  32. data/lib/pact/matchers/index_not_found.rb +15 -0
  33. data/lib/pact/matchers/list_diff_formatter.rb +101 -0
  34. data/lib/pact/matchers/matchers.rb +139 -0
  35. data/lib/pact/matchers/no_diff_indicator.rb +18 -0
  36. data/lib/pact/matchers/regexp_difference.rb +13 -0
  37. data/lib/pact/matchers/type_difference.rb +16 -0
  38. data/lib/pact/matchers/unexpected_index.rb +11 -0
  39. data/lib/pact/matchers/unexpected_key.rb +11 -0
  40. data/lib/pact/matchers/unix_diff_formatter.rb +114 -0
  41. data/lib/pact/reification.rb +28 -0
  42. data/lib/pact/rspec.rb +53 -0
  43. data/lib/pact/shared/active_support_support.rb +51 -0
  44. data/lib/pact/shared/dsl.rb +76 -0
  45. data/lib/pact/shared/jruby_support.rb +18 -0
  46. data/lib/pact/shared/json_differ.rb +15 -0
  47. data/lib/pact/shared/key_not_found.rb +15 -0
  48. data/lib/pact/shared/null_expectation.rb +31 -0
  49. data/lib/pact/shared/request.rb +97 -0
  50. data/lib/pact/shared/text_differ.rb +14 -0
  51. data/lib/pact/something_like.rb +49 -0
  52. data/lib/pact/support.rb +9 -0
  53. data/lib/pact/support/version.rb +5 -0
  54. data/lib/pact/symbolize_keys.rb +12 -0
  55. data/lib/pact/term.rb +85 -0
  56. data/lib/tasks/pact.rake +29 -0
  57. data/pact-support.gemspec +35 -0
  58. data/spec/lib/pact/consumer/request_spec.rb +25 -0
  59. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +58 -0
  60. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +141 -0
  61. data/spec/lib/pact/consumer_contract/headers_spec.rb +107 -0
  62. data/spec/lib/pact/consumer_contract/interaction_spec.rb +151 -0
  63. data/spec/lib/pact/consumer_contract/request_spec.rb +329 -0
  64. data/spec/lib/pact/consumer_contract/response_spec.rb +73 -0
  65. data/spec/lib/pact/matchers/differ_spec.rb +215 -0
  66. data/spec/lib/pact/matchers/difference_spec.rb +22 -0
  67. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +90 -0
  68. data/spec/lib/pact/matchers/index_not_found_spec.rb +21 -0
  69. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +120 -0
  70. data/spec/lib/pact/matchers/matchers_spec.rb +500 -0
  71. data/spec/lib/pact/matchers/regexp_difference_spec.rb +20 -0
  72. data/spec/lib/pact/matchers/type_difference_spec.rb +34 -0
  73. data/spec/lib/pact/matchers/unexpected_index_spec.rb +20 -0
  74. data/spec/lib/pact/matchers/unexpected_key_spec.rb +20 -0
  75. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +216 -0
  76. data/spec/lib/pact/reification_spec.rb +67 -0
  77. data/spec/lib/pact/shared/dsl_spec.rb +86 -0
  78. data/spec/lib/pact/shared/json_differ_spec.rb +36 -0
  79. data/spec/lib/pact/shared/key_not_found_spec.rb +20 -0
  80. data/spec/lib/pact/shared/request_spec.rb +196 -0
  81. data/spec/lib/pact/shared/text_differ_spec.rb +54 -0
  82. data/spec/lib/pact/something_like_spec.rb +21 -0
  83. data/spec/lib/pact/term_spec.rb +89 -0
  84. data/spec/spec_helper.rb +19 -0
  85. data/spec/support/a_consumer-a_producer.json +32 -0
  86. data/spec/support/a_consumer-a_provider.json +32 -0
  87. data/spec/support/active_support_if_configured.rb +6 -0
  88. data/spec/support/case-insensitive-response-header-matching.json +21 -0
  89. data/spec/support/consumer_contract_template.json +24 -0
  90. data/spec/support/dsl_spec_support.rb +7 -0
  91. data/spec/support/factories.rb +82 -0
  92. data/spec/support/generated_index.md +4 -0
  93. data/spec/support/generated_markdown.md +55 -0
  94. data/spec/support/interaction_view_model.json +63 -0
  95. data/spec/support/interaction_view_model_with_terms.json +50 -0
  96. data/spec/support/markdown_pact.json +48 -0
  97. data/spec/support/missing_provider_states_output.txt +25 -0
  98. data/spec/support/options.json +21 -0
  99. data/spec/support/shared_examples_for_request.rb +94 -0
  100. data/spec/support/spec_support.rb +20 -0
  101. data/spec/support/stubbing.json +22 -0
  102. data/spec/support/term.json +48 -0
  103. data/spec/support/test_app_fail.json +61 -0
  104. data/spec/support/test_app_pass.json +38 -0
  105. data/spec/support/test_app_with_right_content_type_differ.json +23 -0
  106. data/tasks/spec.rake +6 -0
  107. metadata +401 -0
@@ -0,0 +1,32 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ },
17
+ "provider_state": "state one"
18
+ },
19
+ {
20
+ "description": "request two",
21
+ "request": {
22
+ "method": "get",
23
+ "path": "/path_two"
24
+ },
25
+ "response": {
26
+ }
27
+ }
28
+ ],
29
+ "metadata": {
30
+ "pactSpecificationVersion": "1.0"
31
+ }
32
+ }
@@ -0,0 +1,6 @@
1
+ if ENV['LOAD_ACTIVE_SUPPORT']
2
+ puts 'LOADING ACTIVE SUPPORT!!!! Hopefully it all still works'
3
+ require 'active_support/all'
4
+ require 'active_support'
5
+ require 'active_support/json'
6
+ end
@@ -0,0 +1,21 @@
1
+ {
2
+ "consumer": {
3
+ "name": "an easy consumer"
4
+ },
5
+ "provider": {
6
+ "name": "a provider which returns headers that don't match the expected case"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "a test request",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/"
14
+ },
15
+ "response": {
16
+ "status": 200,
17
+ "headers": {"Content-Type": "application/hippo"}
18
+ }
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ "status" : 200
17
+ },
18
+ "provider_state": "state one"
19
+ }
20
+ ],
21
+ "metadata": {
22
+ "pactSpecificationVersion": "1.0"
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ def global_method
2
+ "I'm global"
3
+ end
4
+
5
+ def global_app
6
+ "I'm a global app"
7
+ end
@@ -0,0 +1,82 @@
1
+ require 'hashie'
2
+ require 'hashie/extensions/key_conversion'
3
+
4
+ module Pact
5
+ module HashUtils
6
+
7
+ class Converter < Hash
8
+ include Hashie::Extensions::KeyConversion
9
+ include Hashie::Extensions::DeepMerge
10
+ end
11
+
12
+ def symbolize_keys hash
13
+ Hash[Converter[hash].symbolize_keys]
14
+ end
15
+
16
+ def stringify_keys hash
17
+ Hash[Converter[hash].stringify_keys]
18
+ end
19
+
20
+ def deep_merge hash1, hash2
21
+ Converter[hash1].deep_merge(Converter[hash2])
22
+ end
23
+ end
24
+ end
25
+
26
+ class InteractionFactory
27
+
28
+ extend Pact::HashUtils
29
+
30
+ def self.create hash = {}
31
+ defaults = {
32
+ 'description' => 'a description',
33
+ 'provider_state' => 'a thing exists',
34
+ 'request' => {
35
+ 'path' => '/path',
36
+ 'method' => 'get',
37
+ },
38
+ 'response' => {
39
+ 'status' => 200,
40
+ 'body' => {a: 'response body'}
41
+ }
42
+ }
43
+ Pact::Interaction.from_hash(stringify_keys(deep_merge(defaults, stringify_keys(hash))))
44
+ end
45
+ end
46
+
47
+
48
+ class ConsumerContractFactory
49
+ extend Pact::HashUtils
50
+ DEFAULTS = {:consumer_name => 'consumer',
51
+ :provider_name => 'provider',
52
+ :interactions => [InteractionFactory.create]}
53
+
54
+ def self.create overrides = {}
55
+ options = deep_merge(symbolize_keys(DEFAULTS), symbolize_keys(overrides))
56
+ Pact::ConsumerContract.new({:consumer => Pact::ServiceConsumer.new(name: options[:consumer_name]),
57
+ :provider => Pact::ServiceProvider.new(name: options[:provider_name]),
58
+ :interactions => options[:interactions]})
59
+ end
60
+ end
61
+
62
+
63
+
64
+ class ResponseFactory
65
+ extend Pact::HashUtils
66
+ DEFAULTS = {:status => 200, :body => {a: 'body'}}.freeze
67
+ def self.create_hash overrides = {}
68
+ deep_merge(DEFAULTS, overrides)
69
+ end
70
+ end
71
+
72
+ class RequestFactory
73
+ extend Pact::HashUtils
74
+ DEFAULTS = {:path => '/path', :method => 'get', :query => 'query', :headers => {}}.freeze
75
+ def self.create_hash overrides = {}
76
+ deep_merge(DEFAULTS, overrides)
77
+ end
78
+
79
+ def self.create_actual overrides = {}
80
+ Pact::Consumer::Request::Actual.from_hash(create_hash(overrides))
81
+ end
82
+ end
@@ -0,0 +1,4 @@
1
+ ### Pacts for Some Consumer
2
+
3
+ * [Some Provider](Some Provider.md)
4
+ * [Some other provider](Some other provider.md)
@@ -0,0 +1,55 @@
1
+ ### A pact between Some Consumer and Some Provider
2
+
3
+ #### Requests from Some Consumer to Some Provider
4
+
5
+ * [A request for alligators](#a_request_for_alligators_given_alligators_exist) given alligators exist
6
+
7
+ * [A request for polar bears](#a_request_for_polar_bears)
8
+
9
+ #### Interactions
10
+
11
+ <a name="a_request_for_alligators_given_alligators_exist"></a>
12
+ Given **alligators exist**, upon receiving **a request for alligators** from Some Consumer, with
13
+ ```json
14
+ {
15
+ "method": "get",
16
+ "path": "/alligators"
17
+ }
18
+ ```
19
+ Some Provider will respond with:
20
+ ```json
21
+ {
22
+ "status": 200,
23
+ "headers": {
24
+ "Content-Type": "application/json"
25
+ },
26
+ "body": {
27
+ "alligators": [
28
+ {
29
+ "name": "Bob",
30
+ "phoneNumber": "12345678"
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+ <a name="a_request_for_polar_bears"></a>
37
+ Upon receiving **a request for polar bears** from Some Consumer, with
38
+ ```json
39
+ {
40
+ "method": "get",
41
+ "path": "/polar-bears"
42
+ }
43
+ ```
44
+ Some Provider will respond with:
45
+ ```json
46
+ {
47
+ "status": 404,
48
+ "headers": {
49
+ "Content-Type": "application/json"
50
+ },
51
+ "body": {
52
+ "message": "Sorry, due to climate change, the polar bears are currently unavailable."
53
+ }
54
+ }
55
+ ```
@@ -0,0 +1,63 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "a request with a body and headers",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path",
14
+ "query": "some=thing",
15
+ "headers": {
16
+ "key": "a header"
17
+ },
18
+ "body": {
19
+ "key": "a body"
20
+ }
21
+ },
22
+ "response": {}
23
+ },
24
+ {
25
+ "description": "a request with an empty body and empty headers",
26
+ "request": {
27
+ "method": "get",
28
+ "path": "/",
29
+ "headers": {},
30
+ "body": {}
31
+ },
32
+ "response": {}
33
+ },
34
+ {
35
+ "description": "a response with a body and headers",
36
+ "request": {
37
+ "method": "get",
38
+ "path": "/"
39
+ },
40
+ "response": {
41
+ "headers": {
42
+ "key": "a header"
43
+ },
44
+ "body": {
45
+ "key": "a body"
46
+ },
47
+ "status": 200
48
+ }
49
+ },
50
+ {
51
+ "description": "a response with an empty body and empty headers",
52
+ "request": {
53
+ "method": "get",
54
+ "path": "/"
55
+ },
56
+ "response": {
57
+ "status": 200,
58
+ "headers": {},
59
+ "body": {}
60
+ }
61
+ }
62
+ ]
63
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "an interaction with terms",
11
+ "request": {
12
+ "method": "post",
13
+ "path": "/path",
14
+ "query": "some=thing",
15
+ "headers": {
16
+ "key": "a header"
17
+ },
18
+ "body": {
19
+ "term": {
20
+ "json_class": "Pact::Term",
21
+ "data": {
22
+ "generate": "sunny",
23
+ "matcher": {
24
+ "json_class": "Regexp",
25
+ "o": 0,
26
+ "s": "sun"
27
+ }
28
+ }
29
+ }
30
+ }
31
+ },
32
+ "response": {
33
+ "status": 200,
34
+ "body": {
35
+ "term": {
36
+ "json_class": "Pact::Term",
37
+ "data": {
38
+ "generate": "rainy",
39
+ "matcher": {
40
+ "json_class": "Regexp",
41
+ "o": 0,
42
+ "s": "rain"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "provider": {
3
+ "name": "Some Provider"
4
+ },
5
+ "consumer": {
6
+ "name": "Some Consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "a request for alligators",
11
+ "provider_state": "alligators exist",
12
+ "request": {
13
+ "method": "get",
14
+ "path": "/alligators"
15
+ },
16
+ "response": {
17
+ "headers" : {"Content-Type": "application/json"},
18
+ "status" : 200,
19
+ "body" : {
20
+ "alligators": [{
21
+ "name": "Bob",
22
+ "phoneNumber" : {
23
+ "json_class": "Pact::Term",
24
+ "data": {
25
+ "generate": "12345678",
26
+ "matcher": {"json_class":"Regexp","o":0,"s":"\\d+"}
27
+ }
28
+ }
29
+ }]
30
+ }
31
+ }
32
+ },{
33
+ "description": "a request for polar bears",
34
+ "provider_state": null,
35
+ "request": {
36
+ "method": "get",
37
+ "path": "/polar-bears"
38
+ },
39
+ "response": {
40
+ "headers" : {"Content-Type": "application/json"},
41
+ "status" : 404,
42
+ "body" : {
43
+ "message": "Sorry, due to climate change, the polar bears are currently unavailable."
44
+ }
45
+ }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,25 @@
1
+ Pact.provider_states_for "Consumer 1" do
2
+
3
+ provider_state "state1" do
4
+ set_up do
5
+ # Your set up code goes here
6
+ end
7
+ end
8
+
9
+ provider_state "state2" do
10
+ set_up do
11
+ # Your set up code goes here
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ Pact.provider_states_for "Consumer 2" do
18
+
19
+ provider_state "state3" do
20
+ set_up do
21
+ # Your set up code goes here
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,21 @@
1
+ {
2
+ "consumer": {
3
+ "name": "Consumer"
4
+ },
5
+ "provider": {
6
+ "name": "Provider"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "an OPTIONS request",
11
+ "request": {
12
+ "method": "options",
13
+ "path": "/"
14
+ },
15
+ "response": {
16
+ "status": 200
17
+ },
18
+ "provider_state": null
19
+ }
20
+ ]
21
+ }