Skip to content

Commit

Permalink
#1 and parse landing page.
Browse files Browse the repository at this point in the history
  • Loading branch information
ways committed Sep 25, 2024
1 parent b547299 commit 05ebc75
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 35 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ FAILED sedr/schemat.py::test_conformance[GET /conformance] - AssertionError: Con
======================== 1 failed, 21 passed in 95.89s (0:01:35) =========================
```
### Components
Main components of the validator are:
Expand All @@ -150,7 +149,8 @@ Main components of the validator are:
## How to contribute
Create an issue or start a discussion. Please do not contriute without discussing it first.
Create an issue or start a discussion. Please do not contriute without
discussing it first.
## Documentation Template
Expand Down
6 changes: 3 additions & 3 deletions sedr/edreq11.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
]


def requirementA2_2_A5(jsondata: json) -> (bool, str):
def requirementA2_2_A5(jsondata: str) -> tuple[bool, str]:
"""Check if the conformance page contains the required EDR classes.
jsondata should be the "conformsTo"-part of the conformance page.
Expand All @@ -31,7 +31,7 @@ def requirementA2_2_A5(jsondata: json) -> (bool, str):
return True, ""


def requirementA2_2_A7(version: int) -> (bool, str):
def requirementA2_2_A7(version: int) -> tuple[bool, str]:
"""Check if HTTP1.1 was used."""
spec_url = "https://docs.ogc.org/is/19-086r6/19-086r6.html#_0d0c25a0-850f-2aa5-9acb-06efcc04d452"
if version == 11:
Expand All @@ -40,7 +40,7 @@ def requirementA2_2_A7(version: int) -> (bool, str):
return False, f"HTTP version 1.1 was not used. See <{spec_url}> for more info."


def requirementA11_1(jsondata: json) -> (bool, str):
def requirementA11_1(jsondata: str) -> tuple[bool, str]:
"""Check if the conformance page contains openapi classes, and that they match our version."""
spec_url = "https://docs.ogc.org/is/19-086r6/19-086r6.html#_cc7dd5e3-1d54-41ff-b5ba-c5fcb99fa663"

Expand Down
44 changes: 19 additions & 25 deletions sedr/schemat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ def set_up_schemathesis(args):
"""Set up schemathesis."""
if args.openapi_version == "3.1":
schemathesis.experimental.OPEN_API_3_1.enable()

if args.openapi == "":
# Attempt to find schema automatically
args.openapi = util.locate_openapi_url(args.url)
if len(args.openapi) == 0:
raise AssertionError(
f"Unable to find openapi spec for API. Please supply manually with --openapi <url>"
)
util.logger.info("Found openapi spec: %s", args.openapi)
return schemathesis.from_uri(args.openapi, base_url=args.url)


Expand Down Expand Up @@ -67,34 +76,19 @@ def test_landingpage(case):
"""Test that the landing page contains required elements."""
spec_ref = "https://docs.ogc.org/is/19-072/19-072.html#_7c772474-7037-41c9-88ca-5c7e95235389"
response = case.call()
landingpage_json = None
try:
landingpage_json = json.loads(response.text)
landing, landing_message = util.parse_landing_json(landingpage_json)
if not landing:
raise AssertionError(
f"Landing page is missing required elements. See <{spec_ref}> for more info. {landing_message}"
)

util.logger.debug("Landingpage %s tested OK", response.url)
except json.decoder.JSONDecodeError as e:
util.logger.error("Landing page is not valid JSON.")
raise AssertionError(
f"Expected valid JSON but got {e}. See {spec_ref} for more info."
) from e

if "title" not in landingpage_json:
util.logger.warning("Landing page does not contain a title.")
if "description" not in landingpage_json:
util.logger.warning("Landing page does not contain a description.")
assert (
"links" in landingpage_json
), "Landing page does not contain links. See {spec_ref} for more info."
for link in landingpage_json["links"]:
assert isinstance(
link, dict
), f"Link {link} is not a dictionary. See {spec_ref} for more info."
assert (
"href" in link
), f"Link {link} does not have a href attribute. See {spec_ref} for more info."
assert (
"rel" in link
), f"Link {link} does not have a rel attribute. See {spec_ref} for more info."

util.logger.debug("Landingpage %s tested OK", response.url)
util.logger.warning(
"Landing page is not valid JSON, other formats are not tested yet."
)


@schema.include(path_regex="^" + util.args.base_path + "conformance").parametrize()
Expand Down
49 changes: 44 additions & 5 deletions sedr/util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import logging
import requests
import schemathesis
import argparse
import json
Expand All @@ -14,13 +15,12 @@
def parse_args() -> argparse.Namespace:
"""Parse arguments."""
parser = argparse.ArgumentParser(description="schemathesis-edr")
parser.add_argument("-v", "--version", action='version',
version=f'{__version__}')
parser.add_argument("-v", "--version", action="version", version=f"{__version__}")
parser.add_argument(
"--openapi",
type=str,
help="URL to openapi spec for API",
default="https://edrisobaric.k8s.met.no/api",
default="",
)
parser.add_argument(
"--url", type=str, help="URL to API", default="https://edrisobaric.k8s.met.no"
Expand Down Expand Up @@ -116,9 +116,8 @@ def parse_locations(jsondata):
# )


def test_conformance_links(jsondata):
def test_conformance_links(jsondata): # pylint: disable=unused-argument
"""Test that all conformance links are valid and resolves.
TODO: http://www.opengis.net/spec/ogcapi-common-2/1.0/conf/collections doesn't work, so postponing this.
"""

Expand All @@ -136,5 +135,45 @@ def test_conformance_links(jsondata):
return True, ""


def parse_landing_json(jsondata) -> tuple[bool, str]:
"""Parse landing page if it is valid JSON."""
# See https://github.com/metno/sedr/issues/6
if "title" not in jsondata:
return False, "Landing page does not contain a title."
if "description" not in jsondata:
util.logger.warning("Landing page does not contain a description.")
if "links" not in jsondata:
return False, "Landing page does not contain links."
for link in jsondata["links"]:
if not isinstance(link, dict):
return False, f"Link {link} is not a dictionary."
if "href" not in link:
return False, f"Link {link} does not have a href attribute."
if "rel" not in link:
return False, f"Link {link} does not have a rel attribute."
return True, ""


def locate_openapi_url(url: str) -> str:
"""Locate the OpenAPI URL based on main URL."""
request = requests.get(url, timeout=10)

# Json
# See https://github.com/metno/sedr/issues/6
try:
if request.json():
for link in request.json()["links"]:
if link["rel"] == "service-desc":
return link["href"]
except json.JSONDecodeError:
pass

# TODO:
# Html
# Yaml
# Xml
return ""


args = parse_args()
logger = set_up_logging(args=args, logfile=args.log_file)

0 comments on commit 05ebc75

Please sign in to comment.