desmos 0.1.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/.rvmrc +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/autotest/discover.rb +3 -0
- data/desmos.gemspec +91 -0
- data/lib/desmos.rb +19 -0
- data/lib/desmos/configuration.rb +66 -0
- data/lib/desmos/debug_mode.rb +9 -0
- data/lib/desmos/errors.rb +10 -0
- data/lib/desmos/request_support.rb +44 -0
- data/lib/desmos/student.rb +10 -0
- data/lib/desmos/tutor.rb +10 -0
- data/lib/desmos/user.rb +34 -0
- data/lib/desmos/utils.rb +64 -0
- data/lib/desmos/whiteboard.rb +96 -0
- data/spec/desmos/configuration_spec.rb +105 -0
- data/spec/desmos/request_support_spec.rb +99 -0
- data/spec/desmos/student_spec.rb +38 -0
- data/spec/desmos/tutor_spec.rb +38 -0
- data/spec/desmos/user_spec.rb +38 -0
- data/spec/desmos/utils_spec.rb +20 -0
- data/spec/desmos/whiteboard_spec.rb +203 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/configure.rb +9 -0
- metadata +226 -0
data/lib/desmos/utils.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Desmos
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
# Taken from Rack::Utils, 1.2.1 to remove Rack dependency.
|
5
|
+
def escape(s)
|
6
|
+
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/u) {
|
7
|
+
'%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
|
8
|
+
}.tr(' ', '+')
|
9
|
+
end
|
10
|
+
module_function :escape
|
11
|
+
|
12
|
+
# Params are NOT escaped.
|
13
|
+
def traverse_params_hash(hash, result = nil, current_key = nil)
|
14
|
+
result ||= { :files => [], :params => [] }
|
15
|
+
|
16
|
+
hash.keys.sort { |a, b| a.to_s <=> b.to_s }.collect do |key|
|
17
|
+
new_key = (current_key ? "#{current_key}[#{key}]" : key).to_s
|
18
|
+
case hash[key]
|
19
|
+
when Hash
|
20
|
+
traverse_params_hash(hash[key], result, new_key)
|
21
|
+
when Array
|
22
|
+
array_key = "#{new_key}[]"
|
23
|
+
hash[key].each do |v|
|
24
|
+
result[:params] << [array_key, v.to_s]
|
25
|
+
end
|
26
|
+
when File
|
27
|
+
filename = File.basename(hash[key].path)
|
28
|
+
types = MIME::Types.type_for(filename)
|
29
|
+
result[:files] << [
|
30
|
+
new_key,
|
31
|
+
filename,
|
32
|
+
types.empty? ? 'application/octet-stream' : types[0].to_s,
|
33
|
+
File.expand_path(hash[key].path)
|
34
|
+
]
|
35
|
+
else
|
36
|
+
result[:params] << [new_key, hash[key].to_s]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
result
|
40
|
+
end
|
41
|
+
module_function :traverse_params_hash
|
42
|
+
|
43
|
+
def traversal_to_param_string(traversal, escape = true)
|
44
|
+
traversal[:params].collect { |param|
|
45
|
+
"#{Desmos::Utils.escape(param[0])}=#{Desmos::Utils.escape(param[1])}"
|
46
|
+
}.join('&')
|
47
|
+
end
|
48
|
+
module_function :traversal_to_param_string
|
49
|
+
|
50
|
+
# Return the bytesize of String; uses String#size under Ruby 1.8 and
|
51
|
+
# String#bytesize under 1.9.
|
52
|
+
if ''.respond_to?(:bytesize)
|
53
|
+
def bytesize(string)
|
54
|
+
string.bytesize
|
55
|
+
end
|
56
|
+
else
|
57
|
+
def bytesize(string)
|
58
|
+
string.size
|
59
|
+
end
|
60
|
+
end
|
61
|
+
module_function :bytesize
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Desmos
|
2
|
+
class Whiteboard
|
3
|
+
include RequestSupport
|
4
|
+
attr_accessor :hash, :title, :tutor, :students
|
5
|
+
|
6
|
+
def self.find(hash)
|
7
|
+
new(:hash => hash).get
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.create(options = {})
|
11
|
+
new(options).save
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@hash = options[:hash] # optional: The API will generate this if not provided. Must be unique if provided.
|
16
|
+
@title = options[:title] # optional
|
17
|
+
|
18
|
+
# optional: Should be a Desmos::Tutor object
|
19
|
+
if options[:tutor] && !(Tutor === options[:tutor])
|
20
|
+
raise ArgumentError, ':tutor option must be either of type Desmos::Tutor or NilClass'
|
21
|
+
end
|
22
|
+
@tutor = options[:tutor]
|
23
|
+
|
24
|
+
# optional: Should be an Array of Desmos::Student objects
|
25
|
+
if options[:students] && (!options[:students].respond_to?(:all?) || !options[:students].all? { |option| Desmos::Student === option })
|
26
|
+
raise ArgumentError, ':students option must be either an Array containing object of type Desmos::Student or NilClass'
|
27
|
+
end
|
28
|
+
@students = options[:students] || []
|
29
|
+
end
|
30
|
+
|
31
|
+
def save
|
32
|
+
parsed_response = request!(:whiteboard, :create, request_options)
|
33
|
+
if parsed_response.fetch(:success) == 'false'
|
34
|
+
raise RequestError, parsed_response[:error_message] unless parsed_response[:error_message] == 'whiteboard already exists'
|
35
|
+
else
|
36
|
+
self.hash = parsed_response.fetch(:hash)
|
37
|
+
end
|
38
|
+
add_tutor
|
39
|
+
add_students
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_tutor
|
44
|
+
if tutor
|
45
|
+
parsed_response = request!(:whiteboard, :add_user, tutor.request_options.merge(:whiteboard_hash => hash))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_students
|
50
|
+
unless students.empty?
|
51
|
+
students.each do |student|
|
52
|
+
add_student(student)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_student(student)
|
58
|
+
parsed_response = request!(:whiteboard, :add_user, student.request_options.merge(:whiteboard_hash => hash))
|
59
|
+
end
|
60
|
+
|
61
|
+
def get
|
62
|
+
parsed_response = request!(:whiteboard, :read, :whiteboard_hash => hash)
|
63
|
+
if parsed_response[:success] == 'false'
|
64
|
+
case parsed_response[:error_message]
|
65
|
+
when 'Whiteboard not found'
|
66
|
+
raise WhiteboardNotFound, "Whiteboard with HASH=#{hash} could not be found"
|
67
|
+
else
|
68
|
+
raise RequestError, parsed_response[:error_message]
|
69
|
+
end
|
70
|
+
else
|
71
|
+
build_from_hash(parsed_response)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def request_options
|
76
|
+
options = {}
|
77
|
+
options.merge!(:hash => hash) if hash
|
78
|
+
options.merge!(:title => title) if title
|
79
|
+
if tutor
|
80
|
+
options.merge!(:tutor_name => tutor.name) if tutor.name
|
81
|
+
options.merge!(:tutor_id => tutor.id) if tutor.id
|
82
|
+
options.merge!(:tutor_hash => tutor.hash) if tutor.hash
|
83
|
+
end
|
84
|
+
options
|
85
|
+
end
|
86
|
+
|
87
|
+
def build_from_hash(options)
|
88
|
+
self.hash = options[:hash]
|
89
|
+
self.title = options[:title]
|
90
|
+
self.tutor = Tutor.build_from_hash(options[:tutor])
|
91
|
+
self.students = options[:students].collect { |student_attributes| Student.new(student_attributes) }
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Desmos::Configuration, '.domain' do
|
4
|
+
|
5
|
+
it 'has a domain attribute, that when set will return the domain' do
|
6
|
+
Desmos::Configuration.should respond_to(:domain)
|
7
|
+
Desmos::Configuration.domain = 'https://example.com'
|
8
|
+
Desmos::Configuration.domain.should eql('https://example.com')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises a ConfigurationError if domain is called without having been set' do
|
12
|
+
Desmos::Configuration.domain = nil
|
13
|
+
lambda { Desmos::Configuration.domain }.should raise_error(Desmos::ConfigurationError, 'Desmos::Configuration.domain is a required configuration value.')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'adds https:// scheme if none is provided' do
|
17
|
+
Desmos::Configuration.domain = 'something.com'
|
18
|
+
Desmos::Configuration.domain.should eql('https://something.com')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'converts a regular http:// scheme to https:// if needed' do
|
22
|
+
Desmos::Configuration.domain = 'http://something.com'
|
23
|
+
Desmos::Configuration.domain.should eql('https://something.com')
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Desmos::Configuration, '.version' do
|
29
|
+
|
30
|
+
it 'has a version attribute, that when set will return the version' do
|
31
|
+
Desmos::Configuration.should respond_to(:version)
|
32
|
+
Desmos::Configuration.version = 'api_v1'
|
33
|
+
Desmos::Configuration.version.should eql('api_v1')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'raises a ConfigurationError if version is called without having been set' do
|
37
|
+
Desmos::Configuration.version = nil
|
38
|
+
lambda { Desmos::Configuration.version }.should raise_error(Desmos::ConfigurationError, 'Desmos::Configuration.version is a required configuration value.')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "prepends the version with 'api_v' if that part of the string does not exist" do
|
42
|
+
Desmos::Configuration.version = 1
|
43
|
+
Desmos::Configuration.version.should eql('api_v1')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "prepends the version with 'api_v' if that part of the string does not exist" do
|
47
|
+
Desmos::Configuration.version = '1'
|
48
|
+
Desmos::Configuration.version.should eql('api_v1')
|
49
|
+
end
|
50
|
+
|
51
|
+
it "parses out a number if there is one to use as the version" do
|
52
|
+
Desmos::Configuration.version = 'this really 4 should not work'
|
53
|
+
Desmos::Configuration.version.should eql('api_v4')
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe Desmos::Configuration, '.key' do
|
59
|
+
|
60
|
+
it 'has a key attributes, that when set will return the key' do
|
61
|
+
Desmos::Configuration.should respond_to(:key)
|
62
|
+
Desmos::Configuration.key = '133'
|
63
|
+
Desmos::Configuration.key.should eql('133')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises a ConfigurationError if key is called without having been set' do
|
67
|
+
Desmos::Configuration.key = nil
|
68
|
+
lambda { Desmos::Configuration.key }.should raise_error(Desmos::ConfigurationError, 'Desmos::Configuration.key is a required configuration value.')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'converts whatever is passed in into a String' do
|
72
|
+
Desmos::Configuration.key = 133
|
73
|
+
Desmos::Configuration.key.should eql('133')
|
74
|
+
|
75
|
+
Desmos::Configuration.key = true
|
76
|
+
Desmos::Configuration.key.should eql('true')
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe Desmos::Configuration, '.secret' do
|
82
|
+
|
83
|
+
it 'has a secret attribute, that when set will return the secret' do
|
84
|
+
Desmos::Configuration.should respond_to(:secret)
|
85
|
+
Desmos::Configuration.secret = 'abcde'
|
86
|
+
Desmos::Configuration.secret.should eql('abcde')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'raises a ConfigurationError is secret is called without having been set' do
|
90
|
+
Desmos::Configuration.secret = nil
|
91
|
+
lambda { Desmos::Configuration.secret }.should raise_error(Desmos::ConfigurationError, 'Desmos::Configuration.secret is a required configuration value.')
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe Desmos::Configuration, '.debug_mode' do
|
97
|
+
|
98
|
+
it 'has a debug_mode attriubute that defaults to false' do
|
99
|
+
Desmos::Configuration.should respond_to(:debug_mode)
|
100
|
+
Desmos::Configuration.debug_mode.should eql(false)
|
101
|
+
Desmos::Configuration.debug_mode = true
|
102
|
+
Desmos::Configuration.debug_mode.should eql(true)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Desmos::RequestSupport, '#request!' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
class_instance = Class.new
|
7
|
+
class_instance.send(:include, Desmos::RequestSupport)
|
8
|
+
@instance = class_instance.new
|
9
|
+
|
10
|
+
stub_request(:get, /https\:\/\/api\.tutortrove\.com\/api_v1\/whiteboard\/create/).
|
11
|
+
to_return(:status => 200, :body => "{\"success\": \"true\", \"title\": \"Test Session\", \"hash\": \"abcde\"}")
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'makes a request to the Desmos API with the given object, method, and options and returns a response parsed from JSON' do
|
15
|
+
response = @instance.request!(:whiteboard, :create, { :title => 'Test Session' })
|
16
|
+
response.should eql({
|
17
|
+
:success => 'true',
|
18
|
+
:hash => 'abcde',
|
19
|
+
:title => 'Test Session'
|
20
|
+
})
|
21
|
+
assert_requested :get, /https\:\/\/api\.tutortrove\.com\/api_v1\/whiteboard\/create/, :times => 1
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Desmos::RequestSupport, '#make_request' do
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
class_instance = Class.new
|
30
|
+
class_instance.send(:include, Desmos::RequestSupport)
|
31
|
+
@instance = class_instance.new
|
32
|
+
|
33
|
+
stub_request(:get, /https\:\/\/api\.tutortrove\.com\/api_v1\/whiteboard\/create/)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'makes a request to the Desmos API with the given object, method, and options and returns a response from Net::HTTP' do
|
37
|
+
response = @instance.make_request(:whiteboard, :create, { :title => 'Test Session' })
|
38
|
+
response.should be_instance_of(Net::HTTPOK)
|
39
|
+
assert_requested :get, /https\:\/\/api\.tutortrove\.com\/api_v1\/whiteboard\/create/, :times => 1
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe Desmos::RequestSupport, '#build_uri' do
|
45
|
+
|
46
|
+
before(:each) do
|
47
|
+
class_instance = Class.new
|
48
|
+
class_instance.send(:include, Desmos::RequestSupport)
|
49
|
+
@instance = class_instance.new
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'builds a uri for the Desmos API from the given object, method, and options and returns the URI object' do
|
53
|
+
uri = @instance.build_uri(:whiteboard, :create, { :title => 'Test Session' })
|
54
|
+
uri.should be_instance_of(URI::HTTPS)
|
55
|
+
uri.path.should eql('/api_v1/whiteboard/create')
|
56
|
+
uri.query.should eql('title=Test+Session')
|
57
|
+
uri.host.should eql(Desmos::Configuration.domain.split('://')[1])
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe Desmos::RequestSupport, '#build_http' do
|
63
|
+
|
64
|
+
before(:each) do
|
65
|
+
class_instance = Class.new
|
66
|
+
class_instance.send(:include, Desmos::RequestSupport)
|
67
|
+
@instance = class_instance.new
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'builds and returns a Net::HTTP instance setup for SSL' do
|
71
|
+
http = @instance.build_http(@instance.build_uri(:whiteboard, :create, { :title => 'Test Session' }))
|
72
|
+
http.should be_instance_of(Net::HTTP)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Desmos::RequestSupport, '#parse_response' do
|
78
|
+
|
79
|
+
before(:each) do
|
80
|
+
class_instance = Class.new
|
81
|
+
class_instance.send(:include, Desmos::RequestSupport)
|
82
|
+
@instance = class_instance.new
|
83
|
+
|
84
|
+
stub_request(:get, /https\:\/\/api\.tutortrove\.com\/api_v1\/whiteboard\/create/).
|
85
|
+
to_return(:status => 200, :body => "{\"success\": \"true\", \"title\": \"Test Session\", \"hash\": \"abcde\"}")
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'parses the JSON response string into a Hash' do
|
89
|
+
response = @instance.make_request(:whiteboard, :create, { :title => 'Test Session', :hash => 'abcde' })
|
90
|
+
parsed_response = @instance.parse_response(response)
|
91
|
+
parsed_response.should be_instance_of(Hash)
|
92
|
+
parsed_response.should eql({
|
93
|
+
:success => 'true',
|
94
|
+
:title => 'Test Session',
|
95
|
+
:hash => 'abcde'
|
96
|
+
})
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Desmos::Student, '.new' do
|
4
|
+
|
5
|
+
it 'sets the instance variables for the student' do
|
6
|
+
student = Desmos::Student.new(
|
7
|
+
:id => 1,
|
8
|
+
:hash => 'abcde',
|
9
|
+
:name => 'Test',
|
10
|
+
:last_name => 'Student',
|
11
|
+
:family_name => 'StudentName',
|
12
|
+
:skype => 'test_student',
|
13
|
+
:email => 'test_student@example.com'
|
14
|
+
)
|
15
|
+
student.id.should eql(1)
|
16
|
+
student.hash.should eql('abcde')
|
17
|
+
student.type.should eql('student')
|
18
|
+
student.name.should eql('Test')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'requires a name attribute' do
|
22
|
+
lambda { Desmos::Student.new(:id => 1) }.should raise_error(ArgumentError, ':name is a required attribute')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'requires an id attribute' do
|
26
|
+
lambda { Desmos::Student.new(:name => 'test') }.should raise_error(ArgumentError, ':id is a required attribute')
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Desmos::Student, '.build_from_hash' do
|
32
|
+
|
33
|
+
it 'returns a Desmos::Student object' do
|
34
|
+
student = Desmos::Student.build_from_hash(:id => 1, :name => 'test')
|
35
|
+
student.should be_instance_of(Desmos::Student)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Desmos::Tutor, '.new' do
|
4
|
+
|
5
|
+
it 'sets the instance variables for the tutor' do
|
6
|
+
tutor = Desmos::Tutor.new(
|
7
|
+
:id => 1,
|
8
|
+
:hash => 'abcde',
|
9
|
+
:name => 'Test',
|
10
|
+
:last_name => 'Tutor',
|
11
|
+
:family_name => 'TutorName',
|
12
|
+
:skype => 'test_tutor',
|
13
|
+
:email => 'test_tutor@example.com'
|
14
|
+
)
|
15
|
+
tutor.id.should eql(1)
|
16
|
+
tutor.hash.should eql('abcde')
|
17
|
+
tutor.type.should eql('tutor')
|
18
|
+
tutor.name.should eql('Test')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'requires a name attribute' do
|
22
|
+
lambda { Desmos::Tutor.new(:id => 1) }.should raise_error(ArgumentError, ':name is a required attribute')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'requires an id attribute' do
|
26
|
+
lambda { Desmos::Tutor.new(:name => 'test') }.should raise_error(ArgumentError, ':id is a required attribute')
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Desmos::Tutor, '.build_from_hash' do
|
32
|
+
|
33
|
+
it 'returns a Desmos::Tutor object' do
|
34
|
+
tutor = Desmos::Tutor.build_from_hash(:id => 1, :name => 'test')
|
35
|
+
tutor.should be_instance_of(Desmos::Tutor)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Desmos::User, '.new' do
|
4
|
+
|
5
|
+
it 'sets the instance variables for the tutor' do
|
6
|
+
user = Desmos::User.new(
|
7
|
+
:id => 1,
|
8
|
+
:hash => 'abcde',
|
9
|
+
:name => 'Test',
|
10
|
+
:last_name => 'User',
|
11
|
+
:family_name => 'UserName',
|
12
|
+
:skype => 'test_user',
|
13
|
+
:email => 'test_user@example.com'
|
14
|
+
)
|
15
|
+
user.id.should eql(1)
|
16
|
+
user.hash.should eql('abcde')
|
17
|
+
user.type.should eql('user')
|
18
|
+
user.name.should eql('Test')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'requires a name attribute' do
|
22
|
+
lambda { Desmos::User.new(:id => 1) }.should raise_error(ArgumentError, ':name is a required attribute')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'requires an id attribute' do
|
26
|
+
lambda { Desmos::User.new(:name => 'test') }.should raise_error(ArgumentError, ':id is a required attribute')
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Desmos::User, '.build_from_hash' do
|
32
|
+
|
33
|
+
it 'returns a Desmos::User object' do
|
34
|
+
user = Desmos::User.build_from_hash(:id => 1, :name => 'test')
|
35
|
+
user.should be_instance_of(Desmos::User)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|