pinch_hitter 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.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.log
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p327@pinch_hitter"
10
+
11
+
12
+ # First we attempt to load the desired environment directly from the environment
13
+ # file. This is very fast and efficient compared to running through the entire
14
+ # CLI and selector. If you want feedback on which environment was used then
15
+ # insert the word 'use' after --create as this triggers verbose mode.
16
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
17
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
18
+ then
19
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
20
+
21
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
22
+ then
23
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
24
+ fi
25
+ else
26
+ # If the environment file has not yet been created, use the RVM CLI to select.
27
+ if ! rvm --create "$environment_id"
28
+ then
29
+ echo "Failed to create RVM environment '${environment_id}'."
30
+ return 1
31
+ fi
32
+ fi
33
+
34
+
35
+ # If you use bundler, this might be useful to you:
36
+ if [[ -s Gemfile ]] && ! command -v bundle >/dev/null
37
+ then
38
+ printf "The rubygem 'bundler' is not installed. Installing it now.\n"
39
+ gem install bundler
40
+ fi
41
+ if [[ -s Gemfile ]] && command -v bundle
42
+ then
43
+ bundle install
44
+ fi
45
+
46
+ if [[ $- == *i* ]] # check for interactive shells
47
+ then
48
+ echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
49
+ else
50
+ echo "Using: $GEM_HOME" # don't use colors in interactive shells
51
+ fi
52
+
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - 1.8.7
data/Changelog ADDED
@@ -0,0 +1,2 @@
1
+ === Release 0.1 / 2013-1-20
2
+ Initial release of the gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pinch_hitter.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Steve Jackson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Pinch Hitter
2
+ Simple replay mock for web service testing
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ gem 'pinch_hitter'
9
+
10
+ And then execute:
11
+
12
+ $ bundle
13
+
14
+ Or install it yourself as:
15
+
16
+ $ gem install pinch_hitter
17
+
18
+ ## Usage
19
+
20
+ Any xml posted to the /store endpoint will be returned (FIFO) when a post to the /respond endpoint is made.
21
+
22
+ Start the service using rackup
23
+ rackup
24
+
25
+ See Rakefile for test options
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rake/testtask'
3
+ require 'cucumber'
4
+ require 'cucumber/rake/task'
5
+ require "bundler/gem_tasks"
6
+
7
+ Rake::TestTask.new(:unit) do |t|
8
+ t.libs << 'test'
9
+ t.pattern = 'test/**/test_*\.rb'
10
+ end
11
+
12
+ Cucumber::Rake::Task.new(:features) do |t|
13
+ t.profile = 'default'
14
+ end
15
+
16
+ desc 'Run all unit tests and features'
17
+ task :test => [:unit, :features]
18
+
19
+ task :default => :test
data/config.ru ADDED
@@ -0,0 +1,11 @@
1
+ libdir = File.dirname(__FILE__) + '/lib'
2
+ $LOAD_PATH.unshift libdir unless $LOAD_PATH.include? libdir
3
+
4
+ require 'pinch_hitter/service/replay_ws'
5
+ require 'logger'
6
+
7
+ class ::Logger; alias_method :write, :<<; end
8
+ logger = Logger.new('app.log')
9
+ use Rack::CommonLogger, logger
10
+
11
+ run PinchHitter::Service::ReplayWs
data/cucumber.yml ADDED
@@ -0,0 +1 @@
1
+ default: --no-source --color --format pretty
@@ -0,0 +1,77 @@
1
+ <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
2
+ <soapenv:Header></soapenv:Header>
3
+ <soapenv:Body>
4
+ <SubmitXmlResponse>
5
+ <SubmitXmlResult>
6
+ <CarStandardAvail_9 xmlns="">
7
+ <CarAvailDetail>
8
+ <Signature>0</Signature>
9
+ <DataQual>
10
+ <MktgTxtAry></MktgTxtAry>
11
+ <RateSepTextAry></RateSepTextAry>
12
+ <RefPt>GRAND FORKS MARK ANDREWS IN</RefPt>
13
+ <City>GFK</City>
14
+ <State>ND</State>
15
+ <Country>US</Country>
16
+ <DistUnit>M</DistUnit>
17
+ <RateTypeDesc>DAILY</RateTypeDesc>
18
+ <RateCatDesc> STND/PROM</RateCatDesc>
19
+ <Currency>USD</Currency>
20
+ <DecPos>2</DecPos>
21
+ <TruncDec>N</TruncDec>
22
+ <AltRateInd>5</AltRateInd>
23
+ <MoreCarsInd>N</MoreCarsInd>
24
+ <CarDetailAry>
25
+ <CarDetail>
26
+ <Vnd>ZI</Vnd>
27
+ <LocAffiliate>001</LocAffiliate>
28
+ <PrimeLocn>P</PrimeLocn>
29
+ <LinkInd>I</LinkInd>
30
+ <City>GFK</City>
31
+ <LocnCat>T</LocnCat>
32
+ <LocnExpansion></LocnExpansion>
33
+ <LocnNum>1</LocnNum>
34
+ <LocnCarRental>T</LocnCarRental>
35
+ <Dist></Dist>
36
+ <Dir>T</Dir>
37
+ <GeoLat></GeoLat>
38
+ <GeoLon></GeoLon>
39
+ <CarType>MVAR</CarType>
40
+ <YieldMgmt></YieldMgmt>
41
+ <Amt>10299</Amt>
42
+ <BaseRateAmt>10299</BaseRateAmt>
43
+ <DropChargeIncInd></DropChargeIncInd>
44
+ <UpsellInd></UpsellInd>
45
+ <RatePlcmtInd>3</RatePlcmtInd>
46
+ <RateType>D</RateType>
47
+ <RateGuar>G</RateGuar>
48
+ <AdditionalCharges></AdditionalCharges>
49
+ <AvailStatus>N</AvailStatus>
50
+ <MileRate>22</MileRate>
51
+ <Mile> 100</Mile>
52
+ <DropOffRestrictions>Y</DropOffRestrictions>
53
+ <RateCat>S</RateCat>
54
+ <MileageRestrictInd></MileageRestrictInd>
55
+ <FltInd></FltInd>
56
+ <CCInd></CCInd>
57
+ <Rate>2E</Rate>
58
+ <InclRateQual>
59
+ <RateDesc>DAILY PROMO</RateDesc>
60
+ <InclRate1></InclRate1>
61
+ <InclRate2></InclRate2>
62
+ <InclRate3></InclRate3>
63
+ <InclRate4></InclRate4>
64
+ <PrePayInd></PrePayInd>
65
+ <CarTypeDesc>FORD FREESTAR 4DR/7PS</CarTypeDesc>
66
+ <DropChargeAmt></DropChargeAmt>
67
+ <ApproxTotAmt>12762</ApproxTotAmt>
68
+ </InclRateQual>
69
+ </CarDetail>
70
+ </CarDetailAry>
71
+ </DataQual>
72
+ </CarAvailDetail>
73
+ </CarStandardAvail_9>
74
+ </SubmitXmlResult>
75
+ </SubmitXmlResponse>
76
+ </soapenv:Body>
77
+ </soapenv:Envelope>
@@ -0,0 +1,21 @@
1
+ { "glossary": {
2
+ "title": "example glossary",
3
+ "GlossDiv": {
4
+ "title": "S",
5
+ "GlossList": {
6
+ "GlossEntry": {
7
+ "ID": "SGML",
8
+ "SortAs": "SGML",
9
+ "GlossTerm": "Standard Generalized Markup Language",
10
+ "Acronym": "SGML",
11
+ "Abbrev": "ISO 8879:1986",
12
+ "GlossDef": {
13
+ "para": "A meta-markup language, used to create markup languages such as DocBook.",
14
+ "GlossSeeAlso": ["GML", "XML"]
15
+ },
16
+ "GlossSee": "markup"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,35 @@
1
+ Given /^I setup my replay service$/ do
2
+ mock.reset
3
+ end
4
+
5
+ Given /^I want a car rental$/ do
6
+ mock.prime '/car_rental', :car_rental
7
+ end
8
+
9
+ When /^I make a reservation$/ do
10
+ @response = app.post '/car_rental', ''
11
+ end
12
+
13
+ Then /^I see a car reservation$/ do
14
+ @response.body.to_s.should == messages.load(:car_rental).squish
15
+ end
16
+
17
+ Given /^I want a car rental with a "(.*?)" of "(.*?)"$/ do |tag, text|
18
+ mock.prime '/car_rental', :car_rental, tag => text
19
+ end
20
+
21
+ Then /^I see a car reservation with a "(.*?)" of "(.*?)"$/ do |tag, text|
22
+ @response.body.to_s.should == messages.load(:car_rental, { tag => text }).squish
23
+ end
24
+
25
+ Given /^I want to lookup a definition$/ do
26
+ mock.prime '/glossary', :glossary
27
+ end
28
+
29
+ When /^I query the glossary$/ do
30
+ @response = app.get "/glossary?term=SGML"
31
+ end
32
+
33
+ Then /^I see a definition$/ do
34
+ @response.body.to_s.should == messages.load(:glossary).squish
35
+ end
@@ -0,0 +1,28 @@
1
+ require 'rspec-expectations'
2
+ require 'pinch_hitter'
3
+ require 'net/http'
4
+
5
+ def app_host
6
+ '127.0.0.1'
7
+ end
8
+
9
+ def app_port
10
+ 9292
11
+ end
12
+
13
+ def app
14
+ @app ||= Net::HTTP.new app_host, app_port
15
+ end
16
+
17
+ def mock
18
+ @@mock ||= MockWebService.new app_host, app_port
19
+ end
20
+
21
+ def messages
22
+ mock.message_store
23
+ end
24
+
25
+ at_exit do
26
+ mock.stop_service
27
+ end
28
+
@@ -0,0 +1,10 @@
1
+ class MockWebService
2
+ include PinchHitter
3
+
4
+ def initialize(host, port)
5
+ self.start_service host, port
6
+ self.connect host, port
7
+ self.messages_directory = File.join(File.dirname('.'), 'features', 'messages')
8
+ end
9
+
10
+ end
@@ -0,0 +1,23 @@
1
+ Feature: Test WS replay
2
+ I want to test the ability to return a web service call on demand
3
+ As a tester trying to test the application
4
+ So that I can control my test data
5
+
6
+ Background:
7
+ Given I setup my replay service
8
+
9
+ Scenario: Simple replay
10
+ Given I want a car rental
11
+ When I make a reservation
12
+ Then I see a car reservation
13
+
14
+ Scenario: Replay with subsititution
15
+ Given I want a car rental with a "City" of "ATL"
16
+ When I make a reservation
17
+ Then I see a car reservation with a "City" of "ATL"
18
+
19
+ Scenario: Replay with json
20
+ Given I want to lookup a definition
21
+ When I query the glossary
22
+ Then I see a definition
23
+
@@ -0,0 +1,29 @@
1
+ require "pinch_hitter/version"
2
+ require "pinch_hitter/message/message_store"
3
+ require "pinch_hitter/service/runner"
4
+
5
+ module PinchHitter
6
+ include PinchHitter::Service::Runner
7
+ attr_accessor :message_store
8
+
9
+ def messages_directory=(dir)
10
+ self.message_store = PinchHitter::Message::MessageStore.new dir
11
+ end
12
+
13
+ def connect(host, port)
14
+ self.session = Net::HTTP.new host, port
15
+ end
16
+
17
+ def session=(session)
18
+ @session = session
19
+ end
20
+
21
+ def reset
22
+ @session.post '/reset', ''
23
+ end
24
+
25
+ def prime(endpoint, message, overrides={})
26
+ @session.post "/store?endpoint=#{endpoint}", message_store.load(message, overrides)
27
+ end
28
+
29
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def squish
3
+ self.gsub(/\n\s*/, '')
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'pinch_hitter/message/json'
2
+
3
+ module PinchHitter
4
+ module Message
5
+ module ContentType
6
+ include Json
7
+
8
+ def determine_content_type(message)
9
+ return "application/json" if valid_json? message
10
+ "text/xml"
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module PinchHitter
2
+ module Message
3
+ module Json
4
+ def json_message(file, overrides={})
5
+ json_file = load_json_file file
6
+ replace_json json_file, overrides
7
+ end
8
+
9
+ def valid_json?(json)
10
+ begin
11
+ JSON.parse json
12
+ return true
13
+ rescue
14
+ return false
15
+ end
16
+ end
17
+
18
+ private
19
+ def load_json_file(filename)
20
+ IO.read filename
21
+ end
22
+
23
+ def replace_json(content, overrides={})
24
+ return content if overrides.empty?
25
+ modified = child = parent = JSON.parse(content).clone
26
+ overrides.each do |key, value|
27
+
28
+ key.each do |part|
29
+ parent = child
30
+ child = parent.send "fetch", part
31
+ end
32
+ parent[key.last] = value
33
+ end
34
+ modified.to_s
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ require 'pinch_hitter/message/xml'
2
+ require 'pinch_hitter/message/json'
3
+ require 'pinch_hitter/message/content_type'
4
+ require 'pinch_hitter/core_ext/string'
5
+
6
+ module PinchHitter
7
+ module Message
8
+ class MessageStore
9
+ include Xml
10
+ include Json
11
+ include ContentType
12
+
13
+ attr_accessor :message_directory
14
+
15
+ def initialize(message_directory)
16
+ @message_directory = message_directory
17
+ end
18
+
19
+ def load(file, overrides={})
20
+ filename = find_filename file
21
+ if filename =~ /xml$/
22
+ xml_message filename, overrides
23
+ else
24
+ json_message filename, overrides
25
+ end
26
+ end
27
+
28
+ def find_filename(file)
29
+ Dir["#{message_directory}/#{file}*"].first
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require 'nokogiri'
2
+
3
+ module PinchHitter
4
+ module Message
5
+ module Xml
6
+ def xml_message(file, overrides={})
7
+ xml = load_xml_file(file)
8
+ overrides.each do |key, text|
9
+ replace_xml(xml, key, text)
10
+ end
11
+ xml.to_s
12
+ end
13
+
14
+ private
15
+ def load_xml_file(filename)
16
+ Nokogiri::XML File.open filename
17
+ end
18
+
19
+ def replace_xml(xml, key, text)
20
+ parts = key.split('@')
21
+ tag = find_node xml, parts.first
22
+
23
+ if parts.length == 1
24
+ #match text node
25
+ tag.content = text
26
+ else
27
+ #match attribute
28
+ tag[parts.last] = text
29
+ end
30
+ end
31
+
32
+ def find_node(xml, tag)
33
+ xml.at_xpath("//#{tag}", xml.collect_namespaces)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,61 @@
1
+ require 'bundler/setup'
2
+ require 'sinatra/base'
3
+ require 'nokogiri'
4
+ require 'json'
5
+
6
+ require 'pinch_hitter/service/response_queues'
7
+ require 'pinch_hitter/message/content_type'
8
+
9
+ module PinchHitter
10
+ module Service
11
+ class ReplayWs < Sinatra::Base
12
+ include PinchHitter::Message::ContentType
13
+
14
+ configure do
15
+ @@responses = ResponseQueues.new
16
+ #SOAP expects a mime_type of text/xml
17
+ mime_type :xml, "text/xml"
18
+ mime_type :json, "application/json"
19
+ end
20
+
21
+ post '/reset' do
22
+ @@responses.reset
23
+ 200
24
+ end
25
+
26
+ post '/store/*' do
27
+ store "/#{params[:splat].first}", request.body.read
28
+ 200
29
+ end
30
+
31
+ post '/store' do
32
+ store request["endpoint"], request.body.read
33
+ 200
34
+ end
35
+
36
+ post '/respond' do
37
+ respond nil
38
+ end
39
+
40
+ get '/*' do
41
+ respond params[:splat].first
42
+ end
43
+
44
+ post '/*' do
45
+ respond params[:splat].first
46
+ end
47
+
48
+ def store(endpoint='/', message=nil)
49
+ @@responses.store endpoint, message
50
+ end
51
+
52
+ def respond(endpoint='/')
53
+ message = @@responses.retrieve endpoint
54
+ content_type determine_content_type message
55
+ puts "No message found for #{endpoint}" unless message
56
+ message
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,29 @@
1
+ module PinchHitter
2
+ module Service
3
+ class ResponseQueues
4
+
5
+ def reset
6
+ @responses = {}
7
+ end
8
+
9
+ def responses
10
+ @responses ||= {}
11
+ end
12
+
13
+ def store(endpoint, body)
14
+ endpoint_responses(endpoint) << body.gsub(/\n\s*/, '')
15
+ end
16
+
17
+ def retrieve(endpoint='/')
18
+ endpoint_responses(endpoint).shift
19
+ end
20
+
21
+ def endpoint_responses(endpoint='/')
22
+ endpoint = "/#{endpoint}" unless endpoint =~ /^\//
23
+ queue = responses[endpoint] || []
24
+ responses[endpoint] = queue
25
+ queue
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ require 'rack'
2
+ require 'webrick'
3
+ require 'pinch_hitter/service/replay_ws'
4
+
5
+ module PinchHitter
6
+ module Service
7
+ module Runner
8
+
9
+ def start_service(host, port, timeout=10)
10
+ Thread.abort_on_exception = true
11
+ @app = PinchHitter::Service::ReplayWs.new
12
+ @replay_service = Thread.new do
13
+ Rack::Handler::WEBrick.run @app, :Host => host, :Port => port
14
+ end
15
+ wait_for_replay(timeout)
16
+ end
17
+
18
+ def stop_service
19
+ @replay_service.kill
20
+ end
21
+
22
+ private
23
+ def wait_for_replay(timeout)
24
+ end_time = ::Time.now + timeout
25
+ until ::Time.now > end_time
26
+ return if @replay_service.stop?
27
+ sleep 0.25
28
+ end
29
+ raise 'Timed out waiting for replay service to start'
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module PinchHitter
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pinch_hitter/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "pinch_hitter"
8
+ gem.version = PinchHitter::VERSION
9
+ gem.authors = ["Steve Jackson"]
10
+ gem.email = ["steve.jackson@leandogsoftware.com"]
11
+ gem.description = %q{A simple web service that returns primed responses in FIFO order}
12
+ gem.summary = %q{Test utility for mocking out external web responses}
13
+ gem.homepage = "https://github.com/stevenjackson/pinch_hitter"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'sinatra', '>= 1.3.3'
21
+ gem.add_dependency 'nokogiri', '>= 1.5.6'
22
+ gem.add_dependency 'json', '>= 1.7.6'
23
+
24
+ gem.add_development_dependency 'minitest', '>= 4.3.3'
25
+ gem.add_development_dependency 'rack-test', '>= 0.6.2'
26
+ gem.add_development_dependency 'rake', '>= 10.0.3'
27
+ gem.add_development_dependency 'rspec', '>= 2.12.0'
28
+ gem.add_development_dependency 'cucumber', '>= 1.2.1'
29
+ end
@@ -0,0 +1,41 @@
1
+
2
+ ENV['RACK_ENV'] = 'test'
3
+
4
+ require 'minitest/autorun'
5
+
6
+ class TestJsonMessage < MiniTest::Unit::TestCase
7
+
8
+ def setup
9
+ File.open(filename, 'w') {|f| f.write(our_message) }
10
+ @test = Object.new
11
+ @test.extend(PinchHitter::Message::Json)
12
+ end
13
+
14
+ def teardown
15
+ File.delete filename
16
+ end
17
+
18
+ def filename
19
+ "minitest_message.json"
20
+ end
21
+
22
+ def our_message
23
+ %Q{{"menu": {
24
+ "id": "file",
25
+ "value": "File",
26
+ "popup": {
27
+ "menuitem": "OpenDoc()"
28
+ }
29
+ }}
30
+ }
31
+ end
32
+
33
+ def test_message_no_overrides
34
+ assert_equal our_message, @test.json_message(filename)
35
+ end
36
+
37
+ def test_message_with_overrides
38
+ json = @test.json_message(filename, {["menu", "popup", "menuitem"] => 'WhatsUpDoc?' })
39
+ assert json.include? "WhatsUpDoc?"
40
+ end
41
+ end
@@ -0,0 +1,67 @@
1
+
2
+ ENV['RACK_ENV'] = 'test'
3
+
4
+ require 'minitest/autorun'
5
+ require 'pinch_hitter/message/message_store'
6
+ class TestMessage < MiniTest::Unit::TestCase
7
+
8
+ def setup
9
+ File.open("#{xml_filename}.xml", 'w') {|f| f.write(xml_message) }
10
+
11
+ File.open("#{json_file}", 'w') { |f| f.write(json_message) }
12
+
13
+ @messages = PinchHitter::Message::MessageStore.new File.dirname('.')
14
+ end
15
+
16
+ def teardown
17
+ File.delete "#{xml_filename}.xml"
18
+ File.delete "#{json_file}"
19
+ end
20
+
21
+ def xml_filename
22
+ "minitest_xml"
23
+ end
24
+
25
+ def json_file
26
+ "minitest_json"
27
+ end
28
+
29
+ def xml_message
30
+ %Q{<?xml version="1.0" encoding="UTF-8"?>
31
+ <Body/>
32
+ }
33
+ end
34
+
35
+ def json_message
36
+ %Q{{
37
+ "one": "two",
38
+ "A": "B" }
39
+ }
40
+ end
41
+
42
+ def test_setting_dir
43
+ @messages.message_directory = "/foo"
44
+ assert_equal "/foo", @messages.message_directory
45
+ end
46
+
47
+ def test_loads_xml
48
+ assert_equal xml_message, @messages.load(xml_filename.to_sym)
49
+ end
50
+
51
+ def test_loads_json
52
+ assert_equal json_message, @messages.load(json_file.to_sym)
53
+ end
54
+
55
+ def test_message_no_whitespace
56
+ squish = %Q{<?xml version="1.0" encoding="UTF-8"?><Body/>}
57
+ assert_equal squish, @messages.load(xml_filename.to_sym).squish
58
+ end
59
+
60
+ def test_content_type_defaults_to_xml
61
+ assert_equal "text/xml", @messages.determine_content_type("")
62
+ end
63
+
64
+ def test_content_type_determines_json
65
+ assert_equal "application/json", @messages.determine_content_type(json_message)
66
+ end
67
+ end
@@ -0,0 +1,55 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'pinch_hitter/service/replay_ws'
4
+ require 'pinch_hitter'
5
+ require 'minitest/autorun'
6
+ require 'rack/test'
7
+
8
+ class TestPinchHitter < MiniTest::Unit::TestCase
9
+ include Rack::Test::Methods
10
+
11
+ def setup
12
+ @test = Object.new
13
+ @test.extend(PinchHitter)
14
+ @test.session=session
15
+ @test.messages_directory = File.dirname('.')
16
+ File.open(message_file, 'w') {|f| f.write(message_content) }
17
+ end
18
+
19
+ def teardown
20
+ File.delete message_file
21
+ end
22
+
23
+ def message_file
24
+ "fizzbuzz"
25
+ end
26
+
27
+ def message_content
28
+ "{fizzbuzz}"
29
+ end
30
+
31
+ def app
32
+ PinchHitter::Service::ReplayWs
33
+ end
34
+
35
+ def session
36
+ @session ||= Rack::Test::Session.new(Rack::MockSession.new(app))
37
+ end
38
+
39
+ def test_message_store_init
40
+ @test.messages_directory = "/bar"
41
+ assert_equal "/bar", @test.message_store.message_directory
42
+ end
43
+
44
+ def test_service_reset
45
+ @test.reset
46
+ assert_equal '/reset', session.last_request.path_info
47
+ end
48
+
49
+ def test_prime
50
+ @test.prime '/foo', message_file.to_sym
51
+ session.get '/foo'
52
+ assert_equal message_content, session.last_response.body
53
+ end
54
+
55
+ end
@@ -0,0 +1,113 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'pinch_hitter/service/replay_ws'
4
+ require 'minitest/autorun'
5
+ require 'rack/test'
6
+ require 'nokogiri'
7
+
8
+ class TestService < MiniTest::Unit::TestCase
9
+ include Rack::Test::Methods
10
+
11
+ def app
12
+ PinchHitter::Service::ReplayWs
13
+ end
14
+
15
+ def test_retrieve
16
+ post "/store", xml_message
17
+ post "/respond", ''
18
+
19
+ assert_received xml_message
20
+ assert_equal 200, last_response.status
21
+ end
22
+
23
+
24
+ def test_result_should_be_xml
25
+ post "/store", xml_message
26
+ post "/respond", ''
27
+
28
+ assert_equal 'text/xml;charset=utf-8', last_response.content_type
29
+ end
30
+
31
+ def test_result_should_be_json
32
+ post "/store", yml_message
33
+ post "/respond", ''
34
+
35
+ assert_equal 'application/json;charset=utf-8', last_response.content_type
36
+ end
37
+
38
+ def test_reset
39
+ post "/reset", ''
40
+ assert_equal 200, last_response.status
41
+ post "/respond", ''
42
+ assert_equal 200, last_response.status
43
+ assert_equal '', last_response.body
44
+ end
45
+
46
+ def test_store_with_params
47
+ post '/store?endpoint=test2/subtest', yml_message
48
+ post '/test2/subtest', ''
49
+
50
+ assert_received yml_message
51
+ end
52
+
53
+ def test_store_as_subendpoint
54
+ post '/store/test2/subtest', yml_message
55
+ post '/test2/subtest', ''
56
+
57
+ assert_received yml_message
58
+ end
59
+
60
+
61
+ def test_multi_endpoints
62
+ post '/store/endpoint1', xml_message
63
+ post '/store/endpoint2', yml_message
64
+
65
+ post '/endpoint2', ''
66
+ assert_received yml_message
67
+
68
+ post '/endpoint1', ''
69
+ assert_received xml_message
70
+ end
71
+
72
+ def test_multi_endpoint_queues
73
+ post '/store/endpoint1', xml_message
74
+ post '/store/endpoint1', xml_message
75
+ post '/store/endpoint2', yml_message
76
+ post '/store/endpoint2', yml_message
77
+ post '/store/endpoint2', yml_message
78
+
79
+ post '/endpoint2', ''
80
+ assert_received yml_message
81
+ post '/endpoint1', ''
82
+ assert_received xml_message
83
+ post '/endpoint1', ''
84
+ assert_received xml_message
85
+ post '/endpoint2', ''
86
+ assert_received yml_message
87
+ post '/endpoint2', ''
88
+ assert_received yml_message
89
+ #Out of queue
90
+ post '/endpoint1', ''
91
+ assert_equal '', last_response.body
92
+ end
93
+
94
+ def xml_message
95
+ message = %Q{<?xml version="1.0" encoding="UTF-8"?>
96
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:replay="http://www.leandog.com/replay">
97
+ <env:Body>
98
+ <replay:Response>BARK!</replay:Response>
99
+ </env:Body>
100
+ </env:Envelope>}
101
+ end
102
+
103
+ def yml_message
104
+ %Q~{"menu": {
105
+ "id": "file",
106
+ "value": "File"
107
+ }}~
108
+ end
109
+
110
+ def assert_received(message)
111
+ assert_equal message.gsub(/\n\s*/, ''), last_response.body.strip
112
+ end
113
+ end
@@ -0,0 +1,52 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'minitest/autorun'
4
+
5
+ class TestXmlMessage < MiniTest::Unit::TestCase
6
+
7
+ def setup
8
+ File.open(filename, 'w') {|f| f.write(our_message) }
9
+ @test = Object.new
10
+ @test.extend(PinchHitter::Message::Xml)
11
+ end
12
+
13
+ def teardown
14
+ File.delete filename
15
+ end
16
+
17
+ def filename
18
+ "minitest_message.xml"
19
+ end
20
+
21
+ def our_message
22
+ %Q{<?xml version="1.0" encoding="UTF-8"?>
23
+ <wrapper>
24
+ <Body xmlns:ns="http://www.abc.org/OTA/2003/05">
25
+ <node>text</node>
26
+ <withattrib attrib="value"/>
27
+ <ns:testnode>text</ns:testnode>
28
+ </Body>
29
+ </wrapper>
30
+ }
31
+ end
32
+
33
+ def test_message_no_overrides
34
+ assert_equal our_message, @test.xml_message(filename)
35
+ end
36
+
37
+ def test_message_tag_override
38
+ xml = @test.xml_message(filename, {"node" => "newtext"})
39
+ assert xml.include? "<node>newtext</node>"
40
+ end
41
+
42
+ def test_message_tag_override_attrib
43
+ xml = @test.xml_message(filename,
44
+ {"withattrib@attrib" => "BetterValue"})
45
+ assert xml.include? "<withattrib attrib=\"BetterValue\""
46
+ end
47
+
48
+ def test_message_tag_override_with_namespace
49
+ xml = @test.xml_message(filename, {"ns:testnode" => 'newValue'})
50
+ assert xml.include? "<ns:testnode>newValue</ns:testnode>"
51
+ end
52
+ end
metadata ADDED
@@ -0,0 +1,222 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pinch_hitter
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Steve Jackson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sinatra
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.3.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.5.6
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.5.6
46
+ - !ruby/object:Gem::Dependency
47
+ name: json
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 1.7.6
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.7.6
62
+ - !ruby/object:Gem::Dependency
63
+ name: minitest
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 4.3.3
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 4.3.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: rack-test
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.6.2
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.6.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: rake
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 10.0.3
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 10.0.3
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: 2.12.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: 2.12.0
126
+ - !ruby/object:Gem::Dependency
127
+ name: cucumber
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: 1.2.1
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: 1.2.1
142
+ description: A simple web service that returns primed responses in FIFO order
143
+ email:
144
+ - steve.jackson@leandogsoftware.com
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - .gitignore
150
+ - .rvmrc
151
+ - .travis.yml
152
+ - Changelog
153
+ - Gemfile
154
+ - LICENSE
155
+ - README.md
156
+ - Rakefile
157
+ - config.ru
158
+ - cucumber.yml
159
+ - features/messages/car_rental.xml
160
+ - features/messages/glossary.json
161
+ - features/step_definitions/test_replay_steps.rb
162
+ - features/support/env.rb
163
+ - features/support/mock_web_service.rb
164
+ - features/test_replay.feature
165
+ - lib/pinch_hitter.rb
166
+ - lib/pinch_hitter/core_ext/string.rb
167
+ - lib/pinch_hitter/message/content_type.rb
168
+ - lib/pinch_hitter/message/json.rb
169
+ - lib/pinch_hitter/message/message_store.rb
170
+ - lib/pinch_hitter/message/xml.rb
171
+ - lib/pinch_hitter/service/replay_ws.rb
172
+ - lib/pinch_hitter/service/response_queues.rb
173
+ - lib/pinch_hitter/service/runner.rb
174
+ - lib/pinch_hitter/version.rb
175
+ - pinch_hitter.gemspec
176
+ - test/test_json_message.rb
177
+ - test/test_message.rb
178
+ - test/test_pinch_hitter.rb
179
+ - test/test_service.rb
180
+ - test/test_xml_message.rb
181
+ homepage: https://github.com/stevenjackson/pinch_hitter
182
+ licenses: []
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ none: false
189
+ requirements:
190
+ - - ! '>='
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ segments:
194
+ - 0
195
+ hash: -4118053142123846714
196
+ required_rubygems_version: !ruby/object:Gem::Requirement
197
+ none: false
198
+ requirements:
199
+ - - ! '>='
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ segments:
203
+ - 0
204
+ hash: -4118053142123846714
205
+ requirements: []
206
+ rubyforge_project:
207
+ rubygems_version: 1.8.24
208
+ signing_key:
209
+ specification_version: 3
210
+ summary: Test utility for mocking out external web responses
211
+ test_files:
212
+ - features/messages/car_rental.xml
213
+ - features/messages/glossary.json
214
+ - features/step_definitions/test_replay_steps.rb
215
+ - features/support/env.rb
216
+ - features/support/mock_web_service.rb
217
+ - features/test_replay.feature
218
+ - test/test_json_message.rb
219
+ - test/test_message.rb
220
+ - test/test_pinch_hitter.rb
221
+ - test/test_service.rb
222
+ - test/test_xml_message.rb