json_api_conformant 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 92291efde255c5c90b95e15c05e83bf78847cfaf
4
+ data.tar.gz: af194f8d29d1c213ed446298e78530ee65edfa6c
5
+ SHA512:
6
+ metadata.gz: a1ad1aea511b450f83e5b761b5dc2fb55a1f493e73fa9e3fbd9b3bb72875214b6287e49d782462a77a18bb027cf05c485ce26f723597a9519ef82064378d5f49
7
+ data.tar.gz: 50d9dbc0363d0f0619b619fa8bc210ccfb69463c3ce759e0f75e61d739de5bf00f259c630453afc4f7c6af891f89e70daf940f2950b9a90eaa42b827f1b56f02
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in json_api_conformant.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Sebastian Sogamoso
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,80 @@
1
+ # JSON API Conformant
2
+
3
+ When building an API in JSON it is important to follow conventions for the so
4
+ that your system clients know how to send a request for the available resources
5
+ to be fetched or modified and how your system will respond to those requests.
6
+
7
+ JSON API Conformant provides a narrow interface for validating JSON objects
8
+ against a [JSON API](http://jsonapi.org/) conforming
9
+ [JSON API schema](http://jsonapi.org/schema) and provides a custom RSpec
10
+ matcher for use in your tests.
11
+
12
+ **Important:** JSON API is a work in progress. The base schema is not a perfect
13
+ document. The fact that a JSON document validates against this schema, it does
14
+ not necessarily mean it is a valid JSON API document. The schema is provided by
15
+ JSON API for a base level sanity check.
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'json_api_conformant'
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install json_api_conformant
32
+
33
+ ## Usage
34
+
35
+ Validate if your JSON object is JSON API conformant.
36
+ ```ruby
37
+ valid_schema = {"posts" => [{"id" => "1"}]}
38
+ invalid_schema = {"comments" => "Nice gem!"}
39
+
40
+ JSON::API::Conformant.valid?(valid_schema) # => true
41
+ JSON::API::Conformant.valid?(invalid_schema) # => false
42
+ ```
43
+
44
+ Get errors when your JSON object is JSON API not conformant.
45
+ ```ruby
46
+ valid_schema = {"posts" => [{"id" => "1"}]}
47
+ invalid_schema = {"comments" => "Nice gem!"}
48
+
49
+ JSON::API::Conformant.validate(valid_schema) # => []
50
+ JSON::API::Conformant.validate(invalid_schema) # => ["The property
51
+ '#/comments' of type String did not match the"]
52
+ ```
53
+
54
+ JSON API Conformant wraps [json-schema](https://github.com/hoxworth/json-schema,
55
+ so other options that validator accepts will work here too.
56
+
57
+ ### RSpec Matcher
58
+
59
+ It is pretty straighword to use.
60
+ ```ruby
61
+ it "..." do
62
+ data = {"posts" => [{"id" => "1"}]}
63
+
64
+ expect(data).to be_json_api_conformant
65
+ end
66
+ ```
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it ( https://github.com/[my-github-username]/json_api_conformant/fork )
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Run the test suite (`rake`)
73
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 5. Push to the branch (`git push origin my-new-feature`)
75
+ 6. Create a new Pull Request
76
+
77
+ ## License
78
+
79
+ See [LICENSE](https://github.com/sebasoga/json_api_conformant/blob/master/LICENSE.txt)
80
+ for details.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :test => :spec
7
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'json_api_conformant/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "json_api_conformant"
8
+ spec.version = JSON::API::Conformant::VERSION
9
+ spec.authors = ["Sebastian Sogamoso"]
10
+ spec.email = ["sebasoga@gmail.com"]
11
+ spec.summary = %q{Ruby JSON API validator.}
12
+ spec.description = %q{Interface for validating JSON objects against a JSON API schema.}
13
+ spec.homepage = "https://github.com/sebasoga/json_api_conformant"
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.6"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_dependency "rspec", "~> 3.0"
24
+ spec.add_dependency "json-schema", "~> 2.2"
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'json-schema'
2
+
3
+ module JSON
4
+ module API
5
+ class Conformant
6
+ SCHEMA_VERSION = 'draft'
7
+
8
+ class << self
9
+ def valid?(data, options={})
10
+ validator.validate(schema, data, options)
11
+ end
12
+
13
+ def validate(data, options={})
14
+ validator.fully_validate(schema, data, options)
15
+ end
16
+
17
+ private
18
+
19
+ def validator
20
+ JSON::Validator
21
+ end
22
+
23
+ def schema
24
+ File.join(Pathname.new(File.dirname(__FILE__)).parent.parent,
25
+ 'schemas',
26
+ "#{SCHEMA_VERSION}.json"
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require 'rspec/expectations'
2
+ require 'json_api_conformant/conformant'
3
+
4
+ RSpec::Matchers.define :be_json_api_conformant do
5
+ match do |data|
6
+ json_api_conformant? data
7
+ end
8
+
9
+ failure_message do |data|
10
+ errors = get_errors_in data
11
+ message_for errors
12
+ end
13
+
14
+ failure_message_when_negated do |data|
15
+ "Expected data not to be JSON API conformant"
16
+ end
17
+
18
+ private
19
+
20
+ def json_api_conformant?(data)
21
+ JSON::API::Conformant.valid?(data)
22
+ end
23
+
24
+ def get_errors_in(data)
25
+ JSON::API::Conformant.validate(data)
26
+ end
27
+
28
+ def message_for(errors)
29
+ error_message = ['Expected data to be JSON API conformant:'] + errors
30
+ error_message.join("\n* ")
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ module JSON
2
+ module API
3
+ class Conformant
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ require "json_api_conformant/version"
2
+ require "json_api_conformant/conformant"
3
+ require "json_api_conformant/matchers/rspec"
@@ -0,0 +1,40 @@
1
+ {
2
+ "id": "http://jsonapi.org/schema#",
3
+ "$schema": "http://json-schema.org/draft-04/schema#",
4
+ "title": "JSON API Schema",
5
+ "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org",
6
+ "type": "object",
7
+ "resources":{
8
+ "type": "array",
9
+ "items": {
10
+ "type": "object",
11
+ "properties": {
12
+ "id": { "type":["string"] },
13
+ "href": { "type":"string" },
14
+ "links": { "type": "object" }
15
+ },
16
+ "required": ["id"]
17
+ }
18
+ },
19
+ "patternProperties": {
20
+ "^(?!href$)(?!links$)(?!id$)(?!meta)(?!linked)": {
21
+ "$ref":"#/resources"
22
+ }
23
+ },
24
+ "properties": {
25
+ "meta": {
26
+ "type": "object"
27
+ },
28
+ "links":{
29
+ "type": "object"
30
+ },
31
+ "linked": {
32
+ "type": "object",
33
+ "patternProperties": {
34
+ ".*": {
35
+ "$ref":"#/resources"
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "links": {
3
+ "posts.author": {
4
+ "link": "http://example.com/people/{posts.author}"
5
+ }
6
+ },
7
+ "posts": [{
8
+ "title": "Rails is Omakase",
9
+ "links": {
10
+ "comments": [ "1", "2", "3" ]
11
+ }}, {
12
+ "id": "3",
13
+ "title": "Dependency Injection is Not a Virtue",
14
+ "links": {
15
+ "author": "9",
16
+ "comments": "6"
17
+ }
18
+ }],
19
+ "linked": {
20
+ "people": [{
21
+ "name": "@d2h"
22
+ }]
23
+ }
24
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "links": {
3
+ "posts.author": {
4
+ "href": "http://example.com/people/{posts.author}",
5
+ "type": "people"
6
+ },
7
+ "posts.comments": {
8
+ "href": "http://example.com/comments/{posts.comments}",
9
+ "type": "comments"
10
+ }
11
+ },
12
+ "posts": [{
13
+ "id": "1",
14
+ "title": "Rails is Omakase",
15
+ "links": {
16
+ "author": "9",
17
+ "comments": [ "1", "2", "3" ]
18
+ }}, {
19
+ "id": "2",
20
+ "title": "The Parley Letter",
21
+ "links": {
22
+ "author": "9",
23
+ "comments": [ "4", "5" ]
24
+ }}, {
25
+ "id": "3",
26
+ "title": "Dependency Injection is Not a Virtue",
27
+ "links": {
28
+ "author": "9",
29
+ "comments": [ "6" ]
30
+ }
31
+ }],
32
+ "linked": {
33
+ "people": [{
34
+ "id": "9",
35
+ "name": "@d2h"
36
+ }],
37
+ "comments": [{
38
+ "id": "1",
39
+ "body": "Mmmmmakase"
40
+ }, {
41
+ "id": "2",
42
+ "body": "I prefer unagi"
43
+ }, {
44
+ "id": "3",
45
+ "body": "What's Omakase?"
46
+ }, {
47
+ "id": "4",
48
+ "body": "Parley is a discussion, especially one between enemies"
49
+ }, {
50
+ "id": "5",
51
+ "body": "The parsley letter"
52
+ }, {
53
+ "id": "6",
54
+ "body": "Dependency Injection is Not a Vice"
55
+ }]
56
+ }
57
+ }
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe JSON::API::Conformant do
4
+
5
+ let(:valid_data) { parse_fixture('valid') }
6
+ let(:invalid_data) { parse_fixture('invalid') }
7
+
8
+ subject { JSON::API::Conformant }
9
+
10
+ describe ".validate" do
11
+ context "when data is valid" do
12
+ it "is true" do
13
+ expect(subject.valid? valid_data).to be true
14
+ end
15
+ end
16
+
17
+ context "when data is invalid" do
18
+ it "is false" do
19
+ expect(subject.valid? invalid_data).to be false
20
+ end
21
+ end
22
+ end
23
+
24
+ describe ".validate" do
25
+ context "when data is valid" do
26
+ it "returns an empty array" do
27
+ expect(subject.validate valid_data).to eq []
28
+ end
29
+ end
30
+
31
+ context "when data is invalid" do
32
+ it "returns an array with the errors" do
33
+ errors = [
34
+ "The property '#/posts/0' did not contain a required property of 'id' in schema http://jsonapi.org/schema#",
35
+ "The property '#/linked/people/0' did not contain a required property of 'id' in schema http://jsonapi.org/schema#"]
36
+ expect(subject.validate invalid_data).to eq errors
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "be_json_api_conformant matcher" do
4
+
5
+ context "when the JSON object is valid" do
6
+ it "is JSON API conformant" do
7
+ json = parse_fixture('valid')
8
+ expect(json).to be_json_api_conformant
9
+ end
10
+
11
+ it "returns the correct message when the test fails" do
12
+ json = parse_fixture('valid')
13
+ expected_message = 'Expected data not to be JSON API conformant'
14
+ begin
15
+ expect(json).not_to be_json_api_conformant
16
+ rescue RSpec::Expectations::ExpectationNotMetError => e
17
+ expect(e.to_s).to eq expected_message
18
+ end
19
+ end
20
+ end
21
+
22
+ context "when then JSON object is invalid" do
23
+ it "is not JSON API conformant" do
24
+ json = parse_fixture('invalid')
25
+ expect(json).not_to be_json_api_conformant
26
+ end
27
+
28
+ it "returns the correct message when the test fails" do
29
+ json = parse_fixture('invalid')
30
+ expected_message = ["Expected data to be JSON API conformant:",
31
+ "The property '#/posts/0' did not contain a required property of 'id' in schema http://jsonapi.org/schema#",
32
+ "The property '#/linked/people/0' did not contain a required property of 'id' in schema http://jsonapi.org/schema#"]
33
+ begin
34
+ expect(json).to be_json_api_conformant
35
+ rescue RSpec::Expectations::ExpectationNotMetError => e
36
+ expect(e.to_s).to eq expected_message.join("\n* ")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ ENV["env"] ||= "test"
2
+
3
+ require 'json_api_conformant'
4
+
5
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |file| require file }
6
+
7
+ RSpec.configure do |config|
8
+ config.include RSpecHelper
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'json'
2
+
3
+ module RSpecHelper
4
+ def parse_fixture(filename)
5
+ filepath = File.join(Pathname.new(File.dirname(__FILE__)).parent, 'fixtures', "#{filename}.json")
6
+ file = File.read(filepath)
7
+ JSON.parse(file)
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json_api_conformant
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Sogamoso
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json-schema
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.2'
69
+ description: Interface for validating JSON objects against a JSON API schema.
70
+ email:
71
+ - sebasoga@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - json_api_conformant.gemspec
82
+ - lib/json_api_conformant.rb
83
+ - lib/json_api_conformant/conformant.rb
84
+ - lib/json_api_conformant/matchers/rspec.rb
85
+ - lib/json_api_conformant/version.rb
86
+ - schemas/draft.json
87
+ - spec/fixtures/invalid.json
88
+ - spec/fixtures/valid.json
89
+ - spec/json_api_conformant/conformant_spec.rb
90
+ - spec/json_api_conformant/matchers/rspec_spec.rb
91
+ - spec/spec_helper.rb
92
+ - spec/support/json_parser.rb
93
+ homepage: https://github.com/sebasoga/json_api_conformant
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.2.2
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Ruby JSON API validator.
117
+ test_files:
118
+ - spec/fixtures/invalid.json
119
+ - spec/fixtures/valid.json
120
+ - spec/json_api_conformant/conformant_spec.rb
121
+ - spec/json_api_conformant/matchers/rspec_spec.rb
122
+ - spec/spec_helper.rb
123
+ - spec/support/json_parser.rb
124
+ has_rdoc: