rspec-json_api 1.3.1 → 1.4.0

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.
@@ -1,36 +1,36 @@
1
- # frozen_string_literal: true
2
-
3
- # Extension methods for hash class
4
- class Hash
5
- def deep_keys
6
- each_with_object([]) do |(k, v), keys|
7
- keys << k
8
- keys << v.deep_keys if v.respond_to?(:keys)
9
- end
10
- end
11
-
12
- def deep_key_paths
13
- stack = map { |k, v| [[k], v] }
14
- key_map = []
15
-
16
- until stack.empty?
17
- key, value = stack.pop
18
-
19
- key_map << key unless value.is_a? Hash
20
-
21
- next unless value.is_a? Hash
22
-
23
- value.map do |k, v|
24
- stack.push [key.dup << k, v]
25
- end
26
- end
27
-
28
- key_map.reverse
29
- end
30
-
31
- def sanitize!(keys)
32
- keep_if do |k, _v|
33
- keys.include?(k)
34
- end
35
- end
36
- end
1
+ # frozen_string_literal: true
2
+
3
+ # Extension methods for hash class
4
+ class Hash
5
+ def deep_keys
6
+ each_with_object([]) do |(k, v), keys|
7
+ keys << k
8
+ keys << v.deep_keys if v.respond_to?(:keys)
9
+ end
10
+ end
11
+
12
+ def deep_key_paths
13
+ stack = map { |k, v| [[k], v] }
14
+ key_map = []
15
+
16
+ until stack.empty?
17
+ key, value = stack.pop
18
+
19
+ key_map << key unless value.is_a? Hash
20
+
21
+ next unless value.is_a? Hash
22
+
23
+ value.map do |k, v|
24
+ stack.push [key.dup << k, v]
25
+ end
26
+ end
27
+
28
+ key_map.reverse
29
+ end
30
+
31
+ def sanitize!(keys)
32
+ keep_if do |k, _v|
33
+ keys.include?(k)
34
+ end
35
+ end
36
+ end
@@ -1,23 +1,23 @@
1
- # frozen_string_literal: true
2
-
3
- module Rspec
4
- module JsonApi
5
- module Generators
6
- class TypeGenerator < Rails::Generators::NamedBase
7
- source_root File.expand_path("templates", __dir__)
8
-
9
- def copy_interface_file
10
- create_file "spec/rspec/json_api/types/#{file_name}.rb", <<~FILE
11
- module RSpec
12
- module JsonApi
13
- module Types
14
- #{file_name.upcase} = //
15
- end
16
- end
17
- end
18
- FILE
19
- end
20
- end
21
- end
22
- end
23
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module JsonApi
5
+ module Generators
6
+ class TypeGenerator < Rails::Generators::NamedBase
7
+ source_root File.expand_path("templates", __dir__)
8
+
9
+ def copy_type_file
10
+ create_file "spec/rspec/json_api/types/#{file_name}.rb", <<~FILE
11
+ module RSpec
12
+ module JsonApi
13
+ module Types
14
+ #{file_name.upcase} = //
15
+ end
16
+ end
17
+ end
18
+ FILE
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,114 +1,114 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module JsonApi
5
- module CompareHash
6
- extend self
7
-
8
- SUPPORTED_OPTIONS = %i[allow_blank type value min max inclusion regex lambda].freeze
9
-
10
- def compare(actual, expected)
11
- return false if actual.blank? && expected.present?
12
-
13
- keys = expected.deep_key_paths | actual.deep_key_paths
14
-
15
- compare_key_paths_and_values(keys, actual, expected)
16
- end
17
-
18
- def compare_key_paths_and_values(keys, actual, expected)
19
- keys.all? do |key_path|
20
- actual_value = actual.dig(*key_path)
21
- expected_value = expected.dig(*key_path)
22
-
23
- compare_values(actual_value, expected_value)
24
- end
25
- end
26
-
27
- def compare_values(actual_value, expected_value)
28
- case expected_value
29
- when Class
30
- compare_class(actual_value, expected_value)
31
- when Regexp
32
- compare_regexp(actual_value, expected_value)
33
- when Proc
34
- compare_proc(actual_value, expected_value)
35
- when Array
36
- compare_array(actual_value, expected_value)
37
- else
38
- compare_simple_value(actual_value, expected_value)
39
- end
40
- end
41
-
42
- def compare_class(actual_value, expected_value)
43
- actual_value.instance_of?(expected_value)
44
- end
45
-
46
- def compare_regexp(actual_value, expected_value)
47
- actual_value.to_s =~ expected_value
48
- end
49
-
50
- def compare_proc(actual_value, expected_value)
51
- payload = expected_value.call
52
- payload.sanitize!(SUPPORTED_OPTIONS)
53
- payload = payload.sort_by { |k, _v| k == :allow_blank ? 0 : 1 }.to_h
54
-
55
- payload.all? do |condition_key, condition_value|
56
- case condition_key
57
- when :allow_blank
58
- return true if actual_value.blank? && condition_value
59
-
60
- true
61
- when :type
62
- compare_class(actual_value, condition_value)
63
- when :value
64
- compare_simple_value(actual_value, condition_value)
65
- when :inclusion
66
- condition_value.include?(actual_value)
67
- when :min
68
- return false if !condition_value.is_a?(Numeric) || !actual_value.is_a?(Numeric)
69
-
70
- actual_value >= condition_value
71
- when :max
72
- return false if !condition_value.is_a?(Numeric) || !actual_value.is_a?(Numeric)
73
-
74
- actual_value <= condition_value
75
- when :regex
76
- compare_regexp(actual_value, condition_value)
77
- when :lambda
78
- condition_value.call(actual_value)
79
- end
80
- end
81
- end
82
-
83
- def compare_array(actual_value, expected_value)
84
- if simple_type?(expected_value)
85
- type = expected_value[0]
86
-
87
- actual_value.all? { |elem| compare_class(elem, type) }
88
- elsif interface?(expected_value)
89
- interface = expected_value[0]
90
-
91
- actual_value.all? { |elem| compare(elem, interface) }
92
- else
93
- return false if actual_value&.size != expected_value&.size
94
-
95
- expected_value.each_with_index.all? do |elem, index|
96
- elem.is_a?(Hash) ? compare(actual_value[index], elem) : compare_simple_value(actual_value[index], elem)
97
- end
98
- end
99
- end
100
-
101
- def compare_simple_value(actual_value, expected_value)
102
- actual_value == expected_value
103
- end
104
-
105
- def simple_type?(expected_value)
106
- expected_value.size == 1 && expected_value[0].instance_of?(Class)
107
- end
108
-
109
- def interface?(expected_value)
110
- expected_value.size == 1 && expected_value[0].is_a?(Hash)
111
- end
112
- end
113
- end
114
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module JsonApi
5
+ module CompareHash
6
+ module_function
7
+
8
+ SUPPORTED_OPTIONS = %i[allow_blank type value min max inclusion regex lambda].freeze
9
+
10
+ def compare(actual, expected)
11
+ return false if actual.blank? && expected.present?
12
+
13
+ keys = expected.deep_key_paths | actual.deep_key_paths
14
+
15
+ compare_key_paths_and_values(keys, actual, expected)
16
+ end
17
+
18
+ def compare_key_paths_and_values(keys, actual, expected)
19
+ keys.all? do |key_path|
20
+ actual_value = actual.dig(*key_path)
21
+ expected_value = expected.dig(*key_path)
22
+
23
+ compare_values(actual_value, expected_value)
24
+ end
25
+ end
26
+
27
+ def compare_values(actual_value, expected_value)
28
+ case expected_value
29
+ when Class
30
+ compare_class(actual_value, expected_value)
31
+ when Regexp
32
+ compare_regexp(actual_value, expected_value)
33
+ when Proc
34
+ compare_proc(actual_value, expected_value)
35
+ when Array
36
+ compare_array(actual_value, expected_value)
37
+ else
38
+ compare_simple_value(actual_value, expected_value)
39
+ end
40
+ end
41
+
42
+ def compare_class(actual_value, expected_value)
43
+ actual_value.instance_of?(expected_value)
44
+ end
45
+
46
+ def compare_regexp(actual_value, expected_value)
47
+ actual_value.to_s =~ expected_value
48
+ end
49
+
50
+ def compare_proc(actual_value, expected_value)
51
+ payload = expected_value.call
52
+ payload.sanitize!(SUPPORTED_OPTIONS)
53
+ payload = payload.sort_by { |k, _v| k == :allow_blank ? 0 : 1 }.to_h
54
+
55
+ payload.all? do |condition_key, condition_value|
56
+ case condition_key
57
+ when :allow_blank
58
+ return true if actual_value.blank? && condition_value
59
+
60
+ true
61
+ when :type
62
+ compare_class(actual_value, condition_value)
63
+ when :value
64
+ compare_simple_value(actual_value, condition_value)
65
+ when :inclusion
66
+ condition_value.include?(actual_value)
67
+ when :min
68
+ return false if !condition_value.is_a?(Numeric) || !actual_value.is_a?(Numeric)
69
+
70
+ actual_value >= condition_value
71
+ when :max
72
+ return false if !condition_value.is_a?(Numeric) || !actual_value.is_a?(Numeric)
73
+
74
+ actual_value <= condition_value
75
+ when :regex
76
+ compare_regexp(actual_value, condition_value)
77
+ when :lambda
78
+ condition_value.call(actual_value)
79
+ end
80
+ end
81
+ end
82
+
83
+ def compare_array(actual_value, expected_value)
84
+ if simple_type?(expected_value)
85
+ type = expected_value[0]
86
+
87
+ actual_value.all? { |elem| compare_class(elem, type) }
88
+ elsif interface?(expected_value)
89
+ interface = expected_value[0]
90
+
91
+ actual_value.all? { |elem| compare(elem, interface) }
92
+ else
93
+ return false if actual_value&.size != expected_value&.size
94
+
95
+ expected_value.each_with_index.all? do |elem, index|
96
+ elem.is_a?(Hash) ? compare(actual_value[index], elem) : compare_simple_value(actual_value[index], elem)
97
+ end
98
+ end
99
+ end
100
+
101
+ def compare_simple_value(actual_value, expected_value)
102
+ actual_value == expected_value
103
+ end
104
+
105
+ def simple_type?(expected_value)
106
+ expected_value.size == 1 && expected_value[0].instance_of?(Class)
107
+ end
108
+
109
+ def interface?(expected_value)
110
+ expected_value.size == 1 && expected_value[0].is_a?(Hash)
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,7 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module JsonApi
5
- VERSION = "1.3.1"
6
- end
7
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module JsonApi
5
+ VERSION = "1.4.0"
6
+ end
7
+ end
@@ -1,25 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
- # Load 3th party libraries
4
- require "json"
5
- require "diffy"
6
- require "active_support/core_ext/object/blank"
7
-
8
- # Load the json_api parts
9
- require "rspec/json_api/version"
10
- require "rspec/json_api/compare_hash"
11
- require "rspec/json_api/compare_array"
12
-
13
- # Load extentions
14
- require "extentions/hash"
15
- require "extentions/array"
16
-
17
- # Load matchers
18
- require "rspec/json_api/matchers"
19
- require "rspec/json_api/matchers/match_json_schema"
20
- require "rspec/json_api/matchers/have_no_content"
21
-
22
- # Load defined types
23
- require "rspec/json_api/types/email"
24
- require "rspec/json_api/types/uri"
25
- require "rspec/json_api/types/uuid"
1
+ # frozen_string_literal: true
2
+
3
+ # Load 3rd party libraries
4
+ require "json"
5
+ require "diffy"
6
+ require "active_support/core_ext/object/blank"
7
+
8
+ # Load the json_api parts
9
+ require "rspec/json_api/version"
10
+ require "rspec/json_api/compare_hash"
11
+ require "rspec/json_api/compare_array"
12
+
13
+ # Load extensions
14
+ require "extensions/hash"
15
+ require "extensions/array"
16
+
17
+ # Load matchers
18
+ require "rspec/json_api/matchers"
19
+ require "rspec/json_api/matchers/match_json_schema"
20
+ require "rspec/json_api/matchers/have_no_content"
21
+
22
+ # Load defined types
23
+ require "rspec/json_api/types/email"
24
+ require "rspec/json_api/types/uri"
25
+ require "rspec/json_api/types/uuid"
@@ -1,37 +1,38 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/rspec/json_api/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "rspec-json_api"
7
- spec.version = RSpec::JsonApi::VERSION
8
- spec.authors = ["Michal Gajowiak"]
9
- spec.email = ["m.gajowiak@nomtek.com"]
10
-
11
- spec.summary = "RSpec extension to test JSON API response."
12
- spec.homepage = "https://github.com/nomtek/rspec-json_api"
13
- spec.license = "MIT"
14
- spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
15
-
16
- spec.metadata["homepage_uri"] = spec.homepage
17
- spec.metadata["source_code_uri"] = "https://github.com/nomtek/rspec-json_api"
18
- spec.metadata["changelog_uri"] = "https://github.com/nomtek/rspec-json_api/blob/master/CHANGELOG.md"
19
-
20
- # Specify which files should be added to the gem when it is released.
21
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
23
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
24
- end
25
- spec.bindir = "exe"
26
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
- spec.require_paths = ["lib"]
28
-
29
- # Uncomment to register a new dependency of your gem
30
- spec.add_dependency "activesupport", ">= 6.1.4.1"
31
- spec.add_dependency "diffy", ">= 3.4.2"
32
- spec.add_dependency "rails", ">= 6.1.4.1"
33
- spec.add_dependency "rspec-rails", ">= 5.0.2"
34
-
35
- # For more information and examples about making a new gem, checkout our
36
- # guide at: https://bundler.io/guides/creating_gem.html
37
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rspec/json_api/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rspec-json_api"
7
+ spec.version = RSpec::JsonApi::VERSION
8
+ spec.authors = ["Michal Gajowiak"]
9
+ spec.email = ["m.gajowiak@nomtek.com"]
10
+
11
+ spec.summary = "RSpec extension to test JSON API response."
12
+ spec.homepage = "https://github.com/nomtek/rspec-json_api"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.2.0")
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/nomtek/rspec-json_api"
18
+ spec.metadata["changelog_uri"] = "https://github.com/nomtek/rspec-json_api/blob/master/CHANGELOG.md"
19
+ spec.metadata["rubygems_mfa_required"] = "true"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ # Uncomment to register a new dependency of your gem
31
+ spec.add_dependency "activesupport", ">= 6.1.4.1"
32
+ spec.add_dependency "diffy", ">= 3.4.2"
33
+ spec.add_dependency "rails", ">= 6.1.4.1"
34
+ spec.add_dependency "rspec-rails", ">= 5.0.2"
35
+
36
+ # For more information and examples about making a new gem, checkout our
37
+ # guide at: https://bundler.io/guides/creating_gem.html
38
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-json_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Gajowiak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-26 00:00:00.000000000 Z
11
+ date: 2026-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -87,8 +87,8 @@ files:
87
87
  - Rakefile
88
88
  - bin/console
89
89
  - bin/setup
90
- - lib/extentions/array.rb
91
- - lib/extentions/hash.rb
90
+ - lib/extensions/array.rb
91
+ - lib/extensions/hash.rb
92
92
  - lib/generators/rspec/json_api/install/install_generator.rb
93
93
  - lib/generators/rspec/json_api/install/templates/rspec/json_api/interfaces/.empty_directory
94
94
  - lib/generators/rspec/json_api/install/templates/rspec/json_api/types/.empty_directory
@@ -114,6 +114,7 @@ metadata:
114
114
  homepage_uri: https://github.com/nomtek/rspec-json_api
115
115
  source_code_uri: https://github.com/nomtek/rspec-json_api
116
116
  changelog_uri: https://github.com/nomtek/rspec-json_api/blob/master/CHANGELOG.md
117
+ rubygems_mfa_required: 'true'
117
118
  post_install_message:
118
119
  rdoc_options: []
119
120
  require_paths:
@@ -122,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
123
  requirements:
123
124
  - - ">="
124
125
  - !ruby/object:Gem::Version
125
- version: 3.0.0
126
+ version: 3.2.0
126
127
  required_rubygems_version: !ruby/object:Gem::Requirement
127
128
  requirements:
128
129
  - - ">="