torrents 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe Container::Shared do
4
+ before(:each) do
5
+ @shared = Container::Shared.new
6
+ end
7
+ context "the download method" do
8
+ it "should return an empty string when trying to download an empty or non valid URL" do
9
+ @shared.download("non_working_url").should be_empty
10
+ @shared.download(nil).should be_empty
11
+ end
12
+
13
+ it "should return the content of the site if called with the right url" do
14
+ RestClient.should_receive(:get).with("http://example.com", {:timeout => 10, :cookies => nil}).exactly(1).times.and_return("123")
15
+ @shared.download("http://example.com").should eq("123")
16
+ end
17
+ end
18
+
19
+ context "the error method" do
20
+ it "should have a error method" do
21
+ lambda {
22
+ @shared.error("some message")
23
+ @shared.error("some message", "other")
24
+ }.should_not raise_error(Exception)
25
+ end
26
+ end
27
+
28
+ context "the inner_call" do
29
+ before(:each) do
30
+ @load = mock(Object)
31
+ end
32
+
33
+ it "should call an example method with no arguments" do
34
+ @shared.should_receive(:load).and_return(@load)
35
+ @load.should_receive(:example).with.and_return("value") # No arguments
36
+ @shared.inner_call(:example).should eq("value")
37
+ end
38
+
39
+ it "should call an example method with arguments" do
40
+ @shared.should_receive(:load).and_return(@load)
41
+ @load.should_receive(:example).with("abc").and_return("value") # No arguments
42
+ @shared.inner_call(:example, "abc").should eq("value")
43
+ end
44
+
45
+ it "should call an example and rescue an exception" do
46
+ @shared.should_receive(:load).and_return(lambda{
47
+ raise NoMethodError.new
48
+ })
49
+
50
+ @shared.should_receive(:error)
51
+ @shared.should_receive(:default_values).with(:call).and_return("error")
52
+ @shared.inner_call(:call).should eq("error")
53
+ end
54
+
55
+ it "should only catch NoMethodError exception" do
56
+ lambda {
57
+ @shared.should_receive(:load).and_return(lambda{
58
+ raise Exception.new
59
+ })
60
+
61
+ @shared.inner_call(:call).should eq("error")
62
+ }.should raise_error(Exception)
63
+ end
64
+ end
65
+
66
+ context "the default_values method" do
67
+ it "should return the right value" do
68
+ {torrent: "", torrents: [], seeders: 1, title: "", details: ""}.each do |method, value|
69
+ @shared.default_values(method).should eq(value)
70
+ end
71
+ end
72
+
73
+ it "should return an empty string if the value isn't in the hash" do
74
+ @shared.default_values(:random).should eq("")
75
+ end
76
+ end
77
+
78
+ context "the load method" do
79
+ before(:all) do
80
+ class Test < Container::Shared
81
+ def initialize
82
+ @tracker = "the_pirate_bay"
83
+ end
84
+ end
85
+ end
86
+ it "should create a new instance of any string" do
87
+ Test.new.load.should be_instance_of(Trackers::ThePirateBay)
88
+ end
89
+ end
90
+
91
+ context "the url_cleaner method" do
92
+ # Read more about the cleaner here
93
+ # http://stackoverflow.com/questions/4999322/escape-and-download-url-using-ruby
94
+ it "should be able to clean urls" do
95
+ list = {}
96
+ ["{", "}", "|", "\\", "^", "[", "]", "`", " a"].each do |c|
97
+ list.merge!("http://google.com/#{c}" => "http://google.com/#{CGI::escape(c)}")
98
+ end
99
+
100
+ list.each do |url, clean|
101
+ lambda {
102
+ URI.parse(url)
103
+ }.should raise_error(URI::InvalidURIError)
104
+
105
+ lambda {
106
+ URI.parse(@shared.url_cleaner(url)).to_s.should eq(clean)
107
+ }.should_not raise_error(URI::InvalidURIError)
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,9 @@
1
+ require 'rspec'
2
+ require 'torrents'
3
+ require 'torrents/container'
4
+ require 'uri'
5
+ require 'yaml'
6
+
7
+ RSpec.configure do |config|
8
+ config.mock_with :rspec
9
+ end
@@ -0,0 +1,186 @@
1
+ require 'spec_helper'
2
+
3
+ describe Container::Torrent do
4
+ def create_torrent(args = {details: "http://thepiratebay.org/torrent/6173093/", torrent: "http://torrents.thepiratebay.org/6173093/value.torrent", title: "The title", tracker: "the_pirate_bay"})
5
+ Container::Torrent.new(args)
6
+ end
7
+
8
+ def valid_url?(url)
9
+ !! url.match(/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i)
10
+ end
11
+
12
+ def create_torrents(n)
13
+ torrents = []
14
+ n.times do |n|
15
+ torrents << create_torrent({
16
+ details: "http://thepiratebay.org/torrent/617#{n}093/",
17
+ torrent: "http://torrents.thepiratebay.org/617093/value.torrent",
18
+ title: "The title",
19
+ tracker: "the_pirate_bay"
20
+ })
21
+ end
22
+
23
+ torrents
24
+ end
25
+
26
+ def rest_client
27
+ RestClient.should_receive(:get).with("http://thepiratebay.org/torrent/6173093/", {:timeout => 10, :cookies => nil}).at_least(1).times.and_return(File.read('spec/data/the_pirate_bay/details.html'))
28
+ end
29
+
30
+ before(:all) do
31
+ @torrent = create_torrent
32
+ @methods = {:details => String, :torrent => String, :title => String, :seeders => Fixnum, :dead? => [TrueClass, FalseClass]}
33
+ end
34
+
35
+ it "should contain the right accessors" do
36
+ @methods.each do |method, _|
37
+ @torrent.methods.should include(method)
38
+ end
39
+ end
40
+
41
+ it "should have the right return type" do
42
+ rest_client
43
+ @methods.each do |method, type|
44
+ type.class == Array ? (type.should include(@torrent.send(method).class)) : (@torrent.send(method).should be_instance_of(type))
45
+ end
46
+ end
47
+
48
+ it "should have a working valid? method" do
49
+ [["a", "a", ""], ["a", "a", nil], ["a", "a", "<tag>"], ["a", "a", " a"], ["a", "http://google.com", "a"], ["a", "http://google.com.torrent", "a"], ["a", "http://google.com", "a.torrent"]].each do |option|
50
+ option.permutation.to_a.uniq.each do |invalid|
51
+ create_torrent({details: invalid[0], torrent: invalid[1], title: invalid[2], tracker: 'the_pirate_bay'}).should_not be_valid
52
+ end
53
+ end
54
+
55
+ create_torrent({details: "http://google.com/123/", torrent: "http://google.com.torrent", title: "a", tracker: "the_pirate_bay"}).should be_valid
56
+ create_torrent({details: "http://google.com/random/", torrent: "http://google.com.torrent", title: "a", tracker: "the_pirate_bay"}).id.should eq(0)
57
+ end
58
+
59
+ it "should be dead" do
60
+ torrent = create_torrent({details: "a", torrent: "a", title: "a", tracker: "a"})
61
+ torrent.should_receive(:seeders).and_return(0)
62
+ torrent.should be_dead
63
+ end
64
+
65
+ it "should not be dead" do
66
+ torrent = create_torrent
67
+ torrent.should_receive(:seeders).and_return(1)
68
+ torrent.should_not be_dead
69
+ end
70
+
71
+ it "should return the right amount of seeders if it's nil" do
72
+ torrent = create_torrent
73
+ torrent.should_receive(:valid_option?).and_return(false)
74
+ torrent.seeders.should eq(1)
75
+ end
76
+
77
+ it "should return the right amount of seeders if it's set" do
78
+ torrent = create_torrent
79
+ torrent.should_receive(:inner_call).and_return(50)
80
+ torrent.seeders.should eq(50)
81
+ end
82
+
83
+ it "should be able to cache requests" do
84
+ torrent = create_torrent
85
+ torrent.should_receive(:download).exactly(1).times.and_return("")
86
+ 10.times { torrent.seeders }
87
+ end
88
+
89
+ it "should have a id method" do
90
+ torrent = create_torrent
91
+ torrent.id.should eq(6173093)
92
+ end
93
+
94
+ it "should have an id 0 if the details url is invalid" do
95
+ torrent = create_torrent({
96
+ details: "http://thepiratebay.org/torrent/random/",
97
+ torrent: "http://torrents.thepiratebay.org/6173093/value.torrent",
98
+ title: "The title",
99
+ tracker: "the_pirate_bay"
100
+ })
101
+
102
+ torrent.id.should eq(0)
103
+ end
104
+
105
+ it "should have a unique tid (torrent id)" do
106
+ torrents = create_torrents(100)
107
+
108
+ torrents.map!(&:tid)
109
+ lambda do
110
+ torrents.uniq!
111
+ end.should_not change(torrents, :count)
112
+ end
113
+
114
+ it "should have a torrent id method that equals the tid method" do
115
+ create_torrents(100).each do |torrent|
116
+ torrent.torrent_id.should eq(torrent.tid)
117
+ end
118
+ end
119
+
120
+ it "should have a working imdb method" do
121
+ rest_client
122
+
123
+ valid_url?(create_torrent.imdb).should be_true
124
+ create_torrent.imdb.should eq("http://www.imdb.com/title/tt0990407")
125
+ end
126
+
127
+ it "should have a working imdb_id method" do
128
+ rest_client
129
+
130
+ create_torrent.imdb_id.should eq("tt0990407")
131
+ end
132
+
133
+ it "should call the find_movie_by_id if a movie if found" do
134
+ rest_client
135
+ MovieSearcher.should_receive(:find_movie_by_id).with("tt0990407").and_return("123")
136
+
137
+ create_torrent.movie.should eq("123")
138
+ end
139
+
140
+ it "should call the find_by_release_name if no movie was found" do
141
+ torrent = create_torrent
142
+ torrent.should_receive(:imdb_id).and_return(nil)
143
+ torrent.should_receive(:title).and_return("my title")
144
+ MovieSearcher.should_receive(:find_by_release_name).with("my title", :options => {:details => true}).and_return("456")
145
+
146
+ torrent.movie.should eq("456")
147
+ end
148
+
149
+ context "the subtitle method" do
150
+ it "should have a working subtitle method, when a imdb id exists" do
151
+ torrent = create_torrent
152
+ torrent.should_receive(:imdb_id).at_least(1).times.and_return("tt0990407")
153
+ torrent.should_receive(:title).and_return("a subtitle")
154
+ Undertexter.should_receive(:find).with("tt0990407", language: :english).and_return([Struct.new(:title).new("a subtitle")])
155
+
156
+ torrent.subtitle.title.should eq("a subtitle")
157
+ end
158
+
159
+ it "should also work when the imdb_id is nil" do
160
+ torrent = create_torrent
161
+ torrent.should_receive(:imdb_id).at_least(1).times.and_return(nil)
162
+ torrent.subtitle.should be_nil
163
+ end
164
+
165
+ it "should be possible to pass arguments to subtitle" do
166
+ torrent = create_torrent
167
+ torrent.should_receive(:imdb_id).at_least(1).times.and_return("tt0990407")
168
+ torrent.should_receive(:title).and_return("a subtitle")
169
+ Undertexter.should_receive(:find).with("tt0990407", language: :swedish).and_return([Struct.new(:title).new("a subtitle")])
170
+
171
+ torrent.subtitle(:swedish).title.should eq("a subtitle")
172
+ end
173
+ end
174
+
175
+
176
+ it "should have a working title, even when the title is empty from the beginning" do
177
+ torrent = create_torrent
178
+ torrent.title.should eq("The title")
179
+ end
180
+
181
+ it "should have a working torrent method, even when the torrent is empty from the beginning " do
182
+ torrent = create_torrent
183
+ valid_url?(torrent.torrent).should be_true
184
+ torrent.torrent.match(/\.torrent$/)
185
+ end
186
+ end
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+
3
+ describe Torrents do
4
+ def rest_client(url, type)
5
+ RestClient.should_receive(:get).with(url, {:timeout => 10, :cookies => nil}).any_number_of_times.and_return(File.read("spec/data/the_pirate_bay/#{type}.html"))
6
+ end
7
+
8
+ before(:each) do
9
+ @torrents = Torrents.the_pirate_bay
10
+ end
11
+
12
+ context "the exists? method" do
13
+ it "should know if a tracker exists or not" do
14
+ @torrents.exists?("the_pirate_bay").should be_true
15
+ @torrents.exists?("random").should be_false
16
+ end
17
+ end
18
+
19
+ context "the content method" do
20
+ it "should return a nokogiri object" do
21
+ @torrents.should_receive(:url).and_return("data")
22
+ @torrents.should_receive(:download).with("data").and_return("more data")
23
+ @torrents.content.should be_instance_of(Nokogiri::HTML::Document)
24
+ end
25
+ end
26
+
27
+ context "the inner_page method" do
28
+ it "should not care about the order of the page, high" do
29
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(10)
30
+ @torrents.page(1)
31
+ @torrents.inner_page.should eq("10")
32
+ end
33
+
34
+ it "should return the pre defined value" do
35
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(99)
36
+ @torrents.inner_page.should eq("99")
37
+ end
38
+
39
+ it "should not care about the order of the page, low" do
40
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(0)
41
+ @torrents.page(1)
42
+ @torrents.inner_page.should eq("0")
43
+ end
44
+
45
+ it "should not care about the order of the page, low again" do
46
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(1)
47
+ @torrents.page(1)
48
+ @torrents.inner_page.should eq("1")
49
+ end
50
+
51
+ it "should not care about the order of the page, if the page isn't specified, one" do
52
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(1)
53
+ @torrents.inner_page.should eq("1")
54
+ end
55
+
56
+ it "should not care about the order of the page, if the page isn't specified, high" do
57
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(10)
58
+ @torrents.inner_page.should eq("10")
59
+ end
60
+
61
+ it "should not care about the order of the page, if the page isn't specified, zero" do
62
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(0)
63
+ @torrents.inner_page.should eq("0")
64
+ end
65
+
66
+ it "should raise an exception if the page number is lower then 0" do
67
+ @torrents.should_receive(:inner_start_page_index).any_number_of_times.and_return(0)
68
+ lambda {
69
+ @torrents.page(0)
70
+ }.should raise_error(ArgumentError, "To low page value, remember that the first page has the value 1")
71
+ end
72
+ end
73
+
74
+ context "the url method" do
75
+ it "should return the correct url when the searching" do
76
+ @torrents.should_receive(:inner_page).and_return("3")
77
+ @torrents.search("search")
78
+ @torrents.should_receive(:send).and_return("before_<SEARCH>_middle_<PAGE>_after")
79
+ @torrents.url.should eq("before_search_middle_3_after")
80
+ end
81
+
82
+ it "should work when not searching" do
83
+ @torrents.should_receive(:inner_page).and_return("3")
84
+ @torrents.should_receive(:send).and_return("before_middle_<PAGE>_after")
85
+ @torrents.url.should eq("before_middle_3_after")
86
+ end
87
+
88
+ it "should be possible to list torrents based on a category" do
89
+ @torrents.category(:movies).page(100).url.should eq("http://thepiratebay.org/browse/201/99/3")
90
+ end
91
+
92
+ it "should raise an exception if trying to fetch a non existing category" do
93
+ lambda {
94
+ @torrents.category(:random).page(100).url
95
+ }.should raise_error(NotImplementedError)
96
+ end
97
+ end
98
+
99
+ context "the add, page, debugger, search method" do
100
+ it "add" do
101
+ @torrents.add("random").should be_instance_of(Torrents)
102
+ end
103
+
104
+ it "page" do
105
+ @torrents.page(10).should be_instance_of(Torrents)
106
+ end
107
+
108
+ it "debugger" do
109
+ @torrents.debugger(true).should be_instance_of(Torrents)
110
+ end
111
+
112
+ it "search" do
113
+ @torrents.search("value").should be_instance_of(Torrents)
114
+ end
115
+ end
116
+
117
+ context "the method_missing missing" do
118
+ before(:each) do
119
+ @torrent = mock(Object)
120
+ end
121
+
122
+ it "should call inner_call when calling method_missing" do
123
+ @torrents.should_receive(:inner_call).with(:example, "a").and_return("b")
124
+ @torrents.method_missing(:inner_example, "a").should eq("b")
125
+ end
126
+
127
+ it "should raise an exception" do
128
+ lambda {
129
+ @torrents.method_missing(:example, "a")
130
+ }.should raise_error(NoMethodError)
131
+ end
132
+
133
+ it "should also work with the static method" do
134
+ Torrents.should_receive(:new).and_return(@torrent)
135
+ @torrent.should_receive(:exists?).and_return(true)
136
+ @torrent.should_receive(:add).and_return("some")
137
+ Torrents.a_random_method.should eq("some")
138
+ end
139
+
140
+ it "should also raise an exception" do
141
+ Torrents.should_receive(:new).and_return(@torrent)
142
+ @torrent.should_receive(:exists?).and_return(false)
143
+ lambda {
144
+ Torrents.a_random_method
145
+ }.should raise_error(Exception)
146
+ end
147
+ end
148
+
149
+ context "the results method" do
150
+ def inner_torrents(times)
151
+ list = []
152
+ times.times {list << 1}
153
+ @torrents.should_receive(:inner_torrents).exactly(1).times.and_return(list)
154
+ end
155
+
156
+ def prepare
157
+ torrent = mock(Object)
158
+ inner_torrents(50)
159
+ Container::Torrent.should_receive(:new).any_number_of_times.and_return(torrent)
160
+ torrent.should_receive(:valid?).any_number_of_times.and_return(true)
161
+ end
162
+
163
+ before(:each) do
164
+ @torrents.should_receive(:content).and_return("")
165
+ end
166
+
167
+ it "should return an empty list" do
168
+ inner_torrents(0)
169
+ @torrents.results.should be_empty
170
+ end
171
+
172
+ it "should return a list with items" do
173
+ prepare
174
+ @torrents.should have(50).results
175
+ end
176
+
177
+ it "should be able to cache torrents" do
178
+ prepare
179
+ 5.times { @torrents.should have(50).results }
180
+ end
181
+ end
182
+
183
+ context "the cookies method" do
184
+ it "should be possible to pass some cookies" do
185
+ RestClient.should_receive(:get).with("http://thepiratebay.org/recent/0", {:timeout => 10, :cookies => {:session_id => "1234"}}).exactly(1).times.and_return("")
186
+ @torrents.cookies(:session_id => "1234").content
187
+ end
188
+ end
189
+
190
+ context "the find_by_details method" do
191
+ it "should be possible to add a details link and get appropriate data" do
192
+ rest_client("http://thepiratebay.org/torrent/6173093/", "details")
193
+ torrent = Torrents.the_pirate_bay.find_by_details("http://thepiratebay.org/torrent/6173093/")
194
+
195
+ # Makes sure that all methods returnes something
196
+ [:seeders, :title, :dead?, :imdb, :imdb_id, :domain, :id].each do |method|
197
+ torrent.send(method).to_s.should_not be_empty
198
+ end
199
+
200
+ torrent.should_not be_dead
201
+ torrent.seeders.should eq(9383)
202
+ torrent.tid.should_not be_empty
203
+ torrent.domain.should eq("thepiratebay.org")
204
+ end
205
+ end
206
+
207
+ context "the errors method" do
208
+ before(:each) do
209
+ rest_client("http://thepiratebay.org/recent/0", "recent")
210
+ end
211
+
212
+ it "should return the right error messages" do
213
+ errors = @torrents.errors
214
+
215
+ [
216
+ "An error occurred in the the_pirate_bay class at the details method.\n#<NoMethodError: undefined method `attr' for nil:NilClass>",
217
+ "An error occurred in the the_pirate_bay class at the title method.\n#<NoMethodError: undefined method `content' for nil:NilClass>",
218
+ "32 torrents where found, 2 where not valid"
219
+ ].each do |error|
220
+ errors.should include(error)
221
+ end
222
+ end
223
+
224
+ it "should not return any duplicates" do
225
+ errors = @torrents.errors
226
+ lambda do
227
+ errors.uniq!
228
+ end.should_not change(errors, :count)
229
+ end
230
+ end
231
+ end