collectiveidea-tinder 1.2.2
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.
- data/.gitignore +3 -0
- data/CHANGELOG.txt +39 -0
- data/Manifest.txt +10 -0
- data/README.txt +48 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/tinder.rb +16 -0
- data/lib/tinder/campfire.rb +207 -0
- data/lib/tinder/multipart.rb +64 -0
- data/lib/tinder/room.rb +246 -0
- data/site/index.html +101 -0
- data/site/stylesheets/style.css +77 -0
- data/spec/campfire_spec.rb +225 -0
- data/spec/html/full_lobby.html +198 -0
- data/spec/html/normal_lobby.html +192 -0
- data/spec/html/transcript.html +133 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +4 -0
- data/test/remote/credentials.rb.example +4 -0
- data/test/remote/remote_campfire_test.rb +59 -0
- data/test/test_helper.rb +3 -0
- data/tinder.gemspec +77 -0
- metadata +118 -0
data/lib/tinder/room.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
module Tinder
|
2
|
+
# A campfire room
|
3
|
+
class Room
|
4
|
+
attr_reader :id, :name
|
5
|
+
|
6
|
+
def initialize(campfire, id, name = nil)
|
7
|
+
@campfire = campfire
|
8
|
+
@id = id
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
# Join the room. Pass +true+ to join even if you've already joined.
|
13
|
+
def join(force = false)
|
14
|
+
@room = returning(get("room/#{id}")) do |room|
|
15
|
+
raise Error, "Could not join room" unless verify_response(room, :success)
|
16
|
+
@membership_key = room.body.scan(/\"membershipKey\":\s?\"([a-z0-9]+)\"/).to_s
|
17
|
+
@user_id = room.body.scan(/\"userID\":\s?(\d+)/).to_s
|
18
|
+
@last_cache_id = room.body.scan(/\"lastCacheID\":\s?(\d+)/).to_s
|
19
|
+
@timestamp = room.body.scan(/\"timestamp\":\s?(\d+)/).to_s
|
20
|
+
@idle_since = Time.now
|
21
|
+
end if @room.nil? || force
|
22
|
+
ping
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
# Leave a room
|
27
|
+
def leave
|
28
|
+
returning verify_response(post("room/#{id}/leave"), :redirect) do
|
29
|
+
@room, @membership_key, @user_id, @last_cache_id, @timestamp, @idle_since = nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Toggle guest access on or off
|
34
|
+
def toggle_guest_access
|
35
|
+
# re-join the room to get the guest url
|
36
|
+
verify_response(post("room/#{id}/toggle_guest_access"), :success) && join(true)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get the url for guest access
|
40
|
+
def guest_url
|
41
|
+
join
|
42
|
+
link = (Hpricot(@room.body)/"#guest_access h4").first
|
43
|
+
link.inner_html if link
|
44
|
+
end
|
45
|
+
|
46
|
+
def guest_access_enabled?
|
47
|
+
!guest_url.nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
# The invite code use for guest
|
51
|
+
def guest_invite_code
|
52
|
+
guest_url.scan(/\/(\w*)$/).to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Change the name of the room
|
56
|
+
def name=(name)
|
57
|
+
@name = name if verify_response(post("account/edit/room/#{id}", { :room => { :name => name }}, :ajax => true), :success)
|
58
|
+
end
|
59
|
+
alias_method :rename, :name=
|
60
|
+
|
61
|
+
# Change the topic
|
62
|
+
def topic=(topic)
|
63
|
+
topic if verify_response(post("room/#{id}/change_topic", { 'room' => { 'topic' => topic }}, :ajax => true), :success)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get the current topic
|
67
|
+
def topic
|
68
|
+
join
|
69
|
+
h = (Hpricot(@room.body)/"#topic")
|
70
|
+
if h
|
71
|
+
(h/:span).remove
|
72
|
+
h.inner_text.strip
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Lock the room to prevent new users from entering and to disable logging
|
77
|
+
def lock
|
78
|
+
verify_response(post("room/#{id}/lock", {}, :ajax => true), :success)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Unlock the room
|
82
|
+
def unlock
|
83
|
+
verify_response(post("room/#{id}/unlock", {}, :ajax => true), :success)
|
84
|
+
end
|
85
|
+
|
86
|
+
def ping(force = false)
|
87
|
+
returning verify_response(post("room/#{id}/tabs", { }, :ajax => true), :success) do
|
88
|
+
@idle_since = Time.now
|
89
|
+
end if @idle_since < 1.minute.ago || force
|
90
|
+
end
|
91
|
+
|
92
|
+
def destroy
|
93
|
+
verify_response(post("account/delete/room/#{id}"), :success)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Post a new message to the chat room
|
97
|
+
def speak(message, options = {})
|
98
|
+
post_options = {
|
99
|
+
:message => message,
|
100
|
+
:t => Time.now.to_i
|
101
|
+
}.merge(options)
|
102
|
+
|
103
|
+
post_options.delete(:paste) unless post_options[:paste]
|
104
|
+
response = post("room/#{id}/speak", post_options, :ajax => true)
|
105
|
+
|
106
|
+
if verify_response(response, :success)
|
107
|
+
message
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def paste(message)
|
112
|
+
speak message, :paste => true
|
113
|
+
end
|
114
|
+
|
115
|
+
# Get the list of users currently chatting for this room
|
116
|
+
def users
|
117
|
+
@campfire.users name
|
118
|
+
end
|
119
|
+
|
120
|
+
# Get and array of the messages that have been posted to the room. Each
|
121
|
+
# messages is a hash with:
|
122
|
+
# * +:person+: the display name of the person that posted the message
|
123
|
+
# * +:message+: the body of the message
|
124
|
+
# * +:user_id+: Campfire user id
|
125
|
+
# * +:id+: Campfire message id
|
126
|
+
#
|
127
|
+
# room.listen
|
128
|
+
# #=> [{:person=>"Brandon", :message=>"I'm getting very sleepy", :user_id=>"148583", :id=>"16434003"}]
|
129
|
+
#
|
130
|
+
# Called without a block, listen will return an array of messages that have been
|
131
|
+
# posted since you joined. listen also takes an optional block, which then polls
|
132
|
+
# for new messages every 5 seconds and calls the block for each message.
|
133
|
+
#
|
134
|
+
# room.listen do |m|
|
135
|
+
# room.speak "#{m[:person]}, Go away!" if m[:message] =~ /Java/i
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
def listen(interval = 5)
|
139
|
+
join
|
140
|
+
if block_given?
|
141
|
+
catch(:stop_listening) do
|
142
|
+
trap('INT') { throw :stop_listening }
|
143
|
+
loop do
|
144
|
+
ping
|
145
|
+
self.messages.each {|msg| yield msg }
|
146
|
+
sleep interval
|
147
|
+
end
|
148
|
+
end
|
149
|
+
else
|
150
|
+
self.messages
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Get the dates for the available transcripts for this room
|
155
|
+
def available_transcripts
|
156
|
+
@campfire.available_transcripts(id)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Get the transcript for the given date (Returns a hash in the same format as #listen)
|
160
|
+
#
|
161
|
+
# room.transcript(room.available_transcripts.first)
|
162
|
+
# #=> [{:message=>"foobar!",
|
163
|
+
# :user_id=>"99999",
|
164
|
+
# :person=>"Brandon",
|
165
|
+
# :id=>"18659245",
|
166
|
+
# :timestamp=>=>Tue May 05 07:15:00 -0700 2009}]
|
167
|
+
#
|
168
|
+
# The timestamp slot will typically have a granularity of five minutes.
|
169
|
+
#
|
170
|
+
def transcript(transcript_date)
|
171
|
+
url = "room/#{id}/transcript/#{transcript_date.to_date.strftime('%Y/%m/%d')}"
|
172
|
+
date, time = nil, nil
|
173
|
+
(Hpricot(get(url).body) / ".message").collect do |message|
|
174
|
+
person = (message / '.person span').first
|
175
|
+
if !person
|
176
|
+
# No span for enter/leave the room messages
|
177
|
+
person = (message / '.person').first
|
178
|
+
end
|
179
|
+
body = (message / '.body div').first
|
180
|
+
if d = (message / '.date span').first
|
181
|
+
date = d.inner_html
|
182
|
+
end
|
183
|
+
if t = (message / '.time div').first
|
184
|
+
time = t.inner_html
|
185
|
+
end
|
186
|
+
{:id => message.attributes['id'].scan(/message_(\d+)/).to_s,
|
187
|
+
:person => person ? person.inner_html : nil,
|
188
|
+
:user_id => message.attributes['class'].scan(/user_(\d+)/).to_s,
|
189
|
+
:message => body ? body.inner_html : nil,
|
190
|
+
# Use the transcript_date to fill in the correct year
|
191
|
+
:timestamp => Time.parse("#{date} #{time}", transcript_date)
|
192
|
+
}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def upload(filename)
|
197
|
+
File.open(filename, "rb") do |file|
|
198
|
+
params = Multipart::MultipartPost.new({'upload' => file, 'submit' => "Upload"})
|
199
|
+
verify_response post("upload.cgi/room/#{@id}/uploads/new", params.query, :multipart => true), :success
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Get the list of latest files for this room
|
204
|
+
def files(count = 5)
|
205
|
+
join
|
206
|
+
(Hpricot(@room.body)/"#file_list li a").to_a[0,count].map do |link|
|
207
|
+
@campfire.send :url_for, link.attributes['href'][1..-1], :only_path => false
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
protected
|
212
|
+
|
213
|
+
def messages
|
214
|
+
returning [] do |messages|
|
215
|
+
response = post("poll.fcgi", {:l => @last_cache_id, :m => @membership_key,
|
216
|
+
:s => @timestamp, :t => "#{Time.now.to_i}000"}, :ajax => true)
|
217
|
+
if response.body.length > 1
|
218
|
+
lines = response.body.split("\r\n")
|
219
|
+
|
220
|
+
if lines.length > 0
|
221
|
+
@last_cache_id = lines.pop.scan(/chat.poller.lastCacheID = (\d+)/).to_s
|
222
|
+
lines.each do |msg|
|
223
|
+
unless msg.match(/timestamp_message/)
|
224
|
+
if msg.length > 0
|
225
|
+
messages << {
|
226
|
+
:id => msg.scan(/message_(\d+)/).to_s,
|
227
|
+
:user_id => msg.scan(/user_(\d+)/).to_s,
|
228
|
+
:person => msg.scan(/\\u003Ctd class=\\"person\\"\\u003E(?:\\u003Cspan\\u003E)?(.+?)(?:\\u003C\/span\\u003E)?\\u003C\/td\\u003E/).to_s,
|
229
|
+
:message => msg.scan(/\\u003Ctd class=\\"body\\"\\u003E\\u003Cdiv\\u003E(.+?)\\u003C\/div\\u003E\\u003C\/td\\u003E/).to_s
|
230
|
+
}
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
[:post, :get, :verify_response].each do |method|
|
240
|
+
define_method method do |*args|
|
241
|
+
@campfire.send method, *args
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
end
|
data/site/index.html
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
7
|
+
<title>Tinder</title>
|
8
|
+
<link rel="stylesheet" type="text/css" href="http://opensoul.org/stylesheets/code.css" />
|
9
|
+
<link rel="stylesheet" type="text/css" href="stylesheets/style.css" />
|
10
|
+
<link href="http://opensoul.org/stylesheets/ci.css" rel="stylesheet" type="text/css" />
|
11
|
+
<script src="http://opensoul.org/javascripts/code_highlighter.js" type="text/javascript"></script>
|
12
|
+
<script src="http://opensoul.org/javascripts/ruby.js" type="text/javascript"></script>
|
13
|
+
</head>
|
14
|
+
|
15
|
+
<body>
|
16
|
+
<div id="collectiveidea">
|
17
|
+
<a href="http://collectiveidea.com"><img src="http://opensoul.org/images/header_logo.gif" alt="Collective Idea" class="logo" width="17" height="22" /></a>
|
18
|
+
<ul class="links">
|
19
|
+
<li><a href="http://daniel.collectiveidea.com/blog">Daniel</a></li>
|
20
|
+
<li><a href="http://opensoul.org">Brandon</a></li>
|
21
|
+
<li class="name"><a href="http://collectiveidea.com"><img src="http://opensoul.org/images/header_collectiveidea.gif" alt="Collective Idea" width="123" height="21" /></a></li>
|
22
|
+
</ul>
|
23
|
+
</div>
|
24
|
+
<div id="main">
|
25
|
+
<div id="header">
|
26
|
+
<h1><a href="/">Tinder</a></h1>
|
27
|
+
<p>Getting the campfire started</p>
|
28
|
+
<ul id="nav">
|
29
|
+
<li><a href="tinder">API Docs</a></li>
|
30
|
+
<li><a href="http://rubyforge.org/projects/tinder">RubyForge</a></li>
|
31
|
+
<li><a href="http://opensoul.org/tags/tinder">Blog</a></li>
|
32
|
+
</ul>
|
33
|
+
</div>
|
34
|
+
<div id="content">
|
35
|
+
<p>Tinder is an API for interfacing with <a href="http://campfirenow.com">Campfire</a>, the 37Signals chat application.</p>
|
36
|
+
<h2>Example</h2>
|
37
|
+
|
38
|
+
<pre><code class="ruby">campfire = Tinder::Campfire.new 'mysubdomain'
|
39
|
+
campfire.login 'myemail@example.com', 'mypassword'</code></pre>
|
40
|
+
|
41
|
+
<h3>Create, find and destroy rooms</h3>
|
42
|
+
<pre><code class="ruby">room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
|
43
|
+
room = campfire.find_room_by_name 'Other Room'
|
44
|
+
room.destroy</code></pre>
|
45
|
+
|
46
|
+
<h3>Speak and Paste</h3>
|
47
|
+
<pre><code class="ruby">room.speak 'Hello world!'
|
48
|
+
room.paste File.read("path/to/your/file.txt")</code></pre>
|
49
|
+
|
50
|
+
<h3>Listening</h3>
|
51
|
+
<pre><code class="ruby">room.listen
|
52
|
+
#=> [{:person=>"Brandon", :message=>"I'm getting very sleepy", :user_id=>"148583", :id=>"16434003"}]
|
53
|
+
|
54
|
+
# or in block form
|
55
|
+
room.listen do |m|
|
56
|
+
room.speak 'Welcome!' if m[:message] == /hello/
|
57
|
+
end</code></pre>
|
58
|
+
|
59
|
+
<h3>Guest Access</h3>
|
60
|
+
<pre><code class="ruby">room.toggle_guest_access
|
61
|
+
room.guest_url #=> http://mysubdomain.campfirenow.com/11111
|
62
|
+
room.guest_invite_code #=> 11111</code></pre>
|
63
|
+
|
64
|
+
<h3>Change the name and topic</h3>
|
65
|
+
<pre><code class="ruby">room.name = 'Tinder Demo'
|
66
|
+
room.topic = 'Showing how to change the room name and topic with tinder…'</code></pre>
|
67
|
+
|
68
|
+
<h3>Users</h3>
|
69
|
+
<pre><code class="ruby">room.users
|
70
|
+
campfire.users # users in all rooms</code></pre>
|
71
|
+
|
72
|
+
<h3>Transcripts</h3>
|
73
|
+
<pre><code class="ruby">transcript = room.transcript(room.available_transcripts.first)
|
74
|
+
#=> [{:message=>"foobar!", :user_id=>"99999", :person=>"Brandon", :id=>"18659245", :timestamp=>Tue May 05 07:15:00 -0700 2009}]
|
75
|
+
</code></pre>
|
76
|
+
|
77
|
+
<p>See the <a href="tinder">API documentation</a> for more details.</p>
|
78
|
+
|
79
|
+
<h2>Installation</h2>
|
80
|
+
|
81
|
+
<p>Tinder can be installed as a gem or a Rails plugin. Install the gem by executing:</p>
|
82
|
+
|
83
|
+
<pre>gem install tinder</pre>
|
84
|
+
|
85
|
+
<p>Or, download it from <a href="http://rubyforge.org/frs/?group_id=2922">RubyForge</a>.</p>
|
86
|
+
|
87
|
+
<h2>Source</h2>
|
88
|
+
|
89
|
+
<p>Contributions are welcome and appreciated! The source is available from:</p>
|
90
|
+
|
91
|
+
<pre>http://github.com/collectiveidea/tinder</pre>
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
95
|
+
</script>
|
96
|
+
<script type="text/javascript">
|
97
|
+
_uacct = "UA-194397-8";
|
98
|
+
urchinTracker();
|
99
|
+
</script>
|
100
|
+
</body>
|
101
|
+
</html>
|
@@ -0,0 +1,77 @@
|
|
1
|
+
body {
|
2
|
+
font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
|
3
|
+
font-size: 76%;
|
4
|
+
background: #2A2A2A;
|
5
|
+
margin: 0;
|
6
|
+
padding: 0;
|
7
|
+
}
|
8
|
+
|
9
|
+
#collectiveidea {
|
10
|
+
border-bottom: 1px solid #444;
|
11
|
+
}
|
12
|
+
|
13
|
+
a {
|
14
|
+
color: #2D5385;
|
15
|
+
}
|
16
|
+
|
17
|
+
#main {
|
18
|
+
background-color: #FFF;
|
19
|
+
width: 700px;
|
20
|
+
margin: 0 auto;
|
21
|
+
border: 5px #CCC;
|
22
|
+
border-left-style: solid;
|
23
|
+
border-right-style: solid;
|
24
|
+
padding: 0 1em;
|
25
|
+
}
|
26
|
+
|
27
|
+
#header {
|
28
|
+
position: relative;
|
29
|
+
border-bottom: 1px solid #999;
|
30
|
+
padding: 1em;
|
31
|
+
}
|
32
|
+
|
33
|
+
#header h1 {
|
34
|
+
margin: 0;
|
35
|
+
padding: 0;
|
36
|
+
color: #2D5385;
|
37
|
+
}
|
38
|
+
|
39
|
+
#header h1 a {
|
40
|
+
text-decoration: none;
|
41
|
+
}
|
42
|
+
|
43
|
+
#header p {
|
44
|
+
margin: 0;
|
45
|
+
padding: 0;
|
46
|
+
font-size: 0.8em;
|
47
|
+
color: #999;
|
48
|
+
}
|
49
|
+
|
50
|
+
#nav {
|
51
|
+
list-style: none;
|
52
|
+
position: absolute;
|
53
|
+
right: 0;
|
54
|
+
top: 0.6em;
|
55
|
+
}
|
56
|
+
#nav li {
|
57
|
+
display: inline;
|
58
|
+
padding: 0 0.5em;
|
59
|
+
}
|
60
|
+
|
61
|
+
#content {
|
62
|
+
padding: 1em 0;
|
63
|
+
}
|
64
|
+
|
65
|
+
dl {
|
66
|
+
background-color: #DDD;
|
67
|
+
padding: 1em;
|
68
|
+
border: 1px solid #CCC;
|
69
|
+
}
|
70
|
+
dl .pronunciation {
|
71
|
+
color: #C00;
|
72
|
+
}
|
73
|
+
dl .description {
|
74
|
+
text-transform: uppercase;
|
75
|
+
font-size: 0.8em;
|
76
|
+
font-family: fixed;
|
77
|
+
}
|
@@ -0,0 +1,225 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe "Preparing a campfire request" do
|
4
|
+
before do
|
5
|
+
@campfire = Tinder::Campfire.new("foobar")
|
6
|
+
@request = Net::HTTP::Get.new("does_not_matter")
|
7
|
+
end
|
8
|
+
|
9
|
+
def prepare_request
|
10
|
+
@campfire.send(:prepare_request, @request)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the request" do
|
14
|
+
prepare_request.should equal(@request)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set the cookie" do
|
18
|
+
@campfire.instance_variable_set("@cookie", "foobar")
|
19
|
+
prepare_request['Cookie'].should == 'foobar'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should set the user agent" do
|
23
|
+
prepare_request['User-Agent'].should =~ /^Tinder/
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# describe "Performing a campfire request" do
|
28
|
+
#
|
29
|
+
# before do
|
30
|
+
# @response = mock("response")
|
31
|
+
# Net::HTTP.any_instance.stubs(:request).returns(response)
|
32
|
+
# request = Net::HTTP::Get.new("does_not_matter")
|
33
|
+
# response.expects(:[]).with('set-cookie').and_return('foobar')
|
34
|
+
# @campfire.send(:perform_request) { request }
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# it "should set cookie" do
|
38
|
+
# @campfire.instance_variable_get("@cookie").should == 'foobar'
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# end
|
42
|
+
|
43
|
+
describe "Verifying a 200 response" do
|
44
|
+
|
45
|
+
before do
|
46
|
+
@campfire = Tinder::Campfire.new("foobar")
|
47
|
+
@response = mock("response")
|
48
|
+
@response.should_receive(:code).and_return(200)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should return true when expecting success" do
|
52
|
+
@campfire.send(:verify_response, @response, :success).should equal(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return false when expecting a redirect" do
|
56
|
+
@campfire.send(:verify_response, @response, :redirect).should equal(false)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return false when expecting a redirect to a specific path" do
|
60
|
+
@campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(false)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "Verifying a 302 response" do
|
66
|
+
|
67
|
+
before do
|
68
|
+
@campfire = Tinder::Campfire.new("foobar")
|
69
|
+
@response = mock("response")
|
70
|
+
@response.should_receive(:code).and_return(302)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return true when expecting redirect" do
|
74
|
+
@campfire.send(:verify_response, @response, :redirect).should equal(true)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return false when expecting success" do
|
78
|
+
@campfire.send(:verify_response, @response, :success).should equal(false)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return true when expecting a redirect to a specific path" do
|
82
|
+
@response.should_receive(:[]).with('location').and_return("/foobar")
|
83
|
+
@campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(true)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return false when redirecting to a different path than expected" do
|
87
|
+
@response.should_receive(:[]).with('location').and_return("/baz")
|
88
|
+
@campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(false)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "A failed login" do
|
94
|
+
|
95
|
+
before do
|
96
|
+
@campfire = Tinder::Campfire.new 'foobar'
|
97
|
+
@response = mock("response")
|
98
|
+
@campfire.should_receive(:post).and_return(@response)
|
99
|
+
@response.should_receive(:code).and_return("302")
|
100
|
+
@response.should_receive(:[]).with("location").and_return("/login")
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should raise an error" do
|
104
|
+
lambda do
|
105
|
+
@campfire.login "doesn't", "matter"
|
106
|
+
end.should raise_error(Tinder::Error)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not set logged in status" do
|
110
|
+
@campfire.login 'foo', 'bar' rescue
|
111
|
+
@campfire.logged_in?.should equal(false)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "Accessing a room with guest access" do
|
117
|
+
|
118
|
+
before do
|
119
|
+
@room_id = 123
|
120
|
+
@campfire = Tinder::Campfire.new 'foobar'
|
121
|
+
@response = mock("response")
|
122
|
+
@campfire.stub!(:post).and_return(@response)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return a room for the public room" do
|
126
|
+
@response.should_receive(:code).and_return(302)
|
127
|
+
@response.should_receive(:[]).with("location").and_return("/rooms/#{@room_id}")
|
128
|
+
|
129
|
+
room = @campfire.find_room_by_guest_hash "valid_hash", "John Doe"
|
130
|
+
room.should be_kind_of(Tinder::Room)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should raise an error if given an invalid room hash" do
|
134
|
+
@response.should_receive(:code).and_return(500)
|
135
|
+
|
136
|
+
room = @campfire.find_room_by_guest_hash "invalid_hash", "John Doe"
|
137
|
+
room.should be_nil
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "Accessing a room" do
|
143
|
+
|
144
|
+
before do
|
145
|
+
@request = mock("request")
|
146
|
+
@response = mock("response")
|
147
|
+
Net::HTTP.stub!(:new).and_return(@request)
|
148
|
+
@request.stub!(:use_ssl=)
|
149
|
+
@request.stub!(:request).and_return(@response)
|
150
|
+
@response.stub!(:[]).and_return(true)
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "when the room is full" do
|
154
|
+
|
155
|
+
before do
|
156
|
+
@html = File.read(File.dirname(__FILE__) + '/html/full_lobby.html')
|
157
|
+
@response.stub!(:body).and_return(@html)
|
158
|
+
@campfire = Tinder::Campfire.new 'foobar'
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should return a room" do
|
162
|
+
@campfire.rooms.should_not be_empty
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should find a room by name" do
|
166
|
+
@campfire.find_room_by_name("Just Fishin").class.should == Tinder::Room
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "when the room is not full" do
|
172
|
+
|
173
|
+
before do
|
174
|
+
@html = File.read(File.dirname(__FILE__) + '/html/normal_lobby.html')
|
175
|
+
@response.stub!(:body).and_return(@html)
|
176
|
+
@campfire = Tinder::Campfire.new 'foobar'
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should return a room" do
|
180
|
+
@campfire.rooms.should_not be_empty
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should find a room by name" do
|
184
|
+
@campfire.find_room_by_name("Just Fishin").class.should == Tinder::Room
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "Accessing a room's transcript" do
|
191
|
+
|
192
|
+
before do
|
193
|
+
@room = Tinder::Room.new nil, 42
|
194
|
+
@html = File.read(File.dirname(__FILE__) + '/html/transcript.html')
|
195
|
+
@response = mock("response")
|
196
|
+
@response.stub!(:body).and_return(@html)
|
197
|
+
@room.stub!(:get).with("room/42/transcript/2009/05/05").
|
198
|
+
and_return(@response)
|
199
|
+
require 'time'
|
200
|
+
@transcript = @room.transcript(Time.parse("2009-05-05"))
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should return some messages" do
|
204
|
+
@transcript.should_not be_empty
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "the first message" do
|
208
|
+
# This is a timestamp message
|
209
|
+
it "should include a timestamp" do
|
210
|
+
@transcript.first[:timestamp].should == Time.parse("2009-05-05 09:35")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "the second message" do
|
215
|
+
it "should include a timestamp" do
|
216
|
+
@transcript.second[:timestamp].should == Time.parse("2009-05-05 09:35")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "when entering the room" do
|
221
|
+
it "a transcript message should include the person who entered" do
|
222
|
+
@transcript.second[:person].should == "Marcel"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|