transmission-rpc-ruby-ext 0.1.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 (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