metar-parser 0.9.11 → 0.9.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+