ogc 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.
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