transmission-rpc-ruby-ext 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +3 -0
  6. data/Gemfile +10 -0
  7. data/Gemfile.lock +62 -0
  8. data/LICENSE +19 -0
  9. data/README.md +173 -0
  10. data/Rakefile +5 -0
  11. data/lib/transmission.rb +11 -0
  12. data/lib/transmission/arguments.rb +50 -0
  13. data/lib/transmission/arguments/location_set.rb +11 -0
  14. data/lib/transmission/arguments/session_set.rb +56 -0
  15. data/lib/transmission/arguments/torrent_add.rb +24 -0
  16. data/lib/transmission/arguments/torrent_set.rb +32 -0
  17. data/lib/transmission/config.rb +18 -0
  18. data/lib/transmission/extensions.rb +4 -0
  19. data/lib/transmission/extensions/torrent_actions.rb +15 -0
  20. data/lib/transmission/extensions/torrent_attributes.rb +103 -0
  21. data/lib/transmission/extensions/torrent_status.rb +42 -0
  22. data/lib/transmission/extensions/transmission.rb +82 -0
  23. data/lib/transmission/fields.rb +41 -0
  24. data/lib/transmission/fields/session_get.rb +61 -0
  25. data/lib/transmission/fields/session_stats.rb +15 -0
  26. data/lib/transmission/fields/torrent_get.rb +76 -0
  27. data/lib/transmission/model.rb +8 -0
  28. data/lib/transmission/model/session.rb +48 -0
  29. data/lib/transmission/model/session_stats.rb +28 -0
  30. data/lib/transmission/model/torrent.rb +152 -0
  31. data/lib/transmission/rpc.rb +116 -0
  32. data/lib/transmission/rpc/connector.rb +67 -0
  33. data/lib/transmission/utils.rb +24 -0
  34. data/spec/helpers/stubs.rb +82 -0
  35. data/spec/spec_helper.rb +13 -0
  36. data/spec/transmission/arguments_spec.rb +78 -0
  37. data/spec/transmission/fields_spec.rb +60 -0
  38. data/spec/transmission/model/session_spec.rb +85 -0
  39. data/spec/transmission/model/torrent_spec.rb +345 -0
  40. data/spec/transmission/rpc/connector_spec.rb +82 -0
  41. data/spec/transmission/rpc_spec.rb +33 -0
  42. data/spec/transmission/utils_spec.rb +69 -0
  43. data/transmission-rpc-ruby-ext.gemspec +17 -0
  44. metadata +141 -0
@@ -0,0 +1,24 @@
1
+ module Transmission
2
+ module Utils
3
+ def is_valid_key?(key, attributes)
4
+ !attributes.select do |attribute|
5
+ option_keys(key).include? attribute[:field]
6
+ end.empty?
7
+ end
8
+
9
+ def option_keys(key)
10
+ split = key.to_s.split '_'
11
+ dashed = split.join '-'
12
+ camelcase = split.collect(&:capitalize).join
13
+ camelcase = camelcase[0].downcase + camelcase[1..-1]
14
+ [dashed, camelcase]
15
+ end
16
+
17
+ def option_key(key, attributes)
18
+ selected = attributes.select do |attribute|
19
+ option_keys(key).include? attribute[:field]
20
+ end
21
+ selected.first[:field] unless selected.empty?
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,82 @@
1
+ module Stubs
2
+ def stub_rpc_request(options = {})
3
+ host = options[:host] || 'localhost'
4
+ port = options[:port] || 9091
5
+ path = options[:path] || '/transmission/rpc'
6
+ scheme = options[:ssl] ? 'https' : 'http'
7
+ stub_request(:post, "#{scheme}://#{host}:#{port}#{path}")
8
+ end
9
+
10
+ def stub_get_torrent(body, torrents)
11
+ stub_rpc_request
12
+ .with(body: torrent_get_body(body))
13
+ .to_return(successful_response( arguments: { torrents: torrents } ))
14
+ end
15
+
16
+ def stub_get_session(fields)
17
+ stub_rpc_request
18
+ .with(body: session_get_body( fields: fields ))
19
+ .to_return(successful_response)
20
+ end
21
+
22
+ def stub_set_location_torrent(body)
23
+ stub_rpc_request
24
+ .with(body: torrent_set_location_body(body))
25
+ .to_return(successful_response)
26
+ end
27
+
28
+ def torrent_get_body(arguments = {})
29
+ args = { fields: Transmission::Fields::TorrentGet.new.to_fields }.merge(arguments)
30
+ { method: 'torrent-get', arguments: args }.to_json
31
+ end
32
+
33
+ def torrent_add_body(arguments = {})
34
+ { method: 'torrent-add', arguments: arguments }.to_json
35
+ end
36
+
37
+ def torrent_remove_body(arguments = {})
38
+ { method: 'torrent-remove', arguments: arguments }.to_json
39
+ end
40
+
41
+ def torrent_set_body(arguments = {})
42
+ { method: 'torrent-set', arguments: arguments }.to_json
43
+ end
44
+
45
+ def torrent_set_location_body(arguments = {})
46
+ { method: 'torrent-set-location', arguments: arguments }.to_json
47
+ end
48
+
49
+ def torrent_method_body(method, arguments)
50
+ { method: method, arguments: arguments }.to_json
51
+ end
52
+
53
+ def session_get_body(arguments = {})
54
+ { method: 'session-get', arguments: arguments }.to_json
55
+ end
56
+
57
+ def session_set_body(arguments = {})
58
+ { method: 'session-set', arguments: arguments }.to_json
59
+ end
60
+
61
+ def session_stats_body(arguments = {})
62
+ { method: 'session-stats', arguments: arguments }.to_json
63
+ end
64
+
65
+ def successful_response(options = {})
66
+ body = { result: 'success', arguments: (options[:arguments] || {}) }
67
+ { status: 200, body: body.to_json, headers: options[:headers] || {} }
68
+ end
69
+
70
+ def unsuccessful_response(options = {})
71
+ body = { result: (options[:result] || ''), arguments: (options[:arguments] || {}) }
72
+ { status: 200, body: body.to_json, headers: options[:headers] || {} }
73
+ end
74
+
75
+ def unauthorized_response(options = {})
76
+ { status: 401, body: (options[:body] || {}).to_json, headers: options[:headers] || {} }
77
+ end
78
+
79
+ def conflict_response(options = {})
80
+ { status: 409, body: (options[:body] || {}).to_json, headers: options[:headers] || {} }
81
+ end
82
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'webmock/rspec'
3
+ require 'coveralls'
4
+ Coveralls.wear!
5
+
6
+ require_relative File.join('..', 'lib', 'transmission')
7
+ require_relative File.join('helpers', 'stubs')
8
+
9
+ ENV['TESTING'] = 'true'
10
+
11
+ RSpec.configure do |config|
12
+ config.include Stubs
13
+ end
@@ -0,0 +1,78 @@
1
+ describe Transmission::Arguments do
2
+ [
3
+ { className: Transmission::Arguments::SessionSet, arguments: { 'alt-speed-down' => 5 } },
4
+ { className: Transmission::Arguments::TorrentAdd, arguments: { 'paused' => true } },
5
+ { className: Transmission::Arguments::TorrentSet, arguments: { 'location' => '/location' } }
6
+ ].each do |klass|
7
+
8
+ describe klass[:className].to_s do
9
+ describe '#new' do
10
+ it 'should create an instance with correct arguments' do
11
+ instance = klass[:className].new
12
+ expect(instance.arguments.size).to eq(klass[:className]::ATTRIBUTES.size)
13
+ end
14
+
15
+ it 'should create an instance with given arguments' do
16
+ instance = klass[:className].new klass[:arguments]
17
+ expect(instance.arguments.size).to eq(1)
18
+ end
19
+
20
+ it 'should raise an error if invalid arguments is given' do
21
+ expect {
22
+ klass[:className].new 'i-dont-exist' => ''
23
+ }.to raise_error(Transmission::Arguments::InvalidArgument)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '.is_valid?' do
30
+ describe 'with valid key' do
31
+ it 'should return true' do
32
+ stub_const('Transmission::Arguments::ATTRIBUTES', [{ field: 'test-me' }])
33
+ expect(Transmission::Arguments.is_valid?('test_me')).to eq(true)
34
+ end
35
+ end
36
+
37
+ describe 'with invalid key' do
38
+ it 'should return true' do
39
+ stub_const('Transmission::Arguments::ATTRIBUTES', [{ field: 'test-me' }])
40
+ expect(Transmission::Arguments.is_valid?('testMee')).to eq(false)
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '.real_key' do
46
+ describe 'with valid key' do
47
+ it 'should return real key' do
48
+ stub_const('Transmission::Arguments::ATTRIBUTES', [{ field: 'test-me' }])
49
+ expect(Transmission::Arguments.real_key('test_me')).to eq('test-me')
50
+ end
51
+ end
52
+
53
+ describe 'with invalid key' do
54
+ it 'should return nil' do
55
+ stub_const('Transmission::Arguments::ATTRIBUTES', [{ field: 'test-me' }])
56
+ expect(Transmission::Arguments.real_key('testMee')).to eq(nil)
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '.filter' do
62
+ describe 'with valid keys' do
63
+ it 'should filter the correct keys' do
64
+ stub_const('Transmission::Arguments::ATTRIBUTES', [{ field: 'test-me' }])
65
+ hash = { 'test-me' => 'some-value' }
66
+ expect(Transmission::Arguments.filter(hash)).to eq(hash)
67
+ end
68
+ end
69
+
70
+ describe 'with invalid keys' do
71
+ it 'should filter out the incorrect keys' do
72
+ stub_const('Transmission::Arguments::ATTRIBUTES', [{ field: 'test-me' }])
73
+ hash = { 'test-me' => 'some-value', 'incorrect-key' => 'some-value' }
74
+ expect(Transmission::Arguments.filter(hash)).to eq('test-me' => 'some-value')
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,60 @@
1
+ describe Transmission::Fields do
2
+ [
3
+ { className: Transmission::Fields::SessionGet, fields: ['alt-speed-down'] },
4
+ { className: Transmission::Fields::TorrentGet, fields: ['doneDate'] },
5
+ { className: Transmission::Fields::SessionStats, fields: ['activeTorrentCount'] }
6
+ ].each do |klass|
7
+
8
+ describe klass[:className].to_s do
9
+ describe '#new' do
10
+ it 'should create an instance with correct fields' do
11
+ instance = klass[:className].new
12
+ expect(instance.fields.size).to eq(klass[:className]::ATTRIBUTES.size)
13
+ end
14
+
15
+ it 'should create an instance with given fields' do
16
+ instance = klass[:className].new klass[:fields]
17
+ expect(instance.fields.size).to eq(1)
18
+ end
19
+
20
+ it 'should raise an error if invalid arguments is given' do
21
+ expect {
22
+ klass[:className].new 'i-dont-exist' => ''
23
+ }.to raise_error(Transmission::Fields::InvalidField)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '.is_valid?' do
30
+ describe 'with valid key' do
31
+ it 'should return true' do
32
+ stub_const('Transmission::Fields::ATTRIBUTES', [{ field: 'test-me' }])
33
+ expect(Transmission::Fields.is_valid?('test_me')).to eq(true)
34
+ end
35
+ end
36
+
37
+ describe 'with invalid key' do
38
+ it 'should return true' do
39
+ stub_const('Transmission::Fields::ATTRIBUTES', [{ field: 'test-me' }])
40
+ expect(Transmission::Fields.is_valid?('testMee')).to eq(false)
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '.real_key' do
46
+ describe 'with valid key' do
47
+ it 'should return real key' do
48
+ stub_const('Transmission::Fields::ATTRIBUTES', [{ field: 'test-me' }])
49
+ expect(Transmission::Fields.real_key('test_me')).to eq('test-me')
50
+ end
51
+ end
52
+
53
+ describe 'with invalid key' do
54
+ it 'should return nil' do
55
+ stub_const('Transmission::Fields::ATTRIBUTES', [{ field: 'test-me' }])
56
+ expect(Transmission::Fields.real_key('testMee')).to eq(nil)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,85 @@
1
+ describe Transmission::Model::Session do
2
+ describe '.get' do
3
+ describe 'with configuration' do
4
+ before :each do
5
+ Transmission::Config.set
6
+ stub_get_session(Transmission::Fields::SessionGet.new.to_fields)
7
+ end
8
+
9
+ it 'should return a session model' do
10
+ session = Transmission::Model::Session.get
11
+ expect(session).to be_a(Transmission::Model::Session)
12
+ end
13
+ end
14
+
15
+ describe 'with connector' do
16
+ before :each do
17
+ @rpc = Transmission::RPC.new
18
+ stub_get_session(Transmission::Fields::SessionGet.new.to_fields)
19
+ end
20
+
21
+ it 'should return an array of Torrent models' do
22
+ session = Transmission::Model::Session.get connector: @rpc
23
+ expect(session).to be_a(Transmission::Model::Session)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#save!' do
29
+ let(:rpc) { Transmission::RPC.new }
30
+
31
+ before :each do
32
+ stub_const('Transmission::Arguments::SessionSet::ATTRIBUTES', [{ field: 'name' }])
33
+ stub_get_session(Transmission::Fields::SessionGet.new.to_fields)
34
+ stub_rpc_request
35
+ .with(body: session_set_body(name: 'new value'))
36
+ .to_return(successful_response)
37
+ end
38
+
39
+ it 'should send the right parameters' do
40
+ session = Transmission::Model::Session.get connector: rpc
41
+ session.name = 'new value'
42
+ session.save!
43
+ end
44
+ end
45
+
46
+ describe '#to_json' do
47
+ let(:session) { Transmission::Model::Session.new({ 'id' => 1 }, nil) }
48
+
49
+ it 'should return its attributes' do
50
+ expect(session.to_json).to eq('id' => 1)
51
+ end
52
+ end
53
+
54
+ describe '#method_missing' do
55
+ let(:session) { Transmission::Model::Session.new({ 'id' => 1, 'name' => 'some name', 'some-key' => 'some-value' }, nil) }
56
+
57
+ before :each do
58
+ stub_const('Transmission::Fields::SessionGet::ATTRIBUTES', [{ field: 'id' }, { field: 'name' }, { field: 'some-key' }])
59
+ stub_const('Transmission::Arguments::SessionSet::ATTRIBUTES', [{ field: 'name' }])
60
+ end
61
+
62
+ describe 'with existing attributes' do
63
+ it 'should return the correct values' do
64
+ expect(session.id).to eq(1)
65
+ expect(session.name).to eq('some name')
66
+ expect(session.some_key).to eq('some-value')
67
+ end
68
+
69
+ it 'should set the correct values' do
70
+ session.name = 'ok'
71
+ expect(session.name).to eq('ok')
72
+ end
73
+ end
74
+
75
+ describe 'with none existing attributes' do
76
+ it 'should raise error' do
77
+ expect { session.i_dont_exist }.to raise_error(NoMethodError)
78
+ end
79
+
80
+ it 'should raise error' do
81
+ expect { session.i_dont_exist = 'some value' }.to raise_error(NoMethodError)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,345 @@
1
+ describe Transmission::Model::Torrent do
2
+ describe '.all' do
3
+ describe 'with configuration' do
4
+ before :each do
5
+ Transmission::Config.set
6
+ stub_get_torrent({}, [{ id: 1 }])
7
+ end
8
+
9
+ it 'should return a Torrent model instance' do
10
+ torrents = Transmission::Model::Torrent.all
11
+ expect(torrents).to be_a(Transmission::Model::Torrent)
12
+ end
13
+ end
14
+
15
+ describe 'with connector' do
16
+ before :each do
17
+ @rpc = Transmission::RPC.new
18
+ stub_rpc_request
19
+ .with(body: torrent_get_body)
20
+ .to_return(successful_response( arguments: { torrents: [{ id: 1 }] }))
21
+ end
22
+
23
+ it 'should return a Torrent model instance' do
24
+ torrents = Transmission::Model::Torrent.all connector: @rpc
25
+ expect(torrents).to be_a(Transmission::Model::Torrent)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '.find' do
31
+ describe 'with configuration' do
32
+ before :each do
33
+ Transmission::Config.set
34
+ stub_get_torrent({ ids: [1] }, [{ id: 1 }])
35
+ end
36
+
37
+ it 'should return a Torrent instance' do
38
+ torrent = Transmission::Model::Torrent.find 1
39
+ expect(torrent).to be_a(Transmission::Model::Torrent)
40
+ end
41
+ end
42
+
43
+ describe 'with connector' do
44
+ before :each do
45
+ @rpc = Transmission::RPC.new
46
+ stub_get_torrent({ ids: [1] }, [{ id: 1 }])
47
+ end
48
+
49
+ it 'should return a Torrent instance' do
50
+ torrent = Transmission::Model::Torrent.find 1, connector: @rpc
51
+ expect(torrent).to be_a(Transmission::Model::Torrent)
52
+ end
53
+ end
54
+
55
+ describe 'with invalid id' do
56
+ before :each do
57
+ @rpc = Transmission::RPC.new
58
+ stub_get_torrent({ ids: [1] }, [])
59
+ end
60
+
61
+ it 'should raise error' do
62
+ expect {
63
+ Transmission::Model::Torrent.find 1, connector: @rpc
64
+ }.to raise_error(Transmission::Model::Torrent::TorrentNotFoundError)
65
+ end
66
+ end
67
+
68
+ describe 'with multiple ids' do
69
+ before :each do
70
+ @rpc = Transmission::RPC.new
71
+ stub_get_torrent({ ids: [1, 2] }, [{ id: 1 }, { id: 2 }])
72
+ end
73
+
74
+ it 'should return a Torrent model instance' do
75
+ torrent = Transmission::Model::Torrent.find [1, 2], connector: @rpc
76
+ expect(torrent).to be_a(Transmission::Model::Torrent)
77
+ end
78
+
79
+ it 'should remember all ids' do
80
+ torrent = Transmission::Model::Torrent.find [1, 2], connector: @rpc
81
+ expect(torrent.ids).to eq([1, 2])
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '.add' do
87
+ describe 'with configuration' do
88
+ before :each do
89
+ Transmission::Config.set
90
+ stub_rpc_request
91
+ .with(body: torrent_add_body(filename: 'torrent_file'))
92
+ .to_return(successful_response(arguments: { 'torrent-added' => { id: 1 } }))
93
+ stub_get_torrent({ ids: [1] }, [{ id: 1 }])
94
+ end
95
+
96
+ it 'should return a Torrent instance' do
97
+ torrent = Transmission::Model::Torrent.add arguments: { filename: 'torrent_file' }
98
+ expect(torrent).to be_a(Transmission::Model::Torrent)
99
+ end
100
+ end
101
+
102
+ describe 'when torrent is a duplicate' do
103
+ before :each do
104
+ Transmission::Config.set
105
+ stub_rpc_request
106
+ .with(body: torrent_add_body(filename: 'torrent_file'))
107
+ .to_return(unsuccessful_response(result: 'duplicate torrent'))
108
+ end
109
+
110
+ it 'should raise error' do
111
+ expect {
112
+ Transmission::Model::Torrent.add arguments: { filename: 'torrent_file' }
113
+ }.to raise_error(Transmission::RPC::Connector::ConnectionError)
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '.start_all!' do
119
+ before :each do
120
+ Transmission::Config.set
121
+ stub_rpc_request
122
+ .with(body: torrent_method_body('torrent-start', {}))
123
+ .to_return(successful_response)
124
+ end
125
+
126
+ it 'should start all torrents' do
127
+ Transmission::Model::Torrent.start_all!
128
+ end
129
+ end
130
+
131
+ describe '.stop_all!' do
132
+ before :each do
133
+ Transmission::Config.set
134
+ stub_rpc_request
135
+ .with(body: torrent_method_body('torrent-stop', {}))
136
+ .to_return(successful_response)
137
+ end
138
+
139
+ it 'should start all torrents' do
140
+ Transmission::Model::Torrent.stop_all!
141
+ end
142
+ end
143
+
144
+ describe '#set_location' do
145
+ before :each do
146
+ Transmission::Config.set
147
+ stub_get_torrent({ ids: [1] }, [{ id: 1 }])
148
+ stub_set_location_torrent(location: '/some/location', move: false, ids: [1])
149
+ end
150
+
151
+ it 'should set a new location' do
152
+ torrent = Transmission::Model::Torrent.find 1
153
+ torrent.set_location '/some/location'
154
+ end
155
+ end
156
+
157
+ describe '#delete!' do
158
+ describe 'with configuration' do
159
+ before :each do
160
+ Transmission::Config.set
161
+ stub_get_torrent({ ids: [1] }, [{ id: 1 }])
162
+ stub_rpc_request
163
+ .with(body: torrent_remove_body(:ids => [1], 'delete-local-data' => false))
164
+ .to_return(successful_response(arguments: { torrents: [{ id: 1 }] }))
165
+ end
166
+
167
+ it 'should remove the torrent file' do
168
+ torrent = Transmission::Model::Torrent.find 1
169
+ torrent.delete!
170
+ expect(torrent.deleted).to eq(true)
171
+ end
172
+ end
173
+
174
+ describe 'with connector' do
175
+ before :each do
176
+ @rpc = Transmission::RPC.new
177
+ stub_get_torrent({ ids: [1] }, [{ id: 1 }])
178
+ stub_rpc_request
179
+ .with(body: torrent_remove_body(:ids => [1], 'delete-local-data' => false))
180
+ .to_return(successful_response(arguments: { torrents: [{ id: 1 }] }))
181
+ end
182
+
183
+ it 'should remove the torrent file' do
184
+ torrent = Transmission::Model::Torrent.find 1, connector: @rpc
185
+ torrent.delete!
186
+ expect(torrent.deleted).to eq(true)
187
+ end
188
+ end
189
+
190
+ describe 'with multiple ids' do
191
+ before :each do
192
+ @rpc = Transmission::RPC.new
193
+ stub_get_torrent({ ids: [1, 2] }, [{ id: 1 }, { id: 2 }])
194
+ stub_rpc_request
195
+ .with(body: torrent_remove_body(:ids => [1, 2], 'delete-local-data' => false))
196
+ .to_return(successful_response(arguments: { torrents: [{ id: 1 }, { id: 2 }]} ))
197
+ end
198
+
199
+ it 'should remove the torrent files' do
200
+ torrent = Transmission::Model::Torrent.find [1, 2], connector: @rpc
201
+ torrent.delete!
202
+ expect(torrent.deleted).to eq(true)
203
+ end
204
+ end
205
+ end
206
+
207
+ describe '#is_multi?' do
208
+ let(:torrents) { Transmission::Model::Torrent.new([{'id' => 1}, {'id' => 2}], nil) }
209
+ let(:torrent) { Transmission::Model::Torrent.new([{'id' => 1}], nil) }
210
+
211
+ describe 'with multiple torrents' do
212
+ it 'should return true' do
213
+ expect(torrents.is_multi?).to eq(true)
214
+ end
215
+ end
216
+
217
+ describe 'with single torrent' do
218
+ it 'should return false' do
219
+ expect(torrent.is_multi?).to eq(false)
220
+ end
221
+ end
222
+ end
223
+
224
+ describe '#to_json' do
225
+ let(:torrents) { Transmission::Model::Torrent.new([{ 'id' => 1 }, { 'id' => 2 }], nil) }
226
+ let(:torrent) { Transmission::Model::Torrent.new([{ 'id' => 1 }], nil) }
227
+
228
+ describe 'with multiple torrents' do
229
+ it 'should return true' do
230
+ expect(torrents.to_json).to eq([{ 'id' => 1 }, { 'id' => 2 }])
231
+ end
232
+ end
233
+
234
+ describe 'with single torrent' do
235
+ it 'should return false' do
236
+ expect(torrent.to_json).to eq({ 'id' => 1 })
237
+ end
238
+ end
239
+ end
240
+
241
+ describe '#completed?' do
242
+ let(:completed_torrent) { Transmission::Model::Torrent.new([{ 'id' => 1, 'percentDone' => 1 }], nil) }
243
+ let(:incomplete_torrent) { Transmission::Model::Torrent.new([{ 'id' => 1, 'percentDone' => 0.5 }], nil) }
244
+
245
+ describe 'with completed torrent' do
246
+ it 'should return true' do
247
+ expect(completed_torrent.completed?).to eq(true)
248
+ end
249
+ end
250
+
251
+ describe 'with unfinished torrent' do
252
+ it 'should return false' do
253
+ expect(incomplete_torrent.completed?).to eq(false)
254
+ end
255
+ end
256
+ end
257
+
258
+ describe '#method_missing' do
259
+ let(:torrent) { Transmission::Model::Torrent.new([{'id' => 1, 'name' => 'some name', 'some-key' => 'some-value'}], nil) }
260
+
261
+ before :each do
262
+ stub_const("Transmission::Fields::TorrentGet::ATTRIBUTES", [{field: 'id'}, {field: 'name'}, {field: 'some-key'}])
263
+ stub_const("Transmission::Arguments::TorrentSet::ATTRIBUTES", [{field: 'name'}])
264
+ end
265
+
266
+ describe 'with existing attributes' do
267
+ it 'should return the correct values' do
268
+ expect(torrent.id).to eq(1)
269
+ expect(torrent.name).to eq('some name')
270
+ expect(torrent.some_key).to eq('some-value')
271
+ end
272
+
273
+ it 'should set the correct values' do
274
+ torrent.name = 'ok'
275
+ expect(torrent.name).to eq('ok')
276
+ end
277
+ end
278
+
279
+ describe 'with none existing attributes' do
280
+ it 'should raise error' do
281
+ expect {
282
+ torrent.i_dont_exist
283
+ }.to raise_error(NoMethodError)
284
+ end
285
+
286
+ it 'should raise error' do
287
+ expect {
288
+ torrent.i_dont_exist = 'some value'
289
+ }.to raise_error(NoMethodError)
290
+ end
291
+ end
292
+ end
293
+
294
+ describe '#save!' do
295
+ let(:rpc) {Transmission::RPC.new}
296
+
297
+ before :each do
298
+ stub_const("Transmission::Arguments::TorrentSet::ATTRIBUTES", [{field: 'name'}, {field: 'ids'}])
299
+ stub_get_torrent({ids: [1]}, [{id: 1, name: 'test', comment: 'comment'}])
300
+ stub_rpc_request
301
+ .with(body: torrent_set_body({name: 'new value', ids: [1]}))
302
+ .to_return(successful_response)
303
+ end
304
+
305
+ it 'should send the right parameters' do
306
+ torrent = Transmission::Model::Torrent.find 1, connector: rpc
307
+ torrent.name = 'new value'
308
+ torrent.save!
309
+ end
310
+ end
311
+
312
+ [
313
+ {method: 'start!', rpc_method: 'torrent-start'},
314
+ {method: 'start_now!', rpc_method: 'torrent-start-now'},
315
+ {method: 'stop!', rpc_method: 'torrent-stop'},
316
+ {method: 'verify!', rpc_method: 'torrent-verify'},
317
+ {method: 're_announce!', rpc_method: 'torrent-reannounce'},
318
+ {method: 'move_up!', rpc_method: 'queue-move-up'},
319
+ {method: 'move_down!', rpc_method: 'queue-move-down'},
320
+ {method: 'move_top!', rpc_method: 'queue-move-top'},
321
+ {method: 'move_bottom!', rpc_method: 'queue-move-bottom'}
322
+ ].each do |object|
323
+ describe "##{object[:method]}" do
324
+ let(:rpc) {Transmission::RPC.new}
325
+
326
+ [
327
+ {ids: [1], response: [{id: 1}], text: ''},
328
+ {ids: [1, 2], response: [{id: 1}, {id: 2}], text: 'with multiple ids'}
329
+ ].each do |args|
330
+ before :each do
331
+ stub_get_torrent({ids: args[:ids]}, args[:response])
332
+ stub_rpc_request
333
+ .with(body: torrent_method_body(object[:rpc_method], {ids: args[:ids]}))
334
+ .to_return(successful_response)
335
+ end
336
+
337
+ it "should #{object[:method]} torrent #{args[:text]}" do
338
+ torrent = Transmission::Model::Torrent.find args[:ids], connector: rpc
339
+ torrent.send object[:method].to_sym
340
+ end
341
+ end
342
+ end
343
+ end
344
+
345
+ end