ww 0.2.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/Rakefile CHANGED
@@ -62,9 +62,9 @@ spec = Gem::Specification.new do |s|
62
62
  #s.required_ruby_version = '>= 1.8.2'
63
63
 
64
64
  s.files = %w(Rakefile) +
65
- Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
65
+ Dir.glob("{bin,doc,spec,lib,templates,generator,extras,website,script}/**/*") +
66
66
  Dir.glob("ext/**/*.{h,c,rb}") +
67
- Dir.glob("examples/**/*.rb") +
67
+ Dir.glob("example/**/*") +
68
68
  Dir.glob("tools/*.rb") +
69
69
  Dir.glob("rails/*.rb")
70
70
 
@@ -79,7 +79,7 @@ end
79
79
  task :install do
80
80
  name = "#{NAME}-#{VERS}.gem"
81
81
  sh %{rake package}
82
- sh %{gem install pkg/#{name}}
82
+ sh %{gem install --no-rdoc --no-ri pkg/#{name}}
83
83
  end
84
84
 
85
85
  task :uninstall => [:clean] do
@@ -0,0 +1,14 @@
1
+ require 'ww/spy_eye'
2
+
3
+ app = Ww::SpyEye.to_app do
4
+ spy(:get, "/hello") do
5
+ "Hello World"
6
+ end
7
+
8
+ spy(:post, "/hello") do
9
+ redirect "/hello"
10
+ end
11
+ end
12
+
13
+ run app
14
+
@@ -0,0 +1,336 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html>
3
+ <head>
4
+ <title>3 requests - Double Web</title>
5
+ <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js'></script>
6
+ <style type='text/css'>
7
+ body {
8
+ width: 80%;
9
+ margin: auto; }
10
+
11
+ h1 {
12
+ font-size: 10px; }
13
+
14
+ div.stump {
15
+ font-size: 10px;
16
+ border: 1px solid silver;
17
+ padding: 0 1em; }
18
+ div.stump h2 {
19
+ font-size: 10px;
20
+ color: gray; }
21
+ div.stump h2 span.method, div.stump h2 span.path {
22
+ font-size: 16px;
23
+ font-weight: normal;
24
+ font-family: 'Courier', monospace; }
25
+ div.stump h2 span.method {
26
+ color: #090; }
27
+ div.stump h2 span.path {
28
+ color: black; }
29
+ div.stump h2 span.time, div.stump h2 span.source {
30
+ color: blue; }
31
+ div.stump h3 {
32
+ font-size: small;
33
+ border-bottom: 1px solid green;
34
+ background: #cfb;
35
+ padding: 2px 0 0 2px; }
36
+ div.stump h3 span.media_type {
37
+ color: blue;
38
+ font-size: small;
39
+ font-weight: normal;
40
+ font-family: 'Courier', monospace; }
41
+ div.stump .headers table, div.stump div.body pre {
42
+ border: 1px dashed green;
43
+ margin: 1em;
44
+ padding: 1em; }
45
+ div.stump div.body pre {
46
+ overflow: auto;
47
+ font-size: 12px; }
48
+ </style>
49
+ </head>
50
+ <body>
51
+ <h1>3 requests - Double Web</h1>
52
+ <div class='stump' id='13699160'>
53
+ <h2>
54
+ <span class='method'>POST</span>
55
+ <span class='path'>/hello</span>
56
+ on
57
+ <span class='time'>2010-01-16T23:57:01+09:00</span>
58
+ from
59
+ <span class='source'>127.0.0.1</span>
60
+ </h2>
61
+ <div>
62
+ <div class='headers'>
63
+ <h3>Headers</h3>
64
+ <table>
65
+ <tr>
66
+ <th>HTTP_ACCEPT</th>
67
+ <td>*/*</td>
68
+ </tr>
69
+ <tr>
70
+ <th>HTTP_HOST</th>
71
+ <td>localhost:8888</td>
72
+ </tr>
73
+ <tr>
74
+ <th>SERVER_NAME</th>
75
+ <td>localhost</td>
76
+ </tr>
77
+ <tr>
78
+ <th>CONTENT_LENGTH</th>
79
+ <td>28</td>
80
+ </tr>
81
+ <tr>
82
+ <th>HTTP_USER_AGENT</th>
83
+ <td>curl/7.19.5 (i386-apple-darwin9.7.0) libcurl/7.19.5 OpenSSL/0.9.8k zlib/1.2.3</td>
84
+ </tr>
85
+ <tr>
86
+ <th>REQUEST_PATH</th>
87
+ <td>/hello</td>
88
+ </tr>
89
+ <tr>
90
+ <th>SERVER_PROTOCOL</th>
91
+ <td>HTTP/1.1</td>
92
+ </tr>
93
+ <tr>
94
+ <th>CONTENT_TYPE</th>
95
+ <td>application/x-www-form-urlencoded</td>
96
+ </tr>
97
+ <tr>
98
+ <th>REMOTE_ADDR</th>
99
+ <td>127.0.0.1</td>
100
+ </tr>
101
+ <tr>
102
+ <th>PATH_INFO</th>
103
+ <td>/hello</td>
104
+ </tr>
105
+ <tr>
106
+ <th>SERVER_SOFTWARE</th>
107
+ <td>thin 1.2.5 codename This Is Not A Web Server</td>
108
+ </tr>
109
+ <tr>
110
+ <th>SCRIPT_NAME</th>
111
+ <td></td>
112
+ </tr>
113
+ <tr>
114
+ <th>HTTP_VERSION</th>
115
+ <td>HTTP/1.1</td>
116
+ </tr>
117
+ <tr>
118
+ <th>REQUEST_URI</th>
119
+ <td>/hello</td>
120
+ </tr>
121
+ <tr>
122
+ <th>SERVER_PORT</th>
123
+ <td>8888</td>
124
+ </tr>
125
+ <tr>
126
+ <th>REQUEST_METHOD</th>
127
+ <td>POST</td>
128
+ </tr>
129
+ <tr>
130
+ <th>QUERY_STRING</th>
131
+ <td></td>
132
+ </tr>
133
+ <tr>
134
+ <th>GATEWAY_INTERFACE</th>
135
+ <td>CGI/1.2</td>
136
+ </tr>
137
+ </table>
138
+ </div>
139
+ <div class='body'>
140
+ <h3>
141
+ Body
142
+ <span class='media_type'>application/x-www-form-urlencoded</span>
143
+ </h3>
144
+ <pre>{&quot;message&quot;=&gt;&quot;How are you?&quot;, &quot;key&quot;=&gt;&quot;2nd&quot;}</pre>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ <div class='stump' id='13730530'>
149
+ <h2>
150
+ <span class='method'>POST</span>
151
+ <span class='path'>/hello</span>
152
+ on
153
+ <span class='time'>2010-01-16T23:57:01+09:00</span>
154
+ from
155
+ <span class='source'>127.0.0.1</span>
156
+ </h2>
157
+ <div>
158
+ <div class='headers'>
159
+ <h3>Headers</h3>
160
+ <table>
161
+ <tr>
162
+ <th>HTTP_ACCEPT</th>
163
+ <td>*/*</td>
164
+ </tr>
165
+ <tr>
166
+ <th>HTTP_HOST</th>
167
+ <td>localhost:8888</td>
168
+ </tr>
169
+ <tr>
170
+ <th>SERVER_NAME</th>
171
+ <td>localhost</td>
172
+ </tr>
173
+ <tr>
174
+ <th>CONTENT_LENGTH</th>
175
+ <td>27</td>
176
+ </tr>
177
+ <tr>
178
+ <th>HTTP_USER_AGENT</th>
179
+ <td>curl/7.19.5 (i386-apple-darwin9.7.0) libcurl/7.19.5 OpenSSL/0.9.8k zlib/1.2.3</td>
180
+ </tr>
181
+ <tr>
182
+ <th>REQUEST_PATH</th>
183
+ <td>/hello</td>
184
+ </tr>
185
+ <tr>
186
+ <th>SERVER_PROTOCOL</th>
187
+ <td>HTTP/1.1</td>
188
+ </tr>
189
+ <tr>
190
+ <th>CONTENT_TYPE</th>
191
+ <td>application/x-www-form-urlencoded</td>
192
+ </tr>
193
+ <tr>
194
+ <th>REMOTE_ADDR</th>
195
+ <td>127.0.0.1</td>
196
+ </tr>
197
+ <tr>
198
+ <th>PATH_INFO</th>
199
+ <td>/hello</td>
200
+ </tr>
201
+ <tr>
202
+ <th>SERVER_SOFTWARE</th>
203
+ <td>thin 1.2.5 codename This Is Not A Web Server</td>
204
+ </tr>
205
+ <tr>
206
+ <th>SCRIPT_NAME</th>
207
+ <td></td>
208
+ </tr>
209
+ <tr>
210
+ <th>HTTP_VERSION</th>
211
+ <td>HTTP/1.1</td>
212
+ </tr>
213
+ <tr>
214
+ <th>REQUEST_URI</th>
215
+ <td>/hello</td>
216
+ </tr>
217
+ <tr>
218
+ <th>SERVER_PORT</th>
219
+ <td>8888</td>
220
+ </tr>
221
+ <tr>
222
+ <th>REQUEST_METHOD</th>
223
+ <td>POST</td>
224
+ </tr>
225
+ <tr>
226
+ <th>QUERY_STRING</th>
227
+ <td></td>
228
+ </tr>
229
+ <tr>
230
+ <th>GATEWAY_INTERFACE</th>
231
+ <td>CGI/1.2</td>
232
+ </tr>
233
+ </table>
234
+ </div>
235
+ <div class='body'>
236
+ <h3>
237
+ Body
238
+ <span class='media_type'>application/x-www-form-urlencoded</span>
239
+ </h3>
240
+ <pre>{&quot;message&quot;=&gt;&quot;KON-NICHIWA&quot;, &quot;key&quot;=&gt;&quot;1st&quot;}</pre>
241
+ </div>
242
+ </div>
243
+ </div>
244
+ <div class='stump' id='13760510'>
245
+ <h2>
246
+ <span class='method'>GET</span>
247
+ <span class='path'>/hello</span>
248
+ on
249
+ <span class='time'>2010-01-16T23:57:01+09:00</span>
250
+ from
251
+ <span class='source'>127.0.0.1</span>
252
+ </h2>
253
+ <div>
254
+ <div class='headers'>
255
+ <h3>Headers</h3>
256
+ <table>
257
+ <tr>
258
+ <th>HTTP_ACCEPT</th>
259
+ <td>*/*</td>
260
+ </tr>
261
+ <tr>
262
+ <th>HTTP_HOST</th>
263
+ <td>localhost:8888</td>
264
+ </tr>
265
+ <tr>
266
+ <th>SERVER_NAME</th>
267
+ <td>localhost</td>
268
+ </tr>
269
+ <tr>
270
+ <th>HTTP_USER_AGENT</th>
271
+ <td>curl/7.19.5 (i386-apple-darwin9.7.0) libcurl/7.19.5 OpenSSL/0.9.8k zlib/1.2.3</td>
272
+ </tr>
273
+ <tr>
274
+ <th>REQUEST_PATH</th>
275
+ <td>/hello</td>
276
+ </tr>
277
+ <tr>
278
+ <th>SERVER_PROTOCOL</th>
279
+ <td>HTTP/1.1</td>
280
+ </tr>
281
+ <tr>
282
+ <th>REMOTE_ADDR</th>
283
+ <td>127.0.0.1</td>
284
+ </tr>
285
+ <tr>
286
+ <th>PATH_INFO</th>
287
+ <td>/hello</td>
288
+ </tr>
289
+ <tr>
290
+ <th>SERVER_SOFTWARE</th>
291
+ <td>thin 1.2.5 codename This Is Not A Web Server</td>
292
+ </tr>
293
+ <tr>
294
+ <th>SCRIPT_NAME</th>
295
+ <td></td>
296
+ </tr>
297
+ <tr>
298
+ <th>HTTP_VERSION</th>
299
+ <td>HTTP/1.1</td>
300
+ </tr>
301
+ <tr>
302
+ <th>REQUEST_URI</th>
303
+ <td>/hello</td>
304
+ </tr>
305
+ <tr>
306
+ <th>SERVER_PORT</th>
307
+ <td>8888</td>
308
+ </tr>
309
+ <tr>
310
+ <th>REQUEST_METHOD</th>
311
+ <td>GET</td>
312
+ </tr>
313
+ <tr>
314
+ <th>QUERY_STRING</th>
315
+ <td></td>
316
+ </tr>
317
+ <tr>
318
+ <th>GATEWAY_INTERFACE</th>
319
+ <td>CGI/1.2</td>
320
+ </tr>
321
+ </table>
322
+ </div>
323
+ </div>
324
+ </div>
325
+ </body>
326
+ </html>
327
+ <script type='text/javascript'>
328
+ //<![CDATA[
329
+ jQuery(function(){
330
+ $("div.stump .headers h3").click(function(){ $(this).next("table").toggle() });
331
+ $("div.stump .body h3").click(function(){ $(this).next("pre").toggle() });
332
+ $("div.stump .headers table").hide();
333
+ $("div.stump .body pre").hide();
334
+ });
335
+ //]]>
336
+ </script>
@@ -0,0 +1,26 @@
1
+ require 'ww/servlet'
2
+ require 'forwardable'
3
+
4
+ module Ww
5
+ class Application
6
+ attr_reader :current
7
+
8
+ def initialize(&servlet_initializer)
9
+ @servlet_initializer = servlet_initializer
10
+ reset!
11
+ end
12
+
13
+ def call(env)
14
+ current.call(env)
15
+ end
16
+
17
+ def reset!
18
+ @current = build_servlet
19
+ end
20
+
21
+ private
22
+ def build_servlet
23
+ Servlet.base(&@servlet_initializer)
24
+ end
25
+ end
26
+ end
data/lib/ww/server.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'thread'
2
+ require 'forwardable'
3
+ require 'ww/double'
4
+
5
+ module Ww
6
+ autoload :Application, 'ww/application'
7
+ class Server
8
+ extend Forwardable
9
+ @@servers = {}
10
+ @@handler = :webrick
11
+
12
+ class << self
13
+ def servers; @@servers; end
14
+
15
+ def handler; @@handler; end
16
+ def handler=(v); @@handler = v; end
17
+
18
+ def [](name); @@servers[name] ; end
19
+ def []=(name, server); @@servers[name] = server ; end
20
+
21
+ def build_double(port, &block)
22
+ new(Application.new(&block), port)
23
+ end
24
+ end
25
+
26
+ def_delegators :current_app, *double_methods = %w[
27
+ spy requests mock verify stub
28
+ ]
29
+
30
+ attr_reader :app, :port
31
+
32
+ def initialize(app, port)
33
+ @app = app
34
+ @port = port
35
+ @handler = ::Rack::Handler.get(self.class.handler)
36
+ end
37
+
38
+ def start_once
39
+ @app.reset!
40
+ start! unless running?
41
+ end
42
+
43
+ def running?; !!@running ; end
44
+
45
+ def start!
46
+ run_with_picking_server_instance!
47
+ @running = true
48
+ at_exit { shutdown! }
49
+ self
50
+ end
51
+
52
+ def shutdown!
53
+ return unless @running
54
+ shutdown_http_server
55
+ @thread.kill if @thread.alive?
56
+ @running = false
57
+ self
58
+ end
59
+
60
+ private
61
+ def run_with_picking_server_instance!
62
+ q = Queue.new
63
+ @thread = Thread.new { @handler.run(@app, :Port => @port) {|server| q << server } }
64
+ @server = q.pop
65
+ end
66
+
67
+ def shutdown_http_server
68
+ case @server.class.name
69
+ when "WEBrick::HTTPServer" then @server.shutdown
70
+ when "Thin::Server", "Mongrel::HttpServer" then @server.stop
71
+ else
72
+ @server.stop if @server.respond_to? :stop
73
+ end
74
+ end
75
+
76
+ def current_app
77
+ app.current
78
+ end
79
+ end
80
+ end
data/lib/ww/spy_eye.rb CHANGED
@@ -1,9 +1,25 @@
1
+ require 'rack'
1
2
  require 'forwardable'
2
3
  require 'time'
3
4
  require 'haml'
4
5
 
5
6
  module Ww
7
+ autoload :Servlet, 'ww/servlet'
6
8
  class SpyEye
9
+ class << self
10
+ def to_app(spy_eye_path = "/spy", &block)
11
+ Rack::Builder.new {
12
+ use Rack::ShowExceptions
13
+
14
+ servlet = Servlet.base(&block)
15
+ spy = SpyEye.new(servlet)
16
+
17
+ map(spy_eye_path) { run spy }
18
+ map("/") { run servlet }
19
+ }
20
+ end
21
+ end
22
+
7
23
  extend Forwardable
8
24
  def_delegator :@servlet, :requests
9
25
 
data/lib/ww.rb CHANGED
@@ -1,22 +1,16 @@
1
- require 'rubygems'
2
- require 'rack'
3
-
4
1
  module Ww
5
- autoload :Servlet, 'ww/servlet'
6
- autoload :SpyEye, 'ww/spy_eye'
7
-
8
- Version = '0.2.1'
9
-
10
- def to_app(spy_eye_path = "/spy", &block)
11
- Rack::Builder.new {
12
- use Rack::ShowExceptions
2
+ Version = '0.3.0'
13
3
 
14
- servlet = Servlet.base(&block)
15
- spy = SpyEye.new(servlet)
4
+ def to_app(*args, &block)
5
+ $stderr.puts <<-WORNING
6
+ *** DUPLICATION WORNING ***
7
+ Ww.to_app moves to Ww::SpyEye.to_app
16
8
 
17
- map(spy_eye_path) { run spy }
18
- map("/") { run servlet }
19
- }
9
+ This comatibility will be lost on 0.4.0.
10
+ ***************************
11
+ WORNING
12
+ require 'ww/spy_eye'
13
+ Ww::SpyEye.to_app(*args, &block)
20
14
  end
21
15
  module_function :to_app
22
16
  end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ $: << File.expand_path("../lib", File.dirname(__FILE__))
4
+
@@ -0,0 +1,35 @@
1
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
2
+ require 'ww/application'
3
+
4
+ describe Ww::Application do
5
+ before do
6
+ @container = Ww::Application.new do
7
+ get("/hello") do
8
+ "Hello World"
9
+ end
10
+ end
11
+
12
+ @client = Rack::MockRequest.new(@container)
13
+ end
14
+ subject { @client.get("/hello") }
15
+
16
+ describe "GET /hello" do
17
+ its(:status) { should == 200 }
18
+ its(:body) { should == "Hello World" }
19
+ end
20
+
21
+ describe "GET /hello (stubbed)" do
22
+ before do
23
+ @container.current.stub(:get, "/hello") { response = "Good night" }
24
+ end
25
+ its(:body) { should == "Good night" }
26
+
27
+ describe "refleshed" do
28
+ before do
29
+ @container.reset!
30
+ end
31
+
32
+ its(:body) { should == "Hello World" }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,144 @@
1
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
2
+ require 'ww/servlet'
3
+
4
+ describe Ww::Double, "with Servlet" do
5
+ before do
6
+ @server = Ww::Servlet.base do
7
+ get("/") do
8
+ response.status = 200
9
+ response["Content-Type"] = "text/plain"
10
+ response.body = "Hello World"
11
+ end
12
+ end
13
+ end
14
+
15
+ describe "stub(:get, '/dynamic_add')" do
16
+ before do
17
+ @server.stub(:get, '/dynamic_add') do
18
+ response.status = 200
19
+ response["Content-Type"] = "text/plain"
20
+ response.body = "Hi World"
21
+ end
22
+ end
23
+
24
+ subject{
25
+ @server.new.call( Rack::MockRequest.env_for("/dynamic_add", :method => "GET"))
26
+ }
27
+
28
+ it { should == [200, {"Content-Type"=>"text/plain", "Content-Length"=>"8"}, ["Hi World"]] }
29
+ end
30
+
31
+ describe "stub(:get, '/') # override" do
32
+ before do
33
+ @server.stub(:get, '/') do
34
+ response.status = 200
35
+ response["Content-Type"] = "text/plain"
36
+ response.body = "Hi World"
37
+ end
38
+ end
39
+
40
+ subject{
41
+ @server.new.call( Rack::MockRequest.env_for("/", :method => "GET"))
42
+ }
43
+
44
+ it { should == [200, {"Content-Type"=>"text/plain", "Content-Length"=>"8"}, ["Hi World"]] }
45
+ end
46
+
47
+ describe "stub(:get, '/') # re-define after app initialized" do
48
+ before do
49
+ @app = @server.new
50
+
51
+ @server.stub(:get, '/') do
52
+ response.status = 200
53
+ response["Content-Type"] = "text/plain"
54
+ response.body = "Hi! World"
55
+ end
56
+ end
57
+
58
+ subject{
59
+ @app.call( Rack::MockRequest.env_for("/", :method => "GET"))
60
+ }
61
+
62
+ it { should == [200, {"Content-Type"=>"text/plain", "Content-Length"=>"9"}, ["Hi! World"]] }
63
+ end
64
+
65
+ describe "mock(:get, '/')" do
66
+ before do
67
+ @server.mock(:get, '/') do
68
+ response.status = 200
69
+ response["Content-Type"] = "text/plain"
70
+ response.body = "Hi World"
71
+ end
72
+ end
73
+
74
+ describe "call" do
75
+ before do
76
+ app = @server.new
77
+ @response = app.call( Rack::MockRequest.env_for("/", :method => "GET"))
78
+ end
79
+
80
+ subject{ @response }
81
+
82
+ it { should == [200, {"Content-Type"=>"text/plain", "Content-Length"=>"8"}, ["Hi World"]] }
83
+ it {
84
+ expect{ @server.verify }.should_not raise_error Ww::Double::MockError
85
+ }
86
+ end
87
+
88
+ describe "don't call" do
89
+ it { expect{ @server.verify }.should raise_error Ww::Double::MockError }
90
+ end
91
+ end
92
+
93
+ describe "spy(:get, '/')" do
94
+ before do
95
+ @server.spy(:get, '/') do
96
+ response.status = 200
97
+ response["Content-Type"] = "text/plain"
98
+ response.body = "Hi World"
99
+ end
100
+ end
101
+
102
+ describe "GET / リクエストの" do
103
+ before do
104
+ app = @server.new
105
+ @response = app.call( Rack::MockRequest.env_for("/", :method => "GET"))
106
+ end
107
+
108
+ subject{ @server.requests.first }
109
+
110
+ it { should be_a Rack::Request }
111
+ its(:request_method) { should == 'GET' }
112
+ its(:fullpath) { should == "/" }
113
+
114
+ it "bodyは空のIOであること" do
115
+ subject.body.rewind
116
+ subject.body.read.should == ""
117
+ end
118
+
119
+ it "レスポンスは想定どおりのものであること" do
120
+ @response.should ==
121
+ [200, {"Content-Type"=>"text/plain", "Content-Length"=>"8"}, ["Hi World"]]
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "spy(:get, '/') backword compat" do
127
+ before do
128
+ @server.get('/backword') do
129
+ stump!
130
+ response.status = 200
131
+ response["Content-Type"] = "text/plain"
132
+ response.body = "Hi World"
133
+ end
134
+
135
+ app = @server.new
136
+ @response = app.call( Rack::MockRequest.env_for("/backword", :method => "GET"))
137
+ end
138
+
139
+ subject{ @server.requests }
140
+ it { should_not be_empty }
141
+ it { @server.requests.first.should be_a Ww::Double::Spy::Request }
142
+ end
143
+ end
144
+
@@ -0,0 +1,74 @@
1
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
2
+
3
+ require 'json'
4
+ require 'ww/double'
5
+ require 'ww/double/spy/request'
6
+
7
+ describe Ww::Double::Spy::Request do
8
+ describe "GET /" do
9
+ before do
10
+ base = Rack::Request.new(Rack::MockRequest.env_for("/", :method => "GET"))
11
+ @request = Ww::Double::Spy::Request.new(base)
12
+ end
13
+
14
+ subject { @request }
15
+ its(:request_method) { should == "GET" }
16
+ its(:parsed_body) { should == "" }
17
+ end
18
+
19
+ def post_env(path, content_type, body)
20
+ Rack::MockRequest.env_for(
21
+ path, :method => "POST", :input => body
22
+ ).merge("CONTENT_TYPE" => content_type)
23
+ end
24
+
25
+ describe "POST /json_api" do
26
+ before do
27
+ @request = Ww::Double::Spy::Request.new(
28
+ post_env("/json_api", "application/json", JSON.dump({"json" => true}))
29
+ )
30
+ end
31
+
32
+ subject { @request }
33
+ its(:request_method) { should == "POST" }
34
+ its(:parsed_body) { should == {"json" => true} }
35
+ end
36
+
37
+ describe "POST /yaml_api" do
38
+ before do
39
+ @request = Ww::Double::Spy::Request.new(
40
+ post_env("/yaml_api", "application/yaml", {"yaml" => true}.to_yaml)
41
+ )
42
+ end
43
+
44
+ subject { @request }
45
+ its(:parsed_body) { should == {"yaml" => true} }
46
+ end
47
+
48
+ describe "POST /www_url_encoded" do
49
+ before do
50
+ body = {"www_url_encoded" => true, "multipart_formdata" => false}.map { |k,v|
51
+ "#{Rack::Utils.escape(k)}=#{Rack::Utils.escape(v)}"
52
+ }.join("&")
53
+
54
+ @request = Ww::Double::Spy::Request.new(
55
+ post_env("/post", "application/x-www-form-urlencoded", body)
56
+ )
57
+ end
58
+
59
+ subject { @request }
60
+ its(:parsed_body) { should == {"multipart_formdata"=>"false", "www_url_encoded"=>"true"} }
61
+ end
62
+
63
+ describe "POST /unkown_type" do
64
+ before do
65
+ @request = Ww::Double::Spy::Request.new(
66
+ post_env("/post", "application/zip", "--not-changed-dummy-string--")
67
+ )
68
+ end
69
+
70
+ subject { @request }
71
+ its(:parsed_body) { should == "--not-changed-dummy-string--" }
72
+ end
73
+ end
74
+
@@ -0,0 +1,73 @@
1
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
2
+ require 'ww/server'
3
+ require 'open-uri'
4
+ require 'json'
5
+
6
+ describe Ww::Server do
7
+ before do
8
+ Ww::Server.handler = :mongrel # Mongrel is most silent.
9
+ Ww::Server[:spec] ||= Ww::Server.build_double(3080) do
10
+ get("/goodnight") { "Good night" }
11
+ spy(:get, "/hello") { "Hello world" }
12
+ end
13
+ Ww::Server[:spec].start_once
14
+ end
15
+
16
+ describe "store only spy-ed action" do
17
+ before do
18
+ ignore = URI("http://localhost:3080/goodnight").read
19
+ ignore = URI("http://localhost:3080/hello").read
20
+ end
21
+
22
+ subject { Ww::Server[:spec].requests }
23
+ it { should have(1).items }
24
+ it { subject.first.path.should == "/hello" }
25
+ end
26
+
27
+ describe "spying POST action" do
28
+ before do
29
+ Ww::Server[:spec].spy(:post, "/message") { status(200) }
30
+
31
+ Net::HTTP.start("localhost", 3080) do |http|
32
+ post = Net::HTTP::Post.new("/message")
33
+ post["Content-Type"] = "application/json"
34
+ post.body = {:message => "I'm double Ruby.", :madeby => "moro"}.to_json
35
+ http.request post
36
+ end
37
+ end
38
+ subject { Ww::Server[:spec].requests.first }
39
+
40
+ its(:parsed_body) do
41
+ should == {"message" => "I'm double Ruby.", "madeby" => "moro"}
42
+ end
43
+ end
44
+
45
+ describe "with stubing" do
46
+ before do
47
+ # validates it's not stubbed.
48
+ URI("http://localhost:3080/goodnight").read.should == "Good night"
49
+ Ww::Server[:spec].stub(:get, "/goodnight") { "I'm sleepy, too" }
50
+ end
51
+
52
+ subject { URI("http://localhost:3080/goodnight").read }
53
+ it { should == "I'm sleepy, too" }
54
+ end
55
+
56
+ describe "mocking" do
57
+ before do
58
+ Ww::Server[:spec].mock(:get, "/goodnight") do
59
+ "OYASUMI-NASAI"
60
+ end
61
+ end
62
+
63
+ it "pass if access there" do
64
+ ignore = URI("http://localhost:3080/goodnight").read
65
+ expect{ Ww::Server[:spec].verify }.should_not raise_error
66
+ end
67
+
68
+ it "fail unless access there" do
69
+ expect{ Ww::Server[:spec].verify }.should raise_error Ww::Double::MockError
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,39 @@
1
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
2
+ require 'ww/server'
3
+ require 'open-uri'
4
+ require 'json'
5
+
6
+ describe Ww::Server do
7
+ before do
8
+ Ww::Server.handler = :mongrel # Mongrel is most silent.
9
+ Ww::Server[:spec] ||= Ww::Server.build_double(3080) do
10
+ get("/goodnight") { "Good night" }
11
+ spy(:get, "/hello") { "Hello world" }
12
+ end
13
+ Ww::Server[:spec].start_once
14
+ end
15
+ subject { Ww::Server[:spec] }
16
+ it { should be_running }
17
+ it "should works fine" do
18
+ URI("http://localhost:3080/hello").read.should == "Hello world"
19
+ URI("http://localhost:3080/goodnight").read.should == "Good night"
20
+ end
21
+ its(:port){ should == 3080 }
22
+
23
+ describe "shutdown!" do
24
+ before do
25
+ # mongrel fails to shutdon before accepting any req.
26
+ URI("http://localhost:3080/hello").read
27
+ Ww::Server[:spec].shutdown!
28
+ end
29
+
30
+ it { should_not be_running }
31
+
32
+ it "the server should be down" do
33
+ expect { URI("http://localhost:3080/hello").read }.should \
34
+ raise_error Errno::ECONNREFUSED
35
+ end
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,24 @@
1
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
2
+ require 'ww/servlet'
3
+
4
+ describe Ww::Servlet do
5
+ before do
6
+ @server = Ww::Servlet.base do
7
+ get("/") do
8
+ response.status = 200
9
+ response["Content-Type"] = "text/plain"
10
+ response.body = "Hello World"
11
+ end
12
+ end
13
+ end
14
+ subject{ @server }
15
+ it { should be_instance_of Class }
16
+
17
+ describe "GET /" do
18
+ subject do
19
+ @server.new.call( Rack::MockRequest.env_for("/", :method => "GET"))
20
+ end
21
+
22
+ it { should == [200, {"Content-Type"=>"text/plain", "Content-Length"=>"11"}, ["Hello World"]] }
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ww
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - moro
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-14 00:00:00 +09:00
12
+ date: 2010-01-17 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -62,16 +62,27 @@ extra_rdoc_files: []
62
62
 
63
63
  files:
64
64
  - Rakefile
65
+ - spec/spec_helper.rb
66
+ - spec/ww/application_spec.rb
67
+ - spec/ww/double_spec.rb
68
+ - spec/ww/double_spy_request_spec.rb
69
+ - spec/ww/server_integration_spec.rb
70
+ - spec/ww/server_spec.rb
71
+ - spec/ww/servlet_spec.rb
72
+ - lib/ww/application.rb
65
73
  - lib/ww/double/mock.rb
66
74
  - lib/ww/double/spy/request.rb
67
75
  - lib/ww/double/spy.rb
68
76
  - lib/ww/double/stub.rb
69
77
  - lib/ww/double.rb
78
+ - lib/ww/server.rb
70
79
  - lib/ww/servlet.rb
71
80
  - lib/ww/spy_eye.html.haml
72
81
  - lib/ww/spy_eye.rb
73
82
  - lib/ww/store.rb
74
83
  - lib/ww.rb
84
+ - example/spy_eye.ru
85
+ - example/spy_eye_output.html
75
86
  has_rdoc: true
76
87
  homepage: http://github.com/moro/ww/
77
88
  licenses: []