Skip to content

Commit d181b42

Browse files
committed
Implement tests for JSON Schema on list and dict types in the Json parameter type
1 parent 70476ba commit d181b42

File tree

4 files changed

+201
-0
lines changed

4 files changed

+201
-0
lines changed

flask_parameter_validation/test/test_json_params.py

+106
Original file line numberDiff line numberDiff line change
@@ -881,3 +881,109 @@ def test_max_list_length(client):
881881
# Test that above length yields error
882882
r = client.post(url, json={"v": ["the", "longest", "of", "lists"]})
883883
assert "error" in r.json
884+
885+
886+
def test_list_json_schema(client):
887+
url = "/json/list/json_schema"
888+
# Test that passing schema validation yields input
889+
v = [{"user_id": 1, "first_name": "John", "last_name": "Doe", "tags": ["test_account"]}]
890+
r = client.post(url, json={"v": v})
891+
assert type(r.json["v"]) is list
892+
assert len(r.json["v"]) == 1
893+
assert type(r.json["v"][0]) is dict
894+
assert v[0] == r.json["v"][0]
895+
# Test that failing schema validation yields error
896+
v = [{"user_id": 1, "first_name": "John", "last_name": "Doe"}]
897+
r = client.post(url, json={"v": v})
898+
assert "error" in r.json
899+
900+
901+
def test_required_dict(client):
902+
url = "/json/dict/required"
903+
# Test that dict yields input
904+
v = {"a": "b"}
905+
r = client.post(url, json={"v": v})
906+
assert "v" in r.json
907+
assert type(r.json["v"]) is dict
908+
assert v == r.json["v"]
909+
# Test that non-dict yields error
910+
r = client.post(url, json={"v": "a"})
911+
assert "error" in r.json
912+
913+
914+
def test_optional_dict(client):
915+
url = "/json/dict/optional"
916+
# Test that dict yields input
917+
v = {"a": "b"}
918+
r = client.post(url, json={"v": v})
919+
assert "v" in r.json
920+
assert type(r.json["v"]) is dict
921+
assert v == r.json["v"]
922+
# Test that non-dict yields error
923+
r = client.post(url, json={"v": "a"})
924+
assert "error" in r.json
925+
# Test that no input yields None
926+
r = client.post(url)
927+
assert "v" in r.json
928+
assert r.json["v"] is None
929+
930+
931+
def test_dict_default(client):
932+
url = "/json/dict/default"
933+
# Test that present dict yields input values
934+
n_opt = {"e": "f"}
935+
opt = {"g": "h"}
936+
r = client.post(url, json={"n_opt": n_opt, "opt": opt})
937+
assert "n_opt" in r.json
938+
assert "opt" in r.json
939+
assert type(r.json["n_opt"]) is dict
940+
assert type(r.json["opt"]) is dict
941+
assert n_opt == r.json["n_opt"]
942+
assert opt == r.json["opt"]
943+
# Test that missing dict yields default values
944+
n_opt = {"a": "b"}
945+
opt = {"c": "d"}
946+
r = client.post(url)
947+
assert "n_opt" in r.json
948+
assert "opt" in r.json
949+
assert type(r.json["n_opt"]) is dict
950+
assert type(r.json["opt"]) is dict
951+
assert n_opt == r.json["n_opt"]
952+
assert opt == r.json["opt"]
953+
954+
955+
def test_dict_func(client):
956+
url = "/json/dict/func"
957+
# Test that dict passing func yields input value
958+
v = {"a": "b", "c": "d"}
959+
r = client.post(url, json={"v": v})
960+
assert "v" in r.json
961+
assert type(r.json["v"]) is dict
962+
assert v == r.json["v"]
963+
# Test that dict failing func yields error
964+
v = {"A": "B", "C": "D"}
965+
r = client.post(url, json={"v": v})
966+
assert "error" in r.json
967+
968+
969+
def test_dict_json_schema(client):
970+
url = "/json/dict/json_schema"
971+
# Test that dict passing schema yields input value
972+
v = {
973+
"user_id": 1,
974+
"first_name": "John",
975+
"last_name": "Doe",
976+
"tags": []
977+
}
978+
r = client.post(url, json={"v": v})
979+
assert "v" in r.json
980+
assert type(r.json["v"]) is dict
981+
assert v == r.json["v"]
982+
# Test that dict failing schema yields error
983+
v = {
984+
"user_id": 1,
985+
"first_name": "John",
986+
"last_name": "Doe"
987+
}
988+
r = client.post(url, json={"v": v})
989+
assert "error" in r.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import datetime
2+
from typing import Optional, List, Union
3+
4+
from flask import Blueprint, jsonify
5+
6+
from flask_parameter_validation import ValidateParameters, Route
7+
from flask_parameter_validation.parameter_types.parameter import Parameter
8+
9+
10+
def get_dict_blueprint(ParamType: type[Parameter], bp_name: str, http_verb: str) -> Blueprint:
11+
dict_bp = Blueprint(bp_name, __name__, url_prefix="/dict")
12+
decorator = getattr(dict_bp, http_verb)
13+
14+
# dict not currently supported by Route
15+
# def path(base: str, route_additions: str) -> str:
16+
# return base + (route_additions if ParamType is Route else "")
17+
18+
@decorator("/required")
19+
@ValidateParameters()
20+
def req_str(v: dict = ParamType()):
21+
assert type(v) is dict
22+
return jsonify({"v": v})
23+
24+
@decorator("/optional")
25+
@ValidateParameters()
26+
def optional(v: Optional[dict] = ParamType()):
27+
return jsonify({"v": v})
28+
29+
@decorator("/default")
30+
@ValidateParameters()
31+
def default(
32+
n_opt: dict = ParamType(default={"a": "b"}),
33+
opt: dict = ParamType(default={"c": "d"})
34+
):
35+
return jsonify({
36+
"n_opt": n_opt,
37+
"opt": opt
38+
})
39+
40+
def are_keys_lowercase(v):
41+
assert type(v) is dict
42+
for key in v.keys():
43+
if not key.islower():
44+
return False
45+
return True
46+
47+
@decorator("/func")
48+
@ValidateParameters()
49+
def func(v: dict = ParamType(func=are_keys_lowercase)):
50+
return jsonify({"v": v})
51+
52+
json_schema = {
53+
"type": "object",
54+
"required": ["user_id", "first_name", "last_name", "tags"],
55+
"properties": {
56+
"user_id": {"type": "integer"},
57+
"first_name": {"type": "string"},
58+
"last_name": {"type": "string"},
59+
"tags": {
60+
"type": "array",
61+
"items": {"type": "string"}
62+
}
63+
}
64+
}
65+
66+
@decorator("/json_schema")
67+
@ValidateParameters()
68+
def json_schema(v: dict = ParamType(json_schema=json_schema)):
69+
return jsonify({"v": v})
70+
71+
return dict_bp

flask_parameter_validation/test/testing_blueprints/list_blueprint.py

+22
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,26 @@ def min_list_length(v: List[str] = ParamType(min_list_length=3)):
104104
def max_list_length(v: List[str] = ParamType(max_list_length=3)):
105105
return jsonify({"v": v})
106106

107+
json_schema = {
108+
"type": "array",
109+
"items": {
110+
"type": "object",
111+
"required": ["user_id", "first_name", "last_name", "tags"],
112+
"properties": {
113+
"user_id": {"type": "integer"},
114+
"first_name": {"type": "string"},
115+
"last_name": {"type": "string"},
116+
"tags": {
117+
"type": "array",
118+
"items": {"type": "string"}
119+
}
120+
}
121+
}
122+
}
123+
124+
@decorator("/json_schema")
125+
@ValidateParameters()
126+
def json_schema(v: list = ParamType(json_schema=json_schema)):
127+
return jsonify({"v": v})
128+
107129
return list_bp

flask_parameter_validation/test/testing_blueprints/parameter_blueprint.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from flask_parameter_validation.test.testing_blueprints.bool_blueprint import get_bool_blueprint
55
from flask_parameter_validation.test.testing_blueprints.date_blueprint import get_date_blueprint
66
from flask_parameter_validation.test.testing_blueprints.datetime_blueprint import get_datetime_blueprint
7+
from flask_parameter_validation.test.testing_blueprints.dict_blueprint import get_dict_blueprint
78
from flask_parameter_validation.test.testing_blueprints.float_blueprint import get_float_blueprint
89
from flask_parameter_validation.test.testing_blueprints.int_blueprint import get_int_blueprint
910
from flask_parameter_validation.test.testing_blueprints.list_blueprint import get_list_blueprint
@@ -25,4 +26,5 @@ def get_parameter_blueprint(ParamType: type[Parameter], bp_name: str, param_name
2526
param_bp.register_blueprint(get_datetime_blueprint(ParamType, f"{bp_name}_datetime", http_verb))
2627
param_bp.register_blueprint(get_date_blueprint(ParamType, f"{bp_name}_date", http_verb))
2728
param_bp.register_blueprint(get_time_blueprint(ParamType, f"{bp_name}_time", http_verb))
29+
param_bp.register_blueprint(get_dict_blueprint(ParamType, f"{bp_name}_dict", http_verb))
2830
return param_bp

0 commit comments

Comments
 (0)