websocket-rails 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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