fakettp 0.2.4.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/README.rdoc +201 -0
- data/Rakefile +113 -0
- data/VERSION +1 -0
- data/features/control.feature +12 -0
- data/features/dashboard.feature +38 -0
- data/features/expectations.feature +27 -0
- data/features/expectations/expect_get +3 -0
- data/features/expectations/get_foo +3 -0
- data/features/expectations/get_root +3 -0
- data/features/expectations/pass_and_fail +5 -0
- data/features/expectations/set_response +5 -0
- data/features/step_definitions/expectations.rb +5 -0
- data/features/step_definitions/http.rb +42 -0
- data/features/step_definitions/simulator.rb +25 -0
- data/features/step_definitions/webrat_steps.rb +99 -0
- data/features/support/env.rb +5 -0
- data/features/support/fakettp.rb +2 -0
- data/features/support/paths.rb +12 -0
- data/features/support/xpath.rb +10 -0
- data/features/verification.feature +49 -0
- data/lib/fakettp/commands/fakettp_command.rb +31 -19
- data/lib/fakettp/controller.rb +12 -0
- data/lib/fakettp/db.rb +7 -0
- data/lib/fakettp/error.rb +6 -18
- data/lib/fakettp/expectation.rb +28 -44
- data/lib/fakettp/fakettp.yml +3 -0
- data/lib/fakettp/public/fakettp.css +33 -0
- data/lib/fakettp/schema.rb +14 -0
- data/lib/fakettp/simulator.rb +16 -10
- data/lib/fakettp/views/index.erb +14 -0
- data/spec/fakettp/commands/fakettp_command_spec.rb +128 -0
- data/spec/fakettp/controller_spec.rb +250 -0
- data/spec/fakettp/error_spec.rb +40 -0
- data/spec/fakettp/expectation_helper_spec.rb +33 -0
- data/spec/fakettp/expectation_spec.rb +142 -0
- data/spec/fakettp/simulator_spec.rb +149 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +18 -0
- metadata +73 -24
- data/README.html +0 -113
@@ -0,0 +1,25 @@
|
|
1
|
+
Given /^the simulator is reset$/ do
|
2
|
+
req = Net::HTTP::Post.new '/reset'
|
3
|
+
Net::HTTP.new('fakettp.local').start {|http| http.request(req) }
|
4
|
+
end
|
5
|
+
|
6
|
+
Given /^we expect (\S*)$/ do |filename|
|
7
|
+
body = File.read(File.dirname(__FILE__) + "/../expectations/#{filename}")
|
8
|
+
req = Net::HTTP::Post.new '/expect', {'Content-Type' => 'text/plain'}
|
9
|
+
req.body = body
|
10
|
+
Net::HTTP.new('fakettp.local').start {|http| http.request(req) }
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^verifying the simulator should report success$/ do
|
14
|
+
req = Net::HTTP::Get.new '/verify'
|
15
|
+
resp = Net::HTTP.new('fakettp.local').start {|http| http.request(req) }
|
16
|
+
resp.body.should == "Verify OK\n"
|
17
|
+
resp.class.should == Net::HTTPOK
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^verifying the simulator should report a failure, with message "(.*)"$/ do |message|
|
21
|
+
req = Net::HTTP::Get.new '/verify'
|
22
|
+
resp = Net::HTTP.new('fakettp.local').start {|http| http.request(req) }
|
23
|
+
resp.body.should =~ Regexp.new(message, Regexp::MULTILINE)
|
24
|
+
resp.class.should == Net::HTTPInternalServerError
|
25
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
|
2
|
+
|
3
|
+
# Commonly used webrat steps
|
4
|
+
# http://github.com/brynary/webrat
|
5
|
+
|
6
|
+
When /^I go to (.+)$/ do |page_name|
|
7
|
+
visit path_to(page_name)
|
8
|
+
end
|
9
|
+
|
10
|
+
When /^I press "(.*)"$/ do |button|
|
11
|
+
click_button(button)
|
12
|
+
end
|
13
|
+
|
14
|
+
When /^I follow "(.*)"$/ do |link|
|
15
|
+
click_link(link)
|
16
|
+
end
|
17
|
+
|
18
|
+
When /^I fill in "(.*)" with "(.*)"$/ do |field, value|
|
19
|
+
fill_in(field, :with => value)
|
20
|
+
end
|
21
|
+
|
22
|
+
When /^I select "(.*)" from "(.*)"$/ do |value, field|
|
23
|
+
select(value, :from => field)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Use this step in conjunction with Rail's datetime_select helper. For example:
|
27
|
+
# When I select "December 25, 2008 10:00" as the date and time
|
28
|
+
When /^I select "(.*)" as the date and time$/ do |time|
|
29
|
+
select_datetime(time)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Use this step when using multiple datetime_select helpers on a page or
|
33
|
+
# you want to specify which datetime to select. Given the following view:
|
34
|
+
# <%= f.label :preferred %><br />
|
35
|
+
# <%= f.datetime_select :preferred %>
|
36
|
+
# <%= f.label :alternative %><br />
|
37
|
+
# <%= f.datetime_select :alternative %>
|
38
|
+
# The following steps would fill out the form:
|
39
|
+
# When I select "November 23, 2004 11:20" as the "Preferred" data and time
|
40
|
+
# And I select "November 25, 2004 10:30" as the "Alternative" data and time
|
41
|
+
When /^I select "(.*)" as the "(.*)" date and time$/ do |datetime, datetime_label|
|
42
|
+
select_datetime(datetime, :from => datetime_label)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Use this step in conjuction with Rail's time_select helper. For example:
|
46
|
+
# When I select "2:20PM" as the time
|
47
|
+
# Note: Rail's default time helper provides 24-hour time-- not 12 hour time. Webrat
|
48
|
+
# will convert the 2:20PM to 14:20 and then select it.
|
49
|
+
When /^I select "(.*)" as the time$/ do |time|
|
50
|
+
select_time(time)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Use this step when using multiple time_select helpers on a page or you want to
|
54
|
+
# specify the name of the time on the form. For example:
|
55
|
+
# When I select "7:30AM" as the "Gym" time
|
56
|
+
When /^I select "(.*)" as the "(.*)" time$/ do |time, time_label|
|
57
|
+
select_time(time, :from => time_label)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Use this step in conjuction with Rail's date_select helper. For example:
|
61
|
+
# When I select "February 20, 1981" as the date
|
62
|
+
When /^I select "(.*)" as the date$/ do |date|
|
63
|
+
select_date(date)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Use this step when using multiple date_select helpers on one page or
|
67
|
+
# you want to specify the name of the date on the form. For example:
|
68
|
+
# When I select "April 26, 1982" as the "Date of Birth" date
|
69
|
+
When /^I select "(.*)" as the "(.*)" date$/ do |date, date_label|
|
70
|
+
select_date(date, :from => date_label)
|
71
|
+
end
|
72
|
+
|
73
|
+
When /^I check "(.*)"$/ do |field|
|
74
|
+
check(field)
|
75
|
+
end
|
76
|
+
|
77
|
+
When /^I uncheck "(.*)"$/ do |field|
|
78
|
+
uncheck(field)
|
79
|
+
end
|
80
|
+
|
81
|
+
When /^I choose "(.*)"$/ do |field|
|
82
|
+
choose(field)
|
83
|
+
end
|
84
|
+
|
85
|
+
When /^I attach the file at "(.*)" to "(.*)" $/ do |path, field|
|
86
|
+
attach_file(field, path)
|
87
|
+
end
|
88
|
+
|
89
|
+
Then /^I should see "(.*)"$/ do |text|
|
90
|
+
response.body.should =~ /#{text}/m
|
91
|
+
end
|
92
|
+
|
93
|
+
Then /^I should not see "(.*)"$/ do |text|
|
94
|
+
response.body.should_not =~ /#{text}/m
|
95
|
+
end
|
96
|
+
|
97
|
+
Then /^the "(.*)" checkbox should be checked$/ do |label|
|
98
|
+
field_labeled(label).should be_checked
|
99
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
def xml_node_values xml, xpath
|
4
|
+
begin
|
5
|
+
doc = REXML::Document.new(xml).root
|
6
|
+
REXML::XPath.match(doc, xpath).map { |node| (node.respond_to?(:value) ? node.value : node.text) }
|
7
|
+
rescue
|
8
|
+
raise "No #{xpath} found in response body (#{xml})"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
Feature: Verification of expectations
|
2
|
+
Scenario: No expectations and no requests
|
3
|
+
Given the simulator is reset
|
4
|
+
Then verifying the simulator should report success
|
5
|
+
|
6
|
+
Scenario: Satisfied expectation
|
7
|
+
Given the simulator is reset
|
8
|
+
And we expect get_root
|
9
|
+
When we get / on foo.fake.local
|
10
|
+
Then verifying the simulator should report success
|
11
|
+
|
12
|
+
Scenario: Unsatisfied expectation
|
13
|
+
Given the simulator is reset
|
14
|
+
And we expect get_root
|
15
|
+
Then verifying the simulator should report a failure, with message "Expected request not received"
|
16
|
+
|
17
|
+
Scenario: Unexpected request
|
18
|
+
Given the simulator is reset
|
19
|
+
When we get / on foo.fake.local
|
20
|
+
Then verifying the simulator should report a failure, with message "Received unexpected request"
|
21
|
+
|
22
|
+
Scenario: Mismatched expectation
|
23
|
+
Given the simulator is reset
|
24
|
+
And we expect get_root
|
25
|
+
When we get /foo on foo.fake.local
|
26
|
+
Then verifying the simulator should report a failure, with message "Error in GET /: expected: "/",.*got: "/foo""
|
27
|
+
|
28
|
+
Scenario: Two satisfied expectations
|
29
|
+
Given the simulator is reset
|
30
|
+
And we expect get_root
|
31
|
+
And we expect get_foo
|
32
|
+
When we get / on foo.fake.local
|
33
|
+
And we get /foo on foo.fake.local
|
34
|
+
Then verifying the simulator should report success
|
35
|
+
|
36
|
+
Scenario: Two expectations, one satisfied
|
37
|
+
Given the simulator is reset
|
38
|
+
And we expect get_root
|
39
|
+
And we expect get_foo
|
40
|
+
When we get / on foo.fake.local
|
41
|
+
Then verifying the simulator should report a failure, with message "Expected request not received"
|
42
|
+
|
43
|
+
Scenario: Two expectations, with requests received in the wrong order
|
44
|
+
Given the simulator is reset
|
45
|
+
And we expect get_root
|
46
|
+
And we expect get_foo
|
47
|
+
When we get /foo on foo.fake.local
|
48
|
+
And we get / on foo.fake.local
|
49
|
+
Then verifying the simulator should report a failure, with message "Error in GET /: expected: "/",.*got: "/foo".*Error in GET /foo: expected: "/foo",.*got: "/""
|
@@ -6,7 +6,7 @@ module Fakettp
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def run
|
9
|
-
command =
|
9
|
+
command = @args[0]
|
10
10
|
return usage unless command
|
11
11
|
case command
|
12
12
|
when 'install' then
|
@@ -17,37 +17,49 @@ module Fakettp
|
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
20
|
-
|
21
|
-
def get_command
|
22
|
-
@args[0]
|
23
|
-
end
|
24
20
|
|
25
21
|
def install
|
26
|
-
|
27
|
-
return usage unless
|
28
|
-
if File.exist?
|
29
|
-
$stderr.puts "File or directory #{
|
22
|
+
@directory, @hostname = @args[1..2]
|
23
|
+
return usage unless @directory && @hostname
|
24
|
+
if File.exist? @directory
|
25
|
+
$stderr.puts "File or directory #{@directory} already exists."
|
30
26
|
return 1
|
31
27
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
FileUtils.cp File.dirname(__FILE__) + '/../../../README.html', dir
|
28
|
+
copy_files
|
29
|
+
write_config
|
30
|
+
create_database
|
36
31
|
return 0
|
37
32
|
end
|
38
|
-
|
39
|
-
def get_dir
|
40
|
-
@args[1]
|
41
|
-
end
|
42
33
|
|
34
|
+
def copy_files
|
35
|
+
FileUtils.mkdir_p @directory + '/tmp', :mode => 0777
|
36
|
+
FileUtils.mkdir_p @directory + '/public'
|
37
|
+
FileUtils.cp File.dirname(__FILE__) + '/../config.ru', @directory
|
38
|
+
FileUtils.cp File.dirname(__FILE__) + '/../public/fakettp.css', @directory + '/public'
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_config
|
42
|
+
config = {'database' => {'adapter' => 'sqlite3', 'database' => 'fakettp.sqlite3'},
|
43
|
+
'hostname' => @hostname
|
44
|
+
}
|
45
|
+
File.open @directory + '/fakettp.yml', 'w' do |file|
|
46
|
+
file.write config.to_yaml
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_database
|
51
|
+
system %(ruby -e "FAKETTP_BASE = '#{@directory}';load '#{File.dirname(__FILE__)}/../schema.rb'")
|
52
|
+
end
|
53
|
+
|
43
54
|
def usage
|
44
55
|
$stderr.puts <<-EOF
|
45
56
|
Usage:
|
46
57
|
|
47
|
-
|
58
|
+
fakettp install <directory> <hostname>
|
59
|
+
|
48
60
|
EOF
|
49
61
|
return 1
|
50
62
|
end
|
51
63
|
end
|
52
64
|
end
|
53
|
-
end
|
65
|
+
end
|
data/lib/fakettp/controller.rb
CHANGED
@@ -7,6 +7,12 @@ require 'fakettp/expectation_helper'
|
|
7
7
|
require 'fakettp/simulator'
|
8
8
|
require 'fakettp/expectation'
|
9
9
|
|
10
|
+
set :views, File.join(File.dirname(__FILE__), 'views')
|
11
|
+
|
12
|
+
config_file = File.join(FAKETTP_BASE, 'fakettp.yml')
|
13
|
+
config = File.read config_file
|
14
|
+
host = YAML.load(config)['hostname']
|
15
|
+
|
10
16
|
include Fakettp::ExpectationHelper
|
11
17
|
|
12
18
|
post '/expect', :host => 'fakettp.local' do
|
@@ -30,6 +36,12 @@ get '/verify', :host => 'fakettp.local' do
|
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
39
|
+
get '/', :host => 'fakettp.local' do
|
40
|
+
content_type 'text/html'
|
41
|
+
@expectations = Fakettp::Expectation.all
|
42
|
+
erb :index
|
43
|
+
end
|
44
|
+
|
33
45
|
[:get, :post, :put, :delete, :head].each do |method|
|
34
46
|
send method, '/**' do
|
35
47
|
begin
|
data/lib/fakettp/db.rb
ADDED
data/lib/fakettp/error.rb
CHANGED
@@ -1,23 +1,11 @@
|
|
1
1
|
module Fakettp
|
2
|
-
class Error
|
3
|
-
|
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
|
-
|
2
|
+
class Error < ActiveRecord::Base
|
3
|
+
belongs_to :expectation
|
4
|
+
|
19
5
|
def self.list
|
20
|
-
|
6
|
+
errors = Error.all
|
7
|
+
return '' if errors.empty?
|
8
|
+
errors.map {|e| e.message}.join("\n") + "\n"
|
21
9
|
end
|
22
10
|
end
|
23
11
|
end
|
data/lib/fakettp/expectation.rb
CHANGED
@@ -1,56 +1,40 @@
|
|
1
|
+
require 'fakettp/db'
|
2
|
+
|
1
3
|
module Fakettp
|
2
|
-
class Expectation
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
class Expectation < ActiveRecord::Base
|
5
|
+
set_table_name :expectations
|
6
|
+
has_many :errors
|
7
|
+
|
8
|
+
class Error < StandardError
|
9
|
+
attr_reader :line_number
|
10
|
+
def initialize message, line_number = nil
|
11
|
+
@line_number = line_number
|
12
|
+
super(message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def render
|
17
|
+
if executed
|
18
|
+
span_class = errors.empty? ? 'pass' : 'fail'
|
19
|
+
%(<span class="#{span_class}">#{contents}</span>)
|
20
|
+
else
|
21
|
+
contents
|
22
|
+
end
|
9
23
|
end
|
10
24
|
|
11
25
|
def execute binding
|
12
|
-
|
26
|
+
self.executed = true
|
27
|
+
save
|
28
|
+
eval contents, binding
|
13
29
|
# TODO: Include context of expectation file
|
14
30
|
end
|
15
|
-
|
16
|
-
def self.
|
17
|
-
|
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
|
31
|
+
|
32
|
+
def self.all_received?
|
33
|
+
!exists? :executed => false
|
28
34
|
end
|
29
35
|
|
30
36
|
def self.next
|
31
|
-
|
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) - ['.', '..']).sort_by {|a| a.to_i}
|
37
|
+
find_by_executed(false)
|
52
38
|
end
|
53
|
-
|
54
|
-
private_class_method :next_file_to_create, :next_file_to_read, :files
|
55
39
|
end
|
56
40
|
end
|