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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rubocop.yml +20 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/Guardfile +28 -0
- data/LICENSE.txt +21 -0
- data/README.md +76 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/guard +16 -0
- data/bin/setup +8 -0
- data/lib/ogc.rb +9 -0
- data/lib/ogc/clean_xml.rb +13 -0
- data/lib/ogc/exceptions.rb +8 -0
- data/lib/ogc/exceptions/exception_report.rb +44 -0
- data/lib/ogc/exceptions/ogc_exception.rb +5 -0
- data/lib/ogc/exceptions/request_error_exception.rb +7 -0
- data/lib/ogc/exceptions/request_failed_exception.rb +12 -0
- data/lib/ogc/query.rb +11 -0
- data/lib/ogc/version.rb +3 -0
- data/lib/ogc/web_feature_service.rb +19 -0
- data/lib/ogc/web_feature_service/base.rb +95 -0
- data/lib/ogc/web_feature_service/get_capabilities.rb +9 -0
- data/lib/ogc/web_feature_service/get_feature.rb +14 -0
- data/ogc.gemspec +50 -0
- data/test/ogc/clean_xml_test.rb +31 -0
- data/test/ogc/exceptions/exception_report_test.rb +74 -0
- data/test/ogc/exceptions/ogc_exception_test.rb +11 -0
- data/test/ogc/exceptions/request_error_exception_test.rb +11 -0
- data/test/ogc/exceptions/request_failed_exception_test.rb +25 -0
- data/test/ogc/exceptions_test.rb +9 -0
- data/test/ogc/query_test.rb +21 -0
- data/test/ogc/version_test.rb +15 -0
- data/test/ogc/web_feature_service/base_test.rb +145 -0
- data/test/ogc/web_feature_service/get_capabilities_test.rb +34 -0
- data/test/ogc/web_feature_service/get_feature_test.rb +38 -0
- data/test/ogc/web_feature_service_test.rb +22 -0
- data/test/ogc_test.rb +7 -0
- data/test/test_helper.rb +51 -0
- data/test/xml/wfs/exception_report.xml +6 -0
- data/test/xml/wfs/fake_report.xml +4 -0
- data/test/xml/wfs/get_capabilities_request.xml +2 -0
- data/test/xml/wfs/get_capabilities_response.xml +188 -0
- data/test/xml/wfs/get_feature_response.xml +28 -0
- data/test/xml/wfs/service_exception_report.xml +4 -0
- metadata +231 -0
@@ -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,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,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
|