groem 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,198 @@
1
+ require 'eventmachine'
2
+
3
+ module Groem
4
+ module Dummy
5
+ class Server < EM::Connection
6
+ include Groem::Constants
7
+
8
+ DEFAULT_HOST = 'localhost'
9
+ DEFAULT_PORT = 23052 # note one off to avoid port conflict
10
+
11
+ DEFAULT_RESPONSES = { :register => ['-OK', 0],
12
+ :notify => ['-OK', 0],
13
+ :callback => ['CLICK', 10]
14
+ }
15
+
16
+ class << self
17
+ def canned_responses
18
+ @canned_responses ||= DEFAULT_RESPONSES.dup
19
+ end
20
+
21
+ def reset_canned_responses
22
+ @canned_responses = nil
23
+ end
24
+
25
+ def respond_to_register_with(meth, err = 0)
26
+ canned_responses[:register] = [meth.to_s.upcase, err.to_i]
27
+ end
28
+
29
+ def respond_to_notify_with(meth, err = 0)
30
+ canned_responses[:notify] = [meth.to_s.upcase, err.to_i]
31
+ end
32
+
33
+ def callback_with(rslt, secs)
34
+ canned_responses[:callback] = [rslt.to_s.upcase, secs.to_i]
35
+ end
36
+
37
+ def listen(host = DEFAULT_HOST, port = DEFAULT_PORT)
38
+ svr = EM.start_server host, port, self
39
+ puts "SERVER: Dummy GNTP server listening on #{host}:#{port}"
40
+ canned_responses.each_pair do |k, v|
41
+ if k == :register || k == :notify
42
+ puts " #{k.to_s.upcase} responds #{v[0]} with status #{v[1]}"
43
+ elsif k == :callback
44
+ puts " #{k.to_s.upcase} with result #{v[0]} after #{v[1]} secs"
45
+ end
46
+ end
47
+ svr
48
+ end
49
+ end
50
+
51
+ def post_init
52
+ reset_state
53
+ end
54
+
55
+ def receive_data data
56
+ @buffer.extract(data).each do |line|
57
+ update_message_state!(line)
58
+ @lines << line
59
+ end
60
+ receive_message @lines.join("\r\n") + "\r\n" if eof?
61
+ end
62
+
63
+ protected
64
+
65
+ def reset_state
66
+ @buffer = BufferedTokenizer.new("\r\n")
67
+ @lines = []
68
+ @response = nil
69
+ @sections_left = 0
70
+ end
71
+
72
+ # Horribly kludgy but that's GNTP for you...
73
+ def update_message_state!(line)
74
+ if line[/^\s*Notifications-Count\s*:\s*(\d+)/i]
75
+ @sections_left += $1.to_i
76
+ end
77
+ if line[/^.+:\s*x-growl-resource:/i]
78
+ @sections_left += 1
79
+ end
80
+ if line.empty?
81
+ @sections_left -= 1
82
+ end
83
+ #puts line
84
+ #puts "Note: #{@sections_left} more sections"
85
+ end
86
+
87
+ def eof?
88
+ if @lines[-1].empty? && @sections_left > 0
89
+ puts "SERVER: CRLFCRLF received, but expecting #{@sections_left} more sections"
90
+ end
91
+ @lines[-1].empty? && @sections_left <= 0
92
+ end
93
+
94
+ def receive_message message
95
+ puts "SERVER: Received message"
96
+ klass = Class.new { include Groem::Marshal::Request }
97
+ raw = klass.load(message, false)
98
+ #puts "Parsed message:\n#{raw.inspect}"
99
+ prepare_responses_for(raw)
100
+ if @response
101
+ send_data @response
102
+ puts "SERVER: Sent response"
103
+ end
104
+ end
105
+
106
+ def canned_responses; self.class.canned_responses; end
107
+
108
+ def prepare_responses_for(req)
109
+ case req['environment']['request_method']
110
+ when 'REGISTER'
111
+ prepare_register_response_for(req,
112
+ canned_responses[:register][0],
113
+ canned_responses[:register][1]
114
+ )
115
+ when 'NOTIFY'
116
+ prepare_notify_response_for(req,
117
+ canned_responses[:notify][0],
118
+ canned_responses[:notify][1]
119
+ )
120
+ schedule_callback_response_for(req,
121
+ canned_responses[:callback][0],
122
+ canned_responses[:callback][1]
123
+ ) \
124
+ if req['headers']['Notification-Callback-Context']
125
+ end
126
+ end
127
+
128
+ # eventually replace with Response#dump, quick & dirty for now
129
+ def prepare_register_response_for(req, meth, err)
130
+ env, hdrs = req[ENVIRONMENT_KEY], req[HEADERS_KEY]
131
+ out = []
132
+ out << "#{env[(GNTP_PROTOCOL_KEY)]}" +
133
+ "/#{env[(GNTP_VERSION_KEY)]} "+
134
+ "#{meth} "+
135
+ "#{env[(GNTP_ENCRYPTION_ID_KEY)]}"
136
+ out << "#{GNTP_RESPONSE_ACTION_KEY}: #{GNTP_REGISTER_METHOD}"
137
+ if meth == GNTP_ERROR_RESPONSE
138
+ out << "#{GNTP_ERROR_CODE_KEY}: #{err}"
139
+ out << "Error-Description: An error occurred"
140
+ end
141
+ out << nil
142
+ out << nil
143
+ out << nil
144
+ puts "SERVER: Prepared REGISTER response: #{meth}, #{err}"
145
+ @response = out.join("\r\n")
146
+ end
147
+
148
+ def prepare_notify_response_for(req, meth, err)
149
+ env, hdrs = req[ENVIRONMENT_KEY], req[HEADERS_KEY]
150
+ out = []
151
+ out << "#{env[(GNTP_PROTOCOL_KEY)]}" +
152
+ "/#{env[(GNTP_VERSION_KEY)]} "+
153
+ "#{meth} "+
154
+ "#{env[(GNTP_ENCRYPTION_ID_KEY)]}"
155
+ out << "#{GNTP_RESPONSE_ACTION_KEY}: #{GNTP_NOTIFY_METHOD}"
156
+ out << "#{GNTP_NOTIFICATION_ID_KEY}: #{hdrs[(GNTP_NOTIFICATION_ID_KEY)]}"
157
+ if meth == GNTP_ERROR_RESPONSE
158
+ out << "#{GNTP_ERROR_CODE_KEY}: #{err}"
159
+ out << "Error-Description: An error occurred"
160
+ end
161
+ out << nil
162
+ out << nil
163
+ out << nil
164
+ puts "SERVER: Prepared NOTIFY response: #{meth}, #{err}"
165
+ @response = out.join("\r\n")
166
+ end
167
+
168
+ def schedule_callback_response_for(req, rslt, secs)
169
+ EM.add_timer(secs) do
170
+ msg = callback_response_for(req, rslt)
171
+ send_data msg
172
+ puts "SERVER: Sent CALLBACK response: #{rslt}"
173
+ end
174
+ puts "SERVER: Scheduled CALLBACK response in #{secs} secs: #{rslt}"
175
+ end
176
+
177
+ def callback_response_for(req, rslt)
178
+ env, hdrs = req[ENVIRONMENT_KEY], req[HEADERS_KEY]
179
+ out = []
180
+ out << "#{env[(GNTP_PROTOCOL_KEY)]}" +
181
+ "/#{env[(GNTP_VERSION_KEY)]} "+
182
+ "#{GNTP_CALLBACK_RESPONSE} "+
183
+ "#{env[(GNTP_ENCRYPTION_ID_KEY)]}"
184
+ out << "#{GNTP_APPLICATION_NAME_KEY}: #{hdrs[(GNTP_APPLICATION_NAME_KEY)]}"
185
+ out << "#{GNTP_NOTIFICATION_ID_KEY}: #{hdrs[(GNTP_NOTIFICATION_ID_KEY)]}"
186
+ out << "#{GNTP_NOTIFICATION_CALLBACK_RESULT_KEY}: #{rslt}"
187
+ out << "#{GNTP_NOTIFICATION_CALLBACK_TIMESTAMP_KEY}: #{Time.now.strftime('%Y-%m-%d %H:%M:%SZ')}"
188
+ out << "#{GNTP_NOTIFICATION_CALLBACK_CONTEXT_KEY}: #{hdrs[(GNTP_NOTIFICATION_CALLBACK_CONTEXT_KEY)]}"
189
+ out << "#{GNTP_NOTIFICATION_CALLBACK_CONTEXT_TYPE_KEY}: #{hdrs[(GNTP_NOTIFICATION_CALLBACK_CONTEXT_TYPE_KEY)]}"
190
+ out << nil
191
+ out << nil
192
+ out << nil
193
+ out.join("\r\n")
194
+ end
195
+
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,31 @@
1
+
2
+ module DummyServerHelper
3
+
4
+ DEFAULT_PORT = Groem::Dummy::Server::DEFAULT_PORT
5
+
6
+ def self.fork_server(opts = {})
7
+ fork {
8
+ puts '-------------- server process fork ------------------'
9
+ Groem::Dummy::Server.reset_canned_responses
10
+ if opts[:register]
11
+ Groem::Dummy::Server.respond_to_register_with *opts[:register]
12
+ end
13
+ if opts[:notify]
14
+ Groem::Dummy::Server.respond_to_notify_with *opts[:notify]
15
+ end
16
+ if opts[:callback]
17
+ Groem::Dummy::Server.callback_with *opts[:callback]
18
+ end
19
+ EM.run {
20
+ Signal.trap("INT") { EM.next_tick { EM.stop } }
21
+ Groem::Dummy::Server.listen
22
+ }
23
+ puts '-------------- server process exiting -----------'
24
+ }
25
+ end
26
+
27
+ def self.kill_server(pid)
28
+ Process.kill("INT", pid)
29
+ end
30
+
31
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module MarshalHelper
3
+
4
+ def self.dummy_request_class
5
+ Class.new {
6
+ include(Groem::Marshal::Request)
7
+ require 'forwardable'
8
+ extend Forwardable
9
+ def_delegators :@raw, :[], :[]=
10
+ def raw; @raw ||= {}; end
11
+ def initialize(input = {})
12
+ @raw = input
13
+ end
14
+ }
15
+ end
16
+
17
+ def self.dummy_response_class
18
+ Class.new {
19
+ include(Groem::Marshal::Response)
20
+ require 'forwardable'
21
+ extend Forwardable
22
+ def_delegators :@raw, :[], :[]=
23
+ def raw; @raw ||= []; end
24
+ def initialize(input = [])
25
+ @raw = input
26
+ end
27
+ }
28
+ end
29
+
30
+ def self.dummy_request(env = {}, hdrs = {}, notifs = {})
31
+ klass = dummy_request_class
32
+ klass.new({'environment' => env,
33
+ 'headers' => hdrs,
34
+ 'notifications' => notifs
35
+ })
36
+ end
37
+
38
+
39
+
40
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ Bundler.setup :default
5
+
6
+ require 'lib/groem'
7
+
8
+ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'shared', '**', '*.rb'))].each do |f|
9
+ load f
10
+ end
11
+
12
+ Bundler.setup :development
13
+ require 'minitest/spec'
14
+ MiniTest::Unit.autorun
@@ -0,0 +1,77 @@
1
+ require File.join(File.dirname(__FILE__),'..','spec_helper')
2
+
3
+ describe 'Groem::App #[]' do
4
+
5
+ describe 'after initializing' do
6
+
7
+ it 'should set the application_name header based on input' do
8
+ @subject = Groem::App.new('thing')
9
+ @subject['headers']['Application-Name'].must_equal 'thing'
10
+ end
11
+
12
+ it 'should default the environment when no options passed' do
13
+ @subject = Groem::App.new('thing')
14
+ @subject['environment'].must_equal Groem::App::DEFAULT_ENV
15
+ end
16
+
17
+ it 'should merge keys from input environment option into default environment' do
18
+ input = {'version' => '1.2',
19
+ 'request_method' => 'HELLO',
20
+ 'encryption_id' => 'ABC'
21
+ }
22
+ @subject = Groem::App.new('thing', {:environment => input})
23
+ @subject['environment'].must_equal Groem::App::DEFAULT_ENV.merge(input)
24
+ end
25
+
26
+ it 'should set each option in headers hash besides environment, host, and port' do
27
+ opts = {:environment => {},
28
+ :host => 'foo',
29
+ :port => 12345,
30
+ :x_option_1 => '1',
31
+ :x_option_2 => '2',
32
+ :x_option_3 => '3'
33
+ }
34
+ @subject = Groem::App.new('thing', opts)
35
+ @subject['headers'].must_equal(
36
+ {'Application-Name' => 'thing',
37
+ 'X-Option-1' => '1',
38
+ 'X-Option-2' => '2',
39
+ 'X-Option-3' => '3'
40
+ }
41
+ )
42
+ end
43
+
44
+ it 'should initialize the notifications hash to empty' do
45
+ @subject = Groem::App.new('thing')
46
+ @subject['notifications'].must_equal({})
47
+ end
48
+
49
+ end
50
+
51
+ describe 'after setting header' do
52
+
53
+ it 'should add the header to the headers hash based on input' do
54
+ @subject = Groem::App.new('thing')
55
+ @subject.header('x_header', 'boo')
56
+ @subject['headers']['X-Header'].must_equal 'boo'
57
+ end
58
+
59
+ end
60
+
61
+
62
+ describe 'after setting notification' do
63
+
64
+ it 'should set the notifications hash defaulting enabled to true' do
65
+ @subject = Groem::App.new('thing')
66
+ @subject.notification 'action' do end
67
+ @subject['notifications'].keys.must_include 'action'
68
+ @subject['notifications']['action'].keys.must_include 'Notification-Enabled'
69
+ @subject['notifications']['action']['Notification-Enabled'].must_equal 'True'
70
+ end
71
+
72
+ end
73
+
74
+
75
+ end
76
+
77
+
@@ -0,0 +1,380 @@
1
+ require File.join(File.dirname(__FILE__),'..','spec_helper')
2
+
3
+ describe 'Groem::Marshal::Request.load' do
4
+
5
+ #------ REGISTER requests --------#
6
+
7
+ describe 'when valid REGISTER request with one notification and no binaries' do
8
+
9
+ before do
10
+ @input = <<-__________
11
+ GNTP/1.0 REGISTER NONE
12
+ Application-Name: SurfWriter
13
+ Application-Icon: http://www.site.org/image.jpg
14
+ X-Creator: Apple Software
15
+ X-Application-ID:08d6c05a21512a79a1dfeb9d2a8f262f
16
+ Notifications-Count: 1
17
+
18
+ Notification-Name: Download Complete
19
+ Notification-Display-Name: Download completed
20
+ Notification-Enabled:True
21
+ X-Language : English
22
+ X-Timezone: PST
23
+
24
+
25
+ __________
26
+ dummy = Class.new { include(Groem::Marshal::Request) }
27
+ @subject = dummy.load(@input, false)
28
+ end
29
+
30
+ it 'should return a hash with keys for environment, headers, and notifications' do
31
+ @subject.has_key?('environment').must_equal true
32
+ @subject.has_key?('headers').must_equal true
33
+ @subject.has_key?('notifications').must_equal true
34
+ end
35
+
36
+ it 'environment hash should have version == 1.0' do
37
+ @subject['environment']['version'].must_equal '1.0'
38
+ end
39
+
40
+ it 'environment hash should have request_method == REGISTER' do
41
+ @subject['environment']['request_method'].must_equal 'REGISTER'
42
+ end
43
+
44
+ it 'headers hash should have application_name == SurfWriter' do
45
+ @subject['headers']['Application-Name'].must_equal 'SurfWriter'
46
+ end
47
+
48
+ it 'headers hash should have notifications_count == 1' do
49
+ @subject['headers']['Notifications-Count'].must_equal '1'
50
+ end
51
+
52
+ it 'headers hash should have x_application_id == 08d6c05a21512a79a1dfeb9d2a8f262f' do
53
+ @subject['headers']['X-Application-ID'].must_equal '08d6c05a21512a79a1dfeb9d2a8f262f'
54
+ end
55
+
56
+ it 'notifications hash should have 1 key' do
57
+ @subject['notifications'].keys.size.must_equal 1
58
+ end
59
+
60
+ it 'notifications hash should have key \'Download Complete\'' do
61
+ @subject['notifications']['Download Complete'].wont_be_nil
62
+ end
63
+
64
+ it '\'Download Complete\' notification should have notification_display_name == \'Download completed\'' do
65
+ @subject['notifications']['Download Complete']['Notification-Display-Name'].must_equal 'Download completed'
66
+ end
67
+
68
+ it '\'Download Complete\' notification should have notification_enabled == \'True\'' do
69
+ @subject['notifications']['Download Complete']['Notification-Enabled'].must_equal 'True'
70
+ end
71
+
72
+ it '\'Download Complete\' notification should have x_timezone == \'PST\'' do
73
+ @subject['notifications']['Download Complete']['X-Timezone'].must_equal 'PST'
74
+ end
75
+
76
+ it '\'Download Complete\' notification should have x_language == \'English\'' do
77
+ @subject['notifications']['Download Complete']['X-Language'].must_equal 'English'
78
+ end
79
+
80
+ it 'headers hash should not have x_timezone key' do
81
+ @subject['headers'].has_key?('X-Timezone').must_equal false
82
+ end
83
+
84
+ end
85
+
86
+ describe 'when valid REGISTER request with three notifications and no binaries' do
87
+
88
+ before do
89
+ @input = <<-__________
90
+ GNTP/1.0 REGISTER NONE
91
+ Application-Name: SurfWriter
92
+ Application-Icon: http://www.site.org/image.jpg
93
+ X-Creator: Apple Software
94
+ X-Application-ID: 08d6c05a21512a79a1dfeb9d2a8f262f
95
+ Notifications-Count: 3
96
+
97
+ Notification-Name: Download Complete
98
+ Notification-Display-Name: Download completed
99
+ Notification-Enabled: True
100
+ X-Language: English
101
+ X-Timezone: PST
102
+
103
+ Notification-Name: Download Started
104
+ Notification-Display-Name: Download starting
105
+ Notification-Enabled: False
106
+ X-Timezone: GMT
107
+
108
+ Notification-Name: Download Error
109
+ Notification-Display-Name: Error downloading
110
+ Notification-Enabled: True
111
+ X-Language: Spanish
112
+
113
+ __________
114
+ dummy = Class.new { include(Groem::Marshal::Request) }
115
+ @subject = dummy.load(@input, false)
116
+ end
117
+
118
+ it 'should return a hash with keys for environment, headers, and notifications' do
119
+ @subject.has_key?('environment').must_equal true
120
+ @subject.has_key?('headers').must_equal true
121
+ @subject.has_key?('notifications').must_equal true
122
+ end
123
+
124
+ it 'notifications hash should have 3 keys' do
125
+ @subject['notifications'].keys.size.must_equal 3
126
+ end
127
+
128
+ it 'notifications hash should have key \'Download Complete\'' do
129
+ @subject['notifications']['Download Complete'].wont_be_nil
130
+ end
131
+
132
+ it 'notifications hash should have key \'Download Started\'' do
133
+ @subject['notifications']['Download Started'].wont_be_nil
134
+ end
135
+
136
+ it 'notifications hash should have key \'Download Error\'' do
137
+ @subject['notifications']['Download Error'].wont_be_nil
138
+ end
139
+
140
+ it '\'Download Complete\' notification should have notification_display_name == \'Download completed\'' do
141
+ @subject['notifications']['Download Complete']['Notification-Display-Name'].must_equal 'Download completed'
142
+ end
143
+
144
+ it '\'Download Started\' notification should have notification_enabled == \'False\'' do
145
+ @subject['notifications']['Download Started']['Notification-Enabled'].must_equal 'False'
146
+ end
147
+
148
+ it '\'Download Error\' notification should have x_language == \'Spanish\'' do
149
+ @subject['notifications']['Download Error']['X-Language'].must_equal 'Spanish'
150
+ end
151
+
152
+ it '\'Download Started\' notification should not have X-Language key' do
153
+ @subject['notifications']['Download Started'].has_key?('X-Language').must_equal false
154
+ end
155
+
156
+ it '\'Download Error\' notification should not have X-Timezone key' do
157
+ @subject['notifications']['Download Error'].has_key?('X-Timezone').must_equal false
158
+ end
159
+
160
+ end
161
+
162
+ describe 'when valid REGISTER request with one binary referenced once in headers' do
163
+
164
+ end
165
+
166
+ describe 'when valid REGISTER request with one binary referenced once in notifications' do
167
+
168
+ end
169
+
170
+ describe 'when valid REGISTER request with three binaries referenced once each in headers and notifications' do
171
+
172
+ end
173
+
174
+ describe 'when valid REGISTER request with three binaries referenced twice each in headers and notifications' do
175
+
176
+ end
177
+
178
+
179
+ #------ NOTIFY requests --------#
180
+
181
+ describe 'when valid NOTIFY request with no binaries' do
182
+
183
+ before do
184
+ @input = <<-__________
185
+ GNTP/1.0 NOTIFY NONE
186
+ Application-Name: SurfWriter
187
+ Notification-Name: Download Complete
188
+ Notification-ID: 999
189
+ Notification-Title:XYZ finished downloading
190
+ Notification-Sticky: True
191
+ Notification-Icon : http://www.whatever.com/poo.jpg
192
+
193
+ __________
194
+ dummy = Class.new { include(Groem::Marshal::Request) }
195
+ @subject = dummy.load(@input, false)
196
+ end
197
+
198
+ it 'should return a hash with keys for environment, headers, and notifications' do
199
+ @subject.has_key?('environment').must_equal true
200
+ @subject.has_key?('headers').must_equal true
201
+ @subject.has_key?('notifications').must_equal true
202
+ end
203
+
204
+ it 'environment hash should have version == 1.0' do
205
+ @subject['environment']['version'].must_equal '1.0'
206
+ end
207
+
208
+ it 'environment hash should have request_method == NOTIFY' do
209
+ @subject['environment']['request_method'].must_equal 'NOTIFY'
210
+ end
211
+
212
+ it 'headers hash should have application_name == SurfWriter' do
213
+ @subject['headers']['Application-Name'].must_equal 'SurfWriter'
214
+ end
215
+
216
+ it 'headers hash should have notification_title == \'XYZ finished downloading\'' do
217
+ @subject['headers']['Notification-Title'].must_equal 'XYZ finished downloading'
218
+ end
219
+
220
+ it 'headers hash should have notification_sticky == \'True\'' do
221
+ @subject['headers']['Notification-Sticky'].must_equal 'True'
222
+ end
223
+
224
+ it 'headers hash should have notification_icon == \'http://www.whatever.com/poo.jpg\'' do
225
+ @subject['headers']['Notification-Icon'].must_equal 'http://www.whatever.com/poo.jpg'
226
+ end
227
+
228
+ it 'notifications hash should be empty' do
229
+ @subject['notifications'].empty?.must_equal true
230
+ end
231
+
232
+ end
233
+
234
+ describe 'when valid NOTIFY request with one binary referenced once' do
235
+
236
+ end
237
+
238
+ describe 'when valid NOTIFY request with three binaries referenced once each' do
239
+
240
+ end
241
+
242
+ describe 'when valid NOTIFY request with three binaries referenced twice each' do
243
+
244
+ end
245
+
246
+ end
247
+
248
+
249
+
250
+ #---------- dump -----------#
251
+
252
+
253
+ describe 'Groem::Marshal::Request#dump' do
254
+
255
+ describe 'when valid REGISTER request with one notification, no binaries' do
256
+
257
+ before do
258
+ @input_env = { 'protocol' => 'GNTP',
259
+ 'version' => '1.0',
260
+ 'request_method' => 'REGISTER',
261
+ 'encryption_id' => 'NONE'
262
+ }
263
+ @input_hdrs = {'Application-Name' => 'SurfWriter',
264
+ 'Application-Icon' => 'http://www.site.org/image.jpg'
265
+ }
266
+ @input_notifs = { 'Download Complete' => {
267
+ 'Notification-Display-Name' => 'Download completed',
268
+ 'Notification-Enabled' => 'True',
269
+ 'X-Language' => 'English',
270
+ 'X-Timezone' => 'PST'
271
+ }
272
+ }
273
+
274
+ @subject = MarshalHelper.dummy_request(
275
+ @input_env, @input_hdrs, @input_notifs).dump
276
+ end
277
+
278
+ it 'should output a string' do
279
+ @subject.class.must_be_same_as String
280
+ puts
281
+ puts '------------Groem::Marshal::Request#dump when valid REGISTER request with one notification, no binaries ------------'
282
+ puts @subject
283
+ end
284
+
285
+ it 'should output 10 lines terminated by CRLF' do
286
+ lines = @subject.split("\r\n")
287
+ lines.size.must_equal 10
288
+ end
289
+
290
+ it 'should end with 2 CRLF' do
291
+ @subject[-4,4].must_equal "\r\n\r\n"
292
+ end
293
+
294
+ it 'should output the first line as the standard GNTP first header' do
295
+ lines = @subject.split("\r\n")
296
+ lines[0].must_match(/^#{@input_env['protocol']}\/#{@input_env['version']}\s+#{@input_env['request_method']}\s+#{@input_env['encryption_id']}\s*$/i)
297
+ end
298
+
299
+ it 'should output the notification count == count of input notifications' do
300
+ @subject.must_match(/^\s*Notifications-Count\s*:\s*#{@input_notifs.keys.count}\s*$/i)
301
+ end
302
+
303
+ it 'should have a notification-name line for each input notification' do
304
+ @input_notifs.each_pair do |name, pairs|
305
+ @subject.must_match(/^\s*Notification-Name\s*:\s*#{name}\s*$/i)
306
+ end
307
+ end
308
+
309
+ end
310
+
311
+ describe 'when valid NOTIFY request with one notification, no binaries' do
312
+
313
+ before do
314
+ @input_env = { 'protocol' => 'GNTP',
315
+ 'version' => '1.0',
316
+ 'request_method' => 'NOTIFY',
317
+ 'encryption_id' => 'NONE'
318
+ }
319
+ @input_hdrs = {'Application-Name' => 'SurfWriter',
320
+ 'Notification-Name'=> 'Download Complete',
321
+ 'Notification-Id' => '999',
322
+ 'Notification-Title' => 'XYZ finished downloading',
323
+ 'Notification-Sticky' => 'True',
324
+ 'Notification-Icon' => 'http://www.whatever.com/poo.jpg'
325
+ }
326
+ @subject = MarshalHelper.dummy_request(
327
+ @input_env, @input_hdrs, {}).dump
328
+ end
329
+
330
+ it 'should output a string' do
331
+ @subject.class.must_be_same_as String
332
+ puts
333
+ puts '------------Groem::Marshal::Request#dump when valid NOTIFY request with one notification, no binaries ------------'
334
+ puts @subject
335
+ end
336
+
337
+ it 'should output the first line as the standard GNTP first header for NOTIFY request' do
338
+ lines = @subject.split("\r\n")
339
+ lines[0].must_match(/^GNTP\/1.0\s+NOTIFY\s+NONE\s*$/i)
340
+ end
341
+
342
+ it 'should not output a notification-count line' do
343
+ @subject.wont_match(/^\s*Notifications-Count\s*:\s*\d+\s*$/i)
344
+ end
345
+
346
+ end
347
+
348
+ describe 'when no environment' do
349
+
350
+ before do
351
+ @input_hdrs = {'Application-Name' => 'SurfWriter',
352
+ 'Notification-Name'=> 'Download Complete',
353
+ 'Notification-ID' => '999',
354
+ 'Notification-Title' => 'XYZ finished downloading',
355
+ 'Notification-Sticky' => 'True',
356
+ 'Notification-Icon' => 'http://www.whatever.com/poo.jpg'
357
+ }
358
+ @subject = MarshalHelper.dummy_request(
359
+ {}, @input_hdrs, {}).dump
360
+ end
361
+
362
+ it 'should output a string' do
363
+ @subject.class.must_be_same_as String
364
+ puts
365
+ puts '------------Groem::Marshal::Request#dump when no environment ------------'
366
+ puts @subject
367
+ end
368
+
369
+ it 'should output the first line as the default GNTP first header for NOTIFY request' do
370
+ lines = @subject.split("\r\n")
371
+ lines[0].must_match(/^GNTP\/1.0\s+NOTIFY\s+NONE\s*$/i)
372
+ end
373
+
374
+ it 'should not output a notification-count line' do
375
+ @subject.wont_match(/^\s*Notifications-Count\s*:\s*\d+\s*$/i)
376
+ end
377
+
378
+ end
379
+
380
+ end