kerryb-fakettp 0.1.2 → 0.2
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/README.html +9 -4
- data/lib/fakettp.rb +3 -30
- data/lib/fakettp/commands/fakettp_command.rb +2 -1
- data/lib/fakettp/config.ru +1 -1
- data/lib/fakettp/controller.rb +42 -0
- data/lib/fakettp/error.rb +23 -0
- data/lib/fakettp/expectation.rb +56 -0
- data/lib/fakettp/expectation_helper.rb +13 -0
- data/lib/fakettp/simulator.rb +33 -0
- metadata +22 -5
- data/lib/fakettp/Rakefile.rb +0 -7
- data/lib/fakettp/helper.rb +0 -76
data/README.html
CHANGED
@@ -47,7 +47,7 @@
|
|
47
47
|
end
|
48
48
|
</code></pre>
|
49
49
|
<p>The label on the first line is used in error reporting.</p>
|
50
|
-
<p>The expectation code has access to the underlying Sinatra
|
50
|
+
<p>The expectation code has access to the underlying Sinatra request and response objects etc, as well as <a href="http://rspec.info">RSpec</a> matchers.</p>
|
51
51
|
<h3>Verifying</h3>
|
52
52
|
<p>To verify that all expectations have been met, make an <span class="caps">HTTP</span> <span class="caps">GET</span> request to <code>http://fakettp.local/verify</code>.</p>
|
53
53
|
<p>If all is well, the response will be a <em>200 OK</em> with a body of ‘OK’. Otherwise the status will be <em>400 Bad Request</em>, with a list of failures in the body. The failure messages include the complete details of the unexpected request that was received, to assist debugging.</p>
|
@@ -55,6 +55,11 @@
|
|
55
55
|
<p>To have FakeTTP respond to multiple hostnames, create the appropriate hosts entries. If you’re using name-based virtual hosts in Apache, add a <em>ServerAlias</em> entry to the virtual host config, under the <em>ServerName</em> line, eg:</p>
|
56
56
|
<p><code>ServerAlias foo.com bar.com</code></p>
|
57
57
|
<h2>Change log</h2>
|
58
|
+
<p>0.2 (14 Mar 2009)</p>
|
59
|
+
<ul>
|
60
|
+
<li>Complete rewrite, with tests and classes and stuff this time.</li>
|
61
|
+
</ul>
|
62
|
+
<p>If you get an ‘unexpected return’ error, remove the return statement from your expectation, and just put the return value on the last line of the <em>expect</em> block.</p>
|
58
63
|
<p>0.1.2 (13 Feb 2009)</p>
|
59
64
|
<ul>
|
60
65
|
<li>Make sure <span class="caps">README</span>.html appears in generated gem</li>
|
@@ -69,10 +74,8 @@
|
|
69
74
|
</ul>
|
70
75
|
<h2>To Do</h2>
|
71
76
|
<ul>
|
72
|
-
<li>Increase test coverage</li>
|
73
|
-
<li>Refactor to be OO rather than dumping everything in Kernel</li>
|
74
77
|
<li>Add examples</li>
|
75
|
-
<li>Only respond to control requests (reset/expect/verify) on main hostname
|
78
|
+
<li>Only respond to control requests (reset/expect/verify) on main hostname</li>
|
76
79
|
<li>Make control requests RESTful?</li>
|
77
80
|
<li>Make main hostname configurable?</li>
|
78
81
|
<li>Show label in verification error for expected requests that weren’t received</li>
|
@@ -80,4 +83,6 @@
|
|
80
83
|
<li>Allow more flexibility in request ordering</li>
|
81
84
|
<li>Allow user-specific helper files in installation dir</li>
|
82
85
|
<li>Check install/run behaviour when development dependencies are not installed</li>
|
86
|
+
<li>Provide Ruby <span class="caps">API</span> to set expectations etc</li>
|
87
|
+
<li>Return the expected content type even if expectation fails</li>
|
83
88
|
</ul>
|
data/lib/fakettp.rb
CHANGED
@@ -1,30 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require 'fakettp/helper'
|
5
|
-
require 'fakettp/commands/fakettp_command'
|
6
|
-
|
7
|
-
Sinatra::Default.set :run, false
|
8
|
-
Sinatra::Default.set :environment, ENV['RACK_ENV']
|
9
|
-
|
10
|
-
error do
|
11
|
-
request.env['sinatra.error'].inspect
|
12
|
-
end
|
13
|
-
|
14
|
-
post '/expect' do
|
15
|
-
set_expectation
|
16
|
-
end
|
17
|
-
|
18
|
-
post '/reset' do
|
19
|
-
reset_expectations
|
20
|
-
end
|
21
|
-
|
22
|
-
get '/verify' do
|
23
|
-
verify_expectations
|
24
|
-
end
|
25
|
-
|
26
|
-
[:get, :post, :put, :delete, :head].each do |method|
|
27
|
-
send method, '/**' do
|
28
|
-
run_expectation
|
29
|
-
end
|
30
|
-
end
|
1
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
2
|
+
require 'fakettp/controller'
|
3
|
+
require 'fakettp/commands/fakettp_command'
|
data/lib/fakettp/config.ru
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'spec'
|
3
|
+
Sinatra::Default.set :run, false
|
4
|
+
Sinatra::Default.set :environment, ENV['RACK_ENV']
|
5
|
+
|
6
|
+
require 'fakettp/expectation_helper'
|
7
|
+
require 'fakettp/simulator'
|
8
|
+
require 'fakettp/expectation'
|
9
|
+
|
10
|
+
include Fakettp::ExpectationHelper
|
11
|
+
|
12
|
+
post '/expect' do
|
13
|
+
Fakettp::Simulator << request.body.read
|
14
|
+
content_type 'text/plain'
|
15
|
+
"Expect OK\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
post '/reset' do
|
19
|
+
Fakettp::Simulator.reset
|
20
|
+
content_type 'text/plain'
|
21
|
+
"Reset OK\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
get '/verify' do
|
25
|
+
content_type 'text/plain'
|
26
|
+
if Fakettp::Simulator.verify
|
27
|
+
"Verify OK\n"
|
28
|
+
else
|
29
|
+
throw :halt, [500, Fakettp::Simulator.list_errors]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
[:get, :post, :put, :delete, :head].each do |method|
|
34
|
+
send method, '/**' do
|
35
|
+
begin
|
36
|
+
Fakettp::Simulator.handle_request binding
|
37
|
+
rescue Fakettp::Expectation::Error => e
|
38
|
+
content_type 'text/plain'
|
39
|
+
throw :halt, [500, "Simulator received mismatched request\n"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fakettp
|
2
|
+
class Error
|
3
|
+
ERROR_FILE = File.join FAKETTP_BASE, 'tmp', 'errors'
|
4
|
+
|
5
|
+
def self.clear_all
|
6
|
+
FileUtils.rm_rf ERROR_FILE
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.<< message
|
10
|
+
File.open ERROR_FILE, 'a' do |f|
|
11
|
+
f.puts message
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.empty?
|
16
|
+
!File.exists? ERROR_FILE
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.list
|
20
|
+
empty? ? '' : File.read(ERROR_FILE)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Fakettp
|
2
|
+
class Expectation
|
3
|
+
class Error < Exception; end
|
4
|
+
|
5
|
+
EXPECTATION_DIR = File.join FAKETTP_BASE, 'tmp', 'expectations'
|
6
|
+
|
7
|
+
def initialize contents
|
8
|
+
@contents = contents
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute binding
|
12
|
+
eval @contents, binding
|
13
|
+
# TODO: Include context of expectation file
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.clear_all
|
17
|
+
FileUtils.rm_rf Dir.glob(File.join(EXPECTATION_DIR, '*'))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.empty?
|
21
|
+
files.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.<< expectation
|
25
|
+
File.open next_file_to_create, 'w' do |f|
|
26
|
+
f.write expectation
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.next
|
31
|
+
file = next_file_to_read
|
32
|
+
contents = File.read file
|
33
|
+
FileUtils.rm file
|
34
|
+
Expectation.new contents
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def self.next_file_to_create
|
40
|
+
name = (files.last.to_i + 1).to_s
|
41
|
+
File.join EXPECTATION_DIR, name
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.next_file_to_read
|
45
|
+
name = files.first
|
46
|
+
raise Error.new('Received unexpected request') unless name
|
47
|
+
File.join EXPECTATION_DIR, name
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.files
|
51
|
+
Dir.entries(EXPECTATION_DIR) - ['.', '..']
|
52
|
+
end
|
53
|
+
|
54
|
+
private_class_method :next_file_to_create, :next_file_to_read, :files
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'fakettp/expectation'
|
2
|
+
require 'fakettp/error'
|
3
|
+
|
4
|
+
module Fakettp
|
5
|
+
class Simulator
|
6
|
+
def self.reset
|
7
|
+
Expectation.clear_all
|
8
|
+
Error.clear_all
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.verify
|
12
|
+
Error << 'Expected request not received' unless Expectation.empty?
|
13
|
+
Error.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.<< expectation
|
17
|
+
Expectation << expectation
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.handle_request binding
|
21
|
+
begin
|
22
|
+
Expectation.next.execute binding
|
23
|
+
rescue Fakettp::Expectation::Error => e
|
24
|
+
Error << e.message
|
25
|
+
raise e
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.list_errors
|
30
|
+
Error.list
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kerryb-fakettp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: "0.2"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kerry Buckley
|
@@ -9,20 +9,22 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-03-14 00:00:00 -07:00
|
13
13
|
default_executable: fakettp
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sinatra
|
17
|
+
type: :runtime
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
20
21
|
- - ">="
|
21
22
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
23
|
+
version: 0.9.1
|
23
24
|
version:
|
24
25
|
- !ruby/object:Gem::Dependency
|
25
26
|
name: rspec
|
27
|
+
type: :development
|
26
28
|
version_requirement:
|
27
29
|
version_requirements: !ruby/object:Gem::Requirement
|
28
30
|
requirements:
|
@@ -30,8 +32,19 @@ dependencies:
|
|
30
32
|
- !ruby/object:Gem::Version
|
31
33
|
version: 1.1.12
|
32
34
|
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: spicycode-rcov
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.8.0
|
44
|
+
version:
|
33
45
|
- !ruby/object:Gem::Dependency
|
34
46
|
name: cucumber
|
47
|
+
type: :development
|
35
48
|
version_requirement:
|
36
49
|
version_requirements: !ruby/object:Gem::Requirement
|
37
50
|
requirements:
|
@@ -41,6 +54,7 @@ dependencies:
|
|
41
54
|
version:
|
42
55
|
- !ruby/object:Gem::Dependency
|
43
56
|
name: RedCloth
|
57
|
+
type: :development
|
44
58
|
version_requirement:
|
45
59
|
version_requirements: !ruby/object:Gem::Requirement
|
46
60
|
requirements:
|
@@ -61,8 +75,11 @@ files:
|
|
61
75
|
- lib/fakettp/commands
|
62
76
|
- lib/fakettp/commands/fakettp_command.rb
|
63
77
|
- lib/fakettp/config.ru
|
64
|
-
- lib/fakettp/
|
65
|
-
- lib/fakettp/
|
78
|
+
- lib/fakettp/controller.rb
|
79
|
+
- lib/fakettp/error.rb
|
80
|
+
- lib/fakettp/expectation.rb
|
81
|
+
- lib/fakettp/expectation_helper.rb
|
82
|
+
- lib/fakettp/simulator.rb
|
66
83
|
- lib/fakettp.rb
|
67
84
|
- bin/fakettp
|
68
85
|
- README.html
|
data/lib/fakettp/Rakefile.rb
DELETED
data/lib/fakettp/helper.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'spec'
|
2
|
-
include Spec::Matchers
|
3
|
-
|
4
|
-
TMP_DIR = File.join FAKETTP_BASE, 'tmp'
|
5
|
-
ERROR_FILE = File.join TMP_DIR, 'errors'
|
6
|
-
EXPECTATION_DIR = File.join TMP_DIR, 'expectations'
|
7
|
-
|
8
|
-
def expect label
|
9
|
-
begin
|
10
|
-
yield
|
11
|
-
rescue Exception => e
|
12
|
-
File.open(ERROR_FILE, 'a') do |f|
|
13
|
-
f.puts "\nError in #{label}: #{e.message}\n\nRequest: #{request.inspect}"
|
14
|
-
end
|
15
|
-
throw :halt, [500, "Simulator received mismatched request\n"]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# Note: client *must* send a Content-Type header of 'text/plain'. Probably.
|
20
|
-
def set_expectation
|
21
|
-
content_type 'text/plain'
|
22
|
-
expectation = request.body.read
|
23
|
-
File.open(next_expectation_file, 'w') do |f|
|
24
|
-
f.write expectation
|
25
|
-
end
|
26
|
-
"Expect OK\n"
|
27
|
-
end
|
28
|
-
|
29
|
-
def run_expectation
|
30
|
-
content_type 'text/plain'
|
31
|
-
files = Dir.glob(EXPECTATION_DIR + '/*.rb').sort
|
32
|
-
if files.empty?
|
33
|
-
File.open(ERROR_FILE, 'a') do |f|
|
34
|
-
f.puts "\nReceived unexpected request: #{request.inspect}"
|
35
|
-
end
|
36
|
-
throw :halt, [500, "Simulator received unexpected request\n"]
|
37
|
-
end
|
38
|
-
expectation = File.read files.first
|
39
|
-
FileUtils.rm files.first
|
40
|
-
eval(expectation)
|
41
|
-
end
|
42
|
-
|
43
|
-
def reset_expectations
|
44
|
-
content_type 'text/plain'
|
45
|
-
FileUtils.rm_f(Dir.glob(EXPECTATION_DIR + '/*'))
|
46
|
-
File.open(ERROR_FILE, 'w') {|f|}
|
47
|
-
"Reset OK\n"
|
48
|
-
end
|
49
|
-
|
50
|
-
def verify_expectations
|
51
|
-
content_type 'text/plain'
|
52
|
-
check_for_non_received_requests
|
53
|
-
errors = File.read ERROR_FILE
|
54
|
-
throw :halt, [400, errors] unless errors.empty?
|
55
|
-
"Verify OK\n"
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def next_expectation_file
|
61
|
-
files = Dir.glob(EXPECTATION_DIR + '/*.rb').sort
|
62
|
-
if files.empty?
|
63
|
-
"#{EXPECTATION_DIR}/1.rb"
|
64
|
-
else
|
65
|
-
"#{EXPECTATION_DIR}/#{File.basename(files.last, '.rb').to_i + 1}.rb"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def check_for_non_received_requests
|
70
|
-
Dir.glob(EXPECTATION_DIR + '/*.rb').each do |f|
|
71
|
-
File.open(ERROR_FILE, 'a') do |f|
|
72
|
-
f.puts "\nExpected request not received."
|
73
|
-
# TODO: Grab label from expectation (redefine expect?)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|