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 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