rest-assured 0.3.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.rspec +1 -0
  2. data/Gemfile +4 -1
  3. data/README.markdown +47 -25
  4. data/bin/rest-assured +3 -3
  5. data/features/command_line_options.feature +2 -2
  6. data/features/rest_api/redirects.feature +10 -9
  7. data/features/ruby_api/create_double.feature +1 -6
  8. data/features/ruby_api/test_server.feature +42 -0
  9. data/features/ruby_api/verify_requests.feature +1 -6
  10. data/features/ruby_api/wait_for_requests.feature +2 -5
  11. data/features/step_definitions/command_line_options_steps.rb +1 -1
  12. data/features/step_definitions/doubles_steps.rb +4 -0
  13. data/features/step_definitions/redirect_rules_steps.rb +2 -6
  14. data/features/step_definitions/ruby_api_steps.rb +45 -0
  15. data/features/support/env.rb +9 -14
  16. data/features/support/world_helpers.rb +1 -1
  17. data/lib/rest-assured.rb +1 -45
  18. data/lib/rest-assured/api.rb +3 -0
  19. data/lib/rest-assured/api/app_runner.rb +18 -0
  20. data/lib/rest-assured/api/app_session.rb +33 -0
  21. data/lib/rest-assured/{client → api}/resources.rb +0 -0
  22. data/lib/rest-assured/api/server.rb +59 -0
  23. data/lib/rest-assured/application.rb +46 -0
  24. data/lib/rest-assured/config.rb +16 -3
  25. data/lib/rest-assured/models/redirect.rb +6 -0
  26. data/lib/rest-assured/routes/double.rb +1 -1
  27. data/lib/rest-assured/routes/redirect.rb +1 -1
  28. data/lib/rest-assured/routes/response.rb +4 -4
  29. data/lib/rest-assured/utils/drb_sniffer.rb +11 -0
  30. data/lib/rest-assured/utils/port_explorer.rb +22 -0
  31. data/lib/rest-assured/utils/subprocess.rb +50 -0
  32. data/lib/rest-assured/version.rb +1 -1
  33. data/prof-result.html +79521 -0
  34. data/rest-assured.gemspec +2 -1
  35. data/spec/api/app_runner_spec.rb +27 -0
  36. data/spec/api/app_session_spec.rb +51 -0
  37. data/spec/{client → api}/resource_double_spec.rb +1 -14
  38. data/spec/api/server_spec.rb +138 -0
  39. data/spec/config_spec.rb +111 -93
  40. data/spec/functional/response_spec.rb +5 -2
  41. data/spec/models/redirect_spec.rb +22 -0
  42. data/spec/port_explorer_spec.rb +32 -0
  43. data/spec/spec_helper.rb +25 -18
  44. data/spec/subprocess_spec.rb +138 -0
  45. data/spec/{custom_matchers.rb → support/custom_matchers.rb} +0 -0
  46. data/spec/support/reset-singleton.rb +15 -0
  47. metadata +66 -30
  48. data/lib/rest-assured/client.rb +0 -17
data/rest-assured.gemspec CHANGED
@@ -21,8 +21,9 @@ Gem::Specification.new do |s|
21
21
  s.require_paths = ['lib']
22
22
 
23
23
  s.add_dependency 'sinatra', '>= 1.3.1'
24
- s.add_dependency 'rack-flash', '>= 0.1.2'
25
24
  s.add_dependency 'rack', '<= 1.3.6'
25
+ s.add_dependency 'childprocess', '~> 0.2.8'
26
+ s.add_dependency 'sinatra-flash'
26
27
  s.add_dependency 'haml', '>= 3.1.3'
27
28
  s.add_dependency 'activerecord', '~> 3.1.0'
28
29
  s.add_dependency 'activeresource', '~> 3.1.0'
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require File.expand_path('../../../lib/rest-assured/api/app_runner', __FILE__)
3
+
4
+ module RestAssured
5
+ describe AppRunner do
6
+ before do
7
+ Application.stub(:run!)
8
+ Config.stub(:included)
9
+ end
10
+
11
+ it 'requires Application' do
12
+ Kernel.should_receive(:require).with('rest-assured/application').and_return(true)
13
+ AppRunner.run!
14
+ end
15
+ it 'reloads config if Application has already been loaded' do
16
+ Kernel.stub(:require).and_return(false)
17
+
18
+ Application.should_receive(:send).with(:include, Config)
19
+ AppRunner.run!
20
+ end
21
+ it 'runs Application' do
22
+ Application.should_receive(:run!)
23
+ AppRunner.run!
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,51 @@
1
+ require 'childprocess'
2
+ require File.expand_path('../../spec_helper', __FILE__)
3
+ require File.expand_path('../../../lib/rest-assured/api/app_session', __FILE__)
4
+
5
+ module RestAssured
6
+ describe AppSession do
7
+ context 'either without spork or outside prefork block' do
8
+ before do
9
+ AppSession.any_instance.stub(:running_in_drb? => false)
10
+ end
11
+
12
+ it 'start application in subprocess' do
13
+ state = ''
14
+ Utils::Subprocess.should_receive(:new) do |&block|
15
+ state << 'called from block'
16
+ block.call
17
+ state = ''
18
+ end
19
+ AppRunner.should_receive(:run!) do
20
+ state.should == 'called from block'
21
+ end
22
+
23
+ AppSession.new
24
+ end
25
+ end
26
+
27
+ context 'within spork prefork block' do
28
+ before do
29
+ AppSession.any_instance.stub(:running_in_drb? => true)
30
+ end
31
+
32
+ it 'starts application in childprocess' do
33
+ cmdargs = %w{-d :memory: -p 6666}
34
+ Config.stub(:to_cmdargs => cmdargs)
35
+
36
+ ChildProcess.should_receive(:build).with('rest-assured', *cmdargs).and_return(child = mock(:io => mock))
37
+
38
+ state = ''
39
+ child.io.should_receive(:inherit!) do
40
+ state.should_not == 'started'
41
+ end
42
+ child.should_receive(:start) do
43
+ state << 'started'
44
+ end
45
+
46
+ AppSession.new
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -2,22 +2,9 @@ require 'uri'
2
2
  require File.expand_path('../../spec_helper', __FILE__)
3
3
 
4
4
  module RestAssured
5
- describe Double do
6
- before do
7
- @orig_addr = RestAssured::Client.config.server_address
8
- end
9
-
10
- after do
11
- RestAssured::Client.config.server_address = @orig_addr
12
- end
13
-
5
+ describe Double, 'ruby-api' => true do
14
6
  it { should be_kind_of ActiveResource::Base }
15
7
 
16
- it 'knows where rest-assured server is' do
17
- RestAssured::Client.config.server_address = 'http://localhost:1234'
18
- Double.site.should == URI.parse('http://localhost:1234')
19
- end
20
-
21
8
  it 'creates new double' do
22
9
  d = Double.create :fullpath => '/some/api', :content => 'content'
23
10
  Models::Double.where(:fullpath => d.fullpath, :content => d.content).should exist
@@ -0,0 +1,138 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require File.expand_path('../../../lib/rest-assured/api/server', __FILE__)
3
+
4
+ module RestAssured
5
+ describe Server do
6
+ after do
7
+ Server.reset_instance
8
+ end
9
+
10
+ it 'khows when it is up' do
11
+ AppSession.stub(:new).and_return(session = stub(:alive? => true).as_null_object)
12
+ Utils::PortExplorer.stub(:port_free? => false)
13
+ Server.start
14
+
15
+ Server.up?.should == true
16
+ end
17
+
18
+ context 'knows that it is NOT up' do
19
+ it 'if it has not been started' do
20
+ Server.up?.should == false
21
+ end
22
+
23
+ it 'if it is starting at the moment' do
24
+ AppSession.stub(:new).and_return(session = stub(:alive? => true).as_null_object)
25
+ Utils::PortExplorer.stub(:port_free? => true)
26
+ Server.start!
27
+
28
+ Server.up?.should == false
29
+ end
30
+ end
31
+
32
+ context 'when starts' do
33
+ it 'makes sure no previous session is running' do
34
+ session = mock.as_null_object
35
+ session.stub(:alive?).and_return(true, false)
36
+ Utils::PortExplorer.stub(:port_free? => false)
37
+ AppSession.stub(:new).and_return(session)
38
+
39
+ session.should_receive(:stop).once
40
+ Server.start!
41
+ Server.start!
42
+ end
43
+
44
+ it 'builds application config' do
45
+ AppSession.stub(:new).as_null_object
46
+
47
+ opts = { :port => 34545, :database => ':memory:' }
48
+
49
+ Config.should_receive(:build).with(opts)
50
+ Server.start!(opts)
51
+ end
52
+
53
+ context 'sets up server address' do
54
+ before do
55
+ AppSession.stub(:new).as_null_object
56
+ end
57
+
58
+ it 'uses 127.0.0.1 as hostname' do
59
+ RestAssured::Double.should_receive(:site=).with(/127\.0\.0\.1/)
60
+ Server.start!
61
+ Server.address.should =~ /127\.0\.0\.1/
62
+ end
63
+
64
+ it 'uses port from config' do
65
+ RestAssured::Double.should_receive(:site=).with(/#{AppConfig.port}/)
66
+ Server.start!
67
+ Server.address.should =~ /#{AppConfig.port}/
68
+ end
69
+
70
+ it 'uses http by default' do
71
+ RestAssured::Double.should_receive(:site=).with(/http[^s]/)
72
+ Server.start!
73
+ Server.address.should =~ /http[^s]/
74
+ end
75
+
76
+ it 'uses https if ssl is set in config' do
77
+ AppConfig.ssl = true
78
+ RestAssured::Double.should_receive(:site=).with(/https/)
79
+ Server.start!
80
+ Server.address.should =~ /https/
81
+ end
82
+ end
83
+
84
+ describe 'async/sync start' do
85
+ before do
86
+ AppSession.stub(:new).and_return(session = stub(:alive? => false).as_null_object)
87
+ Utils::PortExplorer.stub(:port_free? => true)
88
+
89
+ @t = Thread.new do
90
+ sleep 0.5
91
+ session.stub(:alive?).and_return(true)
92
+ Utils::PortExplorer.stub(:port_free? => false)
93
+ end
94
+ end
95
+
96
+ after do
97
+ @t.join
98
+ end
99
+
100
+ it 'does not wait for Application to come up' do
101
+ Server.start!
102
+ Server.up?.should == false
103
+ end
104
+
105
+ it 'can wait until Application is up before passing control' do
106
+ Server.start
107
+ Server.up?.should == true
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'when stopped' do
113
+ it 'stops application subprocess' do
114
+ AppSession.stub(:new).and_return(session = stub(:alive? => false))
115
+ Server.start!
116
+
117
+ session.should_receive(:stop)
118
+ Server.stop
119
+ end
120
+ end
121
+
122
+ it 'stops application subprocess when current process exits' do
123
+ if not running_in_drb? # drb breaks fork sandbox: at_exits a collected and fired all together on master process exit
124
+ res_file = Tempfile.new('res')
125
+ AppSession.stub(:new).and_return(session = mock.as_null_object)
126
+ session.stub(:stop) do
127
+ res_file.write "stopped"
128
+ res_file.rewind
129
+ end
130
+ fork do
131
+ Server.start!
132
+ end
133
+ Process.wait
134
+ res_file.read.should == 'stopped'
135
+ end
136
+ end
137
+ end
138
+ end
data/spec/config_spec.rb CHANGED
@@ -2,131 +2,149 @@ require File.expand_path('../../lib/rest-assured/config', __FILE__)
2
2
  require 'rack'
3
3
  require 'openssl'
4
4
  require 'webrick'
5
+ require 'enumerator'
5
6
 
6
- describe RestAssured::Config do
7
- #this is thoroughly covered in cucumber (since there it also serves documentation purposes)
8
- #it 'builds config from user options'
9
-
10
- it 'initializes logger' do
11
- logger = double(:logger).as_null_object
12
- AppConfig.stub(:logfile).and_return('test.log')
13
-
14
- Logger.should_receive(:new).with('test.log').and_return(logger)
15
-
16
- RestAssured::Config.init_logger
17
- end
7
+ module RestAssured
8
+ describe Config do
9
+ before do
10
+ Config.build
11
+ end
18
12
 
19
- context 'db setup' do
20
- it 'connects db' do
21
- RestAssured::Config.stub(:migrate_db) # so it does not complain
22
- AppConfig.stub(:db_config).and_return('db_config')
13
+ context 'builds config from user options' do
14
+ #this is thoroughly covered in cucumber (since there it also serves documentation purposes)
15
+ end
23
16
 
24
- ActiveRecord::Base.should_receive(:establish_connection).with('db_config')
17
+ context 'when included in Application' do
18
+ let(:app) { mock(:app).as_null_object }
25
19
 
26
- RestAssured::Config.setup_db
27
- end
20
+ it 'initializes logger' do
21
+ Config.stub(:setup_db)
22
+ logger = double(:logger).as_null_object
23
+ AppConfig.stub(:logfile).and_return('test.log')
28
24
 
29
- context 'active_record logging' do
30
- let(:logger) { double(:logger).as_null_object }
25
+ Logger.should_receive(:new).with('test.log').and_return(logger)
31
26
 
32
- before do
33
- RestAssured::Config.stub(:migrate_db)
34
- RestAssured::Config.stub(:connect_db)
27
+ Config.included(app)
35
28
  end
36
29
 
37
- it 'is silenced in production' do
38
- AppConfig.stub(:environment).and_return('production')
39
- Logger.should_receive(:new).with(RestAssured::Config.dev_null).and_return(logger)
30
+ context 'db setup' do
31
+ it 'connects db' do
32
+ Config.stub(:init_logger)
33
+ Config.stub(:migrate_db) # so it does not complain
34
+ AppConfig.stub(:db_config).and_return('db_config')
40
35
 
41
- ActiveRecord::Base.should_receive(:logger=).with(logger)
36
+ ActiveRecord::Base.should_receive(:establish_connection).with('db_config')
42
37
 
43
- RestAssured::Config.setup_db
44
- end
38
+ Config.included(app)
39
+ end
45
40
 
46
- it 'is set to app logger for non production' do
47
- AppConfig.stub(:environment).and_return('test')
48
- AppConfig.stub(:logger).and_return(logger)
41
+ context 'active_record logging' do
42
+ let(:logger) { double(:logger).as_null_object }
49
43
 
50
- ActiveRecord::Base.should_receive(:logger=).with(logger)
44
+ before do
45
+ Config.stub(:migrate_db)
46
+ Config.stub(:connect_db)
47
+ end
51
48
 
52
- RestAssured::Config.setup_db
53
- end
54
- end
49
+ it 'is silenced in production' do
50
+ AppConfig.stub(:environment).and_return('production')
51
+ Logger.should_receive(:new).with(Config.dev_null).and_return(logger)
55
52
 
56
- it 'runs migrations' do
57
- RestAssured::Config.stub(:connect_db) # so it does not complain
53
+ ActiveRecord::Base.should_receive(:logger=).with(logger)
58
54
 
59
- ActiveRecord::Migrator.should_receive(:migrate)
55
+ Config.setup_db
56
+ end
60
57
 
61
- RestAssured::Config.setup_db
62
- end
63
- end
58
+ it 'is set to app logger for non production' do
59
+ AppConfig.stub(:environment).and_return('test')
60
+ AppConfig.stub(:logger).and_return(logger)
64
61
 
65
- context 'when included in RestAssured::Application' do
66
- let(:app) { mock(:app).as_null_object }
62
+ ActiveRecord::Base.should_receive(:logger=).with(logger)
67
63
 
68
- before do
69
- RestAssured::Config.build
70
- end
64
+ Config.setup_db
65
+ end
66
+ end
71
67
 
72
- it 'initializes resources' do
73
- RestAssured::Config.should_receive(:init_logger)
74
- RestAssured::Config.should_receive(:setup_db)
68
+ it 'runs migrations' do
69
+ Config.stub(:connect_db) # so it does not complain
75
70
 
76
- RestAssured::Config.included(app)
77
- end
71
+ ActiveRecord::Migrator.should_receive(:migrate)
78
72
 
79
- it 'sets up environment' do
80
- app.should_receive(:set).with(:environment, AppConfig.environment)
81
- RestAssured::Config.included(app)
82
- end
73
+ Config.setup_db
74
+ end
75
+ end
83
76
 
84
- it 'sets up port' do
85
- app.should_receive(:set).with(:port, AppConfig.port)
86
- RestAssured::Config.included(app)
87
- end
77
+ it 'sets up environment' do
78
+ app.should_receive(:set).with(:environment, AppConfig.environment)
79
+ Config.included(app)
80
+ end
88
81
 
89
- it 'connects logger' do
90
- logger = double(:logger).as_null_object
91
- AppConfig.stub(:logger).and_return(logger)
82
+ it 'sets up port' do
83
+ app.should_receive(:set).with(:port, AppConfig.port)
84
+ Config.included(app)
85
+ end
92
86
 
93
- app.should_receive(:enable).with(:logging)
94
- app.should_receive(:use).with(Rack::CommonLogger, logger)
87
+ it 'connects logger to application' do
88
+ logger = double(:logger).as_null_object
89
+ AppConfig.stub(:logger).and_return(logger)
95
90
 
96
- RestAssured::Config.included(app)
97
- end
91
+ app.should_receive(:enable).with(:logging)
92
+ app.should_receive(:use).with(Rack::CommonLogger, logger)
98
93
 
99
- context 'when ssl true' do
100
- before do
101
- AppConfig.stub(:use_ssl).and_return(true)
94
+ Config.included(app)
102
95
  end
103
96
 
104
- it 'makes sure only webrick can be used' do
105
- app.should_receive(:set).with(:server, %[webrick])
106
- RestAssured::Config.included(app)
97
+ context 'when ssl true' do
98
+ before do
99
+ AppConfig.stub(:ssl).and_return(true)
100
+ end
101
+
102
+ it 'makes sure only webrick can be used' do
103
+ app.should_receive(:set).with(:server, %[webrick])
104
+ Config.included(app)
105
+ end
106
+
107
+ it 'sets up webrick ssl' do
108
+ OpenSSL::X509::Certificate.stub(:new).with( File.read( AppConfig.ssl_cert ) ).and_return('ssl_cert')
109
+ OpenSSL::PKey::RSA.stub(:new).with( File.read( AppConfig.ssl_key ) ).and_return('ssl_key')
110
+
111
+ ssl_config = {
112
+ :SSLEnable => true,
113
+ :SSLCertificate => 'ssl_cert',
114
+ :SSLPrivateKey => 'ssl_key',
115
+ :SSLCertName => [ ["CN", WEBrick::Utils::getservername] ],
116
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE
117
+ }
118
+
119
+ app.should_receive(:set).with(:webrick, hash_including(ssl_config))
120
+ Config.included(app)
121
+ end
122
+
123
+ it 'does all that only if ssl true' do
124
+ AppConfig.stub(:ssl).and_return(false)
125
+
126
+ app.should_not_receive(:set).with(:webrick, anything)
127
+ Config.included(app)
128
+ end
129
+ end
130
+ end
131
+
132
+ context 'cmd args array conversion' do
133
+ it 'converts true values in form of "value" => ["--#{value}"]' do
134
+ Config.build(:ssl => true)
135
+ Config.to_cmdargs.should == ['--ssl']
107
136
  end
108
137
 
109
- it 'sets up webrick ssl' do
110
- OpenSSL::X509::Certificate.stub(:new).with( File.read( AppConfig.ssl_cert ) ).and_return('ssl_cert')
111
- OpenSSL::PKey::RSA.stub(:new).with( File.read( AppConfig.ssl_key ) ).and_return('ssl_key')
112
-
113
- ssl_config = {
114
- :SSLEnable => true,
115
- :SSLCertificate => 'ssl_cert',
116
- :SSLPrivateKey => 'ssl_key',
117
- :SSLCertName => [ ["CN", WEBrick::Utils::getservername] ],
118
- :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE
119
- }
120
-
121
- app.should_receive(:set).with(:webrick, hash_including(ssl_config))
122
- RestAssured::Config.included(app)
138
+ it 'does not include false values' do
139
+ Config.build(:ssl => false)
140
+ Config.to_cmdargs.should_not include('--ssl')
123
141
  end
124
142
 
125
- it 'does all that only if ssl true' do
126
- AppConfig.stub(:use_ssl).and_return(false)
127
-
128
- app.should_not_receive(:set).with(:webrick, anything)
129
- RestAssured::Config.included(app)
143
+ it 'converts key value pairs in form of "key => value" => ["--#{key}", "value"]' do
144
+ Config.build(:port => 1234, :database => ':memory:')
145
+ Config.to_cmdargs.each_slice(2) do |a|
146
+ (a == ['--port', '1234'] || a == ['--database', ':memory:']).should == true
147
+ end
130
148
  end
131
149
  end
132
150
  end