jason_spec 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +72 -0
- data/LICENSE.txt +20 -0
- data/README.md +120 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/lib/jason/have_jason_matcher.rb +158 -0
- data/lib/jason/matchers.rb +14 -0
- data/lib/jason/spec.rb +264 -0
- data/lib/jason_spec.rb +4 -0
- data/spec/have_jason_matcher_spec.rb +72 -0
- data/spec/jason_spec_spec.rb +174 -0
- data/spec/matchers_spec.rb +23 -0
- data/spec/readme_spec.rb +62 -0
- data/spec/spec_helper.rb +12 -0
- metadata +144 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.3.5)
|
5
|
+
builder (3.2.2)
|
6
|
+
diff-lcs (1.1.3)
|
7
|
+
faraday (0.8.8)
|
8
|
+
multipart-post (~> 1.2.0)
|
9
|
+
git (1.2.6)
|
10
|
+
github_api (0.10.1)
|
11
|
+
addressable
|
12
|
+
faraday (~> 0.8.1)
|
13
|
+
hashie (>= 1.2)
|
14
|
+
multi_json (~> 1.4)
|
15
|
+
nokogiri (~> 1.5.2)
|
16
|
+
oauth2
|
17
|
+
hashie (2.0.5)
|
18
|
+
highline (1.6.19)
|
19
|
+
httpauth (0.2.0)
|
20
|
+
jeweler (1.8.7)
|
21
|
+
builder
|
22
|
+
bundler (~> 1.0)
|
23
|
+
git (>= 1.2.5)
|
24
|
+
github_api (= 0.10.1)
|
25
|
+
highline (>= 1.6.15)
|
26
|
+
nokogiri (= 1.5.10)
|
27
|
+
rake
|
28
|
+
rdoc
|
29
|
+
json (1.8.0)
|
30
|
+
jwt (0.1.8)
|
31
|
+
multi_json (>= 1.5)
|
32
|
+
multi_json (1.8.0)
|
33
|
+
multi_xml (0.5.5)
|
34
|
+
multipart-post (1.2.0)
|
35
|
+
nokogiri (1.5.10)
|
36
|
+
oauth2 (0.9.2)
|
37
|
+
faraday (~> 0.8)
|
38
|
+
httpauth (~> 0.2)
|
39
|
+
jwt (~> 0.1.4)
|
40
|
+
multi_json (~> 1.0)
|
41
|
+
multi_xml (~> 0.5)
|
42
|
+
rack (~> 1.2)
|
43
|
+
rack (1.5.2)
|
44
|
+
rake (10.1.0)
|
45
|
+
rdoc (3.12.2)
|
46
|
+
json (~> 1.4)
|
47
|
+
rspec (2.8.0)
|
48
|
+
rspec-core (~> 2.8.0)
|
49
|
+
rspec-expectations (~> 2.8.0)
|
50
|
+
rspec-mocks (~> 2.8.0)
|
51
|
+
rspec-core (2.8.0)
|
52
|
+
rspec-expectations (2.8.0)
|
53
|
+
diff-lcs (~> 1.1.2)
|
54
|
+
rspec-mocks (2.8.0)
|
55
|
+
rufus-json (1.0.6)
|
56
|
+
simplecov (0.7.1)
|
57
|
+
multi_json (~> 1.0)
|
58
|
+
simplecov-html (~> 0.7.1)
|
59
|
+
simplecov-html (0.7.1)
|
60
|
+
yard (0.8.7.2)
|
61
|
+
|
62
|
+
PLATFORMS
|
63
|
+
ruby
|
64
|
+
|
65
|
+
DEPENDENCIES
|
66
|
+
bundler (~> 1.0)
|
67
|
+
jeweler (~> 1.8.7)
|
68
|
+
rdoc (~> 3.12)
|
69
|
+
rspec (~> 2.8.0)
|
70
|
+
rufus-json (= 1.0.6)
|
71
|
+
simplecov
|
72
|
+
yard (~> 0.7)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 OrganisedMinds GmbH
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# jason_spec
|
2
|
+
|
3
|
+
Write specs for JSON without writing JSON or data-structures
|
4
|
+
|
5
|
+
<a href="http://www.flickr.com/photos/frogdna/5534481247/" title="Friday the 13th - Jason Mask Replica by frogDNA, on Flickr"><img src="http://farm6.staticflickr.com/5094/5534481247_361aa64980.jpg" width="375" height="500" alt="Friday the 13th - Jason Mask Replica"></a>
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
`gem install jason_spec`
|
10
|
+
|
11
|
+
or, in your Gemfile, possibly in the test group
|
12
|
+
|
13
|
+
`gem "jason_spec"`
|
14
|
+
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
### Test by specification
|
19
|
+
|
20
|
+
Jason spec is designed to test json by specifying the desired result. This
|
21
|
+
means you should not type or create any JSON; or even data structures.
|
22
|
+
|
23
|
+
The following snippet:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
%q({"first_name":"Jason","last_name":"Voorhees"}).should have_jason([:first_name,:last_name])
|
27
|
+
```
|
28
|
+
|
29
|
+
would result in a match. The supplied JSON has a `:first_name` and a
|
30
|
+
`:last_name` key - that's all we wanted to know.
|
31
|
+
|
32
|
+
Off course, you can also specify your root object:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
%q({"movie":{"title":"Friday the 13th","release_year":"1980"}}).should have_jason(
|
36
|
+
movie: [ :title, :release_year ]
|
37
|
+
)
|
38
|
+
```
|
39
|
+
|
40
|
+
### Test by object
|
41
|
+
|
42
|
+
Now it is also nice to test the actual values; you can do this by supplying an
|
43
|
+
object in the specifications key, like so:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
# assuming ActiveRecord or so
|
47
|
+
|
48
|
+
my_movie = Movie.find(x)
|
49
|
+
|
50
|
+
%q({"movie":{"title":"Friday the 13th","release_year":"1980"}}).should have_jason(
|
51
|
+
{ movie: { my_movie => [ :title, :release_year ] } }
|
52
|
+
)
|
53
|
+
```
|
54
|
+
|
55
|
+
This will check the values of the JSON against the value of `my_movie.title`
|
56
|
+
and `my_movie.release_year`
|
57
|
+
|
58
|
+
### Test by enhanced specification
|
59
|
+
|
60
|
+
Now; that is all pretty nice and dandy, but what about complex(er) JSON
|
61
|
+
structures? How can I test those, without supplying huge structures as a
|
62
|
+
specification?
|
63
|
+
|
64
|
+
**Jason::Spec** to the resque:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
%q({"movies":[{"title":"Friday the 13th"},{"title":"Nightmare on Elm Street"}]}).should have_jason(
|
68
|
+
movies: Jason.spec( type: Array, size: 2, each: [ :title ] )
|
69
|
+
)
|
70
|
+
```
|
71
|
+
|
72
|
+
Basicly we are saying; the JSON should have a `movies` key, it should hold
|
73
|
+
an `Array` with a size of `2` and each element should have a `title` key.
|
74
|
+
|
75
|
+
Off course you should combine all of it to make full use of the potential:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
json = %q({"user":{
|
79
|
+
"user_name":"jason",
|
80
|
+
"favorite_movies":[
|
81
|
+
{"title":"Friday the 13th","id":1},
|
82
|
+
{"title":"Nightmare on Elm Street","id":2}
|
83
|
+
]
|
84
|
+
},
|
85
|
+
"links":[
|
86
|
+
{ "href":"/users/2", "rel": "self" },
|
87
|
+
{ "href":"/users/2/movies", "rel": "favorite movies"}
|
88
|
+
]
|
89
|
+
})
|
90
|
+
|
91
|
+
json.should have_jason(
|
92
|
+
user: {
|
93
|
+
user_name: "jason",
|
94
|
+
favorite_movies: Jason.spec(type: Array, each: [ :title, :id ])
|
95
|
+
},
|
96
|
+
links: Jason.spec(type: Array, each: [ :href, :rel ])
|
97
|
+
)
|
98
|
+
```
|
99
|
+
|
100
|
+
## State
|
101
|
+
|
102
|
+
Alpha - not even released to RubyGems.org.
|
103
|
+
|
104
|
+
The final example might just work, see `spec/readme_spec.rb`
|
105
|
+
|
106
|
+
## Contributing to jason_spec
|
107
|
+
|
108
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
109
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
110
|
+
* Fork the project.
|
111
|
+
* Start a feature/bugfix branch.
|
112
|
+
* Commit and push until you are happy with your contribution.
|
113
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
114
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
115
|
+
|
116
|
+
## Copyright
|
117
|
+
|
118
|
+
Copyright (c) 2013 OrganisedMinds GmbH. See LICENSE.txt for
|
119
|
+
further details.
|
120
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "jason_spec"
|
18
|
+
gem.homepage = "http://github.com/coffeeaddict/jason_spec"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Spec your JSON}
|
21
|
+
gem.description = %Q{Write specifications for the expected json, without writing json}
|
22
|
+
gem.email = "hartog@organisedminds.com"
|
23
|
+
gem.authors = ["Hartog C. de Mik"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'yard'
|
42
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'jason/spec'
|
3
|
+
|
4
|
+
module Jason
|
5
|
+
|
6
|
+
# Provides the have_jason functionality
|
7
|
+
class HaveJasonMatcher
|
8
|
+
|
9
|
+
# @param [Array,Hash] specs List of specifications
|
10
|
+
#
|
11
|
+
# @example Specs by array
|
12
|
+
# # will check if the actual JSON has a foo and a bar key
|
13
|
+
# HaveJasonMatcher.new([ :foo, :bar ])
|
14
|
+
#
|
15
|
+
# @example Specs by hash
|
16
|
+
# # will check if the actual has an item object with a foo and a bar key
|
17
|
+
# HaveJasonMatcher.new( item: [ :foo, :bar ])
|
18
|
+
#
|
19
|
+
# # will check if the actual has an item object with a foo key with a
|
20
|
+
# # bar value
|
21
|
+
# HaveJasonMatcher.new( item: { foo: "bar" } )
|
22
|
+
#
|
23
|
+
# @example Specs by hash with objects
|
24
|
+
# # will check if the actual has a attribute key with the value of
|
25
|
+
# # ruby_object.attribute()
|
26
|
+
# HaveJasonMatcher.new( ruby_object => [ :attribute ] )
|
27
|
+
#
|
28
|
+
# @example Specs by Jason.spec
|
29
|
+
# # will check the actual against the provided Jason::Spec
|
30
|
+
# HaveJasonMatcher.new( item: Jason.spec(type: Hash, fields: [ :foo, :bar ] ))
|
31
|
+
#
|
32
|
+
def initialize(specs)
|
33
|
+
@specs = specs
|
34
|
+
end
|
35
|
+
|
36
|
+
# Check if the given JSON matches the specifications
|
37
|
+
#
|
38
|
+
# @param [JSON, Hash] actual the value to check
|
39
|
+
#
|
40
|
+
# @return [Boolean]
|
41
|
+
#
|
42
|
+
def matches?(actual)
|
43
|
+
@actual = actual.is_a?(String) ? Rufus::Json.decode(actual) : actual
|
44
|
+
|
45
|
+
@misses = match_recursively(@specs, @actual)
|
46
|
+
|
47
|
+
@misses.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
# recursivly walk over the specs and the actual to find any misses
|
51
|
+
#
|
52
|
+
# @param [Array,Hash] specs List of specifications
|
53
|
+
# @param [Array,Hash] actual Provided data-structure (once JSON)
|
54
|
+
#
|
55
|
+
# @return [Hash] Hash with all the misses
|
56
|
+
#
|
57
|
+
def match_recursively(specs, actual, root="")
|
58
|
+
actual ||= {}
|
59
|
+
|
60
|
+
misses = {}
|
61
|
+
|
62
|
+
if specs.is_a?(Array)
|
63
|
+
specs.map(&:to_s).each do |key|
|
64
|
+
res_key = root != "" ? "#{root}.#{key}" : "#{key}"
|
65
|
+
if !actual.has_key? key
|
66
|
+
misses[res_key] = :missing
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
return misses
|
71
|
+
end
|
72
|
+
|
73
|
+
if specs.is_a?(Jason::Spec)
|
74
|
+
root = "root" if root == ""
|
75
|
+
|
76
|
+
if !actual
|
77
|
+
misses[root] = { expected: { key: root }, got: :not_present }
|
78
|
+
elsif !specs.fits?(actual)
|
79
|
+
misses[root] = { expected: specs.opts, got: specs.misses }
|
80
|
+
end
|
81
|
+
|
82
|
+
return misses
|
83
|
+
end
|
84
|
+
|
85
|
+
specs.each do |key, value|
|
86
|
+
res_key = root != "" ? "#{root}.#{key}" : "#{key}"
|
87
|
+
key = key.to_s if key.is_a?(Symbol)
|
88
|
+
|
89
|
+
if key.is_a?(String)
|
90
|
+
if value.is_a?(Jason::Spec)
|
91
|
+
if !actual[key]
|
92
|
+
misses[res_key] = { expected: { key: key }, got: :not_present }
|
93
|
+
next
|
94
|
+
end
|
95
|
+
|
96
|
+
if !value.fits?(actual[key])
|
97
|
+
misses[res_key] = { expected: value.opts, got: value.misses }
|
98
|
+
end
|
99
|
+
|
100
|
+
elsif value.is_a?(Array) or value.is_a?(Hash)
|
101
|
+
begin
|
102
|
+
misses.merge!(match_recursively(value, actual[key], res_key))
|
103
|
+
rescue => ex
|
104
|
+
$stderr.puts ex.backtrace.join("\n\t")
|
105
|
+
misses[res_key] = { error: ex.message }
|
106
|
+
end
|
107
|
+
|
108
|
+
elsif actual[key] != value
|
109
|
+
misses[res_key] = { expected: value, got: actual[key] }
|
110
|
+
end
|
111
|
+
|
112
|
+
else # the key is an object, the value is an array of methods
|
113
|
+
value.each do |attr|
|
114
|
+
res_key = root != "" ? "#{root}.#{attr}" : "#{attr}"
|
115
|
+
|
116
|
+
if attr.is_a?(Hash)
|
117
|
+
misses.merge!(match_recursively(attr, actual[attr], res_key))
|
118
|
+
next
|
119
|
+
end
|
120
|
+
|
121
|
+
attr = attr.to_s
|
122
|
+
|
123
|
+
expected = key.send(attr) rescue nil
|
124
|
+
found = actual[attr]
|
125
|
+
|
126
|
+
if found
|
127
|
+
if expected.is_a?(Time)
|
128
|
+
# revert to seconds - microseconds do not compare
|
129
|
+
found = Time.at(Time.parse(found).to_i)
|
130
|
+
expected = Time.at(expected.to_i)
|
131
|
+
|
132
|
+
elsif expected.is_a?(Date)
|
133
|
+
found = Date.parse(found)
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
if found != expected
|
139
|
+
misses[res_key] = { expected: expected, got: found }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
return misses
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [String] Message to provide if it should have matched but didn't
|
149
|
+
def failure_message
|
150
|
+
"Jason misses: #{@misses.pretty_inspect}\n\tin #{@actual}"
|
151
|
+
end
|
152
|
+
|
153
|
+
# @return [String] Message to provide if it shouldn't have matched but did
|
154
|
+
def negative_failure_message
|
155
|
+
"Jason has: #{@actual}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/lib/jason/spec.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
module Jason
|
2
|
+
|
3
|
+
# @returns [Jason::Spec] Specifications for JSON checking
|
4
|
+
def self.spec(spec)
|
5
|
+
Spec.new(spec)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Class for holding and checking specifications for a JSON structure
|
9
|
+
#
|
10
|
+
# @attr_reader [Hash] specs Stored specifications
|
11
|
+
# @attr_reader [Array] misses List of collected failures
|
12
|
+
#
|
13
|
+
class Spec
|
14
|
+
attr_reader :specs, :misses
|
15
|
+
|
16
|
+
# @param [Hash] specs Specifications for testing
|
17
|
+
# @option specs [Class] :type Type of the actual
|
18
|
+
# @option specs [Integer] :size Size of the actual
|
19
|
+
# @option specs [Array] :each Each element in actual should have
|
20
|
+
# these fields
|
21
|
+
# @option specs [Array] :fields Fields that should be present in actual
|
22
|
+
#
|
23
|
+
def initialize(specs)
|
24
|
+
@specs = specs
|
25
|
+
@misses = []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if the specs fit the actual
|
29
|
+
#
|
30
|
+
# @returns [Boolean]
|
31
|
+
#
|
32
|
+
def fits?(actual)
|
33
|
+
@misses = [] # reset misses
|
34
|
+
@specs.each do |key, value|
|
35
|
+
method = :"match_#{key}"
|
36
|
+
if !respond_to?(method)
|
37
|
+
@misses << "Unknown spec: #{key}"
|
38
|
+
break
|
39
|
+
end
|
40
|
+
|
41
|
+
begin
|
42
|
+
self.send(method, value, actual)
|
43
|
+
rescue => ex
|
44
|
+
@misses << "Error in #{key} check: #{ex.class}: #{ex.message}"
|
45
|
+
end
|
46
|
+
|
47
|
+
break if @misses.any?
|
48
|
+
end
|
49
|
+
|
50
|
+
@misses.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
# Does the value match the requested type, populates @misses in failure
|
54
|
+
#
|
55
|
+
# @param [Symbol, String, Class] type What type should the value be.
|
56
|
+
# Supported strings are: hash, array, string or boolean
|
57
|
+
#
|
58
|
+
# @param [Object] value
|
59
|
+
#
|
60
|
+
# @example Hash
|
61
|
+
# match_type(:hash, { foo: "bar" }) # match
|
62
|
+
# match_type("array", [0,1,2]) # match
|
63
|
+
# match_type(String, "meh") # match
|
64
|
+
# match_tyoe(:booelean, false) # match
|
65
|
+
#
|
66
|
+
# @return [void]
|
67
|
+
def match_type(type, value)
|
68
|
+
matched = case type
|
69
|
+
when :array, :Array, "array", "Array"
|
70
|
+
value.is_a?(Array)
|
71
|
+
when :hash, :Hash, "hash", "Hash"
|
72
|
+
value.is_a?(Hash)
|
73
|
+
when :string, "string", "String"
|
74
|
+
value.is_a?(String)
|
75
|
+
when :boolean, :Boolean, "boolean", "Boolean"
|
76
|
+
value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
77
|
+
else
|
78
|
+
value.is_a?(type)
|
79
|
+
end
|
80
|
+
|
81
|
+
@misses << "Type mismatch; Expected #{type}, got #{value.class}: #{value}" if !matched
|
82
|
+
end
|
83
|
+
|
84
|
+
# Does the value match the requested size. Populates @misses in failure
|
85
|
+
#
|
86
|
+
# @param [Integer] size The needed size
|
87
|
+
# @param [Object] value
|
88
|
+
# @return [void]
|
89
|
+
#
|
90
|
+
def match_size(size, value)
|
91
|
+
if !value.respond_to?(:size)
|
92
|
+
@misses << "Size mismatch; #{value} has no size"
|
93
|
+
return
|
94
|
+
end
|
95
|
+
|
96
|
+
hit = if size.is_a?(Fixnum)
|
97
|
+
value.size == size
|
98
|
+
elsif size.is_a?(Range)
|
99
|
+
size.cover?(value.size)
|
100
|
+
elsif size.is_a?(Array)
|
101
|
+
size.include?(value.size)
|
102
|
+
end
|
103
|
+
|
104
|
+
@misses << "Size mismatch; Expected #{size}, got #{value.size}" if !hit
|
105
|
+
end
|
106
|
+
|
107
|
+
# Does the array contain each of the requested specs
|
108
|
+
#
|
109
|
+
# @param [Hash,Array,Jason::Spec] mapping What the array should contain
|
110
|
+
# @param [Array] value Array to check
|
111
|
+
# @param [Symbol] type How to check:
|
112
|
+
# * :each - all items must match)
|
113
|
+
# * :any - at least one item must match)
|
114
|
+
# * :none - no item may match
|
115
|
+
# @param [String] root Root for recursive checks
|
116
|
+
#
|
117
|
+
# @return [void]
|
118
|
+
#
|
119
|
+
# @example Shallow check for key
|
120
|
+
# match_each([ :id ], [ { 'id' => 1 }])
|
121
|
+
#
|
122
|
+
# @example Shallow check for key with any
|
123
|
+
# match_each([ :id ], [ { 'id' => 1 }, { 'bar' => 'beer' } ], :any )
|
124
|
+
#
|
125
|
+
# @example Shallow check for key with none
|
126
|
+
# not match_each([ :id ], [ { 'id' => 1 }, { 'bar' => 'beer' } ], :any )
|
127
|
+
#
|
128
|
+
# @example Deep check
|
129
|
+
# match_each(
|
130
|
+
# { item: [ :id, :name ] }
|
131
|
+
# [ { "item" => { "id" => "one", "name" => "two" } } ]
|
132
|
+
# )
|
133
|
+
#
|
134
|
+
def match_each(mapping, value, type=:each, root="")
|
135
|
+
misses = []
|
136
|
+
if mapping.is_a?(Array)
|
137
|
+
misses = match_each_shallow(mapping, value)
|
138
|
+
else
|
139
|
+
value.each_with_index do |val, index|
|
140
|
+
if !val.is_a?(Hash)
|
141
|
+
misses << "Each check failed. #{val} is no hash at #{root}[#{index}]"
|
142
|
+
break
|
143
|
+
end
|
144
|
+
|
145
|
+
mapping.each do |key, fields|
|
146
|
+
key = key.to_s
|
147
|
+
miss_key = root == "" ? key : "#{root}.#{key}"
|
148
|
+
|
149
|
+
if !val[key]
|
150
|
+
misses << "Each check failed. Key #{miss_key} is missing at #{root}[#{index}]"
|
151
|
+
end
|
152
|
+
|
153
|
+
if !val[key].is_a?(Hash)
|
154
|
+
misses << "Each check failed. #{miss_key} is no hash at #{root}[#{index}]"
|
155
|
+
end
|
156
|
+
|
157
|
+
if fields.is_a?(Hash)
|
158
|
+
match_each(fields,val[key],type,miss_key)
|
159
|
+
next
|
160
|
+
end
|
161
|
+
|
162
|
+
fields.each do |attr|
|
163
|
+
if !val[key].has_key?(attr.to_s)
|
164
|
+
misses << "Each check failed. #{miss_key}[#{attr}] is missing at #{root}[#{index}]"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
case type
|
172
|
+
when :each
|
173
|
+
@misses += misses.compact
|
174
|
+
when :any
|
175
|
+
if misses.compact.size == value.size
|
176
|
+
@misses << "Shallow any check failed: #{misses}"
|
177
|
+
end
|
178
|
+
when :none
|
179
|
+
if misses.compact.size != value.size
|
180
|
+
@misses << "Shallow none check failed: #{misses}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Wrapper around #match_each
|
186
|
+
#
|
187
|
+
def match_any(fields, value)
|
188
|
+
match_each(fields, value, :any)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Wrapper around #match_each
|
192
|
+
#
|
193
|
+
def match_none(fields, value)
|
194
|
+
match_each(fields, value, :none)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Match each only for fields
|
198
|
+
#
|
199
|
+
# @param [Array<Symbol>] fields list of required fields
|
200
|
+
# @param [Array] list of objects that carry fields
|
201
|
+
# @return [void]
|
202
|
+
#
|
203
|
+
def match_each_shallow(fields, value)
|
204
|
+
misses = []
|
205
|
+
value.each_with_index do |val, index|
|
206
|
+
fields.each do |attr|
|
207
|
+
if !val.has_key?(attr.to_s)
|
208
|
+
misses[index] = "Shallow each check failed. Key #{attr} is missing at [#{index}]"
|
209
|
+
break
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
return misses
|
215
|
+
end
|
216
|
+
|
217
|
+
# Match fields on a hash
|
218
|
+
# @param [Hash,Array<Symbol>] fields list of required fields
|
219
|
+
# @param [Hash] value Hash to check fields in
|
220
|
+
# @return [void]
|
221
|
+
#
|
222
|
+
# @example Using array (each)
|
223
|
+
# # every field must be present
|
224
|
+
# spec = Jason.spec(fields: [ :id, :name ])
|
225
|
+
# spec.fits({ 'id' => 1, 'name' => "jason" })
|
226
|
+
# not spec.fits({ 'id' => 1 })
|
227
|
+
#
|
228
|
+
# @example Using each
|
229
|
+
# # same as passing the array
|
230
|
+
# spec = Jason.spec(fields: { each: [ :id, :name ] })
|
231
|
+
# spec.fits({ 'id' => 1, 'name' => "jason" })
|
232
|
+
# not spec.fits({ 'id' => 1 })
|
233
|
+
#
|
234
|
+
# @example Using any
|
235
|
+
# spec = Jason.spec(fields: { any: [ :id, :name ] })
|
236
|
+
# spec.fits({ 'id' => 1 })
|
237
|
+
#
|
238
|
+
# @example Using none
|
239
|
+
# spec = Jason.spec(fields: { none: [ :id, :name ] })
|
240
|
+
# not spec.fits({ 'id' => 1 })
|
241
|
+
#
|
242
|
+
def match_fields(fields, value, type=:each)
|
243
|
+
if fields.is_a?(Hash)
|
244
|
+
fields.each do |type, v_fields|
|
245
|
+
match_fields(v_fields, value, type)
|
246
|
+
end
|
247
|
+
return
|
248
|
+
end
|
249
|
+
|
250
|
+
fields.map!(&:to_s)
|
251
|
+
res = fields & value.keys
|
252
|
+
|
253
|
+
case type
|
254
|
+
when :each
|
255
|
+
@misses << "Field(s) #{res - fields} are missing" if res.sort != fields.sort
|
256
|
+
when :any
|
257
|
+
@misses << "None of the fields #{fields} where found" if res.empty?
|
258
|
+
when :none
|
259
|
+
@misses << "Fields #{res} found, none of them where expected" if res.any?
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
end
|
data/lib/jason_spec.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'jason_spec'
|
4
|
+
|
5
|
+
describe Jason::HaveJasonMatcher do
|
6
|
+
it "should match non-rooted objects" do
|
7
|
+
%({"first_name":"Jason","last_name":"Voorhees"}).should have_jason(
|
8
|
+
[:first_name, :last_name]
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should negate match non-rooted objects" do
|
13
|
+
%({"first_name":"Jason","last_name":"Voorhees"}).should_not have_jason(
|
14
|
+
[:url, :email]
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should match rooted objects" do
|
19
|
+
%({"user":{"first_name":"Jason","last_name":"Voorhees"}}).should have_jason(
|
20
|
+
{ user: [:first_name, :last_name] }
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should negate match rooted objects" do
|
25
|
+
%({"user":{"first_name":"Jason","last_name":"Voorhees"}}).should_not have_jason(
|
26
|
+
{ user: [:email, :url] }
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "With given object" do
|
31
|
+
class User
|
32
|
+
attr_reader :first_name, :last_name
|
33
|
+
def initialize(fn, ln)
|
34
|
+
@first_name = fn; @last_name = ln
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
let(:user) { User.new("Jason", "Voorhees") }
|
39
|
+
|
40
|
+
it "should exactly match rooted object" do
|
41
|
+
%({"user":{"first_name":"Jason","last_name":"Voorhees"}}).should have_jason(
|
42
|
+
{ user: { user => [:first_name, :last_name] } }
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should negate exactly match rooted object" do
|
47
|
+
%({"user":{"first_name":"Freddy","last_name":"Kruger"}}).should_not have_jason(
|
48
|
+
{ user: { user => [:first_name, :last_name] } }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should exactly match non-rooted object" do
|
53
|
+
%({"first_name":"Jason","last_name":"Voorhees"}).should have_jason(
|
54
|
+
{ user => [:first_name, :last_name] }
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should negate exactly matched non-rooted object" do
|
59
|
+
%({"user":{"first_name":"Freddy","last_name":"Kruger"}}).should_not have_jason(
|
60
|
+
{ user => [:first_name, :last_name] }
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "With Jason::Spec" do
|
66
|
+
it "takes a Jason::Spec" do
|
67
|
+
%([{"name":"Alexis"},{"name":"Ali"},{"name":"Freddy Kruger"}]).should have_jason(
|
68
|
+
Jason.spec(type: :array, each: [ :name ])
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jason::Spec do
|
4
|
+
it "provides a spec class method" do
|
5
|
+
Jason.should be_respond_to :spec
|
6
|
+
Jason.spec({}).should be_kind_of(Jason::Spec)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "refuses unknown specs" do
|
10
|
+
spec = Jason.spec(unknown: 1)
|
11
|
+
spec.should_not be_fits(:anything)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Type" do
|
15
|
+
it "takes a type spec" do
|
16
|
+
spec = Jason::Spec.new(type: Array)
|
17
|
+
spec.fits?(:x)
|
18
|
+
spec.misses.should_not include("Unknown spec: type")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "Matches by string/symbol" do
|
22
|
+
[ "array", "Array", :array, :Array ].each do |type|
|
23
|
+
spec = Jason::Spec.new(type: type)
|
24
|
+
spec.should be_fits([])
|
25
|
+
end
|
26
|
+
|
27
|
+
[ "hash", "Hash", :hash, :Hash ].each do |type|
|
28
|
+
spec = Jason::Spec.new(type: type)
|
29
|
+
spec.should be_fits({})
|
30
|
+
end
|
31
|
+
|
32
|
+
[ "boolean", "Boolean", :boolean, :Boolean ].each_with_index do |type,i|
|
33
|
+
spec = Jason::Spec.new(type: type)
|
34
|
+
spec.should be_fits(true)
|
35
|
+
spec.should be_fits(false)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "Matches by class" do
|
40
|
+
spec = Jason::Spec.new(type: Jason::Spec)
|
41
|
+
spec.should be_fits(spec)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "Size" do
|
46
|
+
it "takes a size spec" do
|
47
|
+
spec = Jason::Spec.new(size: 1)
|
48
|
+
spec.fits?(:x)
|
49
|
+
spec.misses.should_not include("Unknown spec: size")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "takes a fixnum for size" do
|
53
|
+
spec = Jason.spec(size: 1)
|
54
|
+
spec.should_not be_fits( [ ] )
|
55
|
+
spec.should be_fits( [ 1 ] )
|
56
|
+
end
|
57
|
+
|
58
|
+
it "takes a range for size" do
|
59
|
+
spec = Jason.spec(size: 1..3)
|
60
|
+
spec.should be_fits( [ 1 ] )
|
61
|
+
spec.should be_fits( [ 1, 2 ])
|
62
|
+
spec.should_not be_fits( [ ] )
|
63
|
+
spec.should_not be_fits( [ 1, 2, 3, 4 ] )
|
64
|
+
end
|
65
|
+
|
66
|
+
it "takes an array (as a range) for size" do
|
67
|
+
spec = Jason.spec(size: [ 1, 3, 5 ])
|
68
|
+
spec.should be_fits( [ 1 ] )
|
69
|
+
spec.should_not be_fits( [ 1, 2 ] )
|
70
|
+
spec.should be_fits( [ 1, 2, 3 ] )
|
71
|
+
end
|
72
|
+
|
73
|
+
it "matches hashes by key size" do
|
74
|
+
spec = Jason::Spec.new(size: 1)
|
75
|
+
spec.should_not be_fits({ a: 1, b: 2 })
|
76
|
+
spec.should be_fits({ c: 3 })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "Each" do
|
81
|
+
it "takes an each spec" do
|
82
|
+
spec = Jason.spec(each: [ :id ])
|
83
|
+
spec.fits?(:x)
|
84
|
+
spec.misses.should_not include("Unknown spec: each")
|
85
|
+
end
|
86
|
+
|
87
|
+
it "checks that each item in the array matches" do
|
88
|
+
spec = Jason.spec(each: [ :id ])
|
89
|
+
spec.should be_fits([ { 'id' => 1 }, { 'id' => 2 } ])
|
90
|
+
spec.should_not be_fits([ { 'id' => 1 }, { 'uid' => 2 } ])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "Complex each structures" do
|
95
|
+
it "should match hash structures" do
|
96
|
+
spec = Jason.spec(each: { item: [ :id, :name ], link: [ :href ] })
|
97
|
+
res = spec.fits?([ { "item" => { "id" => 1, "name" => "Jason" }, "link" => { "href" => "file:///" } } ] )
|
98
|
+
|
99
|
+
$stderr.puts spec.misses
|
100
|
+
res.should be_true
|
101
|
+
|
102
|
+
spec.should_not be_fits( [ { "item" => { "nid" => 1, "fame" => "Jason" }, "link" => { "href" => "file:///" } } ] )
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should match deep hash structures"
|
106
|
+
it "should match Jason::Spec"
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "Any" do
|
110
|
+
it "takes an any spec" do
|
111
|
+
spec = Jason.spec(any: [ :id ])
|
112
|
+
spec.fits?(:x)
|
113
|
+
spec.misses.should_not include("Unknown spec: any")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "checks if there is at least one item in the array that match" do
|
117
|
+
spec = Jason.spec(any: [ :id ])
|
118
|
+
spec.should be_fits([ { 'id' => 1 }, { 'id' => 2 } ])
|
119
|
+
spec.should be_fits([ { 'id' => 1 }, { 'uid' => 2 } ])
|
120
|
+
spec.should_not be_fits([ { 'uid' => 1 }, { 'uid' => 2 } ])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "None" do
|
125
|
+
it "takes a none spec" do
|
126
|
+
spec = Jason.spec(none: [ :id ])
|
127
|
+
spec.fits?(:x)
|
128
|
+
spec.misses.should_not include("Unknown spec: none")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "checks if there are no items in the array that match" do
|
132
|
+
spec = Jason.spec(none: [ :id ])
|
133
|
+
spec.should_not be_fits([ { 'id' => 1 }, { 'id' => 2 } ])
|
134
|
+
spec.should_not be_fits([ { 'id' => 1 }, { 'uid' => 2 } ])
|
135
|
+
spec.should be_fits([ { 'uid' => 1 }, { 'uid' => 2 } ])
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "Fields" do
|
140
|
+
it "takes a fields spec" do
|
141
|
+
spec = Jason.spec(fields: [ :id ])
|
142
|
+
spec.fits?(:x)
|
143
|
+
spec.misses.should_not include("Unknown spec: fields")
|
144
|
+
end
|
145
|
+
|
146
|
+
it "checks if all the provided fields are in the hash" do
|
147
|
+
spec = Jason.spec(fields: [ :a, :b, :c ])
|
148
|
+
spec.should_not be_fits({ 'd' => 1 })
|
149
|
+
spec.should_not be_fits({ 'b' => 1 })
|
150
|
+
spec.should be_fits({ 'a' => 1, 'b' => 2, 'c' => 3 })
|
151
|
+
end
|
152
|
+
|
153
|
+
it "checks each" do
|
154
|
+
spec = Jason.spec(fields: { each: [ :a, :b, :c ] })
|
155
|
+
spec.should_not be_fits({ 'd' => 1 })
|
156
|
+
spec.should_not be_fits({ 'b' => 1 })
|
157
|
+
spec.should be_fits({ 'a' => 1, 'b' => 2, 'c' => 3 })
|
158
|
+
end
|
159
|
+
|
160
|
+
it "checks any" do
|
161
|
+
spec = Jason.spec(fields: { any: [ :a, :b, :c ] })
|
162
|
+
spec.should be_fits({ 'b' => 1 })
|
163
|
+
spec.should be_fits({ 'a' => 1, 'c' => 3 })
|
164
|
+
spec.should_not be_fits({ 'd' => 1 })
|
165
|
+
end
|
166
|
+
|
167
|
+
it "checks none" do
|
168
|
+
spec = Jason.spec(fields: { none: [ :a, :b, :c ] })
|
169
|
+
spec.should_not be_fits({ 'b' => 1 })
|
170
|
+
spec.should_not be_fits({ 'a' => 1, 'b' => 2, 'c' => 3 })
|
171
|
+
spec.should be_fits({ 'd' => 1 })
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Jason::Matchers do
|
4
|
+
let(:fake_rspec) do
|
5
|
+
fake = Class.new
|
6
|
+
fake.send(:include, Jason::Matchers)
|
7
|
+
fake.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "provides have_jason in rspec space" do
|
11
|
+
fake_rspec.should be_respond_to(:have_jason)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return instantiate a Jason::Spec" do
|
15
|
+
spec = { type: Array }
|
16
|
+
Jason::HaveJasonMatcher.should_receive(:new).with(spec)
|
17
|
+
fake_rspec.have_jason(spec)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return a Jason::Spec" do
|
21
|
+
fake_rspec.have_jason({}).should be_is_a(Jason::HaveJasonMatcher)
|
22
|
+
end
|
23
|
+
end
|
data/spec/readme_spec.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Examples from readme" do
|
4
|
+
it "should do the most basic example" do
|
5
|
+
%q({"first_name":"Jason","last_name":"Voorhees"}).should have_jason([:first_name,:last_name])
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should do the root example" do
|
9
|
+
%q({"movie":{"title":"Friday the 13th","release_year":"1980"}}).should have_jason(
|
10
|
+
movie: [ :title, :release_year ]
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should do the object example" do
|
15
|
+
class Movie
|
16
|
+
attr_reader :title, :release_year
|
17
|
+
def self.find(x)
|
18
|
+
new
|
19
|
+
end
|
20
|
+
def initialize
|
21
|
+
@title = "Friday the 13th"
|
22
|
+
@release_year = "1980"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
my_movie = Movie.find(1)
|
27
|
+
|
28
|
+
%q({"movie":{"title":"Friday the 13th","release_year":"1980"}}).should have_jason(
|
29
|
+
{ movie: { my_movie => [ :title, :release_year ] } }
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should do the basic Jason.spec example" do
|
34
|
+
%q({"movies":[{"title":"Friday the 13th"},{"title":"Nightmare on Elm Street"}]}).should have_jason(
|
35
|
+
movies: Jason.spec( type: Array, size: 2, each: [ :title ] )
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should do the final example" do
|
40
|
+
json = %q({"user":{
|
41
|
+
"user_name":"jason",
|
42
|
+
"favorite_movies":[
|
43
|
+
{"title":"Friday the 13th","id":1},
|
44
|
+
{"title":"Nightmare on Elm Street","id":2}
|
45
|
+
]
|
46
|
+
},
|
47
|
+
"links":[
|
48
|
+
{ "href":"/users/2", "rel": "self" },
|
49
|
+
{ "href":"/users/2/movies", "rel": "favorite movies"}
|
50
|
+
]
|
51
|
+
})
|
52
|
+
|
53
|
+
json.should have_jason(
|
54
|
+
user: {
|
55
|
+
user_name: "jason",
|
56
|
+
favorite_movies: Jason.spec(type: Array, each: [ :title, :id ])
|
57
|
+
},
|
58
|
+
links: Jason.spec(type: Array, each: [ :href, :rel ])
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'jason_spec'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jason_spec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Hartog C. de Mik
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rufus-json
|
16
|
+
requirement: &9558320 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - =
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.0.6
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *9558320
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &9574040 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.8.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *9574040
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: yard
|
38
|
+
requirement: &9572560 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.7'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *9572560
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rdoc
|
49
|
+
requirement: &9571440 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.12'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *9571440
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: bundler
|
60
|
+
requirement: &9570460 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '1.0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *9570460
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: jeweler
|
71
|
+
requirement: &9569260 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.8.7
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *9569260
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: simplecov
|
82
|
+
requirement: &9568280 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *9568280
|
91
|
+
description: Write specifications for the expected json, without writing json
|
92
|
+
email: hartog@organisedminds.com
|
93
|
+
executables: []
|
94
|
+
extensions: []
|
95
|
+
extra_rdoc_files:
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.md
|
98
|
+
files:
|
99
|
+
- .document
|
100
|
+
- .rspec
|
101
|
+
- Gemfile
|
102
|
+
- Gemfile.lock
|
103
|
+
- LICENSE.txt
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- VERSION
|
107
|
+
- lib/jason/have_jason_matcher.rb
|
108
|
+
- lib/jason/matchers.rb
|
109
|
+
- lib/jason/spec.rb
|
110
|
+
- lib/jason_spec.rb
|
111
|
+
- spec/have_jason_matcher_spec.rb
|
112
|
+
- spec/jason_spec_spec.rb
|
113
|
+
- spec/matchers_spec.rb
|
114
|
+
- spec/readme_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
homepage: http://github.com/coffeeaddict/jason_spec
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: -1377093198486398749
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 1.8.11
|
141
|
+
signing_key:
|
142
|
+
specification_version: 3
|
143
|
+
summary: Spec your JSON
|
144
|
+
test_files: []
|