sogger 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/README.md +33 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/bin/sogger +8 -0
- data/lib/sogger.rb +8 -0
- data/lib/sogger/question.rb +38 -0
- data/lib/sogger/runner.rb +92 -0
- data/lib/sogger/sogger.rb +45 -0
- data/sogger.gemspec +74 -0
- data/test/fixtures/so_feed_sample.xml +1150 -0
- data/test/helper.rb +25 -0
- data/test/test_question.rb +60 -0
- data/test/test_runner.rb +9 -0
- data/test/test_sogger.rb +70 -0
- metadata +114 -0
data/test/helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'fakeweb'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'sogger'
|
9
|
+
|
10
|
+
FakeWeb.register_uri :get, Sogger::Sogger::SO_FEED_URL, :body => File.read("test/fixtures/so_feed_sample.xml")
|
11
|
+
|
12
|
+
class Test::Unit::TestCase
|
13
|
+
include Sogger
|
14
|
+
def setup
|
15
|
+
Sogger.save_path = "test/feed.xml"
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_sample_file(filename)
|
19
|
+
File.read("test/fixtures/#{filename}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
File.delete(Sogger.save_path) if File.exists?(Sogger.save_path)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestQuestion < Test::Unit::TestCase
|
4
|
+
context "Question" do
|
5
|
+
setup do
|
6
|
+
@xml_element = Nokogiri::XML(read_sample_file("so_feed_sample.xml")).css('entry').first
|
7
|
+
end
|
8
|
+
|
9
|
+
should "be initializeable from xml" do
|
10
|
+
assert_nothing_raised do
|
11
|
+
Question.from_xml(@xml_element)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
should "have correct attributes when instantiated from xml" do
|
16
|
+
q = Question.from_xml(@xml_element)
|
17
|
+
expected_attributes = {
|
18
|
+
:title => "Windows and Minibuffer floating over the frame",
|
19
|
+
:url => "http://stackoverflow.com/questions/1856203/windows-and-minibuffer-floating-over-the-frame",
|
20
|
+
:tags => ["emacs"],
|
21
|
+
:published => DateTime.parse("2009-12-06T18:48:09Z")}
|
22
|
+
|
23
|
+
assert_equal expected_attributes, q.attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
context "instance" do
|
27
|
+
setup do
|
28
|
+
@question = Question.from_xml(@xml_element)
|
29
|
+
end
|
30
|
+
|
31
|
+
should "have title attribute" do
|
32
|
+
assert_equal "Windows and Minibuffer floating over the frame", @question.title
|
33
|
+
end
|
34
|
+
|
35
|
+
should "have url attribute" do
|
36
|
+
assert_equal "http://stackoverflow.com/questions/1856203/windows-and-minibuffer-floating-over-the-frame", @question.url
|
37
|
+
end
|
38
|
+
|
39
|
+
should "have tags attribute" do
|
40
|
+
assert_equal ["emacs"], @question.tags
|
41
|
+
end
|
42
|
+
|
43
|
+
should "have published attribute" do
|
44
|
+
assert_equal DateTime.parse("2009-12-06T18:48:09+00:00"), @question.published
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "Array of questions" do
|
50
|
+
setup do
|
51
|
+
@newer_question = Question.new(:published => DateTime.parse("12/12/2009"))
|
52
|
+
@older_question = Question.new(:published => DateTime.parse("12/12/2008"))
|
53
|
+
@questions = [@older_question, @newer_question]
|
54
|
+
end
|
55
|
+
|
56
|
+
should "sort by published" do
|
57
|
+
assert_equal [@newer_question, @older_question], @questions.sort
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/test/test_runner.rb
ADDED
data/test/test_sogger.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSogger < Test::Unit::TestCase
|
4
|
+
context "Sogger" do
|
5
|
+
should "have an SO_FEED_URL" do
|
6
|
+
assert Sogger::SO_FEED_URL
|
7
|
+
end
|
8
|
+
|
9
|
+
should "have a save_path" do
|
10
|
+
assert Sogger.save_path
|
11
|
+
end
|
12
|
+
|
13
|
+
context "populated with data" do
|
14
|
+
setup do
|
15
|
+
@sogger = Sogger.new
|
16
|
+
@sogger.download_feed!
|
17
|
+
end
|
18
|
+
|
19
|
+
should "retrieve feed from #{Sogger::SO_FEED_URL}" do
|
20
|
+
assert_equal read_sample_file('so_feed_sample.xml'), @sogger.raw_data
|
21
|
+
end
|
22
|
+
|
23
|
+
should "parse collection of 30 questions" do
|
24
|
+
assert_equal 30, @sogger.questions.size
|
25
|
+
end
|
26
|
+
|
27
|
+
should "return question objects in questions collection" do
|
28
|
+
assert_equal Question, @sogger.questions.first.class
|
29
|
+
end
|
30
|
+
|
31
|
+
should "have questions always sorted" do
|
32
|
+
newer_question = Question.new(:published => DateTime.parse("12/12/2009"))
|
33
|
+
older_question = Question.new(:published => DateTime.parse("12/12/2008"))
|
34
|
+
@sogger.instance_variable_set("@questions", [older_question, newer_question])
|
35
|
+
assert_equal [newer_question, older_question], @sogger.questions
|
36
|
+
end
|
37
|
+
|
38
|
+
should "save feed" do
|
39
|
+
@sogger.save!
|
40
|
+
assert File.exists?(Sogger.save_path)
|
41
|
+
end
|
42
|
+
|
43
|
+
should "load feed" do
|
44
|
+
@sogger.save!
|
45
|
+
sogger2 = Sogger.new
|
46
|
+
sogger2.load!
|
47
|
+
assert_equal read_sample_file('so_feed_sample.xml'), sogger2.raw_data
|
48
|
+
end
|
49
|
+
|
50
|
+
should "return new question when subtracted from another sogger" do
|
51
|
+
very_new_question1 = Question.new(:published => DateTime.parse("12/12/2012"))
|
52
|
+
very_new_question2 = Question.new(:published => DateTime.parse("12/12/2010"))
|
53
|
+
very_old_question = Question.new(:published => DateTime.parse("12/12/1999"))
|
54
|
+
fixture_question = Question.new(:published => DateTime.parse("2009-12-06T07:14:23Z"))
|
55
|
+
|
56
|
+
collection = [very_old_question, very_new_question1, fixture_question, very_new_question2]
|
57
|
+
newer_sogger = Sogger.new(collection)
|
58
|
+
|
59
|
+
expected_difference = [very_new_question1, very_new_question2]
|
60
|
+
actual_difference = (newer_sogger - @sogger).questions
|
61
|
+
|
62
|
+
expected_inspect = expected_difference.map{|q| q.published.strftime('%d/%m/%y %H:%M:%S')}.inspect
|
63
|
+
actual_inspect = actual_difference.map{|q| q.published.strftime('%d/%m/%y %H:%M:%S')}.inspect
|
64
|
+
|
65
|
+
assert_equal expected_difference, actual_difference,
|
66
|
+
"Expected #{expected_inspect}, but was #{actual_inspect}."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sogger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maxim Chernyak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-08 00:00:00 -05:00
|
13
|
+
default_executable: sogger
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: meow
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: nokogiri
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: shoulda
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: fakeweb
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
description: Simple tool that growls new questions from Stack Overflow. Supports filtering by tags.
|
56
|
+
email: max@bitsonnet.com
|
57
|
+
executables:
|
58
|
+
- sogger
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- LICENSE
|
63
|
+
- README.md
|
64
|
+
files:
|
65
|
+
- .document
|
66
|
+
- .gitignore
|
67
|
+
- LICENSE
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- VERSION
|
71
|
+
- bin/sogger
|
72
|
+
- lib/sogger.rb
|
73
|
+
- lib/sogger/question.rb
|
74
|
+
- lib/sogger/runner.rb
|
75
|
+
- lib/sogger/sogger.rb
|
76
|
+
- sogger.gemspec
|
77
|
+
- test/fixtures/so_feed_sample.xml
|
78
|
+
- test/helper.rb
|
79
|
+
- test/test_question.rb
|
80
|
+
- test/test_runner.rb
|
81
|
+
- test/test_sogger.rb
|
82
|
+
has_rdoc: true
|
83
|
+
homepage: http://github.com/maxim/sogger
|
84
|
+
licenses: []
|
85
|
+
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options:
|
88
|
+
- --charset=UTF-8
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: "0"
|
96
|
+
version:
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
version:
|
103
|
+
requirements: []
|
104
|
+
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.3.5
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Stack overflow growler written in Ruby.
|
110
|
+
test_files:
|
111
|
+
- test/helper.rb
|
112
|
+
- test/test_question.rb
|
113
|
+
- test/test_runner.rb
|
114
|
+
- test/test_sogger.rb
|