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