Skip to content
Browse files

Add the ability to speak to a room.

  • Loading branch information...
1 parent 5c04a3a commit 64eda7cafc0672d0360ee1f4a1e82f1b39026a3a @Manfred committed Dec 16, 2009
Showing with 220 additions and 34 deletions.
  1. +31 −2 lib/broach/room.rb
  2. +28 −11 lib/broach/session.rb
  3. +2 −2 lib/broach/user.rb
  4. +2 −1 settings.yml.sample
  5. +27 −0 test/remote/room_test.rb
  6. +1 −1 test/start.rb
  7. +46 −0 test/unit/room_test.rb
  8. +83 −17 test/unit/session_test.rb
View
33 lib/broach/room.rb
@@ -1,15 +1,44 @@
module Broach
class Room
+ TYPE_MAP = {
+ :text => 'TextMessage',
+ :paste => 'PasteMessage',
+ :sound => 'SoundMessage'
+ }
+
include Broach::Attributes
+ # Send a message to the room
+ #
+ # ==== Options
+ #
+ # [+:type+]
+ # The type of message to send, this is :text by default for normal text messages.
+ # You can also use :paste and :sound. Valid sound messages are 'rimshot', 'crickets',
+ # or 'trombone'.
+ #
+ # ==== Examples
+ #
+ # room = Broach::Room.all.first
+ # room.speak("Let's review these figures.")
+ # room.speak("<code>$stderr.write('-')</code>", :type => :paste)
+ # room.speak("rimshot", :type => :sound)
+ def speak(content, options={})
+ options[:type] ||= :text
+ Broach.session.post("room/#{id}/speak", 'message' => {
+ 'type' => TYPE_MAP[options[:type]],
+ 'body' => content
+ })
+ end
+
def self.all
- Broach.session.fetch('rooms')['rooms'].map do |attributes|
+ Broach.session.get('rooms')['rooms'].map do |attributes|
Broach::Room.new(attributes)
end
end
def self.find(id)
- new(Broach.session.fetch("room/#{id.to_i}")['room'])
+ new(Broach.session.get("room/#{id.to_i}")['room'])
end
end
end
View
39 lib/broach/session.rb
@@ -15,27 +15,44 @@ def url_for(path)
["#{scheme}:/", "#{account}.campfirenow.com", path].join('/')
end
- def headers
- { 'Accept' => 'application/json', 'User-Agent' => 'Broach' }
+ def headers_for(method)
+ headers = { 'Accept' => 'application/json', 'User-Agent' => 'Broach' }
+ headers['Content-type'] = 'application/json' if method == :post
+ headers
end
def credentials
{ :username => token, :password => 'x' }
end
- def fetch(path)
- response = REST.get(url_for(path), headers, credentials)
-
+ def get(path)
+ response = REST.get(url_for(path), headers_for(:get), credentials)
if response.ok?
- return JSON.parse(response.body)
- elsif response.unauthorized?
- exception = Broach::AuthenticationError.new("Couldn't authenticate with the supplied credentials for the account `#{account}'")
+ return JSON.parse(response.body)
+ else
+ handle_response(:get, path, response)
+ end
+ end
+
+ def post(path, payload)
+ response = REST.post(url_for(path), JSON.dump(payload), headers_for(:post), credentials)
+ if response.created?
+ return JSON.parse(response.body)
+ else
+ handle_response(:post, path, response)
+ end
+ end
+
+ private
+
+ def handle_response(method, path, response)
+ exception = if response.unauthorized?
+ Broach::AuthenticationError.new("Couldn't authenticate with the supplied credentials for the account `#{account}'")
elsif response.forbidden?
- exception = Broach::AuthorizationError.new("Couldn't fetch the resource `#{path}' on the account `#{account}'")
+ Broach::AuthorizationError.new("Couldn't #{method.to_s.upcase} the resource `#{path}' on the account `#{account}'")
else
- exception = Broach::APIError.new("Response from the server was unexpected (#{response.status_code})")
+ Broach::APIError.new("Response from the server was unexpected (#{response.status_code})")
end
-
exception.response = response
raise exception
end
View
4 lib/broach/user.rb
@@ -3,11 +3,11 @@ class User
include Broach::Attributes
def self.me
- new(Broach.session.fetch('users/me')['user'])
+ new(Broach.session.get('users/me')['user'])
end
def self.find(id)
- new(Broach.session.fetch("users/#{id.to_i}")['user'])
+ new(Broach.session.get("users/#{id.to_i}")['user'])
end
end
end
View
3 settings.yml.sample
@@ -1,4 +1,5 @@
# Used for remote server testing, copy to settings.yml and complete with proper credentials
account: sample
token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-use_ssl: true
+use_ssl: true
+room: My test room
View
27 test/remote/room_test.rb
@@ -19,4 +19,31 @@
room.name.should.not == ''
end
end
+end
+
+describe "A Room" do
+ before do
+ Broach.settings = settings
+ @room = Broach::Room.all.find do |room|
+ room.name == Broach.session.room
+ end
+ end
+
+ it "should speak text" do
+ body = 'Should speak text'
+ message = @room.speak(body)
+ message['message']['body'].should == body
+ end
+
+ it "should speak paste" do
+ body = 'Should speak paste'
+ message = @room.speak(body, :type => :paste)
+ message['message']['body'].should == body
+ end
+
+ it "should speak sound" do
+ body = 'crickets'
+ message = @room.speak(body, :type => :sound)
+ message['message']['body'].should == body
+ end
end
View
2 test/start.rb
@@ -11,7 +11,7 @@ def settings
end
def mock_response(path, payload)
- Broach.session.stub!(:fetch).with(path).and_return(payload)
+ Broach.session.stub!(:get).with(path).and_return(payload)
end
end
View
46 test/unit/room_test.rb
@@ -1,5 +1,11 @@
require File.expand_path('../../start', __FILE__)
+module RoomSpecHelpers
+ def room(attributes)
+ Broach::Room.new(attributes)
+ end
+end
+
describe "Room" do
it "should initialize with attributes fetched from the server" do
attributes = {"name" => "Office", "created_at" => "2007/01/03 08:59:11 +0000", "updated_at" => "2009/12/13 19:53:03 +0000", "topic" => "Maybe IRB bug!!", "id" => 65667, "membership_limit" => 25 }
@@ -17,4 +23,44 @@
room = Broach::Room.find(65667)
room.id.should == 65667
end
+end
+
+describe "A Room, concerning messages" do
+ extend RoomSpecHelpers
+
+ before do
+ @room = room('id' => 12)
+ end
+
+ it "should speak text by default" do
+ Broach.session.should.receive(:post).with('room/12/speak', 'message' => {
+ 'type' => 'TextMessage',
+ 'body' => 'Howdy'
+ })
+ @room.speak('Howdy')
+ end
+
+ it "should speak text" do
+ Broach.session.should.receive(:post).with('room/12/speak', 'message' => {
+ 'type' => 'TextMessage',
+ 'body' => 'Howdy'
+ })
+ @room.speak('Howdy', :type => :text)
+ end
+
+ it "should speak paste" do
+ Broach.session.should.receive(:post).with('room/12/speak', 'message' => {
+ 'type' => 'PasteMessage',
+ 'body' => '<code></code>'
+ })
+ @room.speak('<code></code>', :type => :paste)
+ end
+
+ it "should speak sound" do
+ Broach.session.should.receive(:post).with('room/12/speak', 'message' => {
+ 'type' => 'SoundMessage',
+ 'body' => 'crickets'
+ })
+ @room.speak('crickets', :type => :sound)
+ end
end
View
100 test/unit/session_test.rb
@@ -4,6 +4,10 @@ module SessionSpecHelpers
def session(attributes)
Broach::Session.new(attributes)
end
+
+ def example_session
+ @session ||= session('account' => 'example', 'token' => 'xxx', 'use_ssl' => true)
+ end
end
describe "Session" do
@@ -37,47 +41,49 @@ def session(attributes)
end
end
-describe "A Session, when fetching resources" do
+describe "A Session, concerning HTTP" do
extend SessionSpecHelpers
- before do
- @session = session('account' => 'example', 'token' => 'xxx', 'use_ssl' => true)
- end
-
it "should use a JSON accept header" do
- @session.headers['Accept'].should == 'application/json'
+ [:get, :post].each do |method|
+ example_session.headers_for(method)['Accept'].should == 'application/json'
+ end
end
it "should pass the authentication token as username" do
- @session.credentials[:username].should == 'xxx'
+ example_session.credentials[:username].should == 'xxx'
end
it "should use a dummy password" do
- @session.credentials[:password].should == 'x'
+ example_session.credentials[:password].should == 'x'
end
+end
+
+describe "A Session, when fetching resources" do
+ extend SessionSpecHelpers
it "should use the URL, headers, and credentials when fetching a resource" do
REST.should.receive(:get).with(
- @session.url_for('rooms'),
- @session.headers,
- @session.credentials
+ example_session.url_for('rooms'),
+ example_session.headers_for(:get),
+ example_session.credentials
).and_return(
mock('Response', :ok? => true, :body => '{}')
)
- @session.fetch('rooms')
+ example_session.get('rooms')
end
it "should return the parsed body when the response was OK" do
payload = { 'room' => { 'id' => 12 } }
REST.stub!(:get).and_return(mock('Response', :ok? => true, :body => JSON.dump(payload)))
- @session.fetch('room/12').should == payload
+ example_session.get('room/12').should == payload
end
it "should raise an authentication error when the response was a 401" do
response = mock('Response', :ok? => false, :unauthorized? => true)
REST.stub!(:get).and_return(response)
begin
- @session.fetch('room/12')
+ example_session.get('room/12')
rescue Broach::AuthenticationError => error
error.response.should == response
error.message.should == "Couldn't authenticate with the supplied credentials for the account `example'"
@@ -88,18 +94,78 @@ def session(attributes)
response = mock('Response', :ok? => false, :unauthorized? => false, :forbidden? => true)
REST.stub!(:get).and_return(response)
begin
- @session.fetch('room/12')
+ example_session.get('room/12')
rescue Broach::AuthorizationError => error
error.response.should == response
- error.message.should == "Couldn't fetch the resource `room/12' on the account `example'"
+ error.message.should == "Couldn't GET the resource `room/12' on the account `example'"
end
end
it "should raise a general API error when the response was not expected" do
response = mock('Response', :ok? => false, :unauthorized? => false, :forbidden? => false, :status_code => 422)
REST.stub!(:get).and_return(response)
begin
- @session.fetch('room/12')
+ example_session.get('room/12')
+ rescue Broach::APIError => error
+ error.response.should == response
+ error.message.should == "Response from the server was unexpected (422)"
+ end
+ end
+end
+
+describe "A Session, when posting a resource" do
+ extend SessionSpecHelpers
+
+ it "should send a JSON content-type header" do
+ example_session.headers_for(:post)['Content-type'].should == 'application/json'
+ end
+
+ it "should use the URL, headers, and credentials when fetching a resource" do
+ payload = { 'message' => { 'body' => 'Heya', 'type' => 'TextMessage' } }
+ REST.should.receive(:post).with(
+ example_session.url_for('room/12/speak'),
+ JSON.dump(payload),
+ example_session.headers_for(:post),
+ example_session.credentials
+ ).and_return(
+ mock('Response', :created? => true, :body => '{}')
+ )
+ example_session.post('room/12/speak', payload)
+ end
+
+ it "should return the parsed body when the response was OK" do
+ payload = { 'message' => { 'id' => 12 } }
+ REST.stub!(:post).and_return(mock('Response', :created? => true, :body => JSON.dump(payload)))
+ example_session.post('room/12/speak', {}).should == payload
+ end
+
+ it "should raise an authentication error when the response was a 401" do
+ response = mock('Response', :created? => false, :unauthorized? => true)
+ REST.stub!(:post).and_return(response)
+ begin
+ example_session.post('room/12/speak', {})
+ rescue Broach::AuthenticationError => error
+ error.response.should == response
+ error.message.should == "Couldn't authenticate with the supplied credentials for the account `example'"
+ end
+ end
+
+ it "should raise an authorization error when the response was a 403" do
+ response = mock('Response', :created? => false, :unauthorized? => false, :forbidden? => true)
+ REST.stub!(:post).and_return(response)
+ begin
+ example_session.post('room/12/speak', {})
+ rescue Broach::AuthorizationError => error
+ error.response.should == response
+ error.message.should == "Couldn't POST the resource `room/12/speak' on the account `example'"
+ end
+ end
+
+ it "should raise a general API error when the response was not expected" do
+ response = mock('Response', :created? => false, :unauthorized? => false, :forbidden? => false, :status_code => 422)
+ REST.stub!(:post).and_return(response)
+ begin
+ example_session.post('room/12/speak', {})
rescue Broach::APIError => error
error.response.should == response
error.message.should == "Response from the server was unexpected (422)"

0 comments on commit 64eda7c

Please sign in to comment.
Something went wrong with that request. Please try again.