spec/lib/aixm/feature/airspace_spec.rb in aixm-0.2.3 vs spec/lib/aixm/feature/airspace_spec.rb in aixm-0.3.0
- old
+ new
@@ -1,259 +1,382 @@
require_relative '../../../spec_helper'
describe AIXM::Feature::Airspace do
- context "incomplete" do
+
+ context "only required attributes set" do
subject do
- AIXM.airspace(name: 'foobar', type: 'D')
+ AIXM.airspace(type: "TMA", name: "Test TMA")
end
- describe :complete? do
- it "must fail validation" do
- subject.wont_be :complete?
+ describe :initialize do
+ it "sets defaults" do
+ subject.id.must_equal '22E2F734'
+ subject.layers.must_equal []
+ subject.geometry.must_be_instance_of AIXM::Component::Geometry
end
end
- end
- context "complete" do
- context "with one class layer" do
- subject do
- AIXM::Factory.polygon_airspace
+ describe :id= do
+ it "fails on invalid values" do
+ [:foobar, 123].wont_be_written_to subject, :id
end
- describe :complete? do
- it "must pass validation" do
- subject.must_be :complete?
- end
+ it "falls back to id derived from digest of id, name and short_name" do
+ subject.tap { |s| s.id = nil }.id.must_equal '22E2F734'
end
- describe :to_digest do
- it "must return digest of payload" do
- subject.to_digest.must_equal 367297292
- end
+ it "upcases value" do
+ subject.tap { |s| s.id = 'löl' }.id.must_equal 'LOEL'
end
+ end
- describe :to_aixm do
- it "must build correct XML with OFM extensions" do
- digest = subject.to_digest
- subject.to_aixm(:ofm).must_equal <<~"END"
- <!-- Airspace: [D] POLYGON AIRSPACE -->
- <Ase xt_classLayersAvail="false">
- <AseUid mid="#{digest}" newEntity="true">
- <codeType>D</codeType>
- <codeId>#{digest}</codeId>
- </AseUid>
- <txtLocalType>POLYGON</txtLocalType>
- <txtName>POLYGON AIRSPACE</txtName>
- <codeClass>C</codeClass>
- <codeDistVerUpper>STD</codeDistVerUpper>
- <valDistVerUpper>65</valDistVerUpper>
- <uomDistVerUpper>FL</uomDistVerUpper>
- <codeDistVerLower>STD</codeDistVerLower>
- <valDistVerLower>45</valDistVerLower>
- <uomDistVerLower>FL</uomDistVerLower>
- <codeDistVerMax>ALT</codeDistVerMax>
- <valDistVerMax>6000</valDistVerMax>
- <uomDistVerMax>FT</uomDistVerMax>
- <codeDistVerMnm>HEI</codeDistVerMnm>
- <valDistVerMnm>3000</valDistVerMnm>
- <uomDistVerMnm>FT</uomDistVerMnm>
- <Att>
- <codeWorkHr>H24</codeWorkHr>
- </Att>
- <txtRmk>polygon airspace</txtRmk>
- <xt_selAvail>false</xt_selAvail>
- </Ase>
- <Abd>
- <AbdUid>
- <AseUid mid="#{digest}" newEntity="true">
- <codeType>D</codeType>
- <codeId>#{digest}</codeId>
- </AseUid>
- </AbdUid>
- <Avx>
- <codeType>CWA</codeType>
- <geoLat>47.85916667N</geoLat>
- <geoLong>7.56000000E</geoLong>
- <codeDatum>WGE</codeDatum>
- <geoLatArc>47.90416667N</geoLatArc>
- <geoLongArc>7.56333333E</geoLongArc>
- </Avx>
- <Avx>
- <codeType>FNT</codeType>
- <geoLat>47.94361111N</geoLat>
- <geoLong>7.59583333E</geoLong>
- <codeDatum>WGE</codeDatum>
- <GbrUid>
- <txtName>FRANCE_GERMANY</txtName>
- </GbrUid>
- </Avx>
- <Avx>
- <codeType>GRC</codeType>
- <geoLat>47.85916667N</geoLat>
- <geoLong>7.56000000E</geoLong>
- <codeDatum>WGE</codeDatum>
- </Avx>
- </Abd>
- END
- end
+ describe :type= do
+ it "fails on invalid values" do
+ [nil, :foobar, 123].wont_be_written_to subject, :type
end
- context "with two class layers" do
- subject do
- AIXM::Factory.polygon_airspace.tap do |airspace|
- airspace.class_layers << AIXM::Factory.class_layer
- end
- end
+ it "looks up valid values" do
+ subject.tap { |s| s.type = :danger_area }.type.must_equal :danger_area
+ subject.tap { |s| s.type = :P }.type.must_equal :prohibited_area
+ end
+ end
- describe :complete? do
- it "must pass validation" do
- subject.must_be :complete?
- end
- end
+ describe :name= do
+ it "fails on invalid values" do
+ [:foobar, 123].wont_be_written_to subject, :name
+ end
- describe :to_digest do
- it "must return digest of payload" do
- subject.to_digest.must_equal 481196243
- end
- end
+ it "accepts nil value" do
+ [nil].must_be_written_to subject, :name
+ end
- describe :to_aixm do
- it "must build correct XML with OFM extensions" do
- digest = subject.to_digest
- subject.to_aixm(:ofm).must_equal <<~"END"
- <!-- Airspace: [D] POLYGON AIRSPACE -->
- <Ase xt_classLayersAvail="true">
- <AseUid mid="#{digest}" newEntity="true">
- <codeType>D</codeType>
- <codeId>#{digest}</codeId>
- </AseUid>
- <txtLocalType>POLYGON</txtLocalType>
- <txtName>POLYGON AIRSPACE</txtName>
- <codeClass>C</codeClass>
- <codeDistVerUpper>STD</codeDistVerUpper>
- <valDistVerUpper>65</valDistVerUpper>
- <uomDistVerUpper>FL</uomDistVerUpper>
- <codeDistVerLower>STD</codeDistVerLower>
- <valDistVerLower>45</valDistVerLower>
- <uomDistVerLower>FL</uomDistVerLower>
- <codeDistVerMax>ALT</codeDistVerMax>
- <valDistVerMax>6000</valDistVerMax>
- <uomDistVerMax>FT</uomDistVerMax>
- <codeDistVerMnm>HEI</codeDistVerMnm>
- <valDistVerMnm>3000</valDistVerMnm>
- <uomDistVerMnm>FT</uomDistVerMnm>
- <Att>
- <codeWorkHr>H24</codeWorkHr>
- </Att>
- <txtRmk>polygon airspace</txtRmk>
- <xt_selAvail>false</xt_selAvail>
- </Ase>
- <Abd>
- <AbdUid>
- <AseUid mid="#{digest}" newEntity="true">
- <codeType>D</codeType>
- <codeId>#{digest}</codeId>
- </AseUid>
- </AbdUid>
- <Avx>
- <codeType>CWA</codeType>
- <geoLat>47.85916667N</geoLat>
- <geoLong>7.56000000E</geoLong>
- <codeDatum>WGE</codeDatum>
- <geoLatArc>47.90416667N</geoLatArc>
- <geoLongArc>7.56333333E</geoLongArc>
- </Avx>
- <Avx>
- <codeType>FNT</codeType>
- <geoLat>47.94361111N</geoLat>
- <geoLong>7.59583333E</geoLong>
- <codeDatum>WGE</codeDatum>
- <GbrUid>
- <txtName>FRANCE_GERMANY</txtName>
- </GbrUid>
- </Avx>
- <Avx>
- <codeType>GRC</codeType>
- <geoLat>47.85916667N</geoLat>
- <geoLong>7.56000000E</geoLong>
- <codeDatum>WGE</codeDatum>
- </Avx>
- </Abd>
- <Adg>
- <AdgUid>
- <AseUid mid="#{digest}.1">
- <codeType>CLASS</codeType>
- </AseUid>
- </AdgUid>
- <AdgUid>
- <AseUid mid="#{digest}.2">
- <codeType>CLASS</codeType>
- </AseUid>
- </AdgUid>
- <AseUidSameExtent mid="#{digest}"/>
- </Adg>
- <Ase>
- <AseUid mid="#{digest}.1">
- <codeType>CLASS</codeType>
- </AseUid>
- <txtName>POLYGON AIRSPACE</txtName>
- <codeClass>C</codeClass>
- <codeDistVerUpper>STD</codeDistVerUpper>
- <valDistVerUpper>65</valDistVerUpper>
- <uomDistVerUpper>FL</uomDistVerUpper>
- <codeDistVerLower>STD</codeDistVerLower>
- <valDistVerLower>45</valDistVerLower>
- <uomDistVerLower>FL</uomDistVerLower>
- <codeDistVerMax>ALT</codeDistVerMax>
- <valDistVerMax>6000</valDistVerMax>
- <uomDistVerMax>FT</uomDistVerMax>
- <codeDistVerMnm>HEI</codeDistVerMnm>
- <valDistVerMnm>3000</valDistVerMnm>
- <uomDistVerMnm>FT</uomDistVerMnm>
- </Ase>
- <Ase>
- <AseUid mid="#{digest}.2">
- <codeType>CLASS</codeType>
- </AseUid>
- <txtName>POLYGON AIRSPACE</txtName>
- <codeClass>C</codeClass>
- <codeDistVerUpper>STD</codeDistVerUpper>
- <valDistVerUpper>65</valDistVerUpper>
- <uomDistVerUpper>FL</uomDistVerUpper>
- <codeDistVerLower>STD</codeDistVerLower>
- <valDistVerLower>45</valDistVerLower>
- <uomDistVerLower>FL</uomDistVerLower>
- <codeDistVerMax>ALT</codeDistVerMax>
- <valDistVerMax>6000</valDistVerMax>
- <uomDistVerMax>FT</uomDistVerMax>
- <codeDistVerMnm>HEI</codeDistVerMnm>
- <valDistVerMnm>3000</valDistVerMnm>
- <uomDistVerMnm>FT</uomDistVerMnm>
- </Ase>
- END
- end
- end
+ it "upcases value" do
+ subject.tap { |s| s.name = 'löl' }.name.must_equal 'LOEL'
end
end
- context "partially complete" do
- subject do
- AIXM::Factory.polygon_airspace
+ describe :short_name= do
+ it "fails on invalid values" do
+ [:foobar, 123].wont_be_written_to subject, :short_name
end
- it "must build correct XML without short name" do
- subject.short_name = nil
- subject.to_aixm.wont_match(/txtLocalType/)
+ it "accepts nil value" do
+ [nil].must_be_written_to subject, :short_name
end
- it "must build correct XML with identical name and short name" do
- subject.short_name = 'POLYGON AIRSPACE'
- subject.to_aixm.wont_match(/txtLocalType/)
+ it "upcases value" do
+ subject.tap { |s| s.short_name = 'löl' }.short_name.must_equal 'LOEL'
end
+ end
- it "must build correct XML without schedule" do
- subject.schedule = nil
- subject.to_aixm.wont_match(/codeWorkHr/)
+ describe :to_uid do
+ it "builds with arbitrary tag" do
+ subject.to_uid.must_match(/<AseUid>/)
+ subject.to_uid(as: :FooBar).must_match(/<FooBar>/)
end
end
+
+ describe :to_xml do
+ it "fails to build AIXM since geometry is not closed" do
+ subject.layers << AIXM::Factory.layer
+ -> { subject.to_xml }.must_raise AIXM::GeometryError
+ end
+
+ it "fails to build AIXM since layers are not defined" do
+ subject.geometry = AIXM::Factory.circle_geometry
+ -> { subject.to_xml }.must_raise AIXM::LayerError
+ end
+ end
end
+
+ context "only required attributes, geometry and layers set" do
+ subject do
+ AIXM.airspace(type: "TMA", name: "Test TMA").tap do |airspace|
+ airspace.geometry = AIXM::Factory.circle_geometry
+ airspace.layers << AIXM::Factory.layer
+ end
+ end
+
+ describe :to_xml do
+ it "builds correct AIXM without id" do
+ AIXM.aixm!
+ subject.to_xml.must_match(%r{<codeId>22E2F734</codeId>})
+ end
+
+ it "builds correct AIXM without short name" do
+ AIXM.aixm!
+ subject.to_xml.wont_match(/<txtLocalType>/)
+ end
+
+ it "builds correct AIXM with identical name and short name" do
+ AIXM.aixm!
+ subject.to_xml.wont_match(/<txtLocalType>/)
+ end
+ end
+ end
+
+ context "with one layer" do
+ subject do
+ AIXM::Factory.polygon_airspace
+ end
+
+ describe :to_xml do
+ it "builds correct complete OFMX" do
+ AIXM.ofmx!
+ subject.to_xml.must_equal <<~"END"
+ <!-- Airspace: [D] POLYGON AIRSPACE -->
+ <Ase source="LF|GEN|0.0 FACTORY|0|0">
+ <AseUid region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUid>
+ <txtLocalType>POLYGON</txtLocalType>
+ <txtName>POLYGON AIRSPACE</txtName>
+ <codeClass>C</codeClass>
+ <codeDistVerUpper>STD</codeDistVerUpper>
+ <valDistVerUpper>65</valDistVerUpper>
+ <uomDistVerUpper>FL</uomDistVerUpper>
+ <codeDistVerLower>STD</codeDistVerLower>
+ <valDistVerLower>45</valDistVerLower>
+ <uomDistVerLower>FL</uomDistVerLower>
+ <codeDistVerMax>ALT</codeDistVerMax>
+ <valDistVerMax>6000</valDistVerMax>
+ <uomDistVerMax>FT</uomDistVerMax>
+ <codeDistVerMnm>HEI</codeDistVerMnm>
+ <valDistVerMnm>3000</valDistVerMnm>
+ <uomDistVerMnm>FT</uomDistVerMnm>
+ <Att>
+ <codeWorkHr>H24</codeWorkHr>
+ </Att>
+ <codeSelAvbl>Y</codeSelAvbl>
+ <txtRmk>airspace layer</txtRmk>
+ </Ase>
+ <Abd>
+ <AbdUid>
+ <AseUid region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUid>
+ </AbdUid>
+ <Avx>
+ <codeType>CWA</codeType>
+ <geoLat>47.85916667N</geoLat>
+ <geoLong>007.56000000E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ <geoLatArc>47.90416667N</geoLatArc>
+ <geoLongArc>007.56333333E</geoLongArc>
+ </Avx>
+ <Avx>
+ <GbrUid>
+ <txtName>FRANCE_GERMANY</txtName>
+ </GbrUid>
+ <codeType>FNT</codeType>
+ <geoLat>47.94361111N</geoLat>
+ <geoLong>007.59583333E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ </Avx>
+ <Avx>
+ <codeType>GRC</codeType>
+ <geoLat>47.85916667N</geoLat>
+ <geoLong>007.56000000E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ </Avx>
+ </Abd>
+ END
+ end
+
+ it "builds correct minimal OFMX" do
+ AIXM.ofmx!
+ subject.short_name = subject.name = nil
+ subject.to_xml.must_equal <<~"END"
+ <!-- Airspace: [D] UNNAMED -->
+ <Ase source="LF|GEN|0.0 FACTORY|0|0">
+ <AseUid region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUid>
+ <codeClass>C</codeClass>
+ <codeDistVerUpper>STD</codeDistVerUpper>
+ <valDistVerUpper>65</valDistVerUpper>
+ <uomDistVerUpper>FL</uomDistVerUpper>
+ <codeDistVerLower>STD</codeDistVerLower>
+ <valDistVerLower>45</valDistVerLower>
+ <uomDistVerLower>FL</uomDistVerLower>
+ <codeDistVerMax>ALT</codeDistVerMax>
+ <valDistVerMax>6000</valDistVerMax>
+ <uomDistVerMax>FT</uomDistVerMax>
+ <codeDistVerMnm>HEI</codeDistVerMnm>
+ <valDistVerMnm>3000</valDistVerMnm>
+ <uomDistVerMnm>FT</uomDistVerMnm>
+ <Att>
+ <codeWorkHr>H24</codeWorkHr>
+ </Att>
+ <codeSelAvbl>Y</codeSelAvbl>
+ <txtRmk>airspace layer</txtRmk>
+ </Ase>
+ <Abd>
+ <AbdUid>
+ <AseUid region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUid>
+ </AbdUid>
+ <Avx>
+ <codeType>CWA</codeType>
+ <geoLat>47.85916667N</geoLat>
+ <geoLong>007.56000000E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ <geoLatArc>47.90416667N</geoLatArc>
+ <geoLongArc>007.56333333E</geoLongArc>
+ </Avx>
+ <Avx>
+ <GbrUid>
+ <txtName>FRANCE_GERMANY</txtName>
+ </GbrUid>
+ <codeType>FNT</codeType>
+ <geoLat>47.94361111N</geoLat>
+ <geoLong>007.59583333E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ </Avx>
+ <Avx>
+ <codeType>GRC</codeType>
+ <geoLat>47.85916667N</geoLat>
+ <geoLong>007.56000000E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ </Avx>
+ </Abd>
+ END
+ end
+ end
+ end
+
+ context "with two layers" do
+ subject do
+ AIXM::Factory.polygon_airspace.tap do |airspace|
+ airspace.layers << AIXM::Factory.layer
+ end
+ end
+
+ describe :to_xml do
+ it "builds correct OFMX" do
+ AIXM.ofmx!
+ subject.to_xml.must_equal <<~"END"
+ <!-- Airspace: [D] POLYGON AIRSPACE -->
+ <Ase source="LF|GEN|0.0 FACTORY|0|0" classLayers="2">
+ <AseUid region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUid>
+ <txtLocalType>POLYGON</txtLocalType>
+ <txtName>POLYGON AIRSPACE</txtName>
+ </Ase>
+ <Abd>
+ <AbdUid>
+ <AseUid region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUid>
+ </AbdUid>
+ <Avx>
+ <codeType>CWA</codeType>
+ <geoLat>47.85916667N</geoLat>
+ <geoLong>007.56000000E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ <geoLatArc>47.90416667N</geoLatArc>
+ <geoLongArc>007.56333333E</geoLongArc>
+ </Avx>
+ <Avx>
+ <GbrUid>
+ <txtName>FRANCE_GERMANY</txtName>
+ </GbrUid>
+ <codeType>FNT</codeType>
+ <geoLat>47.94361111N</geoLat>
+ <geoLong>007.59583333E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ </Avx>
+ <Avx>
+ <codeType>GRC</codeType>
+ <geoLat>47.85916667N</geoLat>
+ <geoLong>007.56000000E</geoLong>
+ <codeDatum>WGE</codeDatum>
+ </Avx>
+ </Abd>
+ <Ase>
+ <AseUid region="LF">
+ <codeType>CLASS</codeType>
+ <codeId>522496D6</codeId>
+ </AseUid>
+ <txtName>POLYGON AIRSPACE LAYER 1</txtName>
+ <codeClass>C</codeClass>
+ <codeDistVerUpper>STD</codeDistVerUpper>
+ <valDistVerUpper>65</valDistVerUpper>
+ <uomDistVerUpper>FL</uomDistVerUpper>
+ <codeDistVerLower>STD</codeDistVerLower>
+ <valDistVerLower>45</valDistVerLower>
+ <uomDistVerLower>FL</uomDistVerLower>
+ <codeDistVerMax>ALT</codeDistVerMax>
+ <valDistVerMax>6000</valDistVerMax>
+ <uomDistVerMax>FT</uomDistVerMax>
+ <codeDistVerMnm>HEI</codeDistVerMnm>
+ <valDistVerMnm>3000</valDistVerMnm>
+ <uomDistVerMnm>FT</uomDistVerMnm>
+ <Att>
+ <codeWorkHr>H24</codeWorkHr>
+ </Att>
+ <codeSelAvbl>Y</codeSelAvbl>
+ <txtRmk>airspace layer</txtRmk>
+ </Ase>
+ <Adg>
+ <AdgUid>
+ <AseUid region="LF">
+ <codeType>CLASS</codeType>
+ <codeId>522496D6</codeId>
+ </AseUid>
+ </AdgUid>
+ <AseUidSameExtent region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUidSameExtent>
+ </Adg>
+ <Ase>
+ <AseUid region="LF">
+ <codeType>CLASS</codeType>
+ <codeId>CAA85949</codeId>
+ </AseUid>
+ <txtName>POLYGON AIRSPACE LAYER 2</txtName>
+ <codeClass>C</codeClass>
+ <codeDistVerUpper>STD</codeDistVerUpper>
+ <valDistVerUpper>65</valDistVerUpper>
+ <uomDistVerUpper>FL</uomDistVerUpper>
+ <codeDistVerLower>STD</codeDistVerLower>
+ <valDistVerLower>45</valDistVerLower>
+ <uomDistVerLower>FL</uomDistVerLower>
+ <codeDistVerMax>ALT</codeDistVerMax>
+ <valDistVerMax>6000</valDistVerMax>
+ <uomDistVerMax>FT</uomDistVerMax>
+ <codeDistVerMnm>HEI</codeDistVerMnm>
+ <valDistVerMnm>3000</valDistVerMnm>
+ <uomDistVerMnm>FT</uomDistVerMnm>
+ <Att>
+ <codeWorkHr>H24</codeWorkHr>
+ </Att>
+ <codeSelAvbl>Y</codeSelAvbl>
+ <txtRmk>airspace layer</txtRmk>
+ </Ase>
+ <Adg>
+ <AdgUid>
+ <AseUid region="LF">
+ <codeType>CLASS</codeType>
+ <codeId>CAA85949</codeId>
+ </AseUid>
+ </AdgUid>
+ <AseUidSameExtent region="LF">
+ <codeType>D</codeType>
+ <codeId>PA</codeId>
+ </AseUidSameExtent>
+ </Adg>
+ END
+ end
+ end
+ end
+
end