mirage 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +50 -0
- data/README.md +93 -0
- data/bin/mirage +54 -0
- data/features/checking_for_requests.feature +74 -0
- data/features/clearing_requests_and_responses.feature +81 -0
- data/features/client/checking_for_requests.feature +20 -0
- data/features/client/clearing_responses.feature +75 -0
- data/features/client/getting_responses.feature +30 -0
- data/features/client/mirage_client.feature +36 -0
- data/features/client/peeking.feature +32 -0
- data/features/client/setting_responses.feature +91 -0
- data/features/client/snapshotting.feature +34 -0
- data/features/command_line_iterface.feature +39 -0
- data/features/default_responses.feature +91 -0
- data/features/file_hosting.feature +8 -0
- data/features/logging.feature +7 -0
- data/features/peeking_at_response.feature +24 -0
- data/features/resources/test.zip +0 -0
- data/features/response_templates.feature +45 -0
- data/features/root_responses.feature +47 -0
- data/features/setting_responses.feature +40 -0
- data/features/setting_responses_with_a_delay.feature +10 -0
- data/features/setting_responses_with_pattern_matching.feature +72 -0
- data/features/snapshotting.feature +25 -0
- data/features/step_definitions/my_steps.rb +127 -0
- data/features/support/env.rb +89 -0
- data/features/web_user_interface.feature +39 -0
- data/full_build.sh +100 -0
- data/lib/config.ru +5 -0
- data/lib/mirage.rb +14 -0
- data/lib/mirage/client.rb +140 -0
- data/lib/mirage/core.rb +206 -0
- data/lib/mirage/util.rb +40 -0
- data/lib/mirage/web.rb +65 -0
- data/lib/start_mirage.rb +15 -0
- data/lib/view/mirage/index.xhtml +23 -0
- data/mirage.gemspec +40 -0
- data/rakefile +50 -0
- metadata +199 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
Feature: Mirage can respond with a 'root' response when a when the response requested at a sub url is not found.
|
2
|
+
I.e.
|
3
|
+
if a response is held for 'level1' and request comes in for 'level1/level2' the response for 'level1'
|
4
|
+
can be returned if nothing is held for 'level1/level2'
|
5
|
+
|
6
|
+
If a request is made and there is more than one response that could be appropriate then the closet is chosen.
|
7
|
+
|
8
|
+
E.g.
|
9
|
+
responses exist for: 'level1' and 'level1/level2'. If a response for 'level1/level2/level3 is made, then the response for
|
10
|
+
'level1/level2' will be returned as it is the most specific match out of the two.
|
11
|
+
|
12
|
+
Root responses can cause unexpected behaviour and so in order to qualify as a root reponse a client must knowingly mark it as one.
|
13
|
+
|
14
|
+
Scenario: A root response is returned
|
15
|
+
Given I hit 'http://localhost:7001/mirage/set/level0/level1' with parameters:
|
16
|
+
| response | another level |
|
17
|
+
And I hit 'http://localhost:7001/mirage/set/level1' with parameters:
|
18
|
+
| response | level 1 |
|
19
|
+
| root_response | true |
|
20
|
+
|
21
|
+
When I hit 'http://localhost:7001/mirage/get/level1/level2'
|
22
|
+
Then 'level 1' should be returned
|
23
|
+
|
24
|
+
|
25
|
+
Scenario: More than one potential root response exists
|
26
|
+
Given I hit 'http://localhost:7001/mirage/set/level1' with parameters:
|
27
|
+
| response | level 1 |
|
28
|
+
| root_response | true |
|
29
|
+
And I hit 'http://localhost:7001/mirage/set/level1/level2' with parameters:
|
30
|
+
| response | level 2 |
|
31
|
+
| root_response | true |
|
32
|
+
And I hit 'http://localhost:7001/mirage/set/level1/level2/level3' with parameters:
|
33
|
+
| response | level 3 |
|
34
|
+
| root_response | false |
|
35
|
+
And I hit 'http://localhost:7001/mirage/set/level1/level2/level3/level4/level5' with parameters:
|
36
|
+
| response | level 5 |
|
37
|
+
| root_response | true |
|
38
|
+
|
39
|
+
When I hit 'http://localhost:7001/mirage/get/level1/level2/level3/level4'
|
40
|
+
Then 'level 2' should be returned
|
41
|
+
|
42
|
+
|
43
|
+
Scenario: There isnt a root response
|
44
|
+
Given I hit 'http://localhost:7001/mirage/set/level1' with parameters:
|
45
|
+
| response | level 1 |
|
46
|
+
When I hit 'http://localhost:7001/mirage/get/level1/level2'
|
47
|
+
Then a 404 should be returned
|
@@ -0,0 +1,40 @@
|
|
1
|
+
Feature: Mirage can be configured with endpoints that when request returned defined responses.
|
2
|
+
On setting a response, a unique id is retuned. This is a key that can be used to manage the response. E.g. clearing or peek at it.
|
3
|
+
|
4
|
+
Usage:
|
5
|
+
${mirage_url}/set/your/end/point?response=your_response
|
6
|
+
|
7
|
+
|
8
|
+
Scenario: Setting a response without any selection criteria
|
9
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
10
|
+
| response | Hello, how are you? |
|
11
|
+
|
12
|
+
When I hit 'http://localhost:7001/mirage/get/greeting'
|
13
|
+
Then 'Hello, how are you?' should be returned
|
14
|
+
|
15
|
+
Scenario: A response hosted on a longer url
|
16
|
+
Given I hit 'http://localhost:7001/mirage/set/say/hello/to/me' with parameters:
|
17
|
+
| response | Hello to me |
|
18
|
+
|
19
|
+
When I hit 'http://localhost:7001/mirage/get/say/hello/to/me'
|
20
|
+
Then 'Hello to me' should be returned
|
21
|
+
|
22
|
+
|
23
|
+
Scenario: The same endpoint is set more than once
|
24
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
25
|
+
| response | Hello |
|
26
|
+
Then '1' should be returned
|
27
|
+
|
28
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
29
|
+
| response | Hi |
|
30
|
+
Then '1' should be returned
|
31
|
+
|
32
|
+
|
33
|
+
Scenario: A response is not supplied
|
34
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting'
|
35
|
+
Then a 500 should be returned
|
36
|
+
|
37
|
+
|
38
|
+
Scenario: Getting a response that does not exist
|
39
|
+
When I hit 'http://localhost:7001/mirage/get/response_that_does_not_exist'
|
40
|
+
Then a 404 should be returned
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: Its possible introduce a delay before responding to a client with a particular response. This lets you simulate real world
|
2
|
+
conditions by making your application wait before receiving a response.
|
3
|
+
|
4
|
+
Scenario: Response with a delay
|
5
|
+
Given I hit 'http://localhost:7001/mirage/set/an_appology' with parameters:
|
6
|
+
| response | Sorry it took me so long! |
|
7
|
+
| delay | 4 |
|
8
|
+
|
9
|
+
When I hit 'http://localhost:7001/mirage/get/an_appology'
|
10
|
+
Then it should take at least '4' seconds
|
@@ -0,0 +1,72 @@
|
|
1
|
+
Feature: Mirage can be configured to return particular responses conditionally based on if a prescribed pattern is found in
|
2
|
+
querystring or the body of a request.
|
3
|
+
|
4
|
+
Patterns can be either plain text or a regular expression
|
5
|
+
|
6
|
+
Background: There is already a default response for 'greeting'
|
7
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
8
|
+
| response | Hello Stranger. |
|
9
|
+
|
10
|
+
|
11
|
+
Scenario: A plain text pattern found in the request body
|
12
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
13
|
+
| response | Hello Leon, how are you? |
|
14
|
+
| pattern | <name>leon</name> |
|
15
|
+
When I hit 'http://localhost:7001/mirage/get/greeting' with request body:
|
16
|
+
"""
|
17
|
+
<greetingRequest>
|
18
|
+
<name>leon</name>
|
19
|
+
</greetingRequest>
|
20
|
+
"""
|
21
|
+
Then 'Hello Leon, how are you?' should be returned
|
22
|
+
|
23
|
+
|
24
|
+
Scenario: A regex based pattern found in the request body
|
25
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
26
|
+
| response | Hello Leon, how are you? |
|
27
|
+
| pattern | .*?leon<\/name> |
|
28
|
+
|
29
|
+
When I hit 'http://localhost:7001/mirage/get/greeting' with request body:
|
30
|
+
"""
|
31
|
+
<greetingRequest>
|
32
|
+
<name>leon</name>
|
33
|
+
</greetingRequest>
|
34
|
+
"""
|
35
|
+
Then 'Hello Leon, how are you?' should be returned
|
36
|
+
|
37
|
+
|
38
|
+
Scenario: A plain text pattern found in the query string
|
39
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
40
|
+
| response | Hello Leon, how are you? |
|
41
|
+
| pattern | leon |
|
42
|
+
|
43
|
+
When I hit 'http://localhost:7001/mirage/get/greeting' with parameters:
|
44
|
+
| name | leon |
|
45
|
+
|
46
|
+
Then 'Hello Leon, how are you?' should be returned
|
47
|
+
|
48
|
+
|
49
|
+
Scenario: A regex based pattern found in the query string
|
50
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
51
|
+
| response | Hello Leon, how are you? |
|
52
|
+
| pattern | name=[L\|l]eon |
|
53
|
+
|
54
|
+
When I hit 'http://localhost:7001/mirage/get/greeting' with parameters:
|
55
|
+
| name | leon |
|
56
|
+
|
57
|
+
Then 'Hello Leon, how are you?' should be returned
|
58
|
+
|
59
|
+
|
60
|
+
Scenario: The pattern is not matched
|
61
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
62
|
+
| response | Hello Leon, how are you? |
|
63
|
+
| pattern | .*?leon<\/name> |
|
64
|
+
|
65
|
+
When I hit 'http://localhost:7001/mirage/get/greeting' with request body:
|
66
|
+
"""
|
67
|
+
<greetingRequest>
|
68
|
+
<name>jim</name>
|
69
|
+
</greetingRequest>
|
70
|
+
"""
|
71
|
+
|
72
|
+
Then 'Hello Stranger.' should be returned
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Having set up the Mirage with a number of defaults, your tests may continue to change its state.
|
2
|
+
Clearing and resetting all of your responses, potentially hundreds of times, can be time expensive.
|
3
|
+
|
4
|
+
Mirage provides the ability to take a snapshot of its current state and to roll it back to that state.
|
5
|
+
|
6
|
+
Background: The MockServer has been setup with some default responses
|
7
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
8
|
+
| response | The default greeting |
|
9
|
+
|
10
|
+
|
11
|
+
Scenario: Taking a snapshot and rolling it back
|
12
|
+
Given I hit 'http://localhost:7001/mirage/snapshot'
|
13
|
+
And I hit 'http://localhost:7001/mirage/set/leaving' with parameters:
|
14
|
+
| response | Goodye |
|
15
|
+
|
16
|
+
And I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
17
|
+
| response | Changed |
|
18
|
+
|
19
|
+
And I hit 'http://localhost:7001/mirage/rollback'
|
20
|
+
|
21
|
+
When I hit 'http://localhost:7001/mirage/get/leaving'
|
22
|
+
Then a 404 should be returned
|
23
|
+
|
24
|
+
When I hit 'http://localhost:7001/mirage/get/greeting'
|
25
|
+
Then 'The default greeting' should be returned
|
@@ -0,0 +1,127 @@
|
|
1
|
+
Before('@command_line') do
|
2
|
+
stop_mirage
|
3
|
+
end
|
4
|
+
|
5
|
+
After('@command_line') do
|
6
|
+
stop_mirage
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^'(.*?)' should be returned$/ do |expected_response|
|
10
|
+
response_text = @response.body
|
11
|
+
if ["1.8.6", "1.8.7"].include?(RUBY_VERSION) && response_text != expected_response
|
12
|
+
expected_response.length.should == response_text.length
|
13
|
+
expected_response.split('&').each { |param_value_pair| response_text.should =~ /#{param_value_pair}/ }
|
14
|
+
else
|
15
|
+
response_text.should == expected_response
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /^a (404|500) should be returned$/ do |error_code|
|
20
|
+
@response.code.should == error_code.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
Then /^it should take at least '(.*)' seconds$/ do |time|
|
24
|
+
(@response_time).should >= time.to_f
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
Then /^the response should be a file the same as '([^']*)'$/ do |file_path|
|
29
|
+
download_path = "#{SCRATCH}/temp.download"
|
30
|
+
@response.save_as(download_path)
|
31
|
+
FileUtils.cmp(download_path, file_path).should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
Then /^mirage should be running on '(.*)'$/ do |url|
|
35
|
+
get(url).code.to_i.should == 200
|
36
|
+
end
|
37
|
+
|
38
|
+
Given /^I run '(.*)'$/ do |command|
|
39
|
+
path = ENV['mode'] == 'regression' ? '' : "../bin/"
|
40
|
+
@commandline_output = normalise(IO.popen("export RUBYOPT='' && cd #{SCRATCH} && #{path}#{command}").read)
|
41
|
+
end
|
42
|
+
|
43
|
+
Given /^Mirage (is|is not) running$/ do |running|
|
44
|
+
if running == 'is'
|
45
|
+
start_mirage unless $mirage.running?
|
46
|
+
else
|
47
|
+
stop_mirage if $mirage.running?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Then /^Connection should be refused to '(.*)'$/ do |url|
|
52
|
+
|
53
|
+
begin
|
54
|
+
get(url)
|
55
|
+
fail "Mirage is still running"
|
56
|
+
rescue Errno::ECONNREFUSED
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
Given /^the file '(.*)' contains:$/ do |file_path, content|
|
62
|
+
file_path = "#{SCRATCH}/#{file_path}" unless file_path =~ /^\//
|
63
|
+
|
64
|
+
FileUtils.rm_rf(file_path) if File.exists?(file_path)
|
65
|
+
directory = File.dirname(file_path)
|
66
|
+
FileUtils.mkdir_p(directory)
|
67
|
+
file = File.new("#{directory}/#{File.basename(file_path)}", 'w')
|
68
|
+
file.write(content)
|
69
|
+
file.close
|
70
|
+
end
|
71
|
+
|
72
|
+
Then /^the usage information should be displayed$/ do
|
73
|
+
@usage.each { |line| @commandline_output.should =~ /#{line}/ }
|
74
|
+
end
|
75
|
+
Given /^usage information:$/ do |table|
|
76
|
+
@usage = table.raw.flatten.collect { |line| normalise(line) }
|
77
|
+
end
|
78
|
+
|
79
|
+
Then /^I run$/ do |text|
|
80
|
+
text.gsub!("\"", "\\\\\"")
|
81
|
+
raise "run failed" unless system "#{RUBY_CMD} -e \"#{@code_snippet}\n#{text}\""
|
82
|
+
end
|
83
|
+
|
84
|
+
Given /^the following gems are required to run the Mirage client test code:$/ do |text|
|
85
|
+
@code_snippet = text.gsub("\"", "\\\\\"")
|
86
|
+
end
|
87
|
+
|
88
|
+
When /^I hit '(http:\/\/localhost:7001\/mirage\/(.*?))'$/ do |url, response_id|
|
89
|
+
@response = hit_mirage(url)
|
90
|
+
end
|
91
|
+
|
92
|
+
When /^I (hit|get|post to) '(http:\/\/localhost:7001\/mirage\/(.*?))' with parameters:$/ do |http_method, url, endpoint, table|
|
93
|
+
|
94
|
+
parameters = {}
|
95
|
+
table.raw.each do |row|
|
96
|
+
parameter, value = row[0].to_sym, row[1]
|
97
|
+
value = (parameter == :file ? File.open(value) : value)
|
98
|
+
parameters[parameter.to_sym]=value
|
99
|
+
end
|
100
|
+
|
101
|
+
@response = hit_mirage(url, parameters)
|
102
|
+
end
|
103
|
+
|
104
|
+
When /^I hit '(http:\/\/localhost:7001\/mirage\/(.*?))' with request body:$/ do |url, endpoint, request_body|
|
105
|
+
@response = hit_mirage(url, {:body => request_body})
|
106
|
+
end
|
107
|
+
|
108
|
+
Then /^I should see '(.*?)' on the command line$/ do |content|
|
109
|
+
@commandline_output.should =~/#{content}/
|
110
|
+
end
|
111
|
+
|
112
|
+
Then /^'(.*)' should exist$/ do |path|
|
113
|
+
File.exists?("#{SCRATCH}/#{path}").should == true
|
114
|
+
end
|
115
|
+
|
116
|
+
Then /^'(.*)' should contain '(.*)'$/ do |file, content|
|
117
|
+
fail("#{content} not found in: #{File.read(file)}") unless File.read("#{SCRATCH}/#{file}").index(content)
|
118
|
+
end
|
119
|
+
Given /^I goto '(.*)'$/ do |url|
|
120
|
+
@page = Mechanize.new.get url
|
121
|
+
end
|
122
|
+
Then /^I should see '(.*)'$/ do |text|
|
123
|
+
@page.body.index(text).should_not == nil
|
124
|
+
end
|
125
|
+
When /^I click '(.*)'$/ do |thing|
|
126
|
+
@page = @page.links.find{|link| link.attributes['id'] == thing}.click
|
127
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../../lib")
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
Bundler.setup(:test)
|
5
|
+
require 'mirage'
|
6
|
+
require 'cucumber'
|
7
|
+
require 'rspec'
|
8
|
+
require 'mechanize'
|
9
|
+
|
10
|
+
SCRATCH = './scratch'
|
11
|
+
RUBY_CMD = RUBY_PLATFORM == 'JAVA' ? 'jruby' : 'ruby'
|
12
|
+
|
13
|
+
|
14
|
+
module Web
|
15
|
+
include Mirage::Web
|
16
|
+
|
17
|
+
def get(url)
|
18
|
+
browser = Mechanize.new
|
19
|
+
browser.keep_alive= false
|
20
|
+
browser.get(url)
|
21
|
+
end
|
22
|
+
|
23
|
+
def hit_mirage(url, parameters={})
|
24
|
+
start_time = Time.now
|
25
|
+
response = (parameters.include?(:file) ? http_post(url, parameters) : http_get(url, parameters))
|
26
|
+
@response_time = Time.now - start_time
|
27
|
+
response
|
28
|
+
end
|
29
|
+
|
30
|
+
def normalise text
|
31
|
+
text.gsub(/[\n]/, ' ').gsub(/\s+/, ' ')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
module Regression
|
37
|
+
def stop_mirage
|
38
|
+
`export RUBYOPT='' && cd #{SCRATCH} && mirage stop`
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_mirage
|
42
|
+
`truncate mirage.log --size 0`
|
43
|
+
`export RUBYOPT='' && cd #{SCRATCH} && mirage start`
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module IntelliJ
|
48
|
+
include Mirage::Util
|
49
|
+
|
50
|
+
def stop_mirage
|
51
|
+
system "cd #{SCRATCH} && ../bin/mirage stop"
|
52
|
+
wait_until do
|
53
|
+
!$mirage.running?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def start_mirage
|
58
|
+
puts "starting mirage"
|
59
|
+
`truncate mirage.log --size 0`
|
60
|
+
system "cd #{SCRATCH} && ../bin/mirage start"
|
61
|
+
|
62
|
+
wait_until do
|
63
|
+
$mirage.running?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
'regression' == ENV['mode'] ? World(Regression) : World(IntelliJ)
|
69
|
+
'regression' == ENV['mode'] ? include(Regression) : include(IntelliJ)
|
70
|
+
|
71
|
+
World(Web)
|
72
|
+
|
73
|
+
Before do
|
74
|
+
FileUtils.mkdir_p(SCRATCH)
|
75
|
+
$mirage = Mirage::Client.new
|
76
|
+
|
77
|
+
if $mirage.running?
|
78
|
+
$mirage.clear
|
79
|
+
else
|
80
|
+
start_mirage
|
81
|
+
end
|
82
|
+
|
83
|
+
`ls #{SCRATCH}/ | grep -v mirage.log | rm -rf`
|
84
|
+
`truncate -s 0 #{SCRATCH}/mirage.log`
|
85
|
+
end
|
86
|
+
|
87
|
+
at_exit do
|
88
|
+
stop_mirage
|
89
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Feature: Mirage's home page allows you to see what response are currently being hosted.
|
2
|
+
From this page you can:
|
3
|
+
- Peek at a responses content
|
4
|
+
- Check the response to see if a request has been made to it
|
5
|
+
|
6
|
+
Background: There are already a couple of responses hosted on he Mirage server
|
7
|
+
Given I hit 'http://localhost:7001/mirage/set/greeting' with parameters:
|
8
|
+
| response | hello |
|
9
|
+
| root_response | true |
|
10
|
+
And I hit 'http://localhost:7001/mirage/set/leaving' with parameters:
|
11
|
+
| response | goodbye |
|
12
|
+
|
13
|
+
Scenario: Using the home page to see what response are being hosted
|
14
|
+
Given I goto 'http://localhost:7001/mirage'
|
15
|
+
Then I should see 'greeting/*'
|
16
|
+
Then I should see 'leaving'
|
17
|
+
|
18
|
+
Scenario: Using the home page to peek at a response
|
19
|
+
Given I goto 'http://localhost:7001/mirage'
|
20
|
+
When I click 'peek_response_1'
|
21
|
+
Then I should see 'hello'
|
22
|
+
|
23
|
+
Scenario: Using the home page to check if a request has been made
|
24
|
+
Given I hit 'http://localhost:7001/mirage/get/greeting' with request body:
|
25
|
+
"""
|
26
|
+
Yo!
|
27
|
+
"""
|
28
|
+
Given I goto 'http://localhost:7001/mirage'
|
29
|
+
When I click 'check_response_1'
|
30
|
+
Then I should see 'Yo!'
|
31
|
+
|
32
|
+
Scenario: Using the home page to check if a request has been made
|
33
|
+
Given I hit 'http://localhost:7001/mirage/get/greeting' with request body:
|
34
|
+
"""
|
35
|
+
Yo!
|
36
|
+
"""
|
37
|
+
Given I goto 'http://localhost:7001/mirage'
|
38
|
+
When I click 'check_response_1'
|
39
|
+
Then I should see 'Yo!'
|