kerryb-fakettp 0.1.2 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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/Rack stuff (this will be tidied up at some point), as well as <a href="http://rspec.info">RSpec</a> matchers.</p>
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 &#8216;OK&#8217;. 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&#8217;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 &#8216;unexpected return&#8217; 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 only</li>
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&#8217;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
- $:.unshift(File.dirname(__FILE__))
2
-
3
- require 'sinatra'
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'
@@ -11,8 +11,9 @@ module Fakettp
11
11
  case command
12
12
  when 'install' then
13
13
  return install
14
+ else
15
+ return usage
14
16
  end
15
- return 0
16
17
  end
17
18
 
18
19
  private
@@ -3,4 +3,4 @@ require 'rubygems'
3
3
  FAKETTP_BASE = File.expand_path(File.dirname(__FILE__))
4
4
  require 'fakettp'
5
5
 
6
- run Sinatra.application
6
+ run Sinatra::Application
@@ -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,13 @@
1
+ require 'fakettp/expectation'
2
+
3
+ module Fakettp
4
+ module ExpectationHelper
5
+ def expect label
6
+ begin
7
+ yield
8
+ rescue Exception => e
9
+ raise Fakettp::Expectation::Error.new("Error in #{label}: #{e.message}")
10
+ end
11
+ end
12
+ end
13
+ 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.1.2
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-02-13 00:00:00 -08:00
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.3.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/helper.rb
65
- - lib/fakettp/Rakefile.rb
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
@@ -1,7 +0,0 @@
1
- $:.unshift(File.dirname(__FILE__) + '/../../lib')
2
- require 'cucumber/rake/task'
3
-
4
- task :default => :features
5
- Cucumber::Rake::Task.new do |t|
6
- t.cucumber_opts = "--format pretty"
7
- end
@@ -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