rscribd 1.0.3 → 1.0.4
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 +5 -0
- data/History.txt +5 -0
- data/Rakefile +20 -24
- data/VERSION +1 -0
- data/lib/scribddoc.rb +18 -11
- data/lib/scribdmultiparthack.rb +2 -2
- data/lib/scribduser.rb +5 -3
- data/spec/api_spec.rb +131 -0
- data/spec/document_spec.rb +557 -0
- data/spec/error_spec.rb +12 -0
- data/spec/resource_spec.rb +126 -0
- data/spec/rscribd_spec.rb +35 -0
- data/spec/user_spec.rb +195 -0
- metadata +30 -23
data/History.txt
CHANGED
data/Rakefile
CHANGED
@@ -1,29 +1,25 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'hoe'
|
3
2
|
require 'spec/rake/spectask'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "rscribd"
|
8
|
+
gemspec.summary = "Ruby client library for the Scribd API"
|
9
|
+
gemspec.description = "The official Ruby gem for the Scribd API. Scribd is a document-sharing website allowing people to upload and view documents online."
|
10
|
+
gemspec.email = "api@scribd.com"
|
11
|
+
gemspec.homepage = "http://www.scribd.com/developers"
|
12
|
+
gemspec.authors = [ "Tim Morgan", "Jared Friedman", "Mike Watts" ]
|
13
|
+
|
14
|
+
gemspec.add_dependency 'mime-types'
|
15
|
+
gemspec.add_development_dependency "rspec"
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
16
19
|
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
namespace :github do
|
25
|
-
desc "Prepare for GitHub gem packaging"
|
26
|
-
task :prepare do
|
27
|
-
`rake debug_gem > rscribd.gemspec`
|
28
|
-
end
|
29
|
-
end
|
21
|
+
desc "Verify gem specs"
|
22
|
+
Spec::Rake::SpecTask.new do |t|
|
23
|
+
t.spec_files = FileList['spec/*.rb']
|
24
|
+
t.spec_opts = [ '-cfs' ]
|
25
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.4
|
data/lib/scribddoc.rb
CHANGED
@@ -91,15 +91,16 @@ module Scribd
|
|
91
91
|
def save
|
92
92
|
if not created? and @attributes[:file].nil? then
|
93
93
|
raise "'file' attribute must be specified for new documents"
|
94
|
-
return false
|
95
94
|
end
|
96
95
|
|
97
96
|
if created? and @attributes[:file] and (@attributes[:owner].nil? or @attributes[:owner].session_key.nil?) then
|
98
97
|
raise PrivilegeError, "The current API user is not the owner of this document"
|
99
98
|
end
|
100
|
-
|
99
|
+
|
101
100
|
# Make a request form
|
101
|
+
response = nil
|
102
102
|
fields = @attributes.dup
|
103
|
+
fields[:session_key] = fields.delete(:owner).session_key if fields[:owner]
|
103
104
|
if file = @attributes[:file] then
|
104
105
|
fields.delete :file
|
105
106
|
is_file_object = file.is_a?(File)
|
@@ -110,12 +111,7 @@ module Scribd
|
|
110
111
|
fields[:doc_type] ||= ext
|
111
112
|
fields[:doc_type].downcase! if fields[:doc_type]
|
112
113
|
fields[:rev_id] = fields.delete(:doc_id)
|
113
|
-
|
114
|
-
fields[:session_key] = fields.delete(:owner).session_key if fields[:owner]
|
115
|
-
response = nil
|
116
|
-
|
117
|
-
if @attributes[:file] then
|
118
|
-
uri = nil
|
114
|
+
|
119
115
|
begin
|
120
116
|
uri = URI.parse @attributes[:file]
|
121
117
|
rescue URI::InvalidURIError
|
@@ -141,9 +137,9 @@ module Scribd
|
|
141
137
|
@created = true
|
142
138
|
end
|
143
139
|
|
140
|
+
fields.delete :access if fields[:file] # when uploading a doc, don't send access twice
|
144
141
|
fields.delete :file
|
145
142
|
fields.delete :type
|
146
|
-
fields.delete :access
|
147
143
|
fields.delete :conversion_status
|
148
144
|
|
149
145
|
changed_attributes = fields.dup # changed_attributes is what we will stick into @attributes once we update remotely
|
@@ -207,7 +203,7 @@ module Scribd
|
|
207
203
|
# this manner.
|
208
204
|
|
209
205
|
def self.find(scope, options={})
|
210
|
-
doc_id = scope
|
206
|
+
doc_id = scope.kind_of?(Integer) ? scope : nil
|
211
207
|
raise ArgumentError, "You must specify a query or document ID" unless options[:query] or doc_id
|
212
208
|
|
213
209
|
if doc_id then
|
@@ -247,7 +243,18 @@ module Scribd
|
|
247
243
|
response = API.instance.send_request('docs.getConversionStatus', :doc_id => self.id)
|
248
244
|
response.elements['/rsp/conversion_status'].text
|
249
245
|
end
|
250
|
-
|
246
|
+
|
247
|
+
# Returns the document read count. This is only retrieved from the server the first time it's queried.
|
248
|
+
# To force re-retrieval on subsequent calls include :force => true in the options parameter.
|
249
|
+
|
250
|
+
def reads(options = {})
|
251
|
+
if @reads.nil? || options[:force]
|
252
|
+
response = API.instance.send_request('docs.getStats', :doc_id => self.id)
|
253
|
+
@reads = response.elements['/rsp/reads'].text
|
254
|
+
end
|
255
|
+
@reads
|
256
|
+
end
|
257
|
+
|
251
258
|
# Deletes a document. Returns true if successful.
|
252
259
|
|
253
260
|
def destroy
|
data/lib/scribdmultiparthack.rb
CHANGED
@@ -12,14 +12,14 @@ module Net #:nodoc:all
|
|
12
12
|
boundary_token = [Array.new(8) {rand(256)}].join
|
13
13
|
self.content_type = "multipart/form-data; boundary=#{boundary_token}"
|
14
14
|
boundary_marker = "--#{boundary_token}\r\n"
|
15
|
-
self.body = param_hash.map
|
15
|
+
self.body = param_hash.map do |param_name, param_value|
|
16
16
|
boundary_marker + case param_value
|
17
17
|
when File
|
18
18
|
file_to_multipart(param_name, param_value)
|
19
19
|
else
|
20
20
|
text_to_multipart(param_name, param_value.to_s)
|
21
21
|
end
|
22
|
-
|
22
|
+
end.join('') + "--#{boundary_token}--\r\n"
|
23
23
|
end
|
24
24
|
|
25
25
|
protected
|
data/lib/scribduser.rb
CHANGED
@@ -56,7 +56,9 @@ module Scribd
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
# Returns a list of
|
59
|
+
# Returns a list of documents owned by this user. By default, the size of the returned
|
60
|
+
# list is capped at 1000. Use the :limit and :offset parameters to page through this
|
61
|
+
# user's documents, however :limit cannot be greater than 1000. This list is _not_
|
60
62
|
# backed by the server, so if you add or remove items from it, it will not
|
61
63
|
# make those changes server-side. This also has some tricky consequences
|
62
64
|
# when modifying a list of documents while iterating over it:
|
@@ -71,8 +73,8 @@ module Scribd
|
|
71
73
|
# additional attributes are documented online at
|
72
74
|
# http://www.scribd.com/publisher/api?method_name=docs.getSettings
|
73
75
|
|
74
|
-
def documents
|
75
|
-
response = API.instance.send_request('docs.getList',
|
76
|
+
def documents(options = {})
|
77
|
+
response = API.instance.send_request('docs.getList', options.merge(:session_key => @attributes[:session_key]))
|
76
78
|
documents = Array.new
|
77
79
|
response.elements['/rsp/resultset'].elements.each do |doc|
|
78
80
|
documents << Document.new(:xml => doc, :owner => self)
|
data/spec/api_spec.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
old_dir = Dir.getwd
|
2
|
+
Dir.chdir(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rscribd'
|
4
|
+
|
5
|
+
describe Scribd::API do
|
6
|
+
it "should be a singleton" do
|
7
|
+
Scribd::API.instance.should be_kind_of(Scribd::API)
|
8
|
+
lambda { Scribd::API.new }.should raise_error(NoMethodError)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "with the API key and secret in ENV" do
|
12
|
+
before :each do
|
13
|
+
ENV['SCRIBD_API_KEY'] = 'env key'
|
14
|
+
ENV['SCRIBD_API_SECRET'] = 'env sec'
|
15
|
+
@api = Scribd::API.send(:new)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should set the API key and secret accordingly" do
|
19
|
+
@api.key.should eql('env key')
|
20
|
+
@api.secret.should eql('env sec')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should favor local API key and secret settings" do
|
24
|
+
@api.key = 'test key'
|
25
|
+
@api.secret = 'test sec'
|
26
|
+
@api.key.should eql('test key')
|
27
|
+
@api.secret.should eql('test sec')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "freshly reset" do
|
32
|
+
before :each do
|
33
|
+
ENV['SCRIBD_API_KEY'] = nil
|
34
|
+
ENV['SCRIBD_API_SECRET'] = nil
|
35
|
+
# reset the singleton; total hack
|
36
|
+
@api = Scribd::API.send(:new)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should raise NotReadyError when send_request is called" do
|
40
|
+
lambda { @api.send_request('blah', {}) }.should raise_error(Scribd::NotReadyError)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "with a key and secret set" do
|
44
|
+
before :each do
|
45
|
+
@api.key = 'test key'
|
46
|
+
@api.secret = 'test sec'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have the correct API key and secret" do
|
50
|
+
@api.key.should eql('test key')
|
51
|
+
@api.secret.should eql('test sec')
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should raise ArgumentError if the method is empty" do
|
55
|
+
lambda { @api.send_request(nil, {}) }.should raise_error(ArgumentError)
|
56
|
+
lambda { @api.send_request('', {}) }.should raise_error(ArgumentError)
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "with a mocked Net::HTTP" do
|
60
|
+
before :each do
|
61
|
+
@response = mock('Net::HTTP::Response @response')
|
62
|
+
@response.stub!(:body).and_return("<rsp stat='ok'/>")
|
63
|
+
|
64
|
+
@http = Net::HTTP.new('http://www.example.com', 80)
|
65
|
+
@http.stub!(:request).and_return(@response)
|
66
|
+
Net::HTTP.stub!(:new).and_return(@http)
|
67
|
+
|
68
|
+
@request = Net::HTTP::Post.new('/test')
|
69
|
+
Net::HTTP::Post.stub!(:new).and_return(@request)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should set a nice, long read timeout" do
|
73
|
+
@api.send_request('test', {})
|
74
|
+
@http.read_timeout.should >= 60
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should set the multipart parameters to the given fields" do
|
78
|
+
fields = { :field1 => 1, :field2 => 'hi' }
|
79
|
+
@api.send_request('test', fields)
|
80
|
+
body = @request.body
|
81
|
+
fields.each do |key, value|
|
82
|
+
serial_str = <<-EOF
|
83
|
+
Content-Disposition: form-data; name=#{key.to_s.inspect}
|
84
|
+
|
85
|
+
#{value.to_s}
|
86
|
+
EOF
|
87
|
+
body.should include(serial_str.gsub(/\n/, "\r\n"))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# it "should attempt to make the request 3 times" do
|
92
|
+
# @http.stub!(:request).and_raise Exception
|
93
|
+
# @http.should_receive(:request).exactly(3).times
|
94
|
+
# lambda { @api.send_request('test', {}) }.should raise_error
|
95
|
+
# end
|
96
|
+
|
97
|
+
it "should raise MalformedResponseError if the response doesn't have an rsp tag as its root" do
|
98
|
+
@response.stub!(:body).and_return("<invalid/>")
|
99
|
+
lambda { @api.send_request('test', {}) }.should raise_error(Scribd::MalformedResponseError)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should raise a ResponseError for error responses" do
|
103
|
+
@response.stub!(:body).and_return("<rsp stat='fail'><error code='123' message='testmsg' /></rsp>")
|
104
|
+
lambda { @api.send_request('testmeth', {}) }.should raise_error(Scribd::ResponseError) { |error|
|
105
|
+
error.code.should eql("123")
|
106
|
+
error.message.should eql('Method: testmeth Response: code=123 message=testmsg')
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return the REXML doc for successful responses" do
|
111
|
+
@response.stub!(:body).and_return("<rsp stat='ok'><element attr='val'><otherelem>val2</otherelem></element></rsp>")
|
112
|
+
@api.send_request('testmeth', {}).should be_kind_of(REXML::Document)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should not be asynchronous by default" do
|
119
|
+
Scribd::API.instance.asynchronous.should_not be_true
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should not be in debug mode by default" do
|
123
|
+
Scribd::API.instance.instance_variable_get(:@debug).should_not be_true
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should have a user by default" do
|
127
|
+
Scribd::API.instance.user.should_not be_nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
Dir.chdir old_dir
|
@@ -0,0 +1,557 @@
|
|
1
|
+
old_dir = Dir.getwd
|
2
|
+
Dir.chdir(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rscribd'
|
4
|
+
|
5
|
+
describe Scribd::Document do
|
6
|
+
before :each do
|
7
|
+
Scribd::API.instance.key = 'test key'
|
8
|
+
Scribd::API.instance.secret = 'test sec'
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "initialized from attributes" do
|
12
|
+
before :each do
|
13
|
+
@document = Scribd::Document.new(:access => 'private', :title => 'mytitle')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have its attributes set appropriately" do
|
17
|
+
@document.access.should eql('private')
|
18
|
+
@document.title.should eql('mytitle')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be unsaved" do
|
22
|
+
@document.should_not be_saved
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be uncreated" do
|
26
|
+
@document.should_not be_created
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "initialized from XML" do
|
31
|
+
before :each do
|
32
|
+
@owner = mock('Scribd::User @owner')
|
33
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<rsp stat='ok'><attr1>val1</attr1><attr2>val2</attr2></rsp>").root, :owner => @owner)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have its attributes set appropriately" do
|
37
|
+
@document.attr1.should eql('val1')
|
38
|
+
@document.attr2.should eql('val2')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be saved" do
|
42
|
+
@document.should be_saved
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be created" do
|
46
|
+
@document.should be_created
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have its owner set appropriately" do
|
50
|
+
@document.owner.should eql(@owner)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "not yet created" do
|
55
|
+
before :each do
|
56
|
+
@document = Scribd::Document.new(:access => 'private', :title => 'mytitle')
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should raise an exception if saved without a file" do
|
60
|
+
lambda { @document.save }.should raise_error
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "created" do
|
65
|
+
before :each do
|
66
|
+
@http = mock('Net::HTTP @http')
|
67
|
+
@http.stub! :read_timeout=
|
68
|
+
@response = mock('Net::HTTPResponse @response')
|
69
|
+
@response.stub!(:body).and_return "<rsp stat='ok'></rsp>"
|
70
|
+
@http.stub!(:request).and_return(@response)
|
71
|
+
Net::HTTP.stub!(:new).and_return(@http)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should not raise an exception if saved" do
|
75
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<rsp stat='ok'><attr1>val1</attr1><attr2>val2</attr2></rsp>").root)
|
76
|
+
lambda { @document.save }.should_not raise_error
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "that we own" do
|
80
|
+
before :each do
|
81
|
+
@owner = mock('Scribd::User @owner')
|
82
|
+
@owner.stub!(:session_key).and_return('test session key')
|
83
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<rsp stat='ok'><attr1>val1</attr1><attr2>val2</attr2></rsp>").root, :owner => @owner)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "that we don't own" do
|
88
|
+
before :each do
|
89
|
+
@owner = mock('Scribd::User @owner')
|
90
|
+
@owner.stub!(:session_key)
|
91
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<rsp stat='ok'><attr1>val1</attr1><attr2>val2</attr2></rsp>").root, :owner => @owner)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should raise PrivilegeError when trying to change the file" do
|
95
|
+
@document.file = 'sample/test.txt'
|
96
|
+
lambda { @document.save }.should raise_error(Scribd::PrivilegeError)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "with no owner" do
|
101
|
+
before :each do
|
102
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<rsp stat='ok'><attr1>val1</attr1><attr2>val2</attr2></rsp>").root)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should raise PrivilegeError when trying to change the file" do
|
106
|
+
@document.file = 'sample/test.txt'
|
107
|
+
lambda { @document.save }.should raise_error(Scribd::PrivilegeError)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "to be uploaded from file" do
|
113
|
+
before :each do
|
114
|
+
@document = Scribd::Document.new(:file => 'sample/test.txt')
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should make a call to docs.upload" do
|
118
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:file => an_instance_of(File)))
|
119
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
120
|
+
@document.save
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "to be uploaded from URL" do
|
125
|
+
before :each do
|
126
|
+
@document = Scribd::Document.new(:file => 'http://www.example.com/file.txt')
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should make a call to docs.uploadFromUrl" do
|
130
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.uploadFromUrl', hash_including(:url => 'http://www.example.com/file.txt'))
|
131
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
132
|
+
@document.save
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should recognize HTTPS URLs" do
|
136
|
+
@document.file.gsub!(/http/, 'https')
|
137
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.uploadFromUrl', hash_including(:url => 'https://www.example.com/file.txt'))
|
138
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
139
|
+
@document.save
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should recognize FTP URLs" do
|
143
|
+
@document.file.gsub!(/http/, 'ftp')
|
144
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.uploadFromUrl', hash_including(:url => 'ftp://www.example.com/file.txt'))
|
145
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
146
|
+
@document.save
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "to be uploaded" do
|
151
|
+
describe "given a file path" do
|
152
|
+
before :each do
|
153
|
+
@document = Scribd::Document.new(:file => 'sample/test.txt')
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should set the doc_type attribute to the file's extension" do
|
157
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'txt'))
|
158
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
159
|
+
@document.save
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should prefer a doc_type set in the type attribute" do
|
163
|
+
@document.type = 'pdf'
|
164
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'pdf'))
|
165
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
166
|
+
@document.save
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should not raise an exception if the document does not have an extension" do
|
170
|
+
@document.file = 'Rakefile'
|
171
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => nil))
|
172
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
173
|
+
lambda { @document.save }.should_not raise_error
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should downcase filename extensions" do
|
177
|
+
@document.file = 'sample/test.TXT'
|
178
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'txt'))
|
179
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
180
|
+
lambda { @document.save }.should_not raise_error
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should downcase attributed file extensions" do
|
184
|
+
@document.type = 'PDF'
|
185
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'pdf'))
|
186
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
187
|
+
@document.save
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "given a file object" do
|
192
|
+
before :each do
|
193
|
+
@document = Scribd::Document.new(:file => File.new('sample/test.txt'))
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should set the doc_type attribute to the file's extension" do
|
197
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'txt'))
|
198
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
199
|
+
@document.save
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should prefer a doc_type set in the type attribute" do
|
203
|
+
@document.type = 'pdf'
|
204
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'pdf'))
|
205
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
206
|
+
@document.save
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should not raise an exception if the document does not have an extension" do
|
210
|
+
@document.file = File.open('Rakefile')
|
211
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => nil))
|
212
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
213
|
+
lambda { @document.save }.should_not raise_error
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should downcase filename extensions" do
|
217
|
+
@document.file = File.open('sample/test.TXT')
|
218
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'txt'))
|
219
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
220
|
+
lambda { @document.save }.should_not raise_error
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should downcase attributed file extensions" do
|
224
|
+
@document.type = 'PDF'
|
225
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:doc_type => 'pdf'))
|
226
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
227
|
+
@document.save
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "given a file to upload" do
|
232
|
+
before :each do
|
233
|
+
@document = Scribd::Document.new(:file => 'sample/test.txt')
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should set the rev_id field to the doc_id attribute" do
|
237
|
+
@document.doc_id = 123
|
238
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:rev_id => 123))
|
239
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
240
|
+
@document.save
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should set the access field to the access attribute" do
|
244
|
+
@document.access = 'private'
|
245
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:access => 'private'))
|
246
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
247
|
+
@document.save
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should set the session_key field to the owner's session key" do
|
251
|
+
owner = mock('Scribd::User owner')
|
252
|
+
owner.stub!(:session_key).and_return('his key')
|
253
|
+
@document.owner = owner
|
254
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:session_key => 'his key'))
|
255
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
256
|
+
@document.save
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should pass through any other attributes to the docs.upload call" do
|
260
|
+
@document.hello = 'there'
|
261
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', hash_including(:hello => 'there'))
|
262
|
+
Scribd::API.instance.should_receive(:send_request).any_number_of_times
|
263
|
+
@document.save
|
264
|
+
end
|
265
|
+
|
266
|
+
describe "successfully" do
|
267
|
+
before :each do
|
268
|
+
@document.stub!(:id).and_return(3)
|
269
|
+
@xml = REXML::Document.new("<rsp stat='ok'><access_key>abc123</access_key></rsp>")
|
270
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.upload', an_instance_of(Hash)).and_return(@xml)
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "without testing changeSettings" do
|
274
|
+
before :each do
|
275
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.changeSettings', an_instance_of(Hash))
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should load attributes from the response" do
|
279
|
+
@document.save
|
280
|
+
@document.access_key.should eql('abc123')
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should set created to true" do
|
284
|
+
@document.save
|
285
|
+
@document.should be_created
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should set saved to true" do
|
289
|
+
@document.save
|
290
|
+
@document.should be_saved
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should return true" do
|
294
|
+
@document.save.should be_true
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should not send the file, type, or access parameters to the changeSettings call" do
|
299
|
+
@document.type = 'pdf'
|
300
|
+
@document.access = 'private'
|
301
|
+
Scribd::API.instance.should_not_receive(:send_request).with('docs.changeSettings', hash_including(:file => 'sample/text.txt'))
|
302
|
+
Scribd::API.instance.should_not_receive(:send_request).with('docs.changeSettings', hash_including(:type => 'pdf'))
|
303
|
+
Scribd::API.instance.should_not_receive(:send_request).with('docs.changeSettings', hash_including(:access => 'private'))
|
304
|
+
@document.save
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should pass all other attributes to the changeSettings call" do
|
308
|
+
@document.attr1 = 'val1'
|
309
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.changeSettings', hash_including(:attr1 => 'val1'))
|
310
|
+
@document.save
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should pass the owner's session key to changeSettings" do
|
314
|
+
owner = mock('Scribd::User owner')
|
315
|
+
owner.stub!(:session_key).and_return('his key')
|
316
|
+
@document.owner = owner
|
317
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.changeSettings', hash_including(:session_key => 'his key'))
|
318
|
+
@document.save
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should pass the document's ID to changeSettings" do
|
322
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.changeSettings', hash_including(:doc_ids => 3))
|
323
|
+
@document.save
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
describe ".update_all" do
|
330
|
+
before :each do
|
331
|
+
@owner1 = mock('Scribd::User @owner1')
|
332
|
+
@owner1.stub!(:session_key).and_return 'session1'
|
333
|
+
@docs = [
|
334
|
+
Scribd::Document.new(:owner => @owner1, :doc_id => 1),
|
335
|
+
Scribd::Document.new(:owner => @owner1, :doc_id => 2)
|
336
|
+
]
|
337
|
+
end
|
338
|
+
|
339
|
+
it "should raise ArgumentError if an array of docs is not provided" do
|
340
|
+
lambda { Scribd::Document.update_all 'string', {} }.should raise_error(ArgumentError)
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should raise ArgumentError unless all array elements are Scribd::Documents" do
|
344
|
+
@docs << 'string'
|
345
|
+
lambda { Scribd::Document.update_all @docs, {} }.should raise_error(ArgumentError)
|
346
|
+
end
|
347
|
+
|
348
|
+
it "should raise ArgumentError unless all documents have session keys" do
|
349
|
+
@docs << Scribd::Document.new
|
350
|
+
lambda { Scribd::Document.update_all @docs, {} }.should raise_error(ArgumentError)
|
351
|
+
end
|
352
|
+
|
353
|
+
it "should raise ArgumentError unless options is a hash" do
|
354
|
+
lambda { Scribd::Document.update_all @docs, 'string' }.should raise_error(ArgumentError)
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should call changeSettings once for each session key" do
|
358
|
+
@owner2 = mock('Scribd::User @owner2')
|
359
|
+
@owner2.stub!(:session_key).and_return 'session2'
|
360
|
+
@docs << Scribd::Document.new(:owner => @owner2, :doc_id => 3)
|
361
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.changeSettings', hash_including(:session_key => 'session1'))
|
362
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.changeSettings', hash_including(:session_key => 'session2'))
|
363
|
+
Scribd::Document.update_all @docs, { :access => 'private' }
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should set the doc_ids field to a comma-delimited list of document IDs" do
|
367
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.changeSettings', hash_including(:doc_ids => '1,2'))
|
368
|
+
Scribd::Document.update_all @docs, { :access => 'private' }
|
369
|
+
end
|
370
|
+
|
371
|
+
it "should pass all options to the changeSettings call" do
|
372
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.changeSettings', hash_including(:access => 'private', :bogus => 'test'))
|
373
|
+
Scribd::Document.update_all @docs, { :access => 'private', :bogus => 'test' }
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
describe ".find" do
|
378
|
+
it "should raise an ArgumentError if an invalid doc ID is provided" do
|
379
|
+
lambda { Scribd::Document.find('oh hai') }.should raise_error(ArgumentError)
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should raise an ArgumentError if a query is not provided for scoped lookups" do
|
383
|
+
lambda { Scribd::Document.find(:all, :title => 'hi') }.should raise_error(ArgumentError)
|
384
|
+
end
|
385
|
+
|
386
|
+
describe "by ID" do
|
387
|
+
before :each do
|
388
|
+
@xml = REXML::Document.new("<rsp stat='ok'><access_key>abc123</access_key></rsp>")
|
389
|
+
end
|
390
|
+
|
391
|
+
it "should call getSettings with the doc ID" do
|
392
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getSettings', hash_including(:doc_id => 123)).and_return(@xml)
|
393
|
+
Scribd::Document.find 123
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should pass other options to the getSettings call" do
|
397
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getSettings', hash_including(:arg => 'val')).and_return(@xml)
|
398
|
+
Scribd::Document.find 123, :arg => 'val'
|
399
|
+
end
|
400
|
+
|
401
|
+
it "should return a Document created from the resulting XML" do
|
402
|
+
Scribd::API.instance.stub!(:send_request).and_return(@xml)
|
403
|
+
doc = Scribd::Document.find(123)
|
404
|
+
doc.should be_kind_of(Scribd::Document)
|
405
|
+
doc.access_key.should eql('abc123')
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
describe "by query" do
|
410
|
+
before :each do
|
411
|
+
@xml = REXML::Document.new("<rsp stat='ok'><result_set><result><access_key>abc123</access_key></result><result><access_key>abc321</access_key></result></result_set></rsp>")
|
412
|
+
end
|
413
|
+
|
414
|
+
it "should set the scope field according to the parameter" do
|
415
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.search', hash_including(:scope => 'all')).and_return(@xml)
|
416
|
+
Scribd::Document.find(:all, :query => 'test')
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should return an ordered array of Document results" do
|
420
|
+
Scribd::API.instance.stub!(:send_request).and_return(@xml)
|
421
|
+
docs = Scribd::Document.find(:all, :query => 'test')
|
422
|
+
docs.should have(2).items
|
423
|
+
docs.first.access_key.should eql('abc123')
|
424
|
+
docs.last.access_key.should eql('abc321')
|
425
|
+
end
|
426
|
+
|
427
|
+
it "should set the scope to 'all' and return the first result if :first is provided" do
|
428
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.search', hash_including(:scope => 'all')).and_return(@xml)
|
429
|
+
docs = Scribd::Document.find(:first, :query => 'test')
|
430
|
+
docs.should be_kind_of(Scribd::Document)
|
431
|
+
docs.access_key.should eql('abc123')
|
432
|
+
end
|
433
|
+
|
434
|
+
it "should set the num_results field to the limit option" do
|
435
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.search', hash_including(:num_results => 10)).and_return(@xml)
|
436
|
+
docs = Scribd::Document.find(:all, :query => 'test', :limit => 10)
|
437
|
+
end
|
438
|
+
|
439
|
+
it "should set the num_start field to the offset option" do
|
440
|
+
Scribd::API.instance.should_receive(:send_request).with('docs.search', hash_including(:num_start => 10)).and_return(@xml)
|
441
|
+
docs = Scribd::Document.find(:all, :query => 'test', :offset => 10)
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
it "should have an upload synonym for the create method"
|
447
|
+
|
448
|
+
describe ".conversion_status" do
|
449
|
+
before :each do
|
450
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<doc_id type='integer'>123</doc_id>"))
|
451
|
+
@xml = REXML::Document.new("<rsp stat='ok'><conversion_status>EXAMPLE</conversion_status></rsp>")
|
452
|
+
end
|
453
|
+
|
454
|
+
it "should call getConversionStatus with the correct doc_id" do
|
455
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getConversionStatus', :doc_id => 123).and_return(@xml)
|
456
|
+
@document.conversion_status
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should return the conversion status" do
|
460
|
+
Scribd::API.instance.stub!(:send_request).and_return(@xml)
|
461
|
+
@document.conversion_status.should eql('EXAMPLE')
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
describe ".reads" do
|
466
|
+
before :each do
|
467
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<doc_id type='integer'>123</doc_id>"))
|
468
|
+
@xml = REXML::Document.new("<rsp stat='ok'><reads>12321</reads></rsp>")
|
469
|
+
end
|
470
|
+
|
471
|
+
it "should call getStats with the correct doc_id" do
|
472
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getStats', :doc_id => 123).and_return(@xml)
|
473
|
+
@document.reads
|
474
|
+
end
|
475
|
+
|
476
|
+
it "should return the read count" do
|
477
|
+
Scribd::API.instance.stub!(:send_request).and_return(@xml)
|
478
|
+
@document.reads.should eql('12321')
|
479
|
+
end
|
480
|
+
|
481
|
+
it "should call getStats only once when read call made more than once" do
|
482
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getStats', :doc_id => 123).and_return(@xml)
|
483
|
+
@document.reads
|
484
|
+
@document.reads
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should call getStats everytime when read call made with :force => true" do
|
488
|
+
Scribd::API.instance.should_receive(:send_request).twice.with('docs.getStats', :doc_id => 123).and_return(@xml)
|
489
|
+
@document.reads
|
490
|
+
@document.reads(:force => true)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
describe ".destroy" do
|
495
|
+
before :each do
|
496
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<doc_id type='integer'>123</doc_id>"))
|
497
|
+
@success = REXML::Document.new("<rsp stat='ok' />")
|
498
|
+
@fail = REXML::Document.new("<rsp stat='fail' />")
|
499
|
+
end
|
500
|
+
|
501
|
+
it "should call delete with the correct doc_id" do
|
502
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.delete', :doc_id => 123).and_return(@success)
|
503
|
+
@document.destroy
|
504
|
+
end
|
505
|
+
|
506
|
+
it "should return true if successful" do
|
507
|
+
Scribd::API.instance.stub!(:send_request).and_return(@success)
|
508
|
+
@document.destroy.should be_true
|
509
|
+
end
|
510
|
+
|
511
|
+
it "should return false if unsuccessful" do
|
512
|
+
Scribd::API.instance.stub!(:send_request).and_return(@fail)
|
513
|
+
@document.destroy.should be_false
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
it "should have an id attribute that aliases doc_id" do
|
518
|
+
document = Scribd::Document.new(:xml => REXML::Document.new("<doc_id type='integer'>123</doc_id>"))
|
519
|
+
document.id.should eql(123)
|
520
|
+
end
|
521
|
+
|
522
|
+
describe ".owner=" do
|
523
|
+
it "should raise NotImplementedError for saved docs" do
|
524
|
+
document = Scribd::Document.new(:xml => REXML::Document.new("<doc_id type='integer'>123</doc_id>"))
|
525
|
+
lambda { document.owner = Scribd::User.new }.should raise_error(NotImplementedError)
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
describe ".download_url" do
|
530
|
+
before :each do
|
531
|
+
@document = Scribd::Document.new(:xml => REXML::Document.new("<doc_id type='integer'>123</doc_id>"))
|
532
|
+
@xml = REXML::Document.new("<rsp stat='ok'><download_link><![CDATA[http://www.example.com/doc.pdf]]></download_link></rsp>")
|
533
|
+
end
|
534
|
+
|
535
|
+
it "should call docs.getDownloadUrl with the correct doc_id" do
|
536
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getDownloadUrl', hash_including(:doc_id => 123)).and_return(@xml)
|
537
|
+
@document.download_url
|
538
|
+
end
|
539
|
+
|
540
|
+
it "should default to the original file format" do
|
541
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getDownloadUrl', hash_including(:doc_type => 'original')).and_return(@xml)
|
542
|
+
@document.download_url
|
543
|
+
end
|
544
|
+
|
545
|
+
it "should allow custom file formats" do
|
546
|
+
Scribd::API.instance.should_receive(:send_request).once.with('docs.getDownloadUrl', hash_including(:doc_type => 'pdf')).and_return(@xml)
|
547
|
+
@document.download_url('pdf')
|
548
|
+
end
|
549
|
+
|
550
|
+
it "should return the download link" do
|
551
|
+
Scribd::API.instance.stub!(:send_request).and_return(@xml)
|
552
|
+
@document.download_url.should eql("http://www.example.com/doc.pdf")
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
Dir.chdir old_dir
|