crags 1.6.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Item do
4
+ before do
5
+ elem = stub
6
+ elem.stub!(:title).and_return("title!")
7
+ elem.stub!(:url).and_return("url!")
8
+ elem.stub!(:date).and_return("date!")
9
+ @item = Item.new(elem)
10
+ end
11
+
12
+ it "has a title reader" do
13
+ @item.title.should == "title!"
14
+ end
15
+
16
+ it "has a url reader" do
17
+ @item.url.should == "url!"
18
+ end
19
+
20
+ it "has a date reader" do
21
+ @item.date.should == "date!"
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Location do
4
+ before do
5
+ @loc = Location.new("domain.com")
6
+ end
7
+
8
+ it "has a domain reader" do
9
+ @loc.domain.should == "domain.com"
10
+ end
11
+
12
+ it "has a url generated form the domain" do
13
+ @loc.url.should == "http://domain.com"
14
+ end
15
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Search::Country do
4
+ before do
5
+ Crags::Config.stub!(:defaults).and_return({:country => 'heya', :interval => 200})
6
+ @default = Search::Country.new
7
+ @custom = Search::Country.new({:country => 'gabba', :interval => 10})
8
+ end
9
+
10
+ it "has config default country" do
11
+ @default.country.should == "heya"
12
+ end
13
+
14
+ it "has config default interval" do
15
+ @default.interval.should == 200
16
+ end
17
+
18
+ it "has custom country" do
19
+ @custom.country.should == "gabba"
20
+ end
21
+
22
+ it "has config default interval" do
23
+ @custom.interval.should == 10
24
+ end
25
+
26
+ it "delegates locations to country" do
27
+ @default.country.should_receive(:locations).and_return("locations")
28
+ @default.locations.should == "locations"
29
+ end
30
+
31
+ describe "with location searches" do
32
+ before do
33
+ @search = stub
34
+ @search.stub!(:items)
35
+ Search::Location.stub!(:new).and_return(@search)
36
+ @locations = ["loc1", "loc2"]
37
+ @custom.stub!(:sleep)
38
+ end
39
+
40
+ it "calls sleep with interval for each location" do
41
+ @custom.stub!(:locations).and_return(@locations)
42
+ @custom.should_receive(:sleep).with(10).twice
43
+ @custom.items
44
+ end
45
+
46
+ it "creates a new search for each location" do
47
+ Search::Location.should_receive(:new).twice.and_return(@search)
48
+ @custom.stub!(:locations).and_return(@locations)
49
+ @custom.items
50
+ end
51
+
52
+ it "performs the search for each location" do
53
+ @search.should_receive(:items).twice
54
+ @custom.stub!(:locations).and_return(@locations)
55
+ @custom.items
56
+ end
57
+
58
+ it "flattens the search results" do
59
+ collect = mock
60
+ collect.should_receive(:flatten).and_return("flat!")
61
+ locations = stub
62
+ locations.stub!(:collect).and_return(collect)
63
+ @custom.stub!(:locations).and_return(locations)
64
+ @custom.items.should == "flat!"
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Search::Location do
4
+ before do
5
+ @default_loc = Crags::Location.new("default.domain.com")
6
+ @default_cat = Crags::Category.new('for sale', 'sss/')
7
+ @custom_loc = Crags::Location.new("custom.domain.com")
8
+ Crags::Config.stub!(:defaults).and_return({
9
+ :keyword => 'bicycle',
10
+ :location => @default_loc,
11
+ :category => @default_cat
12
+ })
13
+ @default = Search::Location.new
14
+ @custom = Search::Location.new({:location => @custom_loc})
15
+ end
16
+
17
+ it "has config default location" do
18
+ @default.location.should == @default_loc
19
+ end
20
+
21
+ it "has custom country" do
22
+ @custom.location.should == @custom_loc
23
+ end
24
+
25
+ it "generate a url based on location, category and keyword" do
26
+ @default.stub!(:url_encode).with('bicycle').and_return('bicycle')
27
+ @default.url.should == "#{@default_loc.url}/search#{@default_cat.url}?query=bicycle"
28
+ end
29
+
30
+ it "fetch the doc at the url with an rss format" do
31
+ @default.stub!(:url).and_return("url")
32
+ @default.should_receive(:fetch_doc).with("url&format=rss").and_return('doc')
33
+ @default.doc.should == 'doc'
34
+ end
35
+
36
+ describe "with a doc" do
37
+ before do
38
+ @doc = mock
39
+ @items = ["item"]
40
+ @doc.stub!(:search).and_return(@items)
41
+ @default.stub!(:doc).and_return(@doc)
42
+ Item.stub!(:new).and_return("crags_item")
43
+ end
44
+
45
+ it "gets all items from the doc" do
46
+ @doc.should_receive(:search).with("item").and_return(@items)
47
+ @default.items
48
+ end
49
+
50
+ it "creates a new crags item for each doc item" do
51
+ Item.should_receive(:new).with("item").and_return("crags_item")
52
+ @default.items
53
+ end
54
+
55
+ it "collects all created items" do
56
+ @default.items.should == ["crags_item"]
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Search::Search do
4
+ before do
5
+ Crags::Config.stub!(:defaults).and_return({:keyword => 'cribz', :category => 'cribcat'})
6
+ @default_obj = Search::Search.new
7
+ @custom_obj = Search::Search.new(:keyword => 'zaks', :category => 'catz')
8
+ end
9
+
10
+ it "has a custom keyword" do
11
+ @custom_obj.keyword.should == "zaks"
12
+ end
13
+
14
+ it "has a custom category" do
15
+ @custom_obj.category.should == "catz"
16
+ end
17
+
18
+ it "has a custom keyword" do
19
+ @default_obj.keyword.should == "cribz"
20
+ end
21
+
22
+ it "has a custom category" do
23
+ @default_obj.category.should == "cribcat"
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hpricot::Elem do
4
+ before do
5
+ @elem = Hpricot::Elem.new("<omg></omg>")
6
+ end
7
+
8
+ it "uses the inner_text of title element for title" do
9
+ title = stub
10
+ title.stub!(:inner_text).and_return("title!")
11
+ @elem.stub!(:at).with("title").and_return(title)
12
+ @elem.title.should == "title!"
13
+ end
14
+
15
+ it "rdf:about attribute for the url" do
16
+ @elem.stub!(:[]).with("rdf:about").and_return("url!")
17
+ @elem.url.should == "url!"
18
+ end
19
+
20
+ it "uses the inner_text of the dc:date element for date_str" do
21
+ dc_date = stub
22
+ dc_date.stub!(:inner_text).and_return("date_str!")
23
+ @elem.stub!(:at).with("dc:date").and_return(dc_date)
24
+ @elem.date_str.should == "date_str!"
25
+ end
26
+
27
+ it "parses date_str to create a real date" do
28
+ DateTime.should_receive(:parse).with("date_str!").and_return("date!")
29
+ @elem.stub!(:date_str).and_return("date_str!")
30
+ @elem.date.should == "date!"
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe String do
4
+ it "removes http:// and trailing /" do
5
+ url = "http://omg/"
6
+ url.strip_http.should == "omg"
7
+ end
8
+
9
+ it "removes http:// when there is no trailing slash" do
10
+ url = "http://omg"
11
+ url.strip_http.should == "omg"
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require(:default, :test)
4
+ require 'crags'
5
+ include Crags
metadata CHANGED
@@ -3,10 +3,10 @@ name: crags
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 1
7
- - 6
6
+ - 2
8
7
  - 0
9
- version: 1.6.0
8
+ - 0
9
+ version: 2.0.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Justin Marney
@@ -14,10 +14,33 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-14 00:00:00 -04:00
17
+ date: 2010-07-26 00:00:00 -04:00
18
18
  default_executable:
19
- dependencies: []
20
-
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: curb
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: hpricot
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :runtime
43
+ version_requirements: *id002
21
44
  description: A library to help search across multiple craigslist locations.
22
45
  email: gotascii@gmail.com
23
46
  executables: []
@@ -29,21 +52,34 @@ extra_rdoc_files:
29
52
  - README.rdoc
30
53
  files:
31
54
  - .gitignore
55
+ - Gemfile
32
56
  - LICENSE
33
57
  - README.rdoc
34
58
  - Rakefile
35
59
  - VERSION
36
60
  - crags.gemspec
37
61
  - lib/crags.rb
38
- - lib/crags/fetch.rb
39
- - lib/crags/proxy.rb
40
- - lib/crags/runner.rb
41
- - lib/crags/searcher.rb
42
- - test/crags/fetch_test.rb
43
- - test/crags/proxy_test.rb
44
- - test/crags/runner_test.rb
45
- - test/crags/searcher_test.rb
46
- - test/test_helper.rb
62
+ - lib/crags/category.rb
63
+ - lib/crags/country.rb
64
+ - lib/crags/fetcher.rb
65
+ - lib/crags/item.rb
66
+ - lib/crags/location.rb
67
+ - lib/crags/search/country.rb
68
+ - lib/crags/search/location.rb
69
+ - lib/crags/search/search.rb
70
+ - lib/ext/hpricot/elem.rb
71
+ - lib/ext/string.rb
72
+ - spec/crags/category_spec.rb
73
+ - spec/crags/country_spec.rb
74
+ - spec/crags/fetcher_spec.rb
75
+ - spec/crags/item_spec.rb
76
+ - spec/crags/location_spec.rb
77
+ - spec/crags/search/country_spec.rb
78
+ - spec/crags/search/location_spec.rb
79
+ - spec/crags/search/search_spec.rb
80
+ - spec/ext/hpricot/elem_spec.rb
81
+ - spec/ext/string_spec.rb
82
+ - spec/spec_helper.rb
47
83
  has_rdoc: true
48
84
  homepage: http://github.com/gotascii/crags
49
85
  licenses: []
@@ -75,8 +111,14 @@ signing_key:
75
111
  specification_version: 3
76
112
  summary: A library to help search across multiple craigslist locations.
77
113
  test_files:
78
- - test/crags/fetch_test.rb
79
- - test/crags/proxy_test.rb
80
- - test/crags/runner_test.rb
81
- - test/crags/searcher_test.rb
82
- - test/test_helper.rb
114
+ - spec/crags/category_spec.rb
115
+ - spec/crags/country_spec.rb
116
+ - spec/crags/fetcher_spec.rb
117
+ - spec/crags/item_spec.rb
118
+ - spec/crags/location_spec.rb
119
+ - spec/crags/search/country_spec.rb
120
+ - spec/crags/search/location_spec.rb
121
+ - spec/crags/search/search_spec.rb
122
+ - spec/ext/hpricot/elem_spec.rb
123
+ - spec/ext/string_spec.rb
124
+ - spec/spec_helper.rb
data/lib/crags/proxy.rb DELETED
@@ -1,21 +0,0 @@
1
- module Crags
2
- module Proxy
3
- include Fetch
4
-
5
- def lists
6
- ["http://www.proxy4free.com/page1.html","http://www.proxy4free.com/page3.html"]
7
- end
8
-
9
- def fetch_lists
10
- lists.collect {|url| fetch_html(url)}
11
- end
12
-
13
- def scan(text)
14
- text.scan(/\d+\.\d+\.\d+\.\d+/)
15
- end
16
-
17
- def proxies
18
- fetch_lists.collect{|html|scan(html)}.flatten.uniq
19
- end
20
- end
21
- end
data/lib/crags/runner.rb DELETED
@@ -1,10 +0,0 @@
1
- module Crags
2
- class Runner
3
- include Searcher
4
-
5
- def search_location(keyword, loc, category = 'sss')
6
- puts "Searching #{loc}..."
7
- super
8
- end
9
- end
10
- end
@@ -1,77 +0,0 @@
1
- module Crags
2
- module Searcher
3
- include Fetch
4
- include ERB::Util
5
-
6
- def strip_http(url)
7
- url.gsub(/^http\:\/\//,'').gsub(/\/$/,'')
8
- end
9
-
10
- def location_link(country)
11
- "http://geo.craigslist.org/iso/#{country}"
12
- end
13
-
14
- def location_doc(country)
15
- fetch_doc(location_link(country))
16
- end
17
-
18
- def location_request(country)
19
- fetch_request(location_link(country))
20
- end
21
-
22
- def location_links(country)
23
- location_doc(country).search("#list a")
24
- end
25
-
26
- def locations(country)
27
- linkz = location_links(country)
28
- if linkz.empty?
29
- [strip_http(location_request(country).last_effective_url)]
30
- else
31
- linkz.collect{|link| strip_http(link["href"]) }
32
- end
33
- end
34
-
35
- def categories
36
- doc = fetch_doc("http://sfbay.craigslist.org/")
37
- links = doc.search("table[@summary=\"for sale\"] a")
38
- categories = {}
39
- links.each do |link|
40
- categories[link.inner_html] = link["href"]
41
- end
42
- categories
43
- end
44
-
45
- def search(keyword, country = 'us', category = 'sss', &block)
46
- locations(country).collect do |loc|
47
- sleep(1 + rand(3))
48
- search_location(keyword, loc, category, &block)
49
- end.flatten
50
- end
51
-
52
- def items(doc)
53
- doc.search("item").collect do |item|
54
- hashify(item)
55
- end
56
- end
57
-
58
- def hashify(item)
59
- title = item.at("title").inner_text
60
- url = strip_http(item["rdf:about"])
61
- date = DateTime.parse(item.at("dc:date").inner_text)
62
- {:title => title, :url => url, :date => date}
63
- end
64
-
65
- def search_location_link(keyword, loc, category = 'sss')
66
- "http://#{loc}/search/#{category}?query=#{url_encode(keyword)}"
67
- end
68
-
69
- def search_location(keyword, loc, category = 'sss', &block)
70
- doc = fetch_doc("#{search_location_link(keyword, loc, category)}&format=rss")
71
- items(doc).collect do |item|
72
- yield item if block_given?
73
- item
74
- end
75
- end
76
- end
77
- end
@@ -1,33 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class Crags::FetchTest < Test::Unit::TestCase
4
- context "Fetch" do
5
- setup do
6
- extend Crags::Fetch
7
- end
8
-
9
- should "fetch doc should hpricot fetched html" do
10
- stubs(:fetch_html).with("url").returns("html")
11
- Hpricot.expects(:parse).with("html").returns("doc")
12
- fetch_doc("url").should == "doc"
13
- end
14
-
15
- should "fetch html should fetch_request a url" do
16
- curb = stub(:body_str => "uhh")
17
- expects(:fetch_request).with("url").returns(curb)
18
- fetch_html("url").should == "uhh"
19
- end
20
-
21
- should "create a new request" do
22
- req = stub(:follow_location= => nil, :perform => nil)
23
- Curl::Easy.expects(:new).with("url").returns(req)
24
- fetch_request("url").should == req
25
- end
26
-
27
- should "follow redirects for fetched requests" do
28
- req = mock(:follow_location= => nil, :perform => nil)
29
- Curl::Easy.stubs(:new).returns(req)
30
- fetch_request("url")
31
- end
32
- end
33
- end
@@ -1,25 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class Crags::ProxyTest < Test::Unit::TestCase
4
- context "Proxy" do
5
- setup do
6
- extend Crags::Proxy
7
- end
8
-
9
- should "lists should return a list of proxy list websites" do
10
- lists.should == ["http://www.proxy4free.com/page1.html", "http://www.proxy4free.com/page3.html"]
11
- end
12
-
13
- should "fetch lists should fetch html for each site in lists" do
14
- stubs(:lists).returns(["1", "2"])
15
- expects(:fetch_html).with("1").returns("html_1")
16
- expects(:fetch_html).with("2").returns("html_2")
17
- fetch_lists.should == ["html_1", "html_2"]
18
- end
19
-
20
- should "scan should return all ips in a text blizoc" do
21
- text = "192.168.1.2 omg dude!! wtf.f.f.asdasd9.8.9 78.900.42.32"
22
- scan(text).should == ["192.168.1.2", "78.900.42.32"]
23
- end
24
- end
25
- end
@@ -1,28 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class Crags::RunnerTest < Test::Unit::TestCase
4
- context "instance of Runner" do
5
- setup do
6
- @runner = Crags::Runner.new
7
- @runner.stubs(:fetch_doc)
8
- @runner.stubs(:items).returns([])
9
- end
10
-
11
- should "runner should include searcher" do
12
- Crags::Runner.ancestors.include?(Crags::Searcher).should == true
13
- end
14
-
15
- should "search location should puts message with loc" do
16
- @runner.expects(:puts).with { |val| val =~ /location/ }
17
- @runner.search_location("", "location", "category")
18
- end
19
-
20
- should "search location should take a category" do
21
- @runner.search_location("", "location", "category")
22
- end
23
-
24
- should "search location should have default category sss" do
25
- @runner.search_location("", "location")
26
- end
27
- end
28
- end