forked from francois2metz/em-eventsource
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathem-eventsource_spec.rb
executable file
·226 lines (205 loc) · 7.34 KB
/
em-eventsource_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#!/usr/bin/env ruby
# encoding: utf-8
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
require "minitest/autorun"
require "minitest-spec-context"
describe EventMachine::EventSource do
def start_source(url="http://example.com/streaming", query={}, headers={})
EM.run do
source = EventMachine::EventSource.new(url, query, headers)
source.start
req = source.instance_variable_get "@req"
yield source, req if block_given?
end
end
def create_response_headers(status, content_type="", other={})
headers = EM::HttpResponseHeader.new
headers.http_status = status
headers['CONTENT_TYPE'] = content_type
headers.merge!(other)
end
it "connect to the good server" do
start_source do |source, req|
source.ready_state.must_equal EM::EventSource::CONNECTING
source.url.must_equal "http://example.com/streaming"
req.url.must_equal "http://example.com/streaming"
req.opts[:inactivity_timeout].must_equal 60
req.get_args[0].must_equal({ :query => {},
:head => {"Cache-Control" => "no-cache",
"Accept" => "text/event-stream"} })
EM.stop
end
end
it "connect to the good server with query and headers" do
start_source "http://example.net/streaming", {:chuck => "norris"}, {"DNT" => 1} do |source, req|
req.url.must_equal "http://example.net/streaming"
req.get_args[0].must_equal({ :query => {:chuck => "norris"},
:head => {"DNT" => 1,
"Cache-Control" => "no-cache",
"Accept" => "text/event-stream"} })
EM.stop
end
end
it "connect and error if status != 200" do
start_source do |source, req|
source.error do |error|
error.must_equal "Unexpected response status 400"
source.ready_state.must_equal EM::EventSource::CLOSED
EM.stop
end
source.open { assert false }
req.call_headers(create_response_headers "400")
end
end
it "connect and error if the content-type doens't match text/event-stream" do
start_source do |source, req|
source.error do |error|
error.must_equal "The content-type 'text/plop' is not text/event-stream"
source.ready_state.must_equal EM::EventSource::CLOSED
EM.stop
end
req.call_headers(create_response_headers "200", "text/plop")
end
end
it "connect and error if the content-type is not set" do
start_source do |source, req|
source.error do |error|
error.must_equal "The content-type '' is not text/event-stream"
EM.stop
end
req.call_headers(create_response_headers "200", "", "HEADER_NAME" => "BAD")
end
end
it "connect without error with 200 and good content-type" do
start_source do |source, req|
source.error do
assert false
end
source.open do
source.ready_state.must_equal EM::EventSource::OPEN
assert true
EM.stop
end
req.call_headers(create_response_headers "200", "text/event-stream; charset=utf-8")
end
end
{"LF" => "\n", "CRLF" => "\r\n"}.each do |eol_desc, eol|
context "with #{eol_desc} EOL" do
it "connect and handle message" do
start_source do |source, req|
source.message do |message|
message.must_equal "hello world"
source.close
EM.stop
end
req.stream_data("data: hello world#{eol}#{eol}")
end
end
it "handle multiple messages" do
start_source do |source, req|
source.message do |message|
message.must_equal "hello world\nplop"
source.close
EM.stop
end
req.stream_data("data: hello world#{eol}data:plop#{eol}#{eol}")
end
end
it "ignore empty message" do
start_source do |source, req|
source.message do |message|
message.must_equal "hello world"
EM.stop
end
req.stream_data(":#{eol}#{eol}")
req.stream_data("data: hello world#{eol}#{eol}")
end
end
it "handle event name" do
start_source do |source, req|
source.on "plop" do |message|
message.must_equal "hello world"
source.close
EM.stop
end
req.stream_data("data: hello world#{eol}event:plop#{eol}#{eol}")
end
end
it "reconnect after error with last-event-id" do
start_source do |source, req|
req.stream_data("id: roger#{eol}#{eol}")
source.error do |error|
error.must_equal "Connection lost. Reconnecting."
source.ready_state.must_equal EM::EventSource::CONNECTING
EM.add_timer(4) do
req2 = source.instance_variable_get "@req"
refute_same(req2, req)
source.last_event_id.must_equal "roger"
req2.get_args[0].must_equal({ :head => { "Last-Event-Id" => "roger",
"Accept" => "text/event-stream",
"Cache-Control" => "no-cache" },
:query => {} })
EM.stop
end
end
req.call_errback
end
end
it "reconnect after callback with last-event-id" do
start_source do |source, req|
req.stream_data("id: roger#{eol}#{eol}")
source.error do |error|
error.must_equal "Connection lost. Reconnecting."
source.ready_state.must_equal EM::EventSource::CONNECTING
EM.add_timer(4) do
req2 = source.instance_variable_get "@req"
refute_same(req2, req)
source.last_event_id.must_equal "roger"
req2.get_args[0].must_equal({ :head => { "Last-Event-Id" => "roger",
"Accept" => "text/event-stream",
"Cache-Control" => "no-cache" },
:query => {} })
EM.stop
end
end
req.call_callback
end
end
it "handle retry event" do
start_source do |source ,req|
req.stream_data("retry: plop#{eol}#{eol}")
source.retry.must_equal 3
req.stream_data("retry: 45plop#{eol}#{eol}")
source.retry.must_equal 3
req.stream_data("retry: 45#{eol}#{eol}")
source.retry.must_equal 45
EM.stop
end
end
end
end
it "add connection middlewares" do
start_source do |source ,req|
proc = Proc.new {}
source.use "oup", "la", "boom", &proc
source.close
source.start
req2 = source.instance_variable_get "@req"
req2.middlewares.must_equal [["oup", "la", "boom", proc]]
EM.stop
end
end
it "allows to set the inactivity_timeout" do
EM.run do
source = EventMachine::EventSource.new("")
source.inactivity_timeout = 0
source.start
req = source.instance_variable_get "@req"
req.opts[:inactivity_timeout].must_equal 0
EM.stop
end
end
it "doesn't fail when trying to close not yet started source" do
EventMachine::EventSource.new("").close
end
end