From ab8bae010e1cf4b01a51d63e654e8a7ef5442c32 Mon Sep 17 00:00:00 2001 From: pccr Date: Sun, 30 Nov 2014 11:57:25 -0500 Subject: [PATCH 1/2] Add haveJsonValue matcher Adds a helper to match a specific value in JSON --- .ruby-gemset | 1 + .ruby-version | 1 + lib/json_spec/matchers.rb | 5 +++ lib/json_spec/matchers/have_json_value.rb | 36 ++++++++++++++++ .../matchers/have_json_value_spec.rb | 41 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 .ruby-gemset create mode 100644 .ruby-version create mode 100644 lib/json_spec/matchers/have_json_value.rb create mode 100644 spec/json_spec/matchers/have_json_value_spec.rb diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 0000000..1cd1720 --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +json_spec diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..f01bc44 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +ruby-2.1.4 diff --git a/lib/json_spec/matchers.rb b/lib/json_spec/matchers.rb index cf58e89..2500806 100644 --- a/lib/json_spec/matchers.rb +++ b/lib/json_spec/matchers.rb @@ -2,6 +2,7 @@ require "json_spec/matchers/include_json" require "json_spec/matchers/have_json_path" require "json_spec/matchers/have_json_type" +require "json_spec/matchers/have_json_value" require "json_spec/matchers/have_json_size" module JsonSpec @@ -22,6 +23,10 @@ def have_json_type(type) JsonSpec::Matchers::HaveJsonType.new(type) end + def have_json_value(value) + JsonSpec::Matchers::HaveJsonValue.new(value) + end + def have_json_size(size) JsonSpec::Matchers::HaveJsonSize.new(size) end diff --git a/lib/json_spec/matchers/have_json_value.rb b/lib/json_spec/matchers/have_json_value.rb new file mode 100644 index 0000000..de75fbc --- /dev/null +++ b/lib/json_spec/matchers/have_json_value.rb @@ -0,0 +1,36 @@ +module JsonSpec + module Matchers + class HaveJsonValue + include JsonSpec::Helpers + include JsonSpec::Messages + + def initialize(value) + @value = value + end + + def matches?(json) + @ruby = parse_json(json, @path) + @value == @ruby + end + + def at_path(path) + @path = path + self + end + + def failure_message + message_with_path("Expected JSON value to be \"#{@value}\", got \"#{@ruby}\"") + end + alias :failure_message_for_should :failure_message + + def failure_message_when_negated + message_with_path("Expected JSON value to not be \"#{@value}\", got \"#{@ruby}\"") + end + alias :failure_message_for_should_not :failure_message_when_negated + + def description + message_with_path(%(have JSON value "#{@value}")) + end + end + end +end diff --git a/spec/json_spec/matchers/have_json_value_spec.rb b/spec/json_spec/matchers/have_json_value_spec.rb new file mode 100644 index 0000000..92dbad7 --- /dev/null +++ b/spec/json_spec/matchers/have_json_value_spec.rb @@ -0,0 +1,41 @@ +require "spec_helper" + +describe JsonSpec::Matchers::HaveJsonValue do + it "matches value at root path" do + %("bar").should have_json_value("bar") + end + + it "matches value at path" do + %({"foo": "bar"}).should have_json_value("bar").at_path("foo") + end + + it "matches value at deep path" do + %({"foo": {"pipe": "bar"}}).should have_json_value("bar").at_path("foo/pipe") + end + + it "provides a failure message" do + matcher = have_json_value("pipe") + matcher.matches?(%("bar")) + matcher.failure_message.should == "Expected JSON value to be \"pipe\", got \"bar\"" + matcher.failure_message_for_should.should == "Expected JSON value to be \"pipe\", got \"bar\"" # RSpec 2 interface + end + + it "provides a failure message for negation" do + matcher = have_json_value("pipe") + matcher.matches?(%("bar")) + matcher.failure_message_when_negated.should == "Expected JSON value to not be \"pipe\", got \"bar\"" + matcher.failure_message_for_should_not.should == "Expected JSON value to not be \"pipe\", got \"bar\"" # RSpec 2 interface + end + + it "provides a description message" do + matcher = have_json_value("pipe") + matcher.matches?(%("pipe")) + matcher.description.should == %(have JSON value "pipe") + end + + it "provides a description message with path" do + matcher = have_json_value("pipe").at_path("json") + matcher.matches?(%({"id":1,"json":"pipe"})) + matcher.description.should == %(have JSON value "pipe" at path "json") + end +end From 63e4f5527138ec896ddefd1e480e9926ec080e31 Mon Sep 17 00:00:00 2001 From: pccr Date: Sun, 30 Nov 2014 12:00:09 -0500 Subject: [PATCH 2/2] New gem build --- json_spec-1.1.4.gem | Bin 0 -> 18432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 json_spec-1.1.4.gem diff --git a/json_spec-1.1.4.gem b/json_spec-1.1.4.gem new file mode 100644 index 0000000000000000000000000000000000000000..a210247a4fa7f7a15f4438af2266a3f3776563c0 GIT binary patch literal 18432 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 literal 0 HcmV?d00001