diff --git a/README.md b/README.md
index a45d3dd..55be1b4 100644
--- a/README.md
+++ b/README.md
@@ -3,3 +3,69 @@
![Build status](https://github.com/pact-foundation/pact-support/workflows/Test/badge.svg)
Provides shared code for the Pact gems
+
+## Compatibility
+
+Specification Compatibility
+
+| Version | Stable | [Spec] Compatibility |
+| ------- | ------ | -------------------- |
+| 1.x.x | Yes | 2, 3\* |
+
+_\*_ v3 support is limited to the subset of functionality required to enable language inter-operable [Message support].
+
+- See V3 tracking [issue](https://github.com/pact-foundation/pact-ruby/issues/318).
+- See V4 tracking [issue](https://github.com/pact-foundation/pact-ruby/issues/319).
+
+Want V3/V4 support now? See the new standalone [pact-verifier](https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_verifier_cli#standalone-pact-verifier)
+
+[message support]: https://github.com/pact-foundation/pact-specification/tree/version-3#introduces-messages-for-services-that-communicate-via-event-streams-and-message-queues
+
+
+
+### Supported matching rules
+
+| matcher | Spec Version | Implemented | Usage|
+|---------------|--------------|-------------|-------------|
+| Equality | V1 | | |
+| Regex | V2 | ✅ | `Pact.term(generate, matcher)` |
+| Type | V2 | ✅ | `Pact.like(generate)` |
+| MinType | V2 | ✅ | `Pact.each_like(generate, min: )` |
+| MaxType | V2 | | |
+| MinMaxType | V2 | | |
+| Include | V3 | | |
+| Integer | V3 | | |
+| Decimal | V3 | | |
+| Number | V3 | | |
+| Timestamp | V3 | | |
+| Time | V3 | | |
+| Date | V3 | | |
+| Null | V3 | | |
+| Boolean | V3 | | |
+| ContentType | V3 | | |
+| Values | V3 | | |
+| ArrayContains | V4 | | |
+| StatusCode | V4 | | |
+| NotEmpty | V4 | | |
+| Semver | V4 | | |
+| EachKey | V4 | | |
+| EachValue | V4 | | |
+
+### Supported generators
+
+Currently limited to provider verification only. No current way to set in consumer tests.
+
+| Generator | Spec Version | Implemented |
+|------------------------|--------------|----|
+| RandomInt | V3 | ✅ |
+| RandomDecimal | V3 | ✅ |
+| RandomHexadecimal | V3 | ✅ |
+| RandomString | V3 | ✅ |
+| Regex | V3 | ✅ |
+| Uuid | V3/V4 | ✅ |
+| Date | V3 | ✅ |
+| Time | V3 | ✅ |
+| DateTime | V3 | ✅ |
+| RandomBoolean | V3 | ✅ |
+| ProviderState | V4 | ✅ |
+| MockServerURL | V4 | 🚧 |
diff --git a/lib/pact/generator/date.rb b/lib/pact/generator/date.rb
new file mode 100644
index 0000000..d444241
--- /dev/null
+++ b/lib/pact/generator/date.rb
@@ -0,0 +1,62 @@
+require 'date'
+
+module Pact
+ module Generator
+ # Date provides the time generator which will give the current date in the defined format
+ class Date
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == type
+ end
+
+ def call(hash, _params = nil, _example_value = nil)
+ format = hash['format'] || default_format
+ ::Time.now.strftime(convert_from_java_simple_date_format(format))
+ end
+
+ def type
+ 'Date'
+ end
+
+ def default_format
+ 'yyyy-MM-dd'
+ end
+
+ # Format for the pact specficiation should be the Java DateTimeFormmater
+ # This tries to convert to something Ruby can format.
+ def convert_from_java_simple_date_format(format)
+ # Year
+ format.sub!(/(?= 0
+ if position.positive?
+ # add string
+ return_string.push(buffer[0...position])
+ end
+ end_position = buffer.index(END_EXPRESSION, position)
+ raise 'Missing closing brace in expression string' if !end_position || end_position.negative?
+
+ variable = buffer[position + 2...end_position]
+
+ logger.info "Could not subsitute provider state key #{variable}, have #{params}" unless params[variable]
+
+ expression = params[variable] || ''
+ return_string.push(expression)
+
+ buffer = buffer[end_position + 1...-1]
+ position = buffer.index(START_EXPRESSION)
+ end
+
+ return_string.join('')
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/random_boolean.rb b/lib/pact/generator/random_boolean.rb
new file mode 100644
index 0000000..beb1224
--- /dev/null
+++ b/lib/pact/generator/random_boolean.rb
@@ -0,0 +1,14 @@
+module Pact
+ module Generator
+ # Boolean provides the boolean generator which will give a true or false value
+ class RandomBoolean
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'RandomBoolean'
+ end
+
+ def call(_hash, _params = nil, _example_value = nil)
+ [true, false].sample
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/random_decimal.rb b/lib/pact/generator/random_decimal.rb
new file mode 100644
index 0000000..f255989
--- /dev/null
+++ b/lib/pact/generator/random_decimal.rb
@@ -0,0 +1,37 @@
+require 'bigdecimal'
+
+module Pact
+ module Generator
+ # RandomDecimal provides the random decimal generator which will generate a decimal value of digits length
+ class RandomDecimal
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'RandomDecimal'
+ end
+
+ def call(hash, _params = nil, _example_value = nil)
+ digits = hash['digits'] || 6
+
+ raise 'RandomDecimalGenerator digits must be > 0, got $digits' if digits < 1
+
+ return rand(0..9) if digits == 1
+
+ return rand(0..9) + rand(1..9) / 10 if digits == 2
+
+ pos = rand(1..digits - 1)
+ precision = digits - pos
+ integers = ''
+ decimals = ''
+ while pos.positive?
+ integers += String(rand(1..9))
+ pos -= 1
+ end
+ while precision.positive?
+ decimals += String(rand(1..9))
+ precision -= 1
+ end
+
+ Float("#{integers}.#{decimals}")
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/random_hexadecimal.rb b/lib/pact/generator/random_hexadecimal.rb
new file mode 100644
index 0000000..b90a3de
--- /dev/null
+++ b/lib/pact/generator/random_hexadecimal.rb
@@ -0,0 +1,19 @@
+require 'securerandom'
+
+module Pact
+ module Generator
+ # RandomHexadecimal provides the random hexadecimal generator which will generate a hexadecimal
+ class RandomHexadecimal
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'RandomHexadecimal'
+ end
+
+ def call(hash, _params = nil, _example_value = nil)
+ digits = hash['digits'] || 8
+ bytes = (digits / 2).ceil
+ string = SecureRandom.hex(bytes)
+ string[0, digits]
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/random_int.rb b/lib/pact/generator/random_int.rb
new file mode 100644
index 0000000..fc157be
--- /dev/null
+++ b/lib/pact/generator/random_int.rb
@@ -0,0 +1,16 @@
+module Pact
+ module Generator
+ # RandomInt provides the random int generator which generate a random integer, with a min/max
+ class RandomInt
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'RandomInt'
+ end
+
+ def call(hash, _params = nil, _example_value = nil)
+ min = hash['min'] || 0
+ max = hash['max'] || 2_147_483_647
+ rand(min..max)
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/random_string.rb b/lib/pact/generator/random_string.rb
new file mode 100644
index 0000000..e61c57a
--- /dev/null
+++ b/lib/pact/generator/random_string.rb
@@ -0,0 +1,16 @@
+module Pact
+ module Generator
+ # RandomString provides the random string generator which generate a random string of size length
+ class RandomString
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'RandomString'
+ end
+
+ def call(hash, _params = nil, _example_value = nil)
+ size = hash['size'] || 20
+ string = rand(36**(size + 2)).to_s(36)
+ string[0, size]
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/regex.rb b/lib/pact/generator/regex.rb
new file mode 100644
index 0000000..eb587b2
--- /dev/null
+++ b/lib/pact/generator/regex.rb
@@ -0,0 +1,17 @@
+require 'string_pattern'
+
+module Pact
+ module Generator
+ # Regex provides the regex generator which will generate a value based on the regex pattern provided
+ class Regex
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'Regex'
+ end
+
+ def call(hash, _params = nil, _example_value = nil)
+ pattern = hash['pattern'] || ''
+ StringPattern.generate(Regexp.new(pattern))
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/time.rb b/lib/pact/generator/time.rb
new file mode 100644
index 0000000..bbd7651
--- /dev/null
+++ b/lib/pact/generator/time.rb
@@ -0,0 +1,16 @@
+require 'date'
+
+module Pact
+ module Generator
+ # Time provides the time generator which will give the current time in the defined format
+ class Time < Date
+ def type
+ 'Time'
+ end
+
+ def default_format
+ 'HH:mm'
+ end
+ end
+ end
+end
diff --git a/lib/pact/generator/uuid.rb b/lib/pact/generator/uuid.rb
new file mode 100644
index 0000000..457dcce
--- /dev/null
+++ b/lib/pact/generator/uuid.rb
@@ -0,0 +1,19 @@
+require 'securerandom'
+
+module Pact
+ module Generator
+ # Uuid provides the uuid generator
+ class Uuid
+ def can_generate?(hash)
+ hash.key?('type') && hash['type'] == 'Uuid'
+ end
+
+ # If we had the example value, we could determine what type of uuid
+ # to send, this is what pact-jvm does
+ # See https://github.com/pact-foundation/pact-jvm/blob/master/core/model/src/main/kotlin/au/com/dius/pact/core/model/generators/Generator.kt
+ def call(_hash, _params = nil, _example_value = nil)
+ SecureRandom.uuid
+ end
+ end
+ end
+end
diff --git a/lib/pact/generators.rb b/lib/pact/generators.rb
new file mode 100644
index 0000000..4d41b02
--- /dev/null
+++ b/lib/pact/generators.rb
@@ -0,0 +1,64 @@
+require 'pact/generator/random_boolean'
+require 'pact/generator/date'
+require 'pact/generator/datetime'
+require 'pact/generator/provider_state'
+require 'pact/generator/random_decimal'
+require 'pact/generator/random_hexadecimal'
+require 'pact/generator/random_int'
+require 'pact/generator/random_string'
+require 'pact/generator/regex'
+require 'pact/generator/time'
+require 'pact/generator/uuid'
+require 'pact/matching_rules/jsonpath'
+require 'pact/matching_rules/v3/extract'
+require 'jsonpath'
+
+module Pact
+ class Generators
+ def self.add_generator(generator)
+ generators.unshift(generator)
+ end
+
+ def self.generators
+ @generators ||= []
+ end
+
+ def self.execute_generators(object, state_params = nil, example_value = nil)
+ generators.each do |parser|
+ return parser.call(object, state_params, example_value) if parser.can_generate?(object)
+ end
+
+ raise Pact::UnrecognizePactFormatError, "This document does not use a recognised Pact generator: #{object}"
+ end
+
+ def self.apply_generators(expected_request, component, example_value, state_params)
+ # Latest pact-support is required to have generators exposed
+ if expected_request.methods.include?(:generators) && expected_request.generators[component]
+ # Some component will have single generator without selectors, i.e. path
+ generators = expected_request.generators[component]
+ if generators.is_a?(Hash) && generators.key?('type')
+ return execute_generators(generators, state_params, example_value)
+ end
+
+ generators.each do |selector, generator|
+ val = JsonPath.new(selector).on(example_value)
+ replace = execute_generators(generator, state_params, val)
+ example_value = JsonPath.for(example_value).gsub(selector) { |_v| replace }.to_hash
+ end
+ end
+ example_value
+ end
+
+ add_generator(Generator::RandomBoolean.new)
+ add_generator(Generator::Date.new)
+ add_generator(Generator::DateTime.new)
+ add_generator(Generator::ProviderState.new)
+ add_generator(Generator::RandomDecimal.new)
+ add_generator(Generator::RandomHexadecimal.new)
+ add_generator(Generator::RandomInt.new)
+ add_generator(Generator::RandomString.new)
+ add_generator(Generator::Regex.new)
+ add_generator(Generator::Time.new)
+ add_generator(Generator::Uuid.new)
+ end
+end
diff --git a/pact-support.gemspec b/pact-support.gemspec
index a984465..b240d6f 100644
--- a/pact-support.gemspec
+++ b/pact-support.gemspec
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency "awesome_print", "~> 1.9"
spec.add_runtime_dependency "diff-lcs", "~> 1.5"
spec.add_runtime_dependency "expgen", "~> 0.1"
+ spec.add_runtime_dependency 'string_pattern', '~> 2.0'
+ spec.add_runtime_dependency 'jsonpath', '~> 1.0'
spec.add_development_dependency "rspec", ">= 2.14", "< 4.0"
spec.add_development_dependency "rake", "~> 13.0"
diff --git a/spec/lib/pact/generator/date_spec.rb b/spec/lib/pact/generator/date_spec.rb
new file mode 100644
index 0000000..4319d9e
--- /dev/null
+++ b/spec/lib/pact/generator/date_spec.rb
@@ -0,0 +1,20 @@
+require 'pact/generator/date'
+
+describe Pact::Generator::Date do
+ generator = Pact::Generator::Date.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'Date' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'Date' }
+ expect(generator.call(hash).length).to eq(10)
+ end
+end
diff --git a/spec/lib/pact/generator/datetime_spec.rb b/spec/lib/pact/generator/datetime_spec.rb
new file mode 100644
index 0000000..345a858
--- /dev/null
+++ b/spec/lib/pact/generator/datetime_spec.rb
@@ -0,0 +1,21 @@
+require 'pact/generator/datetime'
+
+describe Pact::Generator::DateTime do
+ generator = Pact::Generator::DateTime.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'DateTime' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'DateTime' }
+ p generator.call(hash)
+ expect(generator.call(hash).length).to eq(16)
+ end
+end
diff --git a/spec/lib/pact/generator/provider_state_spec.rb b/spec/lib/pact/generator/provider_state_spec.rb
new file mode 100644
index 0000000..d371685
--- /dev/null
+++ b/spec/lib/pact/generator/provider_state_spec.rb
@@ -0,0 +1,37 @@
+require 'pact/generator/provider_state'
+
+describe Pact::Generator::ProviderState do
+ generator = Pact::Generator::ProviderState.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'ProviderState' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call without params' do
+ hash = { 'type' => 'ProviderState', 'expression' => 'Bearer ${access_token}' }
+ expect(generator.call(hash)).to eq 'Bearer '
+ end
+
+ it 'call with correct params' do
+ hash = { 'type' => 'ProviderState', 'expression' => 'Bearer ${access_token}' }
+ params = { 'access_token' => 'ABC' }
+ expect(generator.call(hash, params)).to eq 'Bearer ABC'
+ end
+
+ it 'call with wrong params' do
+ hash = { 'type' => 'ProviderState', 'expression' => 'Bearer ${access_token}' }
+ params = { 'refresh_token' => 'ABC' }
+ expect(generator.call(hash, params)).to eq 'Bearer '
+ end
+
+ it 'call with incomplete expression' do
+ hash = { 'type' => 'ProviderState', 'expression' => 'Bearer ${access_token' }
+ expect { generator.call(hash) }.to raise_error('Missing closing brace in expression string')
+ end
+end
diff --git a/spec/lib/pact/generator/random_boolean_spec.rb b/spec/lib/pact/generator/random_boolean_spec.rb
new file mode 100644
index 0000000..8834861
--- /dev/null
+++ b/spec/lib/pact/generator/random_boolean_spec.rb
@@ -0,0 +1,20 @@
+require 'pact/generator/random_boolean'
+
+describe Pact::Generator::RandomBoolean do
+ generator = Pact::Generator::RandomBoolean.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'RandomBoolean' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'RandomBoolean' }
+ expect(generator.call(hash)).to eq(true).or eq(false)
+ end
+end
diff --git a/spec/lib/pact/generator/random_decimal_spec.rb b/spec/lib/pact/generator/random_decimal_spec.rb
new file mode 100644
index 0000000..4c1689f
--- /dev/null
+++ b/spec/lib/pact/generator/random_decimal_spec.rb
@@ -0,0 +1,27 @@
+require 'pact/generator/random_decimal'
+
+describe Pact::Generator::RandomDecimal do
+ generator = Pact::Generator::RandomDecimal.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'RandomDecimal' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'RandomDecimal' }
+ value = generator.call(hash)
+ expect(String(value).length).to eq 7
+ end
+
+ it 'call with digits' do
+ hash = { 'type' => 'RandomDecimal', 'digits' => 10 }
+ value = generator.call(hash)
+ expect(String(value).length).to eq 11
+ end
+end
diff --git a/spec/lib/pact/generator/random_hexadecimal_spec.rb b/spec/lib/pact/generator/random_hexadecimal_spec.rb
new file mode 100644
index 0000000..8b124ba
--- /dev/null
+++ b/spec/lib/pact/generator/random_hexadecimal_spec.rb
@@ -0,0 +1,25 @@
+require 'pact/generator/random_hexadecimal'
+
+describe Pact::Generator::RandomHexadecimal do
+ generator = Pact::Generator::RandomHexadecimal.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'RandomHexadecimal' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'RandomHexadecimal' }
+ expect(generator.call(hash).length).to eq(8)
+ end
+
+ it 'call with size' do
+ hash = { 'type' => 'RandomHexadecimal', 'digits' => 2 }
+ expect(generator.call(hash).length).to eq(2)
+ end
+end
diff --git a/spec/lib/pact/generator/random_int_spec.rb b/spec/lib/pact/generator/random_int_spec.rb
new file mode 100644
index 0000000..a2290fd
--- /dev/null
+++ b/spec/lib/pact/generator/random_int_spec.rb
@@ -0,0 +1,25 @@
+require 'pact/generator/random_int'
+
+describe Pact::Generator::RandomInt do
+ generator = Pact::Generator::RandomInt.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'RandomInt' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'RandomInt' }
+ expect(generator.call(hash).instance_of?(Integer)).to be true
+ end
+
+ it 'call with min/max' do
+ hash = { 'type' => 'RandomInt', 'min' => 5, 'max' => 5 }
+ expect(generator.call(hash)).to eq 5
+ end
+end
diff --git a/spec/lib/pact/generator/random_string_spec.rb b/spec/lib/pact/generator/random_string_spec.rb
new file mode 100644
index 0000000..8675058
--- /dev/null
+++ b/spec/lib/pact/generator/random_string_spec.rb
@@ -0,0 +1,25 @@
+require 'pact/generator/random_string'
+
+describe Pact::Generator::RandomString do
+ generator = Pact::Generator::RandomString.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'RandomString' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'RandomString' }
+ expect(generator.call(hash).length).to eq(20)
+ end
+
+ it 'call with size' do
+ hash = { 'type' => 'RandomString', 'size' => 30 }
+ expect(generator.call(hash).length).to eq(30)
+ end
+end
diff --git a/spec/lib/pact/generator/regex_spec.rb b/spec/lib/pact/generator/regex_spec.rb
new file mode 100644
index 0000000..723383d
--- /dev/null
+++ b/spec/lib/pact/generator/regex_spec.rb
@@ -0,0 +1,20 @@
+require 'pact/generator/regex'
+
+describe Pact::Generator::Regex do
+ generator = Pact::Generator::Regex.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'Regex' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'Regex', 'pattern' => '(one|two)' }
+ expect(generator.call(hash)).to eq('one').or eq('two')
+ end
+end
diff --git a/spec/lib/pact/generator/time_spec.rb b/spec/lib/pact/generator/time_spec.rb
new file mode 100644
index 0000000..21cd9a5
--- /dev/null
+++ b/spec/lib/pact/generator/time_spec.rb
@@ -0,0 +1,20 @@
+require 'pact/generator/time'
+
+describe Pact::Generator::Time do
+ generator = Pact::Generator::Time.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'Time' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'Time' }
+ expect(generator.call(hash).length).to eq(5)
+ end
+end
diff --git a/spec/lib/pact/generator/uuid_spec.rb b/spec/lib/pact/generator/uuid_spec.rb
new file mode 100644
index 0000000..aa9a94d
--- /dev/null
+++ b/spec/lib/pact/generator/uuid_spec.rb
@@ -0,0 +1,20 @@
+require 'pact/generator/uuid'
+
+describe Pact::Generator::Uuid do
+ generator = Pact::Generator::Uuid.new
+
+ it 'can_generate with a supported hash' do
+ hash = { 'type' => 'Uuid' }
+ expect(generator.can_generate?(hash)).to be true
+ end
+
+ it 'can_generate with a unsupported hash' do
+ hash = { 'type' => 'unknown' }
+ expect(generator.can_generate?(hash)).to be false
+ end
+
+ it 'call' do
+ hash = { 'type' => 'Uuid' }
+ expect(generator.call(hash).length).to eq(36)
+ end
+end
diff --git a/spec/lib/pact/generators_spec.rb b/spec/lib/pact/generators_spec.rb
new file mode 100644
index 0000000..5a190a5
--- /dev/null
+++ b/spec/lib/pact/generators_spec.rb
@@ -0,0 +1,59 @@
+require 'pact/generators'
+
+describe Pact::Generators do
+ it 'execute_generators with RandomBoolean' do
+ hash = { 'type' => 'RandomBoolean' }
+ expect(Pact::Generators.execute_generators(hash)).to eq(true).or eq(false)
+ end
+
+ it 'execute_generators with Date' do
+ hash = { 'type' => 'Date' }
+ expect(Pact::Generators.execute_generators(hash).length).to eq(10)
+ end
+
+ it 'execute_generators with DateTime' do
+ hash = { 'type' => 'DateTime' }
+ expect(Pact::Generators.execute_generators(hash).length).to eq(16)
+ end
+
+ it 'execute_generators with ProviderState' do
+ hash = { 'type' => 'ProviderState', 'expression' => 'Bearer ${access_token}' }
+ params = { 'access_token' => 'ABC' }
+ expect(Pact::Generators.execute_generators(hash, params)).to eq('Bearer ABC')
+ end
+
+ it 'execute_generators with RandomDecimal' do
+ hash = { 'type' => 'RandomDecimal' }
+ expect(String(Pact::Generators.execute_generators(hash)).length).to eq(7)
+ end
+
+ it 'execute_generators with RandomHexadecimal' do
+ hash = { 'type' => 'RandomHexadecimal' }
+ expect(Pact::Generators.execute_generators(hash).length).to eq(8)
+ end
+
+ it 'execute_generators with RandomInt' do
+ hash = { 'type' => 'RandomInt' }
+ expect(Pact::Generators.execute_generators(hash).instance_of?(Integer)).to be true
+ end
+
+ it 'execute_generators with RandomString' do
+ hash = { 'type' => 'RandomString' }
+ expect(Pact::Generators.execute_generators(hash).length).to eq(20)
+ end
+
+ it 'execute_generators with Regex' do
+ hash = { 'type' => 'Regex', 'pattern' => '(one|two)' }
+ expect(Pact::Generators.execute_generators(hash)).to eq('one').or eq('two')
+ end
+
+ it 'execute_generators with Time' do
+ hash = { 'type' => 'Time' }
+ expect(Pact::Generators.execute_generators(hash).length).to eq(5)
+ end
+
+ it 'execute_generators with Uuid' do
+ hash = { 'type' => 'Uuid' }
+ expect(Pact::Generators.execute_generators(hash).length).to eq(36)
+ end
+end