Skip to content

Commit 78d20ba

Browse files
committed
e2e / add {api_init.py.jina, endpoint_init.py.jinja} custom templates tests
1 parent 0da439f commit 78d20ba

File tree

7 files changed

+267
-19
lines changed

7 files changed

+267
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
my-test-api-client
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
""" Contains methods for accessing the API """
2+
3+
4+
from typing import Type
5+
6+
from my_test_api_client.api.default import DefaultEndpoints
7+
from my_test_api_client.api.tests import TestsEndpoints
8+
9+
10+
class MyTestApiClientApi:
11+
@classmethod
12+
def tests(cls) -> Type[TestsEndpoints]:
13+
return TestsEndpoints
14+
15+
@classmethod
16+
def default(cls) -> Type[DefaultEndpoints]:
17+
return DefaultEndpoints
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
""" Contains methods for accessing the API Endpoints """
2+
3+
4+
import types
5+
6+
from my_test_api_client.api.default import get_common_parameters, post_common_parameters
7+
8+
9+
class DefaultEndpoints:
10+
@classmethod
11+
def get_common_parameters(cls) -> types.ModuleType:
12+
return get_common_parameters
13+
14+
@classmethod
15+
def post_common_parameters(cls) -> types.ModuleType:
16+
return post_common_parameters
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
""" Contains methods for accessing the API Endpoints """
2+
3+
4+
import types
5+
6+
from my_test_api_client.api.tests import (
7+
defaults_tests_defaults_post,
8+
get_basic_list_of_booleans,
9+
get_basic_list_of_floats,
10+
get_basic_list_of_integers,
11+
get_basic_list_of_strings,
12+
get_user_list,
13+
int_enum_tests_int_enum_post,
14+
json_body_tests_json_body_post,
15+
no_response_tests_no_response_get,
16+
octet_stream_tests_octet_stream_get,
17+
optional_value_tests_optional_query_param,
18+
test_inline_objects,
19+
token_with_cookie_auth_token_with_cookie_get,
20+
unsupported_content_tests_unsupported_content_get,
21+
upload_file_tests_upload_post,
22+
)
23+
24+
25+
class TestsEndpoints:
26+
@classmethod
27+
def get_user_list(cls) -> types.ModuleType:
28+
"""
29+
Get a list of things
30+
"""
31+
return get_user_list
32+
33+
@classmethod
34+
def get_basic_list_of_strings(cls) -> types.ModuleType:
35+
"""
36+
Get a list of strings
37+
"""
38+
return get_basic_list_of_strings
39+
40+
@classmethod
41+
def get_basic_list_of_integers(cls) -> types.ModuleType:
42+
"""
43+
Get a list of integers
44+
"""
45+
return get_basic_list_of_integers
46+
47+
@classmethod
48+
def get_basic_list_of_floats(cls) -> types.ModuleType:
49+
"""
50+
Get a list of floats
51+
"""
52+
return get_basic_list_of_floats
53+
54+
@classmethod
55+
def get_basic_list_of_booleans(cls) -> types.ModuleType:
56+
"""
57+
Get a list of booleans
58+
"""
59+
return get_basic_list_of_booleans
60+
61+
@classmethod
62+
def upload_file_tests_upload_post(cls) -> types.ModuleType:
63+
"""
64+
Upload a file
65+
"""
66+
return upload_file_tests_upload_post
67+
68+
@classmethod
69+
def json_body_tests_json_body_post(cls) -> types.ModuleType:
70+
"""
71+
Try sending a JSON body
72+
"""
73+
return json_body_tests_json_body_post
74+
75+
@classmethod
76+
def defaults_tests_defaults_post(cls) -> types.ModuleType:
77+
"""
78+
Defaults
79+
"""
80+
return defaults_tests_defaults_post
81+
82+
@classmethod
83+
def octet_stream_tests_octet_stream_get(cls) -> types.ModuleType:
84+
"""
85+
Octet Stream
86+
"""
87+
return octet_stream_tests_octet_stream_get
88+
89+
@classmethod
90+
def no_response_tests_no_response_get(cls) -> types.ModuleType:
91+
"""
92+
No Response
93+
"""
94+
return no_response_tests_no_response_get
95+
96+
@classmethod
97+
def unsupported_content_tests_unsupported_content_get(cls) -> types.ModuleType:
98+
"""
99+
Unsupported Content
100+
"""
101+
return unsupported_content_tests_unsupported_content_get
102+
103+
@classmethod
104+
def int_enum_tests_int_enum_post(cls) -> types.ModuleType:
105+
"""
106+
Int Enum
107+
"""
108+
return int_enum_tests_int_enum_post
109+
110+
@classmethod
111+
def test_inline_objects(cls) -> types.ModuleType:
112+
"""
113+
Test Inline Objects
114+
"""
115+
return test_inline_objects
116+
117+
@classmethod
118+
def optional_value_tests_optional_query_param(cls) -> types.ModuleType:
119+
"""
120+
Test optional query parameters
121+
"""
122+
return optional_value_tests_optional_query_param
123+
124+
@classmethod
125+
def token_with_cookie_auth_token_with_cookie_get(cls) -> types.ModuleType:
126+
"""
127+
Test optional cookie parameters
128+
"""
129+
return token_with_cookie_auth_token_with_cookie_get
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
""" Contains methods for accessing the API """
2+
3+
{% macro snake_to_pascal_case(name) %}
4+
{%- for part in name.split('_') -%}
5+
{{ part | capitalize }}
6+
{%- endfor -%}
7+
{% endmacro %}
8+
9+
from typing import Type
10+
{% for tag, collection in endpoint_collections_by_tag %}
11+
from {{ package_name }}.api.{{ tag }} import {{ snake_to_pascal_case(tag) }}Endpoints
12+
{% endfor %}
13+
14+
class {{ snake_to_pascal_case(package_name) }}Api:
15+
{% for tag, collection in endpoint_collections_by_tag %}
16+
@classmethod
17+
def {{ tag }}(cls) -> Type[{{ snake_to_pascal_case(tag) }}Endpoints]:
18+
return {{ snake_to_pascal_case(tag) }}Endpoints
19+
{% endfor %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
""" Contains methods for accessing the API Endpoints """
2+
3+
{% macro snake_to_pascal_case(name) %}
4+
{%- for part in name.split('_') -%}
5+
{{ part | capitalize }}
6+
{%- endfor -%}
7+
{% endmacro %}
8+
9+
{% macro to_snake_name(name) %}
10+
{% set last_snakize = {'at': 0} %}
11+
{%- for part in name -%}
12+
{{ '_' if not loop.first and part in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' and (loop.index - last_snakize.at) > 1 and not last_snakize.update({'at': loop.index}) }}{{ part | lower }}
13+
{%- endfor -%}
14+
{% endmacro %}
15+
16+
import types
17+
{% for endpoint in endpoints %}
18+
from {{ package_name }}.api.{{ tag }} import {{ to_snake_name(endpoint.name) }}
19+
{% endfor %}
20+
21+
class {{ snake_to_pascal_case(tag) }}Endpoints:
22+
23+
{% for endpoint in endpoints %}
24+
25+
@classmethod
26+
def {{ to_snake_name(endpoint.name) }}(cls) -> types.ModuleType:
27+
{% if endpoint.description %}
28+
"""
29+
{{ endpoint.description }}
30+
"""
31+
{% elif endpoint.summary %}
32+
"""
33+
{{ endpoint.summary }}
34+
"""
35+
{% endif %}
36+
return {{ to_snake_name(endpoint.name) }}
37+
{% endfor %}

end_to_end_tests/test_end_to_end.py

+48-19
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
def _compare_directories(
1313
record: Path,
1414
test_subject: Path,
15-
expected_differences: Optional[Dict[str, str]] = None,
15+
expected_differences: Optional[Dict[str, str]] = None, #key: path relative to generated directory, value: expected generated content
16+
depth=0
1617
):
1718
first_printable = record.relative_to(Path.cwd())
1819
second_printable = test_subject.relative_to(Path.cwd())
@@ -22,28 +23,42 @@ def _compare_directories(
2223
pytest.fail(f"{first_printable} or {second_printable} was missing: {missing_files}", pytrace=False)
2324

2425
expected_differences = expected_differences or {}
25-
_, mismatch, errors = cmpfiles(record, test_subject, dc.common_files, shallow=False)
26-
mismatch = set(mismatch)
27-
28-
for file_name in mismatch | set(expected_differences.keys()):
29-
if file_name not in expected_differences:
30-
continue
31-
if file_name not in mismatch:
32-
pytest.fail(f"Expected {file_name} to be different but it was not", pytrace=False)
33-
generated = (test_subject / file_name).read_text()
34-
assert generated == expected_differences[file_name], f"Unexpected output in {file_name}"
35-
del expected_differences[file_name]
36-
mismatch.remove(file_name)
37-
38-
if mismatch:
26+
_, mismatches, errors = cmpfiles(record, test_subject, dc.common_files, shallow=False)
27+
mismatches = set(mismatches)
28+
29+
expected_path_mismatches = []
30+
for file_name in mismatches:
31+
32+
mismatch_file_path = test_subject.joinpath(file_name)
33+
for expected_differences_path in expected_differences.keys():
34+
35+
if mismatch_file_path.match(str(expected_differences_path)):
36+
37+
generated_content = (test_subject / file_name).read_text()
38+
expected_content = expected_differences[expected_differences_path]
39+
assert generated_content == expected_content, f"Unexpected output in {mismatch_file_path}"
40+
expected_path_mismatches.append(expected_differences_path)
41+
42+
for path_mismatch in expected_path_mismatches:
43+
matched_file_name = path_mismatch.name
44+
mismatches.remove(matched_file_name)
45+
del expected_differences[path_mismatch]
46+
47+
if mismatches:
3948
pytest.fail(
40-
f"{first_printable} and {second_printable} had differing files: {mismatch}, and errors {errors}",
49+
f"{first_printable} and {second_printable} had differing files: {mismatches}, and errors {errors}",
4150
pytrace=False,
4251
)
4352

4453
for sub_path in dc.common_dirs:
45-
_compare_directories(record / sub_path, test_subject / sub_path, expected_differences=expected_differences)
54+
_compare_directories(record / sub_path, test_subject / sub_path, expected_differences=expected_differences, depth=depth+1)
4655

56+
if depth == 0 and len(expected_differences.keys()) > 0:
57+
failure = "\n".join([f"Expected {path} to be different but it was not" for path in expected_differences.keys()])
58+
pytest.fail(
59+
failure,
60+
pytrace=False
61+
)
4762

4863
def run_e2e_test(extra_args=None, expected_differences=None):
4964
runner = CliRunner()
@@ -60,6 +75,7 @@ def run_e2e_test(extra_args=None, expected_differences=None):
6075

6176
if result.exit_code != 0:
6277
raise result.exception
78+
6379
_compare_directories(gr_path, output_path, expected_differences=expected_differences)
6480

6581
import mypy.api
@@ -75,7 +91,20 @@ def test_end_to_end():
7591

7692

7793
def test_custom_templates():
94+
expected_differences = {} #key: path relative to generated directory, value: expected generated content
95+
expected_difference_paths = [
96+
Path('README.md'),
97+
Path('my_test_api_client').joinpath('api', '__init__.py'),
98+
Path('my_test_api_client').joinpath('api', 'tests', '__init__.py'),
99+
Path('my_test_api_client').joinpath('api', 'default', '__init__.py'),
100+
]
101+
102+
golden_tpls_root_dir = Path(__file__).parent.joinpath('custom-templates-golden-record')
103+
for expected_difference_path in expected_difference_paths:
104+
path = Path('my-test-api-client').joinpath(expected_difference_path)
105+
expected_differences[path] = (golden_tpls_root_dir / expected_difference_path).read_text()
106+
78107
run_e2e_test(
79-
extra_args=["--custom-template-path=end_to_end_tests/test_custom_templates"],
80-
expected_differences={"README.md": "my-test-api-client"},
108+
extra_args=["--custom-template-path=end_to_end_tests/test_custom_templates/"],
109+
expected_differences=expected_differences,
81110
)

0 commit comments

Comments
 (0)