match_json 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: 6700101a6f7589f99d3ac22a5e22392cca6bef8b
4
+ data.tar.gz: e608c2d863253955e52214efad1bc0ff984c0352
5
+ SHA512:
6
+ metadata.gz: 59005a3e78998816e9fac442cf60296e5c9a7bb5e111ac787eb78129c8f22465e7b221aef64617014f8059102fd5b2b7346c4216fdf3a13a5b7c9f53c70f5341
7
+ data.tar.gz: 1cc241114b0cc43d5cec22b479b4b5823920d07e17cda729ea04688ca2121eefb8810df813146fcd2622b997d58c081b1ec4c2116a481e400bc7fcaf3701f961
data/.gitignore ADDED
@@ -0,0 +1,14 @@
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
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in match_json.gemspec
4
+ gemspec
5
+
6
+ gem 'rspec', git: 'https://github.com/rspec/rspec.git'
7
+ gem 'rspec-core', git: 'https://github.com/rspec/rspec-core.git'
8
+ gem 'rspec-mocks', git: 'https://github.com/rspec/rspec-mocks.git'
9
+ gem 'rspec-expectations', git: 'https://github.com/rspec/rspec-expectations.git'
10
+ gem 'rspec-support', git: 'https://github.com/rspec/rspec-support.git'
11
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Pavel Gabriel and White Payments Technologies FZE
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,94 @@
1
+ # MatchJson
2
+
3
+ Easily test your JSON in RSpec and Cucumber.
4
+
5
+ This matcher can't be the only tool when you test your JSON. We also
6
+ recommend to use [json-schema](https://github.com/ruby-json-schema/json-schema)
7
+ as a perfect companion to MatchJson.
8
+
9
+ ## Usage: RSpec
10
+
11
+ In RSpec we add this matcher: ```include_json```
12
+
13
+ So you can use it as follows:
14
+
15
+ ```ruby
16
+ it 'returns charge' do
17
+ get '/charges/#{charge.id}'
18
+
19
+ expect(response).to include_json(<<-JSON)
20
+ {
21
+ "id": "{uuid}",
22
+ "amount": 100,
23
+ "currency": "USD",
24
+ "created_at": "{date_time_iso8601}"
25
+ }
26
+ JSON
27
+ end
28
+
29
+ it 'returns list of charges' do
30
+ get '/charges'
31
+
32
+ expect(response).to include_json(<<-JSON)
33
+ {
34
+ "charges": [
35
+ {
36
+ "id": "{uuid}",
37
+ "amount": 100,
38
+ "currency": "USD",
39
+ "created_at": "{date_time_iso8601}"
40
+ }
41
+ ]
42
+ }
43
+ JSON
44
+ end
45
+ ```
46
+
47
+ As you can see for cases when you do not know the value of some properties like
48
+ ```id``` or ```created_at``` or even ```email``` you can use 'pattern' instead.
49
+
50
+ You can use the following predefined patterns:
51
+
52
+ * date_time_iso8601
53
+ * date
54
+ * uuid
55
+ * email
56
+ * string
57
+
58
+ You also can add your own pattern in this way:
59
+
60
+ ```ruby
61
+ MatchJson::Matchers::IncludeJson::PATTERNS['id'] = /\A\d{6}\z/
62
+ ```
63
+
64
+ and then use it in your spec:
65
+
66
+ ```ruby
67
+ it 'uses patten to check value' do
68
+ expect(%Q({"one": "123456"})).to include_json(%Q({"one": "{id}"}))
69
+ end
70
+ ```
71
+
72
+ ## Installation
73
+
74
+ Add this line to your application's Gemfile:
75
+
76
+ ```ruby
77
+ gem 'match_json'
78
+ ```
79
+
80
+ And then execute:
81
+
82
+ $ bundle
83
+
84
+ Or install it yourself as:
85
+
86
+ $ gem install match_json
87
+
88
+ ## Contributing
89
+
90
+ 1. Fork it ( https://github.com/[my-github-username]/match_json/fork )
91
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
92
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
93
+ 4. Push to the branch (`git push origin my-new-feature`)
94
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,98 @@
1
+
2
+ module MatchJson
3
+ module Matchers
4
+ class IncludeJson
5
+ PATTERNS = {
6
+ 'date_time_iso8601' => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/,
7
+ 'date' => /^\d{4}-\d{2}-\d{2}/,
8
+ 'uuid' => /\h{32}/,
9
+ 'email' => /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,6}\z/i,
10
+ 'string' => /\A.+\z/i
11
+ }
12
+
13
+ def initialize(expected_json)
14
+ @expected_json = JSON.parse(expected_json)
15
+ end
16
+
17
+ def matches?(actual_json)
18
+ @actual_json = actual_json.respond_to?(:body) ? JSON.parse(actual_json.body) : JSON.parse(actual_json)
19
+
20
+ match = catch(:match) { json_included?(@actual_json, @expected_json) }
21
+ end
22
+
23
+ def failure_message
24
+ @failure_message
25
+ end
26
+
27
+ def failure_message_when_negated
28
+ "does not support negation"
29
+ end
30
+
31
+ private
32
+
33
+ def json_included?(actual, expected)
34
+ equal_value?(actual, expected)
35
+ end
36
+
37
+ def hash_included?(actual, expected, nested, raise_error)
38
+ expected.each do |key, value|
39
+ if (!equal_value?(actual[key], value, "#{nested} > #{key}", raise_error))
40
+ @failure_message = %Q("#{key}"=>#{value} was not found in\n #{actual})
41
+
42
+ if raise_error
43
+ throw(:match, false)
44
+ else
45
+ return false
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def array_included?(actual, expected, nested, raise_error)
52
+ expected.each do |value|
53
+ if (!actual.any? { |actual_value| equal_value?(actual_value, value, nested, false) })
54
+ @failure_message = %Q("#{value}" was not found in\n )
55
+ @failure_message << %Q("#{nested}"=>) if !nested.empty?
56
+ @failure_message << "#{actual}"
57
+
58
+ if raise_error
59
+ throw(:match, false)
60
+ else
61
+ return false
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def equal_value?(actual, expected, nested = '', raise_error = true)
68
+ case expected
69
+ when Array then array_included?(actual, expected, nested, raise_error)
70
+ when Hash then hash_included?(actual, expected, nested, raise_error)
71
+ when String then compare_with_pattern(expected, actual)
72
+ else
73
+ actual == expected
74
+ end
75
+ end
76
+
77
+ def compare_with_pattern(value, actual)
78
+ case
79
+ when regexp?(value)
80
+ reg_exp = value.match(/{re:(.*)}/)[1]
81
+ actual =~ Regexp.new(reg_exp)
82
+ when pattern?(value)
83
+ actual =~ PATTERNS["#{value.gsub('{', '').gsub('}', '')}"]
84
+ else
85
+ value == actual
86
+ end
87
+ end
88
+
89
+ def pattern?(str)
90
+ !!(str =~ /\A\{\w+\}\z/)
91
+ end
92
+
93
+ def regexp?(str)
94
+ !!(str =~ /\A\{re:.+\}\z/)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,13 @@
1
+ require 'match_json/matchers/include_json'
2
+
3
+ module MatchJson
4
+ module Matchers
5
+ def include_json(json)
6
+ MatchJson::Matchers::IncludeJson.new(json)
7
+ end
8
+ end
9
+ end
10
+
11
+ RSpec.configure do |config|
12
+ config.include MatchJson::Matchers
13
+ end
@@ -0,0 +1,3 @@
1
+ module MatchJson
2
+ VERSION = "0.0.1"
3
+ end
data/lib/match_json.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "json"
2
+ require "match_json/version"
3
+ require "match_json/matchers"
4
+
5
+ module MatchJson
6
+ # Your code goes here...
7
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'match_json/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "match_json"
8
+ spec.version = MatchJson::VERSION
9
+ spec.authors = ["Pavel Gabriel", "White Payments"]
10
+ spec.email = ["alovak@gmail.com"]
11
+ spec.summary = %q{RSpec matcher for JSON documents}
12
+ spec.description = %q{Easily test your JSON in RSpec and Cucumber.}
13
+ spec.homepage = "https://github.com/WhitePayments/match_json"
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 "rake", "~> 10.0"
23
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe "include_json" do
4
+ it 'passes when object is partially included' do
5
+ expect(%Q({ "one": 1, "two": 2 })).to include_json(%Q({ "one": 1 }))
6
+ end
7
+
8
+ it "fails when expected object is not included" do
9
+ expect {
10
+ expect(%Q({ "one": 1 })).to include_json(%Q({ "one": 2 }))
11
+ }.to fail_with(%Q("one"=>2 was not found in\n {"one"=>1}))
12
+ end
13
+
14
+ it 'passes when array is partially included' do
15
+ expect(%Q([1, 2, 3])).to include_json(%Q([3, 2]))
16
+ expect(%Q([1, 2, 3])).to include_json(%Q([1, 2, 3]))
17
+ end
18
+
19
+ it 'fails when there is no such array' do
20
+ expect {
21
+ expect(%Q([1, 2, 3])).to include_json(%Q([3, 5]))
22
+ }.to fail_with(%Q("5" was not found in\n [1, 2, 3]))
23
+ end
24
+
25
+ context 'when object contains array' do
26
+ it 'passes when array included' do
27
+ expect(%Q({ "array" : [1, 2, 3] })).to include_json(%Q({ "array" : [3, 2, 1] }))
28
+ end
29
+
30
+ it 'fails with there is no such array' do
31
+ expect {
32
+ expect(%Q({ "array" : [1, 2, 3] })).to include_json(%Q({ "array" : [5, 1] }))
33
+ }.to fail_with(%Q("5" was not found in\n " > array"=>[1, 2, 3]))
34
+ end
35
+ end
36
+
37
+ context 'when array contains object' do
38
+ it 'passes when object included in array' do
39
+ expect(%Q([ { "one": 1 }, { "two": 2 }])).to include_json(%Q([ { "one": 1 }]))
40
+ end
41
+
42
+ it 'fails when there is no such object in array' do
43
+ expect {
44
+ expect(%Q([ { "one": 1 }, { "two": 2 }])).to include_json(%Q([ { "one": 2 }]))
45
+ }.to fail_with(%Q(\"{"one"=>2}\" was not found in\n [{"one"=>1}, {"two"=>2}]))
46
+ end
47
+ end
48
+
49
+ context 'in multilevel structure' do
50
+ it 'fails if object was not found' do
51
+ expect {
52
+ expect(%Q([ { "one": { "array": [1,2,3] } } ])).to include_json(%Q([ { "one": { "array": [1,2,3,4] } } ]))
53
+ }.to fail_with(%Q("{"one"=>{"array"=>[1, 2, 3, 4]}}" was not found in\n [{"one"=>{"array"=>[1, 2, 3]}}]))
54
+ end
55
+ end
56
+
57
+ context 'with pattern' do
58
+ it 'passes when value matches pattern' do
59
+ expect(%Q({"one": "test@exmaple.com"})).to include_json(%Q({"one": "{email}"}))
60
+ expect(%Q({"one": "2020-12-22"})).to include_json(%Q({"one": "{date}"}))
61
+ end
62
+ end
63
+
64
+ context 'with custom pattern' do
65
+ before do
66
+ MatchJson::Matchers::IncludeJson::PATTERNS['id'] = /\A\d{6}\z/
67
+ end
68
+
69
+ after do
70
+ MatchJson::Matchers::IncludeJson::PATTERNS.delete('id')
71
+ end
72
+
73
+ it 'uses patten to check value' do
74
+ expect(%Q({"one": "123456"})).to include_json(%Q({"one": "{id}"}))
75
+
76
+ expect {
77
+ expect(%Q({"one": "abcdef"})).to include_json(%Q({"one": "{id}"}))
78
+ }.to fail_with(%Q("one"=>{id} was not found in\n {"one"=>"abcdef"}))
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,10 @@
1
+ require 'match_json'
2
+ require 'byebug'
3
+
4
+ Dir['./spec/support/**/*'].each do |f|
5
+ require f.sub(%r{\./spec/}, '')
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.include RSpec::Matchers::FailMatchers
10
+ end
@@ -0,0 +1,41 @@
1
+ module RSpec
2
+ module Matchers
3
+ # Matchers for testing RSpec matchers. Include them with:
4
+ #
5
+ # require 'rspec/matchers/fail_matchers'
6
+ # RSpec.configure do |config|
7
+ # config.include RSpec::Matchers::FailMatchers
8
+ # end
9
+ #
10
+ module FailMatchers
11
+ # Matches if an expectation fails
12
+ #
13
+ # @example
14
+ # expect { some_expectation }.to fail
15
+ def fail
16
+ raise_error(RSpec::Expectations::ExpectationNotMetError)
17
+ end
18
+
19
+ # Matches if an expectation fails with the provided message
20
+ #
21
+ # @example
22
+ # expect { some_expectation }.to fail_with("some failure message")
23
+ # expect { some_expectation }.to fail_with(/some failure message/)
24
+ def fail_with(message)
25
+ raise_error(RSpec::Expectations::ExpectationNotMetError, message)
26
+ end
27
+
28
+ # Matches if an expectation fails including the provided message
29
+ #
30
+ # @example
31
+ # expect { some_expectation }.to fail_including("portion of some failure message")
32
+ def fail_including(snippet)
33
+ raise_error(
34
+ RSpec::Expectations::ExpectationNotMetError,
35
+ a_string_including(snippet)
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: match_json
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Pavel Gabriel
8
+ - White Payments
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-02-27 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: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
42
+ description: Easily test your JSON in RSpec and Cucumber.
43
+ email:
44
+ - alovak@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - lib/match_json.rb
55
+ - lib/match_json/matchers.rb
56
+ - lib/match_json/matchers/include_json.rb
57
+ - lib/match_json/version.rb
58
+ - match_json.gemspec
59
+ - spec/match_json/matchers_spec.rb
60
+ - spec/spec_helper.rb
61
+ - spec/support/fail_matchers.rb
62
+ homepage: https://github.com/WhitePayments/match_json
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.4.5
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: RSpec matcher for JSON documents
86
+ test_files:
87
+ - spec/match_json/matchers_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/support/fail_matchers.rb