Skip to content

Commit

Permalink
Merge pull request #215 from cdent/json-lhs-expand
Browse files Browse the repository at this point in the history
Template expansion in LHS of json path test
  • Loading branch information
cdent committed Jul 7, 2017
2 parents b7e767e + 683dba6 commit 00dd7c2
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 6 deletions.
3 changes: 2 additions & 1 deletion docs/source/format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ All of these variables may be used in all of the following fields:
* ``data``
* ``request_headers``
* ``response_strings``
* ``response_json_paths`` (on the value side of the key value pair)
* ``response_json_paths`` (in both the key and value, see
:ref:`json path substitution <json-subs>` for more info)
* ``response_headers`` (on the value side of the key value pair)
* ``response_forbidden_headers``
* ``count`` and ``delay`` fields of ``poll``
Expand Down
25 changes: 25 additions & 0 deletions docs/source/jsonpath.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,31 @@ Examples like this can be found in one of gabbi's `own tests`_.
There are more JSONPath examples in :doc:`example` and in the
`jsonpath_rw`_ and `jsonpath_rw_ext`_ documentation.

.. _json-subs:

Substitution
------------

:ref:`Substitutions <state-substitution>` can be made in both the
left (query) and right (expected) hand sides of the json path
expression. When subtitutions are used in the query, care must be
taken to ensure proper quoting of the resulting value. For example
if there is a uuid (with hyphens) at ``$RESPONSE['$.id']`` then this
expression may fail::

$.nested.structure.$RESPONSE['$.id'].name: foobar

as it will evaluate to something like::

$.nested.structure.ADC8AAFC-D564-40D1-9724-7680D3C010C2.name: foobar

which may be treated as an arithemtic expression by the json path
parser. The test author should write::

$.nested.structure["$RESPONSE['$.id']"].name: foobar

to quote the result of the substitution.

.. _jsonpath_rw: http://jsonpath-rw.readthedocs.io/en/latest/
.. _jsonpath_rw_ext: https://python-jsonpath-rw-ext.readthedocs.io/en/latest/
.. _own tests: https://github.com/cdent/gabbi/blob/master/gabbi/tests/gabbits_intercept/data.yaml
7 changes: 2 additions & 5 deletions gabbi/handlers/jsonhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,8 @@ def extract_json_path_value(data, path):

def action(self, test, path, value=None):
"""Test json_paths against json data."""
# NOTE: This process has some advantages over other process that
# might come along because the JSON data has already been
# processed (to provided for the magic template replacing).
# Other handlers that want access to data structures will need
# to do their own processing.
# Do template expansion in the left hand side.
path = test.replace_template(path)
try:
match = self.extract_json_path_value(
test.response_data, path)
Expand Down
37 changes: 37 additions & 0 deletions gabbi/tests/gabbits_intercept/json-left-side.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defaults:
request_headers:
content-type: application/json
verbose: True

tests:
- name: left side json one
desc: for reuse on the next test
POST: /
data:
alpha: alpha1
beta: beta1

- name: expand left side
POST: /
data:
alpha1: alpha
beta1: beta
response_json_paths:
$["$RESPONSE['$.alpha']"]: alpha

- name: expand environ left side
POST: /
data:
alpha1: alpha
beta1: beta
1: cow
response_json_paths:
$.['$ENVIRON['ONE']']: cow

- name: set key and value
GET: /jsonator?key=$ENVIRON['ONE']&value=10

- name: check key and value
GET: /jsonator?key=$ENVIRON['ONE']&value=10
response_json_paths:
$.["$ENVIRON['ONE']"]: $RESPONSE['$['1']']
5 changes: 5 additions & 0 deletions gabbi/tests/simple_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ def __call__(self, environ, start_response):
# fall through if we've ended the loop
elif path_info == '/cookie':
headers.append(('Set-Cookie', 'session=1234; domain=.example.com'))
elif path_info == '/jsonator':
json_data = json.dumps({query_data['key'][0]:
query_data['value'][0]})
start_response('200 OK', [('Content-Type', 'application/json')])
return [json_data.encode('utf-8')]

start_response('200 OK', headers)

Expand Down

0 comments on commit 00dd7c2

Please sign in to comment.