pact 1.1.0.rc1 → 1.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/README.md +6 -2
- data/lib/pact/configuration.rb +4 -0
- data/lib/pact/consumer/consumer_contract_builder.rb +1 -1
- data/lib/pact/matchers/difference.rb +38 -0
- data/lib/pact/matchers/matchers.rb +1 -28
- data/lib/pact/matchers/nested_json_diff_decorator.rb +6 -1
- data/lib/pact/provider/pact_spec_runner.rb +28 -28
- data/lib/pact/provider/print_missing_provider_states.rb +2 -2
- data/lib/pact/provider/rspec/formatter.rb +63 -0
- data/lib/pact/provider/rspec/silent_json_formatter.rb +18 -0
- data/lib/pact/provider/rspec.rb +16 -7
- data/lib/pact/provider/world.rb +6 -0
- data/lib/pact/tasks/task_helper.rb +15 -18
- data/lib/pact/templates/provider_state.erb +0 -1
- data/lib/pact/version.rb +1 -1
- data/spec/lib/pact/matchers/difference_spec.rb +32 -0
- data/spec/lib/pact/tasks/task_helper_spec.rb +80 -0
- data/spec/lib/pact/verification_task_spec.rb +0 -10
- data/spec/support/pact_helper.rb +5 -2
- data/spec/support/stubbing.json +1 -1
- data/spec/support/term.json +36 -0
- data/spec/support/test_app_fail.json +29 -2
- data/spec/support/test_app_pass.json +4 -4
- data/tasks/pact-test.rake +12 -0
- metadata +11 -5
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@ Do this to generate your change history
|
|
2
2
|
|
3
3
|
git log --date=relative --pretty=format:' * %h - %s (%an, %ad)'
|
4
4
|
|
5
|
+
### 1.0.38 (24 March 2014)
|
6
|
+
|
7
|
+
* 7fb2bc3 - Improved readability of pact:verify specs by removing pactfile name and request details from output (bethesque, 23 hours ago)
|
8
|
+
* ff1de3c - Improving readability of error messages when pact:verify fails (bethesque, 23 hours ago)
|
9
|
+
* 8a08abf - Removed the last RSpec private API usage. I think. (bethesque, 33 hours ago)
|
10
|
+
* 6a0be58 - Reducing even more use of RSpec private APIs (bethesque, 33 hours ago)
|
11
|
+
* e1fd51c - Reducing use of RSpec private APIs (bethesque, 34 hours ago)
|
12
|
+
* 587cb90 - Replaced rspec 'commands to rerun failed examples' with Pact specific commands to rerun failed interactions (bethesque, 2 days ago)
|
13
|
+
|
5
14
|
### 1.0.37 (19 March 2014)
|
6
15
|
|
7
16
|
* 0e8b80e - Cleaned up pact:verify rspec matcher lines so the output makes more sense to the reader (bethesque, 3 minutes ago)
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -377,9 +377,13 @@ Configure the pact_uri in the Pact.service_provider block with the pact artifact
|
|
377
377
|
|
378
378
|
It should run with all your other tests. If an integration is broken, you want to know about it *before* you check in.
|
379
379
|
|
380
|
-
####
|
380
|
+
#### Stub calls to downstream systems
|
381
381
|
|
382
|
-
|
382
|
+
Consider making a separate pact with the downstream system and using shared fixtures.
|
383
|
+
|
384
|
+
#### Consider carefully whether to use the real database or stub calls
|
385
|
+
|
386
|
+
You may choose not stub your database calls for pact:verify. This can be a good time for you to test your database integration if you have a simple application, however, for a complex one, you might want to carefully choose a point at which to stub calls.
|
383
387
|
|
384
388
|
## Gotchas
|
385
389
|
|
data/lib/pact/configuration.rb
CHANGED
@@ -10,6 +10,8 @@ module Pact
|
|
10
10
|
attr_accessor :tmp_dir
|
11
11
|
attr_accessor :reports_dir
|
12
12
|
attr_writer :pactfile_write_mode
|
13
|
+
attr_accessor :error_stream
|
14
|
+
attr_accessor :output_stream
|
13
15
|
|
14
16
|
def log_path
|
15
17
|
log_dir + "/pact.log"
|
@@ -54,6 +56,8 @@ module Pact
|
|
54
56
|
c.logger = default_logger c.log_path
|
55
57
|
c.pactfile_write_mode = :overwrite
|
56
58
|
c.reports_dir = File.expand_path('./reports/pacts')
|
59
|
+
c.output_stream = $stdout
|
60
|
+
c.error_stream = $stderr
|
57
61
|
c
|
58
62
|
end
|
59
63
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Pact
|
2
|
+
module Matchers
|
3
|
+
class Difference
|
4
|
+
|
5
|
+
attr_reader :expected, :actual
|
6
|
+
|
7
|
+
def initialize expected, actual
|
8
|
+
@expected = expected
|
9
|
+
@actual = actual
|
10
|
+
end
|
11
|
+
|
12
|
+
def any?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
if Regexp === expected
|
18
|
+
{:EXPECTED_TO_MATCH => expected.inspect, :ACTUAL => actual}
|
19
|
+
else
|
20
|
+
{:EXPECTED => expected, :ACTUAL => actual}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json options = {}
|
25
|
+
to_hash.to_json(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
to_hash.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
def == other
|
33
|
+
other.is_a?(Difference) && other.expected == expected && other.actual == actual
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -6,38 +6,11 @@ require 'pact/shared/key_not_found'
|
|
6
6
|
require 'pact/matchers/unexpected_key'
|
7
7
|
require 'pact/matchers/unexpected_index'
|
8
8
|
require 'pact/matchers/index_not_found'
|
9
|
+
require 'pact/matchers/difference'
|
9
10
|
|
10
11
|
module Pact
|
11
12
|
module Matchers
|
12
13
|
|
13
|
-
class Difference
|
14
|
-
attr_reader :expected, :actual
|
15
|
-
def initialize expected, actual
|
16
|
-
@expected = expected
|
17
|
-
@actual = actual
|
18
|
-
end
|
19
|
-
|
20
|
-
def any?
|
21
|
-
true
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_hash
|
25
|
-
{:EXPECTED => expected, :ACTUAL => actual}
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_json options = {}
|
29
|
-
to_hash.to_json(options)
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
to_hash.to_s
|
34
|
-
end
|
35
|
-
|
36
|
-
def == other
|
37
|
-
other.is_a?(Difference) && other.expected == expected && other.actual == actual
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
14
|
class NoDiffIndicator
|
42
15
|
|
43
16
|
def to_json options = {}
|
@@ -9,6 +9,11 @@ module Pact
|
|
9
9
|
|
10
10
|
EXPECTED = '"EXPECTED"'
|
11
11
|
EXPECTED_COLOURED = '"' + "expected".red + '"'
|
12
|
+
|
13
|
+
EXPECTED_REGEXP = '"EXPECTED_TO_MATCH"'
|
14
|
+
EXPECTED_REGEXP_COLOURED = '"' + "expected_to_match".red + '"'
|
15
|
+
|
16
|
+
|
12
17
|
ACTUAL = '"ACTUAL"'
|
13
18
|
ACTUAL_COLOURED = '"' + "actual".green + '"'
|
14
19
|
|
@@ -39,7 +44,7 @@ module Pact
|
|
39
44
|
end
|
40
45
|
|
41
46
|
def colourise line
|
42
|
-
line.white.gsub(EXPECTED, EXPECTED_COLOURED).gsub(ACTUAL, ACTUAL_COLOURED)
|
47
|
+
line.white.gsub(EXPECTED, EXPECTED_COLOURED).gsub(ACTUAL, ACTUAL_COLOURED).gsub(EXPECTED_REGEXP, EXPECTED_REGEXP_COLOURED)
|
43
48
|
end
|
44
49
|
|
45
50
|
end
|
@@ -4,7 +4,8 @@ require 'rspec/core'
|
|
4
4
|
require 'rspec/core/formatters/documentation_formatter'
|
5
5
|
require 'rspec/core/formatters/json_formatter'
|
6
6
|
require 'pact/provider/pact_helper_locator'
|
7
|
-
require 'pact/provider/
|
7
|
+
require 'pact/provider/rspec/formatter'
|
8
|
+
require 'pact/provider/rspec/silent_json_formatter'
|
8
9
|
require_relative 'rspec'
|
9
10
|
|
10
11
|
|
@@ -36,6 +37,7 @@ module Pact
|
|
36
37
|
run_specs
|
37
38
|
ensure
|
38
39
|
::RSpec.reset
|
40
|
+
Pact.clear_world
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
@@ -43,11 +45,11 @@ module Pact
|
|
43
45
|
|
44
46
|
def require_pact_helper spec_definition
|
45
47
|
if spec_definition[:pact_helper]
|
46
|
-
puts "Using #{spec_definition[:pact_helper]}"
|
48
|
+
Pact.configuration.output_stream.puts "Using #{spec_definition[:pact_helper]}"
|
47
49
|
require spec_definition[:pact_helper]
|
48
50
|
elsif spec_definition[:support_file]
|
49
|
-
puts "Using #{spec_definition[:support_file]}"
|
50
|
-
|
51
|
+
Pact.configuration.output_stream.puts "Using #{spec_definition[:support_file]}"
|
52
|
+
Pact.configuration.error_stream.puts SUPPORT_FILE_DEPRECATION_MESSAGE
|
51
53
|
require spec_definition[:support_file]
|
52
54
|
else
|
53
55
|
require 'pact/provider/client_project_pact_helper'
|
@@ -70,42 +72,40 @@ module Pact
|
|
70
72
|
config = ::RSpec.configuration
|
71
73
|
|
72
74
|
config.color = true
|
75
|
+
config.pattern = "pattern which doesn't match any files"
|
76
|
+
config.backtrace_inclusion_patterns = [/pact\/provider\/rspec/]
|
77
|
+
config.backtrace_exclusion_patterns << /pact/
|
78
|
+
|
73
79
|
config.extend Pact::Provider::RSpec::ClassMethods
|
74
80
|
config.include Pact::Provider::RSpec::InstanceMethods
|
75
81
|
config.include Pact::Provider::TestMethods
|
76
|
-
config.backtrace_inclusion_patterns = [/pact\/provider\/rspec/]
|
77
82
|
|
78
|
-
|
79
|
-
|
80
|
-
|
83
|
+
if options[:silent]
|
84
|
+
config.output_stream = StringIO.new
|
85
|
+
config.error_stream = StringIO.new
|
86
|
+
else
|
87
|
+
config.error_stream = Pact.configuration.error_stream
|
88
|
+
config.output_stream = Pact.configuration.output_stream
|
81
89
|
end
|
82
90
|
|
83
|
-
|
84
|
-
|
85
|
-
config.output_stream = $stdout
|
86
|
-
end
|
91
|
+
config.add_formatter Pact::Provider::RSpec::Formatter
|
92
|
+
config.add_formatter Pact::Provider::RSpec::SilentJsonFormatter
|
87
93
|
|
88
|
-
formatter = ::RSpec::Core::Formatters::DocumentationFormatter.new(config.output)
|
89
|
-
@json_formatter = ::RSpec::Core::Formatters::JsonFormatter.new(StringIO.new)
|
90
|
-
reporter = ::RSpec::Core::Reporter.new(formatter, @json_formatter)
|
91
|
-
config.instance_variable_set(:@reporter, reporter)
|
92
94
|
end
|
93
95
|
|
94
96
|
def run_specs
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
begin
|
99
|
-
config.run_hook(:before, :suite)
|
100
|
-
world.example_groups.ordered.map {|g| g.run(reporter)}.all? ? 0 : config.failure_exit_code
|
101
|
-
ensure
|
102
|
-
config.run_hook(:after, :suite)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
PrintMissingProviderStates.call Pact.world.provider_states.missing_provider_states
|
106
|
-
@output = @json_formatter.output_hash
|
97
|
+
exit_code = ::RSpec::Core::CommandLine.new(NoConfigurationOptions.new)
|
98
|
+
.run(::RSpec.configuration.output_stream, ::RSpec.configuration.error_stream)
|
99
|
+
@output = JSON.parse(Pact.world.json_formatter_stream.string, symbolize_keys: true)
|
107
100
|
exit_code
|
108
101
|
end
|
102
|
+
|
103
|
+
class NoConfigurationOptions
|
104
|
+
def method_missing(method, *args, &block)
|
105
|
+
# Do nothing!
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
@@ -3,9 +3,9 @@ module Pact
|
|
3
3
|
class PrintMissingProviderStates
|
4
4
|
|
5
5
|
# Hash of consumer names to array of names of missing provider states
|
6
|
-
def self.call missing_provider_states
|
6
|
+
def self.call missing_provider_states, output
|
7
7
|
if missing_provider_states.any?
|
8
|
-
puts orangeify(text(missing_provider_states))
|
8
|
+
output.puts orangeify(text(missing_provider_states))
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'pact/provider/print_missing_provider_states'
|
2
|
+
require 'rspec/core/formatters'
|
3
|
+
require 'colored'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Provider
|
7
|
+
module RSpec
|
8
|
+
class Formatter < ::RSpec::Core::Formatters::DocumentationFormatter
|
9
|
+
|
10
|
+
|
11
|
+
def dump_commands_to_rerun_failed_examples
|
12
|
+
return if failed_examples.empty?
|
13
|
+
|
14
|
+
print_rerun_commands
|
15
|
+
print_failure_message
|
16
|
+
print_missing_provider_states
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def print_rerun_commands
|
21
|
+
output.puts("\n")
|
22
|
+
interaction_failure_messages.each do | message |
|
23
|
+
output.puts(message)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def print_missing_provider_states
|
28
|
+
PrintMissingProviderStates.call Pact.world.provider_states.missing_provider_states, output
|
29
|
+
end
|
30
|
+
|
31
|
+
def interaction_failure_messages
|
32
|
+
failed_examples.collect do |example|
|
33
|
+
interaction_failure_message_for example
|
34
|
+
end.uniq
|
35
|
+
end
|
36
|
+
|
37
|
+
def interaction_failure_message_for example
|
38
|
+
provider_state = example.metadata[:pact_interaction].provider_state
|
39
|
+
description = example.metadata[:pact_interaction].description
|
40
|
+
pactfile_uri = example.metadata[:pactfile_uri]
|
41
|
+
example_description = example.metadata[:pact_interaction_example_description]
|
42
|
+
failure_color("rake pact:verify:at[#{pactfile_uri}] PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\"") + " " + detail_color("# #{example_description}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def print_failure_message
|
46
|
+
output.puts failure_message
|
47
|
+
end
|
48
|
+
|
49
|
+
def failure_message
|
50
|
+
|
51
|
+
"\n" + "For assistance debugging failures, please note:".underline.yellow + "\n\n" +
|
52
|
+
"The pact files have been stored locally in the following temp directory:\n #{Pact.configuration.tmp_dir}\n\n" +
|
53
|
+
"The requests and responses are logged in the following log file:\n #{Pact.configuration.log_path}\n\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rspec/core/formatters'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Provider
|
5
|
+
module RSpec
|
6
|
+
class SilentJsonFormatter < ::RSpec::Core::Formatters::JsonFormatter
|
7
|
+
|
8
|
+
def initialize stream
|
9
|
+
# Don't want to display this to the screen,
|
10
|
+
# not sure how else to set a custom stream for a particular formatter
|
11
|
+
# Store a reference to this so it can be inspected afterwards.
|
12
|
+
super(Pact.world.json_formatter_stream)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/pact/provider/rspec.rb
CHANGED
@@ -19,12 +19,10 @@ module Pact
|
|
19
19
|
include ::RSpec::Core::DSL
|
20
20
|
|
21
21
|
def honour_pactfile pactfile_uri, options = {}
|
22
|
-
puts "Filtering specs by: #{options[:criteria]}" if options[:criteria]
|
22
|
+
puts "Filtering specs by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
|
23
23
|
consumer_contract = Pact::ConsumerContract.from_json(read_pact_from(pactfile_uri, options))
|
24
|
-
describe "
|
25
|
-
|
26
|
-
honour_consumer_contract consumer_contract, options
|
27
|
-
end
|
24
|
+
describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}", :pactfile_uri => pactfile_uri do
|
25
|
+
honour_consumer_contract consumer_contract, options
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
@@ -60,12 +58,19 @@ module Pact
|
|
60
58
|
|
61
59
|
def describe_interaction interaction, options
|
62
60
|
|
63
|
-
|
61
|
+
metadata = {
|
62
|
+
:pact => :verify,
|
63
|
+
:pact_interaction => interaction,
|
64
|
+
:pact_interaction_example_description => interaction_description_for_rerun_command(interaction)
|
65
|
+
}
|
66
|
+
|
67
|
+
describe description_for(interaction), metadata do
|
64
68
|
|
65
69
|
interaction_context = InteractionContext.new
|
66
70
|
|
67
71
|
before do
|
68
72
|
interaction_context.run_once :before do
|
73
|
+
Pact.configuration.logger.info "Running example '#{self.example.full_description}'"
|
69
74
|
set_up_provider_state interaction.provider_state, options[:consumer]
|
70
75
|
replay_interaction interaction
|
71
76
|
interaction_context.last_response = last_response
|
@@ -119,7 +124,11 @@ module Pact
|
|
119
124
|
end
|
120
125
|
|
121
126
|
def description_for interaction
|
122
|
-
|
127
|
+
interaction.provider_state ? interaction.description : interaction.description.capitalize
|
128
|
+
end
|
129
|
+
|
130
|
+
def interaction_description_for_rerun_command interaction
|
131
|
+
description_for(interaction).capitalize + ( interaction.provider_state ? " given #{interaction.provider_state}" : "")
|
123
132
|
end
|
124
133
|
|
125
134
|
def read_pact_from uri, options = {}
|
data/lib/pact/provider/world.rb
CHANGED
@@ -14,6 +14,12 @@ module Pact
|
|
14
14
|
module Provider
|
15
15
|
class World
|
16
16
|
|
17
|
+
attr_reader :json_formatter_stream
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@json_formatter_stream = StringIO.new
|
21
|
+
end
|
22
|
+
|
17
23
|
def provider_states
|
18
24
|
@provider_states_proxy ||= Pact::Provider::State::ProviderStateProxy.new
|
19
25
|
end
|
@@ -1,32 +1,29 @@
|
|
1
1
|
module Pact
|
2
2
|
module TaskHelper
|
3
|
-
def failure_message
|
4
|
-
redify(
|
5
|
-
"\n* * * * * * * * * * * * * * * * * * *\n" +
|
6
|
-
"Provider did not honour pact file.\nSee\n * #{Pact.configuration.log_path}\n * #{Pact.configuration.tmp_dir}\nfor logs and pact files." +
|
7
|
-
"\n* * * * * * * * * * * * * * * * * * *\n\n"
|
8
|
-
)
|
9
|
-
end
|
10
3
|
|
11
|
-
|
12
|
-
"\e[31m#{string}\e[m"
|
13
|
-
end
|
4
|
+
extend self
|
14
5
|
|
15
6
|
def handle_verification_failure
|
16
7
|
exit_status = yield
|
17
|
-
if exit_status != 0
|
18
|
-
$stderr.puts failure_message
|
19
|
-
fail
|
20
|
-
end
|
8
|
+
abort if exit_status != 0
|
21
9
|
end
|
22
10
|
|
23
11
|
def spec_criteria defaults = {description: nil, provider_state: nil}
|
24
12
|
criteria = {}
|
25
|
-
|
26
|
-
|
27
|
-
|
13
|
+
|
14
|
+
description = ENV.fetch("PACT_DESCRIPTION", defaults[:description])
|
15
|
+
criteria[:description] = Regexp.new(description) if description
|
16
|
+
|
17
|
+
provider_state = ENV.fetch("PACT_PROVIDER_STATE", defaults[:provider_state])
|
18
|
+
if provider_state
|
19
|
+
if provider_state.length == 0
|
20
|
+
criteria[:provider_state] = nil #Allow PACT_PROVIDER_STATE="" to mean no provider state
|
21
|
+
else
|
22
|
+
criteria[:provider_state] = Regexp.new(provider_state)
|
23
|
+
end
|
28
24
|
end
|
29
|
-
|
25
|
+
|
26
|
+
criteria
|
30
27
|
end
|
31
28
|
end
|
32
29
|
end
|
data/lib/pact/version.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/matchers/difference'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Matchers
|
6
|
+
describe Difference do
|
7
|
+
|
8
|
+
describe "#to_hash" do
|
9
|
+
|
10
|
+
context "when a regexp is expected" do
|
11
|
+
|
12
|
+
subject { Difference.new(/ap/, 'pear').to_hash }
|
13
|
+
|
14
|
+
it "indicates that the actual was indended 'to match'" do
|
15
|
+
expect(subject).to eq({:EXPECTED_TO_MATCH => "/ap/", :ACTUAL => "pear"})
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when something other than a regexp is expected" do
|
21
|
+
|
22
|
+
subject { Difference.new("apple", 'pear').to_hash }
|
23
|
+
|
24
|
+
it "indicates that the actual was intended 'to eq'" do
|
25
|
+
expect(subject).to eq({:EXPECTED => "apple", :ACTUAL => "pear"})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/tasks/task_helper'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
describe TaskHelper do
|
6
|
+
include TaskHelper
|
7
|
+
|
8
|
+
let(:env_description) { "pact description set in ENV"}
|
9
|
+
let(:env_provider_state) { "provider state set in ENV"}
|
10
|
+
let(:env_criteria){ {:description=>/#{env_description}/, :provider_state=>/#{env_provider_state}/} }
|
11
|
+
let(:default_description) { "default description"}
|
12
|
+
let(:default_provider_state) { "default provider state"}
|
13
|
+
|
14
|
+
shared_context "PACT_DESCRIPTION is defined" do
|
15
|
+
before do
|
16
|
+
ENV.stub(:[])
|
17
|
+
ENV.stub(:[]).with("PACT_DESCRIPTION").and_return(env_description)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
shared_context 'PACT_PROVIDER_STATE is defined' do
|
22
|
+
before do
|
23
|
+
ENV.stub(:[])
|
24
|
+
ENV.stub(:[]).with("PACT_PROVIDER_STATE").and_return(env_provider_state)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
shared_context 'default description is defined' do
|
29
|
+
let(:default_description) { "default description"}
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:defaults) { {:description => default_description, :provider_state => default_provider_state} }
|
33
|
+
|
34
|
+
describe "spec_criteria" do
|
35
|
+
|
36
|
+
context "when ENV variables are defined" do
|
37
|
+
before do
|
38
|
+
ENV.stub(:fetch).with("PACT_DESCRIPTION", anything).and_return(env_description)
|
39
|
+
ENV.stub(:fetch).with("PACT_PROVIDER_STATE", anything).and_return(env_provider_state)
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when defaults are not passed in" do
|
43
|
+
it "returns the env vars as regexes" do
|
44
|
+
expect(spec_criteria).to eq(env_criteria)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when defaults are passed in" do
|
49
|
+
it "returns the env vars as regexes" do
|
50
|
+
expect(spec_criteria(defaults)).to eq(env_criteria)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when ENV variables are not defined" do
|
56
|
+
context "when defaults are passed in" do
|
57
|
+
it "returns the defaults as regexes" do
|
58
|
+
expect(spec_criteria(defaults)).to eq({:description=>/#{default_description}/, :provider_state=>/#{default_provider_state}/})
|
59
|
+
end
|
60
|
+
end
|
61
|
+
context "when defaults are not passed in" do
|
62
|
+
it "returns an empty hash" do
|
63
|
+
expect(spec_criteria).to eq({})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when provider state is an empty string" do
|
69
|
+
before do
|
70
|
+
ENV.stub(:fetch).with(anything, anything).and_return(nil)
|
71
|
+
ENV.stub(:fetch).with("PACT_PROVIDER_STATE", anything).and_return('')
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns a nil provider state so that it matches a nil provider state on the interaction" do
|
75
|
+
expect(spec_criteria[:provider_state]).to be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -88,16 +88,6 @@ module Pact
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
context 'when one or more specs fail' do
|
92
|
-
|
93
|
-
let(:exit_code) {1}
|
94
|
-
|
95
|
-
it 'raises an exception' do
|
96
|
-
$stderr.should_receive(:puts) #Confusing if this shows on the screen!
|
97
|
-
expect { Rake::Task[@task_name].execute }.to raise_error RuntimeError
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
101
91
|
end
|
102
92
|
end
|
103
93
|
end
|
data/spec/support/pact_helper.rb
CHANGED
@@ -28,12 +28,16 @@ module Pact
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
Pact.set_up do
|
32
|
+
WEATHER ||= {}
|
33
|
+
end
|
31
34
|
|
32
35
|
#one with a top level consumer
|
33
36
|
Pact.provider_states_for 'some-test-consumer' do
|
37
|
+
|
34
38
|
provider_state "the weather is sunny" do
|
35
39
|
set_up do
|
36
|
-
|
40
|
+
|
37
41
|
WEATHER[:current_state] = 'sunny'
|
38
42
|
end
|
39
43
|
end
|
@@ -42,7 +46,6 @@ module Pact
|
|
42
46
|
#one without a top level consumer
|
43
47
|
Pact.provider_state "the weather is cloudy" do
|
44
48
|
set_up do
|
45
|
-
WEATHER ||= {}
|
46
49
|
WEATHER[:current_state] = 'cloudy'
|
47
50
|
end
|
48
51
|
end
|
data/spec/support/stubbing.json
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"consumer": {
|
3
|
+
"name": "some-test-consumer"
|
4
|
+
},
|
5
|
+
"provider": {
|
6
|
+
"name": "an unknown provider"
|
7
|
+
},
|
8
|
+
"interactions": [
|
9
|
+
{
|
10
|
+
"description": "a test request",
|
11
|
+
"request": {
|
12
|
+
"method": "get",
|
13
|
+
"path": "/weather",
|
14
|
+
"query": ""
|
15
|
+
},
|
16
|
+
"response": {
|
17
|
+
"status": 200,
|
18
|
+
"headers" : {"Content-type": "application/json"},
|
19
|
+
"body": {
|
20
|
+
"message" : {
|
21
|
+
"json_class": "Pact::Term",
|
22
|
+
"data": {
|
23
|
+
"generate": "rainy",
|
24
|
+
"matcher": {
|
25
|
+
"json_class": "Regexp",
|
26
|
+
"o": 0,
|
27
|
+
"s": "rain"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
},
|
33
|
+
"provider_state": "the weather is sunny"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
@@ -4,10 +4,10 @@
|
|
4
4
|
},
|
5
5
|
"provider": {
|
6
6
|
"name": "an unknown provider"
|
7
|
-
},
|
7
|
+
},
|
8
8
|
"interactions": [
|
9
9
|
{
|
10
|
-
"description": "
|
10
|
+
"description": "a test request",
|
11
11
|
"request": {
|
12
12
|
"method": "get",
|
13
13
|
"path": "/weather",
|
@@ -20,6 +20,33 @@
|
|
20
20
|
|
21
21
|
},
|
22
22
|
"provider_state": "the weather is cloudy"
|
23
|
+
},{
|
24
|
+
"description": "another test request",
|
25
|
+
"request": {
|
26
|
+
"method": "get",
|
27
|
+
"path": "/weather",
|
28
|
+
"query": ""
|
29
|
+
},
|
30
|
+
"response": {
|
31
|
+
"status": 200,
|
32
|
+
"headers" : {"Content-type": "application/json"},
|
33
|
+
"body": {"message" : "this is not the weather you are looking for"}
|
34
|
+
|
35
|
+
}
|
36
|
+
},{
|
37
|
+
"description": "another test request",
|
38
|
+
"provider_state": "a missing provider state",
|
39
|
+
"request": {
|
40
|
+
"method": "get",
|
41
|
+
"path": "/weather",
|
42
|
+
"query": ""
|
43
|
+
},
|
44
|
+
"response": {
|
45
|
+
"status": 200,
|
46
|
+
"headers" : {"Content-type": "application/json"},
|
47
|
+
"body": {"message" : "this is not the weather you are looking for"}
|
48
|
+
|
49
|
+
}
|
23
50
|
}
|
24
51
|
]
|
25
52
|
}
|
@@ -4,10 +4,10 @@
|
|
4
4
|
},
|
5
5
|
"provider": {
|
6
6
|
"name": "an unknown provider"
|
7
|
-
},
|
7
|
+
},
|
8
8
|
"interactions": [
|
9
9
|
{
|
10
|
-
"description": "
|
10
|
+
"description": "a test request",
|
11
11
|
"request": {
|
12
12
|
"method": "get",
|
13
13
|
"path": "/weather",
|
@@ -21,7 +21,7 @@
|
|
21
21
|
"provider_state": "the weather is sunny"
|
22
22
|
},
|
23
23
|
{
|
24
|
-
"description": "
|
24
|
+
"description": "a test request for text",
|
25
25
|
"request": {
|
26
26
|
"method": "get",
|
27
27
|
"path": "/sometext",
|
@@ -33,6 +33,6 @@
|
|
33
33
|
"headers" : {"Content-type": "text/plain"},
|
34
34
|
"body": "some text"
|
35
35
|
}
|
36
|
-
}
|
36
|
+
}
|
37
37
|
]
|
38
38
|
}
|
data/tasks/pact-test.rake
CHANGED
@@ -8,6 +8,17 @@ Pact::VerificationTask.new(:stubbing_using_allow) do | pact |
|
|
8
8
|
pact.uri './spec/support/stubbing.json', :pact_helper => './spec/support/stubbing_using_allow.rb'
|
9
9
|
end
|
10
10
|
|
11
|
+
Pact::VerificationTask.new(:pass) do | pact |
|
12
|
+
pact.uri './spec/support/test_app_pass.json'
|
13
|
+
end
|
14
|
+
|
15
|
+
Pact::VerificationTask.new(:fail) do | pact |
|
16
|
+
pact.uri './spec/support/test_app_fail.json'
|
17
|
+
end
|
18
|
+
|
19
|
+
Pact::VerificationTask.new(:term) do | pact |
|
20
|
+
pact.uri './spec/support/term.json'
|
21
|
+
end
|
11
22
|
|
12
23
|
namespace :pact do
|
13
24
|
|
@@ -20,6 +31,7 @@ namespace :pact do
|
|
20
31
|
silent = true
|
21
32
|
puts "Running task pact:tests"
|
22
33
|
# Run these specs silently, otherwise expected failures will be written to stdout and look like unexpected failures.
|
34
|
+
Pact.configuration.output_stream = StringIO.new if silent
|
23
35
|
|
24
36
|
result = Pact::Provider::PactSpecRunner.new([{ uri: './spec/support/test_app_pass.json' }], silent: silent).run
|
25
37
|
fail 'Expected pact to pass' unless (result == 0)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.0.
|
4
|
+
version: 1.1.0.rc2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2014-03-
|
16
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: randexp
|
@@ -362,6 +362,7 @@ files:
|
|
362
362
|
- lib/pact/logging.rb
|
363
363
|
- lib/pact/matchers.rb
|
364
364
|
- lib/pact/matchers/diff_decorator.rb
|
365
|
+
- lib/pact/matchers/difference.rb
|
365
366
|
- lib/pact/matchers/index_not_found.rb
|
366
367
|
- lib/pact/matchers/matchers.rb
|
367
368
|
- lib/pact/matchers/nested_json_diff_decorator.rb
|
@@ -378,6 +379,8 @@ files:
|
|
378
379
|
- lib/pact/provider/print_missing_provider_states.rb
|
379
380
|
- lib/pact/provider/request.rb
|
380
381
|
- lib/pact/provider/rspec.rb
|
382
|
+
- lib/pact/provider/rspec/formatter.rb
|
383
|
+
- lib/pact/provider/rspec/silent_json_formatter.rb
|
381
384
|
- lib/pact/provider/state/provider_state.rb
|
382
385
|
- lib/pact/provider/state/provider_state_configured_modules.rb
|
383
386
|
- lib/pact/provider/state/provider_state_manager.rb
|
@@ -426,6 +429,7 @@ files:
|
|
426
429
|
- spec/lib/pact/consumer_contract/interaction_spec.rb
|
427
430
|
- spec/lib/pact/consumer_contract/request_spec.rb
|
428
431
|
- spec/lib/pact/matchers/diff_decorator_spec.rb
|
432
|
+
- spec/lib/pact/matchers/difference_spec.rb
|
429
433
|
- spec/lib/pact/matchers/matchers_spec.rb
|
430
434
|
- spec/lib/pact/matchers/nested_json_diff_decorator_spec.rb
|
431
435
|
- spec/lib/pact/matchers/plus_minus_diff_decorator_spec.rb
|
@@ -442,6 +446,7 @@ files:
|
|
442
446
|
- spec/lib/pact/reification_spec.rb
|
443
447
|
- spec/lib/pact/shared/dsl_spec.rb
|
444
448
|
- spec/lib/pact/something_like_spec.rb
|
449
|
+
- spec/lib/pact/tasks/task_helper_spec.rb
|
445
450
|
- spec/lib/pact/term_spec.rb
|
446
451
|
- spec/lib/pact/verification_task_spec.rb
|
447
452
|
- spec/spec_helper.rb
|
@@ -457,6 +462,7 @@ files:
|
|
457
462
|
- spec/support/stubbing.json
|
458
463
|
- spec/support/stubbing.rb
|
459
464
|
- spec/support/stubbing_using_allow.rb
|
465
|
+
- spec/support/term.json
|
460
466
|
- spec/support/test_app_fail.json
|
461
467
|
- spec/support/test_app_pass.json
|
462
468
|
- tasks/pact-test.rake
|
@@ -474,9 +480,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
474
480
|
- - ! '>='
|
475
481
|
- !ruby/object:Gem::Version
|
476
482
|
version: '0'
|
477
|
-
segments:
|
478
|
-
- 0
|
479
|
-
hash: -3201059694268013519
|
480
483
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
481
484
|
none: false
|
482
485
|
requirements:
|
@@ -517,6 +520,7 @@ test_files:
|
|
517
520
|
- spec/lib/pact/consumer_contract/interaction_spec.rb
|
518
521
|
- spec/lib/pact/consumer_contract/request_spec.rb
|
519
522
|
- spec/lib/pact/matchers/diff_decorator_spec.rb
|
523
|
+
- spec/lib/pact/matchers/difference_spec.rb
|
520
524
|
- spec/lib/pact/matchers/matchers_spec.rb
|
521
525
|
- spec/lib/pact/matchers/nested_json_diff_decorator_spec.rb
|
522
526
|
- spec/lib/pact/matchers/plus_minus_diff_decorator_spec.rb
|
@@ -533,6 +537,7 @@ test_files:
|
|
533
537
|
- spec/lib/pact/reification_spec.rb
|
534
538
|
- spec/lib/pact/shared/dsl_spec.rb
|
535
539
|
- spec/lib/pact/something_like_spec.rb
|
540
|
+
- spec/lib/pact/tasks/task_helper_spec.rb
|
536
541
|
- spec/lib/pact/term_spec.rb
|
537
542
|
- spec/lib/pact/verification_task_spec.rb
|
538
543
|
- spec/spec_helper.rb
|
@@ -548,5 +553,6 @@ test_files:
|
|
548
553
|
- spec/support/stubbing.json
|
549
554
|
- spec/support/stubbing.rb
|
550
555
|
- spec/support/stubbing_using_allow.rb
|
556
|
+
- spec/support/term.json
|
551
557
|
- spec/support/test_app_fail.json
|
552
558
|
- spec/support/test_app_pass.json
|