fakettp 0.2.4.1 → 0.3.0
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 +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
|