Skip to content

Commit

Permalink
feat: refactor setup and spec code
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Feb 21, 2018
1 parent 5fbc230 commit b05528f
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 393 deletions.
12 changes: 6 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ PLATFORMS
ruby

DEPENDENCIES
childprocess
octokit
rack
rake
rspec
rubyzip
childprocess (~> 0.7)
octokit (~> 4.7)
rack (~> 2.0)
rake (~> 12.0)
rspec (~> 3.7)
rubyzip (~> 1.2)

BUNDLED WITH
1.15.4
216 changes: 6 additions & 210 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,223 +1,19 @@
require 'openssl'

require 'rspec/core/rake_task'
require './tasks/support'

RSpec::Core::RakeTask.new(:spec)

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
if windows?
build_process ["cmd.exe", "/c","pact-mock-service.bat", "service", "-p", "1235"], "tmp/pact/bin"
else
# Manually downloaded and extracted, for local testing
build_process ["./pact-mock-service", "service", "-p", "1235"], "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

desc 'Download latest pact-X.X.X-win32.zip'
task :download_latest_release do |t, args |
begin
require 'fileutils'
FileUtils.rm_rf "tmp"
FileUtils.mkdir_p "tmp"

url = get_latest_release_asset_url /win.*zip/
download_release_asset url, LOCAL_PACKAGE_LOCATION

rescue StandardError => e
# Appveyor doesn't display stderr in a helpful way, need to manually print error
puts "#{e.class} #{e.message} #{e.backtrace.join("\n")}"
raise e
end
include Pact::StandaloneWindowsTest::Setup
download_latest_release
end

desc 'Unzip package'
task :unzip_package do
unzip_package LOCAL_PACKAGE_LOCATION
end

desc 'Test windows batch file'
task :test_mock_service do
begin
puts "Testing pact-mock-service"
test_mock_service
rescue StandardError => e
# Appveyor doesn't display stderr in a helpful way, need to manually print error
puts "#{e.class} #{e.message} #{e.backtrace.join("\n")}"
raise e
end
end

desc 'Test windows pact verifier batch file'
task :test_verifier do
begin
puts "Testing pact-provider-verifier"
test_verifier
rescue StandardError => e
# Appveyor doesn't display stderr in a helpful way, need to manually print error
puts "#{e.class} #{e.message} #{e.backtrace.join("\n")}"
raise e
end
include Pact::StandaloneWindowsTest::Setup
unzip_package
end

task :test => [:test_mock_service, :test_verifier] # :test_verifier disabled for now, don't have time to debug why it isn't working
task :default => [:download_latest_release, :unzip_package, :test]
task :default => [:download_latest_release, :unzip_package, :spec]
11 changes: 6 additions & 5 deletions spec/mock_service_with_merge_spec.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require 'faraday'
require 'json'
RSpec.describe "running the mock service with the pact-file-mode merge" do

PACT_FILE_PATH = "./pacts/foo-bar.json"
RSpec.describe "Running the mock service with --pact-file-mode merge" do

let(:pact_file_path) { "./pacts/foo-bar.json" }

let(:faraday) do
Faraday.new(:url => "http://localhost:1235") do |faraday|
Expand Down Expand Up @@ -38,19 +39,19 @@ def logger.debug *args; end
end

let(:pact_hash) do
JSON.parse(File.read(PACT_FILE_PATH), symbolize_names: true)
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
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))
expect(File.exists?(pact_file_path))
end
end

Expand Down
15 changes: 15 additions & 0 deletions spec/provider_verifier_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'faraday'

RSpec.describe "The pact provider verifier" do
it "verifies the given pact against a running service" do
with_process(test_provider_process, false) do
sleep 2

Bundler.with_clean_env do
output = `#{pact_verifier_command}`
puts output
expect(output).to include "1 interaction, 0 failures"
end
end
end
end
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

config.disable_monkey_patching!

config.include Pact::StandaloneWindowsTest::TestHelpers

config.expect_with :rspec do |c|
c.syntax = :expect
end
Expand Down
Loading

0 comments on commit b05528f

Please sign in to comment.