mirage-on-thin 3.0.8

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.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/.simplecov +6 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +29 -0
  7. data/Gemfile.lock +151 -0
  8. data/HISTORY +22 -0
  9. data/README.md +156 -0
  10. data/Rakefile +10 -0
  11. data/VERSION +1 -0
  12. data/bin/mirage +14 -0
  13. data/features/.nav +29 -0
  14. data/features/client/clear.feature +78 -0
  15. data/features/client/configure.feature +72 -0
  16. data/features/client/model.feature +95 -0
  17. data/features/client/preview_responses.feature +33 -0
  18. data/features/client/prime.feature +32 -0
  19. data/features/client/put.feature +111 -0
  20. data/features/client/readme.md +3 -0
  21. data/features/client/requests.feature +20 -0
  22. data/features/client/running.feature +51 -0
  23. data/features/client/save_and_revert.feature +39 -0
  24. data/features/client/start.feature +46 -0
  25. data/features/client/stop.feature +53 -0
  26. data/features/commandline_interface/help.feature +17 -0
  27. data/features/commandline_interface/readme.md +1 -0
  28. data/features/commandline_interface/start.feature +18 -0
  29. data/features/commandline_interface/stop.feature +42 -0
  30. data/features/logging.feature +6 -0
  31. data/features/prime.feature +35 -0
  32. data/features/readme.md +7 -0
  33. data/features/requests/delete.feature +48 -0
  34. data/features/requests/get.feature +36 -0
  35. data/features/save_and_revert.feature +35 -0
  36. data/features/step_definitions/my_steps.rb +98 -0
  37. data/features/step_definitions/observation_steps.rb +103 -0
  38. data/features/support/command_line.rb +33 -0
  39. data/features/support/env.rb +22 -0
  40. data/features/support/hooks.rb +26 -0
  41. data/features/support/mirage.rb +12 -0
  42. data/features/support/web.rb +20 -0
  43. data/features/templates/delete.feature +45 -0
  44. data/features/templates/get.feature +54 -0
  45. data/features/templates/path_wildcards.feature +10 -0
  46. data/features/templates/preview.feature +18 -0
  47. data/features/templates/put.feature +77 -0
  48. data/features/templates/put_with_substitutions.feature +22 -0
  49. data/features/templates/readme.md +4 -0
  50. data/features/templates/required_content.feature +113 -0
  51. data/features/web_user_interface.feature +44 -0
  52. data/full_build.sh +100 -0
  53. data/lib/mirage/client.rb +10 -0
  54. data/lib/mirage/client/cli_bridge.rb +30 -0
  55. data/lib/mirage/client/client.rb +73 -0
  56. data/lib/mirage/client/error.rb +22 -0
  57. data/lib/mirage/client/helpers/method_builder.rb +19 -0
  58. data/lib/mirage/client/request.rb +26 -0
  59. data/lib/mirage/client/requests.rb +13 -0
  60. data/lib/mirage/client/runner.rb +103 -0
  61. data/lib/mirage/client/template.rb +56 -0
  62. data/lib/mirage/client/template/configuration.rb +44 -0
  63. data/lib/mirage/client/template/model.rb +48 -0
  64. data/lib/mirage/client/template/model/common_methods.rb +24 -0
  65. data/lib/mirage/client/template/model/instance_methods.rb +95 -0
  66. data/lib/mirage/client/templates.rb +50 -0
  67. data/mirage-on-thin.gemspec +175 -0
  68. data/mirage_server.rb +35 -0
  69. data/server/app.rb +4 -0
  70. data/server/binary_data_checker.rb +15 -0
  71. data/server/extensions/hash.rb +10 -0
  72. data/server/extensions/object.rb +5 -0
  73. data/server/helpers.rb +3 -0
  74. data/server/helpers/http_headers.rb +31 -0
  75. data/server/helpers/template_requirements.rb +33 -0
  76. data/server/mock_response.rb +242 -0
  77. data/server/server.rb +184 -0
  78. data/spec/client/cli_bridge_spec.rb +63 -0
  79. data/spec/client/client_spec.rb +179 -0
  80. data/spec/client/helpers/method_builder_spec.rb +40 -0
  81. data/spec/client/request_spec.rb +39 -0
  82. data/spec/client/requests_spec.rb +9 -0
  83. data/spec/client/runner_spec.rb +138 -0
  84. data/spec/client/template/configuration_spec.rb +32 -0
  85. data/spec/client/template/model/common_methods_spec.rb +25 -0
  86. data/spec/client/template/model/instance_methods_spec.rb +169 -0
  87. data/spec/client/template/model_spec.rb +119 -0
  88. data/spec/client/template_spec.rb +146 -0
  89. data/spec/client/templates_spec.rb +197 -0
  90. data/spec/resources/binary.file +0 -0
  91. data/spec/server/binary_data_checker_spec.rb +21 -0
  92. data/spec/server/helpers/http_headers_spec.rb +20 -0
  93. data/spec/server/helpers/template_requirements_spec.rb +34 -0
  94. data/spec/server/mock_response_spec.rb +577 -0
  95. data/spec/server/server_spec.rb +156 -0
  96. data/spec/spec_helper.rb +85 -0
  97. data/tasks/application.rake +7 -0
  98. data/tasks/packaging.rake +28 -0
  99. data/tasks/tests.rake +25 -0
  100. data/views/index.haml +16 -0
  101. data/views/response.haml +46 -0
  102. metadata +337 -0
@@ -0,0 +1,98 @@
1
+ Given /^I run '(.*)'$/ do |command|
2
+ if ENV['mode'] == 'regression' && ChildProcess.windows?
3
+ command.gsub!(/^mirage/, MIRAGE_CMD)
4
+ else
5
+ path = "#{RUBY_CMD} ../bin/"
6
+ end
7
+
8
+ @commandline_output = normalise(run("#{path}#{command}"))
9
+ end
10
+
11
+ Given /^the file '(.*)' contains:$/ do |file_path, content|
12
+ write_to_file file_path, content
13
+ end
14
+
15
+ Given /^usage information:$/ do |usage|
16
+ @usage = normalise(usage.to_s)
17
+ end
18
+
19
+ Then /^I run$/ do |text|
20
+ text.gsub!("\"", "\\\\\"")
21
+ Dir.chdir SCRATCH do
22
+ raise "run failed" unless system "#{RUBY_CMD} -I #{SOURCE_PATH} -e \"#{@code_snippet}\n#{text}\""
23
+ end
24
+ end
25
+
26
+ Given /^the following require statements are needed:$/ do |text|
27
+ @code_snippet = text.gsub("\"", "\\\\\"")
28
+ end
29
+
30
+ When /^I send (POST|PUT) to '(.*)' with request entity$/ do |method, endpoint, entity|
31
+ url = "http://localhost:7001#{endpoint}"
32
+ @response = case method
33
+ when 'POST'
34
+ post(url, body: entity)
35
+ when 'PUT'
36
+ put(url, body: entity)
37
+ end
38
+ end
39
+
40
+ When /^(GET|PUT|POST|DELETE) is sent to '([^']*)'$/ do |method, endpoint|
41
+ start_time = Time.now
42
+ url = "http://localhost:7001#{endpoint}"
43
+ @response = case method
44
+ when 'GET' then
45
+ get(url)
46
+ when 'PUT' then
47
+ put(url, body: '')
48
+ when 'POST' then
49
+ post(url, body: '')
50
+ when 'DELETE' then
51
+ delete(url)
52
+ end
53
+ @response_time = Time.now - start_time
54
+ end
55
+
56
+ When /^I click '(.*)'$/ do |thing|
57
+ @page = @page.links.find { |link| link.attributes['id'] == thing }.click
58
+ end
59
+
60
+ When /^I send (GET|POST) to '(.*)' with parameters:$/ do |http_method, endpoint, table|
61
+
62
+
63
+ url = "http://localhost:7001#{endpoint}"
64
+ parameters = {}
65
+ table.raw.each do |row|
66
+ parameter, value = row[0].to_sym, row[1]
67
+ value = File.exists?(value) ? File.open(value, 'rb') : value
68
+ parameters[parameter]=value
69
+ end
70
+ puts parameters
71
+
72
+ @response = case http_method
73
+ when 'POST' then
74
+ post(url, query: parameters, headers: {'Content-length' => '0'})
75
+ when 'GET' then
76
+ get(url, query: parameters)
77
+ end
78
+ end
79
+
80
+ Given /^the following template template:$/ do |text|
81
+ @response_template = Hashie::Mash.new(JSON.parse(text))
82
+ end
83
+
84
+ When /^'(.*)' is base64 encoded$/ do |template_component|
85
+ @response_template.send(:eval, "#{template_component}=Base64.encode64(#{template_component})")
86
+ end
87
+
88
+ When /^the template is sent using PUT to '(.*?)'$/ do |endpoint|
89
+ @response = put("http://localhost:7001#{endpoint}", body: @response_template.to_hash.to_json, :headers => {"Content-Type" => "application/json"})
90
+ end
91
+
92
+ Given /^a template for '(.*)' has been set with a value of '(.*)'$/ do |endpoint, value|
93
+ mirage.templates.put(endpoint, value)
94
+ end
95
+
96
+ Given(/^the following Template JSON:$/) do |text|
97
+ @response_template = Hashie::Mash.new(JSON.parse(text))
98
+ end
@@ -0,0 +1,103 @@
1
+ Then /^'([^']*)' should be returned$/ do |expected_response|
2
+ response_text = @response.body
3
+ if response_text != expected_response
4
+ expected_response.split('&').each { |param_value_pair| response_text.should =~ /#{param_value_pair}/ }
5
+ expected_response.length.should == response_text.length
6
+ end
7
+ end
8
+
9
+ Then /^a (\d+) should be returned$/ do |error_code|
10
+ @response.code.to_i.should == error_code.to_i
11
+ end
12
+
13
+ Then /^it should take at least '(.*)' seconds$/ do |time|
14
+ (@response_time).should >= time.to_f
15
+ end
16
+
17
+ Then /^mirage (should|should not) be running on '(.*)'$/ do |should, url|
18
+ running = begin
19
+ get(url).code.to_i.should == 200
20
+ rescue
21
+ false
22
+ end
23
+
24
+ should == "should" ? running.should == true : running.should == false
25
+ end
26
+
27
+ Given /^Mirage (is|is not) running$/ do |running|
28
+ if running == 'is'
29
+ start_mirage_in_scratch_dir unless Mirage.running?
30
+ else
31
+ Mirage.stop :all
32
+ end
33
+ end
34
+
35
+ Then /^the usage information should be displayed$/ do
36
+ @usage.each_line { |line| @commandline_output.should include(line) }
37
+ end
38
+
39
+ Then /^I should see '(.*?)' on the command line$/ do |content|
40
+ @commandline_output.should include(content)
41
+ end
42
+
43
+ Then /^'(.*)' should exist$/ do |path|
44
+ File.exists?("#{SCRATCH}/#{path}").should == true
45
+ end
46
+
47
+ Then /^mirage.log should contain '(.*)'$/ do |content|
48
+ log_file_content = @mirage_log_file.readlines.to_s
49
+ fail("#{content} not found in mirage.log: #{log_file_content}") unless log_file_content.index(content)
50
+ end
51
+
52
+ Given /^I goto '(.*)'$/ do |url|
53
+ @page = Mechanize.new.get url
54
+ end
55
+
56
+ Then /^I should see '(.*)'$/ do |text|
57
+ @page.body.index(text).should_not == nil
58
+ end
59
+
60
+ When /^the response '([^']*)' should be '([^']*)'$/ do |header, value|
61
+ @response.response[header].should include(value)
62
+ end
63
+
64
+ Then /^request data should have been retrieved$/ do
65
+ puts @response.body
66
+ request_data = JSON.parse(@response.body)
67
+ request_data.include?('parameters').should == true
68
+ request_data.include?('headers').should == true
69
+ request_data.include?('body').should == true
70
+ request_data.include?('request_url').should == true
71
+ request_data.include?('id').should == true
72
+ end
73
+
74
+ Then(/^the template (request|response) specification should have the following set:$/) do |spec, table|
75
+ template_json = JSON.parse(get("http://localhost:7001/templates/#{JSON.parse(@response.body)['id']}").body)
76
+ request_specification = template_json[spec]
77
+ request_specification.size.should==table.hashes.size
78
+ table.hashes.each do |hash|
79
+ default = request_specification[hash['Setting'].downcase.gsub(' ', '_')]
80
+ case required_default = hash['Default']
81
+ when 'none'
82
+ case default
83
+ when Array
84
+ default.should == []
85
+ when Hash
86
+ default.should == {}
87
+ else
88
+ default.should == ""
89
+
90
+ end
91
+ else
92
+ default.to_s.downcase.should == required_default.downcase
93
+ end
94
+ end
95
+ end
96
+
97
+ Then(/^the following json should be returned:$/) do |text|
98
+ JSON.parse(text).should == JSON.parse(@response.body)
99
+ end
100
+
101
+ When(/^the content-type should be '(.*)'$/) do |content_type|
102
+ @response.content_type.should == content_type
103
+ end
@@ -0,0 +1,33 @@
1
+ require 'tempfile'
2
+ module CommandLine
3
+ def run command
4
+ output = Tempfile.new("child")
5
+ Dir.chdir SCRATCH do
6
+ process = ChildProcess.build(*("#{command}".split(' ')))
7
+ process.detach
8
+ process.io.stdout = output
9
+ process.io.stderr = output
10
+ process.start
11
+ wait_until(:timeout_after => 30.seconds) { process.exited? }
12
+ end
13
+ File.read(output.path)
14
+ end
15
+
16
+ def normalise text
17
+ text.gsub(/[\n]/, ' ').gsub(/\s+/, ' ').strip
18
+ end
19
+
20
+ def write_to_file file_path, content
21
+ file_path = "#{SCRATCH}/#{file_path}" unless file_path =~ /^\//
22
+
23
+ FileUtils.rm_rf(file_path) if File.exists?(file_path)
24
+ FileUtils.mkdir_p(File.dirname(file_path))
25
+
26
+ File.open("#{file_path}", 'w') do |file|
27
+ file.write(content)
28
+ end
29
+ end
30
+ end
31
+
32
+ World CommandLine
33
+ include CommandLine
@@ -0,0 +1,22 @@
1
+ ROOT_DIR = File.expand_path("#{File.dirname(__FILE__)}/../..")
2
+ SOURCE_PATH = "#{ROOT_DIR}/lib"
3
+ Bundler.require
4
+
5
+ $LOAD_PATH.unshift(SOURCE_PATH)
6
+ require 'base64'
7
+ require 'mirage/client'
8
+
9
+ SCRATCH = "#{ROOT_DIR}/scratch"
10
+ RUBY_CMD = ChildProcess.jruby? ? 'jruby' : 'ruby'
11
+ BLANK_RUBYOPT_CMD = ChildProcess.windows? ? 'set RUBYOPT=' : "export RUBYOPT=''"
12
+ ENV['RUBYOPT'] = ''
13
+
14
+
15
+ if 'regression' == ENV['mode']
16
+ MIRAGE_CMD = ChildProcess.windows? ? `where mirage.bat`.chomp : 'mirage'
17
+ else
18
+ MIRAGE_CMD = "#{RUBY_CMD} ../bin/mirage"
19
+ end
20
+
21
+
22
+
@@ -0,0 +1,26 @@
1
+ Before do
2
+ FileUtils.mkdir_p(SCRATCH)
3
+
4
+ mirage.templates.delete_all
5
+
6
+ Dir["#{SCRATCH}/*"].each do |file|
7
+ FileUtils.rm_rf(file) unless file == "#{SCRATCH}/mirage.log"
8
+ end
9
+
10
+ if File.exists? "#{SCRATCH}/mirage.log"
11
+ @mirage_log_file = File.open("#{SCRATCH}/mirage.log")
12
+ @mirage_log_file.seek(0, IO::SEEK_END)
13
+ end
14
+ end
15
+
16
+ Before ('@command_line') do
17
+ Mirage.stop :all
18
+ end
19
+
20
+ After('@command_line') do
21
+ Mirage.stop :all
22
+ end
23
+
24
+ at_exit do
25
+ Mirage.stop :all
26
+ end
@@ -0,0 +1,12 @@
1
+ module Mirage
2
+ def start_mirage_in_scratch_dir
3
+ Dir.chdir SCRATCH do
4
+ Mirage.start
5
+ end
6
+ end
7
+
8
+ def mirage
9
+ @mirage ||= Mirage.running? ? Mirage::Client.new : start_mirage_in_scratch_dir
10
+ end
11
+ end
12
+ World Mirage
@@ -0,0 +1,20 @@
1
+ require 'httparty'
2
+ module Mirage
3
+ module Web
4
+ def get *args
5
+ HTTParty.get(*args)
6
+ end
7
+ def put *args
8
+ HTTParty.put(*args)
9
+ end
10
+ def post *args
11
+ puts "running this one"
12
+ HTTParty.post(*args)
13
+ end
14
+ def delete *args
15
+ HTTParty.delete(*args)
16
+ end
17
+ end
18
+ end
19
+
20
+ World(Mirage::Web)
@@ -0,0 +1,45 @@
1
+ Feature: Deleting
2
+ When a template is deleted, any tracked request data is also removed.
3
+
4
+ Background: The MockServer has already got a response for greeting and leaving on it.
5
+ Given the following template template:
6
+ """
7
+ {
8
+ "response":{
9
+ "body":"Hello"
10
+ }
11
+ }
12
+ """
13
+ And 'response.body' is base64 encoded
14
+ And the template is sent using PUT to '/templates/greeting'
15
+
16
+ Given the following template template:
17
+ """
18
+ {
19
+ "response":{
20
+ "body":"Goodbye"
21
+ }
22
+ }
23
+ """
24
+ And 'response.body' is base64 encoded
25
+ And the template is sent using PUT to '/templates/leaving'
26
+
27
+
28
+ Scenario: Deleting all templates
29
+ Given DELETE is sent to '/templates'
30
+ When GET is sent to '/responses/greeting'
31
+ Then a 404 should be returned
32
+ When GET is sent to '/responses/leaving'
33
+ Then a 404 should be returned
34
+
35
+
36
+ Scenario: Deleting a particular template
37
+ Given DELETE is sent to '/templates/1'
38
+
39
+ When GET is sent to '/responses/greeting'
40
+ Then a 404 should be returned
41
+
42
+ When GET is sent to '/responses/leaving'
43
+ Then a 200 should be returned
44
+
45
+
@@ -0,0 +1,54 @@
1
+ Feature: Retrieving
2
+ Templates can be retrieved by using the ID that was returned when they were created
3
+
4
+
5
+ Scenario: Retrieving a template
6
+ Given the following template template:
7
+ """
8
+ {
9
+ "response":{
10
+ "default":false,
11
+ "body":"Hello",
12
+ "delay":0,
13
+ "content_type":"text/plain",
14
+ "status":200
15
+ },
16
+ "request":{
17
+ "parameters":{
18
+
19
+ },
20
+ "body_content":[
21
+
22
+ ],
23
+ "http_method":"get"
24
+ }
25
+ }
26
+ """
27
+ And the template is sent using PUT to '/templates/greeting'
28
+ When GET is sent to '/templates/1'
29
+ Then the following json should be returned:
30
+ """
31
+ {
32
+ "id": 1,
33
+ "endpoint": "greeting",
34
+ "requests_url": "http://localhost:7001/requests/1",
35
+ "response":{
36
+ "default":false,
37
+ "body":"Hello",
38
+ "delay":0,
39
+ "content_type":"text/plain",
40
+ "status":200
41
+ },
42
+ "request":{
43
+ "parameters":{
44
+
45
+ },
46
+ "headers":{},
47
+ "body_content":[
48
+ ],
49
+ "http_method":"get"
50
+ }
51
+ }
52
+ """
53
+
54
+
@@ -0,0 +1,10 @@
1
+ Feature: URI wildcards
2
+
3
+ Scenario: Setting a template with wildcards
4
+ Given the following Template JSON:
5
+ """
6
+ {"response":{"body":"SGVsbG8="}}
7
+ """
8
+ And the template is sent using PUT to '/templates/greeting/*/davis'
9
+ When GET is sent to '/responses/greeting/leon/davis'
10
+ Then 'Hello' should be returned
@@ -0,0 +1,18 @@
1
+ Feature: Previewing
2
+ A Template's body can be previewed
3
+
4
+
5
+ Scenario: Preview template body
6
+ Given the following template template:
7
+ """
8
+ {
9
+ "response":{
10
+ "body":"SGVsbG8="
11
+ },
12
+ "request":{
13
+ }
14
+ }
15
+ """
16
+ And the template is sent using PUT to '/templates/greeting'
17
+ When GET is sent to '/templates/1/preview'
18
+ Then 'Hello' should be returned