ogc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rubocop.yml +20 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +4 -0
  7. data/Guardfile +28 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +76 -0
  10. data/Rakefile +10 -0
  11. data/bin/console +14 -0
  12. data/bin/guard +16 -0
  13. data/bin/setup +8 -0
  14. data/lib/ogc.rb +9 -0
  15. data/lib/ogc/clean_xml.rb +13 -0
  16. data/lib/ogc/exceptions.rb +8 -0
  17. data/lib/ogc/exceptions/exception_report.rb +44 -0
  18. data/lib/ogc/exceptions/ogc_exception.rb +5 -0
  19. data/lib/ogc/exceptions/request_error_exception.rb +7 -0
  20. data/lib/ogc/exceptions/request_failed_exception.rb +12 -0
  21. data/lib/ogc/query.rb +11 -0
  22. data/lib/ogc/version.rb +3 -0
  23. data/lib/ogc/web_feature_service.rb +19 -0
  24. data/lib/ogc/web_feature_service/base.rb +95 -0
  25. data/lib/ogc/web_feature_service/get_capabilities.rb +9 -0
  26. data/lib/ogc/web_feature_service/get_feature.rb +14 -0
  27. data/ogc.gemspec +50 -0
  28. data/test/ogc/clean_xml_test.rb +31 -0
  29. data/test/ogc/exceptions/exception_report_test.rb +74 -0
  30. data/test/ogc/exceptions/ogc_exception_test.rb +11 -0
  31. data/test/ogc/exceptions/request_error_exception_test.rb +11 -0
  32. data/test/ogc/exceptions/request_failed_exception_test.rb +25 -0
  33. data/test/ogc/exceptions_test.rb +9 -0
  34. data/test/ogc/query_test.rb +21 -0
  35. data/test/ogc/version_test.rb +15 -0
  36. data/test/ogc/web_feature_service/base_test.rb +145 -0
  37. data/test/ogc/web_feature_service/get_capabilities_test.rb +34 -0
  38. data/test/ogc/web_feature_service/get_feature_test.rb +38 -0
  39. data/test/ogc/web_feature_service_test.rb +22 -0
  40. data/test/ogc_test.rb +7 -0
  41. data/test/test_helper.rb +51 -0
  42. data/test/xml/wfs/exception_report.xml +6 -0
  43. data/test/xml/wfs/fake_report.xml +4 -0
  44. data/test/xml/wfs/get_capabilities_request.xml +2 -0
  45. data/test/xml/wfs/get_capabilities_response.xml +188 -0
  46. data/test/xml/wfs/get_feature_response.xml +28 -0
  47. data/test/xml/wfs/service_exception_report.xml +4 -0
  48. metadata +231 -0
@@ -0,0 +1,9 @@
1
+ module Ogc
2
+ module WebFeatureService
3
+ class GetCapabilities < Base
4
+ def get(&block)
5
+ super(request: self.class.request_name, &block)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module Ogc
2
+ module WebFeatureService
3
+ class GetFeature < Base
4
+ def get(type_name, extra_params = {}, &block)
5
+ params = {
6
+ 'request' => self.class.request_name,
7
+ 'typeName' => type_name
8
+ }.merge!(extra_params)
9
+
10
+ super(params, &block)
11
+ end
12
+ end
13
+ end
14
+ end
data/ogc.gemspec ADDED
@@ -0,0 +1,50 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'English'
7
+ require 'ogc/version'
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.required_ruby_version = '~> 2.1'
11
+
12
+ spec.name = 'ogc'
13
+ spec.version = Ogc::VERSION
14
+ spec.authors = ['Geoffrey Roguelon']
15
+ spec.email = ['geoffrey.roguelon@gmail.com']
16
+
17
+ spec.summary = 'Allow you to use WFS protocol defined by OGC.'
18
+ spec.description = <<-STR
19
+ This gems allow you to make calls in using Web Feature Service protocol
20
+ defined by OGC (Open Geospatial Consortium) organization.
21
+ STR
22
+ spec.homepage = 'https://github.com/GRoguelon/ogc'
23
+ spec.license = 'MIT'
24
+
25
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
26
+ # delete this section to allow pushing this gem to any host.
27
+ if spec.respond_to?(:metadata)
28
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
29
+ else
30
+ # rubocop:disable Metrics/LineLength
31
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
32
+ # rubocop:enable Metrics/LineLength
33
+ end
34
+
35
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
36
+ spec.bindir = 'exe'
37
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
+ spec.require_paths = ['lib']
39
+
40
+ spec.add_dependency 'nokogiri', '~> 1.6', '>= 1.6.6'
41
+ spec.add_dependency 'activesupport', '>= 4.0', '< 5.0'
42
+
43
+ spec.add_development_dependency 'bundler', '~> 1.10'
44
+ spec.add_development_dependency 'rake', '~> 10.0'
45
+ spec.add_development_dependency 'minitest', '~> 5.8'
46
+ spec.add_development_dependency 'guard', '~> 2.13'
47
+ spec.add_development_dependency 'guard-minitest', '~> 2.4'
48
+ spec.add_development_dependency 'webmock', '~> 1.22'
49
+ spec.add_development_dependency 'rubocop', '~> 0.35'
50
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+ require 'active_support/core_ext/string/strip'
3
+
4
+ module Ogc
5
+ class CleanXMLTest < TestCase
6
+ using CleanXML
7
+
8
+ setup do
9
+ @xml = <<-XML.strip_heredoc
10
+ <class name="FakeClass"
11
+ extends="Object">
12
+ <methods>
13
+ <class-method name="clean" arity="1">
14
+ <arguements>
15
+ <argument name="xml" />
16
+ </arguments>
17
+ </methods>
18
+ </class>
19
+ XML
20
+
21
+ @cleaned_xml = '<class name="FakeClass" extends="Object"><methods>'
22
+ @cleaned_xml += '<class-method name="clean" arity="1">'
23
+ @cleaned_xml += '<arguements><argument name="xml" /></arguments>'
24
+ @cleaned_xml += '</methods></class>'
25
+ end
26
+
27
+ test 'clean_xml! method remove the breaklines' do
28
+ assert_equal @cleaned_xml, @xml.clean_xml!
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,74 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ module Exceptions
5
+ class ExceptionReportTest < TestCase
6
+ using CleanXML
7
+
8
+ setup do
9
+ @xml_100 = read_xml('wfs/service_exception_report')
10
+ @report_100 = ExceptionReport.new(@xml_100)
11
+
12
+ @xml_110 = read_xml('wfs/exception_report')
13
+ @report_110 = ExceptionReport.new(@xml_110)
14
+
15
+ @xml_fake = read_xml('wfs/fake_report')
16
+ end
17
+
18
+ test 'class inherits from OgcException' do
19
+ assert ExceptionReport < OgcException
20
+ end
21
+
22
+ test 'ROOTS constant is a frozen array of string' do
23
+ assert ExceptionReport::ROOTS.frozen?
24
+ assert_kind_of Array, ExceptionReport::ROOTS
25
+ end
26
+
27
+ test 'exception? class method return boolean' do
28
+ assert ExceptionReport.exception?(@xml_100)
29
+ refute ExceptionReport.exception?(@xml_fake)
30
+ end
31
+
32
+ test 'constructor takes xml and sets the attribute' do
33
+ assert_equal @xml_100.to_xml, @report_100.report.to_xml
34
+ assert_equal @xml_110.to_xml, @report_110.report.to_xml
35
+ end
36
+
37
+ test 'constructor raises ArgumentError is not an WFS exception' do
38
+ assert_raises(ArgumentError) { ExceptionReport.new(@xml_fake) }
39
+ end
40
+
41
+ test 'constructor sets the message of StandardError attribute' do
42
+ msg = 'Unable to INSERT STMT'
43
+ assert_equal msg, @report_100.message
44
+
45
+ msg = 'parse error: missing closing tag for element wkbGeom'
46
+ assert_equal msg, @report_110.message
47
+ end
48
+
49
+ test 'at_xpath method delegates to report instance variable' do
50
+ assert_equal '1.2.0', @report_100.at_xpath('/*/@version').text
51
+ assert_equal '1.1.0', @report_110.at_xpath('/*/@version').text
52
+ end
53
+
54
+ test 'xpath method delegates to report instance variable' do
55
+ expected_xml = '<ServiceException code="999" locator="INSERT STMT 01">'
56
+ expected_xml += 'Unable to INSERT STMT'
57
+ expected_xml += '</ServiceException>'
58
+ actual_xml = @report_100.xpath('//xmlns:ServiceException').first.to_xml
59
+ assert_equal expected_xml, actual_xml
60
+
61
+ expected_xml = '<ExceptionText>'
62
+ expected_xml += 'parse error: missing closing tag for element wkbGeom'
63
+ expected_xml += '</ExceptionText>'
64
+ actual_xml = @report_110.xpath('//xmlns:ExceptionText').first.to_xml
65
+ assert_equal expected_xml, actual_xml
66
+ end
67
+
68
+ test 'version method returns version attribute' do
69
+ assert_equal '1.2.0', @report_100.version
70
+ assert_equal '1.1.0', @report_110.version
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ module Exceptions
5
+ class OgcExceptionTest < TestCase
6
+ test 'class inherits from StandardError' do
7
+ assert OgcException < StandardError
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ module Exceptions
5
+ class RequestErrorExceptionTest < TestCase
6
+ test 'class inherits from OgcException' do
7
+ assert RequestErrorException < OgcException
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+ require 'minitest/mock'
3
+
4
+ module Ogc
5
+ module Exceptions
6
+ class RequestFailedExceptionTest < TestCase
7
+ setup do
8
+ @mock = Minitest::Mock.new
9
+ @mock.expect :code, 666
10
+ @mock.expect :message, 'Hello Wolrd'
11
+ end
12
+
13
+ test 'class inherits from OgcException' do
14
+ assert RequestFailedException < OgcException
15
+ end
16
+
17
+ test 'constructor takes a HTTP error' do
18
+ ex = RequestFailedException.new(@mock)
19
+ assert 666, ex.code
20
+ assert 'Hello World', ex.message
21
+ @mock.verify
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ class ExceptionsTest < TestCase
5
+ test 'Exceptions module is defined' do
6
+ refute_nil Exceptions
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ require 'active_support/core_ext/object/to_query'
3
+
4
+ module Ogc
5
+ class QueryTest < TestCase
6
+ using Query
7
+
8
+ setup do
9
+ @hash = {
10
+ 'service' => 'wfs',
11
+ 'srsname' => 'epsg:4326',
12
+ 'version' => '1.0.0'
13
+ }
14
+ @query = @hash.to_query
15
+ end
16
+
17
+ test 'query method converts a query to hash' do
18
+ assert_equal @hash, Hash.from_query(@query)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ class VersionTest < TestCase
5
+ SEMANTIV_VERSION_REGEX = /\A\d+\.\d+\.\d+(\.[a-z0-9]+)?\z/
6
+
7
+ test 'ogc version is defined' do
8
+ assert_kind_of String, VERSION
9
+ end
10
+
11
+ test 'ogc version respects semantic versions' do
12
+ assert_match SEMANTIV_VERSION_REGEX, VERSION
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,145 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ module WebFeatureService
5
+ class BaseTest < TestCase
6
+ include Exceptions
7
+ using CleanXML
8
+
9
+ URL = 'http://localhost/wfs'
10
+ PARAMS = { 'version' => '1.0.0', 'key' => 'ABCDE' }
11
+ FULL_PARAMS = PARAMS.merge(Base::DEFAULT_PARAMS)
12
+
13
+ # Fake exception
14
+ CalledBlockException = Class.new(StandardError)
15
+
16
+ setup do
17
+ @base = Base.new(URL, PARAMS)
18
+
19
+ # XML files
20
+ @request = read_file('wfs/get_capabilities_request')
21
+ @response = read_file('wfs/get_capabilities_response')
22
+ @exception = read_file('wfs/exception_report')
23
+
24
+ query = FULL_PARAMS.merge(request: :hello).to_query
25
+
26
+ # Get method returns xml response:
27
+ stub_request(:get, "#{URL}?#{query}").to_return(body: @response)
28
+
29
+ # Get method returns xml exception:
30
+ stub_request(:get, "#{URL}?ex=xml&#{query}")
31
+ .to_return(body: @exception)
32
+
33
+ # Get method returns Timeout exception:
34
+ stub_request(:get, "#{URL}?ex=timeout&#{query}")
35
+ .to_raise(Timeout::Error)
36
+
37
+ # Get method returns NotFound return:
38
+ stub_request(:get, "#{URL}?ex=notFound&#{query}")
39
+ .to_return(status: [404, 'Not Found'])
40
+
41
+ # Post method returns xml response:
42
+ stub_request(:post, "#{URL}").with(body: @request)
43
+ .to_return(body: @response)
44
+ end
45
+
46
+ test 'DEFAULT_PARAMS constant is frozen' do
47
+ assert Base::DEFAULT_PARAMS.frozen?
48
+ end
49
+
50
+ test 'request_name class method returns the name of the class' do
51
+ assert_equal 'Base', Base.request_name
52
+ assert_same Base.request_name, Base.request_name
53
+
54
+ FakeService = Class.new(Base)
55
+ assert_equal 'FakeService', FakeService.request_name
56
+ end
57
+
58
+ test 'constructor takes an url and some params as arguments' do
59
+ assert_equal URL, @base.url
60
+ refute_same PARAMS, @base.params
61
+ assert_equal FULL_PARAMS, @base.params
62
+ end
63
+
64
+ test 'constructor stringifies the keys of params' do
65
+ base = Base.new(URL, PARAMS.symbolize_keys)
66
+ assert_equal FULL_PARAMS, base.params
67
+ end
68
+
69
+ test 'http method exposes the http object' do
70
+ assert_instance_of Net::HTTP, @base.http
71
+ end
72
+
73
+ test 'get method returns xml response' do
74
+ xml = Nokogiri::XML(@response.clean_xml!).to_xml
75
+ assert_equal xml, @base.get(request: 'hello').to_xml
76
+ end
77
+
78
+ test 'get method takes a block to overload the request' do
79
+ assert_raises CalledBlockException do
80
+ @base.get(request: 'hello') do |_|
81
+ raise CalledBlockException
82
+ end
83
+ end
84
+ end
85
+
86
+ test 'get method takes a block which exposes the request' do
87
+ @base.get(request: :hello) do |request|
88
+ assert_instance_of Net::HTTP::Get, request
89
+ end
90
+ end
91
+
92
+ test 'post method returns xml response' do
93
+ xml = Nokogiri::XML(@response.clean_xml!).to_xml
94
+ assert_equal xml, @base.post(@request).to_xml
95
+ end
96
+
97
+ test 'post method takes a block to overload the request' do
98
+ assert_raises CalledBlockException do
99
+ @base.post(@request) do |_|
100
+ raise CalledBlockException
101
+ end
102
+ end
103
+ end
104
+
105
+ test 'post method takes a block which exposes the request' do
106
+ @base.post(@request) do |request|
107
+ assert_instance_of Net::HTTP::Post, request
108
+ end
109
+ end
110
+
111
+ test 'exception is raised if WFS returns exception' do
112
+ assert_raises ExceptionReport do
113
+ @base.get(request: :hello, ex: :xml)
114
+ end
115
+ end
116
+
117
+ test 'exception is raised if Timeout is raised' do
118
+ assert_raises RequestErrorException do
119
+ @base.get(request: :hello, ex: :timeout)
120
+ end
121
+ end
122
+
123
+ test 'exception raised has a cause' do
124
+ begin
125
+ @base.get(request: :hello, ex: :timeout)
126
+ assert false # In case where the exception is not raised.
127
+ rescue RequestErrorException => ex
128
+ assert_instance_of Timeout::Error, ex.cause
129
+ end
130
+ end
131
+
132
+ test 'request error raises RequestFailedException exception' do
133
+ assert_raises RequestFailedException do
134
+ @base.get(request: :hello, ex: :notFound)
135
+ end
136
+ end
137
+
138
+ test 'response is cached' do
139
+ assert_nil @base.response
140
+ @base.get(request: 'hello')
141
+ refute_nil @base.response
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ module Ogc
4
+ module WebFeatureService
5
+ class GetCapabilitiesTest < TestCase
6
+ using CleanXML
7
+
8
+ URL = 'http://localhost/wfs'
9
+ PARAMS = { 'version' => '1.0.0', 'key' => 'ABCDE' }
10
+ FULL_PARAMS = PARAMS.merge(Base::DEFAULT_PARAMS)
11
+
12
+ setup do
13
+ @base = GetCapabilities.new(URL, PARAMS)
14
+
15
+ # XML files
16
+ @response = read_file('wfs/get_capabilities_response')
17
+
18
+ query = FULL_PARAMS.merge(request: GetCapabilities.request_name).to_query
19
+
20
+ # Get method returns xml response:
21
+ stub_request(:get, "#{URL}?#{query}").to_return(body: @response)
22
+ end
23
+
24
+ test 'class inherits from Base' do
25
+ assert GetCapabilities < Base
26
+ end
27
+
28
+ test 'get method returns xml response' do
29
+ xml = Nokogiri::XML(@response.clean_xml!).to_xml
30
+ assert_equal xml, @base.get.to_xml
31
+ end
32
+ end
33
+ end
34
+ end