websocket-rails 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module WebsocketRails
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -7,8 +7,7 @@ Dummy::Application.configure do
7
7
  # and recreated between test runs. Don't rely on the data there!
8
8
  config.cache_classes = true
9
9
 
10
- # Log error messages when you accidentally call methods on nil.
11
- config.whiny_nils = true
10
+ config.eager_load = true
12
11
 
13
12
  # Show full error reports and disable caching
14
13
  config.consider_all_requests_local = true
@@ -0,0 +1,10 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :name
5
+ t.string :email
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20130902222552) do
15
+
16
+ create_table "users", force: true do |t|
17
+ t.string "name"
18
+ t.string "email"
19
+ t.datetime "created_at"
20
+ t.datetime "updated_at"
21
+ end
22
+
23
+ end
Binary file
@@ -0,0 +1,17 @@
1
+  (1.2ms) CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL) 
2
+  (0.7ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
3
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
4
+ Migrating to CreateUsers (20130902222552)
5
+  (0.0ms) begin transaction
6
+  (0.3ms) CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "email" varchar(255), "created_at" datetime, "updated_at" datetime) 
7
+ SQL (1.4ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "20130902222552"]]
8
+  (0.9ms) commit transaction
9
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
10
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
11
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
12
+  (1.0ms) CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "email" varchar(255), "created_at" datetime, "updated_at" datetime) 
13
+  (1.0ms) CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL)
14
+  (0.8ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
15
+  (0.1ms) SELECT version FROM "schema_migrations"
16
+  (0.8ms) INSERT INTO "schema_migrations" (version) VALUES ('20130902222552')
17
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
@@ -111,7 +111,7 @@ module WebsocketRails
111
111
  end
112
112
 
113
113
  context "WebSocket Adapter" do
114
- let(:socket) { @server.connections.first }
114
+ let(:socket) { @server.connections.first[1] }
115
115
 
116
116
  before do
117
117
  ::Faye::WebSocket.stub(:websocket?).and_return(true)
@@ -122,7 +122,7 @@ module WebsocketRails
122
122
  end
123
123
 
124
124
  describe "HTTP Adapter" do
125
- let(:socket) { @server.connections.first }
125
+ let(:socket) { @server.connections.first[1] }
126
126
 
127
127
  before do
128
128
  @server = ConnectionManager.new
@@ -18,8 +18,15 @@ module WebsocketRails
18
18
  end
19
19
 
20
20
  context ".establish_connection" do
21
+ before do
22
+ connection_manager = double(ConnectionManager)
23
+ connection_manager.stub(:connections).and_return({})
24
+ @dispatcher = double(Dispatcher).as_null_object
25
+ @dispatcher.stub(:connection_manager).and_return(connection_manager)
26
+ end
27
+
21
28
  it "should return the correct connection adapter instance" do
22
- adapter = ConnectionAdapters.establish_connection( mock_request, double('Dispatcher').as_null_object )
29
+ adapter = ConnectionAdapters.establish_connection(mock_request, @dispatcher)
23
30
  adapter.class.should == ConnectionAdapters::Test
24
31
  end
25
32
  end
@@ -28,11 +35,18 @@ module WebsocketRails
28
35
 
29
36
  module ConnectionAdapters
30
37
  describe Base do
31
- let(:dispatcher) { double('Dispatcher').as_null_object }
32
- let(:channel_manager) { double('ChannelManager').as_null_object }
33
- let(:event) { double('Event').as_null_object }
34
- before { Event.stub(:new_from_json).and_return(event) }
35
- subject { Base.new( mock_request, dispatcher ) }
38
+ let(:connection_manager) { double(ConnectionManager).as_null_object }
39
+ let(:dispatcher) { double(Dispatcher).as_null_object }
40
+ let(:channel_manager) { double(ChannelManager).as_null_object }
41
+ let(:event) { double(Event).as_null_object }
42
+
43
+ before do
44
+ connection_manager.stub(:connections).and_return({})
45
+ dispatcher.stub(:connection_manager).and_return(connection_manager)
46
+ Event.stub(:new_from_json).and_return(event)
47
+ end
48
+
49
+ subject { Base.new(mock_request, dispatcher) }
36
50
 
37
51
  context "new adapter" do
38
52
  it "should register itself in the adapters array when inherited" do
@@ -44,17 +58,17 @@ module WebsocketRails
44
58
  subject.data_store.should be_a DataStore::Connection
45
59
  end
46
60
 
47
- before do
48
- WebsocketRails.config.stub(:user_identifier).and_return(:name)
49
- WebsocketRails::DelegationController.any_instance
50
- .stub_chain(:current_user, :name)
51
- .and_return('Frank')
52
- subject
53
- end
61
+ #before do
62
+ # WebsocketRails.config.stub(:user_identifier).and_return(:name)
63
+ # WebsocketRails::DelegationController.any_instance
64
+ # .stub_chain(:current_user, :name)
65
+ # .and_return('Frank')
66
+ # subject
67
+ #end
54
68
 
55
- it "adds itself to the UserManager Hash" do
56
- WebsocketRails.users['Frank'].should == subject
57
- end
69
+ #it "adds itself to the UserManager Hash" do
70
+ # WebsocketRails.users['Frank'].should == subject
71
+ #end
58
72
  end
59
73
 
60
74
  describe "#on_open" do
@@ -81,11 +95,6 @@ module WebsocketRails
81
95
  dispatcher.should_receive(:dispatch).with(on_close_event)
82
96
  subject.on_close("data")
83
97
  end
84
-
85
- it "removes itself from the global UserMnaager" do
86
- subject.on_close
87
- WebsocketRails.users[subject.id].nil?.should == true
88
- end
89
98
  end
90
99
 
91
100
  describe "#on_error" do
@@ -137,45 +146,72 @@ module WebsocketRails
137
146
  end
138
147
  end
139
148
 
140
- describe "#enqueue" do
141
- it "should add the event to the queue" do
142
- subject.enqueue 'event'
143
- subject.queue.queue.should == ['event']
149
+ describe "#user_connection?" do
150
+ context "when a user is signed in" do
151
+ before do
152
+ subject.stub(:user_identifier).and_return("Jimbo Jones")
153
+ end
154
+
155
+ it "returns true" do
156
+ subject.user_connection?.should == true
157
+ end
158
+ end
159
+
160
+ context "when a user is signed out" do
161
+ before do
162
+ subject.stub(:user_identifier).and_return(nil)
163
+ end
164
+
165
+ it "returns true" do
166
+ subject.user_connection?.should == false
167
+ end
144
168
  end
145
169
  end
146
170
 
147
- describe "#trigger" do
148
- =begin
149
- it "should add the event to the queue" do
150
- pending
151
- subject.stub(:flush)
152
- subject.should_receive(:enqueue).with('event')
153
- subject.trigger 'event'
171
+ describe "#user" do
172
+ it "provides access to the current_user object" do
173
+ user = double('User')
174
+ subject.stub(:user_identifier).and_return true
175
+ subject.stub_chain(:controller_delegate, :current_user).and_return user
176
+ subject.user.should == user
154
177
  end
178
+ end
155
179
 
156
- it "should flush the queue" do
157
- subject.should_receive(:flush)
158
- subject.trigger 'event'
180
+ describe "#enqueue" do
181
+ it "should add the event to the queue" do
182
+ subject.enqueue 'event'
183
+ subject.queue.queue.should == ['event']
159
184
  end
160
- =end
161
185
  end
162
186
 
163
187
  describe "#flush" do
164
188
  before do
165
- event = double('event')
166
- event.stub!(:serialize).and_return("['event']")
167
- 3.times { subject.enqueue event }
189
+ event = Event.new(:queued_event, data: 'test')
190
+ 2.times { subject.enqueue event }
168
191
  end
169
192
 
170
193
  it "should serialize all events into one array" do
171
- serialized_array = "[['event'],['event'],['event']]"
172
- subject.should_receive(:send).with(serialized_array)
194
+ serialized_array = <<-EOF.strip_heredoc
195
+ [["queued_event",{"id":null,"channel":null,"user_id":null,"data":"test","success":null,"result":null,"server_token":null}],
196
+ ["queued_event",{"id":null,"channel":null,"user_id":null,"data":"test","success":null,"result":null,"server_token":null}]]
197
+ EOF
198
+
199
+ subject.should_receive(:send).with(serialized_array.gsub(/\n/,'').strip)
173
200
  subject.flush
174
201
  end
175
202
  end
176
203
 
204
+ describe "#trigger" do
205
+ it "passes a serialized event to the connections #send method" do
206
+ event.stub(:serialize).and_return('test')
207
+ subject.should_receive(:send).with "[test]"
208
+ subject.trigger event
209
+ end
210
+ end
211
+
177
212
  describe "#close_connection" do
178
213
  before do
214
+ subject.stub(:user_identifier).and_return(1)
179
215
  @connection_manager = double('connection_manager').as_null_object
180
216
  subject.stub_chain(:dispatcher, :connection_manager).and_return(@connection_manager)
181
217
  end
@@ -17,13 +17,13 @@ module WebsocketRails
17
17
 
18
18
  before(:each) do
19
19
  ConnectionAdapters::Base.any_instance.stub(:send)
20
- @mock_socket = ConnectionAdapters::Base.new(mock_request,dispatcher)
20
+ @mock_socket = ConnectionAdapters::Base.new(mock_request, dispatcher)
21
21
  ConnectionAdapters.stub(:establish_connection).and_return(@mock_socket)
22
22
  end
23
23
 
24
24
  describe "#initialize" do
25
- it "should create an empty connections array" do
26
- subject.connections.should be_a Array
25
+ it "should create an empty connections hash" do
26
+ subject.connections.should be_a Hash
27
27
  end
28
28
 
29
29
  it "should create a new dispatcher instance" do
@@ -36,20 +36,44 @@ module WebsocketRails
36
36
  expect { open_connection }.to change { connections.count }.by(1)
37
37
  end
38
38
 
39
- it "should store the new connection in the @connections array" do
39
+ it "should store the new connection in the @connections Hash" do
40
40
  open_connection
41
- connections.include?(@mock_socket).should be_true
41
+ connections[@mock_socket.id].should == @mock_socket
42
42
  end
43
43
 
44
44
  it "should return an Async Rack response" do
45
45
  open_connection.should == [ -1, {}, [] ]
46
46
  end
47
+
48
+ before do
49
+ SecureRandom.stub(:hex).and_return(1, 2)
50
+ end
51
+
52
+ it "gives the new connection a unique ID" do
53
+ @mock_socket.should_receive(:id=).with(1)
54
+ open_connection
55
+ @mock_socket.should_receive(:id=).with(2)
56
+ open_connection
57
+ end
58
+
59
+ context "user connections" do
60
+ before do
61
+ @mock_socket.stub(:user_connection?).and_return true
62
+ @mock_socket.stub(:user_identifier).and_return "El Jefe"
63
+ open_connection
64
+ end
65
+
66
+ it "stores the connection in the UserManager" do
67
+ WebsocketRails.users["El Jefe"].connections.first.should == @mock_socket
68
+ end
69
+ end
47
70
  end
48
71
 
49
72
  context "new POST event" do
50
73
  before(:each) do
51
- @mock_http = ConnectionAdapters::Http.new(mock_request,dispatcher)
52
- app.connections << @mock_http
74
+ @mock_http = ConnectionAdapters::Http.new(mock_request, dispatcher)
75
+ @mock_http.id = 1
76
+ app.connections[@mock_http.id] = @mock_http
53
77
  end
54
78
 
55
79
  it "should receive the new event for the correct connection" do
@@ -60,7 +84,7 @@ module WebsocketRails
60
84
 
61
85
  context "open connections" do
62
86
  before(:each) do
63
- ConnectionAdapters.stub(:establish_connection).and_return(@mock_socket,ConnectionAdapters::Base.new(mock_request,dispatcher))
87
+ ConnectionAdapters.stub(:establish_connection).and_return(@mock_socket, ConnectionAdapters::Base.new(mock_request, dispatcher))
64
88
  4.times { open_connection }
65
89
  end
66
90
 
@@ -81,7 +105,7 @@ module WebsocketRails
81
105
  context "when closing" do
82
106
  it "should remove the connection object from the @connections array" do
83
107
  @mock_socket.on_close
84
- connections.include?(@mock_socket).should be_false
108
+ connections.has_key?(@mock_socket.id).should be_false
85
109
  end
86
110
 
87
111
  it "should decrement the connection count by one" do
@@ -95,6 +119,18 @@ module WebsocketRails
95
119
  end
96
120
  @mock_socket.on_close
97
121
  end
122
+
123
+ context "user connections" do
124
+ before do
125
+ @mock_socket.stub(:user_connection?).and_return true
126
+ @mock_socket.stub(:user_identifier).and_return "El Jefe"
127
+ end
128
+
129
+ it "deletes the connection from the UserManager" do
130
+ @mock_socket.on_close
131
+ WebsocketRails.users["El Jefe"].class.should == UserManager::MissingConnection
132
+ end
133
+ end
98
134
  end
99
135
 
100
136
  end
@@ -1,18 +1,8 @@
1
1
  require "spec_helper"
2
2
  require "eventmachine"
3
+ require "ostruct"
3
4
 
4
5
  module WebsocketRails
5
- #class Synchronization
6
- # def test_block(channel, &block)
7
- # # do nothing beyatch
8
- # block.call
9
- # end
10
-
11
- # def synchronize!
12
- # test_block("something") { raise "FTW!" }
13
- # end
14
- #end
15
-
16
6
  describe Synchronization do
17
7
 
18
8
  around(:each) do |example|
@@ -59,7 +49,7 @@ module WebsocketRails
59
49
 
60
50
  context "when dispatching user events" do
61
51
  before do
62
- @event = Event.new(:channel_event, :user_id => :username, :data => 'hello channel one')
52
+ @event = Event.new(:channel_event, :user_id => "username", :data => 'hello channel one')
63
53
  end
64
54
 
65
55
  context "and the user is not connected to this server" do
@@ -71,18 +61,18 @@ module WebsocketRails
71
61
  context "and the user is connected to this server" do
72
62
  before do
73
63
  @connection = double('Connection')
74
- WebsocketRails.users[:username] = @connection
64
+ WebsocketRails.users["username"] = @connection
75
65
  end
76
66
 
77
67
  it "triggers the event on the correct user" do
78
- WebsocketRails.users[:username].should_receive(:trigger).with @event
68
+ WebsocketRails.users["username"].should_receive(:trigger).with @event
79
69
  subject.trigger_incoming @event
80
70
  end
81
71
  end
82
72
  end
83
73
  end
84
74
 
85
- describe "#generate_unique_token" do
75
+ describe "#generate_server_token" do
86
76
  before do
87
77
  SecureRandom.stub(:urlsafe_base64).and_return(1, 2, 3)
88
78
  end
@@ -91,14 +81,14 @@ module WebsocketRails
91
81
  @redis.del "websocket_rails.active_servers"
92
82
  end
93
83
 
94
- it "should generate a unique token" do
84
+ it "should generate a unique server token" do
95
85
  SecureRandom.should_receive(:urlsafe_base64).at_least(1).times
96
- subject.generate_unique_token
86
+ subject.generate_server_token
97
87
  end
98
88
 
99
89
  it "should generate another id if the current id is already registered" do
100
90
  @redis.sadd "websocket_rails.active_servers", 1
101
- token = subject.generate_unique_token
91
+ token = subject.generate_server_token
102
92
  token.should == 2
103
93
  end
104
94
  end
@@ -117,5 +107,44 @@ module WebsocketRails
117
107
  end
118
108
  end
119
109
 
110
+ describe "#register_user" do
111
+ before do
112
+ @connection = double('Connection')
113
+ @user = User.new
114
+ @user.attributes.update(name: 'Frank The Tank', email: 'frank@tank.com')
115
+ @user.instance_variable_set(:@new_record, false)
116
+ @user.instance_variable_set(:@destroyed, false)
117
+ @connection.stub(:user_identifier).and_return 'Frank The Tank'
118
+ @connection.stub(:user).and_return @user
119
+ end
120
+
121
+ it "stores the serialized user object in redis" do
122
+ @user.persisted?.should == true
123
+ Redis.any_instance.should_receive(:hset).with("websocket_rails.users", @connection.user_identifier, @user.as_json.to_json)
124
+ Synchronization.register_user(@connection)
125
+ end
126
+ end
127
+
128
+ describe "#destroy_user" do
129
+ it "stores the serialized user object in redis" do
130
+ Redis.any_instance.should_receive(:hdel).with("websocket_rails.users", 'user_id')
131
+ Synchronization.destroy_user('user_id')
132
+ end
133
+ end
134
+
135
+ describe "#find_user" do
136
+ it "retrieves the serialized user object in redis" do
137
+ Redis.any_instance.should_receive(:hget).with("websocket_rails.users", 'test')
138
+ Synchronization.find_user('test')
139
+ end
140
+ end
141
+
142
+ describe "#all_users" do
143
+ it "retrieves the entire serialized users hash redis" do
144
+ Redis.any_instance.should_receive(:hgetall).with("websocket_rails.users")
145
+ Synchronization.all_users
146
+ end
147
+ end
148
+
120
149
  end
121
150
  end