probity 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +71 -0
- data/lib/probity.rb +12 -0
- data/lib/probity/middleware.rb +58 -0
- data/lib/probity/validators/json.rb +5 -0
- data/lib/probity/validators/xml.rb +5 -0
- data/lib/probity/version.rb +3 -0
- data/probity.gemspec +26 -0
- data/spec/middleware_spec.rb +141 -0
- data/spec/validators/json_spec.rb +24 -0
- data/spec/validators/xml_spec.rb +27 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZjRlOGFjYmFjZWY3ODdjOTk0MTNlMzJmZDY1OTJiZjI0NjFhNjI1MA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MTk3OWY0ZGZiY2FhNWFkNjU5MzZjZmI5MGM4Yzc5NzlhMDgyMjk1MA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ODc2NTIzZTViMzRjOTQwYWY1NWUyNzNkMmJkZGRkZTFmYzBkODVmYzFjMzYw
|
10
|
+
ODJjYjM2ZjlkYTU4NzhhMTczZDI1Njg5NGM1MTk2YjVmMWEyMTE0OWNkYWY0
|
11
|
+
ZWMxNWQ2ODhlZGE0MWRiY2JhNDJlZDZjMzg1NDk1NjhhZTg5ZmM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OTkxOWI1NzI2ZGUyYmVhMTZmZDc5Y2VhOTgzZWM3MzQzN2FjNjNiNmE3NDVk
|
14
|
+
NjhiYmYzNzU4YzY2NmJlNzVjMGQ5MjE1YTYyOGY5YjY3YmJiODE3Mzc2ZDNi
|
15
|
+
M2RlZDhhMGVjNWVmMDIzOWE4NDI3MmY5MmZiMmMxZDBhMTNkYzQ=
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Medidata Solutions Worldwide
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Probity
|
2
|
+
|
3
|
+
Even Rails can't be trusted not to produce malformed xml sometimes. Add this Rack middleware to the stack while you run your tests and it will monitor the responses you send, infer the appropriate validations based on content type, and raise if they fail.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'probity', git: 'git@github.com:mdsol/probity.git'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install probity
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Probity should only be included in your middleware stack when running in test/development mode. If you're using a conventional Rails app, for example, you could include it like so:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# in config/environments/test.rb
|
27
|
+
config.middleware.use(Probity::ResponseValidatorMiddleware)
|
28
|
+
```
|
29
|
+
|
30
|
+
Now, run your test scripts! If your app produces malformed responses, Probity will turn a passing test into a failing one by raising a parsing error in your server. Depending on your particular test setup, this might manifest in different ways, but as long as your tests are at all meaningful they at least shouldn't pass.
|
31
|
+
|
32
|
+
## Configuration
|
33
|
+
|
34
|
+
By default, Probity will validate the `application/xml` and `application/json` content types, and **raise** if it sees anything else. If you're serving something other than those two, such as html, you'll probably want to do
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
middleware.use(Probity::ResponseValidatorMiddleware, missing_validator: :warn)
|
38
|
+
#or
|
39
|
+
middleware.use(Probity::ResponseValidatorMiddleware, missing_validator: :ignore)
|
40
|
+
```
|
41
|
+
|
42
|
+
A blank body is not valid JSON or XML. If you would like to special-case this as an allowable response, use
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
middleware.use(Probity::ResponseValidatorMiddleware, blank_body: :ignore)
|
46
|
+
```
|
47
|
+
|
48
|
+
You can add validators for your content types with code like this:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
Probity.validators['application/hal+json'] = Proc.new do |body|
|
52
|
+
raise unless Halidator.new(body).valid?
|
53
|
+
end
|
54
|
+
```
|
55
|
+
You can also override the default validators the same way:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
Probity.validators['application/xml'] = # Object that responds to .call(str)
|
59
|
+
```
|
60
|
+
|
61
|
+
## Validators
|
62
|
+
|
63
|
+
The XML validator uses [Nokogiri](http://www.nokogiri.org/) in Strict Mode, while the JSON validator uses Ruby's built-in `JSON.parse`. Pull requests are welcome for more content types.
|
64
|
+
|
65
|
+
## Contributing
|
66
|
+
|
67
|
+
1. Fork it ( https://github.com/[my-github-username]/probity/fork )
|
68
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
70
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
+
5. Create a new Pull Request
|
data/lib/probity.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module Probity
|
2
|
+
|
3
|
+
class ResponseValidatorMiddleware
|
4
|
+
|
5
|
+
def initialize(app, options = {})
|
6
|
+
@app = app
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
status, headers, response = @app.call(env)
|
12
|
+
content_type = response.respond_to?(:content_type) ? response.content_type : headers["Content-Type"]
|
13
|
+
validator = Probity.validators[content_type]
|
14
|
+
if validator
|
15
|
+
body = response.respond_to?(:body) ? response.body : response.join("")
|
16
|
+
validate(body, validator)
|
17
|
+
else
|
18
|
+
missing_validator(content_type)
|
19
|
+
end
|
20
|
+
[status, headers, response]
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate(body, validator)
|
24
|
+
if blank_string?(body)
|
25
|
+
blank_body(body, validator)
|
26
|
+
else
|
27
|
+
validator.call(body)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def blank_string?(str)
|
32
|
+
! str[/\S/]
|
33
|
+
end
|
34
|
+
|
35
|
+
def blank_body(body, validator)
|
36
|
+
case @options[:blank_body]
|
37
|
+
when nil, :validate
|
38
|
+
validator.call(body)
|
39
|
+
when :raise
|
40
|
+
raise 'Response with an empty body'
|
41
|
+
when :ignore
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def missing_validator(content_type)
|
46
|
+
error = "No validator defined for #{content_type}. Fix this by putting `#{self.class}.validators['#{content_type}'] = Proc.new do |body| ... end` in a test initializer."
|
47
|
+
case @options[:missing_validator]
|
48
|
+
when nil, :raise
|
49
|
+
raise error
|
50
|
+
when :warn
|
51
|
+
warn(error)
|
52
|
+
when :ignore
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/probity.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'probity/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'probity'
|
8
|
+
spec.version = Probity::VERSION
|
9
|
+
spec.authors = ['Aaron Weiner', 'Curtis White']
|
10
|
+
spec.email = spec.authors.map{|name|name.sub(/(.).* (.*)/,'\1\2@mdsol.com')}
|
11
|
+
spec.summary = %q{Rack middleware to test whether your app is producing valid json, xml, etc.}
|
12
|
+
spec.description = %q{Even Rails can't be trusted not to produce malformed xml sometimes. Add this Rack middleware to the stack while you run your tests and it will monitor the responses you send, infer the appropriate validations based on content type, and raise if they fail.}
|
13
|
+
spec.homepage = 'https://github.com/mdsol/probity'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
22
|
+
spec.add_development_dependency 'rspec'
|
23
|
+
|
24
|
+
spec.add_dependency 'nokogiri'
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'probity'
|
2
|
+
|
3
|
+
describe(Probity::ResponseValidatorMiddleware) do
|
4
|
+
|
5
|
+
context 'missing a validator for the content type' do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@inner_app = double
|
9
|
+
@response = double
|
10
|
+
allow(@response).to receive(:content_type).and_return('magic')
|
11
|
+
allow(@inner_app).to receive(:call).and_return([200, {}, @response])
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'raises by default' do
|
15
|
+
app = described_class.new(@inner_app)
|
16
|
+
expect{app.call({})}.to raise_error(RuntimeError, /No validator defined for magic/)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'warns when passed {missing_validator: :warn}' do
|
20
|
+
app = described_class.new(@inner_app, missing_validator: :warn)
|
21
|
+
expect_any_instance_of(Object).to receive(:warn).once
|
22
|
+
expect{app.call({})}.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does nothing when passed ignore' do
|
26
|
+
app = described_class.new(@inner_app, missing_validator: :ignore)
|
27
|
+
expect_any_instance_of(Object).not_to receive(:warn)
|
28
|
+
expect{app.call({})}.not_to raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with an array of json strings as the body" do
|
32
|
+
before do
|
33
|
+
@body = [
|
34
|
+
JSON.pretty_generate( {'errors' => {'authentication' => ['Unauthorized']}} ),
|
35
|
+
JSON.pretty_generate( {'warning' => "warning"} )
|
36
|
+
]
|
37
|
+
|
38
|
+
allow(@response).to receive(:content_type).and_return('magic')
|
39
|
+
allow(@response).to receive(:body).and_return(@body)
|
40
|
+
allow(@inner_app).to receive(:call).and_return([401, {'Content-Type' => 'magic'}, @body])
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'raises by default' do
|
44
|
+
app = described_class.new(@inner_app)
|
45
|
+
expect{app.call({})}.to raise_error(RuntimeError, /No validator defined for magic/)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'warns when passed {missing_validator: :warn}' do
|
49
|
+
app = described_class.new(@inner_app, missing_validator: :warn)
|
50
|
+
expect_any_instance_of(Object).to receive(:warn).once
|
51
|
+
expect{app.call({})}.not_to raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'does nothing when passed ignore' do
|
55
|
+
app = described_class.new(@inner_app, missing_validator: :ignore)
|
56
|
+
expect_any_instance_of(Object).not_to receive(:warn)
|
57
|
+
expect{app.call({})}.not_to raise_error
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with an appropriate validator' do
|
65
|
+
|
66
|
+
before do
|
67
|
+
@inner_app = double
|
68
|
+
@response = double
|
69
|
+
@body = 'some_body'
|
70
|
+
allow(@response).to receive(:content_type).and_return('application/json')
|
71
|
+
allow(@response).to receive(:body).and_return(@body)
|
72
|
+
allow(@inner_app).to receive(:call).and_return([201,{'foo' => 'bar'},@response])
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'calls the appropriate validator' do
|
76
|
+
expect(Probity.validators['application/json']).to receive(:call).with(@body)
|
77
|
+
expect(Probity.validators['application/xml']).not_to receive(:call)
|
78
|
+
app = described_class.new(@inner_app)
|
79
|
+
app.call({})
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'passes the response through transparently if no error is raised by the validator' do
|
83
|
+
allow(Probity.validators['application/json']).to receive(:call).and_return(nil)
|
84
|
+
app = described_class.new(@inner_app)
|
85
|
+
expect(app.call({})).to eq([201,{'foo' => 'bar'},@response])
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'with an empty body' do
|
89
|
+
|
90
|
+
before do
|
91
|
+
@inner_app = double
|
92
|
+
@response = double
|
93
|
+
@body = ''
|
94
|
+
allow(@response).to receive(:content_type).and_return('application/json')
|
95
|
+
allow(@response).to receive(:body).and_return(@body)
|
96
|
+
allow(@inner_app).to receive(:call).and_return([201,{'foo' => 'bar'},@response])
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'validates as normal by default' do
|
100
|
+
expect(Probity.validators['application/json']).to receive(:call).with(@body)
|
101
|
+
app = described_class.new(@inner_app)
|
102
|
+
app.call({})
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'raises when passed {blank_body: :raise}' do
|
106
|
+
expect(Probity.validators['application/json']).not_to receive(:call)
|
107
|
+
app = described_class.new(@inner_app, blank_body: :raise)
|
108
|
+
expect{app.call({})}.to raise_error(/Response with an empty body/)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'skips validation when passed {blank_body: :ignore}' do
|
112
|
+
expect(Probity.validators['application/json']).not_to receive(:call)
|
113
|
+
app = described_class.new(@inner_app, blank_body: :ignore)
|
114
|
+
expect{app.call({})}.not_to raise_error
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with an array of json strings as the body" do
|
120
|
+
before do
|
121
|
+
@body = [
|
122
|
+
JSON.pretty_generate( {'errors' => {'authentication' => ['Unauthorized']}} ),
|
123
|
+
JSON.pretty_generate( {'warning' => "warning"} )
|
124
|
+
]
|
125
|
+
|
126
|
+
allow(@response).to receive(:content_type).and_return('application/json')
|
127
|
+
allow(@response).to receive(:body).and_return(@body)
|
128
|
+
allow(@inner_app).to receive(:call).and_return([401, {'Content-Type' => 'application/json'}, @body])
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'validates the joined json strings by default' do
|
132
|
+
expect(Probity.validators['application/json']).to receive(:call).with(@body.join(""))
|
133
|
+
app = described_class.new(@inner_app)
|
134
|
+
app.call({})
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'probity'
|
2
|
+
|
3
|
+
describe "Probity's built-in json validator" do
|
4
|
+
|
5
|
+
it 'is callable' do
|
6
|
+
expect(Probity.validators['application/json']).to respond_to(:call)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'does not raise on valid json' do
|
10
|
+
valid_json = <<-'JSON'
|
11
|
+
{"fruit": [
|
12
|
+
{"name": "apple",
|
13
|
+
"number": 3}
|
14
|
+
]
|
15
|
+
}
|
16
|
+
JSON
|
17
|
+
expect{Probity.validators['application/json'].call(valid_json)}.not_to raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'raises an error on invalid json' do
|
21
|
+
expect{Probity.validators['application/json'].call('{"fruit":[,{"name":"apple","number":3}]}')}.to raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'probity'
|
2
|
+
|
3
|
+
describe "Probity's built-in xml validator" do
|
4
|
+
|
5
|
+
it 'is callable' do
|
6
|
+
expect(Probity.validators['application/xml']).to respond_to(:call)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'does not raise on valid xml' do
|
10
|
+
valid_xml = <<-'XML'
|
11
|
+
<?xml version="1.0"?>
|
12
|
+
<?xml-stylesheet href="example.xsl" type="text/xsl"?>
|
13
|
+
<!DOCTYPE example SYSTEM "example.dtd">
|
14
|
+
<fruit>
|
15
|
+
<apple color="red" image="red_apple_1.jpg">
|
16
|
+
<condition>Fresh</condition>
|
17
|
+
</apple>
|
18
|
+
</fruit>
|
19
|
+
XML
|
20
|
+
expect{Probity.validators['application/xml'].call(valid_xml)}.not_to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'raises an error on invalid xml' do
|
24
|
+
expect{Probity.validators['application/xml'].call('<a></b>')}.to raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: probity
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aaron Weiner
|
8
|
+
- Curtis White
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-05-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.7'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.7'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rspec
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: nokogiri
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: Even Rails can't be trusted not to produce malformed xml sometimes. Add
|
57
|
+
this Rack middleware to the stack while you run your tests and it will monitor the
|
58
|
+
responses you send, infer the appropriate validations based on content type, and
|
59
|
+
raise if they fail.
|
60
|
+
email:
|
61
|
+
- AWeiner@mdsol.com
|
62
|
+
- CWhite@mdsol.com
|
63
|
+
executables: []
|
64
|
+
extensions: []
|
65
|
+
extra_rdoc_files: []
|
66
|
+
files:
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- lib/probity.rb
|
71
|
+
- lib/probity/middleware.rb
|
72
|
+
- lib/probity/validators/json.rb
|
73
|
+
- lib/probity/validators/xml.rb
|
74
|
+
- lib/probity/version.rb
|
75
|
+
- probity.gemspec
|
76
|
+
- spec/middleware_spec.rb
|
77
|
+
- spec/validators/json_spec.rb
|
78
|
+
- spec/validators/xml_spec.rb
|
79
|
+
homepage: https://github.com/mdsol/probity
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.1.10
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Rack middleware to test whether your app is producing valid json, xml, etc.
|
103
|
+
test_files:
|
104
|
+
- spec/middleware_spec.rb
|
105
|
+
- spec/validators/json_spec.rb
|
106
|
+
- spec/validators/xml_spec.rb
|
107
|
+
has_rdoc:
|