gliffy 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MTk3NDU4YmY2MTdmMTk1MTM4YTE5MmZhOGUwYjg3MzE2ZmI5NzYxNg==
4
+ YzU3NGY4YjYxMzMzMTg4ZmUwMjBmYWE4Y2E5NWQ3MGUwMzgwNWU1Nw==
5
5
  data.tar.gz: !binary |-
6
- ZGJhY2Y5ZGFiMGEzMmU5NmIyOGU4NjI0M2NlZWQ3NjZhNWFkMzlkNA==
6
+ YzhkNzViNDI3ZWMyMWFlZWI0NzM5MjI5MjFkZjUzYjk5MzJkNzhmOQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZTBiYjRhOTVmZjgwYTVhY2JlZmFlNzYyMDRlYmE5YTJkZWE1NTNlZjMwYmNj
10
- ZDE1NGM1OGM1YTIwNjZkZjFjMjU3MzQ1ZTg0YzEyYTVhYTVjOTI3Yjg1NGM2
11
- MTJmYzhkZTg2ZjE1ODUyMDI2YzIwOTgwYmQ5YWMxMWYyNzViMWI=
9
+ YmU2NDFiMWYwZGZiMDRiMmU3YjZhNDE2MjY3OWI2MzYwOTVmMzE0NWI3MjYz
10
+ YTEzM2NkYTgzY2E0ZDIwOWUwNGI5NjE3Nzk2NDIxMTA4ZTcyZDI0YzE0NTBk
11
+ OTg2OTAwN2ZkNzVkMjM4ZmYyMmIzYzE2OTVmNzBjMTNlYTE1ZjM=
12
12
  data.tar.gz: !binary |-
13
- OTJhZTQ2NTZkNTc1MGJjOWM1N2JjNDQ0ZDY3MzI5N2E2ZjdjN2NmNjg3NWVj
14
- MzlmMTBlZGYwNDA5ODE5ZjUzMDEzYTI1ZDRjYWE1MWNiMjdiYTY0OTc2ODkw
15
- NDI0NTlkZjBmODYyZWVhYjM0ZmU2YmJmNjk0NTJiMDY4N2Q3MzU=
13
+ NTE2NDVlNzQ5MTBlNDVhYTA3ZTQ0ZGJkOTMyYTQ4Yzk0NmMxY2NiMjkzZDA3
14
+ ZjNjYmJhZTA3ZmM2NGMwNDFlYjE2ZjJhMWE2OTVhY2M3ZmExYjAyYWJjNDQy
15
+ Y2M2MGFlMjgxODViNzVhYmIzNDRkZWJjYWYyNzVhMzgzZGE2NWE=
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  Gliffy API wrapper
2
2
  ==================
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/gliffy.png)](http://badge.fury.io/rb/gliffy)
5
+ [![Code Climate](https://codeclimate.com/github/bkon/gliffy.png)](https://codeclimate.com/github/bkon/gliffy)
6
+
4
7
  Basic usage
5
8
  -----------
6
9
 
@@ -36,9 +39,11 @@ Basic usage
36
39
 
37
40
  doc.xml.content
38
41
 
39
- ### Navigating folders
42
+ ### Working with folders
40
43
 
41
44
  root = account.root
42
45
  root.folders[0].documents
43
46
  root.folders[1].name
44
47
  root.folders[1].path
48
+
49
+ folder.delete
@@ -37,6 +37,12 @@ module Gliffy
37
37
  api.web(web_root + partial_url, params)
38
38
  end
39
39
 
40
+ # Path is alphanumeric + spaces and '/'. Spaces should be
41
+ # escaped; slashes should NOT be escaped.
42
+ def escape_path(path)
43
+ path.gsub(' ', '+')
44
+ end
45
+
40
46
  def get_folders(account_id)
41
47
  get("/accounts/#{account_id}/folders.xml",
42
48
  :action => 'get')
@@ -64,6 +70,21 @@ module Gliffy
64
70
  :action => "delete")
65
71
  end
66
72
 
73
+ def move_document(document_id, folder_path)
74
+ post("/accounts/#{account_id}/folders/#{escape_path folder_path}/documents/#{document_id}.xml",
75
+ :action => "move")
76
+ end
77
+
78
+ def get_documents_in_folder(path)
79
+ get("/accounts/#{account_id}/folders/#{escape_path path}/documents.xml",
80
+ :action => "get")
81
+ end
82
+
83
+ def delete_folder(path)
84
+ post("/accounts/#{account_id}/folders/#{escape_path path}.xml",
85
+ :action => "delete")
86
+ end
87
+
67
88
  def create_document(name, type, original_id, path)
68
89
  params = {
69
90
  :action => "create",
@@ -83,6 +104,11 @@ module Gliffy
83
104
  params)
84
105
  end
85
106
 
107
+ def create_folder(path)
108
+ post("/accounts/#{account_id}/folders/#{path}.xml",
109
+ :action => "create")
110
+ end
111
+
86
112
  private
87
113
 
88
114
  def handle_error(response)
@@ -43,12 +43,20 @@ module Gliffy
43
43
  api.update_document_metadata(id, new_name, nil)
44
44
  end
45
45
 
46
+ def move(folder)
47
+ api.move_document(id, folder.path)
48
+
49
+ changed
50
+ notify_observers :document_removed, self
51
+ folder.update :document_added, self
52
+ end
53
+
46
54
  def delete
47
55
  api.delete_document(id)
48
56
  @is_deleted = true
49
57
 
50
58
  changed
51
- notify_observers :delete, self
59
+ notify_observers :document_deleted, self
52
60
  end
53
61
 
54
62
  def deleted?
@@ -2,6 +2,8 @@ require 'uri'
2
2
 
3
3
  module Gliffy
4
4
  class Folder
5
+ include Observable
6
+
5
7
  attr_reader :name, :path
6
8
  attr_reader :owner, :parent
7
9
  attr_reader :folders
@@ -23,7 +25,10 @@ module Gliffy
23
25
  @folders = folders
24
26
  @folders.each do |f|
25
27
  f.parent = self
28
+ f.add_observer(self)
26
29
  end
30
+
31
+ @is_deleted = false
27
32
  end
28
33
 
29
34
  def parent=(parent)
@@ -38,6 +43,20 @@ module Gliffy
38
43
  api.create_document(name, Gliffy::Document::TYPE_DIAGRAM, nil, path)
39
44
  end
40
45
 
46
+ def create_folder(name)
47
+ if has_child? name
48
+ raise ArgumentError.new(name)
49
+ end
50
+
51
+ new_path = path + "/" + name
52
+
53
+ api.create_folder(new_path)
54
+
55
+ new_folder = Folder.new(owner, name, new_path, [])
56
+ folders.push(new_folder)
57
+ new_folder
58
+ end
59
+
41
60
  def documents
42
61
  @documents ||= load_documents
43
62
  end
@@ -46,36 +65,49 @@ module Gliffy
46
65
  path == "ROOT"
47
66
  end
48
67
 
68
+ def deleted?
69
+ @is_deleted
70
+ end
71
+
72
+ def has_child?(name)
73
+ normalized_name = name.downcase
74
+ not folders.index do |child|
75
+ child.name.downcase == normalized_name
76
+ end.nil?
77
+ end
78
+
49
79
  # observer callback
50
80
  def update(event, target)
51
81
  case event
52
- when :delete
82
+ when :document_removed, :document_deleted
53
83
  @documents = @documents.delete_if { |element| element == target }
84
+ target.delete_observer(self)
85
+ when :document_added
86
+ @documents.push target
87
+ target.add_observer(self)
88
+ when :folder_deleted
89
+ @folders = @folders.delete_if { |element| element == target }
54
90
  else
55
91
  raise ArgumentError.new(event)
56
92
  end
57
93
  end
58
94
 
59
- private
95
+ def delete
96
+ api.delete_folder(path)
97
+ @is_deleted = true
60
98
 
61
- def api
62
- owner.api
99
+ changed
100
+ notify_observers :folder_deleted, self
63
101
  end
64
102
 
65
- def account_id
66
- owner.id
67
- end
103
+ private
68
104
 
69
- def escaped_path
70
- path.gsub(' ', '+')
105
+ def api
106
+ owner.api
71
107
  end
72
108
 
73
109
  def load_documents
74
- # Path is alphanumeric + spaces and '/'. Spaces should be
75
- # escaped; slashes should NOT be escaped.
76
- url = "/accounts/#{account_id}/folders/#{escaped_path}/documents.xml"
77
- response = api.get(url,
78
- :action => "get")
110
+ response = api.get_documents_in_folder(path)
79
111
 
80
112
  response
81
113
  .nodes('//g:document')
@@ -1,6 +1,20 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  shared_examples_for "an API facade" do
4
+ it "has folder path escame method" do
5
+ expect(facade).to respond_to :escape_path
6
+ end
7
+
8
+ describe "folder path escape method" do
9
+ it "escapes spaces" do
10
+ expect(facade.escape_path("A B")).to eq "A+B"
11
+ end
12
+
13
+ it "does not escape slashes" do
14
+ expect(facade.escape_path("A/B")).to eq "A/B"
15
+ end
16
+ end
17
+
4
18
  context "when sending GET request" do
5
19
  it "forwards request to the API backend with HTTP protocol" do
6
20
  api.should_receive(
@@ -121,6 +135,80 @@ shared_examples_for "an API facade" do
121
135
  end
122
136
  end
123
137
 
138
+ it "allows user to move document to a different folder" do
139
+ expect(facade).to respond_to :move_document
140
+ end
141
+
142
+ context "when moving a document" do
143
+ let(:document_id) { 144 }
144
+ let(:folder_path) { "ROOT/FOLDER/SUBFOLDER" }
145
+
146
+ before :each do
147
+ facade.stub(:post)
148
+ end
149
+
150
+ it "sends POST request" do
151
+ facade.move_document(document_id, folder_path)
152
+
153
+ expect(facade).to have_received(:post)
154
+ .with("/accounts/#{account_id}/folders/#{folder_path}/documents/#{document_id}.xml",
155
+ hash_including(:action => "move"))
156
+ end
157
+ end
158
+
159
+ it "allows to load documents in a folder" do
160
+ expect(facade).to respond_to :get_documents_in_folder
161
+ end
162
+
163
+ context "when loading documents in a folder" do
164
+ let(:folder_path) { "ROOT/test" }
165
+ let(:response) { double(Gliffy::API::Response) }
166
+
167
+ before :each do
168
+ facade.stub(:get).and_return(response)
169
+ facade.stub(:escape_path).and_call_original
170
+
171
+ facade.get_documents_in_folder(folder_path)
172
+ end
173
+
174
+ it "sends GET request" do
175
+ expect(facade).to have_received(:get)
176
+ .with("/accounts/#{account_id}/folders/ROOT/test/documents.xml",
177
+ hash_including(:action => "get"))
178
+ end
179
+
180
+ it "escapes folder path properly" do
181
+ expect(facade).to have_received(:escape_path)
182
+ .with(folder_path)
183
+ end
184
+ end
185
+
186
+ it "allows user to delete a folder" do
187
+ expect(facade).to respond_to :delete_folder
188
+ end
189
+
190
+ context "when deleting a folder" do
191
+ let(:folder_path) { "ROOT/test" }
192
+
193
+ before :each do
194
+ facade.stub(:post)
195
+ facade.stub(:escape_path).and_call_original
196
+
197
+ facade.delete_folder(folder_path)
198
+ end
199
+
200
+ it "escapes folder path properly" do
201
+ expect(facade).to have_received(:escape_path)
202
+ .with(folder_path)
203
+ end
204
+
205
+ it "sends POST request" do
206
+ expect(facade).to have_received(:post)
207
+ .with("/accounts/#{account_id}/folders/#{folder_path}.xml",
208
+ hash_including(:action => "delete"))
209
+ end
210
+ end
211
+
124
212
  it "allows user to create a document" do
125
213
  expect(facade).to respond_to :create_document
126
214
  end
@@ -164,6 +252,24 @@ shared_examples_for "an API facade" do
164
252
  end
165
253
  end
166
254
 
255
+ it "allows user to create a folder" do
256
+ expect(facade).to respond_to :create_folder
257
+ end
258
+
259
+ context "when creating a folder" do
260
+ let(:folder_path) { "ROOT/TEST/SUBFOLDER" }
261
+
262
+ it "sends POST request" do
263
+ facade.stub(:post)
264
+
265
+ facade.create_folder(folder_path)
266
+
267
+ expect(facade).to have_received(:post)
268
+ .with("/accounts/#{account_id}/folders/#{folder_path}.xml",
269
+ hash_including(:action => "create"))
270
+ end
271
+ end
272
+
167
273
  context "when POST request returns an error" do
168
274
  let(:response) { Gliffy::API::Response.new(fixture("error-401")) }
169
275
 
@@ -137,6 +137,41 @@ describe Gliffy::Document do
137
137
  end
138
138
  end
139
139
 
140
+ it "can be moved" do
141
+ expect(document).to respond_to :move
142
+ end
143
+
144
+ context "when moved" do
145
+ let(:observer) { double(Object, :update => nil) }
146
+ let(:folder) do
147
+ double(Gliffy::Folder,
148
+ :path => "ROOT/FOLDER/SUBFOLDER",
149
+ :update => nil)
150
+ end
151
+
152
+ before :each do
153
+ api.stub(:move_document)
154
+
155
+ document.add_observer(observer)
156
+ document.move(folder)
157
+ end
158
+
159
+ it "calls REST API" do
160
+ expect(api).to have_received(:move_document)
161
+ .with(document.id, folder.path)
162
+ end
163
+
164
+ it "notifies observers" do
165
+ expect(observer).to have_received(:update)
166
+ .with(:document_removed, document)
167
+ end
168
+
169
+ it "notifies new parent" do
170
+ expect(folder).to have_received(:update)
171
+ .with(:document_added, document)
172
+ end
173
+ end
174
+
140
175
  it "can be deleted" do
141
176
  expect(document).to respond_to :delete
142
177
  end
@@ -173,7 +208,7 @@ describe Gliffy::Document do
173
208
  end
174
209
 
175
210
  it "notifies observers" do
176
- expect(observer).to have_received(:update).with(:delete, document)
211
+ expect(observer).to have_received(:update).with(:document_deleted, document)
177
212
  end
178
213
  end
179
214
  end
@@ -40,34 +40,30 @@ describe Gliffy::Folder do
40
40
  end
41
41
 
42
42
  describe "document list" do
43
- it "is loaded from API" do
44
- api.should_receive(
45
- :get
46
- ).and_return(
47
- Gliffy::API::Response.new(fixture("documents"))
48
- )
43
+ let(:response) { Gliffy::API::Response.new(fixture("documents")) }
44
+
45
+ before :each do
46
+ api.stub(:get_documents_in_folder)
47
+ .and_return(response)
48
+ end
49
49
 
50
+ it "is loaded from API" do
50
51
  folder.documents
52
+
53
+ expect(api).to have_received(:get_documents_in_folder)
54
+ .with(folder.path)
51
55
  end
52
56
 
53
57
  it "has correct length" do
54
- api.stub(
55
- :get
56
- ).and_return(
57
- Gliffy::API::Response.new(fixture("documents"))
58
- )
59
-
60
58
  expect(folder.documents.length).to eq 3
61
59
  end
62
60
 
63
- it "is empty when API returns appropriate response" do
64
- api.stub(
65
- :get
66
- ).and_return(
67
- Gliffy::API::Response.new(fixture("documents-empty"))
68
- )
61
+ context "when API returns empty response" do
62
+ let(:response) { Gliffy::API::Response.new(fixture("documents-empty")) }
69
63
 
70
- expect(folder.documents.length).to eq 0
64
+ it "is empty" do
65
+ expect(folder.documents.length).to eq 0
66
+ end
71
67
  end
72
68
  end
73
69
 
@@ -75,6 +71,16 @@ describe Gliffy::Folder do
75
71
  expect(folder).to respond_to :folders
76
72
  end
77
73
 
74
+ it "listens for changes in nested folders" do
75
+ folder.stub(:update)
76
+
77
+ folder.folders[0].changed
78
+ folder.folders[0].notify_observers(:event, :target)
79
+
80
+ expect(folder).to have_received(:update)
81
+ .with(:event, :target)
82
+ end
83
+
78
84
  describe "folder list" do
79
85
  subject(:children) { folder.folders }
80
86
 
@@ -194,24 +200,151 @@ describe Gliffy::Folder do
194
200
  end
195
201
  end
196
202
 
203
+ it "allows us to create a folder" do
204
+ expect(folder).to respond_to :create_folder
205
+ end
206
+
207
+ context "when creating a folder" do
208
+ let(:folder_name) { "SUBFOLDER" }
209
+
210
+ before :each do
211
+ api.stub(:create_folder)
212
+ end
213
+
214
+ it "calls REST API" do
215
+ folder.create_folder(folder_name)
216
+ expect(api).to have_received(:create_folder)
217
+ .with(folder.path + "/" + folder_name)
218
+ end
219
+
220
+ it "returns a new folder" do
221
+ new_folder = folder.create_folder(folder_name)
222
+ expect(new_folder).to be_instance_of Gliffy::Folder
223
+ end
224
+
225
+ it "updates subfolder list" do
226
+ old_length = folder.folders.length
227
+
228
+ new_folder = folder.create_folder(folder_name)
229
+
230
+ expect(folder.folders.length).to eq old_length + 1
231
+ expect(folder.folders).to include new_folder
232
+ end
233
+
234
+ context "when subfolder with the same name already exists" do
235
+ let(:folder_name) { folder.folders[0].name }
236
+
237
+ it "throws an exception" do
238
+ expect { folder.create_folder(folder_name) }.to raise_error ArgumentError
239
+ end
240
+ end
241
+
242
+ context "when subfolder with differently capitalized name already exists" do
243
+ let(:folder_name) { folder.folders[0].name.swapcase }
244
+
245
+ it "throws an exception" do
246
+ expect { folder.create_folder(folder_name) }.to raise_error ArgumentError
247
+ end
248
+ end
249
+ end
250
+
251
+ context "when notified that a document has been removed" do
252
+ let(:document) do
253
+ api.stub(:get_documents_in_folder)
254
+ .and_return(Gliffy::API::Response.new(fixture("documents")))
255
+
256
+ folder.documents[1]
257
+ end
258
+
259
+ before :each do
260
+ document.stub(:delete_observer).and_call_original
261
+ end
262
+
263
+ it "removes document from the document list" do
264
+ original_length = folder.documents.length
265
+
266
+ folder.update(:document_removed, document)
267
+
268
+ expect(folder.documents.length).to eq original_length - 1
269
+ expect(folder.documents).to_not include document
270
+ end
271
+
272
+ it "stops listening to this document's events" do
273
+ folder.update(:document_removed, document)
274
+
275
+ expect(document).to have_received(:delete_observer)
276
+ .with(folder)
277
+ end
278
+ end
279
+
280
+ context "when notified that a document has been added" do
281
+ let(:document) do
282
+ api.stub(:get_documents_in_folder)
283
+ .and_return(Gliffy::API::Response.new(fixture("documents")))
284
+
285
+ folder.documents[1]
286
+ end
287
+
288
+ before :each do
289
+ document.stub(:add_observer).and_call_original
290
+ end
291
+
292
+ it "adds document to the document list" do
293
+ original_length = folder.documents.length
294
+
295
+ folder.update(:document_added, document)
296
+
297
+ expect(folder.documents.length).to eq original_length + 1
298
+ expect(folder.documents).to include document
299
+ end
300
+
301
+ it "starts listening to this document's events" do
302
+ folder.update(:document_added, document)
303
+
304
+ expect(document).to have_received(:add_observer)
305
+ .with(folder)
306
+ end
307
+ end
308
+
197
309
  context "when receives a document delete notification" do
310
+ let(:document) do
311
+ api.stub(:get_documents_in_folder)
312
+ .and_return(Gliffy::API::Response.new(fixture("documents")))
313
+
314
+ folder.documents[1]
315
+ end
316
+
198
317
  before :each do
199
- api.should_receive(
200
- :get
201
- ).and_return(
202
- Gliffy::API::Response.new(fixture("documents"))
203
- )
318
+ document.stub(:delete_observer).and_call_original
204
319
  end
205
320
 
206
321
  it "removes document from the document list" do
207
322
  original_length = folder.documents.length
208
- document = folder.documents[1]
209
323
 
210
- folder.update(:delete, document)
324
+ folder.update(:document_deleted, document)
211
325
 
212
326
  expect(folder.documents.length).to eq original_length - 1
213
327
  expect(folder.documents).to_not include document
214
328
  end
329
+
330
+ it "stops listening to this document's events" do
331
+ folder.update(:document_deleted, document)
332
+
333
+ expect(document).to have_received(:delete_observer)
334
+ .with(folder)
335
+ end
336
+ end
337
+
338
+ context "when received a child folder delete notification" do
339
+ it "removes folder from the children list" do
340
+ original_length = folder.folders.length
341
+ child = folder.folders[1]
342
+
343
+ folder.update(:folder_deleted, child)
344
+
345
+ expect(folder.folders.length).to eq original_length - 1
346
+ expect(folder.folders).to_not include child
347
+ end
215
348
  end
216
349
 
217
350
  context "when receives an unknown event" do
@@ -221,4 +354,42 @@ describe Gliffy::Folder do
221
354
  expect { folder.update(:unknown, document) }.to raise_error ArgumentError
222
355
  end
223
356
  end
357
+
358
+ it "can be deleted" do
359
+ expect(folder).to respond_to :delete
360
+ end
361
+
362
+ it "knows its deleted state" do
363
+ expect(folder).to respond_to :deleted?
364
+ end
365
+
366
+ it "is not marked as deleted by default" do
367
+ expect(folder.deleted?).to be_false
368
+ end
369
+
370
+ context "when being deleted" do
371
+ let(:observer) { double(Object) }
372
+
373
+ before :each do
374
+ api.stub(:delete_folder)
375
+
376
+ observer.stub(:update)
377
+ folder.add_observer(observer)
378
+
379
+ folder.delete
380
+ end
381
+
382
+ it "calls REST API" do
383
+ expect(api).to have_received(:delete_folder)
384
+ .with(folder.path)
385
+ end
386
+
387
+ it "notifies observers about this" do
388
+ expect(observer).to have_received(:update).with(:folder_deleted, folder)
389
+ end
390
+
391
+ it "is marked as deleted" do
392
+ expect(folder.deleted?).to be_true
393
+ end
394
+ end
224
395
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gliffy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Burnaev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-05 00:00:00.000000000 Z
11
+ date: 2013-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth