Skip to content

Instantly share code, notes, and snippets.

@bitmage
Created June 14, 2011 04:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitmage/1024324 to your computer and use it in GitHub Desktop.
Save bitmage/1024324 to your computer and use it in GitHub Desktop.
Assertion Class for Parsing JSON
class HaveJson
def initialize(selector)
@actual = []
@depths = []
@selector = selector
@path, @test = selector.split('=')
@path = @path.split('/')
end
def matches?(json)
#turn symbols into strings so path matching works
h = {}
json.each { |k, v| h[k.to_s] = v }
json = h
result = traverse(json, @path)
max_depth = @depths.max || 0
@closest = max_depth > 0 ? @path[max_depth - 1] : 'NO MATCHES'
return result
end
def description
"find selector in JSON"
end
def failure_message
@actual.present? ? actual : closest
end
def closest
"Closest node found: #{@closest}.\n"
end
def actual
"Test: \"#{@test}\" Actual: #{@actual}\n"
end
def negative_failure_message
"Found: #{@selector} in JSON string. Expected nil."
end
private
def traverse(json, path, depth=0)
if path.size == 0
@actual << json
return @test.nil? || json.include?(@test)
end
if json.class == Array
return json.map{|j| dig(j, path, depth+1)}.include? true
else
return dig(json, path, depth+1)
end
end
def dig(json, path, depth)
key, *rest = *path #pop current key
if json.include? key
@depths << depth
return traverse(json[key], rest, depth)
else
return false
end
end
end
def have_json(selector)
HaveJson.new(selector)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment