open311-validator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +14 -0
- data/README.markdown +7 -0
- data/bin/open311-validate +41 -0
- data/lib/client.rb +70 -0
- data/lib/resource.rb +98 -0
- data/lib/ruby_spec.rb +75 -0
- data/lib/session.rb +106 -0
- data/lib/test_helper.rb +37 -0
- data/lib/validate_311.rb +11 -0
- data/tests/create.rb +29 -0
- data/tests/discovery.rb +105 -0
- data/tests/service_definition.rb +11 -0
- data/tests/services.rb +18 -0
- metadata +106 -0
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright 2011 SeeClickFix
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
5
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
require 'validate_311'
|
9
|
+
|
10
|
+
options = { :discovery_url => 'http://seeclickfix.com/open311/discovery',
|
11
|
+
:production => false,
|
12
|
+
:write => false
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
op = OptionParser.new do |opts|
|
17
|
+
opts.banner = "Usage: validate [options]"
|
18
|
+
opts.on('-u', '--url [discovery_url]','') do |url|
|
19
|
+
options[:discovery_url] = url if url
|
20
|
+
end
|
21
|
+
opts.on('-p', '--production [true/false]', 'Default: false') do |resp|
|
22
|
+
options[:production] = resp unless resp.nil?
|
23
|
+
end
|
24
|
+
opts.on('-k', '--api_key [key]', 'Default: none') do |resp|
|
25
|
+
options[:api_key] = resp unless resp.nil?
|
26
|
+
end
|
27
|
+
opts.on('-w', '--write [true/false]', 'Default: false') do |resp|
|
28
|
+
options[:write] = resp unless resp.nil?
|
29
|
+
end
|
30
|
+
opts.on('-j', '--jurisdiction_id [jurisdiction_id]', 'Default: none') do |resp|
|
31
|
+
options[:jurisdiction_id] = resp unless resp.nil?
|
32
|
+
end
|
33
|
+
opts.on('-a', '--address [address]', 'Default: none') do |resp|
|
34
|
+
options[:address] = resp unless resp.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
op.parse!
|
39
|
+
|
40
|
+
@session = Session.new(options)
|
41
|
+
@session.valid? ? @session.run_tests : (puts op)
|
data/lib/client.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class Client
|
4
|
+
attr_accessor :raw, :base, :format, :unwrap
|
5
|
+
|
6
|
+
def initialize(base,format)
|
7
|
+
@base = base
|
8
|
+
@format = format
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_and_unwrap(url,unwrap)
|
12
|
+
@unwrap = unwrap
|
13
|
+
get(url)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(url)
|
17
|
+
@raw = HTTParty.get("#{@base}#{url}")
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def post(url,body)
|
22
|
+
# TODO: remove. This is simply for my testing.
|
23
|
+
url = 'http://localhost:3000/open311/requests.xml'
|
24
|
+
@raw = HTTParty.post(url, :body => body)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def response
|
29
|
+
if @format == 'xml' and !@unwrap.nil?
|
30
|
+
Array(Session.unwrap(raw_response,@unwrap))
|
31
|
+
else
|
32
|
+
raw_response
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw_response
|
37
|
+
Client.hash2ostruct(@raw.parsed_response)
|
38
|
+
end
|
39
|
+
|
40
|
+
def headers
|
41
|
+
Client.hash2ostruct(@raw.headers)
|
42
|
+
end
|
43
|
+
|
44
|
+
def body
|
45
|
+
@raw.body
|
46
|
+
end
|
47
|
+
|
48
|
+
def request
|
49
|
+
@raw.request
|
50
|
+
end
|
51
|
+
|
52
|
+
# Recursively create ostruct obj from
|
53
|
+
# httparty's Hash/Array mess.
|
54
|
+
def self.hash2ostruct(object)
|
55
|
+
return case object
|
56
|
+
when Hash
|
57
|
+
object = object.clone
|
58
|
+
object.each do |key, value|
|
59
|
+
object[key] = Client.hash2ostruct(value)
|
60
|
+
end
|
61
|
+
OpenStruct.new(object)
|
62
|
+
when Array
|
63
|
+
object = object.clone
|
64
|
+
object.map! { |i| Client.hash2ostruct(i) }
|
65
|
+
else
|
66
|
+
object
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/lib/resource.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class Resource
|
4
|
+
attr_accessor :options, :raw
|
5
|
+
|
6
|
+
def initialize(session,options)
|
7
|
+
@options = options
|
8
|
+
@session = session
|
9
|
+
@last_resource = session.resource
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_next
|
13
|
+
self.send @options[:with]
|
14
|
+
end
|
15
|
+
|
16
|
+
def discovery_url
|
17
|
+
@raw = OpenStruct.new
|
18
|
+
@raw.json = Client.new(@options[:discovery_url],'json').get(".json")
|
19
|
+
@raw.xml = Client.new(@options[:discovery_url],'xml').get(".xml")
|
20
|
+
end
|
21
|
+
|
22
|
+
def services_resource
|
23
|
+
@raw = []
|
24
|
+
@session.endpoint_array.each do |endpoint|
|
25
|
+
response = Client.new(endpoint[0],endpoint[1])
|
26
|
+
response.get_and_unwrap("/services.#{endpoint[1]}?jurisdiction_id=#{@options[:jurisdiction_id]}",'services.service')
|
27
|
+
@raw << response
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def definition_resource
|
32
|
+
@raw = []
|
33
|
+
@session.raw_services.each do |raw_service|
|
34
|
+
raw_service.response.each do |service|
|
35
|
+
next if !service.metadata or service.metadata == 'false'
|
36
|
+
response = Client.new(raw_service.base,raw_service.format)
|
37
|
+
response.get_and_unwrap("/services/#{service.service_code}.#{raw_service.format}?jurisdiction_id=#{@options[:jurisdiction_id]}",'')
|
38
|
+
@raw << response
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Purpose: Create service requests
|
45
|
+
# URL: https://[API endpoint]/requests.[format]
|
46
|
+
# Sample URL: https://api.city.gov/dev/v2/requests.xml
|
47
|
+
# Format sent: Content-Type: application/x-www-form-urlencoded
|
48
|
+
# Formats returned: XML (JSON available if denoted by Service Discovery)
|
49
|
+
# HTTP Method: POST
|
50
|
+
# Requires API Key: Yes
|
51
|
+
#
|
52
|
+
#
|
53
|
+
# Required Arguments
|
54
|
+
# jurisdiction_id
|
55
|
+
# service_code (obtained from GET Service List method)
|
56
|
+
# location: either lat & long or address_string or address_id must be submitted
|
57
|
+
# attribute - only required if the service_code requires a service definition with required fields
|
58
|
+
# Explanation: An array of key/value responses based on Service Definitions. This takes the form of attribute[code]=value where multiple code/value pairs can be specified as well as multiple values for the same code in the case of a multivaluelist datatype (attribute[code1][]=value1&attribute[code1][]=value2&attribute[code1][]=value3) - see example
|
59
|
+
#
|
60
|
+
def create_resource_once
|
61
|
+
@raw.xml = []
|
62
|
+
@raw.json = []
|
63
|
+
# For each endpoint...
|
64
|
+
@session.discovery.xml.response.discovery.endpoints.endpoint.each do |endpoint|
|
65
|
+
next if type(endpoint) == 'production' and !@options.production
|
66
|
+
@raw.xml << Client.new.post("#{endpoint.url}/requests.xml",data_from_options)
|
67
|
+
end
|
68
|
+
|
69
|
+
@session.discovery.json.response.endpoints.each do |endpoint|
|
70
|
+
next if type(endpoint) == 'production' and !@options.production
|
71
|
+
@raw.json << Client.new.post("#{endpoint.url}/requests.json",data_from_options)
|
72
|
+
end if @options.json
|
73
|
+
|
74
|
+
@raw.options = @options
|
75
|
+
@raw
|
76
|
+
end
|
77
|
+
|
78
|
+
def data_from_options
|
79
|
+
## Converting @options back to a hash and merge them with user-supplied
|
80
|
+
# post data.
|
81
|
+
{ :api_key => @options.api_key,
|
82
|
+
:jurisdiction_id => @options.jurisdiction_id,
|
83
|
+
:service_code => first_service_code,
|
84
|
+
:address_string => @options.address
|
85
|
+
}.merge!(@options.post)
|
86
|
+
end
|
87
|
+
|
88
|
+
def first_service_code
|
89
|
+
@session.resources[1].xml.first.response.services.service.service_code
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
end
|
data/lib/ruby_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
# class PositiveSpec
|
3
|
+
# def initialize(obj,required)
|
4
|
+
# @obj = obj
|
5
|
+
# @required = required
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# def ==(other)
|
9
|
+
# if @obj != other
|
10
|
+
# raise Exception.new("#{requirement}: \"Expected: #{other} Got: #{@obj}\"")
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def >(other)
|
15
|
+
# unless @obj > other
|
16
|
+
# raise Exception.new("#{requirement}: \"Expected: #{other} Got: #{@obj}\"")
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def requirement
|
21
|
+
# @required ? "REQUIRED" : "WARNING"
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
|
25
|
+
# class NegativeSpec
|
26
|
+
# def initialize(obj,required)
|
27
|
+
# @obj = obj
|
28
|
+
# @required = required
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def ==(other)
|
32
|
+
# if @obj == other
|
33
|
+
# raise Exception.new("#{requirement}: \"Expected: #{other} Got: #{@obj}\"")
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# def requirement
|
38
|
+
# @required ? "REQUIRED" : "WARNING"
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
|
42
|
+
# class Object
|
43
|
+
# def should
|
44
|
+
# PositiveSpec.new(self,false)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def should_not
|
48
|
+
# NegativeSpec.new(self,false)
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def must
|
52
|
+
# RequiredPositiveSpec.new(self,true)
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def must_not
|
56
|
+
# RequiredNegativeSpec.new(self,true)
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
|
60
|
+
|
61
|
+
def rule(msg)
|
62
|
+
begin
|
63
|
+
yield
|
64
|
+
print " #{msg.to_s.lstrip.ljust(90)[0..70]}","PASSED"
|
65
|
+
rescue Exception => e
|
66
|
+
print " #{msg.to_s.lstrip.ljust(90)[0..70]}","FAILED #{e.to_s}"
|
67
|
+
end
|
68
|
+
puts ""
|
69
|
+
end
|
70
|
+
|
71
|
+
def test(msg,options)
|
72
|
+
puts " Testing - #{msg.to_s}"
|
73
|
+
@session.add_resource(options)
|
74
|
+
yield
|
75
|
+
end
|
data/lib/session.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
|
2
|
+
class Session
|
3
|
+
attr_accessor :options
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
@resources = []
|
7
|
+
@options = {
|
8
|
+
:production => false,
|
9
|
+
:write => false
|
10
|
+
}.merge options
|
11
|
+
end
|
12
|
+
|
13
|
+
def run_tests
|
14
|
+
load 'tests/discovery.rb'
|
15
|
+
load 'tests/services.rb'
|
16
|
+
load 'tests/service_definition.rb'
|
17
|
+
load 'tests/create.rb' if @options[:write]
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
@options[:discovery_url] &&
|
22
|
+
!@options[:production].nil? &&
|
23
|
+
!@options[:write].nil? &&
|
24
|
+
!@options[:production].nil? &&
|
25
|
+
(!@options[:write] || ( @options[:write] && !@options[:address].nil? ))
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Resource mgmt.
|
30
|
+
def add_resource(options)
|
31
|
+
resource = Resource.new(self,@options.merge(options))
|
32
|
+
resource.get_next
|
33
|
+
@resources << resource
|
34
|
+
end
|
35
|
+
|
36
|
+
def resources
|
37
|
+
@resources
|
38
|
+
end
|
39
|
+
|
40
|
+
def discovery
|
41
|
+
@resources.first
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource
|
45
|
+
@resources.last
|
46
|
+
end
|
47
|
+
|
48
|
+
# Endpoint mgmt.
|
49
|
+
def endpoint_array
|
50
|
+
t = []
|
51
|
+
all_endpoints.each do |endpoint|
|
52
|
+
Session.endpoint_formats_as_array(endpoint).each do |format|
|
53
|
+
next if format =~ /^.*html$/i
|
54
|
+
t << [endpoint.url,format]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
t
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.endpoint_formats_as_array(endpoint)
|
61
|
+
Session.endpoint_formats(endpoint).map{|format| format.to_s.split('/')[1]}
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.endpoint_formats(endpoint)
|
65
|
+
endpoint.formats.is_a?(Array) ? endpoint.formats : Array(Session.unwrap(endpoint,'formats.format'))
|
66
|
+
end
|
67
|
+
|
68
|
+
def all_endpoints
|
69
|
+
json_endpoints + xml_endpoints
|
70
|
+
end
|
71
|
+
|
72
|
+
def json_endpoints
|
73
|
+
Session.unwrap(discovery.raw.json, 'response.endpoints').select{|endpoint| production_safe?(endpoint) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def xml_endpoints
|
77
|
+
Array(Session.unwrap(discovery.raw.xml,'response.discovery.endpoints.endpoint')).select{|endpoint| production_safe?(endpoint) }
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Services Lookup
|
82
|
+
#
|
83
|
+
def services
|
84
|
+
@resources[1].raw.map{|r| r.response }.flatten
|
85
|
+
end
|
86
|
+
|
87
|
+
def raw_services
|
88
|
+
@resources[1].raw
|
89
|
+
end
|
90
|
+
|
91
|
+
# Class Methods
|
92
|
+
def self.unwrap(obj,methods)
|
93
|
+
methods.split('.').each do |method|
|
94
|
+
obj = obj.send method.to_sym
|
95
|
+
end
|
96
|
+
obj
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# The marshal_dump is to avoid calling .type on the obj.
|
102
|
+
def production_safe?(endpoint)
|
103
|
+
endpoint.marshal_dump[:type] != 'production' or @options[:production]
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
data/lib/test_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module TestHelper
|
3
|
+
|
4
|
+
def validate_date_time(time)
|
5
|
+
time.is_a?(Time) ? time : Time.iso8601(time) rescue false
|
6
|
+
end
|
7
|
+
|
8
|
+
def resource
|
9
|
+
@session.resource
|
10
|
+
end
|
11
|
+
|
12
|
+
def xml_endpoints
|
13
|
+
@session.discovery.raw.xml.response.discovery.endpoints.endpoint
|
14
|
+
end
|
15
|
+
|
16
|
+
def json_endpoints
|
17
|
+
@session.discovery.raw.json.response.endpoints
|
18
|
+
end
|
19
|
+
|
20
|
+
def all_endpoints
|
21
|
+
xml_endpoints + json_endpoints
|
22
|
+
end
|
23
|
+
|
24
|
+
def v2_endpoints
|
25
|
+
all_endpoints.select{|endpoint| endpoint.specification =~ /^.*_v2$/i }
|
26
|
+
end
|
27
|
+
|
28
|
+
def xml_discovery
|
29
|
+
@session.discovery.raw.xml.response.discovery
|
30
|
+
end
|
31
|
+
|
32
|
+
def json_discovery
|
33
|
+
@session.discovery.raw.json.response
|
34
|
+
end
|
35
|
+
|
36
|
+
extend self
|
37
|
+
end
|
data/lib/validate_311.rb
ADDED
data/tests/create.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# @session.resources = History of resources for entire session of tests.
|
4
|
+
# @resource = currently tested resource.
|
5
|
+
# @resource.options = options used for that resource
|
6
|
+
# @resource.json.response = objectified response
|
7
|
+
# @resource.json.headers = response headers
|
8
|
+
# @resource.json.body = response body
|
9
|
+
# @resource.json.request = httparty request object
|
10
|
+
#
|
11
|
+
#
|
12
|
+
|
13
|
+
data = { :email => 'foo@bar.com', :description => 'I know' }
|
14
|
+
|
15
|
+
test "Creating Client Once", { :with => :create_resource_once, :post => data } do
|
16
|
+
|
17
|
+
rule 'each should return something' do
|
18
|
+
@resource.xml.each do |request|
|
19
|
+
request.response.should_not == ''
|
20
|
+
end
|
21
|
+
|
22
|
+
if @resource.options.json
|
23
|
+
@resource.json.each do |request|
|
24
|
+
request.response.should_not == ''
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/tests/discovery.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'test_helper';include TestHelper
|
2
|
+
|
3
|
+
test "Service Discovery", :with => :discovery_url do
|
4
|
+
|
5
|
+
rule 'url should end with "discovery"' do
|
6
|
+
resource.options[:discovery_url][-9..-1].should == 'discovery'
|
7
|
+
end
|
8
|
+
|
9
|
+
rule 'both formats should return results' do
|
10
|
+
resource.raw.xml.to_s.strip.should_not == '' && resource.raw.json.to_s.strip.should_not == ''
|
11
|
+
end
|
12
|
+
|
13
|
+
rule 'both formats should have contacts' do
|
14
|
+
xml_discovery.contact.to_s.strip.should_not == ''
|
15
|
+
json_discovery.contact.to_s.strip.should_not == ''
|
16
|
+
end
|
17
|
+
|
18
|
+
rule 'both formats should have key_service information' do
|
19
|
+
xml_discovery.key_service.to_s.strip.should_not == ''
|
20
|
+
json_discovery.key_service.to_s.strip.should_not == ''
|
21
|
+
end
|
22
|
+
|
23
|
+
rule 'return valid DateTime objects' do
|
24
|
+
validate_date_time(xml_discovery.changeset).class.should == Time
|
25
|
+
validate_date_time(json_discovery.changeset).class.should == Time
|
26
|
+
end
|
27
|
+
|
28
|
+
rule "contacts should return same for both formats" do
|
29
|
+
xml_discovery.contacts.should == json_discovery.contacts
|
30
|
+
end
|
31
|
+
|
32
|
+
rule "xml endpoint should be an array" do
|
33
|
+
xml_endpoints.class.should == Array
|
34
|
+
end
|
35
|
+
|
36
|
+
rule "there should be at least one endpoint" do
|
37
|
+
xml_endpoints.size.should > 0
|
38
|
+
end
|
39
|
+
|
40
|
+
rule "each endpoint should have a specification" do
|
41
|
+
all_endpoints.each do |endpoint|
|
42
|
+
endpoint.specification.should_not == ''
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
rule "each endpoint should have a url" do
|
47
|
+
all_endpoints.each do |endpoint|
|
48
|
+
endpoint.url.should_not == ''
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
rule "each endpoint should have a changeset" do
|
53
|
+
all_endpoints.each do |endpoint|
|
54
|
+
endpoint.changeset.should_not == ''
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
rule "each endpoint should have a valid changeset" do
|
59
|
+
all_endpoints.each do |endpoint|
|
60
|
+
validate_date_time(endpoint.changeset).class.should == Time
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
rule "each endpoint should have a changeset in the past" do
|
65
|
+
all_endpoints.each do |endpoint|
|
66
|
+
validate_date_time(endpoint.changeset).should < Time.now
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
rule "each endpoint should have a type" do
|
71
|
+
all_endpoints.each do |endpoint|
|
72
|
+
endpoint.marshal_dump[:type].should_not == ''
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
rule "each endpoint should have an array of formats" do
|
77
|
+
xml_endpoints.each do |endpoint|
|
78
|
+
endpoint.formats.format.class.should == Array
|
79
|
+
end
|
80
|
+
json_endpoints.each do |endpoint|
|
81
|
+
endpoint.formats.class.should == Array
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
rule "each endpoint should have at least one supported format" do
|
86
|
+
all_endpoints.each do |endpoint|
|
87
|
+
Session.endpoint_formats(endpoint).size.should > 0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
rule "all v2 endpoints should support xml" do
|
92
|
+
v2_endpoints.each do |endpoint|
|
93
|
+
Session.endpoint_formats(endpoint).select{|format| format == 'text/xml' }.size.should > 0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'test_helper';include TestHelper
|
2
|
+
|
3
|
+
test "Service Definitions", :with => :definition_resource do
|
4
|
+
|
5
|
+
rule 'test resource' do
|
6
|
+
# raise @session.resource.raw.inspect
|
7
|
+
# raise @session.prev_resource.inspect
|
8
|
+
# raise @resource.xml.inspect
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
data/tests/services.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_helper';include TestHelper
|
2
|
+
|
3
|
+
|
4
|
+
test "Services", :with => :services_resource do
|
5
|
+
|
6
|
+
rule 'there should be at least one service right?' do
|
7
|
+
@session.raw_services.each do |services|
|
8
|
+
services.response.size.should > 0
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
rule 'all services should have a service code' do
|
13
|
+
@session.services.each do |service|
|
14
|
+
service.service_code.should_not == nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: open311-validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- SeeClickFix (Jeff Blasius)
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-14 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: httparty
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
description: A command line Open311 validator. (http://open311.org)
|
49
|
+
email: dev@seeclickfix.com
|
50
|
+
executables:
|
51
|
+
- open311-validate
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files: []
|
55
|
+
|
56
|
+
files:
|
57
|
+
- LICENSE
|
58
|
+
- README.markdown
|
59
|
+
- bin/open311-validate
|
60
|
+
- lib/client.rb
|
61
|
+
- lib/resource.rb
|
62
|
+
- lib/ruby_spec.rb
|
63
|
+
- lib/session.rb
|
64
|
+
- lib/test_helper.rb
|
65
|
+
- lib/validate_311.rb
|
66
|
+
- tests/create.rb
|
67
|
+
- tests/discovery.rb
|
68
|
+
- tests/service_definition.rb
|
69
|
+
- tests/services.rb
|
70
|
+
homepage: http://github.com/seeclickfix/open311-validator
|
71
|
+
licenses: []
|
72
|
+
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
hash: 3
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 17
|
93
|
+
segments:
|
94
|
+
- 1
|
95
|
+
- 3
|
96
|
+
- 5
|
97
|
+
version: 1.3.5
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.8.11
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Open311 Validator
|
105
|
+
test_files: []
|
106
|
+
|