camper_van 0.0.1

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.
@@ -0,0 +1,433 @@
1
+ require "spec_helper"
2
+
3
+ describe CamperVan::Channel do
4
+
5
+ class TestClient
6
+ attr_reader :sent, :nick, :user, :host
7
+ include CamperVan::ServerReply
8
+ def initialize
9
+ @nick, @user, @host = "nathan", "nathan", "localhost"
10
+ @sent = []
11
+ end
12
+ def send_line(line)
13
+ @sent << line
14
+ end
15
+ def subdomain
16
+ "subdomain"
17
+ end
18
+ end
19
+
20
+ class TestRoom
21
+ attr_reader :locked, :full, :topic, :membership_limit
22
+ attr_reader :sent
23
+
24
+ attr_writer :users, :topic, :locked, :full, :open_to_guests
25
+ attr_writer :stream
26
+
27
+ def initialize
28
+ @users = []
29
+ @sent = []
30
+ @membership_limit = 12
31
+ end
32
+
33
+ def id
34
+ 10
35
+ end
36
+
37
+ def locked?
38
+ @locked
39
+ end
40
+ def full?
41
+ @full
42
+ end
43
+ def open_to_guests?
44
+ @open_to_guests
45
+ end
46
+ def join
47
+ yield
48
+ end
49
+
50
+ def users
51
+ yield @users if block_given?
52
+ @users
53
+ end
54
+
55
+ def text(line)
56
+ @sent << line
57
+ end
58
+
59
+ def tweet(line)
60
+ @sent << [:tweet, line]
61
+ end
62
+
63
+ def stream
64
+ if @messages
65
+ @messages.each { |m| yield m }
66
+ end
67
+ return @stream
68
+ end
69
+ end
70
+
71
+ before :each do
72
+ @client = TestClient.new
73
+ @room = TestRoom.new
74
+ @room.topic = "the topic"
75
+ @channel = CamperVan::Channel.new("#test", @client, @room)
76
+ end
77
+
78
+ describe "#join" do
79
+ it "sends a user join as the command" do
80
+ @channel.join
81
+ @client.sent.first.must_equal ":nathan!nathan@localhost JOIN :#test"
82
+ end
83
+
84
+ it "sends the topic as a command" do
85
+ @channel.join
86
+ @client.sent[1].must_equal ":camper_van 332 nathan #test :the topic"
87
+ end
88
+
89
+ it "sends the list of users" do
90
+ @room.users = [
91
+ OpenStruct.new(:id => 10, :name => "Nathan", :email_address => "x@y.com"),
92
+ OpenStruct.new(:id => 11, :name => "Bob", :email_address => "x@y.com"),
93
+ OpenStruct.new(:id => 12, :name => "Joe", :email_address => "x@y.com")
94
+ ]
95
+ @channel.join
96
+ @client.sent[2].must_equal ":camper_van 353 nathan = #test :nathan bob joe"
97
+ @client.sent[3].must_equal ":camper_van 366 nathan #test :End of /NAMES list."
98
+ end
99
+
100
+ it "sends the list of users including myself, even if the server doesn't say i'm there" do
101
+ @room.users = [
102
+ OpenStruct.new(:id => 11, :name => "Bob", :email_address => "x@y.com"),
103
+ OpenStruct.new(:id => 12, :name => "Joe", :email_address => "x@y.com")
104
+ ]
105
+ @channel.join
106
+ @client.sent[2].must_equal ":camper_van 353 nathan = #test :nathan bob joe"
107
+ end
108
+ end
109
+
110
+ describe "#part" do
111
+ it "sends a part command to the client" do
112
+ @channel.part
113
+ @client.sent.last.must_match /PART #test/
114
+ end
115
+
116
+ it "closes the connection on the stream" do
117
+ @room.stream = MiniTest::Mock.new
118
+ @room.stream.expect(:close_connection, nil)
119
+ @channel.stream_campfire_to_channel # sets up stream
120
+ @channel.part
121
+
122
+ @room.stream.verify
123
+ end
124
+ end
125
+
126
+ describe "#list_users" do
127
+ before :each do
128
+ @room.users = [OpenStruct.new(:id => 10, :name => "Joe", :email_address => "user@example.com")]
129
+ @channel.join
130
+ @client.sent.clear
131
+ end
132
+ it "retrieves a list of users and sends them to the client" do
133
+ @channel.list_users
134
+ @client.sent.first.must_equal(
135
+ ":camper_van 352 nathan #test user example.com camper_van joe H :0 Joe"
136
+ )
137
+ @client.sent.last.must_match /:camper_van 315 nathan #test :End/
138
+ end
139
+
140
+ it "issues JOIN irc commands for users who have joined but aren't yet tracked" do
141
+ @channel.list_users
142
+ @room.users << OpenStruct.new(:id => 11, :name => "Bob", :email_address => "bob@example.com")
143
+ @client.sent.clear
144
+ @channel.list_users
145
+ @client.sent.first.must_match /bob.*JOIN #test/
146
+ end
147
+
148
+ it "issues PART commands for users who have left but are still tracked" do
149
+ @room.users = []
150
+ @channel.list_users
151
+ @client.sent.first.must_match /joe.*PART #test/
152
+ end
153
+
154
+ it "shows a user as away if they are idle" do
155
+ @channel.users[10].idle = true
156
+ @channel.list_users
157
+ @client.sent.first.must_match /joe G :0 Joe/
158
+ end
159
+
160
+ it "shows admin users as having +o" do
161
+ @channel.users[10].admin = true
162
+ @channel.list_users
163
+ @client.sent.first.must_match /joe H@ :0 Joe/
164
+ end
165
+ end
166
+
167
+ describe "#privmsg" do
168
+ it "sends the message as text to the room" do
169
+ @channel.privmsg "hello world"
170
+ @room.sent.first.must_equal "hello world"
171
+ end
172
+
173
+ it "converts ACTION messages to campfire-appropriate messages" do
174
+ @channel.privmsg "\01ACTION runs away\01"
175
+ @room.sent.first.must_equal "*runs away*"
176
+ end
177
+
178
+ it "converts twitter urls to tweet messages" do
179
+ url = "https://twitter.com/aniero/status/12345"
180
+ @channel.privmsg url
181
+ @room.sent.first.must_equal [:tweet, url]
182
+ end
183
+
184
+ it "converts leading nicknames into campfire names" do
185
+ # get the users into the room
186
+ @room.users = [
187
+ OpenStruct.new(:id => 11, :name => "Bob Fred", :email_address => "x@y.com"),
188
+ OpenStruct.new(:id => 12, :name => "Joe", :email_address => "x@y.com")
189
+ ]
190
+ @channel.list_users
191
+
192
+ @channel.privmsg "bob_fred: sup dude"
193
+ @room.sent.last.must_match /Bob Fred: sup dude/
194
+ end
195
+ end
196
+
197
+ describe "#current_mode" do
198
+ it "sends the current mode to the client" do
199
+ @channel.current_mode
200
+ @client.sent.last.must_match ":camper_van 324 nathan #test +ls 12"
201
+ end
202
+
203
+ context "and a locked room" do
204
+ it "includes +i mode" do
205
+ @room.locked = true
206
+ @channel.current_mode
207
+ @client.sent.last.must_match ":camper_van 324 nathan #test +ils 12"
208
+ end
209
+ end
210
+
211
+ context "and a room that allows guests" do
212
+ it "drops the +s from the mode" do
213
+ @room.open_to_guests = true
214
+ @channel.current_mode
215
+ @client.sent.last.must_match ":camper_van 324 nathan #test +l 12"
216
+ end
217
+ end
218
+ end
219
+
220
+ describe "#set_mode" do
221
+ before :each do
222
+ @room = OpenStruct.new :membership_limit => 10
223
+ class << @room
224
+ def locked?
225
+ self.locked
226
+ end
227
+ def lock
228
+ self.lock_called = true
229
+ end
230
+ def unlock
231
+ self.unlock_called = true
232
+ end
233
+ end
234
+ @channel = CamperVan::Channel.new("#test", @client, @room)
235
+ end
236
+
237
+ context "with a +i" do
238
+ it "locks the room" do
239
+ @channel.set_mode "+i"
240
+ @room.lock_called.must_equal true
241
+ @room.locked.must_equal true
242
+ end
243
+
244
+ it "tells the client that the channel mode has changed" do
245
+ @channel.set_mode "+i"
246
+ @client.sent.last.must_match /MODE #test \+ils 10/
247
+ end
248
+ end
249
+
250
+ context "with a -i" do
251
+ it "unlocks the room" do
252
+ @channel.set_mode "-i"
253
+ @room.unlock_called.must_equal true
254
+ @room.locked.must_equal false
255
+ end
256
+
257
+ it "tells the client the channel mode has changed" do
258
+ @channel.set_mode "-i"
259
+ @client.sent.last.must_match /MODE #test \+ls 10/
260
+ end
261
+ end
262
+
263
+ context "with an unknown mode" do
264
+ it "replies with an irc error" do
265
+ @channel.set_mode "+m"
266
+ @client.sent.last.must_match /472 nathan :.*unknown mode/
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "#map_message_to_irc when streaming" do
272
+ class TestMessage < OpenStruct
273
+ def user
274
+ yield OpenStruct.new :name => "Joe", :id => 10, :email_address => "joe@example.com"
275
+ end
276
+ end
277
+
278
+ def msg(type, attributes={})
279
+ TestMessage.new(
280
+ attributes.merge :type => "#{type}Message", :id => 1234
281
+ )
282
+ end
283
+
284
+ it "sends a privmsg with the message when a user says something" do
285
+ @channel.map_message_to_irc msg("Text", :body => "hello")
286
+ @client.sent.last.must_match ":joe!joe@campfire PRIVMSG #test hello"
287
+ end
288
+
289
+ it "sends a privmsg with the pasted url and the first line when a user pastes something" do
290
+ @channel.map_message_to_irc msg("Paste", :body => "foo\nbar\nbaz\nbleh")
291
+ @client.sent.last.must_match %r(:joe\S+ PRIVMSG #test .*room/10/paste/1234)
292
+ end
293
+
294
+ it "sends a privmsg with an action when a user message is wrapped in *'s" do
295
+ @channel.map_message_to_irc msg("Text", :body => "*did a thing*")
296
+ @client.sent.last.must_match /PRIVMSG #test :\x01ACTION did a thing\x01/
297
+ end
298
+
299
+ it "converts leading name matches to irc nicks" do
300
+ # get the users into the room
301
+ @room.users = [
302
+ OpenStruct.new(:id => 11, :name => "Bob Fred", :email_address => "x@y.com"),
303
+ OpenStruct.new(:id => 12, :name => "Joe", :email_address => "x@y.com")
304
+ ]
305
+ @channel.list_users
306
+ @client.sent.clear
307
+
308
+ # now check the mapping
309
+ @channel.map_message_to_irc msg("Text", :body => "Bob Fred: hello")
310
+ @client.sent.last.must_match %r(PRIVMSG #test :bob_fred: hello)
311
+ end
312
+
313
+ it "sends an action when a user plays the crickets sound" do
314
+ @channel.map_message_to_irc msg("Sound", :body => "crickets")
315
+ @client.sent.last.must_match /\x01ACTION hears crickets chirping\x01/
316
+ end
317
+
318
+ it "sends an action when a user plays the rimshot sound" do
319
+ @channel.map_message_to_irc msg("Sound", :body => "rimshot")
320
+ @client.sent.last.must_match /\x01ACTION plays a rimshot\x01/
321
+ end
322
+
323
+ it "sends an action when a user plays the trombone sound" do
324
+ @channel.map_message_to_irc msg("Sound", :body => "trombone")
325
+ @client.sent.last.must_match /\x01ACTION plays a sad trombone\x01/
326
+ end
327
+
328
+ it "sends an action when a user plays the vuvuzela sound" do
329
+ @channel.map_message_to_irc msg("Sound", :body => "vuvuzela")
330
+ @client.sent.last.must_match /ACTION ======<\(\)/
331
+ end
332
+
333
+ it "sends an action when a user plays an unknown sound" do
334
+ @channel.map_message_to_irc msg("Sound", :body => "boing")
335
+ @client.sent.last.must_match /\x01ACTION played a boing sound\x01/
336
+ end
337
+
338
+ it "sends a mode change when the room is locked" do
339
+ @channel.map_message_to_irc msg("Lock")
340
+ @client.sent.last.must_match %r/:joe\S+ MODE #test \+i/
341
+ end
342
+
343
+ it "sends a mode change when the room is unlocked" do
344
+ @channel.map_message_to_irc msg("Unlock")
345
+ @client.sent.last.must_match %r/:joe\S+ MODE #test -i/
346
+ end
347
+
348
+ it "sends a mode change when the room disallows guests" do
349
+ @channel.map_message_to_irc msg("DisallowGuests")
350
+ @client.sent.last.must_match %r/:joe\S+ MODE #test \+s/
351
+ end
352
+
353
+ it "sends a mode change when the room allows guests" do
354
+ @channel.map_message_to_irc msg("AllowGuests")
355
+ @client.sent.last.must_match %r/:joe\S+ MODE #test -s/
356
+ end
357
+
358
+ it "sends a join command when a user enters the room" do
359
+ @channel.map_message_to_irc msg("Enter")
360
+ @client.sent.last.must_match %r/:joe\S+ JOIN #test/
361
+ end
362
+
363
+ it "adds the user to the internal tracking list when a user joins" do
364
+ @channel.map_message_to_irc msg("Enter")
365
+ @client.sent.last.must_match %r/:joe\S+ JOIN #test/
366
+ @channel.users[10].wont_equal nil
367
+ end
368
+
369
+ it "sends a part command when a user leaves the room" do
370
+ @channel.map_message_to_irc msg("Leave")
371
+ @client.sent.last.must_match %r/:joe\S+ PART #test/
372
+ end
373
+
374
+ it "removes the user from the tracking list when they depart" do
375
+ @channel.map_message_to_irc msg("Enter")
376
+ @channel.map_message_to_irc msg("Leave")
377
+ @channel.users.size.must_equal 0
378
+ end
379
+
380
+ it "sends a part command when a user is kicked from the room" do
381
+ @channel.map_message_to_irc msg("Kick")
382
+ @client.sent.last.must_match %r/:joe\S+ PART #test/
383
+ end
384
+
385
+ it "sends a topic command when a user changes the topic" do
386
+ @channel.map_message_to_irc msg("TopicChange", :body => "new topic")
387
+ @client.sent.last.must_match ":joe!joe@campfire TOPIC #test :new topic"
388
+ end
389
+
390
+ it "sends a message containing the upload link when a user uploads a file" do
391
+ @channel.map_message_to_irc msg("Upload", :body => "filename")
392
+ @client.sent.last.must_match %r(:joe\S+ PRIVMSG #test .*uploads/1234/filename)
393
+ end
394
+
395
+ it "sends a message containing the tweet url when a user posts a tweet" do
396
+ body = {
397
+ "id" => 12345,
398
+ "author_username" => "aniero",
399
+ "message" => "hello, twitter",
400
+ "author_avatar_url" => "http://example.com/url.img"
401
+ }
402
+ @channel.map_message_to_irc msg("Tweet", :body => body.to_yaml)
403
+ @client.sent.last.must_match %r(:joe\S+ PRIVMSG #test .*twitter.com/aniero/status/12345.*)
404
+ end
405
+
406
+ it "sends a message containing the tweet url when a user posts a tweet with symbols" do
407
+ body = {
408
+ :id => 12345,
409
+ :author_username => "aniero",
410
+ :message => "hello, twitter",
411
+ :author_avatar_url => "http://example.com/url.img"
412
+ }
413
+ @channel.map_message_to_irc msg("Tweet", :body => body.to_yaml)
414
+ @client.sent.last.must_match %r(:joe\S+ PRIVMSG #test .*twitter.com/aniero/status/12345.*)
415
+ end
416
+
417
+ # it "sends a notice with the message when the system sends a message"
418
+
419
+ it "marks the user as away when a user goes idle" do
420
+ @channel.map_message_to_irc msg("Enter")
421
+ @channel.map_message_to_irc msg("Idle")
422
+ @channel.users[10].idle?.must_equal true
423
+ end
424
+
425
+ it "marks the user as back when a user becomes active" do
426
+ @channel.map_message_to_irc msg("Enter")
427
+ @channel.map_message_to_irc msg("Idle")
428
+ @channel.map_message_to_irc msg("Unidle")
429
+ @channel.users[10].idle?.must_equal false
430
+ end
431
+ end
432
+ end
433
+
@@ -0,0 +1,54 @@
1
+ require "spec_helper"
2
+
3
+ describe CamperVan::CommandDefinition do
4
+ before :each do
5
+ @test_commands = Class.new do
6
+ include CamperVan::CommandDefinition
7
+ attr_accessor :nick
8
+
9
+ handle :nick do |args|
10
+ @nick = args.first
11
+ args
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ it "defines a handle class method on a class" do
18
+ @test_commands.must_respond_to :handle
19
+ end
20
+
21
+ it "defines a handle instance method on a class" do
22
+ @test_commands.new.must_respond_to :handle
23
+ end
24
+
25
+ describe "#handle" do
26
+ before :each do
27
+ @cmd = @test_commands.new
28
+ end
29
+
30
+ it "raises an exception when no handler is available" do
31
+ lambda { @cmd.handle(:foo => []) }.must_raise(CamperVan::HandlerMissing)
32
+ end
33
+
34
+ it "passes the arguments to the block" do
35
+ @cmd.handle(:nick => %w(lol what)).must_equal %w(lol what)
36
+ end
37
+
38
+ it "evaluates the block in the instance context" do
39
+ @cmd.nick.must_equal nil
40
+ @cmd.handle(:nick => ["bob"])
41
+ @cmd.nick.must_equal "bob"
42
+ end
43
+ end
44
+
45
+ describe ".handle" do
46
+ it "defines a handler for the given command" do
47
+ @test_commands.handle :foo do
48
+ "success"
49
+ end
50
+ @test_commands.new.handle(:foo => []).must_equal "success"
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe CamperVan::CommandParser do
4
+ class TestParser
5
+ include CamperVan::CommandParser
6
+ end
7
+
8
+ it "defines a parse method on a class that includes it" do
9
+ TestParser.new.must_respond_to :parse
10
+ end
11
+
12
+ describe "#parse" do
13
+ before :each do
14
+ @parser = TestParser.new
15
+ end
16
+
17
+ it "returns nil for a malformed command" do
18
+ @parser.parse("lolwhat").must_equal nil
19
+ end
20
+
21
+ it "parses a LIST command" do
22
+ @parser.parse("LIST").must_equal :list => []
23
+ end
24
+
25
+ it "parses a NICK command" do
26
+ @parser.parse("NICK nathan").must_equal :nick => ["nathan"]
27
+ end
28
+
29
+ it "parses a PRIVMSG command" do
30
+ @parser.parse("PRIVMSG #chan :hello there").must_equal(
31
+ :privmsg => ["#chan", "hello there"]
32
+ )
33
+ end
34
+
35
+ it "parses a MODE command" do
36
+ @parser.parse("MODE +i").must_equal :mode => ["+i"]
37
+ end
38
+ end
39
+
40
+ end