ww 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: []