From 1bac970568a95a12f06b1f15ea6692809ae5ad5c Mon Sep 17 00:00:00 2001 From: Boris Staal Date: Tue, 10 Apr 2012 02:25:08 +0400 Subject: [PATCH 1/7] HaveJsonFields matcher --- lib/json_spec/matchers.rb | 5 +++ lib/json_spec/matchers/have_json_fields.rb | 35 +++++++++++++++++++ .../matchers/have_json_fields_spec.rb | 17 +++++++++ 3 files changed, 57 insertions(+) create mode 100644 lib/json_spec/matchers/have_json_fields.rb create mode 100644 spec/json_spec/matchers/have_json_fields_spec.rb diff --git a/lib/json_spec/matchers.rb b/lib/json_spec/matchers.rb index cf58e89..07fd45a 100644 --- a/lib/json_spec/matchers.rb +++ b/lib/json_spec/matchers.rb @@ -3,6 +3,7 @@ require "json_spec/matchers/have_json_path" require "json_spec/matchers/have_json_type" require "json_spec/matchers/have_json_size" +require "json_spec/matchers/have_json_fields" module JsonSpec module Matchers @@ -25,6 +26,10 @@ def have_json_type(type) def have_json_size(size) JsonSpec::Matchers::HaveJsonSize.new(size) end + + def have_json_fields(size) + JsonSpec::Matchers::HaveJsonFields.new(size) + end end end diff --git a/lib/json_spec/matchers/have_json_fields.rb b/lib/json_spec/matchers/have_json_fields.rb new file mode 100644 index 0000000..c39bbed --- /dev/null +++ b/lib/json_spec/matchers/have_json_fields.rb @@ -0,0 +1,35 @@ +module JsonSpec + module Matchers + class HaveJsonFields + include JsonSpec::Helpers + include JsonSpec::Messages + + def initialize(fields) + @fields = fields + end + + def matches?(json) + @data = parse_json(json, @path) + return false unless @data.is_a?(Hash) + !@fields.map{|f| @data.has_key?(f)}.include?(false) + end + + def at_path(path) + @path = path + self + end + + def failure_message_for_should + message_with_path("Expected JSON to contain all of the following fields #{@fields.join(", ")}") + end + + def failure_message_for_should_not + message_with_path("Expected JSON to not contain any of the following fields #{@fields.join(", ")}") + end + + def description + message_with_path(%(have JSON fields "#{@fields.join(", ")}")) + end + end + end +end diff --git a/spec/json_spec/matchers/have_json_fields_spec.rb b/spec/json_spec/matchers/have_json_fields_spec.rb new file mode 100644 index 0000000..369b725 --- /dev/null +++ b/spec/json_spec/matchers/have_json_fields_spec.rb @@ -0,0 +1,17 @@ +require "spec_helper" + +describe JsonSpec::Matchers::HaveJsonFields do + it "fails for non-hashes" do + %([1,2,3]).should_not have_json_fields([]) + %(1).should_not have_json_fields([]) + %("test").should_not have_json_fields([]) + end + + it "fails for non-complete set of fields" do + %({"a": "a", "b": "b"}).should_not have_json_fields(%w(a b c)) + end + + it "matches complete set of fields" do + %({"a": "a", "b": "b", "c": "c"}).should have_json_fields(%w(a b c)) + end +end From 5c667c7944fb07c348f9043c8457cd5c93334fe9 Mon Sep 17 00:00:00 2001 From: Alexander Pavlenko Date: Wed, 24 Oct 2012 19:14:05 +0400 Subject: [PATCH 2/7] accept symbols as field names --- lib/json_spec/matchers/have_json_fields.rb | 2 +- spec/json_spec/matchers/have_json_fields_spec.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/json_spec/matchers/have_json_fields.rb b/lib/json_spec/matchers/have_json_fields.rb index c39bbed..fd72c1c 100644 --- a/lib/json_spec/matchers/have_json_fields.rb +++ b/lib/json_spec/matchers/have_json_fields.rb @@ -11,7 +11,7 @@ def initialize(fields) def matches?(json) @data = parse_json(json, @path) return false unless @data.is_a?(Hash) - !@fields.map{|f| @data.has_key?(f)}.include?(false) + !@fields.map{|f| @data.has_key?(f.to_s)}.include?(false) end def at_path(path) diff --git a/spec/json_spec/matchers/have_json_fields_spec.rb b/spec/json_spec/matchers/have_json_fields_spec.rb index 369b725..e80ab5e 100644 --- a/spec/json_spec/matchers/have_json_fields_spec.rb +++ b/spec/json_spec/matchers/have_json_fields_spec.rb @@ -9,9 +9,11 @@ it "fails for non-complete set of fields" do %({"a": "a", "b": "b"}).should_not have_json_fields(%w(a b c)) + %({"a": "a", "b": "b"}).should_not have_json_fields([:a, :b, :c]) end it "matches complete set of fields" do %({"a": "a", "b": "b", "c": "c"}).should have_json_fields(%w(a b c)) + %({"a": "a", "b": "b", "c": "c"}).should have_json_fields([:a, :b, :c]) end end From f0a1d90aac65d2fcb931bf10d076c1a99f6e866c Mon Sep 17 00:00:00 2001 From: AlexanderPavlenko Date: Mon, 29 Oct 2012 00:04:53 +0400 Subject: [PATCH 3/7] rename variable --- lib/json_spec/matchers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/json_spec/matchers.rb b/lib/json_spec/matchers.rb index 07fd45a..4198883 100644 --- a/lib/json_spec/matchers.rb +++ b/lib/json_spec/matchers.rb @@ -27,8 +27,8 @@ def have_json_size(size) JsonSpec::Matchers::HaveJsonSize.new(size) end - def have_json_fields(size) - JsonSpec::Matchers::HaveJsonFields.new(size) + def have_json_fields(fields) + JsonSpec::Matchers::HaveJsonFields.new(fields) end end end From f5de25d20ff92e8f2049216fd61ce3af26646741 Mon Sep 17 00:00:00 2001 From: AlexanderPavlenko Date: Wed, 14 Nov 2012 21:16:11 +0400 Subject: [PATCH 4/7] support cucumber have_json_keys matcher; improve tests; fix bug with table.rows --- README.md | 1 + features/keys.feature | 37 ++++++++++++++++ lib/json_spec/cucumber.rb | 20 +++++++++ lib/json_spec/matchers.rb | 6 +-- ...{have_json_fields.rb => have_json_keys.rb} | 14 +++--- .../matchers/have_json_fields_spec.rb | 19 -------- .../json_spec/matchers/have_json_keys_spec.rb | 43 +++++++++++++++++++ 7 files changed, 111 insertions(+), 29 deletions(-) create mode 100644 features/keys.feature rename lib/json_spec/matchers/{have_json_fields.rb => have_json_keys.rb} (65%) delete mode 100644 spec/json_spec/matchers/have_json_fields_spec.rb create mode 100644 spec/json_spec/matchers/have_json_keys_spec.rb diff --git a/README.md b/README.md index 952a98d..e7ae0eb 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ json_spec defines five new RSpec matchers: * `be_json_eql` * `include_json` * `have_json_path` +* `have_json_keys` * `have_json_type` * `have_json_size` diff --git a/features/keys.feature b/features/keys.feature new file mode 100644 index 0000000..59d35b8 --- /dev/null +++ b/features/keys.feature @@ -0,0 +1,37 @@ +Feature: Paths + Background: + Given the JSON is: + """ + { + "a": 1, + "b": 2, + "c": 3, + "z" : { + "d": 4, + "e": 5 + } + } + """ + + Scenario: Base paths + When I get the JSON + Then the JSON should have keys "a, b, c" + Then the JSON should not have keys "d, e" + Then the JSON at "z" should have keys "d, e" + Then the JSON at "z" should not have keys "m, z" + + Scenario: Table format + When I get the JSON + Then the JSON should have the following keys: + | a | + | b | + | c | + Then the JSON should not have the following keys: + | d | + | e | + Then the JSON at "z" should have the following keys: + | d | + | e | + Then the JSON at "z" should not have the following keys: + | m | + | z | diff --git a/lib/json_spec/cucumber.rb b/lib/json_spec/cucumber.rb index f4b66a9..fece25a 100644 --- a/lib/json_spec/cucumber.rb +++ b/lib/json_spec/cucumber.rb @@ -70,6 +70,16 @@ end end +Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have the following keys:$/ do |base, negative, table| + match = have_json_keys(table.raw) + match = match.at_path(base) if base + if negative + last_json.should_not match + else + last_json.should match + end +end + Then /^the (?:JSON|json)(?: response)? should( not)? have "(.*)"$/ do |negative, path| if negative last_json.should_not have_json_path(path) @@ -78,6 +88,16 @@ end end +Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have keys "(.*)"$/ do |base, negative, keys| + match = have_json_keys(keys.split(',').map(&:strip)) + match = match.at_path(base) if base + if negative + last_json.should_not match + else + last_json.should match + end +end + Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? be an? (.*)$/ do |path, negative, type| if negative last_json.should_not have_json_type(type).at_path(path) diff --git a/lib/json_spec/matchers.rb b/lib/json_spec/matchers.rb index 4198883..26b1a97 100644 --- a/lib/json_spec/matchers.rb +++ b/lib/json_spec/matchers.rb @@ -3,7 +3,7 @@ require "json_spec/matchers/have_json_path" require "json_spec/matchers/have_json_type" require "json_spec/matchers/have_json_size" -require "json_spec/matchers/have_json_fields" +require "json_spec/matchers/have_json_keys" module JsonSpec module Matchers @@ -27,8 +27,8 @@ def have_json_size(size) JsonSpec::Matchers::HaveJsonSize.new(size) end - def have_json_fields(fields) - JsonSpec::Matchers::HaveJsonFields.new(fields) + def have_json_keys(*keys) + JsonSpec::Matchers::HaveJsonKeys.new(keys.flatten) end end end diff --git a/lib/json_spec/matchers/have_json_fields.rb b/lib/json_spec/matchers/have_json_keys.rb similarity index 65% rename from lib/json_spec/matchers/have_json_fields.rb rename to lib/json_spec/matchers/have_json_keys.rb index fd72c1c..c316164 100644 --- a/lib/json_spec/matchers/have_json_fields.rb +++ b/lib/json_spec/matchers/have_json_keys.rb @@ -1,17 +1,17 @@ module JsonSpec module Matchers - class HaveJsonFields + class HaveJsonKeys include JsonSpec::Helpers include JsonSpec::Messages - def initialize(fields) - @fields = fields + def initialize(keys) + @keys = keys end def matches?(json) @data = parse_json(json, @path) return false unless @data.is_a?(Hash) - !@fields.map{|f| @data.has_key?(f.to_s)}.include?(false) + !@keys.map{|f| @data.has_key?(f.to_s)}.include?(false) end def at_path(path) @@ -20,15 +20,15 @@ def at_path(path) end def failure_message_for_should - message_with_path("Expected JSON to contain all of the following fields #{@fields.join(", ")}") + message_with_path("Expected JSON to contain all of the following keys #{@keys.join(", ")}") end def failure_message_for_should_not - message_with_path("Expected JSON to not contain any of the following fields #{@fields.join(", ")}") + message_with_path("Expected JSON to not contain any of the following keys #{@keys.join(", ")}") end def description - message_with_path(%(have JSON fields "#{@fields.join(", ")}")) + message_with_path(%(have JSON keys "#{@keys.join(", ")}")) end end end diff --git a/spec/json_spec/matchers/have_json_fields_spec.rb b/spec/json_spec/matchers/have_json_fields_spec.rb deleted file mode 100644 index e80ab5e..0000000 --- a/spec/json_spec/matchers/have_json_fields_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "spec_helper" - -describe JsonSpec::Matchers::HaveJsonFields do - it "fails for non-hashes" do - %([1,2,3]).should_not have_json_fields([]) - %(1).should_not have_json_fields([]) - %("test").should_not have_json_fields([]) - end - - it "fails for non-complete set of fields" do - %({"a": "a", "b": "b"}).should_not have_json_fields(%w(a b c)) - %({"a": "a", "b": "b"}).should_not have_json_fields([:a, :b, :c]) - end - - it "matches complete set of fields" do - %({"a": "a", "b": "b", "c": "c"}).should have_json_fields(%w(a b c)) - %({"a": "a", "b": "b", "c": "c"}).should have_json_fields([:a, :b, :c]) - end -end diff --git a/spec/json_spec/matchers/have_json_keys_spec.rb b/spec/json_spec/matchers/have_json_keys_spec.rb new file mode 100644 index 0000000..500eef1 --- /dev/null +++ b/spec/json_spec/matchers/have_json_keys_spec.rb @@ -0,0 +1,43 @@ +require "spec_helper" + +describe JsonSpec::Matchers::HaveJsonKeys do + it "fails for non-hashes" do + %([1,2,3]).should_not have_json_keys + %(1).should_not have_json_keys + %("test").should_not have_json_keys + end + + it "fails for bigger set of keys" do + %({"a": "1", "b": "2"}).should_not have_json_keys(:a, :b, :c) + end + + it "matches for equal set of keys" do + [:a, :b, :c].permutation.each do |keys| + %({"a": "1", "b": "2", "c": "3"}).should have_json_keys(*keys) + end + end + + it "matches for smaller set of keys" do + %({"a": "1", "b": "2", "c": "3"}).should have_json_keys(:a, :b) + end + + it "matches for empty set of keys" do + %({"a": "1", "b": "2", "c": "3"}).should have_json_keys + end + + it "accepts array of symbol keys" do + %({"a": "1", "b": "2"}).should have_json_keys([:a, :b]) + end + + it "accepts array of string keys" do + %({"a": "1", "b": "2"}).should have_json_keys(['a', 'b']) + end + + it "accepts symbol keys" do + %({"a": "1", "b": "2"}).should have_json_keys(:a, :b) + end + + it "accepts string keys" do + %({"a": "1", "b": "2"}).should have_json_keys('a', 'b') + end +end From bec87248b345150c8cce02d6e2eacd679c4175f2 Mon Sep 17 00:00:00 2001 From: AlexanderPavlenko Date: Thu, 14 Feb 2013 13:57:53 +0400 Subject: [PATCH 5/7] fix check logic --- lib/json_spec/matchers/have_json_keys.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/json_spec/matchers/have_json_keys.rb b/lib/json_spec/matchers/have_json_keys.rb index c316164..4494268 100644 --- a/lib/json_spec/matchers/have_json_keys.rb +++ b/lib/json_spec/matchers/have_json_keys.rb @@ -11,7 +11,7 @@ def initialize(keys) def matches?(json) @data = parse_json(json, @path) return false unless @data.is_a?(Hash) - !@keys.map{|f| @data.has_key?(f.to_s)}.include?(false) + @keys.all?{|key| @data.has_key?(key.to_s)} end def at_path(path) From 03866ad6ecc1045933d528e93c3201bcf5b21d1d Mon Sep 17 00:00:00 2001 From: AlexanderPavlenko Date: Thu, 14 Feb 2013 17:43:43 +0400 Subject: [PATCH 6/7] support arbitrary json keys --- features/keys.feature | 12 +++++++----- lib/json_spec/cucumber.rb | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/features/keys.feature b/features/keys.feature index 59d35b8..cf6af30 100644 --- a/features/keys.feature +++ b/features/keys.feature @@ -9,16 +9,18 @@ Feature: Paths "z" : { "d": 4, "e": 5 - } + }, + "strange keys: '\_(\")_/', FTW!": true } """ Scenario: Base paths When I get the JSON - Then the JSON should have keys "a, b, c" - Then the JSON should not have keys "d, e" - Then the JSON at "z" should have keys "d, e" - Then the JSON at "z" should not have keys "m, z" + Then the JSON should have keys "a", "b", "c" + Then the JSON should not have keys "d", "e" + Then the JSON at "z" should have keys "d", "e" + Then the JSON at "z" should not have keys "m", "z" + Then the JSON should have keys "strange keys: '\_(\")_/', FTW!", "a", "b" Scenario: Table format When I get the JSON diff --git a/lib/json_spec/cucumber.rb b/lib/json_spec/cucumber.rb index fece25a..03c6000 100644 --- a/lib/json_spec/cucumber.rb +++ b/lib/json_spec/cucumber.rb @@ -88,8 +88,9 @@ end end -Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have keys "(.*)"$/ do |base, negative, keys| - match = have_json_keys(keys.split(',').map(&:strip)) +Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have keys (.*)$/ do |base, negative, keys| + keys = eval("[#{keys}]") + match = have_json_keys(keys) match = match.at_path(base) if base if negative last_json.should_not match From 6db3b90ba620ad17cec7ade6d5b7cdb7842ec268 Mon Sep 17 00:00:00 2001 From: AlexanderPavlenko Date: Mon, 21 Oct 2013 13:28:50 +0400 Subject: [PATCH 7/7] keys feature --- features/keys.feature | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/features/keys.feature b/features/keys.feature index cf6af30..bf980c2 100644 --- a/features/keys.feature +++ b/features/keys.feature @@ -17,10 +17,10 @@ Feature: Paths Scenario: Base paths When I get the JSON Then the JSON should have keys "a", "b", "c" - Then the JSON should not have keys "d", "e" - Then the JSON at "z" should have keys "d", "e" - Then the JSON at "z" should not have keys "m", "z" - Then the JSON should have keys "strange keys: '\_(\")_/', FTW!", "a", "b" + And the JSON should not have keys "d", "e" + And the JSON at "z" should have keys "d", "e" + And the JSON at "z" should not have keys "m", "z" + And the JSON should have keys "strange keys: '\_(\")_/', FTW!", "a", "b" Scenario: Table format When I get the JSON @@ -28,12 +28,12 @@ Feature: Paths | a | | b | | c | - Then the JSON should not have the following keys: + And the JSON should not have the following keys: | d | | e | - Then the JSON at "z" should have the following keys: + And the JSON at "z" should have the following keys: | d | | e | - Then the JSON at "z" should not have the following keys: + And the JSON at "z" should not have the following keys: | m | | z |