delicious 1.0.0

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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/delicious.gemspec +28 -0
  3. data/lib/delicious.rb +39 -0
  4. data/lib/delicious/api_model.rb +26 -0
  5. data/lib/delicious/bookmarks/api.rb +15 -0
  6. data/lib/delicious/bookmarks/methods/all.rb +112 -0
  7. data/lib/delicious/bookmarks/methods/create.rb +57 -0
  8. data/lib/delicious/bookmarks/methods/delete.rb +23 -0
  9. data/lib/delicious/bundle.rb +43 -0
  10. data/lib/delicious/bundles/api.rb +20 -0
  11. data/lib/delicious/bundles/methods/all.rb +23 -0
  12. data/lib/delicious/bundles/methods/delete.rb +23 -0
  13. data/lib/delicious/bundles/methods/find.rb +26 -0
  14. data/lib/delicious/bundles/methods/set.rb +27 -0
  15. data/lib/delicious/client.rb +57 -0
  16. data/lib/delicious/error.rb +6 -0
  17. data/lib/delicious/post.rb +42 -0
  18. data/lib/delicious/tag.rb +26 -0
  19. data/lib/delicious/tags/api.rb +15 -0
  20. data/lib/delicious/tags/methods/all.rb +24 -0
  21. data/lib/delicious/tags/methods/delete.rb +23 -0
  22. data/lib/delicious/tags/methods/rename.rb +24 -0
  23. data/lib/delicious/version.rb +5 -0
  24. data/spec/delicious/bookmarks/methods/all_spec.rb +122 -0
  25. data/spec/delicious/bookmarks/methods/create_spec.rb +120 -0
  26. data/spec/delicious/bundle_spec.rb +42 -0
  27. data/spec/delicious/bundles/methods/set_spec.rb +78 -0
  28. data/spec/delicious/client_spec.rb +189 -0
  29. data/spec/delicious/post_spec.rb +34 -0
  30. data/spec/delicious/tags/methods/all_spec.rb +70 -0
  31. data/spec/delicious/tags/methods/delete_spec.rb +47 -0
  32. data/spec/delicious/tags/methods/rename_spec.rb +47 -0
  33. data/spec/spec_helper.rb +11 -0
  34. data/spec/support/helpers/request_helper.rb +10 -0
  35. data/spec/support/shared/api_action.rb +13 -0
  36. metadata +175 -0
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delicious::Bundle do
4
+ it { should validate_presence_of :name }
5
+ it { should validate_presence_of :tags }
6
+
7
+ describe '#delete' do
8
+ context 'persisted' do
9
+ it 'invokes delete with the bundle name on associated client' do
10
+ client = ::Delicious::Client.new { |c| c.access_token = 'my-access-token' }
11
+ bundle = described_class.build_persisted client, name: 'mybundle', tags: %w(tag1 tag2)
12
+ expect(client.bundles).to receive(:delete).with bundle: 'mybundle'
13
+ bundle.delete
14
+ end
15
+ end
16
+
17
+ context 'not persisted' do
18
+ it 'throws an error' do
19
+ bundle = described_class.new name: 'mybundle', tags: %w(tag1 tag2)
20
+ expect { bundle.delete }.to raise_error('Bundle was not saved yet')
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#save' do
26
+ context 'persisted' do
27
+ it 'invokes set with bundle attrs on associated client' do
28
+ client = ::Delicious::Client.new { |c| c.access_token = 'my-access-token' }
29
+ bundle = described_class.build_persisted client, name: 'mybundle', tags: %w(tag1 tag2)
30
+ expect(client.bundles).to receive(:set).with('mybundle', %w(tag1 tag2))
31
+ expect(bundle.save).to eq true
32
+ end
33
+ end
34
+
35
+ context 'not persisted' do
36
+ it 'throws an error' do
37
+ bundle = described_class.new name: 'mybundle', tags: %w(tag1 tag2)
38
+ expect { bundle.save }.to raise_error('Bundle was not saved yet')
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delicious::Bundles::Methods::Set do
4
+ let(:client) do
5
+ Delicious::Client.new do |config|
6
+ config.access_token = 'my-access-token'
7
+ end
8
+ end
9
+
10
+ describe '#set' do
11
+ let(:result) { :success }
12
+
13
+ let(:bundle) { 'hardware' }
14
+ let(:tags) { %w(tag1 tag2) }
15
+
16
+ let(:method) { :post }
17
+ let(:endpoint) { 'https://previous.delicious.com/v1/tags/bundles/set' }
18
+ let(:action) { client.bundles.set bundle, tags }
19
+
20
+ let(:success_body) { '<?xml version="1.0" encoding="UTF-8"?><result>ok</result>' }
21
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?><result>tagbundle name is required</result>' }
22
+
23
+ before do
24
+ body = result == :failure ? failure_body : success_body
25
+ @request = stub_request(method, endpoint)
26
+ .to_return body: body, headers: {'Content-Type' => 'text/xml; charset=UTF-8'}
27
+ end
28
+
29
+ context 'valid attrs given' do
30
+ it_behaves_like 'api action'
31
+
32
+ it 'sends post to /v1/tags/bundles/set' do
33
+ action
34
+ expect(WebMock).to have_requested(:post, endpoint).with do |r|
35
+ assert_param(r, 'bundle', 'hardware') && assert_param(r, 'tags', 'tag1,tag2')
36
+ end
37
+ end
38
+
39
+ context 'ok from server' do
40
+ it 'returns an instance of Delicious::Bundle' do
41
+ expect(action).to be_an_instance_of(Delicious::Bundle)
42
+ end
43
+
44
+ it 'has name' do
45
+ expect(action.name).to eq 'hardware'
46
+ end
47
+
48
+ it 'has tags' do
49
+ expect(action.tags).to eq %w(tag1 tag2)
50
+ end
51
+ end
52
+
53
+ context 'error on server' do
54
+ let(:result) { :failure }
55
+
56
+ it 'throws an error' do
57
+ expect { action }.to raise_error Delicious::Error
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'bundle name omitted' do
63
+ let(:bundle) { nil }
64
+
65
+ it 'throws an error' do
66
+ expect { action }.to raise_error(Delicious::Error, "Bundle name can't be blank")
67
+ end
68
+ end
69
+
70
+ context 'tags are empty' do
71
+ let(:tags) { nil }
72
+
73
+ it 'throws an error' do
74
+ expect { action }.to raise_error(Delicious::Error, "Please specify at least 1 tag")
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delicious::Client do
4
+ let(:client) do
5
+ described_class.new do |config|
6
+ config.access_token = 'my-access-token'
7
+ end
8
+ end
9
+
10
+ describe 'configuration' do
11
+ it 'sets access_token to my-access-token' do
12
+ expect(client.access_token).to eq 'my-access-token'
13
+ end
14
+
15
+ it 'sets access_token to another-access-token' do
16
+ another_client = described_class.new { |config| config.access_token = 'another-access-token' }
17
+ expect(another_client.access_token).to eq 'another-access-token'
18
+ end
19
+ end
20
+
21
+ context 'actions' do
22
+ let(:result) { :success }
23
+ let(:success_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="done"/>' }
24
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="error adding link"/>' }
25
+ before do
26
+ body = result == :failure ? failure_body : success_body
27
+ @request = stub_request(method, endpoint)
28
+ .to_return body: body, headers: {'Content-Type' => 'text/xml; charset=UTF-8'}
29
+ end
30
+
31
+ describe '#bookmarks' do
32
+ describe '#delete' do
33
+ let(:method) { :post }
34
+ let(:endpoint) { 'https://previous.delicious.com/v1/posts/delete' }
35
+ let(:action) { client.bookmarks.delete 'http://example.com' }
36
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="The url or md5 could not be found."/>' }
37
+
38
+ it_behaves_like 'api action'
39
+
40
+ it 'sends url=http://example.com' do
41
+ action
42
+ expect(WebMock).to have_requested(:post, endpoint).with { |r| assert_param(r, 'url', 'http://example.com') }
43
+ end
44
+
45
+ context 'existing URL' do
46
+ it 'returns true' do
47
+ expect(action).to eq true
48
+ end
49
+ end
50
+
51
+ context 'non-existing URL' do
52
+ let(:result) { :failure }
53
+
54
+ it 'return false' do
55
+ expect(action).to eq false
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#bundles' do
62
+ describe '#find' do
63
+ let(:method) { :get }
64
+ let(:endpoint) { 'https://previous.delicious.com/v1/tags/bundles/all?bundle=hardware' }
65
+ let(:action) { client.bundles.find 'hardware' }
66
+ let(:success_body) do
67
+ <<-EOT
68
+ <?xml version="1.0" encoding="UTF-8"?>
69
+ <bundles>
70
+ <bundle name="hardware" tags="cpu hardware wifi"/>
71
+ </bundles>
72
+ EOT
73
+ end
74
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?>' }
75
+
76
+ it_behaves_like 'api action'
77
+
78
+ it 'sends /v1/tags/bundles/all request' do
79
+ action
80
+ expect(WebMock).to have_requested(:get, endpoint)
81
+ end
82
+
83
+ context 'found' do
84
+ let(:result) { :success }
85
+
86
+ it 'returns bundle instance' do
87
+ expect(action).to be_an_instance_of Delicious::Bundle
88
+ end
89
+
90
+ it 'sets name' do
91
+ expect(action.name).to eq 'hardware'
92
+ end
93
+
94
+ it 'sets tags' do
95
+ expect(action.tags).to eq %w(cpu hardware wifi)
96
+ end
97
+
98
+ it 'can be deleted' do
99
+ bundle = action
100
+ expect(client.bundles).to receive(:delete).with(bundle: bundle.name)
101
+ bundle.delete
102
+ end
103
+ end
104
+
105
+ context 'not found' do
106
+ let(:result) { :failure }
107
+
108
+ it 'is nil' do
109
+ expect(action).to be_nil
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#all' do
115
+ let(:method) { :get }
116
+ let(:endpoint) { 'https://previous.delicious.com/v1/tags/bundles/all' }
117
+ let(:action) { client.bundles.all }
118
+ let(:success_body) do
119
+ <<-EOT
120
+ <?xml version="1.0" encoding="UTF-8"?>
121
+ <bundles>
122
+ <bundle name="hardware" tags="cpu hardware wifi"/>
123
+ <bundle name="software" tags="editor graphics programming"/>
124
+ </bundles>
125
+ EOT
126
+ end
127
+
128
+ it_behaves_like 'api action'
129
+
130
+ it 'sends /v1/tags/bundles/all request' do
131
+ action
132
+ expect(WebMock).to have_requested(:get, endpoint)
133
+ end
134
+
135
+ it 'returns array of 2 bundles' do
136
+ expect(action.count).to eq 2
137
+ end
138
+
139
+ describe 'first' do
140
+ it 'has name' do
141
+ expect(action[0].name).to eq 'hardware'
142
+ end
143
+
144
+ it 'has tags' do
145
+ expect(action[0].tags).to eq %w(cpu hardware wifi)
146
+ end
147
+
148
+ it 'can be deleted' do
149
+ bundle = action[0]
150
+ expect(client.bundles).to receive(:delete).with(bundle: 'hardware')
151
+ bundle.delete
152
+ end
153
+ end
154
+
155
+ describe 'second' do
156
+ it 'has name' do
157
+ expect(action[1].name).to eq 'software'
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ describe '#delete' do
164
+ let(:method) { :post }
165
+ let(:endpoint) { 'https://previous.delicious.com/v1/tags/bundles/delete' }
166
+ let(:action) { client.bundles.delete 'hardware' }
167
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="The url or md5 could not be found."/>' }
168
+
169
+ it_behaves_like 'api action'
170
+
171
+ it 'sends post to /v1/tags/bundles/delete' do
172
+ action
173
+ expect(WebMock).to have_requested(:post, endpoint).with { |r| assert_param(r, 'bundle', 'hardware') }
174
+ end
175
+
176
+ context 'existing URL' do
177
+ it 'returns true' do
178
+ expect(action).to eq true
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ describe '#tags' do
185
+ it 'is an instance of Delicious::Tags::Api' do
186
+ expect(client.tags).to be_an_instance_of Delicious::Tags::Api
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delicious::Post do
4
+ it { should validate_presence_of :url }
5
+ it { should validate_presence_of :description }
6
+
7
+ it 'defaults shared to false' do
8
+ expect(described_class.new.shared).to eq false
9
+ end
10
+
11
+ describe '#delete' do
12
+ context 'persisted' do
13
+ before do
14
+ stub_request(:post, 'https://previous.delicious.com/v1/posts/add')
15
+ .to_return body: '<?xml version="1.0" encoding="UTF-8"?><result code="done"/>',
16
+ headers: {'Content-Type' => 'text/xml; charset=UTF-8'}
17
+ end
18
+
19
+ it 'invokes delete with the URL on associated client' do
20
+ client = Delicious::Client.new { |c| c.access_token = 'my-access-token' }
21
+ post = client.bookmarks.create url: 'http://example.com', description: 'Cool site'
22
+ expect(client.bookmarks).to receive(:delete).with url: 'http://example.com'
23
+ post.delete
24
+ end
25
+ end
26
+
27
+ context 'not persisted' do
28
+ it 'throws an error' do
29
+ post = described_class.new url: 'http://example.com', description: 'Cool site'
30
+ expect { post.delete }.to raise_error('Bookmark was not saved yet')
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delicious::Tags::Methods::All do
4
+ let(:client) do
5
+ Delicious::Client.new do |config|
6
+ config.access_token = 'my-access-token'
7
+ end
8
+ end
9
+
10
+ describe '#all' do
11
+ let(:result) { :success }
12
+
13
+ let(:method) { :get }
14
+ let(:endpoint) { 'https://previous.delicious.com/v1/tags/get' }
15
+ let(:action) { client.tags.all }
16
+
17
+ let(:success_body) do
18
+ <<-EOT
19
+ <?xml version="1.0" encoding="UTF-8"?>
20
+ <tags>
21
+ <tag count="78" tag="ruby"/>
22
+ <tag count="70" tag="rails"/>
23
+ <tag count="58" tag="css"/>
24
+ </tags>
25
+ EOT
26
+ end
27
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="access denied"/>' }
28
+
29
+ before do
30
+ body = result == :failure ? failure_body : success_body
31
+ @request = stub_request(method, endpoint)
32
+ .to_return body: body, headers: {'Content-Type' => 'text/xml; charset=UTF-8'}
33
+ end
34
+
35
+ it_behaves_like 'api action'
36
+
37
+ context 'success' do
38
+ it 'returns 3 tags' do
39
+ expect(action.count).to eq 3
40
+ end
41
+
42
+ describe 'first tag' do
43
+ subject { action[0] }
44
+
45
+ it { should be_an_instance_of Delicious::Tag }
46
+
47
+ it 'has name' do
48
+ expect(subject.name).to eq 'ruby'
49
+ end
50
+
51
+ it 'has count' do
52
+ expect(subject.count).to eq 78
53
+ end
54
+
55
+ it 'is possible to delete' do
56
+ expect(client.tags).to receive(:delete).with 'ruby'
57
+ subject.delete
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'failure' do
63
+ let(:result) { :failure }
64
+
65
+ it 'throws an error' do
66
+ expect { action }.to raise_error Delicious::Error
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delicious::Tags::Methods::Delete do
4
+ let(:client) do
5
+ Delicious::Client.new do |config|
6
+ config.access_token = 'my-access-token'
7
+ end
8
+ end
9
+
10
+ describe '#delete' do
11
+ let(:result) { :success }
12
+
13
+ let(:method) { :post }
14
+ let(:endpoint) { 'https://previous.delicious.com/v1/tags/delete' }
15
+ let(:action) { client.tags.delete 'ruby' }
16
+
17
+ let(:success_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="done"/>' }
18
+ let(:failure_body) { '<?xml version="1.0" encoding="UTF-8"?><result code="done"/>' }
19
+
20
+ before do
21
+ body = result == :failure ? failure_body : success_body
22
+ @request = stub_request(method, endpoint)
23
+ .to_return body: body, headers: {'Content-Type' => 'text/xml; charset=UTF-8'}
24
+ end
25
+
26
+ it_behaves_like 'api action'
27
+
28
+ it 'sends request' do
29
+ action
30
+ expect(WebMock).to have_requested(:post, endpoint).with { |r| assert_param(r, 'tag', 'ruby') }
31
+ end
32
+
33
+ context 'success' do
34
+ it 'return true' do
35
+ expect(action).to eq true
36
+ end
37
+ end
38
+
39
+ context 'failure' do
40
+ let(:result) { :failure }
41
+
42
+ it 'return true' do
43
+ expect(action).to eq true
44
+ end
45
+ end
46
+ end
47
+ end