forked from daleal/zum
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request daleal#15 from daleal/master
Release version 0.0.3
- Loading branch information
Showing
14 changed files
with
336 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[run] | ||
omit = zum/constants.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[tool.poetry] | ||
name = "zum" | ||
version = "0.0.2" | ||
version = "0.0.3" | ||
description = "Stop writing scripts to test your APIs. Call them as CLIs instead." | ||
license = "MIT" | ||
authors = ["Daniel Leal <[email protected]>"] | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import os | ||
|
||
import pytest | ||
|
||
from zum.configs.core import ( | ||
retrieve_config_file, | ||
search_for_config_file, | ||
validate_configs, | ||
validate_endpoints, | ||
validate_metadata, | ||
) | ||
from zum.configs.errors import InvalidConfigFileError, MissingConfigFileError | ||
|
||
|
||
class TestSearchForConfigFile: | ||
def test_path_is_file(self, tmpdir): | ||
config_file = tmpdir.join("zum.toml") | ||
open(config_file.strpath, "a").close() | ||
search_for_config_file(config_file.strpath) | ||
|
||
def test_path_is_folder(self, tmpdir): | ||
with pytest.raises(MissingConfigFileError): | ||
config_file = tmpdir.join("zum.toml") | ||
os.mkdir(config_file.strpath) | ||
search_for_config_file(config_file.strpath) | ||
|
||
def test_path_does_not_exist(self, tmpdir): | ||
with pytest.raises(MissingConfigFileError): | ||
config_file = tmpdir.join("zum.toml") | ||
search_for_config_file(config_file.strpath) | ||
|
||
|
||
class TestRetrieveConfigFile: | ||
def setup_method(self): | ||
self.content = ( | ||
"[metadata]\n" | ||
'server = "http://localhost:8000"\n' | ||
"[endpoints.example]\n" | ||
'route = "/example"\n' | ||
'method = "get"\n' | ||
) | ||
self.parsed = { | ||
"metadata": {"server": "http://localhost:8000"}, | ||
"endpoints": {"example": {"route": "/example", "method": "get"}}, | ||
} | ||
|
||
def test_expected_retrieval(self, tmpdir): | ||
config_file = tmpdir.join("zum.toml") | ||
with open(config_file.strpath, "w") as raw_config_file: | ||
raw_config_file.write(self.content) | ||
assert retrieve_config_file(config_file.strpath) == self.parsed | ||
|
||
|
||
class TestValidateConfigs: | ||
# Just tests that a valid config passes, as the sub-methods are tested | ||
# against errors and invalid formats | ||
def setup_method(self): | ||
self.config = { | ||
"metadata": {"server": "http://localhost:8000"}, | ||
"endpoints": {"example": {"path": "/example", "method": "get"}}, | ||
} | ||
|
||
def test_valid_config(self): | ||
validate_configs(self.config) | ||
|
||
|
||
class TestValidateMetadata: | ||
def setup_method(self): | ||
self.missing = {"some-key": "some-value"} | ||
self.invalid_type = {"some-key": "some-value", "metadata": "nice"} | ||
self.missing_server = { | ||
"some-key": "some-value", | ||
"metadata": {"some-thing": "some-value"}, | ||
} | ||
|
||
def test_missing_metadata_key(self): | ||
with pytest.raises(InvalidConfigFileError) as excinfo: | ||
validate_metadata(self.missing) | ||
assert "Missing 'metadata' section" in str(excinfo.value) | ||
|
||
def test_invalid_endpoints_key_type(self): | ||
with pytest.raises(InvalidConfigFileError) as excinfo: | ||
validate_metadata(self.invalid_type) | ||
assert ("The 'metadata' section shold be a dictionary or mapping") in str( | ||
excinfo.value | ||
) | ||
|
||
def test_empty_endpoints_key(self): | ||
with pytest.raises(InvalidConfigFileError) as excinfo: | ||
validate_metadata(self.missing_server) | ||
assert "Missing 'server' value from the 'metadata' section" in str( | ||
excinfo.value | ||
) | ||
|
||
|
||
class TestValidateEndpoints: | ||
def setup_method(self): | ||
self.missing = {"some-key": "some-value"} | ||
self.invalid_type = {"some-key": "some-value", "endpoints": "nice"} | ||
self.empty = {"some-key": "some-value", "endpoints": {}} | ||
|
||
def test_missing_endpoints_key(self): | ||
with pytest.raises(InvalidConfigFileError) as excinfo: | ||
validate_endpoints(self.missing) | ||
assert "Missing 'endpoints' section" in str(excinfo.value) | ||
|
||
def test_invalid_endpoints_key_type(self): | ||
with pytest.raises(InvalidConfigFileError) as excinfo: | ||
validate_endpoints(self.invalid_type) | ||
assert ("The 'endpoints' section shold be a dictionary or mapping") in str( | ||
excinfo.value | ||
) | ||
|
||
def test_empty_endpoints_key(self): | ||
with pytest.raises(InvalidConfigFileError) as excinfo: | ||
validate_endpoints(self.empty) | ||
assert "At least one endpoint is required" in str(excinfo.value) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import pytest | ||
|
||
from zum.requests.core import generate_request, reduce_arguments | ||
from zum.requests.errors import MissingEndpointParamsError | ||
from zum.requests.models import Request | ||
|
||
|
||
class TestReduceArguments: | ||
def setup_method(self): | ||
self.keys = ["first", "second", "third"] | ||
self.short_args = [1, 2] | ||
self.perfect_args = [1, 2, 3] | ||
self.long_args = [1, 2, 3, 4, 5] | ||
self.output = { | ||
"perfect": { | ||
"processed": {"first": 1, "second": 2, "third": 3}, | ||
"remaining": [], | ||
}, | ||
"long": { | ||
"processed": {"first": 1, "second": 2, "third": 3}, | ||
"remaining": [4, 5], | ||
}, | ||
} | ||
|
||
def test_empty_keys(self): | ||
processed, remaining = reduce_arguments(None, self.perfect_args) | ||
assert processed == {} | ||
assert remaining == self.perfect_args | ||
|
||
def test_short_args(self): | ||
with pytest.raises(MissingEndpointParamsError): | ||
processed, remaining = reduce_arguments(self.keys, self.short_args) | ||
|
||
def test_perfect_args(self): | ||
processed, remaining = reduce_arguments(self.keys, self.perfect_args) | ||
assert processed == self.output["perfect"]["processed"] | ||
assert remaining == self.output["perfect"]["remaining"] | ||
|
||
def test_long_args(self): | ||
processed, remaining = reduce_arguments(self.keys, self.long_args) | ||
assert processed == self.output["long"]["processed"] | ||
assert remaining == self.output["long"]["remaining"] | ||
|
||
|
||
class TestGenerateRequest: | ||
def setup_method(self): | ||
self.raw_endpoint = { | ||
"route": "/example/{id}?query={query}", | ||
"method": "post", | ||
"params": ["id", "query"], | ||
"body": ["name", "city"], | ||
} | ||
self.params = {"id": 69, "query": "nais"} | ||
self.body = {"name": "Dani", "city": "Barcelona"} | ||
self.arguments = [ | ||
self.params["id"], | ||
self.params["query"], | ||
self.body["name"], | ||
self.body["city"], | ||
] | ||
self.expected_route = ( | ||
f"/example/{self.params['id']}?query={self.params['query']}" | ||
) | ||
|
||
def test_request_generation(self): | ||
request = generate_request(self.raw_endpoint, self.arguments) | ||
assert isinstance(request, Request) | ||
assert request.params == self.params | ||
assert request.body == self.body | ||
assert request.route == self.expected_route |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from zum.requests.models import Request | ||
|
||
|
||
class TestRequestModel: | ||
def setup_method(self): | ||
self.simple = {"route": "/example", "method": "get", "params": {}, "body": {}} | ||
self.complex = { | ||
"route": "/example/{id}?query={query}", | ||
"method": "get", | ||
"params": {"query": "nais", "id": 69}, | ||
"body": {}, | ||
} | ||
self.simple_route = "/example" | ||
self.complex_route = ( | ||
f"/example/{self.complex['params']['id']}" | ||
f"?query={self.complex['params']['query']}" | ||
) | ||
|
||
def test_simple_request_route_interpolation(self): | ||
request = Request(**self.simple) | ||
assert request.route == self.simple_route | ||
|
||
def test_complex_request_route_interpolation(self): | ||
request = Request(**self.complex) | ||
assert request.route == self.complex_route |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import pytest | ||
|
||
from zum.requests.errors import InvalidEndpointDefinitionError | ||
from zum.requests.validations import ( | ||
validate_raw_endpoint, | ||
validate_raw_endpoint_method, | ||
validate_raw_endpoint_route, | ||
) | ||
|
||
|
||
class TestRawEndpointValidation: | ||
# Just tests that a valid raw endpont passes, as the sub-methods are | ||
# tested against errors and invalid formats | ||
def setup_method(self): | ||
self.raw_endpoint = {"method": "get", "route": "/valid"} | ||
|
||
def test_valid_raw_endpoint(self): | ||
validate_raw_endpoint(self.raw_endpoint) | ||
|
||
|
||
class TestRawEndpointRouteValidation: | ||
def setup_method(self): | ||
self.missing = {"some": "thing"} | ||
self.invalid_type = {"route": 4} | ||
self.valid = {"route": "/valid"} | ||
|
||
def test_missing_route(self): | ||
with pytest.raises(InvalidEndpointDefinitionError) as excinfo: | ||
validate_raw_endpoint_route(self.missing) | ||
assert "Missing 'route' attribute" in str(excinfo.value) | ||
|
||
def test_invalid_type_route(self): | ||
with pytest.raises(InvalidEndpointDefinitionError) as excinfo: | ||
validate_raw_endpoint_route(self.invalid_type) | ||
assert "The 'route' attribute of the endpoint must be a string" in str( | ||
excinfo.value | ||
) | ||
|
||
def test_valid_route(self): | ||
validate_raw_endpoint_route(self.valid) | ||
|
||
|
||
class TestRawEndpointMethodValidation: | ||
def setup_method(self): | ||
self.missing = {"some": "thing"} | ||
self.invalid_type = {"method": 4} | ||
self.invalid_content = {"method": "not valid"} | ||
self.spaced_valid = {"method": " get "} | ||
self.uppercased_valid = {"method": "GET"} | ||
|
||
def test_missing_method(self): | ||
with pytest.raises(InvalidEndpointDefinitionError) as excinfo: | ||
validate_raw_endpoint_method(self.missing) | ||
assert "Missing 'method' attribute" in str(excinfo.value) | ||
|
||
def test_invalid_type_method(self): | ||
with pytest.raises(InvalidEndpointDefinitionError) as excinfo: | ||
validate_raw_endpoint_method(self.invalid_type) | ||
assert "The 'method' attribute for the endpoint must be a string" in str( | ||
excinfo.value | ||
) | ||
|
||
def test_invalid_content_method(self): | ||
with pytest.raises(InvalidEndpointDefinitionError) as excinfo: | ||
validate_raw_endpoint_method(self.invalid_content) | ||
assert ( | ||
"Invalid 'method' value for the endpoint (not a valid HTTP method)" | ||
in str(excinfo.value) | ||
) | ||
|
||
def test_spaced_valid_method(self): | ||
validate_raw_endpoint_method(self.spaced_valid) | ||
|
||
def test_uppercased_valid_method(self): | ||
validate_raw_endpoint_method(self.uppercased_valid) |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.