metar-parser 0.9.11 → 0.9.12

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,32 @@
1
+ load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+
3
+ describe Metar::Pressure do
4
+
5
+ context '.parse' do
6
+
7
+ it 'interprets the Q prefix as hectopascals' do
8
+ Metar::Pressure.parse( 'Q1300' ).value.
9
+ should be_within( 0.01 ).of( 1.3 )
10
+ end
11
+
12
+ it 'interprets the A prefix as inches of mercury' do
13
+ Metar::Pressure.parse( 'A1234' ).value.
14
+ should be_within( 0.01 ).of( 0.42 )
15
+ end
16
+
17
+ it 'require 4 digits' do
18
+ Metar::Pressure.parse( 'Q12345' ).
19
+ should be_nil
20
+ Metar::Pressure.parse( 'A123' ).
21
+ should be_nil
22
+ end
23
+
24
+ it 'returns nil for nil' do
25
+ Metar::Pressure.parse( nil ).
26
+ should be_nil
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
@@ -0,0 +1,196 @@
1
+ load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ # encoding: utf-8
3
+
4
+ require 'net/ftp'
5
+
6
+ describe Metar::Raw do
7
+
8
+ after :each do
9
+ Metar::Raw.send( :class_variable_set, '@@connection', nil )
10
+ end
11
+
12
+ context '.connection' do
13
+
14
+ context 'uncached' do
15
+
16
+ it 'sets up the connection' do
17
+ ftp = stub( 'ftp', :login => nil, :chdir => nil, :passive= => nil )
18
+
19
+ Net::FTP. should_receive( :new ).
20
+ and_return( ftp )
21
+
22
+ Metar::Raw.connect
23
+ end
24
+
25
+ end
26
+
27
+ context 'cached' do
28
+
29
+ before :each do
30
+ @ftp = stub( 'ftp' )
31
+ Metar::Raw.send( :class_variable_set, '@@connection', @ftp )
32
+ end
33
+
34
+ it 'does not connect to FTP' do
35
+ Net::FTP. should_not_receive( :new )
36
+
37
+ Metar::Raw.connection
38
+ end
39
+
40
+ it 'returns the cached connection' do
41
+ connection = Metar::Raw.connection
42
+
43
+ connection. should == @ftp
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ context '.connect' do
51
+
52
+ it 'sets up the connection' do
53
+ ftp = stub( 'ftp' )
54
+
55
+ Net::FTP. should_receive( :new ).
56
+ and_return( ftp )
57
+ ftp. should_receive( :login )
58
+ ftp. should_receive( :chdir )
59
+ ftp. should_receive( :passive= ).
60
+ with( true )
61
+
62
+ Metar::Raw.connect
63
+ end
64
+
65
+ end
66
+
67
+ context '.fetch' do
68
+
69
+ it 'uses the connection' do
70
+ ftp = stub( 'ftp', :login => nil, :chdir => nil, :passive= => nil, :retrbinary => nil )
71
+
72
+ Net::FTP. should_receive( :new ).
73
+ and_return( ftp )
74
+
75
+ Metar::Raw.fetch( 'the_cccc' )
76
+ end
77
+
78
+ it 'downloads the raw report' do
79
+ ftp = stub( 'ftp', :login => nil, :chdir => nil, :passive= => nil )
80
+ Net::FTP.stub!( :new ).and_return( ftp )
81
+
82
+ ftp. should_receive( :retrbinary ) do | *args, &block |
83
+ args[ 0 ]. should == 'RETR the_cccc.TXT'
84
+ args[ 1 ]. should be_a Fixnum
85
+ end
86
+
87
+ Metar::Raw.fetch( 'the_cccc' )
88
+ end
89
+
90
+ it 'returns the data' do
91
+ ftp = stub( 'ftp', :login => nil, :chdir => nil, :passive= => nil )
92
+ def ftp.retrbinary( *args, &block )
93
+ block.call "chunk 1\n"
94
+ block.call "chunk 2\n"
95
+ end
96
+ Net::FTP.stub!( :new ).and_return( ftp )
97
+
98
+ raw = Metar::Raw.fetch( 'the_cccc' )
99
+
100
+ raw. should == "chunk 1\nchunk 2\n"
101
+ end
102
+
103
+ it 'retries retrieval once' do
104
+ ftp = stub( 'ftp', :login => nil, :chdir => nil, :passive= => nil )
105
+ def ftp.attempt
106
+ @attempt
107
+ end
108
+ def ftp.attempt=(a)
109
+ @attempt = a
110
+ end
111
+ ftp.attempt = 0
112
+ def ftp.retrbinary( *args, &block )
113
+ self.attempt = self.attempt + 1
114
+ raise Net::FTPTempError if self.attempt == 1
115
+ block.call "chunk 1\n"
116
+ block.call "chunk 2\n"
117
+ end
118
+ Net::FTP.stub!( :new ).and_return( ftp )
119
+
120
+ raw = Metar::Raw.fetch( 'the_cccc' )
121
+
122
+ raw. should == "chunk 1\nchunk 2\n"
123
+ end
124
+
125
+ it 'fails with an error, if retrieval fails twice' do
126
+ ftp = stub( 'ftp', :login => nil, :chdir => nil, :passive= => nil )
127
+ def ftp.attempt
128
+ @attempt
129
+ end
130
+ def ftp.attempt=(a)
131
+ @attempt = a
132
+ end
133
+ ftp.attempt = 0
134
+ def ftp.retrbinary( *args, &block )
135
+ self.attempt = self.attempt + 1
136
+ raise Net::FTPTempError
137
+ end
138
+ Net::FTP.stub!( :new ).and_return( ftp )
139
+
140
+ expect do
141
+ Metar::Raw.fetch( 'the_cccc' )
142
+ end. to raise_error( RuntimeError, /failed 2 times/)
143
+ end
144
+
145
+ end
146
+
147
+ context 'initialization' do
148
+
149
+ it 'should accept CCCC codes' do
150
+ raw = Metar::Raw.new( 'XXXX' )
151
+
152
+ raw.cccc. should == 'XXXX'
153
+ end
154
+
155
+ it 'should accept Stations' do
156
+ station = stub( 'Metar::Station', :cccc => 'YYYY' )
157
+ raw = Metar::Raw.new( station )
158
+
159
+ raw.cccc. should == 'YYYY'
160
+ end
161
+
162
+ it 'should parse data, if supplied' do
163
+ raw = Metar::Raw.new( 'XXXX', raw_metar )
164
+
165
+ raw.data. should == raw_metar
166
+ raw.raw_time. should == @raw_time
167
+ raw.metar. should == @metar
168
+ raw.time. should == Time.parse( @raw_time )
169
+ end
170
+
171
+ end
172
+
173
+ context 'lazy loading' do
174
+
175
+ it 'should fetch data on demand' do
176
+ raw = Metar::Raw.new( 'ESSB' )
177
+
178
+ Metar::Raw. should_receive( :fetch ).
179
+ with( 'ESSB' ).
180
+ and_return( raw_metar )
181
+
182
+ raw.metar
183
+
184
+ raw.data. should == raw_metar
185
+ end
186
+
187
+ end
188
+
189
+ def raw_metar
190
+ @raw_time = "2010/02/15 10:20"
191
+ @metar = "ESSB 151020Z 26003KT 2000 R12/1000N R30/1500N VV002 M07/M07 Q1013 1271//55"
192
+ "#{ @raw_time }\n#{ @metar }"
193
+ end
194
+
195
+ end
196
+
@@ -0,0 +1,187 @@
1
+ load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ # encoding: utf-8
3
+
4
+ describe Metar::Report do
5
+
6
+ context 'initialization' do
7
+
8
+ it 'loads the Station' do
9
+ station = stub( 'station' )
10
+ parser = stub( 'parser', :station_code => 'SSSS' )
11
+
12
+ Metar::Station. should_receive( :find_by_cccc ).
13
+ with( 'SSSS' ).
14
+ and_return( station )
15
+
16
+ Metar::Report.new( parser )
17
+ end
18
+
19
+ end
20
+
21
+ context 'attributes' do
22
+
23
+ before :each do
24
+ @locale = I18n.locale
25
+ @station_code = 'SSSS'
26
+ @metar_date = '2008/05/06'
27
+ @metar_time = '10:56'
28
+ @metar_datetime = "#{@metar_date} #{@metar_time}"
29
+ @station = stub( 'station', :name => 'Airport 1',
30
+ :country => 'Wwwwww' )
31
+ @parser = stub( 'parser', :station_code => @station_code,
32
+ :date => Date.parse( @metar_date ),
33
+ :time => Time.parse( @metar_datetime ),
34
+ :observer => :real )
35
+ Metar::Station.stub( :find_by_cccc ).with( @station_code ).and_return( @station )
36
+ end
37
+
38
+ subject { Metar::Report.new( @parser ) }
39
+
40
+ after :each do
41
+ I18n.locale = @locale
42
+ end
43
+
44
+ context '#date' do
45
+
46
+ it 'localizes' do
47
+ I18n.locale = :en
48
+
49
+ subject.date. should == '06/05/2008'
50
+
51
+ I18n.locale = :it
52
+
53
+ subject.date. should == '06/05/2008'
54
+ end
55
+
56
+ end
57
+
58
+ context '#time' do
59
+ specify { subject.time. should == @metar_time }
60
+ end
61
+
62
+ context '#observer' do
63
+ specify { subject.observer. should == 'real' }
64
+ end
65
+
66
+ specify { subject.station_name.
67
+ should == 'Airport 1' }
68
+
69
+ specify { subject.station_country.
70
+ should == 'Wwwwww' }
71
+
72
+ specify { subject.station_code.
73
+ should == @station_code }
74
+
75
+ context 'proxied from parser' do
76
+
77
+ context 'singly' do
78
+ [
79
+ :wind,
80
+ :variable_wind,
81
+ :visibility,
82
+ :vertical_visibility,
83
+ :temperature,
84
+ :dew_point,
85
+ :sea_level_pressure,
86
+ ].each do | attribute |
87
+ example attribute do
88
+ @attr = stub( attribute.to_s )
89
+ @parser.stub!( attribute => @attr )
90
+
91
+ @attr. should_receive( :to_s )
92
+
93
+ subject.send( attribute )
94
+ end
95
+ end
96
+
97
+ context '#sky_summary' do
98
+
99
+ it 'returns the summary' do
100
+ @skies1 = stub('sky_conditions')
101
+ @parser.stub!( :sky_conditions => [@skies1] )
102
+
103
+ @skies1. should_receive( :to_summary ).
104
+ and_return( 'skies1' )
105
+
106
+ subject.sky_summary. should == 'skies1'
107
+ end
108
+
109
+ it 'clear skies when missing' do
110
+ @parser.stub!( :sky_conditions => [] )
111
+
112
+ subject.sky_summary. should == 'clear skies'
113
+ end
114
+
115
+ it 'uses the last, if there is more than 1' do
116
+ @skies1 = stub('sky_conditions1' )
117
+ @skies2 = stub('sky_conditions2' )
118
+ @parser.stub!( :sky_conditions => [ @skies1, @skies2 ] )
119
+
120
+ @skies2. should_receive( :to_summary ).
121
+ and_return( 'skies2' )
122
+
123
+ subject.sky_summary. should == 'skies2'
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'joined' do
129
+
130
+ it '#runway_visible_range' do
131
+ @rvr1 = stub( 'rvr1', :to_s => 'rvr1' )
132
+ @rvr2 = stub( 'rvr2', :to_s => 'rvr2' )
133
+ @parser.stub!( :runway_visible_range => [ @rvr1, @rvr2 ] )
134
+
135
+ subject.runway_visible_range.
136
+ should == 'rvr1, rvr2'
137
+ end
138
+
139
+ it '#present_weather' do
140
+ @parser.stub!( :present_weather => [ 'pw1', 'pw2' ] )
141
+
142
+ subject.present_weather.should == 'pw1, pw2'
143
+ end
144
+
145
+ it '#remarks' do
146
+ @parser.stub!( :remarks => [ 'rem1', 'rem2' ] )
147
+
148
+ subject.remarks. should == 'rem1, rem2'
149
+ end
150
+
151
+ it '#sky_conditions' do
152
+ sky1 = stub( 'sky1', :to_s => 'sky1' )
153
+ sky2 = stub( 'sky2', :to_s => 'sky2' )
154
+ @parser.stub!( :sky_conditions => [ sky1, sky2 ] )
155
+
156
+ subject.sky_conditions. should == 'sky1, sky2'
157
+ end
158
+
159
+ end
160
+
161
+ end
162
+
163
+ it '#to_s' do
164
+ sky1 = stub( 'sky1', :to_summary => 'sky1' )
165
+ sky2 = stub( 'sky2', :to_summary => 'sky2' )
166
+ @parser.stub!( :wind => 'wind',
167
+ :visibility => 'visibility',
168
+ :present_weather => ['pw'],
169
+ :sky_conditions => [ sky1, sky2 ],
170
+ :temperature => 'temp' )
171
+ expected = <<EOT
172
+ name: Airport 1
173
+ country: Wwwwww
174
+ time: #{@metar_time}
175
+ wind: wind
176
+ visibility: visibility
177
+ weather: pw
178
+ sky: sky2
179
+ temperature: temp
180
+ EOT
181
+ subject.to_s. should == expected
182
+ end
183
+
184
+ end
185
+
186
+ end
187
+
@@ -0,0 +1,88 @@
1
+ load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ # encoding: utf-8
3
+
4
+ RSpec::Matchers.define :be_runway_visible_range do | designator, visibility1, visibility2, tendency |
5
+ match do | rvr |
6
+ if rvr.nil? && designator.nil?
7
+ true
8
+ elsif rvr.nil? != designator.nil?
9
+ false
10
+ elsif rvr.visibility1.nil? != visibility1.nil?
11
+ false
12
+ elsif rvr.visibility2.nil? != visibility2.nil?
13
+ false
14
+ elsif rvr.tendency.nil? != tendency.nil?
15
+ false
16
+ elsif ! visibility1.nil? &&
17
+ ( ( rvr.visibility1.distance.value - visibility1[0] ).abs > 0.01 ||
18
+ rvr.visibility1.comparator != visibility1[ 2 ] )
19
+ false
20
+ elsif ! visibility2.nil? &&
21
+ ( ( rvr.visibility2.distance.value - visibility2[0] ).abs > 0.02 ||
22
+ rvr.visibility2.comparator != visibility2[2] )
23
+ false
24
+ elsif tendency != rvr.tendency
25
+ false
26
+ else
27
+ true
28
+ end
29
+ end
30
+ end
31
+
32
+ describe Metar::RunwayVisibleRange do
33
+
34
+ context '.parse' do
35
+
36
+ [
37
+ [ 'understands R + nn + / + nnnn', 'R12/3400', [ '12', [3400.00, nil, nil], nil, nil ] ],
38
+ [ 'understands runway positions: RLC', 'R12L/3400', [ '12L', [3400.00, nil, nil], nil, nil ] ],
39
+ [ 'understands comparators: PM', 'R12/P3400', [ '12', [3400.00, nil, :more_than], nil, nil ] ],
40
+ [ 'understands tendencies: NUD', 'R12/3400U', [ '12', [3400.00, nil, nil], nil, :improving ] ],
41
+ [ 'understands feet', 'R12/3400FT', [ '12', [1036.32, nil, nil], nil, nil ] ],
42
+ [ 'understands second visibilties', 'R12/3400V1800FT', [ '12', [1036.32, nil, nil], [548.64, nil, nil], nil ] ],
43
+ [ 'returns nil for nil', nil, [ nil, nil, nil, nil ] ],
44
+ ].each do | docstring, raw, expected |
45
+ example docstring do
46
+ Metar::RunwayVisibleRange.parse( raw ).should be_runway_visible_range( *expected )
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ context '#to_s' do
53
+
54
+ before :all do
55
+ @locale = I18n.locale
56
+ I18n.locale = :it
57
+ end
58
+
59
+ after :all do
60
+ I18n.locale = @locale
61
+ end
62
+
63
+ [
64
+ [ 'v1', :en, [ [3400.00, nil, nil], nil, nil ], 'runway 14: 3400m' ],
65
+ [ 'v1 and v2', :en, [ [3400.00, nil, nil], [1900.00, nil, nil], nil ], 'runway 14: from 3400m to 1900m' ],
66
+ [ 'v1 and tendency', :en, [ [3400.00, nil, nil], nil, :improving ], 'runway 14: 3400m improving' ],
67
+ ].each do | docstring, locale, ( visibility1, visibility2, tendency ), expected |
68
+ d1 = Metar::Distance.new( visibility1[0] )
69
+ v1 = Metar::Visibility.new( d1, visibility1[1], visibility1[2] )
70
+ v2 =
71
+ if ! visibility2.nil?
72
+ d2 = Metar::Distance.new( visibility2[0] )
73
+ Metar::Visibility.new( d2, visibility2[1], visibility2[2] )
74
+ else
75
+ nil
76
+ end
77
+
78
+ example docstring + " (#{locale})" do
79
+ I18n.locale = locale
80
+ Metar::RunwayVisibleRange.new( '14', v1, v2, tendency ).to_s.
81
+ should == expected
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+