@@ -40,7 +40,6 @@ module Agents |
||
| 40 | 40 |
def check |
| 41 | 41 |
api = DropboxAPI.new(interpolated[:access_token]) |
| 42 | 42 |
current_contents = api.dir(interpolated[:dir_to_watch]) |
| 43 |
- |
|
| 44 | 43 |
diff = DropboxDirDiff.new(previous_contents, current_contents) |
| 45 | 44 |
create_event(payload: diff.to_hash) unless previous_contents.nil? || diff.empty? |
| 46 | 45 |
|
@@ -66,13 +65,32 @@ module Agents |
||
| 66 | 65 |
# == Auxiliary classes == |
| 67 | 66 |
|
| 68 | 67 |
class DropboxAPI |
| 68 |
+ class ResourceNotFound < RuntimeError; end |
|
| 69 |
+ |
|
| 70 |
+ include HTTParty |
|
| 71 |
+ base_uri 'https://api.dropbox.com/1' |
|
| 72 |
+ |
|
| 69 | 73 |
def initialize(access_token) |
| 74 |
+ @options = { query: { access_token: access_token } }
|
|
| 75 |
+ end |
|
| 76 |
+ |
|
| 77 |
+ def dir(to_watch) |
|
| 78 |
+ options = @options.deep_merge({ query: { list: true } })
|
|
| 79 |
+ response = self.class.get("/metadata/auto#{to_watch}", options)
|
|
| 80 |
+ raise ResourceNotFound.new(to_watch) if response.not_found? |
|
| 81 |
+ JSON.parse(response)['contents'].map { |entry| slice_json(entry, :path, :rev, :modified) }
|
|
| 82 |
+ end |
|
| 83 |
+ |
|
| 84 |
+ private |
|
| 85 |
+ |
|
| 86 |
+ def slice_json(json, *keys) |
|
| 87 |
+ keys.each_with_object({}){|key, hash| hash[key] = json[key.to_s]}
|
|
| 70 | 88 |
end |
| 71 | 89 |
end |
| 72 | 90 |
|
| 73 | 91 |
class DropboxDirDiff |
| 74 | 92 |
def initialize(previous, current) |
| 75 |
- @previous, @current = [previous, current] |
|
| 93 |
+ @previous, @current = [previous || [], current || []] |
|
| 76 | 94 |
end |
| 77 | 95 |
|
| 78 | 96 |
def empty? |
@@ -154,6 +154,88 @@ describe Agents::DropboxWatchAgent do |
||
| 154 | 154 |
expect(diff_hash[:updated]).to eq [ { path: '1.json', rev: '2' } ]
|
| 155 | 155 |
end |
| 156 | 156 |
|
| 157 |
+ context 'when the previous value is not defined' do |
|
| 158 |
+ it 'considers all additions' do |
|
| 159 |
+ diff_hash = Agents::DropboxWatchAgent::DropboxDirDiff.new(nil, current).to_hash |
|
| 160 |
+ expect(diff_hash[:added]).to eq current |
|
| 161 |
+ expect(diff_hash[:removed]).to eq [] |
|
| 162 |
+ expect(diff_hash[:updated]).to eq [] |
|
| 163 |
+ end |
|
| 164 |
+ end |
|
| 165 |
+ |
|
| 166 |
+ context 'when the current value is not defined' do |
|
| 167 |
+ it 'considers all removals' do |
|
| 168 |
+ diff_hash = Agents::DropboxWatchAgent::DropboxDirDiff.new(previous, nil).to_hash |
|
| 169 |
+ expect(diff_hash[:added]).to eq [] |
|
| 170 |
+ expect(diff_hash[:removed]).to eq previous |
|
| 171 |
+ expect(diff_hash[:updated]).to eq [] |
|
| 172 |
+ end |
|
| 173 |
+ end |
|
| 174 |
+ end |
|
| 175 |
+ end |
|
| 176 |
+ |
|
| 177 |
+ describe Agents::DropboxWatchAgent::DropboxAPI do |
|
| 178 |
+ let(:dir_to_watch) { '/my/dropbox/dir' }
|
|
| 179 |
+ let(:access_token) { '70k3n' }
|
|
| 180 |
+ let(:api_url) { "https://api.dropbox.com/1/metadata/auto#{dir_to_watch}?access_token=#{access_token}&list=true" }
|
|
| 181 |
+ |
|
| 182 |
+ describe '#dir' do |
|
| 183 |
+ |
|
| 184 |
+ context 'when the provided path exists' do |
|
| 185 |
+ before do |
|
| 186 |
+ stub_request(:get, api_url).to_return(body: JSON.dump({
|
|
| 187 |
+ contents: [ |
|
| 188 |
+ {
|
|
| 189 |
+ bytes: 0, |
|
| 190 |
+ icon: "folder", |
|
| 191 |
+ is_dir: true, |
|
| 192 |
+ modified: "Mon, 11 Mar 2013 15:41:44 +0000", |
|
| 193 |
+ path: "#{dir_to_watch}/1.json",
|
|
| 194 |
+ rev: "1", |
|
| 195 |
+ revision: 14743, |
|
| 196 |
+ root: "dropbox", |
|
| 197 |
+ size: "0 bytes", |
|
| 198 |
+ thumb_exists: false |
|
| 199 |
+ }, |
|
| 200 |
+ {
|
|
| 201 |
+ bytes: 0, |
|
| 202 |
+ icon: "folder", |
|
| 203 |
+ is_dir: true, |
|
| 204 |
+ modified: "Mon, 12 Mar 2013 15:41:44 +0000", |
|
| 205 |
+ path: "#{dir_to_watch}/2.json",
|
|
| 206 |
+ rev: "4", |
|
| 207 |
+ revision: 113022, |
|
| 208 |
+ root: "dropbox", |
|
| 209 |
+ size: "0 bytes", |
|
| 210 |
+ thumb_exists: false |
|
| 211 |
+ } |
|
| 212 |
+ ], |
|
| 213 |
+ some: "other", |
|
| 214 |
+ things: "we", |
|
| 215 |
+ dont: "need" |
|
| 216 |
+ })) |
|
| 217 |
+ end |
|
| 218 |
+ |
|
| 219 |
+ it 'trims down the attributes of the response to our needs' do |
|
| 220 |
+ dir_list = Agents::DropboxWatchAgent::DropboxAPI.new(access_token).dir(dir_to_watch) |
|
| 221 |
+ expect(dir_list).to eq [ |
|
| 222 |
+ { path: "#{dir_to_watch}/1.json", rev: '1', modified: 'Mon, 11 Mar 2013 15:41:44 +0000' },
|
|
| 223 |
+ { path: "#{dir_to_watch}/2.json", rev: '4', modified: 'Mon, 12 Mar 2013 15:41:44 +0000' }
|
|
| 224 |
+ ] |
|
| 225 |
+ end |
|
| 226 |
+ end |
|
| 227 |
+ |
|
| 228 |
+ context 'when the provided path does not exist' do |
|
| 229 |
+ before { stub_request(:get, api_url).to_return(status: 404, body: '{"error": "Not Found"}') }
|
|
| 230 |
+ |
|
| 231 |
+ it 'raises a ResourceNotFound error' do |
|
| 232 |
+ expect {
|
|
| 233 |
+ Agents::DropboxWatchAgent::DropboxAPI.new(access_token).dir(dir_to_watch) |
|
| 234 |
+ }.to raise_error(Agents::DropboxWatchAgent::DropboxAPI::ResourceNotFound, dir_to_watch) |
|
| 235 |
+ end |
|
| 236 |
+ end |
|
| 237 |
+ |
|
| 157 | 238 |
end |
| 239 |
+ |
|
| 158 | 240 |
end |
| 159 | 241 |
end |