-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add spec for --pact-file-write-mode merge
- Loading branch information
Showing
8 changed files
with
299 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
tmp | ||
osx | ||
osx | ||
pacts | ||
.rspec_status |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--color | ||
--format documentation | ||
--require spec_helper |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
source 'https://rubygems.org' | ||
|
||
gem 'rake' | ||
gem 'octokit' | ||
gem 'rubyzip' | ||
gem 'childprocess' | ||
gem 'rack' | ||
gem 'rake', '~> 12.0' | ||
gem 'octokit', '~> 4.7' | ||
gem 'rubyzip', '~> 1.2' | ||
gem 'childprocess', '~> 0.7' | ||
gem 'rack', '~> 2.0' | ||
gem 'rspec', '~> 3.7' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
require 'faraday' | ||
require 'json' | ||
RSpec.describe "running the mock service with the pact-file-mode merge" do | ||
|
||
PACT_FILE_PATH = "./pacts/foo-bar.json" | ||
|
||
let(:faraday) do | ||
Faraday.new(:url => "http://localhost:1235") do |faraday| | ||
faraday.adapter Faraday.default_adapter | ||
faraday.response :logger do | logger | | ||
def logger.debug *args; end | ||
end | ||
end | ||
end | ||
|
||
let(:mock_service_options) do | ||
{ cli_args: ['--pact-file-write-mode', 'merge'] } | ||
end | ||
|
||
let(:first_interaction) do | ||
{description: "test", providerState: nil, request: {method: 'GET', path: '/test'}, response: {status: 200} } | ||
end | ||
|
||
let(:second_interaction) do | ||
{description: "another test", providerState: nil, request: {method: 'GET', path: '/another-test'}, response: {status: 200} } | ||
end | ||
|
||
let(:interaction_headers) do | ||
{'X-Pact-Mock-Service' => 'true', 'Content-Type' => 'application/json'} | ||
end | ||
|
||
let(:admin_header) do | ||
{'X-Pact-Mock-Service' => 'true'} | ||
end | ||
|
||
let(:pact_details) do | ||
{ consumer: { name: 'Foo' }, provider: { name: 'bar' }, pact_dir: File.absolute_path('./pacts') } | ||
end | ||
|
||
let(:pact_hash) do | ||
JSON.parse(File.read(PACT_FILE_PATH), symbolize_names: true) | ||
end | ||
|
||
it "creates a file when one does not already exist" do | ||
FileUtils.rm_rf PACT_FILE_PATH | ||
with_process(mock_service_process(mock_service_options)) do | ||
wait_for_mock_service_to_start(faraday, admin_header) | ||
expect_successful_request(faraday, :get, "/", nil, admin_header) | ||
expect_successful_request(faraday, :post, "/interactions", first_interaction.to_json, interaction_headers) | ||
expect_successful_request(faraday, :get, "/test") | ||
expect_successful_request(faraday, :get, "/interactions/verification", nil, admin_header) | ||
expect_successful_request(faraday, :post, "/pact", pact_details.to_json, admin_header) | ||
expect(File.exists?(PACT_FILE_PATH)) | ||
end | ||
end | ||
|
||
it "merges the interaction into the existing file when the pact file exists" do | ||
with_process(mock_service_process(mock_service_options)) do | ||
wait_for_mock_service_to_start(faraday, admin_header) | ||
expect_successful_request(faraday, :get, "/", nil, admin_header) | ||
expect_successful_request(faraday, :post, "/interactions", second_interaction.to_json, interaction_headers) | ||
expect_successful_request(faraday, :get, "/another-test") | ||
expect_successful_request(faraday, :get, "/interactions/verification", nil, admin_header) | ||
expect_successful_request(faraday, :post, "/pact", pact_details.to_json, admin_header) | ||
expect(pact_hash[:interactions].size).to eq 2 | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
require "bundler/setup" | ||
require "support/stuff" | ||
|
||
RSpec.configure do |config| | ||
config.example_status_persistence_file_path = ".rspec_status" | ||
|
||
config.disable_monkey_patching! | ||
|
||
config.expect_with :rspec do |c| | ||
c.syntax = :expect | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
require 'openssl' | ||
|
||
LOCAL_PACKAGE_LOCATION = "tmp/pact.zip".freeze | ||
# Simulate a Windows environment on Mac by giving it an empty cert_store | ||
SSL_OPTIONS = {ca_file: 'cacert.pem', cert_store: OpenSSL::X509::Store.new}.freeze | ||
|
||
def windows? | ||
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil | ||
end | ||
|
||
def github_access_token | ||
ENV.fetch('GITHUB_ACCESS_TOKEN') | ||
end | ||
|
||
def get_latest_release_asset_url release_asset_name_regexp | ||
require 'octokit' | ||
stack = Faraday::RackBuilder.new do |builder| | ||
builder.response :logger do | logger | | ||
logger.filter(/(Authorization: )(.*)/,'\1[REMOVED]') | ||
def logger.debug *args; end | ||
end | ||
builder.use Octokit::Response::RaiseError | ||
builder.adapter Faraday.default_adapter | ||
end | ||
Octokit.middleware = stack | ||
|
||
repository_slug = 'pact-foundation/pact-ruby-standalone' | ||
|
||
client = Octokit::Client.new(access_token: github_access_token) | ||
client.connection_options[:ssl] = SSL_OPTIONS | ||
release = client.latest_release repository_slug | ||
release_assets = client.release_assets release.url | ||
zip = release_assets.find { | release_asset | release_asset.name =~ release_asset_name_regexp } | ||
zip.url | ||
end | ||
|
||
def download_release_asset url, file_path | ||
require 'faraday' | ||
|
||
faraday = Faraday.new(:url => url, :ssl => SSL_OPTIONS) do |faraday| | ||
faraday.adapter Faraday.default_adapter | ||
faraday.response :logger do | logger | | ||
logger.filter(/(Authorization: )(.*)/,'\1[REMOVED]') | ||
def logger.debug *args; end | ||
end | ||
end | ||
|
||
response = faraday.get do | request | | ||
request.headers['Accept'] = 'application/octet-stream' | ||
request.headers['Authorization'] = "token #{github_access_token}" | ||
end | ||
raise "Expected response status 302 but got #{response.status}" unless response.status == 302 | ||
|
||
faraday = Faraday.new(:url => response.headers['Location'], :ssl => SSL_OPTIONS) | ||
response = faraday.get | ||
raise "Error downloading release" unless response.status == 200 | ||
|
||
puts "Writing file #{file_path}" | ||
File.open(file_path, "wb") { |file| file << response.body } | ||
puts "Finished writing file #{file_path}" | ||
end | ||
|
||
def unzip_package path | ||
require 'zip' | ||
require 'pathname' | ||
|
||
puts "Unzipping #{path}" | ||
Zip::File.open(path) do |zip_file| | ||
zip_file.each do |entry| | ||
entry.extract(File.join("tmp", entry.name)) | ||
end | ||
end | ||
puts "Finished unzipping #{path}" | ||
end | ||
|
||
def build_process cmd_parts, cwd = nil | ||
require 'childprocess' | ||
logger = Logger.new($stdout) | ||
logger.level = Logger::INFO | ||
ChildProcess.logger = logger | ||
process = ChildProcess.build(*cmd_parts) | ||
process.cwd = cwd if cwd | ||
process.leader = true if windows? # not sure if we need this | ||
process.io.inherit! | ||
process | ||
end | ||
|
||
def mock_service_process options = {} | ||
port = options[:port] || "1235" | ||
cli_args = options[:cli_args] || [] | ||
if windows? | ||
build_process ["cmd.exe", "/c","pact-mock-service.bat", "service", "-p", port] + cli_args, "tmp/pact/bin" | ||
else | ||
# Manually downloaded and extracted, for local testing | ||
build_process ["./pact-mock-service", "service", "-p", port] + cli_args, "osx/pact/bin" | ||
end | ||
end | ||
|
||
def test_provider_process | ||
if windows? | ||
build_process ["cmd.exe", "/c","bundle", "exec", "rackup", "-p", "1236", "test/config.ru"] | ||
else | ||
build_process ["ruby", "-S", "bundle", "exec", "rackup", "-p", "1236", "test/config.ru"] | ||
end | ||
end | ||
|
||
def pact_verifier_command | ||
suffix = "verify #{File.absolute_path("test/pact.json")} --provider-base-url http://localhost:1236" | ||
if windows? | ||
"cd tmp/pact/bin && cmd.exe /c pact-provider-verifier.bat #{suffix}" | ||
else | ||
# Manually downloaded and extracted, for local testing | ||
"cd osx/pact/bin && ./pact-provider-verifier #{suffix}" | ||
end | ||
end | ||
|
||
def with_process process, clean_env = true | ||
if clean_env | ||
Bundler.with_clean_env do | ||
process.start | ||
end | ||
else | ||
process.start | ||
end | ||
yield | ||
ensure | ||
process.stop if process && process.alive? | ||
end | ||
|
||
def expect_successful_request faraday, http_method, path, body = nil, headers = {} | ||
response = faraday.send(http_method, path, body, headers) | ||
raise "#{response.status} #{response.body}" unless response.status == 200 | ||
response | ||
end | ||
|
||
def test_mock_service | ||
require 'faraday' | ||
require 'json' | ||
|
||
with_process(mock_service_process) do | ||
sleep 5 | ||
admin_header = {'X-Pact-Mock-Service' => 'true'} | ||
pact_details = {consumer: {name: 'Foo'}, provider: {name: 'bar'}, pact_dir: '.\pacts'} | ||
interaction = {description: "test", providerState: nil, request: {method: 'GET', path: '/test'}, response: {status: 200} } | ||
|
||
faraday = Faraday.new(:url => "http://localhost:1235") do |faraday| | ||
faraday.adapter Faraday.default_adapter | ||
faraday.response :logger do | logger | | ||
def logger.debug *args; end | ||
end | ||
end | ||
|
||
expect_successful_request(faraday, :get, "/", nil, admin_header) | ||
expect_successful_request(faraday, :post, "/interactions", interaction.to_json, {'X-Pact-Mock-Service' => 'true', 'Content-Type' => 'application/json'}) | ||
expect_successful_request(faraday, :get, "/test") | ||
expect_successful_request(faraday, :get, "/interactions/verification", nil, admin_header) | ||
expect_successful_request(faraday, :post, "/pact", pact_details.to_json, admin_header) | ||
end | ||
end | ||
|
||
def test_verifier | ||
require 'faraday' | ||
with_process(test_provider_process, false) do | ||
sleep 2 | ||
|
||
Bundler.with_clean_env do | ||
output = `#{pact_verifier_command}` | ||
puts output | ||
raise "pact-provider-verifier did not run as expected" unless output.include?("1 interaction, 0 failures") | ||
end | ||
end | ||
end | ||
|
||
def wait_for_mock_service_to_start faraday, admin_headers | ||
i = 0 | ||
while true | ||
begin | ||
faraday.get("/", nil, admin_headers) | ||
return true | ||
rescue Faraday::ConnectionFailed => e | ||
i += 1 | ||
sleep 1 | ||
retry if i < 15 | ||
raise e | ||
end | ||
end | ||
end |