Skip to content

Commit f3b9473

Browse files
authored
Add support for regex in response_strings (#327)
* Extract is_regex method for handlers * Add docs for regex on response strings Very similar to what is used for headers. Fixes #326
1 parent 6939357 commit f3b9473

File tree

5 files changed

+56
-10
lines changed

5 files changed

+56
-10
lines changed

docs/source/format.rst

+5
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ Response Expectations
181181
``response_strings`` A list of string fragments expected
182182
to be present in the response body.
183183

184+
If the value is wrapped in ``/.../``
185+
the response body will be searched
186+
for the value as a regular
187+
expression.
188+
184189
``response_json_paths`` A dictionary of JSONPath rules paired
185190
with expected matches. Using this
186191
rule requires that the content being

gabbi/handlers/base.py

+9
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ def action(self, test, item, value=None):
6666
"""
6767
pass
6868

69+
def is_regex(self, value):
70+
"""Check if the value is formatted to looks like a regular expression.
71+
72+
Meaning it starts and ends with "/".
73+
"""
74+
return (
75+
value.startswith('/') and value.endswith('/') and len(value) > 1
76+
)
77+
6978
def _register(self):
7079
"""Register this handler on the provided test class."""
7180
self.response_handler = None

gabbi/handlers/core.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,18 @@ class StringResponseHandler(base.ResponseHandler):
2222
test_key_value = []
2323

2424
def action(self, test, expected, value=None):
25-
expected = test.replace_template(expected)
26-
test.assert_in_or_print_output(expected, test.output)
25+
is_regex = self.is_regex(expected)
26+
expected = test.replace_template(expected, escape_regex=is_regex)
27+
28+
if is_regex:
29+
# Trim off /
30+
expected = expected[1:-1]
31+
test.assertRegex(
32+
test.output, expected,
33+
'Expect resonse body %s to match /%s/' %
34+
(test.output, expected))
35+
else:
36+
test.assert_in_or_print_output(expected, test.output)
2737

2838

2939
class ForbiddenHeadersResponseHandler(base.ResponseHandler):
@@ -56,9 +66,7 @@ def action(self, test, header, value=None):
5666
response = test.response
5767

5868
header_value = str(value)
59-
is_regex = (header_value.startswith('/') and
60-
header_value.endswith('/') and
61-
len(header_value) > 1)
69+
is_regex = self.is_regex(header_value)
6270
header_value = test.replace_template(header_value,
6371
escape_regex=is_regex)
6472

gabbi/handlers/jsonhandler.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,7 @@ def action(self, test, path, value=None):
118118
'match %s' % (rhs_path, value))
119119

120120
# If expected is a string, check to see if it is a regex.
121-
is_regex = (isinstance(value, str) and
122-
value.startswith('/') and
123-
value.endswith('/') and
124-
len(value) > 1)
121+
is_regex = isinstance(value, str) and self.is_regex(value)
125122
expected = (rhs_match or
126123
test.replace_template(value, escape_regex=is_regex))
127124
match = lhs_match

gabbi/tests/gabbits_intercept/regex.yaml

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Confirm regex handling in response and json path headers
1+
# Confirm regex handling in response headers, strings and json path handlers
22
tests:
33
- name: regex header test
44
url: /cow?alpha=1
@@ -19,3 +19,30 @@ tests:
1919
$.alpha: /ow$/
2020
$.beta: /(?!cow).*/
2121
$.gamma: /\d+/
22+
23+
- name: regex string test json
24+
PUT: /cow
25+
request_headers:
26+
content-type: application/json
27+
data:
28+
alpha: cow
29+
beta: pig
30+
gamma: 1
31+
response_strings:
32+
- '/"alpha": "cow",/'
33+
34+
- name: regex string test multiline
35+
GET: /presenter
36+
response_strings:
37+
- '/Hello World/'
38+
- '/dolor sit/'
39+
40+
- name: regex string test splat
41+
GET: /presenter
42+
response_strings:
43+
- '/dolor.*amet/'
44+
45+
- name: regex string test mix
46+
GET: /presenter
47+
response_strings:
48+
- '/[Hh]el{2}o [Ww]orld/'

0 commit comments

Comments
 (0)