lita-forecast 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.
@@ -0,0 +1,34 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'English'
3
+
4
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
5
+
6
+ require 'lita-forecast/version'
7
+
8
+ Gem::Specification.new do |g|
9
+ g.name = 'lita-forecast'
10
+ g.version = LitaForecast::VERSION
11
+ g.date = Time.now.strftime('%Y-%m-%d')
12
+ g.description = 'Lita plugin for Forecast.io'
13
+ g.summary = 'Lita + Forecast.io'
14
+ g.authors = ['Tim Heckman']
15
+ g.email = 't@heckman.io'
16
+ g.homepage = 'https://github.com/theckman/lita_forecast'
17
+ g.license = 'MIT'
18
+
19
+ g.test_files = %x(git ls-files spec/*).split
20
+ g.files = %x(git ls-files).split
21
+
22
+ g.add_development_dependency 'bundler', '~> 1.5'
23
+ g.add_development_dependency 'rake', '~> 10.1.0'
24
+ g.add_development_dependency 'rubocop', '~> 0.19.1'
25
+ g.add_development_dependency 'rspec', '>= 3.0.0.beta2'
26
+ g.add_development_dependency 'fuubar', '~> 1.3.2'
27
+ g.add_development_dependency 'coveralls', '~> 0.7.0'
28
+ g.add_development_dependency 'simplecov', '~> 0.8.2'
29
+
30
+ g.add_runtime_dependency 'lita', '~>3.0.0'
31
+ g.add_runtime_dependency 'forecast_io', '~>2.0.0'
32
+ g.add_runtime_dependency 'geocoder', '~>1.1.9'
33
+ g.add_runtime_dependency 'compass_rose', '~> 0.1.0'
34
+ end
@@ -0,0 +1,264 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe LitaForecast::Current do
5
+ let(:forecast) do
6
+ {
7
+ 'currently' => {
8
+ 'temperature' => 100.11,
9
+ 'apparentTemperature' => 102.11,
10
+ 'summary' => 'weather',
11
+ 'windBearing' => 0,
12
+ 'windSpeed' => 5.11,
13
+ 'humidity' => 0.10,
14
+ 'dewPoint' => 20.11,
15
+ 'pressure' => 1020.11,
16
+ 'cloudCover' => 0.01
17
+ },
18
+ 'minutely' => { 'summary' => 'minutely weather' },
19
+ 'hourly' => { 'summary' => 'hourly weather' },
20
+ 'flags' => { 'units' => 'us' }
21
+ }
22
+ end
23
+ let(:current) { described_class.new(forecast) }
24
+
25
+ describe '#new' do
26
+ context 'when given more than one arg' do
27
+ it 'should raise error ArgumentError' do
28
+ expect do
29
+ LitaForecast::Current.new(nil, nil)
30
+ end.to raise_error ArgumentError
31
+ end
32
+ end
33
+
34
+ context 'when given less than one arg' do
35
+ it 'should raise error ArgumentError' do
36
+ expect do
37
+ LitaForecast::Current.new
38
+ end.to raise_error ArgumentError
39
+ end
40
+ end
41
+
42
+ context 'when provided valid arguments' do
43
+ subject { LitaForecast::Current.new(forecast) }
44
+
45
+ it { should be_an_instance_of LitaForecast::Current }
46
+
47
+ it 'should set the f instance variable' do
48
+ expect(subject.instance_variable_get(:@f)).to eql forecast
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '.currently' do
54
+ context 'when given one arg' do
55
+ it 'should raise error ArgumentError' do
56
+ expect do
57
+ current.send(:currently, nil)
58
+ end.to raise_error ArgumentError
59
+ end
60
+ end
61
+
62
+ context 'when passed no args' do
63
+ subject { current.send(:currently) }
64
+
65
+ it { should be_an_instance_of Hash }
66
+
67
+ it { should eql forecast['currently'] }
68
+ end
69
+ end
70
+
71
+ describe '.temp' do
72
+ context 'when given one arg' do
73
+ it 'should raise error ArgumentError' do
74
+ expect do
75
+ current.send(:temp, nil)
76
+ end.to raise_error ArgumentError
77
+ end
78
+ end
79
+
80
+ context 'when passed no args' do
81
+ subject { current.send(:temp) }
82
+ let(:temp) { '100.1F' }
83
+
84
+ it { should be_an_instance_of String }
85
+
86
+ it { should eql temp }
87
+ end
88
+ end
89
+
90
+ describe '.feels' do
91
+ context 'when given one arg' do
92
+ it 'should raise error ArgumentError' do
93
+ expect do
94
+ current.send(:feels, nil)
95
+ end.to raise_error ArgumentError
96
+ end
97
+ end
98
+
99
+ context 'when passed no args' do
100
+ subject { current.send(:feels) }
101
+ let(:feels) { '102.1F' }
102
+
103
+ it { should be_an_instance_of String }
104
+
105
+ it { should eql feels }
106
+ end
107
+ end
108
+
109
+ describe '.wind' do
110
+ context 'when given one arg' do
111
+ it 'should raise error ArgumentError' do
112
+ expect do
113
+ current.send(:wind, nil)
114
+ end.to raise_error ArgumentError
115
+ end
116
+ end
117
+
118
+ context 'when passed no args' do
119
+ subject { current.send(:wind) }
120
+ let(:wind) { 'N 5.1mph' }
121
+
122
+ it { should be_an_instance_of String }
123
+
124
+ it { should eql wind }
125
+ end
126
+ end
127
+
128
+ describe '.humidity' do
129
+ context 'when given one arg' do
130
+ it 'should raise error ArgumentError' do
131
+ expect do
132
+ current.send(:humidity, nil)
133
+ end.to raise_error ArgumentError
134
+ end
135
+ end
136
+
137
+ context 'when passed no args' do
138
+ subject { current.send(:humidity) }
139
+ let(:humidity) { '10%' }
140
+
141
+ it { should be_an_instance_of String }
142
+
143
+ it { should eql humidity }
144
+ end
145
+ end
146
+
147
+ describe '.dew_pt' do
148
+ context 'when given one arg' do
149
+ it 'should raise error ArgumentError' do
150
+ expect do
151
+ current.send(:dew_pt, nil)
152
+ end.to raise_error ArgumentError
153
+ end
154
+ end
155
+
156
+ context 'when passed no args' do
157
+ subject { current.send(:dew_pt) }
158
+ let(:dew_pt) { '20.1F' }
159
+
160
+ it { should be_an_instance_of String }
161
+
162
+ it { should eql dew_pt }
163
+ end
164
+ end
165
+
166
+ describe '.pressure' do
167
+ context 'when given one arg' do
168
+ it 'should raise error ArgumentError' do
169
+ expect do
170
+ current.send(:pressure, nil)
171
+ end.to raise_error ArgumentError
172
+ end
173
+ end
174
+
175
+ context 'when passed no args' do
176
+ subject { current.send(:pressure) }
177
+ let(:pressure) { '1020.1mb' }
178
+
179
+ it { should be_an_instance_of String }
180
+
181
+ it { should eql pressure }
182
+ end
183
+ end
184
+
185
+ describe '.clouds' do
186
+ context 'when given one arg' do
187
+ it 'should raise error ArgumentError' do
188
+ expect do
189
+ current.send(:clouds, nil)
190
+ end.to raise_error ArgumentError
191
+ end
192
+ end
193
+
194
+ context 'when passed no args' do
195
+ subject { current.send(:clouds) }
196
+ let(:clouds) { '1%' } # these clouds are the 1%... (horrible joke) //TH
197
+
198
+ it { should be_an_instance_of String }
199
+
200
+ it { should eql clouds }
201
+ end
202
+ end
203
+
204
+ describe '.next_hour' do
205
+ context 'when given one arg' do
206
+ it 'should raise error ArgumentError' do
207
+ expect do
208
+ current.send(:next_hour, nil)
209
+ end.to raise_error ArgumentError
210
+ end
211
+ end
212
+
213
+ context 'when passed no args' do
214
+ subject { current.send(:next_hour) }
215
+ let(:next_hour) { 'minutely weather' }
216
+
217
+ it { should be_an_instance_of String }
218
+
219
+ it { should eql next_hour }
220
+ end
221
+ end
222
+
223
+ describe '.today' do
224
+ context 'when given one arg' do
225
+ it 'should raise error ArgumentError' do
226
+ expect do
227
+ current.send(:today, nil)
228
+ end.to raise_error ArgumentError
229
+ end
230
+ end
231
+
232
+ context 'when passed no args' do
233
+ subject { current.send(:today) }
234
+ let(:today) { 'hourly weather' }
235
+
236
+ it { should be_an_instance_of String }
237
+
238
+ it { should eql today }
239
+ end
240
+ end
241
+
242
+ describe '.conditions' do
243
+ subject { LitaForecast::Current.new(forecast).conditions }
244
+ let(:fc_string) do
245
+ '100.1F (feels like 102.1F) weather; Winds N 5.1mph; Humidity 10%; ' \
246
+ "Dew Pt 20.1F; Pressure 1020.1mb; Cloud cover 1%.\n" \
247
+ 'Next hour: minutely weather Next 24h: hourly weather'
248
+ end
249
+
250
+ context 'when given one arg' do
251
+ it 'should raise error ArgumentError' do
252
+ expect do
253
+ LitaForecast::Current.new(forecast).conditions(nil)
254
+ end.to raise_error ArgumentError
255
+ end
256
+ end
257
+
258
+ context 'when called with no args' do
259
+ it { should be_an_instance_of String }
260
+
261
+ it { should eql fc_string }
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,260 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe LitaForecast::Future do
5
+ let(:forecast) do
6
+ {
7
+ 'flags' => { 'units' => 'us' },
8
+ 'daily' => {
9
+ 'summary' => 'daily weather',
10
+ 'data' => [
11
+ {
12
+ 'summary' => 'weather today!',
13
+ 'temperatureMax' => 68.0,
14
+ 'temperatureMin' => 60.2,
15
+ 'precipProbability' => 0,
16
+ 'windSpeed' => 0,
17
+ 'windBearing' => 0
18
+ },
19
+ {
20
+ 'summary' => 'weather tomorrow!',
21
+ 'temperatureMax' => 70.0,
22
+ 'temperatureMin' => 62.1,
23
+ 'precipProbability' => 1,
24
+ 'precipType' => 'rain',
25
+ 'windSpeed' => 10,
26
+ 'windBearing' => 270
27
+ }
28
+ ]
29
+ }
30
+ }
31
+ end
32
+
33
+ before do
34
+ @future = LitaForecast::Future.new(forecast)
35
+ end
36
+
37
+ describe '#new' do
38
+ context 'when given more than one arg' do
39
+ it 'should raise ArgumentError' do
40
+ expect do
41
+ LitaForecast::Future.new(nil, nil)
42
+ end.to raise_error ArgumentError
43
+ end
44
+ end
45
+
46
+ context 'when given less than one arg' do
47
+ it 'should raise ArgumentError' do
48
+ expect do
49
+ LitaForecast::Future.new
50
+ end.to raise_error ArgumentError
51
+ end
52
+ end
53
+
54
+ context 'when passed a ForecastIO-like response' do
55
+ subject { LitaForecast::Future.new(forecast) }
56
+
57
+ it { should be_an_instance_of LitaForecast::Future }
58
+
59
+ it 'should set the ForecastIO-like object to the @f variable' do
60
+ i = subject.instance_variable_get(:@f)
61
+ expect(i).to eql forecast
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '.daily' do
67
+ context 'when passed more than zero args' do
68
+ it 'should raise ArgumentError' do
69
+ expect do
70
+ @future.send(:daily, nil)
71
+ end.to raise_error ArgumentError
72
+ end
73
+ end
74
+
75
+ context 'when called' do
76
+ subject { @future.send(:daily) }
77
+
78
+ it { should be_an_instance_of Array }
79
+
80
+ it { should eql forecast['daily']['data'] }
81
+ end
82
+ end
83
+
84
+ describe '.generate_summary' do
85
+ context 'when passed more than zero args' do
86
+ it 'should raise ArgumentError' do
87
+ expect do
88
+ @future.send(:generate_summary, nil)
89
+ end.to raise_error ArgumentError
90
+ end
91
+ end
92
+
93
+ context 'when called' do
94
+ subject { @future.send(:generate_summary) }
95
+
96
+ it { should be_an_instance_of String }
97
+
98
+ it { should eql "Summary: daily weather\n" }
99
+ end
100
+ end
101
+
102
+ describe '.summary' do
103
+ context 'when given more than zero args' do
104
+ it 'should raise ArgumentError' do
105
+ expect do
106
+ @future.send(:summary, nil)
107
+ end.to raise_error ArgumentError
108
+ end
109
+ end
110
+
111
+ context 'when called' do
112
+ before do
113
+ @future.instance_variable_set(:@i, forecast['daily']['data'][0])
114
+ @future.instance_variable_set(:@d, 'Today')
115
+ end
116
+
117
+ subject { @future.send(:summary) }
118
+
119
+ it { should be_an_instance_of String }
120
+
121
+ it { should eql 'Today: weather today!' }
122
+ end
123
+ end
124
+
125
+ describe '.high_low' do
126
+ context 'when given more than zero args' do
127
+ it 'should raise ArgumentError' do
128
+ expect do
129
+ @future.send(:high_low, nil)
130
+ end.to raise_error ArgumentError
131
+ end
132
+ end
133
+
134
+ context 'when called' do
135
+ before do
136
+ @future.instance_variable_set(:@i, forecast['daily']['data'][0])
137
+ @future.instance_variable_set(:@d, 'Today')
138
+ end
139
+ let(:good_string) { 'High 68F, Low 60F.' }
140
+
141
+ subject { @future.send(:high_low) }
142
+
143
+ it { should be_an_instance_of String }
144
+
145
+ it { should eql good_string }
146
+ end
147
+ end
148
+
149
+ describe '.precip' do
150
+ context 'when given more than zero args' do
151
+ it 'should raise ArgumentError' do
152
+ expect do
153
+ @future.send(:precip, nil)
154
+ end.to raise_error ArgumentError
155
+ end
156
+ end
157
+
158
+ context 'when called with no preciptType' do
159
+ before do
160
+ @future.instance_variable_set(:@i, forecast['daily']['data'][0])
161
+ end
162
+
163
+ subject { @future.send(:precip) }
164
+
165
+ it { should be_an_instance_of String }
166
+
167
+ it { should eql '0% chance of precipitation.' }
168
+ end
169
+
170
+ context 'when called with a precipType' do
171
+ before do
172
+ @future.instance_variable_set(:@i, forecast['daily']['data'][1])
173
+ end
174
+
175
+ subject { @future.send(:precip) }
176
+
177
+ it { should be_an_instance_of String }
178
+
179
+ it { should eql '100% chance of rain.' }
180
+ end
181
+ end
182
+
183
+ describe '.wind' do
184
+ context 'when given more than zero args' do
185
+ it 'should raise ArgumentError' do
186
+ expect do
187
+ @future.send(:wind, nil)
188
+ end.to raise_error ArgumentError
189
+ end
190
+ end
191
+
192
+ context 'when called' do
193
+ before do
194
+ @future.instance_variable_set(:@i, forecast['daily']['data'][0])
195
+ end
196
+
197
+ subject { @future.send(:wind) }
198
+
199
+ it { should be_an_instance_of String }
200
+
201
+ it { should eql 'Winds N 0mph.' }
202
+ end
203
+ end
204
+
205
+ describe '.generate_day' do
206
+ context 'when given more than two args' do
207
+ it 'should raise ArgumentError' do
208
+ expect do
209
+ @future.send(:generate_day, nil, nil, nil)
210
+ end.to raise_error ArgumentError
211
+ end
212
+ end
213
+
214
+ context 'when given less than two args' do
215
+ it 'should raise ArgumentError' do
216
+ expect do
217
+ @future.send(:generate_day, nil)
218
+ end.to raise_error ArgumentError
219
+ end
220
+ end
221
+
222
+ context 'when index is 0 and day is Today' do
223
+ let(:good_string) do
224
+ "Today: weather today! High 68F, Low 60F. 0% chance of " \
225
+ "precipitation. Winds N 0mph.\n"
226
+ end
227
+ subject { @future.send(:generate_day, 0, 'Today') }
228
+
229
+ it { should be_an_instance_of String }
230
+
231
+ it { should eql good_string }
232
+ end
233
+ end
234
+
235
+ describe '.conditions' do
236
+ context 'when given more than zero args' do
237
+ it 'should raise ArgumentError' do
238
+ expect do
239
+ @future.conditions(nil)
240
+ end.to raise_error ArgumentError
241
+ end
242
+ end
243
+
244
+ context 'when called' do
245
+ let(:good_string) do
246
+ "Summary: daily weather\n" \
247
+ "Today: weather today! High 68F, Low 60F. 0% chance of " \
248
+ "precipitation. Winds N 0mph.\n" \
249
+ "Tomorrow: weather tomorrow! High 70F, Low 62F. 100% chance of " \
250
+ "rain. Winds W 10mph.\n"
251
+ end
252
+
253
+ subject { @future.conditions }
254
+
255
+ it { should be_an_instance_of String }
256
+
257
+ it { should eql good_string }
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,116 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require 'spec_helper'
3
+ require 'hashie'
4
+
5
+ # Class for stubbing Geolocation data
6
+ #
7
+ class MockGeocoderClass
8
+ DATA = {
9
+ 'address_components' => [
10
+ { 'long_name' => 'San Francisco', 'types' => %w(locality) },
11
+ { 'short_name' => 'CA', 'types' => %w(administrative_area_level_1) }
12
+ ],
13
+ 'geometry' => {
14
+ 'location' => { 'lat' => 37.7749295, 'lng' => -122.4194155 }
15
+ }
16
+ }
17
+
18
+ def self.data
19
+ DATA
20
+ end
21
+ end
22
+
23
+ # Class for stubbing Redis class
24
+ #
25
+ class MockRedisClass
26
+ def self.hgetall(search)
27
+ Hashie::Mash.new({})
28
+ end
29
+ end
30
+
31
+ describe LitaForecast::Location do
32
+ before do
33
+ @lfloc = LitaForecast::Location.new(MockRedisClass)
34
+ end
35
+
36
+ describe '#new' do
37
+ context 'when passed more than one arg' do
38
+ it 'should raise ArgumentError' do
39
+ expect do
40
+ LitaForecast::Location.new(nil, nil)
41
+ end.to raise_error ArgumentError
42
+ end
43
+ end
44
+
45
+ context 'when passed less than one arg' do
46
+ it 'should raise ArgumentError' do
47
+ expect do
48
+ LitaForecast::Location.new
49
+ end.to raise_error ArgumentError
50
+ end
51
+ end
52
+
53
+ context 'when passed an object' do
54
+ subject { LitaForecast::Location.new(MockRedisClass) }
55
+
56
+ it { should be_an_instance_of LitaForecast::Location }
57
+ end
58
+ end
59
+
60
+ describe '.lita_redis' do
61
+ context 'when given an arg' do
62
+ subject { LitaForecast::Location.new(MockRedisClass).lita_redis }
63
+
64
+ it { should eql MockRedisClass }
65
+ end
66
+ end
67
+
68
+ describe '.find_location' do
69
+ before do
70
+ allow_any_instance_of(Geocoder).to receive(:search)
71
+ .and_return([MockGeocoderClass])
72
+ end
73
+
74
+ context 'when given more than one arg' do
75
+ it 'should raise ArgumentError' do
76
+ expect do
77
+ @lfloc.find_location(nil, nil)
78
+ end.to raise_error ArgumentError
79
+ end
80
+ end
81
+
82
+ context 'when given less tha one arg' do
83
+ it 'should raise ArgumentError' do
84
+ expect do
85
+ @lfloc.find_location
86
+ end.to raise_error ArgumentError
87
+ end
88
+ end
89
+
90
+ context 'when passed "san francisco" and not cached' do
91
+ let(:good_hash) do
92
+ { lat: 37.7749295, lng: -122.4194155, desc: 'San Francisco, CA' }
93
+ end
94
+
95
+ subject { @lfloc.find_location('san francisco') }
96
+
97
+ it { should be_an_instance_of Hash }
98
+
99
+ it { should eql good_hash }
100
+ end
101
+
102
+ context 'when passed "san francisco" and cached' do
103
+ before do
104
+ @cr = { lat: 37.7749295, lng: -122.4194155, desc: 'San Francisco, CA' }
105
+ allow_any_instance_of(MockRedisClass).to receive(:hgetall)
106
+ .and_return(@cr)
107
+ end
108
+
109
+ subject { @lfloc.find_location('san francisco') }
110
+
111
+ it { should be_an_instance_of Hash }
112
+
113
+ it { should eql @cr }
114
+ end
115
+ end
116
+ end