regentanz 0.2.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.
- data/.gitignore +5 -0
- data/CHANGELOG.rdoc +22 -0
- data/Gemfile +4 -0
- data/LICENSE +24 -0
- data/README.rdoc +46 -0
- data/Rakefile +23 -0
- data/lib/regentanz/astronomy.rb +69 -0
- data/lib/regentanz/cache/base.rb +51 -0
- data/lib/regentanz/cache/file.rb +86 -0
- data/lib/regentanz/cache.rb +2 -0
- data/lib/regentanz/callbacks.rb +18 -0
- data/lib/regentanz/conditions/base.rb +16 -0
- data/lib/regentanz/conditions/current.rb +14 -0
- data/lib/regentanz/conditions/forecast.rb +14 -0
- data/lib/regentanz/conditions.rb +3 -0
- data/lib/regentanz/configuration.rb +55 -0
- data/lib/regentanz/configurator.rb +22 -0
- data/lib/regentanz/google_weather.rb +151 -0
- data/lib/regentanz/parser/google_weather.rb +100 -0
- data/lib/regentanz/parser.rb +1 -0
- data/lib/regentanz/test_helper.rb +52 -0
- data/lib/regentanz/version.rb +4 -0
- data/lib/regentanz.rb +12 -0
- data/regentanz.gemspec +31 -0
- data/test/factories.rb +8 -0
- data/test/support/support_mailer.rb +7 -0
- data/test/support/tmp/.gitignore +1 -0
- data/test/support/valid_response.xml.erb +26 -0
- data/test/test_helper.rb +18 -0
- data/test/unit/astronomy_test.rb +26 -0
- data/test/unit/cache/base_test.rb +53 -0
- data/test/unit/cache/file_test.rb +141 -0
- data/test/unit/callbacks_test.rb +27 -0
- data/test/unit/configuration_test.rb +57 -0
- data/test/unit/current_condition_test.rb +33 -0
- data/test/unit/forecast_condition_test.rb +35 -0
- data/test/unit/google_weather_test.rb +131 -0
- data/test/unit/parser/google_weather_parser_test.rb +71 -0
- metadata +219 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
module Regentanz
|
2
|
+
module Parser
|
3
|
+
class GoogleWeather
|
4
|
+
require 'iconv'
|
5
|
+
|
6
|
+
XML_ENCODING = 'LATIN1' # source encoding of the XML data
|
7
|
+
|
8
|
+
# Converts a string from XML_ENCODING to UTF-8 using the Iconv library.
|
9
|
+
#
|
10
|
+
# === Note
|
11
|
+
# FIXME The XML source document seems to be delivered LATIN1 or UTF-8, completely
|
12
|
+
# random and unpredictable.
|
13
|
+
#
|
14
|
+
# === Parameters
|
15
|
+
# * +data+: string to convert
|
16
|
+
def convert_encoding data
|
17
|
+
return if data.blank?
|
18
|
+
self.class::XML_ENCODING != "UTF-8" ? Iconv.iconv("UTF-8", self.class::XML_ENCODING, data).flatten.join(" ") : data
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_current!(xml)
|
22
|
+
return if xml.blank?
|
23
|
+
begin
|
24
|
+
doc = REXML::Document.new(xml)
|
25
|
+
if doc.elements['xml_api_reply/weather/current_conditions']
|
26
|
+
attributes = {}
|
27
|
+
doc.elements['xml_api_reply/weather/current_conditions'].each_element do |ele|
|
28
|
+
attributes.merge! parse_node(ele)
|
29
|
+
end
|
30
|
+
Regentanz::Conditions::Current.new(attributes)
|
31
|
+
end
|
32
|
+
rescue
|
33
|
+
# FIXME should report error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_forecast!(xml)
|
38
|
+
return if xml.blank?
|
39
|
+
forecasts = []
|
40
|
+
begin
|
41
|
+
doc = REXML::Document.new(xml)
|
42
|
+
if doc.elements['xml_api_reply/weather/forecast_conditions']
|
43
|
+
doc.elements.each('xml_api_reply/weather/forecast_conditions') do |forecast_element|
|
44
|
+
attributes = {}
|
45
|
+
forecast_element.each_element { |ele| attributes.merge! parse_node(ele) }
|
46
|
+
forecasts << Regentanz::Conditions::Forecast.new(attributes)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
forecasts
|
50
|
+
rescue
|
51
|
+
# FIXME should report error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#private # FIXME private methods should start here after parse! has been implemented
|
56
|
+
|
57
|
+
# Handles some special treatment for certain sub-elements, transforms _element_
|
58
|
+
# into a hash and returns it.
|
59
|
+
#
|
60
|
+
# === Parameters
|
61
|
+
# * +element+ childnode of type REXML::Element
|
62
|
+
def parse_node(element)
|
63
|
+
hash = {}
|
64
|
+
hash.merge! parse_style(element.attribute("data").to_s) if element.name == "icon"
|
65
|
+
if element.name == "humidity"
|
66
|
+
# Handle the small whitespace just before the '%'
|
67
|
+
hash.merge! element.name => element.attribute("data").to_s.gsub(/(\d+).+%$/, '\1 %')
|
68
|
+
elsif element.name == "icon"
|
69
|
+
# We want the full URL
|
70
|
+
hash.merge! element.name => "http://www.google.com" + element.attribute("data").to_s
|
71
|
+
elsif (element.name == "high" or element.name == "low") and @lang == "en"
|
72
|
+
# Forecast-temperatures in EN are listed in °F; we fix that here
|
73
|
+
temp_f = element.attribute("data").to_s.to_i
|
74
|
+
hash.merge! element.name => ( temp_f - 32 ) * 5 / 9
|
75
|
+
else
|
76
|
+
hash.merge! element.name => element.attribute("data").to_s
|
77
|
+
end
|
78
|
+
hash
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Extracts a name for the weather condition from the icon name. Intended to
|
84
|
+
# be used as CSS style class name.
|
85
|
+
#
|
86
|
+
# === Parameters
|
87
|
+
# * +path+ an URI-string to Google's weather icon
|
88
|
+
def parse_style(path)
|
89
|
+
hash = {}
|
90
|
+
unless path.blank?
|
91
|
+
style = File.basename(path) # FIXME is this what we want for everyone?
|
92
|
+
style = style.slice(0, style.rindex(".")).gsub(/_/, '-')
|
93
|
+
hash = { "style" => style }
|
94
|
+
end
|
95
|
+
hash
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'regentanz/parser/google_weather'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Regentanz
|
2
|
+
module TestHelper
|
3
|
+
|
4
|
+
# Default values used for testing. Use this in your setup methods.
|
5
|
+
# Configuration values can be overriden by supplying a block. See
|
6
|
+
# Regentanz::Configuration for supported values.
|
7
|
+
def setup_regentanz_test_configuration!
|
8
|
+
Regentanz.configure do |config|
|
9
|
+
config.retry_ttl = Regentanz::Configuration.default_cache_ttl
|
10
|
+
config.do_not_get_weather = true
|
11
|
+
config.retry_ttl = Regentanz::Configuration.default_retry_ttl
|
12
|
+
config.suppress_stderr_output = true
|
13
|
+
yield config if block_given? # add settings or override above from client
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns an invalid API response that will cause REXML to hickup
|
18
|
+
def invalid_xml_response
|
19
|
+
'<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">' \
|
20
|
+
"<TITLE>302 Moved</TITLE></HEAD><BODY>\n" \
|
21
|
+
"<H1>302 Moved</H1>\n" \
|
22
|
+
"The document has moved\n" \
|
23
|
+
'<A HREF="http://sorry.google.com/sorry/?continue=http://www.google.com/ig/api%3Fweather%3D86747%252CGermany%26hl%3Dde">here</A>' \
|
24
|
+
"</BODY></HTML>\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a valid xml api reply based upon ./test/support/valid_response.xml.erb
|
28
|
+
def valid_xml_response
|
29
|
+
filename = File.join(Regentanz.configuration.cache_dir, '..', 'valid_response.xml.erb')
|
30
|
+
xmlerb = ERB.new(File.open(filename, 'r') { |file| file.read })
|
31
|
+
xmlerb.result
|
32
|
+
end
|
33
|
+
|
34
|
+
# Creates a cache file +filename+ with contents of #invalid_xml_response
|
35
|
+
# FIXME this is deprecated with the introduction of Regentanz::Cache::File
|
36
|
+
def create_invalid_xml_response(filename)
|
37
|
+
File.open(filename, "w+") { |f| f.puts invalid_xml_response }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Stub Net::HTTP.get_response to return a semi-dynamic (ie. current date) xml
|
41
|
+
# response-
|
42
|
+
def stub_valid_xml_api_response!
|
43
|
+
mock_response = mock()
|
44
|
+
mock_response.stubs(:body).returns(valid_xml_response)
|
45
|
+
Net::HTTP.stubs(:get_response).returns(mock_response)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
include Regentanz::TestHelper
|
data/lib/regentanz.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'action_mailer'
|
4
|
+
require 'regentanz/version'
|
5
|
+
require 'regentanz/cache'
|
6
|
+
require 'regentanz/configuration'
|
7
|
+
require 'regentanz/configurator'
|
8
|
+
require 'regentanz/callbacks'
|
9
|
+
require 'regentanz/astronomy'
|
10
|
+
require 'regentanz/conditions'
|
11
|
+
require 'regentanz/parser'
|
12
|
+
require 'regentanz/google_weather'
|
data/regentanz.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "regentanz/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "regentanz"
|
7
|
+
s.version = Regentanz::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Carsten Zimmermann"]
|
10
|
+
s.email = ["cz@aegisnet.de"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Library to access the Google Weather API}
|
13
|
+
s.description = %q{Library to access the Google Weather API}
|
14
|
+
|
15
|
+
s.rubyforge_project = "regentanz"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency 'actionmailer', '~> 3.0.10'
|
23
|
+
s.add_dependency 'activesupport', '~> 3.0.10'
|
24
|
+
|
25
|
+
s.add_development_dependency 'rake'
|
26
|
+
s.add_development_dependency 'mocha'
|
27
|
+
s.add_development_dependency 'bundler'
|
28
|
+
s.add_development_dependency 'redgreen'
|
29
|
+
s.add_development_dependency 'factory_girl'
|
30
|
+
|
31
|
+
end
|
data/test/factories.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.xml
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<xml_api_reply version="1">
|
3
|
+
<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
|
4
|
+
<forecast_information>
|
5
|
+
<city data="Berlin, Berlin"/><postal_code data="Berlin,Germany"/>
|
6
|
+
<latitude_e6 data=""/>
|
7
|
+
<longitude_e6 data=""/>
|
8
|
+
<forecast_date data="<%= Date.today.strftime("%Y-%m-%d") %>"/>
|
9
|
+
<current_date_time data="<%= 5.minutes.ago.utc.strftime("%Y-%m-%d %H:%M:00") %> +0000"/>
|
10
|
+
<unit_system data="SI"/>
|
11
|
+
</forecast_information>
|
12
|
+
<current_conditions>
|
13
|
+
<condition data="Klar"/><temp_f data="77"/>
|
14
|
+
<temp_c data="25"/>
|
15
|
+
<humidity data="Feuchtigkeit: 57 %"/>
|
16
|
+
<icon data="/ig/images/weather/sunny.gif"/>
|
17
|
+
<wind_condition data="Wind: W mit 24 km/h"/>
|
18
|
+
</current_conditions>
|
19
|
+
<forecast_conditions>
|
20
|
+
<day_of_week data="Do."/><low data="16"/>
|
21
|
+
<high data="31"/>
|
22
|
+
<icon data="/ig/images/weather/chance_of_rain.gif"/>
|
23
|
+
<condition data="Vereinzelt Regen"/>
|
24
|
+
</forecast_conditions>
|
25
|
+
</weather>
|
26
|
+
</xml_api_reply>
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
|
4
|
+
require "test/unit"
|
5
|
+
require "active_support/test_case"
|
6
|
+
require 'action_mailer/test_helper'
|
7
|
+
Bundler.require(:default, :development)
|
8
|
+
require 'test/factories'
|
9
|
+
|
10
|
+
# FIXME move SupportMailer into callbacks
|
11
|
+
require File.join(File.dirname(__FILE__), 'support', 'support_mailer')
|
12
|
+
|
13
|
+
# Configure for test mode
|
14
|
+
require 'regentanz/test_helper'
|
15
|
+
setup_regentanz_test_configuration! do |config|
|
16
|
+
config.cache_dir = File.expand_path(File.join(File.dirname(__FILE__), '', 'support', 'tmp'))
|
17
|
+
config.retry_marker = File.expand_path(File.join(File.dirname(__FILE__), 'support', 'tmp', 'test_api_retry.txt'))
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class AstronomyTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@object = Object.new
|
7
|
+
@object.extend Regentanz::Astronomy
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_google_weather_should_include_astronomy
|
11
|
+
assert Regentanz::GoogleWeather.included_modules.include?(Regentanz::Astronomy)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_deg_to_rad
|
15
|
+
assert Regentanz::Astronomy.private_instance_methods.include?("deg_to_rad")
|
16
|
+
degrees = 42
|
17
|
+
assert_equal degrees*Math::PI/180, @object.send(:deg_to_rad, degrees)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_rad_to_deg
|
21
|
+
assert Regentanz::Astronomy.private_instance_methods.include?("rad_to_deg")
|
22
|
+
radians = 42
|
23
|
+
assert_equal radians*180/Math::PI, @object.send(:rad_to_deg, radians)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
class Regentanz::Cache::BaseTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
LINT_METHODS = [:available?, :expire!, :get, :set, :valid?]
|
7
|
+
|
8
|
+
test "should define public interface for all cache backend" do
|
9
|
+
obj = Regentanz::Cache::Base.new
|
10
|
+
LINT_METHODS.each do |method|
|
11
|
+
assert_respond_to obj, method
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should have check cache backend compatability via lint class method" do
|
16
|
+
assert_respond_to Regentanz::Cache::Base, :lint
|
17
|
+
|
18
|
+
obj = Object.new
|
19
|
+
assert !Regentanz::Cache::Base.lint(obj)
|
20
|
+
assert !Regentanz::Cache::Base.lint(Object)
|
21
|
+
|
22
|
+
LINT_METHODS.each do |method|
|
23
|
+
Object.any_instance.stubs(method)
|
24
|
+
end
|
25
|
+
assert Regentanz::Cache::Base.lint(obj)
|
26
|
+
assert Regentanz::Cache::Base.lint(Object)
|
27
|
+
end
|
28
|
+
|
29
|
+
test "should have key sanitizer class method" do
|
30
|
+
assert_respond_to Regentanz::Cache::Base, :sanitize_key
|
31
|
+
key = Digest::SHA1.hexdigest("a test string")
|
32
|
+
assert_equal key, Regentanz::Cache::Base.sanitize_key("a test string")
|
33
|
+
|
34
|
+
assert_not_equal Regentanz::Cache::Base.sanitize_key("a test string"),
|
35
|
+
Regentanz::Cache::Base.sanitize_key("another test string")
|
36
|
+
end
|
37
|
+
|
38
|
+
test "should inform about retry state" do
|
39
|
+
obj = Regentanz::Cache::Base.new
|
40
|
+
assert_respond_to obj, :waiting_for_retry?
|
41
|
+
end
|
42
|
+
|
43
|
+
test "should check if retry wait time is over" do
|
44
|
+
obj = Regentanz::Cache::Base.new
|
45
|
+
assert_respond_to obj, :unset_retry_state!
|
46
|
+
end
|
47
|
+
|
48
|
+
test "should enter retry state" do
|
49
|
+
obj = Regentanz::Cache::Base.new
|
50
|
+
assert_respond_to obj, :set_retry_state!
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class Regentanz::Cache::FileTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
setup_regentanz_test_configuration!
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
Dir.glob(File.join(Regentanz.configuration.cache_dir, "**", "*")).each { |file| File.unlink(file) }
|
11
|
+
end
|
12
|
+
|
13
|
+
test "should not fail lint" do
|
14
|
+
assert Regentanz::Cache::Base.lint(Regentanz::Cache::File)
|
15
|
+
assert Regentanz::Cache::Base.lint(Regentanz::Cache::File.new)
|
16
|
+
end
|
17
|
+
|
18
|
+
test "should return filename for key" do
|
19
|
+
obj = Regentanz::Cache::File.new
|
20
|
+
assert_respond_to obj, :filename
|
21
|
+
filename = File.join(Regentanz.configuration.cache_dir, "regentanz_test.xml")
|
22
|
+
assert_equal filename, obj.filename("test")
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should create cache file" do
|
26
|
+
obj = Regentanz::Cache::File.new
|
27
|
+
assert !File.exists?(obj.filename("test"))
|
28
|
+
assert obj.set("test", "some cache values")
|
29
|
+
assert File.exists?(obj.filename("test"))
|
30
|
+
end
|
31
|
+
|
32
|
+
test "should rescue set from saving errors" do
|
33
|
+
File.expects(:open).raises(SystemCallError, "pretend something went wrong")
|
34
|
+
obj = Regentanz::Cache::File.new
|
35
|
+
assert_nothing_raised do
|
36
|
+
assert !obj.set("test", "some cache values")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
test "available?" do
|
41
|
+
obj = Regentanz::Cache::File.new
|
42
|
+
assert !obj.available?("test")
|
43
|
+
|
44
|
+
File.new(obj.filename("test"), "w+").close
|
45
|
+
assert obj.available?("test")
|
46
|
+
end
|
47
|
+
|
48
|
+
test "should delete file after expire" do
|
49
|
+
obj = Regentanz::Cache::File.new
|
50
|
+
assert !obj.expire!("test") # nothing to expire, return false
|
51
|
+
|
52
|
+
File.new(obj.filename("test"), "w+").close
|
53
|
+
assert obj.expire!("test")
|
54
|
+
assert !File.exists?(obj.filename("test"))
|
55
|
+
end
|
56
|
+
|
57
|
+
test "should rescue expire from saving errors" do
|
58
|
+
File.expects(:delete).raises(SystemCallError, "pretend something went wrong").once
|
59
|
+
obj = Regentanz::Cache::File.new
|
60
|
+
assert_nothing_raised do
|
61
|
+
File.new(obj.filename("test"), "w+").close
|
62
|
+
assert !obj.expire!("test")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
test "should get contents from file" do
|
67
|
+
obj = Regentanz::Cache::File.new
|
68
|
+
|
69
|
+
File.open(obj.filename('test_get'), 'w+') {|file| file.print "cached data" }
|
70
|
+
assert obj.available?('test_get')
|
71
|
+
assert_equal "cached data", obj.get('test_get')
|
72
|
+
# cache not available, return false
|
73
|
+
assert_nil obj.get("does not exist")
|
74
|
+
end
|
75
|
+
|
76
|
+
test "should rescue get from reading errors" do
|
77
|
+
obj = Regentanz::Cache::File.new
|
78
|
+
File.open(obj.filename('test'), 'w+') {|file| file.print "cached data" }
|
79
|
+
File.expects(:open).raises(SystemCallError, "pretend something went wrong").once
|
80
|
+
|
81
|
+
assert_nothing_raised do
|
82
|
+
assert !obj.get("test")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
test "should check validity" do
|
87
|
+
obj = Regentanz::Cache::File.new
|
88
|
+
assert !obj.valid?('test')
|
89
|
+
File.open(obj.filename('test'), 'w+') { |file| file.puts valid_xml_response }
|
90
|
+
|
91
|
+
# valid_xml_response contains current datestamp,
|
92
|
+
# so should be valid on all fronts
|
93
|
+
assert obj.valid?('test')
|
94
|
+
|
95
|
+
# Pretend the file is too old
|
96
|
+
Regentanz.configuration.cache_ttl = 0
|
97
|
+
assert !obj.valid?('test')
|
98
|
+
end
|
99
|
+
|
100
|
+
test "should rescue valid from REXML errors" do
|
101
|
+
obj = Regentanz::Cache::File.new
|
102
|
+
File.open(obj.filename('test'), 'w+') { |file| file.puts invalid_xml_response }
|
103
|
+
REXML::Document.expects(:new).raises(REXML::ParseException, "pretend something went wrong")
|
104
|
+
|
105
|
+
assert_nothing_raised do
|
106
|
+
assert !obj.valid?('test')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# ##############################
|
111
|
+
# Retry-state tests
|
112
|
+
# ##############################
|
113
|
+
|
114
|
+
test "should inform about retry state" do
|
115
|
+
obj = Regentanz::Cache::File.new
|
116
|
+
assert !obj.waiting_for_retry?
|
117
|
+
|
118
|
+
File.expects(:exists?).with(Regentanz.configuration.retry_marker).returns(true)
|
119
|
+
assert obj.waiting_for_retry?
|
120
|
+
end
|
121
|
+
|
122
|
+
test "should check if retry wait time is over" do
|
123
|
+
obj = Regentanz::Cache::File.new
|
124
|
+
File.new(Regentanz.configuration.retry_marker, "w+").close
|
125
|
+
Regentanz.configuration.retry_ttl = 1000.hours.to_i # something incredibly high to warrant retry state
|
126
|
+
assert !obj.unset_retry_state! # not waited long enough
|
127
|
+
|
128
|
+
Regentanz.configuration.retry_ttl = 0
|
129
|
+
assert obj.unset_retry_state!
|
130
|
+
assert !File.exists?(Regentanz.configuration.retry_marker)
|
131
|
+
end
|
132
|
+
|
133
|
+
test "should enter retry state" do
|
134
|
+
obj = Regentanz::Cache::File.new
|
135
|
+
assert !File.exists?(Regentanz.configuration.retry_marker)
|
136
|
+
assert obj.set_retry_state!
|
137
|
+
assert obj.set_retry_state! # subsequent calls return the same
|
138
|
+
assert File.exists?(Regentanz.configuration.retry_marker)
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class CallbacksTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@object = Object.new
|
7
|
+
@object.extend Regentanz::Callbacks
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_should_define_constant
|
11
|
+
assert Regentanz::Callbacks::CALLBACKS
|
12
|
+
expected_callbacks = [:api_failure_detected, :api_failure_resumed]
|
13
|
+
assert_equal expected_callbacks, Regentanz::Callbacks::CALLBACKS
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_google_weather_should_include_callbacks
|
17
|
+
assert Regentanz::GoogleWeather.included_modules.include?(Regentanz::Callbacks)
|
18
|
+
assert Regentanz::GoogleWeather.included_modules.include?(ActiveSupport::Callbacks)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_define_each_callback_method
|
22
|
+
Regentanz::Callbacks::CALLBACKS.each do |callback_method|
|
23
|
+
assert @object.private_methods.include?(callback_method.to_s), "#{callback_method} not defined"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
require "tmpdir"
|
3
|
+
|
4
|
+
class ConfigurationTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
test "should configure Regentanz" do
|
7
|
+
assert_respond_to Regentanz, :configure
|
8
|
+
assert_respond_to Regentanz, :configuration
|
9
|
+
assert_not_nil Regentanz.configuration
|
10
|
+
|
11
|
+
Regentanz.configure do |config|
|
12
|
+
config.do_not_get_weather = true
|
13
|
+
end
|
14
|
+
assert_not_nil Regentanz.configuration
|
15
|
+
assert Regentanz.configuration.do_not_get_weather
|
16
|
+
end
|
17
|
+
|
18
|
+
test "should have configuration" do
|
19
|
+
configuration_options = [
|
20
|
+
:base_url,
|
21
|
+
:cache_backend,
|
22
|
+
:cache_dir,
|
23
|
+
:cache_prefix,
|
24
|
+
:cache_ttl,
|
25
|
+
:retry_marker,
|
26
|
+
:retry_ttl,
|
27
|
+
:do_not_get_weather,
|
28
|
+
:suppress_stderr_output
|
29
|
+
]
|
30
|
+
assert_equal configuration_options, Regentanz::Configuration::OPTIONS, "Diff: #{configuration_options - Regentanz::Configuration::OPTIONS}"
|
31
|
+
obj = Regentanz::Configuration.new
|
32
|
+
configuration_options.each do |config_option|
|
33
|
+
assert_respond_to obj, config_option
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test "every DEFAULT_OPTION should have a cattr_accessor" do
|
38
|
+
assert_not_nil Regentanz::Configuration::DEFAULT_OPTIONS
|
39
|
+
Regentanz::Configuration::DEFAULT_OPTIONS.each do |config_option|
|
40
|
+
assert_respond_to Regentanz::Configuration, :"default_#{config_option}"
|
41
|
+
assert_not_nil Regentanz::Configuration.send(:"default_#{config_option}")
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
test "instance should have sane defaults" do
|
47
|
+
obj = Regentanz::Configuration.new
|
48
|
+
tmpdir = Dir.tmpdir
|
49
|
+
assert_equal "http://www.google.com/ig/api", obj.base_url
|
50
|
+
assert_equal "#{tmpdir}", obj.cache_dir
|
51
|
+
assert_equal "regentanz", obj.cache_prefix
|
52
|
+
assert_equal 14400, obj.cache_ttl
|
53
|
+
assert_equal 3600, obj.retry_ttl
|
54
|
+
assert_equal "#{tmpdir}/regentanz_api_retry.txt", obj.retry_marker
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class CurrentConditionTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "should define setters and getters" do
|
6
|
+
obj = Regentanz::Conditions::Current.new
|
7
|
+
[:condition, :style, :icon, :humidity, :wind_condition, :temp_c, :temp_f].each do |attr|
|
8
|
+
assert_respond_to obj, attr
|
9
|
+
assert_respond_to obj, :"#{attr}="
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
test "should initialize with attributes hash" do
|
14
|
+
attributes = {
|
15
|
+
"condition" => "Klar",
|
16
|
+
"temp_f" => "77",
|
17
|
+
"temp_c" => "25",
|
18
|
+
"humidity" => "Feuchtigkeit: 57 %",
|
19
|
+
"icon" => "http://www.google.com/ig/images/weather/sunny.gif",
|
20
|
+
"style" => "sunny",
|
21
|
+
"wind_condition" => "Wind: W mit 24 km/h"
|
22
|
+
}
|
23
|
+
obj = Regentanz::Conditions::Current.new(attributes)
|
24
|
+
assert_equal "Klar", obj.condition
|
25
|
+
assert_equal 77, obj.temp_f
|
26
|
+
assert_equal 25, obj.temp_c
|
27
|
+
assert_equal "Feuchtigkeit: 57 %", obj.humidity
|
28
|
+
assert_equal "http://www.google.com/ig/images/weather/sunny.gif", obj.icon
|
29
|
+
assert_equal "sunny", obj.style
|
30
|
+
assert_equal "Wind: W mit 24 km/h", obj.wind_condition
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class ForecastConditionTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@object = Regentanz::Conditions::Forecast.new
|
7
|
+
end
|
8
|
+
|
9
|
+
test "should define setters and getters" do
|
10
|
+
[:condition, :style, :icon, :day_of_week, :high, :low].each do |attr|
|
11
|
+
assert_respond_to @object, attr
|
12
|
+
assert_respond_to @object, :"#{attr}="
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test "should initialize with attributes hash" do
|
17
|
+
attributes = {
|
18
|
+
"high" => "31",
|
19
|
+
"condition" => "Vereinzelt Regen",
|
20
|
+
"icon" => "http://www.google.com/ig/images/weather/chance_of_rain.gif",
|
21
|
+
"day_of_week" =>"Do.",
|
22
|
+
"low" => "16",
|
23
|
+
"style" => "chance-of-rain"
|
24
|
+
}
|
25
|
+
|
26
|
+
obj = Regentanz::Conditions::Forecast.new(attributes)
|
27
|
+
assert_equal 31, obj.high
|
28
|
+
assert_equal "Vereinzelt Regen", obj.condition
|
29
|
+
assert_equal "http://www.google.com/ig/images/weather/chance_of_rain.gif", obj.icon
|
30
|
+
assert_equal "Do.", obj.day_of_week
|
31
|
+
assert_equal 16, obj.low
|
32
|
+
assert_equal "chance-of-rain", obj.style
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|