faye 0.8.8 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +16 -10
- data/README.rdoc +1 -1
- data/lib/faye-browser-min.js +1 -1
- data/lib/faye-browser-min.js.map +2 -2
- data/lib/faye-browser.js +302 -287
- data/lib/faye.rb +21 -21
- data/lib/faye/adapters/rack_adapter.rb +50 -48
- data/lib/faye/adapters/static_server.rb +22 -22
- data/lib/faye/engines/connection.rb +13 -13
- data/lib/faye/engines/memory.rb +21 -21
- data/lib/faye/engines/proxy.rb +23 -23
- data/lib/faye/error.rb +6 -6
- data/lib/faye/mixins/logging.rb +12 -12
- data/lib/faye/mixins/publisher.rb +6 -6
- data/lib/faye/mixins/timeouts.rb +1 -1
- data/lib/faye/protocol/channel.rb +24 -24
- data/lib/faye/protocol/client.rb +71 -73
- data/lib/faye/protocol/extensible.rb +7 -7
- data/lib/faye/protocol/grammar.rb +13 -13
- data/lib/faye/protocol/server.rb +57 -57
- data/lib/faye/protocol/socket.rb +4 -4
- data/lib/faye/protocol/subscription.rb +4 -4
- data/lib/faye/transport/http.rb +13 -13
- data/lib/faye/transport/local.rb +5 -5
- data/lib/faye/transport/transport.rb +25 -25
- data/lib/faye/transport/web_socket.rb +34 -30
- data/lib/faye/util/namespace.rb +4 -4
- data/spec/browser.html +5 -5
- data/spec/javascript/channel_spec.js +3 -3
- data/spec/javascript/client_spec.js +104 -98
- data/spec/javascript/engine/memory_spec.js +1 -1
- data/spec/javascript/engine_spec.js +70 -70
- data/spec/javascript/faye_spec.js +6 -6
- data/spec/javascript/grammar_spec.js +12 -12
- data/spec/javascript/node_adapter_spec.js +46 -46
- data/spec/javascript/publisher_spec.js +4 -4
- data/spec/javascript/server/connect_spec.js +21 -21
- data/spec/javascript/server/disconnect_spec.js +15 -15
- data/spec/javascript/server/extensions_spec.js +6 -6
- data/spec/javascript/server/handshake_spec.js +18 -18
- data/spec/javascript/server/integration_spec.js +23 -23
- data/spec/javascript/server/publish_spec.js +9 -9
- data/spec/javascript/server/subscribe_spec.js +30 -30
- data/spec/javascript/server/unsubscribe_spec.js +30 -30
- data/spec/javascript/server_spec.js +15 -15
- data/spec/javascript/transport_spec.js +32 -27
- data/spec/node.js +2 -2
- data/spec/ruby/channel_spec.rb +2 -2
- data/spec/ruby/client_spec.rb +100 -92
- data/spec/ruby/engine_examples.rb +51 -51
- data/spec/ruby/faye_spec.rb +5 -5
- data/spec/ruby/grammar_spec.rb +12 -12
- data/spec/ruby/publisher_spec.rb +4 -4
- data/spec/ruby/rack_adapter_spec.rb +34 -34
- data/spec/ruby/server/connect_spec.rb +22 -22
- data/spec/ruby/server/disconnect_spec.rb +16 -16
- data/spec/ruby/server/extensions_spec.rb +8 -8
- data/spec/ruby/server/handshake_spec.rb +20 -20
- data/spec/ruby/server/integration_spec.rb +22 -24
- data/spec/ruby/server/publish_spec.rb +9 -9
- data/spec/ruby/server/subscribe_spec.rb +31 -31
- data/spec/ruby/server/unsubscribe_spec.rb +31 -31
- data/spec/ruby/server_spec.rb +17 -17
- data/spec/ruby/transport_spec.rb +23 -23
- data/spec/testswarm +23 -10
- data/spec/thin_proxy.rb +5 -5
- metadata +90 -59
data/lib/faye/transport/local.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
module Faye
|
2
|
-
|
2
|
+
|
3
3
|
class Transport::Local < Transport
|
4
4
|
def self.usable?(client, endpoint, &callback)
|
5
5
|
callback.call(endpoint.is_a?(Server))
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def batching?
|
9
9
|
false
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def request(message, timeout)
|
13
13
|
message = Faye.copy_object(message)
|
14
14
|
@endpoint.process(message, true) do |responses|
|
@@ -16,7 +16,7 @@ module Faye
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
Transport.register 'in-process', Transport::Local
|
21
|
-
|
21
|
+
|
22
22
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Faye
|
2
2
|
class Transport
|
3
|
-
|
3
|
+
|
4
4
|
include Logging
|
5
5
|
include Publisher
|
6
6
|
include Timeouts
|
7
|
-
|
7
|
+
|
8
8
|
attr_accessor :cookies, :endpoint, :headers
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(client, endpoint)
|
11
11
|
@client = client
|
12
12
|
@endpoint = endpoint
|
@@ -16,14 +16,14 @@ module Faye
|
|
16
16
|
def batching?
|
17
17
|
true
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def close
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def connection_type
|
24
24
|
self.class.connection_type
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def send(message, timeout)
|
28
28
|
debug('Client ? sending message to ?: ?', @client.client_id, @endpoint, message)
|
29
29
|
|
@@ -55,62 +55,62 @@ module Faye
|
|
55
55
|
@connection_message = nil
|
56
56
|
@outbox = []
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def receive(responses)
|
60
60
|
debug('Client ? received from ?: ?', @client.client_id, @endpoint, responses)
|
61
61
|
responses.each { |response| @client.receive_message(response) }
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def retry_block(message, timeout)
|
65
65
|
lambda do
|
66
66
|
EventMachine.add_timer(@client.retry) { request(message, timeout) }
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
@transports = []
|
71
|
-
|
71
|
+
|
72
72
|
class << self
|
73
73
|
attr_accessor :connection_type
|
74
|
-
|
75
|
-
def get(client,
|
74
|
+
|
75
|
+
def get(client, allowed, disabled, &callback)
|
76
76
|
endpoint = client.endpoint
|
77
|
-
|
78
|
-
|
77
|
+
|
79
78
|
select = lambda do |(conn_type, klass), resume|
|
80
79
|
conn_endpoint = client.endpoints[conn_type] || endpoint
|
81
|
-
|
80
|
+
|
81
|
+
if disabled.include?(conn_type)
|
82
|
+
next resume.call
|
83
|
+
end
|
84
|
+
|
85
|
+
unless allowed.include?(conn_type)
|
82
86
|
klass.usable?(client, conn_endpoint) { |u| }
|
83
87
|
next resume.call
|
84
88
|
end
|
85
|
-
|
89
|
+
|
86
90
|
klass.usable?(client, conn_endpoint) do |is_usable|
|
87
91
|
next resume.call unless is_usable
|
88
92
|
transport = klass.respond_to?(:create) ? klass.create(client, conn_endpoint) : klass.new(client, conn_endpoint)
|
89
93
|
callback.call(transport)
|
90
94
|
end
|
91
95
|
end
|
92
|
-
|
96
|
+
|
93
97
|
error = lambda do
|
94
98
|
raise "Could not find a usable connection type for #{ endpoint }"
|
95
99
|
end
|
96
|
-
|
100
|
+
|
97
101
|
Faye.async_each(@transports, select, error)
|
98
102
|
end
|
99
|
-
|
103
|
+
|
100
104
|
def register(type, klass)
|
101
105
|
@transports << [type, klass]
|
102
106
|
klass.connection_type = type
|
103
107
|
end
|
104
|
-
|
105
|
-
def supported_connection_types
|
106
|
-
@transports.map { |t| t.first }
|
107
|
-
end
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
%w[local web_socket http].each do |type|
|
111
111
|
require File.join(ROOT, 'faye', 'transport', type)
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
@@ -1,31 +1,31 @@
|
|
1
1
|
module Faye
|
2
|
-
|
2
|
+
|
3
3
|
class Transport::WebSocket < Transport
|
4
|
-
UNCONNECTED
|
5
|
-
CONNECTING
|
6
|
-
CONNECTED
|
7
|
-
|
4
|
+
UNCONNECTED = 1
|
5
|
+
CONNECTING = 2
|
6
|
+
CONNECTED = 3
|
7
|
+
|
8
8
|
include EventMachine::Deferrable
|
9
|
-
|
9
|
+
|
10
10
|
def self.usable?(client, endpoint, &callback)
|
11
11
|
create(client, endpoint).usable?(&callback)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def self.create(client, endpoint)
|
15
15
|
sockets = client.transports[:websocket] ||= {}
|
16
16
|
sockets[endpoint] ||= new(client, endpoint)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def batching?
|
20
20
|
false
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def usable?(&callback)
|
24
24
|
self.callback { callback.call(true) }
|
25
25
|
self.errback { callback.call(false) }
|
26
26
|
connect
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def request(messages, timeout = nil)
|
30
30
|
return if messages.empty?
|
31
31
|
@messages ||= {}
|
@@ -33,56 +33,60 @@ module Faye
|
|
33
33
|
callback { |socket| socket.send(Faye.to_json(messages)) }
|
34
34
|
connect
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def close
|
38
|
-
return
|
39
|
-
@
|
40
|
-
@socket.close
|
38
|
+
return unless @socket
|
39
|
+
@socket.onclose = @socket.onerror = nil
|
40
|
+
@socket.close
|
41
|
+
@socket = nil
|
42
|
+
set_deferred_status(:deferred)
|
43
|
+
@state = UNCONNECTED
|
41
44
|
end
|
42
|
-
|
45
|
+
|
43
46
|
def connect
|
44
|
-
return if @closed
|
45
|
-
|
46
47
|
@state ||= UNCONNECTED
|
47
48
|
return unless @state == UNCONNECTED
|
48
|
-
|
49
|
+
|
49
50
|
@state = CONNECTING
|
50
|
-
|
51
|
+
|
51
52
|
@socket = Faye::WebSocket::Client.new(@endpoint.gsub(/^http(s?):/, 'ws\1:'))
|
52
|
-
|
53
|
+
|
53
54
|
@socket.onopen = lambda do |*args|
|
54
55
|
@state = CONNECTED
|
55
56
|
@ever_connected = true
|
56
57
|
set_deferred_status(:succeeded, @socket)
|
57
58
|
trigger(:up)
|
58
59
|
end
|
59
|
-
|
60
|
+
|
60
61
|
@socket.onmessage = lambda do |event|
|
61
|
-
messages =
|
62
|
+
messages = Yajl::Parser.parse(event.data)
|
63
|
+
next if messages.nil?
|
64
|
+
messages = [messages].flatten
|
62
65
|
messages.each { |message| @messages.delete(message['id']) }
|
63
66
|
receive(messages)
|
64
67
|
end
|
65
|
-
|
66
|
-
@socket.onclose = lambda do |*args|
|
68
|
+
|
69
|
+
@socket.onclose = @socket.onerror = lambda do |*args|
|
67
70
|
was_connected = (@state == CONNECTED)
|
68
71
|
set_deferred_status(:deferred)
|
69
72
|
@state = UNCONNECTED
|
70
|
-
|
71
|
-
|
73
|
+
|
74
|
+
close
|
75
|
+
|
72
76
|
next resend if was_connected
|
73
77
|
next set_deferred_status(:failed) unless @ever_connected
|
74
|
-
|
78
|
+
|
75
79
|
EventMachine.add_timer(@client.retry) { connect }
|
76
80
|
trigger(:down)
|
77
81
|
end
|
78
82
|
end
|
79
|
-
|
83
|
+
|
80
84
|
def resend
|
81
85
|
return unless @messages
|
82
86
|
request(@messages.values)
|
83
87
|
end
|
84
88
|
end
|
85
|
-
|
89
|
+
|
86
90
|
Transport.register 'websocket', Transport::WebSocket
|
87
|
-
|
91
|
+
|
88
92
|
end
|
data/lib/faye/util/namespace.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
module Faye
|
2
2
|
class Namespace
|
3
|
-
|
3
|
+
|
4
4
|
extend Forwardable
|
5
5
|
def_delegator :@used, :delete, :release
|
6
6
|
def_delegator :@used, :has_key?, :exists?
|
7
|
-
|
7
|
+
|
8
8
|
def initialize
|
9
9
|
@used = {}
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def generate
|
13
13
|
name = Engine.random
|
14
14
|
name = Engine.random while @used.has_key?(name)
|
15
15
|
@used[name] = name
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/spec/browser.html
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
</head>
|
8
8
|
<body>
|
9
9
|
<script type="text/javascript">
|
10
|
-
|
10
|
+
|
11
11
|
if (typeof TestSwarm === 'undefined')
|
12
12
|
TestSwarm = {
|
13
13
|
submit: function(result) {
|
@@ -15,9 +15,9 @@
|
|
15
15
|
},
|
16
16
|
heartbeat: function() {}
|
17
17
|
}
|
18
|
-
|
18
|
+
|
19
19
|
JS.cacheBust = true
|
20
|
-
|
20
|
+
|
21
21
|
JS.Packages(function() { with(this) {
|
22
22
|
file('../build/browser/faye-browser-min.js').provides('Faye')
|
23
23
|
autoload(/.*Spec/, {from: './javascript'})
|
@@ -30,7 +30,7 @@
|
|
30
30
|
return function(actual) { testcase.assertEqual(expected, actual) }
|
31
31
|
}
|
32
32
|
})
|
33
|
-
|
33
|
+
|
34
34
|
JS.require( 'FayeSpec',
|
35
35
|
'GrammarSpec',
|
36
36
|
'ChannelSpec',
|
@@ -38,7 +38,7 @@
|
|
38
38
|
'TransportSpec',
|
39
39
|
JS.Test.method('autorun'))
|
40
40
|
})
|
41
|
-
|
41
|
+
|
42
42
|
</script>
|
43
43
|
</body>
|
44
44
|
</html>
|
@@ -1,13 +1,13 @@
|
|
1
1
|
JS.ENV.ChannelSpec = JS.Test.describe("Channel", function() { with(this) {
|
2
2
|
describe("expand", function() { with(this) {
|
3
3
|
it("returns all patterns that match a channel", function() { with(this) {
|
4
|
-
|
4
|
+
|
5
5
|
assertEqual( ["/**", "/foo", "/*"],
|
6
6
|
Faye.Channel.expand("/foo") )
|
7
|
-
|
7
|
+
|
8
8
|
assertEqual( ["/**", "/foo/bar", "/foo/*", "/foo/**"],
|
9
9
|
Faye.Channel.expand("/foo/bar") )
|
10
|
-
|
10
|
+
|
11
11
|
assertEqual( ["/**", "/foo/bar/qux", "/foo/bar/*", "/foo/**", "/foo/bar/**"],
|
12
12
|
Faye.Channel.expand("/foo/bar/qux") )
|
13
13
|
}})
|
@@ -4,11 +4,11 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
4
4
|
Faye.extend(transport, Faye.Publisher)
|
5
5
|
stub(Faye.Transport, "get").yields([transport])
|
6
6
|
}})
|
7
|
-
|
7
|
+
|
8
8
|
before(function() { with(this) {
|
9
9
|
stub("setTimeout")
|
10
10
|
}})
|
11
|
-
|
11
|
+
|
12
12
|
define("stubResponse", function(response) { with(this) {
|
13
13
|
stub(transport, "send", function(message) {
|
14
14
|
response.id = message.id
|
@@ -19,7 +19,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
19
19
|
define("createClient", function() { with(this) {
|
20
20
|
this.client = new Faye.Client("http://localhost/")
|
21
21
|
}})
|
22
|
-
|
22
|
+
|
23
23
|
define("createConnectedClient", function() { with(this) {
|
24
24
|
createClient()
|
25
25
|
stubResponse({channel: "/meta/handshake",
|
@@ -27,29 +27,22 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
27
27
|
version: "1.0",
|
28
28
|
supportedConnectionTypes: ["websocket"],
|
29
29
|
clientId: "fakeid" })
|
30
|
-
|
30
|
+
|
31
31
|
client.handshake()
|
32
32
|
}})
|
33
|
-
|
33
|
+
|
34
34
|
define("subscribe", function(client, channel, callback) { with(this) {
|
35
35
|
stubResponse({channel: "/meta/subscribe",
|
36
36
|
successful: true,
|
37
37
|
clientId: "fakeid",
|
38
38
|
subscription: channel })
|
39
|
-
|
39
|
+
|
40
40
|
this.subsCalled = 0
|
41
41
|
callback = callback || function() { subsCalled += 1 }
|
42
42
|
client.subscribe(channel, callback)
|
43
43
|
}})
|
44
44
|
|
45
45
|
describe("initialize", function() { with(this) {
|
46
|
-
it("creates a transport the server must support", function() { with(this) {
|
47
|
-
expect(Faye.Transport, "get").given(instanceOf(Faye.Client),
|
48
|
-
["long-polling", "callback-polling", "in-process"])
|
49
|
-
.yielding([transport])
|
50
|
-
new Faye.Client("http://localhost/")
|
51
|
-
}})
|
52
|
-
|
53
46
|
it("puts the client in the UNCONNECTED state", function() { with(this) {
|
54
47
|
stub(Faye.Transport, "get")
|
55
48
|
var client = new Faye.Client("http://localhost/")
|
@@ -60,7 +53,15 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
60
53
|
describe("handshake", function() { with(this) {
|
61
54
|
before(function() { this.createClient() })
|
62
55
|
|
63
|
-
|
56
|
+
it("creates a transport the server must support", function() { with(this) {
|
57
|
+
expect(Faye.Transport, "get").given(instanceOf(Faye.Client),
|
58
|
+
["long-polling", "callback-polling", "in-process"],
|
59
|
+
[])
|
60
|
+
.yielding([transport])
|
61
|
+
client.handshake()
|
62
|
+
}})
|
63
|
+
|
64
|
+
it("sends a handshake message to the server", function() { with(this) {
|
64
65
|
expect(transport, "send").given({
|
65
66
|
channel: "/meta/handshake",
|
66
67
|
version: "1.0",
|
@@ -75,7 +76,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
75
76
|
client.handshake()
|
76
77
|
assertEqual( "CONNECTING", client.getState() )
|
77
78
|
}})
|
78
|
-
|
79
|
+
|
79
80
|
describe("with an outgoing extension installed", function() { with(this) {
|
80
81
|
before(function() { with(this) {
|
81
82
|
var extension = {
|
@@ -86,7 +87,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
86
87
|
}
|
87
88
|
client.addExtension(extension)
|
88
89
|
}})
|
89
|
-
|
90
|
+
|
90
91
|
it("passes the handshake message through the extension", function() { with(this) {
|
91
92
|
expect(transport, "send").given({
|
92
93
|
channel: "/meta/handshake",
|
@@ -117,23 +118,25 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
117
118
|
client.handshake()
|
118
119
|
assertEqual( "CONNECTED", client.getState() )
|
119
120
|
}})
|
120
|
-
|
121
|
+
|
121
122
|
it("registers any pre-existing subscriptions", function() { with(this) {
|
122
123
|
expect(client, "subscribe").given([], true)
|
123
124
|
client.handshake()
|
124
125
|
}})
|
125
|
-
|
126
|
+
|
126
127
|
it("selects a new transport based on what the server supports", function() { with(this) {
|
127
|
-
expect(Faye.Transport, "get").given(instanceOf(Faye.Client), ["long-polling", "websocket"])
|
128
|
+
expect(Faye.Transport, "get").given(instanceOf(Faye.Client), ["long-polling", "websocket"], [])
|
128
129
|
.yielding([transport])
|
129
130
|
client.handshake()
|
130
131
|
}})
|
131
|
-
|
132
|
+
|
132
133
|
describe("with websocket disabled", function() { with(this) {
|
133
134
|
before(function() { this.client.disable('websocket') })
|
134
|
-
|
135
|
+
|
135
136
|
it("selects a new transport, excluding websocket", function() { with(this) {
|
136
|
-
expect(Faye.Transport, "get").given(instanceOf(Faye.Client),
|
137
|
+
expect(Faye.Transport, "get").given(instanceOf(Faye.Client),
|
138
|
+
["long-polling", "websocket"],
|
139
|
+
["websocket"])
|
137
140
|
.yielding([transport])
|
138
141
|
client.handshake()
|
139
142
|
}})
|
@@ -159,16 +162,16 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
159
162
|
assertEqual( "UNCONNECTED", client.getState() )
|
160
163
|
}})
|
161
164
|
}})
|
162
|
-
|
165
|
+
|
163
166
|
describe("with existing subscriptions after a server restart", function() { with(this) {
|
164
167
|
before(function() { with(this) {
|
165
168
|
createConnectedClient()
|
166
|
-
|
169
|
+
|
167
170
|
this.message = null
|
168
171
|
subscribe(client, "/messages/foo", function(m) { message = m })
|
169
|
-
|
172
|
+
|
170
173
|
client.receiveMessage({advice: {reconnect: "handshake"}})
|
171
|
-
|
174
|
+
|
172
175
|
stubResponse({channel: "/meta/handshake",
|
173
176
|
successful: true,
|
174
177
|
version: "1.0",
|
@@ -176,7 +179,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
176
179
|
clientId: "reconnectid",
|
177
180
|
subscription: "/messages/foo" }) // tacked on to trigger subscribe() callback
|
178
181
|
}})
|
179
|
-
|
182
|
+
|
180
183
|
it("resends the subscriptions to the server", function() { with(this) {
|
181
184
|
expect(transport, "send").given({
|
182
185
|
channel: "/meta/subscribe",
|
@@ -186,17 +189,17 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
186
189
|
}, 60)
|
187
190
|
client.handshake()
|
188
191
|
}})
|
189
|
-
|
192
|
+
|
190
193
|
it("retains the listeners for the subscriptions", function() { with(this) {
|
191
194
|
client.handshake()
|
192
195
|
client.receiveMessage({channel: "/messages/foo", "data": "ok"})
|
193
196
|
assertEqual( "ok", message )
|
194
197
|
}})
|
195
198
|
}})
|
196
|
-
|
199
|
+
|
197
200
|
describe("with a connected client", function() { with(this) {
|
198
201
|
before(function() { this.createConnectedClient() })
|
199
|
-
|
202
|
+
|
200
203
|
it("does not send a handshake message to the server", function() { with(this) {
|
201
204
|
expect(transport, "send").given({
|
202
205
|
channel: "/meta/handshake",
|
@@ -205,12 +208,12 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
205
208
|
id: instanceOf("string")
|
206
209
|
}, 60)
|
207
210
|
.exactly(0)
|
208
|
-
|
211
|
+
|
209
212
|
client.handshake()
|
210
213
|
}})
|
211
214
|
}})
|
212
215
|
}})
|
213
|
-
|
216
|
+
|
214
217
|
describe("connect", function() { with(this) {
|
215
218
|
describe("with an unconnected client", function() { with(this) {
|
216
219
|
before(function() { with(this) {
|
@@ -219,10 +222,10 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
219
222
|
version: "1.0",
|
220
223
|
supportedConnectionTypes: ["websocket"],
|
221
224
|
clientId: "handshakeid" })
|
222
|
-
|
225
|
+
|
223
226
|
createClient()
|
224
227
|
}})
|
225
|
-
|
228
|
+
|
226
229
|
it("handshakes before connecting", function() { with(this) {
|
227
230
|
expect(transport, "send").given({
|
228
231
|
channel: "/meta/connect",
|
@@ -233,10 +236,10 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
233
236
|
client.connect()
|
234
237
|
}})
|
235
238
|
}})
|
236
|
-
|
239
|
+
|
237
240
|
describe("with a connected client", function() { with(this) {
|
238
241
|
before(function() { this.createConnectedClient() })
|
239
|
-
|
242
|
+
|
240
243
|
it("sends a connect message to the server", function() { with(this) {
|
241
244
|
expect(transport, "send").given({
|
242
245
|
channel: "/meta/connect",
|
@@ -246,7 +249,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
246
249
|
}, 60)
|
247
250
|
client.connect()
|
248
251
|
}})
|
249
|
-
|
252
|
+
|
250
253
|
it("only opens one connect request at a time", function() { with(this) {
|
251
254
|
expect(transport, "send").given({
|
252
255
|
channel: "/meta/connect",
|
@@ -255,16 +258,16 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
255
258
|
id: instanceOf("string")
|
256
259
|
}, 60)
|
257
260
|
.exactly(1)
|
258
|
-
|
261
|
+
|
259
262
|
client.connect()
|
260
263
|
client.connect()
|
261
264
|
}})
|
262
265
|
}})
|
263
266
|
}})
|
264
|
-
|
267
|
+
|
265
268
|
describe("disconnect", function() { with(this) {
|
266
269
|
before(function() { this.createConnectedClient() })
|
267
|
-
|
270
|
+
|
268
271
|
it("sends a disconnect message to the server", function() { with(this) {
|
269
272
|
expect(transport, "send").given({
|
270
273
|
channel: "/meta/disconnect",
|
@@ -273,27 +276,27 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
273
276
|
}, 60)
|
274
277
|
client.disconnect()
|
275
278
|
}})
|
276
|
-
|
279
|
+
|
277
280
|
it("puts the client in the DISCONNECTED state", function() { with(this) {
|
278
281
|
stub(transport, "close")
|
279
282
|
client.disconnect()
|
280
283
|
assertEqual( "DISCONNECTED", client.getState() )
|
281
284
|
}})
|
282
|
-
|
285
|
+
|
283
286
|
describe("on successful response", function() { with(this) {
|
284
287
|
before(function() { with(this) {
|
285
288
|
stubResponse({channel: "/meta/disconnect",
|
286
289
|
successful: true,
|
287
290
|
clientId: "fakeid" })
|
288
291
|
}})
|
289
|
-
|
292
|
+
|
290
293
|
it("closes the transport", function() { with(this) {
|
291
294
|
expect(transport, "close")
|
292
295
|
client.disconnect()
|
293
296
|
}})
|
294
297
|
}})
|
295
298
|
}})
|
296
|
-
|
299
|
+
|
297
300
|
describe("subscribe", function() { with(this) {
|
298
301
|
before(function() { with(this) {
|
299
302
|
createConnectedClient()
|
@@ -304,13 +307,13 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
304
307
|
id: instanceOf("string")
|
305
308
|
}
|
306
309
|
}})
|
307
|
-
|
310
|
+
|
308
311
|
describe("with no prior subscriptions", function() { with(this) {
|
309
312
|
it("sends a subscribe message to the server", function() { with(this) {
|
310
313
|
expect(transport, "send").given(subscribeMessage, 60)
|
311
314
|
client.subscribe("/foo")
|
312
315
|
}})
|
313
|
-
|
316
|
+
|
314
317
|
// The Bayeux spec says the server should accept a list of subscriptions
|
315
318
|
// in one message but the cometD server doesn't actually support this
|
316
319
|
describe("with an array of subscriptions", function() { with(this) {
|
@@ -329,7 +332,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
329
332
|
}, 60)
|
330
333
|
client.subscribe(["/foo", "/bar"])
|
331
334
|
}})
|
332
|
-
|
335
|
+
|
333
336
|
it("returns an array of subscriptions", function() { with(this) {
|
334
337
|
stub(transport, "send")
|
335
338
|
var subs = client.subscribe(["/foo", "/bar"])
|
@@ -337,7 +340,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
337
340
|
assertKindOf( Faye.Subscription, subs[0] )
|
338
341
|
}})
|
339
342
|
}})
|
340
|
-
|
343
|
+
|
341
344
|
describe("on successful response", function() { with(this) {
|
342
345
|
before(function() { with(this) {
|
343
346
|
stubResponse({channel: "/meta/subscribe",
|
@@ -345,27 +348,27 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
345
348
|
clientId: "fakeid",
|
346
349
|
subscription: "/foo/*" })
|
347
350
|
}})
|
348
|
-
|
351
|
+
|
349
352
|
it("sets up a listener for the subscribed channel", function() { with(this) {
|
350
353
|
var message
|
351
354
|
client.subscribe("/foo/*", function(m) { message = m })
|
352
355
|
client.receiveMessage({channel: "/foo/bar", data: "hi"})
|
353
356
|
assertEqual( "hi", message )
|
354
357
|
}})
|
355
|
-
|
358
|
+
|
356
359
|
it("does not call the listener for non-matching channels", function() { with(this) {
|
357
360
|
var message
|
358
361
|
client.subscribe("/foo/*", function(m) { message = m })
|
359
362
|
client.receiveMessage({channel: "/bar", data: "hi"})
|
360
363
|
assertEqual( undefined, message )
|
361
364
|
}})
|
362
|
-
|
365
|
+
|
363
366
|
it("activates the subscription", function() { with(this) {
|
364
367
|
var active = false
|
365
368
|
client.subscribe("/foo/*").callback(function() { active = true })
|
366
369
|
assert( active )
|
367
370
|
}})
|
368
|
-
|
371
|
+
|
369
372
|
describe("with an incoming extension installed", function() { with(this) {
|
370
373
|
before(function() { with(this) {
|
371
374
|
var extension = {
|
@@ -378,13 +381,13 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
378
381
|
this.message = null
|
379
382
|
client.subscribe("/foo/*", function(m) { message = m })
|
380
383
|
}})
|
381
|
-
|
384
|
+
|
382
385
|
it("passes delivered messages through the extension", function() { with(this) {
|
383
386
|
client.receiveMessage({channel: "/foo/bar", data: {hello: "there"}})
|
384
387
|
assertEqual( {hello: "there", changed: true}, message )
|
385
388
|
}})
|
386
389
|
}})
|
387
|
-
|
390
|
+
|
388
391
|
describe("with an outgoing extension installed", function() { with(this) {
|
389
392
|
before(function() { with(this) {
|
390
393
|
var extension = {
|
@@ -397,13 +400,13 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
397
400
|
this.message = null
|
398
401
|
client.subscribe("/foo/*", function(m) { message = m })
|
399
402
|
}})
|
400
|
-
|
403
|
+
|
401
404
|
it("leaves messages unchanged", function() { with(this) {
|
402
405
|
client.receiveMessage({channel: "/foo/bar", data: {hello: "there"}})
|
403
406
|
assertEqual( {hello: "there"}, message )
|
404
407
|
}})
|
405
408
|
}})
|
406
|
-
|
409
|
+
|
407
410
|
describe("with an incoming extension that invalidates the response", function() { with(this) {
|
408
411
|
before(function() { with(this) {
|
409
412
|
var extension = {
|
@@ -414,14 +417,14 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
414
417
|
}
|
415
418
|
client.addExtension(extension)
|
416
419
|
}})
|
417
|
-
|
420
|
+
|
418
421
|
it("does not set up a listener for the subscribed channel", function() { with(this) {
|
419
422
|
var message
|
420
423
|
client.subscribe("/foo/*", function(m) { message = m })
|
421
424
|
client.receiveMessage({channel: "/foo/bar", data: "hi"})
|
422
425
|
assertEqual( undefined, message )
|
423
426
|
}})
|
424
|
-
|
427
|
+
|
425
428
|
it("does not activate the subscription", function() { with(this) {
|
426
429
|
var active = false
|
427
430
|
client.subscribe("/foo/*").callback(function() { active = true })
|
@@ -429,7 +432,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
429
432
|
}})
|
430
433
|
}})
|
431
434
|
}})
|
432
|
-
|
435
|
+
|
433
436
|
describe("on unsuccessful response", function() { with(this) {
|
434
437
|
before(function() { with(this) {
|
435
438
|
stubResponse({channel: "/meta/subscribe",
|
@@ -438,14 +441,14 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
438
441
|
clientId: "fakeid",
|
439
442
|
subscription: "/meta/foo" })
|
440
443
|
}})
|
441
|
-
|
444
|
+
|
442
445
|
it("does not set up a listener for the subscribed channel", function() { with(this) {
|
443
446
|
var message
|
444
447
|
client.subscribe("/meta/foo", function(m) { message = m })
|
445
448
|
client.receiveMessage({channel: "/meta/foo", data: "hi"})
|
446
449
|
assertEqual( undefined, message )
|
447
450
|
}})
|
448
|
-
|
451
|
+
|
449
452
|
it("does not activate the subscription", function() { with(this) {
|
450
453
|
var active = false
|
451
454
|
client.subscribe("/meta/foo").callback(function() { active = true })
|
@@ -459,23 +462,23 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
459
462
|
}})
|
460
463
|
}})
|
461
464
|
}})
|
462
|
-
|
465
|
+
|
463
466
|
describe("with an existing subscription", function() { with(this) {
|
464
467
|
before(function() { with(this) {
|
465
468
|
subscribe(client, "/foo/*")
|
466
469
|
}})
|
467
|
-
|
470
|
+
|
468
471
|
it("does not send another subscribe message to the server", function() { with(this) {
|
469
472
|
expect(transport, "send").given(subscribeMessage, 60).exactly(0)
|
470
473
|
client.subscribe("/foo/*")
|
471
474
|
}})
|
472
|
-
|
475
|
+
|
473
476
|
it("sets up another listener on the channel", function() { with(this) {
|
474
477
|
client.subscribe("/foo/*", function() { subsCalled += 1 })
|
475
478
|
client.receiveMessage({channel: "/foo/bar", data: "hi"})
|
476
479
|
assertEqual( 2, subsCalled )
|
477
480
|
}})
|
478
|
-
|
481
|
+
|
479
482
|
it("activates the subscription", function() { with(this) {
|
480
483
|
var active = false
|
481
484
|
client.subscribe("/foo/*").callback(function() { active = true })
|
@@ -483,7 +486,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
483
486
|
}})
|
484
487
|
}})
|
485
488
|
}})
|
486
|
-
|
489
|
+
|
487
490
|
describe("unsubscribe", function() { with(this) {
|
488
491
|
before(function() { with(this) {
|
489
492
|
createConnectedClient()
|
@@ -494,26 +497,26 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
494
497
|
id: instanceOf("string")
|
495
498
|
}
|
496
499
|
}})
|
497
|
-
|
500
|
+
|
498
501
|
describe("with no subscriptions", function() { with(this) {
|
499
502
|
it("does not send an unsubscribe message to the server", function() { with(this) {
|
500
503
|
expect(transport, "send").given(unsubscribeMessage, 60).exactly(0)
|
501
504
|
client.unsubscribe("/foo/*")
|
502
505
|
}})
|
503
506
|
}})
|
504
|
-
|
507
|
+
|
505
508
|
describe("with a single subscription", function() { with(this) {
|
506
509
|
before(function() { with(this) {
|
507
510
|
this.message = null
|
508
511
|
this.listener = function(m) { message = m }
|
509
512
|
subscribe(client, "/foo/*", listener)
|
510
513
|
}})
|
511
|
-
|
514
|
+
|
512
515
|
it("sends an unsubscribe message to the server", function() { with(this) {
|
513
516
|
expect(transport, "send").given(unsubscribeMessage, 60)
|
514
517
|
client.unsubscribe("/foo/*")
|
515
518
|
}})
|
516
|
-
|
519
|
+
|
517
520
|
it("removes the listener from the channel", function() { with(this) {
|
518
521
|
client.receiveMessage({channel: "/foo/bar", data: "first"})
|
519
522
|
client.unsubscribe("/foo/*", listener)
|
@@ -521,7 +524,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
521
524
|
assertEqual( "first", message )
|
522
525
|
}})
|
523
526
|
}})
|
524
|
-
|
527
|
+
|
525
528
|
describe("with multiple subscriptions to the same channel", function() { with(this) {
|
526
529
|
before(function() { with(this) {
|
527
530
|
this.messages = []
|
@@ -530,37 +533,37 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
530
533
|
subscribe(client, "/foo/*", hey)
|
531
534
|
subscribe(client, "/foo/*", bye)
|
532
535
|
}})
|
533
|
-
|
536
|
+
|
534
537
|
it("removes one of the listeners from the channel", function() { with(this) {
|
535
538
|
client.receiveMessage({channel: "/foo/bar", data: {text: "you"}})
|
536
539
|
client.unsubscribe("/foo/*", hey)
|
537
540
|
client.receiveMessage({channel: "/foo/bar", data: {text: "you"}})
|
538
541
|
assertEqual( ["hey you", "bye you", "bye you"], messages)
|
539
542
|
}})
|
540
|
-
|
543
|
+
|
541
544
|
it("does not send an unsubscribe message if one listener is removed", function() { with(this) {
|
542
545
|
expect(transport, "send").given(unsubscribeMessage, 60).exactly(0)
|
543
546
|
client.unsubscribe("/foo/*", bye)
|
544
547
|
}})
|
545
|
-
|
548
|
+
|
546
549
|
it("sends an unsubscribe message if each listener is removed", function() { with(this) {
|
547
550
|
expect(transport, "send").given(unsubscribeMessage, 60)
|
548
551
|
client.unsubscribe("/foo/*", bye)
|
549
552
|
client.unsubscribe("/foo/*", hey)
|
550
553
|
}})
|
551
|
-
|
554
|
+
|
552
555
|
it("sends an unsubscribe message if all listeners are removed", function() { with(this) {
|
553
556
|
expect(transport, "send").given(unsubscribeMessage, 60)
|
554
557
|
client.unsubscribe("/foo/*")
|
555
558
|
}})
|
556
559
|
}})
|
557
|
-
|
560
|
+
|
558
561
|
describe("with multiple subscriptions to different channels", function() { with(this) {
|
559
562
|
before(function() { with(this) {
|
560
563
|
subscribe(client, "/foo")
|
561
564
|
subscribe(client, "/bar")
|
562
565
|
}})
|
563
|
-
|
566
|
+
|
564
567
|
it("sends multiple unsubscribe messages if given an array", function() { with(this) {
|
565
568
|
expect(transport, "send").given({
|
566
569
|
channel: "/meta/unsubscribe",
|
@@ -578,10 +581,10 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
578
581
|
}})
|
579
582
|
}})
|
580
583
|
}})
|
581
|
-
|
584
|
+
|
582
585
|
describe("publish", function() { with(this) {
|
583
586
|
before(function() { this.createConnectedClient() })
|
584
|
-
|
587
|
+
|
585
588
|
it("sends the message to the server with an ID", function() { with(this) {
|
586
589
|
expect(transport, "send").given({
|
587
590
|
channel: "/messages/foo",
|
@@ -591,7 +594,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
591
594
|
}, 60)
|
592
595
|
client.publish("/messages/foo", {hello: "world"})
|
593
596
|
}})
|
594
|
-
|
597
|
+
|
595
598
|
describe("on publish failure", function() { with(this) {
|
596
599
|
before(function() { with(this) {
|
597
600
|
stubResponse({channel: "/messages/foo",
|
@@ -599,13 +602,13 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
599
602
|
successful: false,
|
600
603
|
clientId: "fakeid" })
|
601
604
|
}})
|
602
|
-
|
605
|
+
|
603
606
|
it("should not be published", function() { with(this) {
|
604
607
|
var published = false
|
605
608
|
client.publish("/messages/foo", {text: "hi"}).callback(function() { published = true })
|
606
609
|
assert( !published )
|
607
610
|
}})
|
608
|
-
|
611
|
+
|
609
612
|
it("reports the error through an errback", function() { with(this) {
|
610
613
|
var error = null
|
611
614
|
client.publish("/messages/foo", {text: "hi"}).errback(function(e) { error = e })
|
@@ -614,14 +617,14 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
614
617
|
assertEqual( "Failed to publish", error.message )
|
615
618
|
}})
|
616
619
|
}})
|
617
|
-
|
620
|
+
|
618
621
|
describe("on receipt of the published message", function() { with(this) {
|
619
622
|
before(function() { with(this) {
|
620
623
|
stubResponse({channel: "/messages/foo",
|
621
624
|
data: {text: "hi"},
|
622
625
|
clientId: "fakeid" })
|
623
626
|
}})
|
624
|
-
|
627
|
+
|
625
628
|
it("does not trigger the callbacks", function() { with(this) {
|
626
629
|
var published = false
|
627
630
|
var publication = client.publish("/messages/foo", {text: "hi"})
|
@@ -630,7 +633,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
630
633
|
assert( !published )
|
631
634
|
}})
|
632
635
|
}})
|
633
|
-
|
636
|
+
|
634
637
|
describe("with an outgoing extension installed", function() { with(this) {
|
635
638
|
before(function() { with(this) {
|
636
639
|
var extension = {
|
@@ -641,7 +644,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
641
644
|
}
|
642
645
|
client.addExtension(extension)
|
643
646
|
}})
|
644
|
-
|
647
|
+
|
645
648
|
it("passes messages through the extension", function() { with(this) {
|
646
649
|
expect(transport, "send").given({
|
647
650
|
channel: "/messages/foo",
|
@@ -653,7 +656,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
653
656
|
client.publish("/messages/foo", {hello: "world"})
|
654
657
|
}})
|
655
658
|
}})
|
656
|
-
|
659
|
+
|
657
660
|
describe("with an incoming extension installed", function() { with(this) {
|
658
661
|
before(function() { with(this) {
|
659
662
|
var extension = {
|
@@ -664,7 +667,7 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
664
667
|
}
|
665
668
|
client.addExtension(extension)
|
666
669
|
}})
|
667
|
-
|
670
|
+
|
668
671
|
it("leaves the message unchanged", function() { with(this) {
|
669
672
|
expect(transport, "send").given({
|
670
673
|
channel: "/messages/foo",
|
@@ -676,44 +679,47 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
|
|
676
679
|
}})
|
677
680
|
}})
|
678
681
|
}})
|
679
|
-
|
682
|
+
|
680
683
|
describe("network notifications", function() { with(this) {
|
681
|
-
before(function() { this
|
682
|
-
|
684
|
+
before(function() { with(this) {
|
685
|
+
createClient()
|
686
|
+
client.handshake()
|
687
|
+
}})
|
688
|
+
|
683
689
|
describe("in the default state", function() { with(this) {
|
684
690
|
it("broadcasts a down notification", function() { with(this) {
|
685
691
|
expect(client, "trigger").given("transport:down")
|
686
692
|
transport.trigger("down")
|
687
693
|
}})
|
688
|
-
|
694
|
+
|
689
695
|
it("broadcasts an up notification", function() { with(this) {
|
690
696
|
expect(client, "trigger").given("transport:up")
|
691
697
|
transport.trigger("up")
|
692
698
|
}})
|
693
699
|
}})
|
694
|
-
|
700
|
+
|
695
701
|
describe("when the transport is up", function() { with(this) {
|
696
702
|
before(function() { this.transport.trigger("up") })
|
697
|
-
|
703
|
+
|
698
704
|
it("broadcasts a down notification", function() { with(this) {
|
699
705
|
expect(client, "trigger").given("transport:down")
|
700
706
|
transport.trigger("down")
|
701
707
|
}})
|
702
|
-
|
708
|
+
|
703
709
|
it("does not broadcast an up notification", function() { with(this) {
|
704
710
|
expect(client, "trigger").exactly(0)
|
705
711
|
transport.trigger("up")
|
706
712
|
}})
|
707
713
|
}})
|
708
|
-
|
714
|
+
|
709
715
|
describe("when the transport is down", function() { with(this) {
|
710
716
|
before(function() { this.transport.trigger("down") })
|
711
|
-
|
717
|
+
|
712
718
|
it("does not broadcast a down notification", function() { with(this) {
|
713
719
|
expect(client, "trigger").exactly(0)
|
714
720
|
transport.trigger("down")
|
715
721
|
}})
|
716
|
-
|
722
|
+
|
717
723
|
it("broadcasts an up notification", function() { with(this) {
|
718
724
|
expect(client, "trigger").given("transport:up")
|
719
725
|
transport.trigger("up")
|