From c81382effba7b1652f13a620055b7c0d4005387a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=2E=20Mert=20Y=C4=B1ld=C4=B1ran?= Date: Mon, 18 Jan 2021 19:44:56 +0300 Subject: [PATCH] Add more Faker examples (#40) * Add more Faker examples * Add a test case to demonstrate the issues * Turn 'fake' helper into a context object in the handlebars templating * Add escapeHtml helper * Add tojson helper * Add array helper * Add more Faker examples to the documentation * Add replace helper --- Templating.md | 94 ++++++++++++++++++- mockintosh/handlers.py | 7 +- mockintosh/hbs/methods.py | 43 ++++++++- mockintosh/j2/methods.py | 5 + mockintosh/templating.py | 34 ++++--- requirements.txt | 2 +- .../hbs/common/templates/companies.json.hbs | 4 +- .../json/hbs/common/templates/user.json.hbs | 4 +- .../json/hbs/common/templates/users.json.hbs | 4 +- tests/configs/json/hbs/core/faker.json | 21 +++++ .../json/hbs/core/templates/faker.json.hbs | 61 ++++++++++++ .../json/hbs/core/templates/hello.json.hbs | 2 +- tests/configs/json/j2/core/faker.json | 21 +++++ .../json/j2/core/templates/faker.json.j2 | 61 ++++++++++++ .../hbs/common/templates/companies.json.hbs | 4 +- .../yaml/hbs/common/templates/user.json.hbs | 4 +- .../yaml/hbs/common/templates/users.json.hbs | 4 +- tests/configs/yaml/hbs/core/escape_html.yaml | 8 ++ tests/configs/yaml/j2/core/escape_html.yaml | 8 ++ tests/test_features.py | 76 ++++++++++++--- 20 files changed, 415 insertions(+), 52 deletions(-) create mode 100644 tests/configs/json/hbs/core/faker.json create mode 100644 tests/configs/json/hbs/core/templates/faker.json.hbs create mode 100644 tests/configs/json/j2/core/faker.json create mode 100644 tests/configs/json/j2/core/templates/faker.json.j2 create mode 100644 tests/configs/yaml/hbs/core/escape_html.yaml create mode 100644 tests/configs/yaml/j2/core/escape_html.yaml diff --git a/Templating.md b/Templating.md index 68044e68c..9b6df3272 100644 --- a/Templating.md +++ b/Templating.md @@ -101,10 +101,72 @@ Here is a list of date shifting examples as a Handlebars response template: ### Faker [Faker](https://faker.readthedocs.io/en/master/providers.html) library is provided for generating some dynamic data. -It is available as `fake` object. Refer to the [official docs](https://faker.readthedocs.io/en/master/providers.html) for all capabilities. Below are some examples: +It is available as `fake` object. Refer to the [official docs](https://faker.readthedocs.io/en/master/providers.html) +for all capabilities. Below are some examples (Handlebars): -- `fake.first_name` -- `fake.last_name` +```hbs +{ + "hexify_args": "{{ fake.hexify text="MAC Address: ^^:^^:^^:^^:^^:^^" upper=true }}", + "lexify_args": "{{ fake.lexify text="Random Identifier: ??????????" }}", + "numerify_args": "{{ fake.numerify text="Intel Core i%-%%##K vs AMD Ryzen % %%##X" }}", + "random_choices": "{{ fake.random_choices elements=( array 'a' 'b' 'c' 'd' 'e' ) }}", + "random_digit": {{ fake.random_digit }}, + "random_element": "{{ fake.random_element elements=( array 'a' 'b' 'c' 'd' 'e' ) }}", + "random_elements": {{ tojson ( fake.random_elements elements=( array 'a' 'b' 'c' 'd' 'e' ) length=3 unique=True ) }}, + "random_int_args": {{ fake.random_int min=10000 max=50000 step=500 }}, + "random_letter": "{{ fake.random_letter }}", + "random_letters": {{ tojson ( fake.random_letters ) }}, + "random_letters_args": {{ tojson ( fake.random_letters length=32 ) }}, + "random_lowercase_letter": "{{ fake.random_lowercase_letter }}", + "random_sample": {{ tojson ( fake.random_sample elements=( array 'a' 'b' 'c' 'd' 'e' ) ) }}, + "random_uppercase_letter": "{{ fake.random_uppercase_letter }}", + "first_name": "{{ fake.first_name }}", + "first_name_female": "{{ fake.first_name_female }}", + "first_name_male": "{{ fake.first_name_male }}", + "first_name_nonbinary": "{{ fake.first_name_nonbinary }}", + "last_name": "{{ fake.last_name }}", + "last_name_female": "{{ fake.last_name_female }}", + "last_name_male": "{{ fake.last_name_male }}", + "last_name_nonbinary": "{{ fake.last_name_nonbinary }}", + "address": "{{ replace ( fake.address ) old='\n' new='\\n' }}", + "city": "{{ fake.city }}", + "country": "{{ fake.country }}" +} +``` + +Rendered: + +```json +{ + "hexify_args": "MAC Address: 84:DE:AD:1C:AD:D7", + "lexify_args": "Random Identifier: ZDGINMgIkX", + "numerify_args": "Intel Core i7-8517K vs AMD Ryzen 3 8887X", + "random_choices": "['b', 'a', 'd', 'a', 'b']", + "random_digit": 9, + "random_element": "d", + "random_elements": ["a", "a", "d"], + "random_int_args": 26500, + "random_letter": "A", + "random_letters": ["M", "S", "N", "T", "r", "m", "p", "j", "R", "n", "g", "g", "A", "w", "o", "d"], + "random_letters_args": ["F", "L", "X", "R", "Z", "T", "f", "k", "C", "v", "U", "d", "d", "S", "p", "j", "s", "F", "M", "X", "k", "J", "P", "R", "W", "m", "i", "A", "x", "o", "r", "H"], + "random_lowercase_letter": "i", + "random_sample": ["c", "a", "b"], + "random_uppercase_letter": "U", + "first_name": "Mark", + "first_name_female": "Sharon", + "first_name_male": "Brian", + "first_name_nonbinary": "Jessica", + "last_name": "Campbell", + "last_name_female": "Rodriguez", + "last_name_male": "Combs", + "last_name_nonbinary": "Mcmillan", + "address": "035 Angela Brook\nElizabethhaven, MO 35984", + "city": "Hannaport", + "country": "Burkina Faso" +} +``` + +An extended list of Faker examples can be found in: [Handlebars](https://github.com/up9inc/mockintosh/blob/main/tests/configs/json/hbs/core/templates/faker.json.hbs) and [Jinja2](https://github.com/up9inc/mockintosh/blob/main/tests/configs/json/j2/core/templates/faker.json.j2) ### Counters @@ -138,3 +200,29 @@ And some less frequently used: ### Using JSONPath Syntax You can reference certain fields from request's JSON by using `jsonPath` helper like this: `jsonPath request.json '$.key'`. + +### Other Template Helpers + +#### `escapeHtml(text)` + +`{{ escapeHtml '& < \" >' }}` a helper to escape HTML special characters. (see [`html.escape`](https://wiki.python.org/moin/EscapingHtml)) + +#### `tojson(text)` (Handlebars) + +The equivalent of [`tojson`](https://jinja.palletsprojects.com/en/2.11.x/templates/#tojson) filter in Jinja2. + +Jinja2 usage: `{{ fake.random_letters() | tojson }}` + +Handlebars usage: `{{ tojson ( fake.random_letters ) }}` + +#### `array(*args)` (Handlebars) + +Provides array support in parameters. `{{ array 'a' 'b' 'c' 'd' 'e' }}` returns `['a', 'b', 'c', 'd', 'e']`. + +#### `replace(text, old, new, count=None)` (Handlebars) + +The equivalent of [`replace`](https://jinja.palletsprojects.com/en/2.11.x/templates/#replace) filter in Jinja2. + +Jinja2 usage: `{{ fake.address() | replace('\n','\\n') }}` + +Handlebars usage: `{{ replace ( fake.address ) old='\n' new='\\n' }}` diff --git a/mockintosh/handlers.py b/mockintosh/handlers.py index c831cae3c..36bf46046 100644 --- a/mockintosh/handlers.py +++ b/mockintosh/handlers.py @@ -596,11 +596,11 @@ def loop_alternative(self, alternative, key, subkey): def common_template_renderer(self, template_engine, text): if template_engine == PYBARS: - from mockintosh.hbs.methods import fake, counter, json_path + from mockintosh.hbs.methods import fake, counter, json_path, escape_html self.custom_context['random'] = hbs_random self.custom_context['date'] = hbs_date elif template_engine == JINJA: - from mockintosh.j2.methods import fake, counter, json_path + from mockintosh.j2.methods import fake, counter, json_path, escape_html self.custom_context['random'] = j2_random self.custom_context['date'] = j2_date else: @@ -613,7 +613,8 @@ def common_template_renderer(self, template_engine, text): inject_methods=[ fake, counter, - json_path + json_path, + escape_html ], add_params_callback=self.add_params, fill_undefineds=True diff --git a/mockintosh/hbs/methods.py b/mockintosh/hbs/methods.py index 149b68fe3..64b24e187 100644 --- a/mockintosh/hbs/methods.py +++ b/mockintosh/hbs/methods.py @@ -11,18 +11,22 @@ import os import binascii import time +import html +import json from datetime import datetime from datetime import timedelta from uuid import uuid4 from jsonpath_ng import parse as jsonpath_parse from pybars import PybarsError +from faker import Faker from mockintosh.methods import _handlebars_add_to_context -def fake(this, fake, attr): - return getattr(fake, attr)() +def fake(): + # Fake fake :) + pass def reg_ex(this, regex, *args, **kwargs): @@ -71,6 +75,29 @@ def counter(this, name): return number +def escape_html(this, text): + return html.escape(text) + + +def tojson(this, text): + return json.dumps(text) \ + .replace(u'<', u'\\u003c') \ + .replace(u'>', u'\\u003e') \ + .replace(u'&', u'\\u0026') \ + .replace(u"'", u'\\u0027') + + +def array(this, *args): + return [*args] + + +def replace(this, text, old, new, count=None): + if count is None: + count = -1 + text = text.replace(str(old), str(new)) + return text + + class Random(): def __init__(self): @@ -121,3 +148,15 @@ def date( else: now = now + shift_time return now.strftime(pattern) + + +class HbsFaker(Faker): + def __getattr__(self, name): + attr = Faker.__getattr__(self, name) + if hasattr(attr, '__call__'): + def newfunc(this, *args, **kwargs): + result = attr(*args, **kwargs) + return result + return newfunc + else: + return attr diff --git a/mockintosh/j2/methods.py b/mockintosh/j2/methods.py index 3de6f91de..d6666f9c8 100644 --- a/mockintosh/j2/methods.py +++ b/mockintosh/j2/methods.py @@ -11,6 +11,7 @@ import os import binascii import time +import html from datetime import datetime from datetime import timedelta from uuid import uuid4 @@ -75,6 +76,10 @@ def counter(context, name): return number +def escape_html(text): + return html.escape(text) + + class Random(): def __init__(self): diff --git a/mockintosh/templating.py b/mockintosh/templating.py index 50d11aa0e..2d723e3ab 100644 --- a/mockintosh/templating.py +++ b/mockintosh/templating.py @@ -18,10 +18,11 @@ from mockintosh.constants import SUPPORTED_ENGINES, PYBARS, JINJA, JINJA_VARNAME_DICT, SPECIAL_CONTEXT from mockintosh.exceptions import UnsupportedTemplateEngine from mockintosh.methods import _to_camel_case -from mockintosh.hbs.methods import fake as hbs_fake +from mockintosh.hbs.methods import HbsFaker, tojson, array, replace compiler = Compiler() faker = Faker() +hbs_faker = HbsFaker() debug_mode = environ.get('MOCKINTOSH_DEBUG', False) @@ -63,10 +64,10 @@ def check_engine_support(self): def render_handlebars(self): context, helpers = self.add_globals(compiler._compiler, helpers={}) - template = compiler.compile(self.text) try: + template = compiler.compile(self.text) compiled = template(context, helpers=helpers) - except (PybarsError, TypeError) as e: + except (PybarsError, TypeError, SyntaxError) as e: if self.fill_undefineds: if debug_mode: raise e @@ -112,11 +113,6 @@ def render_jinja(self): return compiled, copy.deepcopy(env.globals[JINJA_VARNAME_DICT]) def add_globals(self, template, helpers=None): - fake = None - # Create the faker object if `fake` is in the `inject_methods` - if 'fake' in self.inject_methods_name_list: - fake = faker - # To provide the support of both PYBARS and JINJA context = {} engine = PYBARS @@ -126,11 +122,22 @@ def add_globals(self, template, helpers=None): helpers = template.globals context = helpers + if engine == PYBARS: + self.inject_methods += [ + tojson, + array, + replace + ] + # Inject the methods: for method in self.inject_methods: if method.__name__ == 'fake': logging.debug('Inject Faker object into the template.') - helpers[method.__name__] = fake + if engine == PYBARS: + # Workaround to provide Faker support in PYBARS + context['fake'] = hbs_faker + else: + context['fake'] = faker else: helpers[_to_camel_case(method.__name__)] = method @@ -142,13 +149,4 @@ def add_globals(self, template, helpers=None): if self.add_params_callback is not None: context = self.add_params_callback(context) - # Workaround to provide Faker support in PYBARS - if engine == PYBARS and 'fake' in self.inject_methods_name_list: - logging.debug('Use Handlebars version of Faker.') - - def super_fake(this, *args, **kwargs): - return hbs_fake(this, fake, *args, **kwargs) - - helpers['fake'] = super_fake - return context, helpers diff --git a/requirements.txt b/requirements.txt index 412e4f540..4fc7cbf37 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ Faker==4.18.0 tornado==6.0.4 PyYAML==5.3.1 jsonschema==3.2.0 -pybars4>=0.9.9 +pybars4>=0.9.11 accept-types==0.4.1 jsonpath-ng==1.5.2 diff --git a/tests/configs/json/hbs/common/templates/companies.json.hbs b/tests/configs/json/hbs/common/templates/companies.json.hbs index 76505899b..2f7ee2883 100644 --- a/tests/configs/json/hbs/common/templates/companies.json.hbs +++ b/tests/configs/json/hbs/common/templates/companies.json.hbs @@ -1,8 +1,8 @@ { "companies": [ { - "name": "{{ fake "company" }}", - "motto": "{{ fake "catch_phrase" }}" + "name": "{{ fake.company }}", + "motto": "{{ fake.catch_phrase }}" } ], "total": 2 diff --git a/tests/configs/json/hbs/common/templates/user.json.hbs b/tests/configs/json/hbs/common/templates/user.json.hbs index b761be4fc..d0e20336c 100644 --- a/tests/configs/json/hbs/common/templates/user.json.hbs +++ b/tests/configs/json/hbs/common/templates/user.json.hbs @@ -1,7 +1,7 @@ { "id": {{ id }}, - "firstName": "{{ fake "first_name" }}", - "lastName": "{{ fake "last_name" }}", + "firstName": "{{ fake.first_name }}", + "lastName": "{{ fake.last_name }}", "friends": [ { "id": "{{ random.uuid4 }}" diff --git a/tests/configs/json/hbs/common/templates/users.json.hbs b/tests/configs/json/hbs/common/templates/users.json.hbs index ca5dc4b16..82248bb93 100644 --- a/tests/configs/json/hbs/common/templates/users.json.hbs +++ b/tests/configs/json/hbs/common/templates/users.json.hbs @@ -2,8 +2,8 @@ "users": [ { "id": {{ random.int 10000 100000 }}, - "firstName": "{{ fake "first_name" }}", - "lastName": "{{ fake "last_name" }}", + "firstName": "{{ fake.first_name }}", + "lastName": "{{ fake.last_name }}", "friends": [ { "id": "{{ random.uuid4 }}" diff --git a/tests/configs/json/hbs/core/faker.json b/tests/configs/json/hbs/core/faker.json new file mode 100644 index 000000000..937fa4e79 --- /dev/null +++ b/tests/configs/json/hbs/core/faker.json @@ -0,0 +1,21 @@ +{ + "templatingEngine": "Handlebars", + "services": [ + { + "name": "Mock for Service1", + "port": 8001, + "endpoints": [ + { + "path": "/faker", + "method": "GET", + "response": { + "headers": { + "Content-Type": "application/json; charset=UTF-8" + }, + "body": "@templates/faker.json.hbs" + } + } + ] + } + ] +} diff --git a/tests/configs/json/hbs/core/templates/faker.json.hbs b/tests/configs/json/hbs/core/templates/faker.json.hbs new file mode 100644 index 000000000..666efe57e --- /dev/null +++ b/tests/configs/json/hbs/core/templates/faker.json.hbs @@ -0,0 +1,61 @@ +{ + "bothify": "{{ fake.bothify }}", + "bothify_args": "{{ fake.bothify text="## ??" letters="ABCDE" }}", + "hexify": "{{ fake.hexify }}", + "hexify_args": "{{ fake.hexify text="MAC Address: ^^:^^:^^:^^:^^:^^" upper=true }}", + "language_code": "{{ fake.language_code }}", + "lexify": "{{ fake.lexify }}", + "lexify_args": "{{ fake.lexify text="Random Identifier: ??????????" }}", + "locale": "{{ fake.locale }}", + "numerify": "{{ fake.numerify }}", + "numerify_args": "{{ fake.numerify text="Intel Core i%-%%##K vs AMD Ryzen % %%##X" }}", + "random_choices": "{{ fake.random_choices elements=( array 'a' 'b' 'c' 'd' 'e' ) }}", + "random_digit": {{ fake.random_digit }}, + "random_digit_not_null": {{ fake.random_digit_not_null }}, + "random_digit_not_null_or_empty": "{{ fake.random_digit_not_null_or_empty }}", + "random_digit_or_empty": "{{ fake.random_digit_or_empty }}", + "random_element": "{{ fake.random_element elements=( array 'a' 'b' 'c' 'd' 'e' ) }}", + "random_elements": {{ tojson ( fake.random_elements elements=( array 'a' 'b' 'c' 'd' 'e' ) length=3 unique=True ) }}, + "random_int": {{ fake.random_int }}, + "random_int_args": {{ fake.random_int min=10000 max=50000 step=500 }}, + "random_letter": "{{ fake.random_letter }}", + "random_letters": {{ tojson ( fake.random_letters ) }}, + "random_letters_args": {{ tojson ( fake.random_letters length=32 ) }}, + "random_lowercase_letter": "{{ fake.random_lowercase_letter }}", + "random_number": {{ fake.random_number }}, + "random_number_args": {{ fake.random_number digits=null fix_len=true }}, + "random_sample": {{ tojson ( fake.random_sample elements=( array 'a' 'b' 'c' 'd' 'e' ) ) }}, + "random_uppercase_letter": "{{ fake.random_uppercase_letter }}", + "randomize_nb_elements": "{{ fake.randomize_nb_elements number=79 le=true ge=true min=80 }}", + "first_name": "{{ fake.first_name }}", + "first_name_female": "{{ fake.first_name_female }}", + "first_name_male": "{{ fake.first_name_male }}", + "first_name_nonbinary": "{{ fake.first_name_nonbinary }}", + "language_name": "{{ fake.language_name }}", + "last_name": "{{ fake.last_name }}", + "last_name_female": "{{ fake.last_name_female }}", + "last_name_male": "{{ fake.last_name_male }}", + "last_name_nonbinary": "{{ fake.last_name_nonbinary }}", + "name": "{{ fake.name }}", + "name_female": "{{ fake.name_female }}", + "name_male": "{{ fake.name_male }}", + "name_nonbinary": "{{ fake.name_nonbinary }}", + "prefix": "{{ fake.prefix }}", + "prefix_female": "{{ fake.prefix_female }}", + "prefix_male": "{{ fake.prefix_male }}", + "prefix_nonbinary": "{{ fake.prefix_nonbinary }}", + "suffix": "{{ fake.suffix }}", + "suffix_female": "{{ fake.suffix_female }}", + "suffix_male": "{{ fake.suffix_male }}", + "suffix_nonbinary": "{{ fake.suffix_nonbinary }}", + "address": "{{ replace ( fake.address ) old='\n' new='\\n' }}", + "city": "{{ fake.city }}", + "city_suffix": "{{ fake.city_suffix }}", + "country": "{{ fake.country }}", + "country_code": "{{ fake.country_code }}", + "postcode": "{{ fake.postcode }}", + "street_address": "{{ fake.street_address }}", + "street_name": "{{ fake.street_name }}", + "street_suffix": "{{ fake.street_suffix }}", + "license_plate": "{{ fake.license_plate }}" +} diff --git a/tests/configs/json/hbs/core/templates/hello.json.hbs b/tests/configs/json/hbs/core/templates/hello.json.hbs index 5e8c2ce71..2318e33fa 100644 --- a/tests/configs/json/hbs/core/templates/hello.json.hbs +++ b/tests/configs/json/hbs/core/templates/hello.json.hbs @@ -1,3 +1,3 @@ { - "hello": "{{ fake "first_name" }}" + "hello": "{{ fake.first_name }}" } diff --git a/tests/configs/json/j2/core/faker.json b/tests/configs/json/j2/core/faker.json new file mode 100644 index 000000000..caa7b5c8f --- /dev/null +++ b/tests/configs/json/j2/core/faker.json @@ -0,0 +1,21 @@ +{ + "templatingEngine": "Jinja2", + "services": [ + { + "name": "Mock for Service1", + "port": 8001, + "endpoints": [ + { + "path": "/faker", + "method": "GET", + "response": { + "headers": { + "Content-Type": "application/json; charset=UTF-8" + }, + "body": "@templates/faker.json.j2" + } + } + ] + } + ] +} diff --git a/tests/configs/json/j2/core/templates/faker.json.j2 b/tests/configs/json/j2/core/templates/faker.json.j2 new file mode 100644 index 000000000..7c6ac9395 --- /dev/null +++ b/tests/configs/json/j2/core/templates/faker.json.j2 @@ -0,0 +1,61 @@ +{ + "bothify": "{{ fake.bothify() }}", + "bothify_args": "{{ fake.bothify(text="## ??", letters="ABCDE") }}", + "hexify": "{{ fake.hexify() }}", + "hexify_args": "{{ fake.hexify(text="MAC Address: ^^:^^:^^:^^:^^:^^", upper=True) }}", + "language_code": "{{ fake.language_code() }}", + "lexify": "{{ fake.lexify() }}", + "lexify_args": "{{ fake.lexify(text="Random Identifier: ??????????") }}", + "locale": "{{ fake.locale() }}", + "numerify": "{{ fake.numerify() }}", + "numerify_args": "{{ fake.numerify(text="Intel Core i%-%%##K vs AMD Ryzen % %%##X") }}", + "random_choices": {{ fake.random_choices(elements=['a', 'b', 'c', 'd', 'e']) | tojson }}, + "random_digit": {{ fake.random_digit() }}, + "random_digit_not_null": {{ fake.random_digit_not_null() }}, + "random_digit_not_null_or_empty": "{{ fake.random_digit_not_null_or_empty() }}", + "random_digit_or_empty": "{{ fake.random_digit_or_empty() }}", + "random_element": "{{ fake.random_element(elements=['a', 'b', 'c', 'd', 'e']) }}", + "random_elements": {{ fake.random_elements(elements=['a', 'b', 'c', 'd', 'e'], length=3, unique=True) | tojson }}, + "random_int": {{ fake.random_int() }}, + "random_int_args": {{ fake.random_int(min=10000, max=50000, step=500) }}, + "random_letter": "{{ fake.random_letter() }}", + "random_letters": {{ fake.random_letters() | tojson }}, + "random_letters_args": {{ fake.random_letters(length=32) | tojson }}, + "random_lowercase_letter": "{{ fake.random_lowercase_letter() }}", + "random_number": {{ fake.random_number() }}, + "random_number_args": {{ fake.random_number(digits=None, fix_len=True) }}, + "random_sample": {{ fake.random_sample(elements=['a', 'b', 'c', 'd', 'e']) | tojson }}, + "random_uppercase_letter": "{{ fake.random_uppercase_letter() }}", + "randomize_nb_elements": "{{ fake.randomize_nb_elements(number=79, le=true, ge=true, min=80) }}", + "first_name": "{{ fake.first_name() }}", + "first_name_female": "{{ fake.first_name_female() }}", + "first_name_male": "{{ fake.first_name_male() }}", + "first_name_nonbinary": "{{ fake.first_name_nonbinary() }}", + "language_name": "{{ fake.language_name() }}", + "last_name": "{{ fake.last_name() }}", + "last_name_female": "{{ fake.last_name_female() }}", + "last_name_male": "{{ fake.last_name_male() }}", + "last_name_nonbinary": "{{ fake.last_name_nonbinary() }}", + "name": "{{ fake.name() }}", + "name_female": "{{ fake.name_female() }}", + "name_male": "{{ fake.name_male() }}", + "name_nonbinary": "{{ fake.name_nonbinary() }}", + "prefix": "{{ fake.prefix() }}", + "prefix_female": "{{ fake.prefix_female() }}", + "prefix_male": "{{ fake.prefix_male() }}", + "prefix_nonbinary": "{{ fake.prefix_nonbinary() }}", + "suffix": "{{ fake.suffix() }}", + "suffix_female": "{{ fake.suffix_female() }}", + "suffix_male": "{{ fake.suffix_male() }}", + "suffix_nonbinary": "{{ fake.suffix_nonbinary() }}", + "address": "{{ fake.address() | replace('\n','\\n') }}", + "city": "{{ fake.city() }}", + "city_suffix": "{{ fake.city_suffix() }}", + "country": "{{ fake.country() }}", + "country_code": "{{ fake.country_code() }}", + "postcode": "{{ fake.postcode() }}", + "street_address": "{{ fake.street_address() }}", + "street_name": "{{ fake.street_name() }}", + "street_suffix": "{{ fake.street_suffix() }}", + "license_plate": "{{ fake.license_plate() }}" +} diff --git a/tests/configs/yaml/hbs/common/templates/companies.json.hbs b/tests/configs/yaml/hbs/common/templates/companies.json.hbs index 76505899b..2f7ee2883 100644 --- a/tests/configs/yaml/hbs/common/templates/companies.json.hbs +++ b/tests/configs/yaml/hbs/common/templates/companies.json.hbs @@ -1,8 +1,8 @@ { "companies": [ { - "name": "{{ fake "company" }}", - "motto": "{{ fake "catch_phrase" }}" + "name": "{{ fake.company }}", + "motto": "{{ fake.catch_phrase }}" } ], "total": 2 diff --git a/tests/configs/yaml/hbs/common/templates/user.json.hbs b/tests/configs/yaml/hbs/common/templates/user.json.hbs index b761be4fc..d0e20336c 100644 --- a/tests/configs/yaml/hbs/common/templates/user.json.hbs +++ b/tests/configs/yaml/hbs/common/templates/user.json.hbs @@ -1,7 +1,7 @@ { "id": {{ id }}, - "firstName": "{{ fake "first_name" }}", - "lastName": "{{ fake "last_name" }}", + "firstName": "{{ fake.first_name }}", + "lastName": "{{ fake.last_name }}", "friends": [ { "id": "{{ random.uuid4 }}" diff --git a/tests/configs/yaml/hbs/common/templates/users.json.hbs b/tests/configs/yaml/hbs/common/templates/users.json.hbs index ca5dc4b16..82248bb93 100644 --- a/tests/configs/yaml/hbs/common/templates/users.json.hbs +++ b/tests/configs/yaml/hbs/common/templates/users.json.hbs @@ -2,8 +2,8 @@ "users": [ { "id": {{ random.int 10000 100000 }}, - "firstName": "{{ fake "first_name" }}", - "lastName": "{{ fake "last_name" }}", + "firstName": "{{ fake.first_name }}", + "lastName": "{{ fake.last_name }}", "friends": [ { "id": "{{ random.uuid4 }}" diff --git a/tests/configs/yaml/hbs/core/escape_html.yaml b/tests/configs/yaml/hbs/core/escape_html.yaml new file mode 100644 index 000000000..857392c6d --- /dev/null +++ b/tests/configs/yaml/hbs/core/escape_html.yaml @@ -0,0 +1,8 @@ +templatingEngine: Handlebars +services: +- name: Mock for Service1 + port: 8001 + endpoints: + - path: "/endp1" + method: GET + response: "{{ escapeHtml '& < \" >' }}" diff --git a/tests/configs/yaml/j2/core/escape_html.yaml b/tests/configs/yaml/j2/core/escape_html.yaml new file mode 100644 index 000000000..5f823c582 --- /dev/null +++ b/tests/configs/yaml/j2/core/escape_html.yaml @@ -0,0 +1,8 @@ +templatingEngine: Jinja2 +services: +- name: Mock for Service1 + port: 8001 + endpoints: + - path: "/endp1" + method: GET + response: "{{ escapeHtml('& < \" >') }}" diff --git a/tests/test_features.py b/tests/test_features.py index e17c560a0..64068caab 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -245,12 +245,12 @@ def test_no_templating_engine_should_default_to_handlebars(self, config): var = 'print_this' with nostdout() and nostderr(): self.mock_server_process = run_mock_server(get_config_path(config)) + resp = requests.get(SRV_8001 + '/%s' % var, headers={'Host': SRV_8001_HOST}) + assert 200 == resp.status_code + assert resp.headers['Content-Type'] == 'text/html; charset=UTF-8' if 'j2' in config: - assert self.mock_server_process.is_alive() is False + assert resp.text == '{{varname}}' else: - resp = requests.get(SRV_8001 + '/%s' % var, headers={'Host': SRV_8001_HOST}) - assert 200 == resp.status_code - assert resp.headers['Content-Type'] == 'text/html; charset=UTF-8' assert resp.text == var @pytest.mark.parametrize(('config'), [ @@ -277,11 +277,13 @@ def test_correct_templating_engine_in_response_should_render_correctly(self, con def test_no_templating_engine_in_response_should_default_to_handlebars(self, config): self.mock_server_process = run_mock_server(get_config_path(config)) resp = requests.get(SRV_8001 + '/', headers={'Host': SRV_8001_HOST}) + + assert 200 == resp.status_code + assert resp.headers['Content-Type'] == 'application/json; charset=UTF-8' + + data = resp.json() if 'j2' in config: - assert 500 == resp.status_code - else: - assert 200 == resp.status_code - assert resp.headers['Content-Type'] == 'application/json; charset=UTF-8' + assert data['hello'] == '{{ fake.first_name() }}' @pytest.mark.parametrize(('config'), [ 'configs/json/hbs/core/no_use_templating_no_templating_engine_in_response.json', @@ -292,11 +294,13 @@ def test_no_templating_engine_in_response_should_default_to_handlebars(self, con def test_no_use_templating_no_templating_engine_in_response_should_default_to_handlebars(self, config): self.mock_server_process = run_mock_server(get_config_path(config)) resp = requests.get(SRV_8001 + '/', headers={'Host': SRV_8001_HOST}) + + assert 200 == resp.status_code + assert resp.headers['Content-Type'] == 'application/json; charset=UTF-8' + + data = resp.json() if 'j2' in config: - assert 500 == resp.status_code - else: - assert 200 == resp.status_code - assert resp.headers['Content-Type'] == 'application/json; charset=UTF-8' + assert data['hello'] == '{{ fake.first_name() }}' @pytest.mark.parametrize(('config'), [ 'configs/json/hbs/core/use_templating_false_in_response.json', @@ -709,6 +713,54 @@ def test_connection_reset(self, config): except ConnectionError as e: assert str(e).split(',')[1].strip().startswith('RemoteDisconnected') + @pytest.mark.parametrize(('config'), [ + 'configs/json/hbs/core/faker.json', + 'configs/json/j2/core/faker.json' + ]) + def test_faker(self, config): + self.mock_server_process = run_mock_server(get_config_path(config)) + + resp = requests.get(SRV_8001 + '/faker') + assert 200 == resp.status_code + assert resp.headers['Content-Type'] == 'application/json; charset=UTF-8' + + data = resp.json() + assert isinstance(data['bothify'], str) and len(data['bothify']) == 5 + assert isinstance(data['bothify_args'], str) and len(data['bothify_args']) == 5 + assert isinstance(data['hexify'], str) and len(data['hexify']) == 4 + assert isinstance(data['hexify_args'], str) and len(data['hexify_args']) == 30 + assert isinstance(data['language_code'], str) and 2 <= len(data['language_code']) <= 3 + assert isinstance(data['lexify'], str) and len(data['lexify']) == 4 + assert isinstance(data['lexify_args'], str) and len(data['lexify_args']) == 29 + assert isinstance(data['lexify'], str) and len(data['lexify']) == 4 + assert isinstance(data['locale'], str) and 5 <= len(data['locale']) <= 6 + assert isinstance(data['numerify'], str) and 0 <= int(data['numerify']) <= 999 + assert isinstance(data['random_choices'][0], str) + assert 0 <= data['random_digit'] <= 9 + assert 1 <= data['random_digit_not_null'] <= 9 + assert isinstance(data['random_element'], str) + assert isinstance(data['random_elements'][0], str) + assert 0 <= data['random_int'] <= 9999 + assert 10000 <= data['random_int_args'] <= 50000 + assert isinstance(data['random_letter'], str) + assert isinstance(data['random_letters'][0], str) + assert isinstance(data['random_letters_args'][0], str) + assert data['random_lowercase_letter'].lower() == data['random_lowercase_letter'] + assert isinstance(data['random_sample'][0], str) + assert data['random_uppercase_letter'].upper() == data['random_uppercase_letter'] + + @pytest.mark.parametrize(('config'), [ + 'configs/yaml/hbs/core/escape_html.yaml', + 'configs/yaml/j2/core/escape_html.yaml' + ]) + def test_escape_html(self, config): + self.mock_server_process = run_mock_server(get_config_path(config)) + + resp = requests.get(SRV_8001 + '/endp1') + assert 200 == resp.status_code + assert resp.headers['Content-Type'] == 'text/html; charset=UTF-8' + assert resp.text == '& < " >' + @pytest.mark.parametrize(('config'), [ 'configs/json/hbs/status/status_code.json',