gliffy 0.0.7 → 0.0.8

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.
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