cloudpt-api 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ module Cloudpt
2
+ module API
3
+
4
+ module Util
5
+
6
+ class << self
7
+
8
+ def escape(string)
9
+ string.gsub(/([^ a-zA-Z0-9\.\\\-\/\_]+)/) do
10
+ '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
11
+ end.gsub(' ', '%20')
12
+ end
13
+
14
+ def query(data)
15
+ data.inject([]) { |memo, entry| memo.push(entry.join('=')); memo }.join('&')
16
+ end
17
+
18
+ def remove_double_slashes(path)
19
+ path.gsub('//', '/')
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ module Cloudpt
2
+ module API
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ app_key: # CONSUMER KEY
2
+ app_secret: # CONSUMER SECRET
3
+ token: # ACCESS TOKEN
4
+ secret: # ACCESS SECRET
5
+ mode: # 'sandbox' or 'cloudpt'
Binary file
@@ -0,0 +1,208 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe Cloudpt::API::Client do
5
+
6
+ before do
7
+ # pending
8
+ @client = Cloudpt::Spec.instance
9
+ end
10
+
11
+ describe "#initialize" do
12
+
13
+ it "has a handle to the connection" do
14
+ @client.connection.should be_an_instance_of(Cloudpt::API::Connection)
15
+ end
16
+
17
+ end
18
+
19
+ describe "#account" do
20
+
21
+ it "retrieves the account object" do
22
+ response = @client.account
23
+ response.should be_an_instance_of(Cloudpt::API::Object)
24
+ end
25
+
26
+ end
27
+
28
+ describe "#find" do
29
+
30
+ before do
31
+ @filename = "#{Cloudpt::Spec.test_dir}/spec-find-file-test-#{Time.now.to_i}.txt"
32
+ @file = @client.upload @filename, "spec file"
33
+
34
+ @dirname = "#{Cloudpt::Spec.test_dir}/spec-find-dir-test-#{Time.now.to_i}"
35
+ @dir = @client.mkdir @dirname
36
+ end
37
+
38
+ it "returns a single file" do
39
+ response = @client.find(@filename)
40
+ response.path.should == @file.path
41
+ response.should be_an_instance_of(Cloudpt::API::File)
42
+ end
43
+
44
+ it "returns a single directory" do
45
+ response = @client.find(@dirname)
46
+ response.path.should == @dir.path
47
+ response.should be_an_instance_of(Cloudpt::API::Dir)
48
+ end
49
+
50
+ end
51
+
52
+ describe "#list" do
53
+ it "lists root" do
54
+ result = @client.list("")
55
+ result.should be_an_instance_of(Array)
56
+ end
57
+ end
58
+
59
+ describe "#ls" do
60
+
61
+ it "returns an array of files and dirs" do
62
+ result = @client.ls
63
+ result.should be_an_instance_of(Array)
64
+ end
65
+
66
+ it "returns a single item array of if we ls a file" do
67
+ result = @client.ls(Cloudpt::Spec.test_dir)
68
+ first_file = result.detect { |f| f.class == Cloudpt::API::File }
69
+ result = @client.ls first_file.path
70
+ result.should be_an_instance_of(Array)
71
+ end
72
+
73
+ end
74
+
75
+ describe "#mkdir" do
76
+
77
+ it "returns an array of files and dirs" do
78
+ dirname = "#{Cloudpt::Spec.test_dir}/test-dir-#{Cloudpt::Spec.namespace}"
79
+ response = @client.mkdir dirname
80
+ response.path.should == dirname
81
+ response.should be_an_instance_of(Cloudpt::API::Dir)
82
+ end
83
+
84
+ it "creates dirs with tricky characters" do
85
+ dirname = "#{Cloudpt::Spec.test_dir}/test-dir |!@\#$%^&*{b}[].;'.,<>?: #{Cloudpt::Spec.namespace}"
86
+ response = @client.mkdir dirname
87
+ response.path.should == dirname.gsub(/[\\\:\?\*\<\>\"\|]+/, '')
88
+ response.should be_an_instance_of(Cloudpt::API::Dir)
89
+ end
90
+
91
+ it "creates dirs with utf8 characters" do
92
+ dirname = "#{Cloudpt::Spec.test_dir}/test-dir łółą #{Cloudpt::Spec.namespace}"
93
+ response = @client.mkdir dirname
94
+ response.path.should == dirname
95
+ response.should be_an_instance_of(Cloudpt::API::Dir)
96
+ end
97
+
98
+ end
99
+
100
+ describe "#upload" do
101
+
102
+ it "puts the file in Cloudpt" do
103
+ filename = "#{Cloudpt::Spec.test_dir}/test-#{Cloudpt::Spec.namespace}.txt"
104
+ response = @client.upload filename, "Some file"
105
+ response.path.should == filename
106
+ response.bytes.should == 9
107
+ end
108
+
109
+ it "uploads the file with tricky characters" do
110
+ filename = "#{Cloudpt::Spec.test_dir}/test ,|!@\#$%^&*{b}[].;'.,<>?:-#{Cloudpt::Spec.namespace}.txt"
111
+ response = @client.upload filename, "Some file"
112
+ response.path.should == filename
113
+ response.bytes.should == 9
114
+ end
115
+
116
+ it "uploads the file with utf8" do
117
+ filename = "#{Cloudpt::Spec.test_dir}/test łołąó-#{Cloudpt::Spec.namespace}.txt"
118
+ response = @client.upload filename, "Some file"
119
+ response.path.should == filename
120
+ response.bytes.should == 9
121
+ end
122
+ end
123
+
124
+ describe "#search" do
125
+
126
+ let(:term) { "searchable-test-#{Cloudpt::Spec.namespace}" }
127
+
128
+ before do
129
+ filename = "#{Cloudpt::Spec.test_dir}/searchable-test-#{Cloudpt::Spec.namespace}.txt"
130
+ @client.upload filename, "Some file"
131
+ end
132
+
133
+ after do
134
+ @response.size.should == 1
135
+ @response.first.class.should == Cloudpt::API::File
136
+ end
137
+
138
+ it "finds a file" do
139
+ @response = @client.search term, :path => "#{Cloudpt::Spec.test_dir}"
140
+ end
141
+
142
+ it "works if leading slash is present in path" do
143
+ @response = @client.search term, :path => "/#{Cloudpt::Spec.test_dir}"
144
+ end
145
+
146
+ end
147
+
148
+ describe "#copy_from_copy_ref" do
149
+
150
+ it "copies a file from a copy_ref" do
151
+ filename = "test/searchable-test-#{Cloudpt::Spec.namespace}.txt"
152
+ @client.upload filename, "Some file"
153
+ response = @client.search "searchable-test-#{Cloudpt::Spec.namespace}", :path => 'test'
154
+ ref = response.first.copy_ref['copy_ref']
155
+ @client.copy_from_copy_ref ref, "#{filename}.copied"
156
+ response = @client.search "searchable-test-#{Cloudpt::Spec.namespace}.txt.copied", :path => 'test'
157
+ response.size.should == 1
158
+ response.first.class.should == Cloudpt::API::File
159
+ end
160
+
161
+ end
162
+
163
+ describe "#download" do
164
+
165
+ it "downloads a file from Cloudpt" do
166
+ @client.upload "#{Cloudpt::Spec.test_dir}/test.txt", "Some file"
167
+ file = @client.download "#{Cloudpt::Spec.test_dir}/test.txt"
168
+ file.should == "Some file"
169
+ end
170
+
171
+ it "raises a 404 when a file is not found in Cloudpt" do
172
+ lambda {
173
+ @client.download "#{Cloudpt::Spec.test_dir}/no.txt"
174
+ }.should raise_error(Cloudpt::API::Error::NotFound)
175
+ end
176
+
177
+ end
178
+
179
+ describe "#delta" do
180
+ it "returns a cursor and list of files" do
181
+ filename = "#{Cloudpt::Spec.test_dir}/delta-test-#{Cloudpt::Spec.namespace}.txt"
182
+ @client.upload filename, 'Some file'
183
+ response = @client.delta
184
+ cursor, files = response.cursor, response.entries
185
+ cursor.should be_an_instance_of(String)
186
+ files.should be_an_instance_of(Array)
187
+ files.last.should be_an_instance_of(Cloudpt::API::File)
188
+ end
189
+
190
+ it "returns the files that have changed since the cursor was made" do
191
+ filename = "#{Cloudpt::Spec.test_dir}/delta-test-#{Cloudpt::Spec.namespace}.txt"
192
+ delete_filename = "#{Cloudpt::Spec.test_dir}/delta-test-delete-#{Cloudpt::Spec.namespace}.txt"
193
+ @client.upload delete_filename, 'Some file'
194
+ response = @client.delta
195
+ cursor, files = response.cursor, response.entries
196
+ files.last.path.should == delete_filename
197
+ files.last.destroy
198
+ @client.upload filename, 'Another file'
199
+ response = @client.delta(cursor)
200
+ cursor, files = response.cursor, response.entries
201
+ files.length.should == 2
202
+ files.first.is_deleted.should == true
203
+ files.first.path.should == delete_filename
204
+ files.last.path.should == filename
205
+ end
206
+ end
207
+
208
+ end
@@ -0,0 +1,82 @@
1
+ require "spec_helper"
2
+
3
+ describe Cloudpt::API::Connection do
4
+
5
+ before do
6
+ @connection = Cloudpt::API::Connection.new(:token => Cloudpt::Spec.token,
7
+ :secret => Cloudpt::Spec.secret)
8
+ end
9
+
10
+ describe "#request" do
11
+
12
+ it "returns a parsed response when the response is a 200" do
13
+ response = mock :code => 200, :body => '{ "a":1}'
14
+ response = @connection.request { response }
15
+ response.should be_an_instance_of(Hash)
16
+ end
17
+
18
+ it "raises a Cloudpt::API::Error::Unauthorized when the response is a 401" do
19
+ response = mock :code => 401, :body => '{ "a":1}'
20
+ lambda do
21
+ @connection.request { response }
22
+ end.should raise_error(Cloudpt::API::Error::Unauthorized)
23
+ end
24
+
25
+ it "raises a Cloudpt::API::Error::Forbidden when the response is a 403" do
26
+ response = mock :code => 403, :body => '{ "a":1}'
27
+ lambda do
28
+ @connection.request { response }
29
+ end.should raise_error(Cloudpt::API::Error::Forbidden)
30
+ end
31
+
32
+ it "raises a Cloudpt::API::Error::NotFound when the response is a 404" do
33
+ response = mock :code => 404, :body => '{ "a":1}'
34
+ lambda do
35
+ @connection.request { response }
36
+ end.should raise_error(Cloudpt::API::Error::NotFound)
37
+ end
38
+
39
+ it "raises a Cloudpt::API::Error when the response is a 3xx" do
40
+ response = mock :code => 301, :body => '{ "a":1}'
41
+ lambda do
42
+ @connection.request { response }
43
+ end.should raise_error(Cloudpt::API::Error::Redirect)
44
+ end
45
+
46
+ it "raises a Cloudpt::API::Error when the response is a 5xx" do
47
+ response = mock :code => 500, :body => '{ "a":1}'
48
+ lambda do
49
+ @connection.request { response }
50
+ end.should raise_error(Cloudpt::API::Error)
51
+ end
52
+
53
+ it "raises a Cloudpt::API::Error when the response is a 400" do
54
+ response = mock :code => 400, :body => '{ "error": "bad request" }'
55
+ lambda do
56
+ @connection.request { response }
57
+ end.should raise_error(Cloudpt::API::Error)
58
+ end
59
+
60
+ it "raises a Cloudpt::API::Error when the response is a 406" do
61
+ response = mock :code => 406, :body => '{ "error": "bad request" }'
62
+ lambda do
63
+ @connection.request { response }
64
+ end.should raise_error(Cloudpt::API::Error)
65
+ end
66
+
67
+ it "returns the raw response if :raw => true is provided" do
68
+ response = mock :code => 200, :body => '{ "something": "more" }'
69
+ response = @connection.request(:raw => true) { response }
70
+ response.should == '{ "something": "more" }'
71
+ end
72
+
73
+ end
74
+
75
+ describe "#consumer" do
76
+
77
+ it "returns an appropriate consumer object" do
78
+ @connection.consumer(:main).should be_a(::OAuth::Consumer)
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe Cloudpt::API::Dir do
4
+
5
+ before do
6
+ @client = Cloudpt::Spec.instance
7
+ @dirname = "#{Cloudpt::Spec.test_dir}/spec-dir-test-#{Time.now.to_i}"
8
+ @dir = @client.mkdir @dirname
9
+ end
10
+
11
+ after do
12
+ # @dir.delete
13
+ end
14
+
15
+ describe "#copy" do
16
+
17
+ it "copies the dir properly" do
18
+ new_dirname = @dirname + "-copied"
19
+ @dir.copy new_dirname
20
+ @dir.path.should == new_dirname
21
+ end
22
+
23
+ end
24
+
25
+ describe "#move" do
26
+
27
+ it "moves the dir properly" do
28
+ new_dirname = @dirname + "-copied"
29
+ @dir.move new_dirname
30
+ @dir.path.should == new_dirname
31
+ end
32
+
33
+ end
34
+
35
+ describe "#destroy" do
36
+
37
+ it "destroys the dir properly" do
38
+ @dir.destroy
39
+ @dir.is_deleted.should == true
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,126 @@
1
+ require "spec_helper"
2
+
3
+ describe Cloudpt::API::File do
4
+
5
+ before do
6
+ @client = Cloudpt::Spec.instance
7
+ @filename = "#{Cloudpt::Spec.test_dir}/spec-test-#{Time.now.to_i}.txt"
8
+ @file = @client.upload @filename, "spec file"
9
+ end
10
+
11
+ after do
12
+ # @file.delete
13
+ end
14
+
15
+ describe "#copy" do
16
+
17
+ it "copies the file properly" do
18
+ new_filename = @filename + ".copied"
19
+ @file.copy new_filename
20
+ @file.path.should == new_filename
21
+ end
22
+
23
+ end
24
+
25
+ describe "#move" do
26
+
27
+ it "moves the file properly" do
28
+ new_filename = @filename + ".copied"
29
+ @file.move new_filename
30
+ @file.path.should == new_filename
31
+ end
32
+
33
+ end
34
+
35
+ describe "#destroy" do
36
+
37
+ it "destroys the file properly" do
38
+ @file.destroy
39
+ @file.is_deleted.should == true
40
+ end
41
+
42
+ end
43
+
44
+ describe "#revisions" do
45
+
46
+ it "retrieves all revisions as an Array of File objects" do
47
+ @client.upload @file.path, "Updated content"
48
+
49
+ revisions = @file.revisions
50
+ revisions.size.should == 2
51
+ revisions.collect { |f| f.class }.should == [Cloudpt::API::File, Cloudpt::API::File]
52
+ end
53
+
54
+ end
55
+
56
+ describe "#restore" do
57
+
58
+ it "restores the file to a specific revision" do
59
+ old_rev = @file.rev
60
+
61
+ @client.upload @file.path, "Updated content"
62
+
63
+ file = @filename.split('/').last
64
+
65
+ found = @client.find(@file.path)
66
+
67
+ found.rev.should_not == old_rev
68
+
69
+ newer_rev = found.rev
70
+
71
+ @file.restore(old_rev)
72
+
73
+ found = @client.find(@file.path)
74
+
75
+ found.rev.should_not == old_rev
76
+ found.rev.should_not == newer_rev
77
+
78
+ end
79
+
80
+ end
81
+
82
+ describe "#share_url" do
83
+
84
+ it "returns an Url object" do
85
+
86
+ result = @file.share_url
87
+ result.should be_an_instance_of(Cloudpt::API::Object)
88
+ result.keys.sort.should == ['expires', 'url']
89
+
90
+ end
91
+
92
+ end
93
+
94
+ describe "#copy_ref" do
95
+
96
+ it "returns a copy_ref object" do
97
+
98
+ result = @file.copy_ref
99
+ result.should be_an_instance_of(Cloudpt::API::Object)
100
+ result.keys.sort.should == ['copy_ref', 'expires']
101
+
102
+ end
103
+
104
+ end
105
+
106
+ describe "#direct_url" do
107
+
108
+ it "returns an Url object" do
109
+
110
+ result = @file.direct_url
111
+ result.should be_an_instance_of(Cloudpt::API::Object)
112
+ result.keys.sort.should == ['expires', 'url']
113
+
114
+ end
115
+
116
+ end
117
+
118
+ describe "#download" do
119
+
120
+ it "should download the file" do
121
+ @file.download.should == 'spec file'
122
+ end
123
+
124
+ end
125
+
126
+ end