faye 0.5.5 → 0.6.0

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.

Files changed (62) hide show
  1. data/History.txt +14 -0
  2. data/README.rdoc +98 -0
  3. data/Rakefile +17 -15
  4. data/lib/faye-browser-min.js +1 -1
  5. data/lib/faye.rb +14 -5
  6. data/lib/faye/adapters/rack_adapter.rb +12 -5
  7. data/lib/faye/engines/base.rb +62 -0
  8. data/lib/faye/engines/connection.rb +63 -0
  9. data/lib/faye/engines/memory.rb +89 -0
  10. data/lib/faye/engines/redis.rb +141 -0
  11. data/lib/faye/error.rb +16 -4
  12. data/lib/faye/mixins/publisher.rb +6 -0
  13. data/lib/faye/protocol/channel.rb +34 -86
  14. data/lib/faye/protocol/client.rb +36 -52
  15. data/lib/faye/protocol/extensible.rb +3 -0
  16. data/lib/faye/protocol/server.rb +119 -169
  17. data/lib/faye/transport/http.rb +45 -0
  18. data/lib/faye/transport/local.rb +15 -0
  19. data/lib/faye/{network → transport}/transport.rb +36 -49
  20. data/spec/browser.html +35 -0
  21. data/spec/install.sh +48 -0
  22. data/spec/javascript/channel_spec.js +15 -0
  23. data/spec/javascript/client_spec.js +610 -0
  24. data/spec/javascript/engine_spec.js +319 -0
  25. data/spec/javascript/faye_spec.js +15 -0
  26. data/spec/javascript/grammar_spec.js +66 -0
  27. data/spec/javascript/node_adapter_spec.js +276 -0
  28. data/spec/javascript/server/connect_spec.js +168 -0
  29. data/spec/javascript/server/disconnect_spec.js +121 -0
  30. data/spec/javascript/server/extensions_spec.js +60 -0
  31. data/spec/javascript/server/handshake_spec.js +153 -0
  32. data/spec/javascript/server/subscribe_spec.js +245 -0
  33. data/spec/javascript/server/unsubscribe_spec.js +245 -0
  34. data/spec/javascript/server_spec.js +146 -0
  35. data/spec/javascript/transport_spec.js +130 -0
  36. data/spec/node.js +34 -0
  37. data/spec/ruby/channel_spec.rb +17 -0
  38. data/spec/ruby/client_spec.rb +615 -0
  39. data/spec/ruby/engine_spec.rb +312 -0
  40. data/spec/ruby/faye_spec.rb +14 -0
  41. data/spec/ruby/grammar_spec.rb +68 -0
  42. data/spec/ruby/rack_adapter_spec.rb +209 -0
  43. data/spec/ruby/server/connect_spec.rb +170 -0
  44. data/spec/ruby/server/disconnect_spec.rb +120 -0
  45. data/spec/ruby/server/extensions_spec.rb +69 -0
  46. data/spec/ruby/server/handshake_spec.rb +151 -0
  47. data/spec/ruby/server/subscribe_spec.rb +247 -0
  48. data/spec/ruby/server/unsubscribe_spec.rb +247 -0
  49. data/spec/ruby/server_spec.rb +138 -0
  50. data/spec/ruby/transport_spec.rb +128 -0
  51. data/spec/spec_helper.rb +5 -0
  52. data/spec/testswarm.pl +200 -0
  53. data/spec/thin_proxy.rb +36 -0
  54. metadata +119 -84
  55. data/Manifest.txt +0 -27
  56. data/README.txt +0 -98
  57. data/lib/faye/protocol/connection.rb +0 -111
  58. data/test/scenario.rb +0 -172
  59. data/test/test_channel.rb +0 -54
  60. data/test/test_clients.rb +0 -381
  61. data/test/test_grammar.rb +0 -86
  62. data/test/test_server.rb +0 -488
@@ -0,0 +1,168 @@
1
+ JS.ENV.Server.ConnectSpec = JS.Test.describe("Server connect", function() { with(this) {
2
+ before(function() { with(this) {
3
+ this.engine = {}
4
+ stub(Faye.Engine, "get").returns(engine)
5
+ this.server = new Faye.Server()
6
+ }})
7
+
8
+ describe("#connect", function() { with(this) {
9
+ before(function() { with(this) {
10
+ this.clientId = "fakeclientid"
11
+ this.message = {channel: "/meta/connect",
12
+ clientId: "fakeclientid",
13
+ connectionType: "long-polling"}
14
+ }})
15
+
16
+ describe("with valid parameters", function() { with(this) {
17
+ before(function() { with(this) {
18
+ message.advice = {timeout: 60}
19
+ expect(engine, "clientExists").given(clientId).yielding([true])
20
+ }})
21
+
22
+ it("connects to the engine to wait for new messages", function() { with(this) {
23
+ expect(engine, "connect").given(clientId, {timeout: 60}).yielding([[]])
24
+ server.connect(message, false, function() {})
25
+ }})
26
+
27
+ it("returns a successful response and any queued messages", function() { with(this) {
28
+ stub(engine, "connect").yields([{channel: "/x", data: "hello"}])
29
+ server.connect(message, false, function(response) {
30
+ assertEqual([
31
+ { channel: "/meta/connect",
32
+ successful: true,
33
+ clientId: clientId
34
+ },
35
+ { channel: "/x",
36
+ data: "hello"
37
+ }
38
+ ], response)
39
+ })
40
+ }})
41
+
42
+ describe("with a message id", function() { with(this) {
43
+ before(function() { this.message.id = "foo" })
44
+
45
+ it("returns the same id", function() { with(this) {
46
+ stub(engine, "connect")
47
+ server.connect(message, false, function(response) {
48
+ assertEqual({
49
+ channel: "/meta/connect",
50
+ successful: true,
51
+ clientId: clientId,
52
+ id: "foo"
53
+ }, response)
54
+ })
55
+ }})
56
+ }})
57
+ }})
58
+
59
+ describe("with an unknown client", function() { with(this) {
60
+ before(function() { with(this) {
61
+ expect(engine, "clientExists").given(clientId).yielding([false])
62
+ }})
63
+
64
+ it("does not connect to the engine", function() { with(this) {
65
+ expect(engine, "connect").exactly(0)
66
+ server.connect(message, false, function() {})
67
+ }})
68
+
69
+ it("returns an unsuccessful response", function() { with(this) {
70
+ server.connect(message, false, function(response) {
71
+ assertEqual({
72
+ channel: "/meta/connect",
73
+ successful: false,
74
+ error: "401:fakeclientid:Unknown client"
75
+ }, response)
76
+ })
77
+ }})
78
+ }})
79
+
80
+ describe("missing clientId", function() { with(this) {
81
+ before(function() { with(this) {
82
+ delete message.clientId
83
+ expect(engine, "clientExists").given(undefined).yielding([false])
84
+ }})
85
+
86
+ it("does not connect to the engine", function() { with(this) {
87
+ expect(engine, "connect").exactly(0)
88
+ server.connect(message, false, function() {})
89
+ }})
90
+
91
+ it("returns an unsuccessful response", function() { with(this) {
92
+ server.connect(message, false, function(response) {
93
+ assertEqual({
94
+ channel: "/meta/connect",
95
+ successful: false,
96
+ error: "402:clientId:Missing required parameter"
97
+ }, response)
98
+ })
99
+ }})
100
+ }})
101
+
102
+ describe("missing connectionType", function() { with(this) {
103
+ before(function() { with(this) {
104
+ delete message.connectionType
105
+ expect(engine, "clientExists").given(clientId).yielding([true])
106
+ }})
107
+
108
+ it("does not connect to the engine", function() { with(this) {
109
+ expect(engine, "connect").exactly(0)
110
+ server.connect(message, false, function() {})
111
+ }})
112
+
113
+ it("returns an unsuccessful response", function() { with(this) {
114
+ server.connect(message, false, function(response) {
115
+ assertEqual({
116
+ channel: "/meta/connect",
117
+ successful: false,
118
+ error: "402:connectionType:Missing required parameter"
119
+ }, response)
120
+ })
121
+ }})
122
+ }})
123
+
124
+ describe("with an unknown connectionType", function() { with(this) {
125
+ before(function() { with(this) {
126
+ message.connectionType = "flash"
127
+ expect(engine, "clientExists").given(clientId).yielding([true])
128
+ }})
129
+
130
+ it("does not connect to the engine", function() { with(this) {
131
+ expect(engine, "connect").exactly(0)
132
+ server.connect(message, false, function() {})
133
+ }})
134
+
135
+ it("returns an unsuccessful response", function() { with(this) {
136
+ server.connect(message, false, function(response) {
137
+ assertEqual({
138
+ channel: "/meta/connect",
139
+ successful: false,
140
+ error: "301:flash:Connection types not supported"
141
+ }, response)
142
+ })
143
+ }})
144
+ }})
145
+
146
+ describe("with an error", function() { with(this) {
147
+ before(function() { with(this) {
148
+ message.error = "invalid"
149
+ expect(engine, "clientExists").given(clientId).yielding([true])
150
+ }})
151
+
152
+ it("does not connect to the engine", function() { with(this) {
153
+ expect(engine, "connect").exactly(0)
154
+ server.connect(message, false, function() {})
155
+ }})
156
+
157
+ it("returns an unsuccessful response", function() { with(this) {
158
+ server.connect(message, false, function(response) {
159
+ assertEqual({
160
+ channel: "/meta/connect",
161
+ successful: false,
162
+ error: "invalid"
163
+ }, response)
164
+ })
165
+ }})
166
+ }})
167
+ }})
168
+ }})
@@ -0,0 +1,121 @@
1
+ JS.ENV.Server.DisconnectSpec = JS.Test.describe("Server disconnect", function() { with(this) {
2
+ before(function() { with(this) {
3
+ this.engine = {}
4
+ stub(Faye.Engine, "get").returns(engine)
5
+ this.server = new Faye.Server()
6
+ }})
7
+
8
+ describe("#disconnect", function() { with(this) {
9
+ before(function() { with(this) {
10
+ this.clientId = "fakeclientid"
11
+ this.message = {channel: "/meta/disconnect",
12
+ clientId: "fakeclientid"}
13
+ }})
14
+
15
+ describe("with valid parameters", function() { with(this) {
16
+ before(function() { with(this) {
17
+ expect(engine, "clientExists").given(clientId).yielding([true])
18
+ }})
19
+
20
+ it("destroys the client", function() { with(this) {
21
+ expect(engine, "destroyClient").given(clientId)
22
+ server.disconnect(message, false, function() {})
23
+ }})
24
+
25
+ it("returns a successful response", function() { with(this) {
26
+ stub(engine, "destroyClient")
27
+ server.disconnect(message, false, function(response) {
28
+ assertEqual({
29
+ channel: "/meta/disconnect",
30
+ successful: true,
31
+ clientId: clientId
32
+ }, response)
33
+ })
34
+ }})
35
+
36
+ describe("with a message id", function() { with(this) {
37
+ before(function() { this.message.id = "foo" })
38
+
39
+ it("returns the same id", function() { with(this) {
40
+ stub(engine, "destroyClient")
41
+ server.disconnect(message, false, function(response) {
42
+ assertEqual({
43
+ channel: "/meta/disconnect",
44
+ successful: true,
45
+ clientId: clientId,
46
+ id: "foo"
47
+ }, response)
48
+ })
49
+ }})
50
+ }})
51
+ }})
52
+
53
+ describe("with an unknown client", function() { with(this) {
54
+ before(function() { with(this) {
55
+ expect(engine, "clientExists").given(clientId).yielding([false])
56
+ }})
57
+
58
+ it("does not destroy the client", function() { with(this) {
59
+ expect(engine, "destroyClient").exactly(0)
60
+ server.disconnect(message, false, function() {})
61
+ }})
62
+
63
+ it("returns an unsuccessful response", function() { with(this) {
64
+ stub(engine, "destroyClient")
65
+ server.disconnect(message, false, function(response) {
66
+ assertEqual({
67
+ channel: "/meta/disconnect",
68
+ successful: false,
69
+ error: "401:fakeclientid:Unknown client"
70
+ }, response)
71
+ })
72
+ }})
73
+ }})
74
+
75
+ describe("missing clientId", function() { with(this) {
76
+ before(function() { with(this) {
77
+ delete message.clientId
78
+ expect(engine, "clientExists").given(undefined).yielding([false])
79
+ }})
80
+
81
+ it("does not destroy the client", function() { with(this) {
82
+ expect(engine, "destroyClient").exactly(0)
83
+ server.disconnect(message, false, function() {})
84
+ }})
85
+
86
+ it("returns an unsuccessful response", function() { with(this) {
87
+ stub(engine, "destroyClient")
88
+ server.disconnect(message, false, function(response) {
89
+ assertEqual({
90
+ channel: "/meta/disconnect",
91
+ successful: false,
92
+ error: "402:clientId:Missing required parameter"
93
+ }, response)
94
+ })
95
+ }})
96
+ }})
97
+
98
+ describe("with an error", function() { with(this) {
99
+ before(function() { with(this) {
100
+ message.error = "invalid"
101
+ expect(engine, "clientExists").given(clientId).yielding([true])
102
+ }})
103
+
104
+ it("does not destroy the client", function() { with(this) {
105
+ expect(engine, "destroyClient").exactly(0)
106
+ server.disconnect(message, false, function() {})
107
+ }})
108
+
109
+ it("returns an unsuccessful response", function() { with(this) {
110
+ stub(engine, "destroyClient")
111
+ server.disconnect(message, false, function(response) {
112
+ assertEqual({
113
+ channel: "/meta/disconnect",
114
+ successful: false,
115
+ error: "invalid"
116
+ }, response)
117
+ })
118
+ }})
119
+ }})
120
+ }})
121
+ }})
@@ -0,0 +1,60 @@
1
+ JS.ENV.Server.ExtensionsSpec = JS.Test.describe("Server extensions", function() { with(this) {
2
+ before(function() { with(this) {
3
+ this.engine = {}
4
+ stub(Faye.Engine, "get").returns(engine)
5
+ this.server = new Faye.Server()
6
+ }})
7
+
8
+ describe("with an incoming extension installed", function() { with(this) {
9
+ before(function() { with(this) {
10
+ var extension = {
11
+ incoming: function(message, callback) {
12
+ message.ext = {auth: "password"}
13
+ callback(message)
14
+ }
15
+ }
16
+ server.addExtension(extension)
17
+ this.message = {channel: "/foo", data: "hello"}
18
+ }})
19
+
20
+ it("passes incoming messages through the extension", function() { with(this) {
21
+ expect(engine, "publish").given({channel: "/foo", data: "hello", ext: {auth: "password"}})
22
+ server.process(message, false, function() {})
23
+ }})
24
+
25
+ it("does not pass outgoing messages through the extension", function() { with(this) {
26
+ stub(server, "handshake").yields([message])
27
+ stub(engine, "publish")
28
+ var response = null
29
+ server.process({channel: "/meta/handshake"}, false, function(r) { response = r })
30
+ assertEqual( [{channel: "/foo", data: "hello", advice: anything()}], response )
31
+ }})
32
+ }})
33
+
34
+ describe("with an outgoing extension installed", function() { with(this) {
35
+ before(function() { with(this) {
36
+ var extension = {
37
+ outgoing: function(message, callback) {
38
+ message.ext = {auth: "password"}
39
+ callback(message)
40
+ }
41
+ }
42
+ server.addExtension(extension)
43
+ this.message = {channel: "/foo", data: "hello"}
44
+ }})
45
+
46
+ it("does not pass incoming messages through the extension", function() { with(this) {
47
+ expect(engine, "publish").given({channel: "/foo", data: "hello"})
48
+ server.process(message, false, function() {})
49
+ }})
50
+
51
+ it("passes outgoing messages through the extension", function() { with(this) {
52
+ stub(server, "handshake").yields([message])
53
+ stub(engine, "publish")
54
+ var response = null
55
+ server.process({channel: "/meta/handshake"}, false, function(r) { response = r })
56
+ assertEqual( [{channel: "/foo", data: "hello", advice: anything(), ext: {auth: "password"}}], response )
57
+ }})
58
+ }})
59
+ }})
60
+
@@ -0,0 +1,153 @@
1
+ JS.ENV.Server.HandshakeSpec = JS.Test.describe("Server handshake", function() { with(this) {
2
+ before(function() { with(this) {
3
+ this.engine = {}
4
+ stub(Faye.Engine, "get").returns(engine)
5
+ this.server = new Faye.Server()
6
+ }})
7
+
8
+ describe("#handshake", function() { with(this) {
9
+ before(function() { with(this) {
10
+ this.message = {channel: "/meta/handshake",
11
+ version: "1.0",
12
+ supportedConnectionTypes: ["long-polling"]}
13
+ }})
14
+
15
+ describe("with valid parameters", function() { with(this) {
16
+ it("creates a client", function() { with(this) {
17
+ expect(engine, "createClient")
18
+ server.handshake(message, false, function() {})
19
+ }})
20
+
21
+ it("returns a successful response", function() { with(this) {
22
+ stub(engine, "createClient").yields(["clientid"])
23
+ server.handshake(message, false, function(response) {
24
+ assertEqual({
25
+ channel: "/meta/handshake",
26
+ successful: true,
27
+ version: "1.0",
28
+ supportedConnectionTypes: ["long-polling", "cross-origin-long-polling", "callback-polling", "websocket"],
29
+ clientId: "clientid"
30
+ }, response)
31
+ })
32
+ }})
33
+
34
+ describe("with a message id", function() { with(this) {
35
+ before(function() { this.message.id = "foo" })
36
+
37
+ it("returns the same id", function() { with(this) {
38
+ stub(engine, "createClient").yields(["clientid"])
39
+ server.handshake(message, false, function(response) {
40
+ assertEqual({
41
+ channel: "/meta/handshake",
42
+ successful: true,
43
+ version: "1.0",
44
+ supportedConnectionTypes: ["long-polling", "cross-origin-long-polling", "callback-polling", "websocket"],
45
+ clientId: "clientid",
46
+ id: "foo"
47
+ }, response)
48
+ })
49
+ }})
50
+ }})
51
+ }})
52
+
53
+ describe("missing version", function() { with(this) {
54
+ before(function() { delete this.message.version })
55
+
56
+ it("does not create a client", function() { with(this) {
57
+ expect(engine, "createClient").exactly(0)
58
+ server.handshake(message, false, function() {})
59
+ }})
60
+
61
+ it("returns an unsuccessful response", function() { with(this) {
62
+ server.handshake(message, false, function(response) {
63
+ assertEqual({
64
+ channel: "/meta/handshake",
65
+ successful: false,
66
+ error: "402:version:Missing required parameter",
67
+ version: "1.0",
68
+ supportedConnectionTypes: ["long-polling", "cross-origin-long-polling", "callback-polling", "websocket"]
69
+ }, response)
70
+ })
71
+ }})
72
+ }})
73
+
74
+ describe("missing supportedConnectionTypes", function() { with(this) {
75
+ before(function() { delete this.message.supportedConnectionTypes })
76
+
77
+ it("does not create a client", function() { with(this) {
78
+ expect(engine, "createClient").exactly(0)
79
+ server.handshake(message, false, function() {})
80
+ }})
81
+
82
+ it("returns an unsuccessful response", function() { with(this) {
83
+ server.handshake(message, false, function(response) {
84
+ assertEqual({
85
+ channel: "/meta/handshake",
86
+ successful: false,
87
+ error: "402:supportedConnectionTypes:Missing required parameter",
88
+ version: "1.0",
89
+ supportedConnectionTypes: ["long-polling", "cross-origin-long-polling", "callback-polling", "websocket"]
90
+ }, response)
91
+ })
92
+ }})
93
+
94
+ it("returns a successful response for local clients", function() { with(this) {
95
+ expect(engine, "createClient").yields(["clientid"])
96
+ server.handshake(message, true, function(response) {
97
+ assertEqual({
98
+ channel: "/meta/handshake",
99
+ successful: true,
100
+ version: "1.0",
101
+ clientId: "clientid"
102
+ }, response)
103
+ })
104
+ }})
105
+ }})
106
+
107
+ describe("with no matching supportedConnectionTypes", function() { with(this) {
108
+ before(function() { with(this) {
109
+ message.supportedConnectionTypes = ["iframe", "flash"]
110
+ }})
111
+
112
+ it("does not create a client", function() { with(this) {
113
+ expect(engine, "createClient").exactly(0)
114
+ server.handshake(message, false, function() {})
115
+ }})
116
+
117
+ it("returns an unsuccessful response", function() { with(this) {
118
+ server.handshake(message, false, function(response) {
119
+ assertEqual({
120
+ channel: "/meta/handshake",
121
+ successful: false,
122
+ error: "301:iframe,flash:Connection types not supported",
123
+ version: "1.0",
124
+ supportedConnectionTypes: ["long-polling", "cross-origin-long-polling", "callback-polling", "websocket"]
125
+ }, response)
126
+ })
127
+ }})
128
+ }})
129
+
130
+ describe("with an error", function() { with(this) {
131
+ before(function() { with(this) {
132
+ message.error = "invalid"
133
+ }})
134
+
135
+ it("does not create a client", function() { with(this) {
136
+ expect(engine, "createClient").exactly(0)
137
+ server.handshake(message, false, function() {})
138
+ }})
139
+
140
+ it("returns an unsuccessful response", function() { with(this) {
141
+ server.handshake(message, false, function(response) {
142
+ assertEqual({
143
+ channel: "/meta/handshake",
144
+ successful: false,
145
+ error: "invalid",
146
+ version: "1.0",
147
+ supportedConnectionTypes: ["long-polling", "cross-origin-long-polling", "callback-polling", "websocket"]
148
+ }, response)
149
+ })
150
+ }})
151
+ }})
152
+ }})
153
+ }})