diff --git a/APIDOCS.apiary b/APIDOCS.apiary index 775dbc5..2e84ea5 100644 --- a/APIDOCS.apiary +++ b/APIDOCS.apiary @@ -87,7 +87,7 @@ Retrieve a single `Result` based on the `id`. "testcase": { "name": "dist.rpmlint", "ref_url": "https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" }, "note": "0 errors, 30 warnings", "ref_url": "https://taskotron-dev.fedoraproject.org/artifacts/all/27f94e36-62ec-11e6-83fd-525400d7d6a4/task_output/koschei-1.7.2-1.fc24.log", @@ -98,7 +98,7 @@ Retrieve a single `Result` based on the `id`. "type": ["koji_build"], "arch": ["x86_64","noarch"] }, - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" } + Response 404 (application/json) @@ -153,7 +153,7 @@ Examples are provided in the Parameters section of the documentation. + Response 200 (application/json) { - "next":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?item:like=koschei*fc24*&outcome=PASSED,FAILED&since=2016-08-15T13:00:00,2016-08-15T13:30:00&page=1", + "next":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?item:like=koschei*fc24*&outcome=PASSED,FAILED&since=2016-08-15T13:00:00,2016-08-15T13:30:00&page=1", "prev":null, "data":[ { @@ -162,7 +162,7 @@ Examples are provided in the Parameters section of the documentation. "testcase":{ "name":"dist.rpmlint", "ref_url":"https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" }, "groups":["27f94e36-62ec-11e6-83fd-525400d7d6a4"], "note":"0 errors, 30 warnings", @@ -173,7 +173,7 @@ Examples are provided in the Parameters section of the documentation. "type":["koji_build"], "arch":["x86_64","noarch"] }, - "href":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" + "href":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" } ] } @@ -225,7 +225,7 @@ An additional available parameter is `_distinct_on`, if specified allows the use "testcase":{ "name":"dist.rpmlint", "ref_url":"https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" }, "groups":["27f94e36-62ec-11e6-83fd-525400d7d6a4"], "note":"0 errors, 30 warnings", @@ -236,7 +236,7 @@ An additional available parameter is `_distinct_on`, if specified allows the use "type":["koji_build"], "arch":["x86_64","noarch"] }, - "href":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" + "href":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" } ] } @@ -290,7 +290,7 @@ When a new `Result` is created, it is assigned an unique `id` and `submit_time` "testcase":{ "name":"dist.rpmlint", "ref_url":"https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" }, "groups":["27f94e36-62ec-11e6-83fd-525400d7d6a4"], "note":"0 errors, 30 warnings", @@ -301,7 +301,7 @@ When a new `Result` is created, it is assigned an unique `id` and `submit_time` "type":["koji_build"], "arch":["x86_64","noarch"] }, - "href":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" + "href":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989" } + Response 400 (application/json) @@ -349,9 +349,9 @@ Retrieve a single `Group` based on the `uuid`. "uuid": "27f94e36-62ec-11e6-83fd-525400d7d6a4", "description": "Taskotron job on koji_build koschei-1.7.2-1.fc24", "ref_url": "https://taskotron-dev.fedoraproject.org/execdb/jobs/27f94e36-62ec-11e6-83fd-525400d7d6a4", - "results": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4", + "results": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4", "results_count": 1, - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4" } @@ -381,16 +381,16 @@ Collection of all the `Groups`. + Response 200 (application/json) { - "next":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups?page=1", + "next":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups?page=1", "prev":null, "data":[ { "uuid": "27f94e36-62ec-11e6-83fd-525400d7d6a4", "description": "Taskotron job on koji_build koschei-1.7.2-1.fc24", "ref_url": "https://taskotron-dev.fedoraproject.org/execdb/jobs/27f94e36-62ec-11e6-83fd-525400d7d6a4", - "results": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4", + "results": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4", "results_count": 1, - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4" } ] } @@ -426,9 +426,9 @@ the new `description` or `ref_url`, if set in the JSON data. "uuid": "27f94e36-62ec-11e6-83fd-525400d7d6a4", "description": "Taskotron job on koji_build koschei-1.7.2-1.fc24", "ref_url": "https://taskotron-dev.fedoraproject.org/execdb/jobs/27f94e36-62ec-11e6-83fd-525400d7d6a4", - "results": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4", + "results": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4", "results_count": 0, - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4" } @@ -467,7 +467,7 @@ Retrieve a single `Testcase` based on the `name`. { "name": "dist.rpmlint", "ref_url": "https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" } + Response 404 (application/json) @@ -498,13 +498,13 @@ Collection of all the `Testcases`. + Response 200 (application/json) { - "next":"http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/name:like=dist.rpmlint.*&page=1", + "next":"https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/name:like=dist.rpmlint.*&page=1", "prev":null, "data":[ { "name": "dist.rpmlint", "ref_url": "https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" } ] } @@ -531,7 +531,7 @@ get updated with the new `ref_url`, if set in the JSON data. { "name": "dist.rpmlint", "ref_url": "https://fedoraproject.org/wiki/Common_Rpmlint_issues", - "href": "http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" + "href": "https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint" } @@ -554,7 +554,7 @@ get updated with the new `ref_url`, if set in the JSON data. - `27f94e36-62ec-11e6-83fd-525400d7d6a4` (string) - data (object) - Any number of key-value pairs. Used to store any additional information. In Taskotron `item` and `type` are the most common keys used to represent "what was tested". - *key* (array[string], optional) -- `href`: `http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989` (string) - Reference to self. +- `href`: `https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results/7484989` (string) - Reference to self. ## Result POST (object) - outcome (OUTCOMES, required) @@ -602,9 +602,9 @@ get updated with the new `ref_url`, if set in the JSON data. - _auth (nullable, optional) - Placeholder for the future implemantation of Authentication/Authorization ## Group GET (Group POST data) -- results: `http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4` (string) - URL to retrieve results in the `Group` via the `Result` resource +- results: `https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/results?group=27f94e36-62ec-11e6-83fd-525400d7d6a4` (string) - URL to retrieve results in the `Group` via the `Result` resource - `results_count`: 1 (number) - Amount of `Results` in the `Group` -- `href`: `http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4` (string) - Reference to self. +- `href`: `https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/groups/27f94e36-62ec-11e6-83fd-525400d7d6a4` (string) - Reference to self. ## Testcase POST data (object) @@ -617,4 +617,4 @@ get updated with the new `ref_url`, if set in the JSON data. - _auth (nullable, optional) - Placeholder for the future implemantation of Authentication/Authorization. ## Testcase GET (Testcase POST data) -- `href`: `http://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint` (string) - Reference to self. +- `href`: `https://taskotron-dev.fedoraproject.org/resultsdb_api/api/v2.0/testcases/dist.rpmlint` (string) - Reference to self. diff --git a/Dockerfile b/Dockerfile index cba90d5..0f3a74a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,7 @@ RUN set -exo pipefail \ && yum --installroot=/mnt/rootfs clean all \ && rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* \ # https://python-poetry.org/docs/master/#installing-with-the-official-installer - && curl -sSL https://install.python-poetry.org | python3 - \ + && curl -sSL --proto "=https" https://install.python-poetry.org | python3 - \ && python3 -m venv --system-site-packages /venv ENV \ diff --git a/Makefile b/Makefile index 2ec4ed8..92b9db8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Copyright 2018, Red Hat, Inc. -# License: GPL-2.0+ +# License: GPL-2.0+ # See the LICENSE file for more details on Licensing ####################################################################### diff --git a/README.md b/README.md index 5e519c6..5a8d110 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ResultsDB is a results store engine for (not only) Fedora QA tools. The API v2 documentation can be found at -. +. ## Repositories diff --git a/pyproject.toml b/pyproject.toml index 3061a21..fcdc88e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ authors = [ license = "GPL-2.0-or-later" readme = "README.md" repository = "https://github.com/release-engineering/resultsdb" -homepage = "http://docs.resultsdb20.apiary.io/" +homepage = "https://docs.resultsdb20.apiary.io/" include = [ "LICENSE", diff --git a/resultsdb/__init__.py b/resultsdb/__init__.py index 2f0ce61..a314d9e 100644 --- a/resultsdb/__init__.py +++ b/resultsdb/__init__.py @@ -54,7 +54,7 @@ def create_app(config_obj=None): app = Flask(__name__) - app.secret_key = "replace-me-with-something-random" # nosec + app.secret_key = "replace-me-with-something-random" # nosec # NOSONAR # make sure app behaves when behind a proxy app.wsgi_app = ReverseProxied(app.wsgi_app) @@ -90,7 +90,7 @@ def create_app(config_obj=None): app.config.from_pyfile(config_file) if app.config["PRODUCTION"]: - if app.secret_key == "replace-me-with-something-random": # nosec + if app.secret_key == "replace-me-with-something-random": # nosec # NOSONAR raise Warning("You need to change the app.secret_key value for production") setup_logging(app) diff --git a/resultsdb/__main__.py b/resultsdb/__main__.py index 52b34b9..ddf6857 100644 --- a/resultsdb/__main__.py +++ b/resultsdb/__main__.py @@ -101,30 +101,36 @@ def mock_data(): if not db.session.query(Testcase).count(): print(" - Testcase, Job, Result, ResultData") - tc1 = Testcase(ref_url="http://example.com/depcheck", name="depcheck") - tc2 = Testcase(ref_url="http://example.com/rpmlint", name="rpmlint") + tc1 = Testcase(ref_url="https://example.com/depcheck", name="depcheck") + tc2 = Testcase(ref_url="https://example.com/rpmlint", name="rpmlint") j1 = Group( uuid="5b3f47b4-2ba2-11e5-a343-5254007dccf9", - ref_url="http://example.com/job1", + ref_url="https://example.com/job1", ) j2 = Group( uuid="4e575b2c-2ba2-11e5-a343-5254007dccf9", - ref_url="http://example.com/job2", + ref_url="https://example.com/job2", ) r1 = Result( - groups=[j1], testcase=tc1, outcome="PASSED", ref_url="http://example.com/r1" + groups=[j1], + testcase=tc1, + outcome="PASSED", + ref_url="https://example.com/r1", ) r2 = Result( groups=[j1, j2], testcase=tc1, outcome="FAILED", - ref_url="http://example.com/r2", + ref_url="https://example.com/r2", ) r3 = Result( - groups=[j2], testcase=tc2, outcome="FAILED", ref_url="http://example.com/r2" + groups=[j2], + testcase=tc2, + outcome="FAILED", + ref_url="https://example.com/r2", ) ResultData(r1, "item", "cabal-rpm-0.8.3-1.fc18") diff --git a/resultsdb/authorization.py b/resultsdb/authorization.py index 4b3692f..c7201a2 100644 --- a/resultsdb/authorization.py +++ b/resultsdb/authorization.py @@ -6,6 +6,8 @@ log = logging.getLogger(__name__) +LDAP_ERROR = "Some error occurred initializing the LDAP connection" + def get_group_membership(ldap, user, con, ldap_search): try: @@ -23,8 +25,8 @@ def get_group_membership(ldap, user, con, ldap_search): log.exception("The LDAP server is not reachable") raise BadGateway("The LDAP server is not reachable") except ldap.LDAPError: - log.exception("Some error occurred initializing the LDAP connection") - raise BadGateway("Some error occurred initializing the LDAP connection") + log.exception(LDAP_ERROR) + raise BadGateway(LDAP_ERROR) def match_testcase_permissions(testcase, permissions): @@ -64,8 +66,8 @@ def verify_authorization(user, testcase, permissions, ldap_host, ldap_searches): try: con = ldap.initialize(ldap_host) except ldap.LDAPError: - log.exception("Some error occurred initializing the LDAP connection") - raise BadGateway("Some error occurred initializing the LDAP connection") + log.exception(LDAP_ERROR) + raise BadGateway(LDAP_ERROR) any_groups_found = False for cur_ldap_search in ldap_searches: diff --git a/resultsdb/config.py b/resultsdb/config.py index 620a0e9..10bd001 100644 --- a/resultsdb/config.py +++ b/resultsdb/config.py @@ -27,7 +27,7 @@ def db_uri_for_testing(): postgres_port = os.getenv("RESULTSDB_POSTGRES_PORT") if postgres_port: - return f"postgresql+psycopg2://resultsdb:resultsdb@localhost:{postgres_port}/resultsdb" + return f"postgresql+psycopg2://resultsdb:resultsdb@localhost:{postgres_port}/resultsdb" # NOSONAR return "sqlite:///.test_db.sqlite" @@ -37,7 +37,7 @@ class Config: DEBUG = True PRODUCTION = False - SECRET_KEY = "replace-me-with-something-random" # nosec + SECRET_KEY = "replace-me-with-something-random" # nosec # NOSONAR HOST = "127.0.0.1" PORT = 5001 diff --git a/resultsdb/controllers/api_v2.py b/resultsdb/controllers/api_v2.py index b623f9e..bceb36a 100644 --- a/resultsdb/controllers/api_v2.py +++ b/resultsdb/controllers/api_v2.py @@ -120,6 +120,23 @@ def prev_next_urls(data, limit=QUERY_LIMIT): # ============================================================================= +def add_group(grp): + if isinstance(grp, (str, bytes)): + grp = dict(uuid=grp) + elif isinstance(grp, dict): + grp["uuid"] = grp.get("uuid", str(uuid.uuid1())) + + group = Group.query.filter_by(uuid=grp["uuid"]).first() + if not group: + group = Group(uuid=grp["uuid"]) + + group.description = grp.get("description", group.description) + group.ref_url = grp.get("ref_url", group.ref_url) + + db.session.add(group) + return group + + @api.route("/groups", methods=["GET"]) @validate() def get_groups(query: GroupsParams): @@ -407,7 +424,7 @@ def get_results_latest(query: ResultsParams): jsonify( { "message": ( - "Please, provide at least one " "filter beside '_distinct_on'" + "Please, provide at least one filter beside '_distinct_on'" ) } ), @@ -508,23 +525,7 @@ def create_result_any_data(body: CreateResultParams): # when a group defined by the string is not found, new is created # group defined by the object, is updated/created with the values from the object # non-existing groups are created automatically - groups = [] - if body.groups: - for grp in body.groups: - if isinstance(grp, (str, bytes)): - grp = dict(uuid=grp) - elif isinstance(grp, dict): - grp["uuid"] = grp.get("uuid", str(uuid.uuid1())) - - group = Group.query.filter_by(uuid=grp["uuid"]).first() - if not group: - group = Group(uuid=grp["uuid"]) - - group.description = grp.get("description", group.description) - group.ref_url = grp.get("ref_url", group.ref_url) - - db.session.add(group) - groups.append(group) + groups = [add_group(group) for group in (body.groups or [])] result = Result( testcase, body.outcome, groups, body.ref_url, body.note, body.submit_time @@ -652,7 +653,7 @@ def landing_page(): "message": "Everything is fine. But choose wisely, for while " "the true Grail will bring you life, the false " "Grail will take it from you.", - "documentation": "http://docs.resultsdb20.apiary.io/", + "documentation": "https://docs.resultsdb20.apiary.io/", "groups": url_for(".get_groups", _external=True), "results": url_for(".get_results", _external=True), "testcases": url_for(".get_testcases", _external=True), diff --git a/resultsdb/proxy.py b/resultsdb/proxy.py index d84dcb3..81c9efc 100644 --- a/resultsdb/proxy.py +++ b/resultsdb/proxy.py @@ -1,11 +1,11 @@ # Copyright 2009-2014, Red Hat, Inc. -# License: GPL-2.0+ +# License: GPL-2.0+ """ Makes fedocal an application behind a reverse proxy and thus ensure the redirects are using ``https``. -Original Source: http://flask.pocoo.org/snippets/35/ by Peter Hansen +Original Source: https://flask.pocoo.org/snippets/35/ by Peter Hansen Source: https://github.com/fedora-infra/fedocal/blob/master/fedocal/proxy.py """ @@ -20,15 +20,15 @@ class ReverseProxied: RewriteEngine On - ProxyPass http://192.168.0.1:5001/ - ProxyPassReverse http://192.168.0.1:5001/ + ProxyPass https://192.168.0.1:5001/ + ProxyPassReverse https://192.168.0.1:5001/ RequestHeader set X-Forwarded-Scheme $scheme RequestHeader add X-Script-Name /myprefix/ In nginx: location /myprefix { - proxy_pass http://192.168.0.1:5001; + proxy_pass https://192.168.0.1:5001; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Scheme $scheme; diff --git a/resultsdb/templates/index.html b/resultsdb/templates/index.html index ed8f4a1..8da8895 100644 --- a/resultsdb/templates/index.html +++ b/resultsdb/templates/index.html @@ -7,7 +7,7 @@

Documentation

{% endblock %} diff --git a/resultsdb/tracing.py b/resultsdb/tracing.py index 744b8cf..616ba56 100644 --- a/resultsdb/tracing.py +++ b/resultsdb/tracing.py @@ -25,6 +25,5 @@ def setup_tracing(app, engine): # pragma: no cover endpoint=app.config["OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"] ) processor = BatchSpanProcessor(otlp_exporter) - # processor = BatchSpanProcessor(ConsoleSpanExporter()) provider.add_span_processor(processor) trace.set_tracer_provider(provider) diff --git a/tests/functest_api_v20.py b/tests/functest_api_v20.py index 8aa1c2d..834d3ee 100644 --- a/tests/functest_api_v20.py +++ b/tests/functest_api_v20.py @@ -19,7 +19,6 @@ import copy import datetime -import json import os from unittest import TestCase from unittest.mock import ANY, patch @@ -30,6 +29,36 @@ from resultsdb.models import db from resultsdb.models.results import utcnow_naive +GROUPS_API = "/api/v2.0/groups" +RESULTS_API = "/api/v2.0/results" +TESTCASES_API = "/api/v2.0/testcases" + +EMPTY_TESTCASE_ERROR = { + "validation_error": [ + { + "loc": ["testcase"], + "msg": "Value error, testcase name must be non-empty", + "type": "value_error", + "input": ANY, + "url": ANY, + } + ] +} + + +def field_required_error(field): + return { + "validation_error": [ + { + "loc": [field], + "msg": "Field required", + "type": "missing", + "input": ANY, + "url": ANY, + } + ] + } + class AboutTime: def __eq__(self, value): @@ -70,7 +99,7 @@ def setup_method(self, method): # Testcase data self.ref_testcase_name = "fedora-ci.koji-build./plans/basic.functional" self.ref_testcase_ref_url = ( - "http://example.com/fedora-ci.koji-build./plans/basic.functional" + "https://example.com/fedora-ci.koji-build./plans/basic.functional" ) self.ref_testcase = { "name": self.ref_testcase_name, @@ -81,7 +110,7 @@ def setup_method(self, method): # Group data self.ref_group_uuid = "3ce5f6d7-ce34-489b-ab61-325ce634eab5" self.ref_group_description = "Testing Group" - self.ref_group_ref_url = "http://example.com/testing.group" + self.ref_group_ref_url = "https://example.com/testing.group" self.ref_group = { "uuid": self.ref_group_uuid, "description": self.ref_group_description, @@ -104,7 +133,7 @@ def setup_method(self, method): "arch": self.ref_result_arch, "moo": ["boo", "woof"], } - self.ref_result_ref_url = "http://example.com/testing.result" + self.ref_result_ref_url = "https://example.com/testing.result" self.ref_result = { "id": self.ref_result_id, "groups": [self.ref_group["uuid"]], @@ -131,43 +160,20 @@ def helper_create_testcase(self, name=None, ref_url=None): name = self.ref_testcase_name if ref_url is None: ref_url = self.ref_testcase_ref_url - ref_data = json.dumps({"name": name, "ref_url": ref_url}) - r = self.app.post( - "/api/v2.0/testcases", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) - return r, data + return self.app.post(TESTCASES_API, json={"name": name, "ref_url": ref_url}) def test_create_testcase(self): - r, data = self.helper_create_testcase() + r = self.helper_create_testcase() assert r.status_code == 201 - assert data == self.ref_testcase + assert r.json == self.ref_testcase def test_create_testcase_missing_data(self): - ref_data = json.dumps({"ref_url": self.ref_testcase_ref_url}) - - r = self.app.post( - "/api/v2.0/testcases", data=ref_data, content_type="application/json" - ) + r = self.app.post(TESTCASES_API, json={"ref_url": self.ref_testcase_ref_url}) assert r.status_code == 400 - assert r.json == { - "validation_error": [ - { - "loc": ["name"], - "msg": "Field required", - "type": "missing", - "input": ANY, - "url": ANY, - } - ] - } + assert r.json == field_required_error("name") def test_create_testcase_empty_name(self): - ref_data = json.dumps({"name": ""}) - - r = self.app.post( - "/api/v2.0/testcases", data=ref_data, content_type="application/json" - ) + r = self.app.post(TESTCASES_API, json={"name": ""}) assert r.status_code == 400 assert r.json == { "validation_error": [ @@ -187,70 +193,58 @@ def test_update_testcase(self): testcase = copy.copy(self.ref_testcase) testcase["ref_url"] = "Updated" - ref_data = json.dumps( - {"name": self.ref_testcase_name, "ref_url": testcase["ref_url"]} - ) - - r = self.app.post( - "/api/v2.0/testcases", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + data = {"name": self.ref_testcase_name, "ref_url": testcase["ref_url"]} + r = self.app.post(TESTCASES_API, json=data) assert r.status_code == 201 - assert data == testcase + assert r.json == testcase def test_get_testcase(self): self.test_create_testcase() - r = self.app.get(f"/api/v2.0/testcases/{self.ref_testcase_name}") - - data = json.loads(r.data) - + r = self.app.get(f"{TESTCASES_API}/{self.ref_testcase_name}") assert r.status_code == 200 - assert data == self.ref_testcase + assert r.json == self.ref_testcase def test_get_missing_testcase(self): - r = self.app.get(f"/api/v2.0/testcases/{self.ref_testcase_name}") - - data = json.loads(r.data) + r = self.app.get(f"{TESTCASES_API}/{self.ref_testcase_name}") assert r.status_code == 404 - assert data["message"] == "Testcase not found" + assert r.json is not None + assert r.json["message"] == "Testcase not found" def test_get_testcases(self): - r = self.app.get("/api/v2.0/testcases") - data = json.loads(r.data) + r = self.app.get(TESTCASES_API) assert r.status_code == 200 - assert data["data"] == [] + assert r.json is not None + assert r.json["data"] == [] self.test_create_testcase() - r = self.app.get("/api/v2.0/testcases") - data = json.loads(r.data) + r = self.app.get(TESTCASES_API) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_testcase + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_testcase def test_get_testcases_by_name(self): self.test_create_testcase() - r = self.app.get(f"/api/v2.0/testcases?name={self.ref_testcase_name}") - data = json.loads(r.data) + r = self.app.get(f"{TESTCASES_API}?name={self.ref_testcase_name}") assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_testcase + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_testcase - r = self.app.get( - f"/api/v2.0/testcases?name:like=*{self.ref_testcase_name[1:-1]}*" - ) - data = json.loads(r.data) + r = self.app.get(f"{TESTCASES_API}?name:like=*{self.ref_testcase_name[1:-1]}*") assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_testcase + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_testcase # =============== GROUPS ================== @@ -261,136 +255,122 @@ def helper_create_group(self, uuid=None, description=None, ref_url=None): description = self.ref_group_description if ref_url is None: ref_url = self.ref_group_ref_url - ref_data = json.dumps( - {"uuid": uuid, "description": description, "ref_url": ref_url} - ) - r = self.app.post( - "/api/v2.0/groups", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) - return r, data + data = {"uuid": uuid, "description": description, "ref_url": ref_url} + + return self.app.post(GROUPS_API, json=data) def test_create_group(self): - r, data = self.helper_create_group() + r = self.helper_create_group() assert r.status_code == 201 - assert data == self.ref_group + assert r.json == self.ref_group def test_create_group_no_data(self): - ref_data = json.dumps({}) - - r = self.app.post( - "/api/v2.0/groups", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(GROUPS_API, json={}) assert r.status_code == 201 - assert len(data["uuid"]) == len(self.ref_group_uuid) - assert data["description"] is None - assert data["ref_url"] is None - assert data["href"] == self.ref_url_prefix + "/groups/" + data["uuid"] - assert data["results_count"] == 0 + assert r.json is not None + assert len(r.json["uuid"]) == len(self.ref_group_uuid) + assert r.json["description"] is None + assert r.json["ref_url"] is None + assert r.json["href"] == self.ref_url_prefix + "/groups/" + r.json["uuid"] + assert r.json["results_count"] == 0 assert ( - data["results"] == self.ref_url_prefix + "/results?groups=" + data["uuid"] + r.json["results"] + == self.ref_url_prefix + "/results?groups=" + r.json["uuid"] ) def test_update_group(self): self.test_create_group() - ref_data = json.dumps( - { - "uuid": self.ref_group_uuid, - "description": "Changed", - "ref_url": "Changed", - } - ) + data = { + "uuid": self.ref_group_uuid, + "description": "Changed", + "ref_url": "Changed", + } - r = self.app.post( - "/api/v2.0/groups", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(GROUPS_API, json=data) group = copy.copy(self.ref_group) group["description"] = group["ref_url"] = "Changed" assert r.status_code == 201 - assert data == group + assert r.json == group def test_get_group(self): self.test_create_group() - r = self.app.get(f"/api/v2.0/groups/{self.ref_group_uuid}") - data = json.loads(r.data) + r = self.app.get(f"{GROUPS_API}/{self.ref_group_uuid}") assert r.status_code == 200 - assert data == self.ref_group + assert r.json == self.ref_group def test_get_missing_group(self): r = self.app.get("/api/v2.0/groups/missing") - data = json.loads(r.data) assert r.status_code == 404 - assert data["message"] == "Group not found" + assert r.json is not None + assert r.json["message"] == "Group not found" def test_get_groups(self): - r = self.app.get("/api/v2.0/groups") - data = json.loads(r.data) + r = self.app.get(GROUPS_API) assert r.status_code == 200 - assert len(data["data"]) == 0 + assert r.json is not None + assert len(r.json["data"]) == 0 self.test_create_group() - r = self.app.get("/api/v2.0/groups") - data = json.loads(r.data) + r = self.app.get(GROUPS_API) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_group + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_group def test_get_groups_by_description(self): self.test_create_group() - r = self.app.get(f"/api/v2.0/groups?description={self.ref_group_description}") - data = json.loads(r.data) + r = self.app.get(f"{GROUPS_API}?description={self.ref_group_description}") assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_group + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_group r = self.app.get( "/api/v2.0/groups?description:like=*%s*" % self.ref_group_description[1:-1] ) - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_group + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_group def test_get_groups_by_more_descriptions(self): - r, data = self.helper_create_group(uuid="1", description="FooBar") - r, data = self.helper_create_group(uuid="2", description="BarFoo") + self.helper_create_group(uuid="1", description="FooBar") + self.helper_create_group(uuid="2", description="BarFoo") r = self.app.get("/api/v2.0/groups?description=FooBar,BarFoo") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 r = self.app.get("/api/v2.0/groups?description:like=*oo*,*ar*") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 def test_get_groups_by_more_uuids(self): - r, data = self.helper_create_group(uuid="FooBar") - r, data = self.helper_create_group(uuid="BarFoo") + self.helper_create_group(uuid="FooBar") + self.helper_create_group(uuid="BarFoo") r = self.app.get("/api/v2.0/groups?uuid=FooBar,BarFoo") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 # =============== RESULTS ================== @@ -404,31 +384,24 @@ def helper_create_result(self, outcome=None, groups=None, testcase=None, data=No if data is None: data = self.ref_result_data - ref_data = json.dumps( - dict( - outcome=outcome, - testcase=testcase, - groups=groups, - note=self.ref_result_note, - data=data, - ref_url=self.ref_result_ref_url, - ) + data = dict( + outcome=outcome, + testcase=testcase, + groups=groups, + note=self.ref_result_note, + data=data, + ref_url=self.ref_result_ref_url, ) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) - - return r, data + return self.app.post(RESULTS_API, json=data) def test_create_result(self): self.test_create_group() self.test_create_testcase() - r, data = self.helper_create_result() + r = self.helper_create_result() assert r.status_code == 201 - assert data == self.ref_result + assert r.json == self.ref_result def test_create_result_custom_outcome(self): self.test_create_group() @@ -436,114 +409,52 @@ def test_create_result_custom_outcome(self): ref_result = copy.deepcopy(self.ref_result) ref_result["outcome"] = "AMAZING" - r, data = self.helper_create_result(outcome="AMAZING") + r = self.helper_create_result(outcome="AMAZING") assert r.status_code == 201 - assert data == ref_result + assert r.json == ref_result def test_create_result_with_testcase_name(self): self.test_create_group() self.test_create_testcase() testcase_name = self.ref_result["testcase"]["name"] - r, data = self.helper_create_result(outcome="AMAZING", testcase=testcase_name) + r = self.helper_create_result(outcome="AMAZING", testcase=testcase_name) assert r.status_code == 201 - assert data["testcase"]["name"] == testcase_name + assert r.json is not None + assert r.json["testcase"]["name"] == testcase_name def test_create_result_empty_testcase(self): - r = self.app.post( - "/api/v2.0/results", json={"outcome": "passed", "testcase": ""} - ) - data = json.loads(r.data) - + r = self.app.post(RESULTS_API, json={"outcome": "passed", "testcase": ""}) assert r.status_code == 400 - assert data == { - "validation_error": [ - { - "loc": ["testcase"], - "msg": "Value error, testcase name must be non-empty", - "type": "value_error", - "input": ANY, - "url": ANY, - } - ] - } + assert r.json == EMPTY_TESTCASE_ERROR def test_create_result_empty_testcase_name(self): r = self.app.post( - "/api/v2.0/results", json={"outcome": "passed", "testcase": {"name": ""}} + RESULTS_API, json={"outcome": "passed", "testcase": {"name": ""}} ) - data = json.loads(r.data) assert r.status_code == 400 - assert data == { - "validation_error": [ - { - "loc": ["testcase"], - "msg": "Value error, testcase name must be non-empty", - "type": "value_error", - "input": ANY, - "url": ANY, - } - ] - } + assert r.json == EMPTY_TESTCASE_ERROR def test_create_result_empty_testcase_dict(self): - r = self.app.post( - "/api/v2.0/results", json={"outcome": "passed", "testcase": {}} - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json={"outcome": "passed", "testcase": {}}) assert r.status_code == 400 - assert data == { - "validation_error": [ - { - "loc": ["testcase"], - "msg": "Value error, testcase name must be non-empty", - "type": "value_error", - "input": ANY, - "url": ANY, - } - ] - } + assert r.json == EMPTY_TESTCASE_ERROR def test_create_result_missing_testcase(self): - r = self.app.post("/api/v2.0/results", json={"outcome": "passed"}) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json={"outcome": "passed"}) assert r.status_code == 400 - assert data == { - "validation_error": [ - { - "loc": ["testcase"], - "msg": "Field required", - "type": "missing", - "input": ANY, - "url": ANY, - } - ] - } + assert r.json == field_required_error("testcase") def test_create_result_missing_outcome(self): - ref_data = json.dumps({"testcase": self.ref_testcase}) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json={"testcase": self.ref_testcase}) assert r.status_code == 400 - assert data == { - "validation_error": [ - { - "loc": ["outcome"], - "msg": "Field required", - "type": "missing", - "input": ANY, - "url": ANY, - } - ] - } + assert r.json == field_required_error("outcome") def test_create_result_multiple_groups(self): uuid2 = "1c26effb-7c07-4d90-9428-86aac053288c" @@ -551,84 +462,77 @@ def test_create_result_multiple_groups(self): self.helper_create_group(uuid=uuid2) self.test_create_testcase() - r, data = self.helper_create_result(groups=[self.ref_group, uuid2]) + r = self.helper_create_result(groups=[self.ref_group, uuid2]) assert r.status_code == 201 - assert len(data["groups"]) == 2 - assert self.ref_group_uuid in " ".join(data["groups"]) - assert uuid2 in ";".join(data["groups"]) + assert r.json is not None + assert len(r.json["groups"]) == 2 + assert self.ref_group_uuid in " ".join(r.json["groups"]) + assert uuid2 in ";".join(r.json["groups"]) ref_result = copy.deepcopy(self.ref_result) ref_result["groups"] = None + data = copy.deepcopy(r.json) data["groups"] = None assert data == ref_result def test_create_result_group_is_none(self): - ref_data = json.dumps( - dict( - outcome=self.ref_result_outcome, - testcase=self.ref_testcase, - groups=None, - ) + ref_data = dict( + outcome=self.ref_result_outcome, + testcase=self.ref_testcase, + groups=None, ) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) assert r.status_code == 201 - assert data["groups"] == [] + assert r.json is not None + assert r.json["groups"] == [] def test_create_result_group_did_not_exist(self): self.helper_create_result(groups=[self.ref_group]) - r = self.app.get(f"/api/v2.0/groups/{self.ref_group_uuid}") - data = json.loads(r.data) + r = self.app.get(f"{GROUPS_API}/{self.ref_group_uuid}") ref_group = copy.deepcopy(self.ref_group) ref_group["results_count"] = 1 assert r.status_code == 200 - assert data == ref_group + assert r.json == ref_group uuid2 = "1c26effb-7c07-4d90-9428-86aac053288c" self.helper_create_result(groups=[uuid2]) - r = self.app.get(f"/api/v2.0/groups/{uuid2}") - data = json.loads(r.data) + r = self.app.get(f"{GROUPS_API}/{uuid2}") assert r.status_code == 200 - assert data["uuid"] == uuid2 - assert data["description"] is None - assert data["ref_url"] is None + assert r.json is not None + assert r.json["uuid"] == uuid2 + assert r.json["description"] is None + assert r.json["ref_url"] is None def test_create_result_testcase_did_not_exist(self): self.helper_create_result(testcase=self.ref_testcase) - r = self.app.get(f"/api/v2.0/testcases/{self.ref_testcase_name}") - data = json.loads(r.data) + r = self.app.get(f"{TESTCASES_API}/{self.ref_testcase_name}") assert r.status_code == 200 - assert data == self.ref_testcase + assert r.json == self.ref_testcase name2 = self.ref_testcase_name + ".fake" self.helper_create_result(testcase=name2) - r = self.app.get(f"/api/v2.0/testcases/{name2}") - data = json.loads(r.data) + r = self.app.get(f"{TESTCASES_API}/{name2}") assert r.status_code == 200 - assert data["name"] == name2 + assert r.json is not None + assert r.json["name"] == name2 def test_create_result_invalid_outcome(self): - ref_data = json.dumps({"outcome": "FAKEOUTCOME", "testcase": self.ref_testcase}) + ref_data = {"outcome": "FAKEOUTCOME", "testcase": self.ref_testcase} - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) assert r.status_code == 400 - assert data == { + assert r.json == { "validation_error": [ { "loc": ["outcome"], @@ -644,90 +548,70 @@ def test_create_result_invalid_outcome(self): } def test_create_result_invalid_data(self): - ref_data = json.dumps( - { - "outcome": self.ref_result_outcome, - "testcase": self.ref_testcase, - "data": {"validkey": 1, "invalid:key": 2, "another:invalid:key": 3}, - } - ) + ref_data = { + "outcome": self.ref_result_outcome, + "testcase": self.ref_testcase, + "data": {"validkey": 1, "invalid:key": 2, "another:invalid:key": 3}, + } - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) assert r.status_code == 400 - assert data["message"].startswith("Colon not allowed in key name:") + assert r.json is not None + assert r.json["message"].startswith("Colon not allowed in key name:") def test_create_result_submit_time_as_number(self): - ref_data = json.dumps( - dict( - outcome=self.ref_result_outcome, - testcase=self.ref_testcase, - submit_time=1661324097123, - ) + ref_data = dict( + outcome=self.ref_result_outcome, + testcase=self.ref_testcase, + submit_time=1661324097123, ) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) - assert r.status_code == 201, data - assert data["submit_time"] == "2022-08-24T06:54:57.123000" + assert r.status_code == 201, r.json + assert r.json is not None + assert r.json["submit_time"] == "2022-08-24T06:54:57.123000" def test_create_result_submit_time_as_number_string(self): - ref_data = json.dumps( - dict( - outcome=self.ref_result_outcome, - testcase=self.ref_testcase, - submit_time="1661324097123", - ) + ref_data = dict( + outcome=self.ref_result_outcome, + testcase=self.ref_testcase, + submit_time="1661324097123", ) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) - assert r.status_code == 201, data - assert data["submit_time"] == "2022-08-24T06:54:57.123000" + assert r.status_code == 201, r.json + assert r.json is not None + assert r.json["submit_time"] == "2022-08-24T06:54:57.123000" def test_create_result_submit_time_as_datetime(self): for suffix in ("", "Z", "+00:00", "+0000", "+00"): - ref_data = json.dumps( - dict( - outcome=self.ref_result_outcome, - testcase=self.ref_testcase, - submit_time=f"2022-08-24T06:54:57.123456{suffix}", - ) + ref_data = dict( + outcome=self.ref_result_outcome, + testcase=self.ref_testcase, + submit_time=f"2022-08-24T06:54:57.123456{suffix}", ) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) - assert r.status_code == 201, data - assert data["submit_time"] == "2022-08-24T06:54:57.123456" + assert r.status_code == 201, r.json + assert r.json is not None + assert r.json["submit_time"] == "2022-08-24T06:54:57.123456" def test_create_result_submit_time_as_invalid(self): - ref_data = json.dumps( - dict( - outcome=self.ref_result_outcome, - testcase=self.ref_testcase, - submit_time="now", - ) + ref_data = dict( + outcome=self.ref_result_outcome, + testcase=self.ref_testcase, + submit_time="now", ) - r = self.app.post( - "/api/v2.0/results", data=ref_data, content_type="application/json" - ) - data = json.loads(r.data) + r = self.app.post(RESULTS_API, json=ref_data) - assert r.status_code == 400, data - assert data == { + assert r.status_code == 400, r.json + assert r.json is not None + assert r.json == { "validation_error": [ { "loc": ["submit_time"], @@ -746,46 +630,47 @@ def test_get_result(self): self.test_create_result() r = self.app.get("/api/v2.0/results/%d" % self.ref_result_id) - data = json.loads(r.data) assert r.status_code == 200 - assert data == self.ref_result + assert r.json == self.ref_result def test_get_missing_result(self): r = self.app.get("/api/v2.0/results/%d" % self.ref_result_id) - data = json.loads(r.data) assert r.status_code == 404 - assert data["message"] == "Result not found" + assert r.json is not None + assert r.json["message"] == "Result not found" def test_get_results(self): - r = self.app.get("/api/v2.0/results") - data = json.loads(r.data) + r = self.app.get(RESULTS_API) assert r.status_code == 200 - assert data["data"] == [] + assert r.json is not None + assert r.json["data"] == [] self.test_create_result() - r = self.app.get("/api/v2.0/results") - data = json.loads(r.data) + r = self.app.get(RESULTS_API) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result def test_get_results_sorted_by_submit_time_desc_by_default(self): r1 = self.helper_create_result() + assert r1.json is not None r2 = self.helper_create_result() + assert r2.json is not None - r = self.app.get("/api/v2.0/results") - data = json.loads(r.data) + r = self.app.get(RESULTS_API) assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 - assert data["data"][0]["id"] == r2[1]["id"] - assert data["data"][1]["id"] == r1[1]["id"] + assert r.json["data"][0]["id"] == r2.json["id"] + assert r.json["data"][1]["id"] == r1.json["id"] def test_get_results_by_group(self): uuid2 = "1c26effb-7c07-4d90-9428-86aac053288c" @@ -794,23 +679,22 @@ def test_get_results_by_group(self): self.test_create_result() self.helper_create_result(groups=[uuid2]) - r1 = self.app.get(f"/api/v2.0/groups/{self.ref_group_uuid}/results") - r2 = self.app.get(f"/api/v2.0/results?groups={self.ref_group_uuid}") - - data1 = json.loads(r1.data) - data2 = json.loads(r2.data) + r1 = self.app.get(f"{GROUPS_API}/{self.ref_group_uuid}/results") + r2 = self.app.get(f"{RESULTS_API}?groups={self.ref_group_uuid}") assert r1.status_code == 200, r1.text assert r2.status_code == 200, r2.text - assert len(data1["data"]) == len(data2["data"]) == 1 - assert data1 == data2 - assert data1["data"][0] == self.ref_result + assert r1.json is not None + assert r2.json is not None + assert len(r1.json["data"]) == len(r1.json["data"]) == 1 + assert r1.json == r2.json + assert r1.json["data"][0] == self.ref_result - r = self.app.get(f"/api/v2.0/results?groups={self.ref_group_uuid},{uuid2}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}?groups={self.ref_group_uuid},{uuid2}") assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 def test_get_results_by_testcase(self): name2 = self.ref_testcase_name + ".fake" @@ -819,24 +703,21 @@ def test_get_results_by_testcase(self): self.test_create_result() self.helper_create_result(testcase=name2) - r1 = self.app.get(f"/api/v2.0/testcases/{self.ref_testcase_name}/results") - r2 = self.app.get(f"/api/v2.0/results?testcases={self.ref_testcase_name}") - - data1 = json.loads(r1.data) - data2 = json.loads(r2.data) + r1 = self.app.get(f"{TESTCASES_API}/{self.ref_testcase_name}/results") + r2 = self.app.get(f"{RESULTS_API}?testcases={self.ref_testcase_name}") assert r1.status_code == 200, r1.text assert r2.status_code == 200, r2.text - assert data1["data"][0] == self.ref_result - assert data2["data"][0] == self.ref_result + assert r1.json is not None + assert r2.json is not None + assert r1.json["data"][0] == self.ref_result + assert r2.json["data"][0] == self.ref_result - r = self.app.get( - f"/api/v2.0/results?testcases={self.ref_testcase_name},{name2}" - ) - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}?testcases={self.ref_testcase_name},{name2}") assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 def test_get_results_by_testcase_like(self): name2 = self.ref_testcase_name + ".fake" @@ -845,44 +726,40 @@ def test_get_results_by_testcase_like(self): self.test_create_result() self.helper_create_result(testcase=name2) - r1 = self.app.get(f"/api/v2.0/testcases/{self.ref_testcase_name}/results") - r2 = self.app.get(f"/api/v2.0/results?testcases:like={self.ref_testcase_name}") - - data1 = json.loads(r1.data) - data2 = json.loads(r2.data) + r1 = self.app.get(f"{TESTCASES_API}/{self.ref_testcase_name}/results") + r2 = self.app.get(f"{RESULTS_API}?testcases:like={self.ref_testcase_name}") assert r1.status_code == 200, r1.text assert r2.status_code == 200, r2.text - assert data1["data"][0] == self.ref_result - assert data2["data"][0] == self.ref_result + assert r1.json is not None + assert r2.json is not None + assert r1.json["data"][0] == self.ref_result + assert r2.json["data"][0] == self.ref_result - r1 = self.app.get(f"/api/v2.0/results?testcases:like={self.ref_testcase_name}*") + r1 = self.app.get(f"{RESULTS_API}?testcases:like={self.ref_testcase_name}*") r2 = self.app.get( - f"/api/v2.0/results?testcases:like={self.ref_testcase_name},{self.ref_testcase_name}*" + f"{RESULTS_API}?testcases:like={self.ref_testcase_name},{self.ref_testcase_name}*" ) - data1 = json.loads(r1.data) - data2 = json.loads(r2.data) - assert r1.status_code == r2.status_code == 200 - assert data1 == data2 + assert r1.json == r2.json def test_get_results_by_outcome(self): self.test_create_result() self.helper_create_result(outcome="FAILED") r = self.app.get("/api/v2.0/results?outcome=PASSED") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result r = self.app.get("/api/v2.0/results?outcome=PASSED,FAILED") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 2 + assert r.json is not None + assert len(r.json["data"]) == 2 def test_get_results_sorting_by_submit_time(self): name1 = "aa_fake." + self.ref_testcase_name @@ -892,13 +769,15 @@ def test_get_results_sorting_by_submit_time(self): self.helper_create_result(testcase=name1) r1 = self.app.get("/api/v2.0/results?_sort=desc:submit_time") - data1 = json.loads(r1.data) + data1 = r1.json + assert data1 is not None assert r1.status_code == 200 assert len(data1["data"]) == 2 r2 = self.app.get("/api/v2.0/results?_sort=asc:submit_time") - data2 = json.loads(r2.data) + data2 = r2.json + assert data2 is not None assert r2.status_code == 200 assert len(data2["data"]) == 2 @@ -922,60 +801,60 @@ def test_get_results_by_since(self): before2 = (utcnow_naive() - datetime.timedelta(seconds=99)).isoformat() after = (utcnow_naive() + datetime.timedelta(seconds=100)).isoformat() - r = self.app.get(f"/api/v2.0/results?since={before1}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}?since={before1}") assert r.status_code == 200, r.text - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result - r = self.app.get(f"/api/v2.0/results?since={before1},{after}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}?since={before1},{after}") assert r.status_code == 200, r.text - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result - r = self.app.get(f"/api/v2.0/results?since={(after)}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}?since={(after)}") assert r.status_code == 200, r.text - assert len(data["data"]) == 0 + assert r.json is not None + assert len(r.json["data"]) == 0 - r = self.app.get(f"/api/v2.0/results?since={before1},{before2}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}?since={before1},{before2}") assert r.status_code == 200, r.text - assert len(data["data"]) == 0 + assert r.json is not None + assert len(r.json["data"]) == 0 def test_get_results_by_result_data(self): self.test_create_result() r = self.app.get("/api/v2.0/results?item=perl-Specio-0.25-1.fc26") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result r = self.app.get("/api/v2.0/results?item=perl-Specio-0.25-1.fc26&moo=boo,woof") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result r = self.app.get("/api/v2.0/results?item=perl-Specio-0.25-1.fc26&moo=boo,fake") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result r = self.app.get("/api/v2.0/results?moo:like=*oo*") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result r = self.app.get("/api/v2.0/results?moo:like=*fake*,*oo*") - data = json.loads(r.data) assert r.status_code == 200 - assert len(data["data"]) == 1 - assert data["data"][0] == self.ref_result + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0] == self.ref_result def test_get_results_latest(self): self.helper_create_testcase() @@ -984,25 +863,25 @@ def test_get_results_latest(self): self.helper_create_result(outcome="PASSED") r = self.app.get("/api/v2.0/results/latest") - data = json.loads(r.data) - assert len(data["data"]) == 1 + assert r.json is not None + assert len(r.json["data"]) == 1 self.helper_create_result(outcome="FAILED") r = self.app.get("/api/v2.0/results/latest") - data = json.loads(r.data) - assert len(data["data"]) == 1 - assert data["data"][0]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0]["outcome"] == "FAILED" self.helper_create_result(testcase=self.ref_testcase_name + ".1") r = self.app.get("/api/v2.0/results/latest") - data = json.loads(r.data) - assert len(data["data"]) == 2 - assert data["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" - assert data["data"][1]["testcase"]["name"] == self.ref_testcase_name - assert data["data"][1]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 2 + assert r.json["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" + assert r.json["data"][1]["testcase"]["name"] == self.ref_testcase_name + assert r.json["data"][1]["outcome"] == "FAILED" def test_get_results_latest_modifiers(self): self.helper_create_testcase() @@ -1020,41 +899,41 @@ def test_get_results_latest_modifiers(self): outcome="FAILED", ) - r = self.app.get(f"/api/v2.0/results/latest?testcases={self.ref_testcase_name}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}/latest?testcases={self.ref_testcase_name}") - assert len(data["data"]) == 1 - assert data["data"][0]["testcase"]["name"] == self.ref_testcase_name - assert data["data"][0]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0]["testcase"]["name"] == self.ref_testcase_name + assert r.json["data"][0]["outcome"] == "FAILED" r = self.app.get( - f"/api/v2.0/results/latest?testcases={self.ref_testcase_name},{self.ref_testcase_name + '.1'}" + f"{RESULTS_API}/latest?testcases={self.ref_testcase_name},{self.ref_testcase_name + '.1'}" ) - data = json.loads(r.data) - assert len(data["data"]) == 2 - assert data["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" - assert data["data"][0]["outcome"] == "FAILED" - assert data["data"][1]["testcase"]["name"] == self.ref_testcase_name - assert data["data"][1]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 2 + assert r.json["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" + assert r.json["data"][0]["outcome"] == "FAILED" + assert r.json["data"][1]["testcase"]["name"] == self.ref_testcase_name + assert r.json["data"][1]["outcome"] == "FAILED" r = self.app.get("/api/v2.0/results/latest?testcases:like=*") - data = json.loads(r.data) - assert len(data["data"]) == 2 - assert data["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" - assert data["data"][0]["outcome"] == "FAILED" - assert data["data"][1]["testcase"]["name"] == self.ref_testcase_name - assert data["data"][1]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 2 + assert r.json["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" + assert r.json["data"][0]["outcome"] == "FAILED" + assert r.json["data"][1]["testcase"]["name"] == self.ref_testcase_name + assert r.json["data"][1]["outcome"] == "FAILED" - r = self.app.get(f"/api/v2.0/results/latest?groups={self.ref_group_uuid}") - data = json.loads(r.data) + r = self.app.get(f"{RESULTS_API}/latest?groups={self.ref_group_uuid}") - assert len(data["data"]) == 2 - assert data["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" - assert data["data"][0]["outcome"] == "PASSED" - assert data["data"][1]["testcase"]["name"] == self.ref_testcase_name - assert data["data"][1]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 2 + assert r.json["data"][0]["testcase"]["name"] == self.ref_testcase_name + ".1" + assert r.json["data"][0]["outcome"] == "PASSED" + assert r.json["data"][1]["testcase"]["name"] == self.ref_testcase_name + assert r.json["data"][1]["outcome"] == "FAILED" def test_get_results_latest_distinct_on(self): """This test requires PostgreSQL, because DISTINCT ON does work differently in SQLite""" @@ -1078,15 +957,15 @@ def test_get_results_latest_distinct_on(self): + self.ref_testcase_name + "&_distinct_on=scenario" ) - data = json.loads(r.data) - assert len(data["data"]) == 2 - assert data["data"][0]["data"]["scenario"][0] == "scenario2" - assert data["data"][1]["data"]["scenario"][0] == "scenario1" + assert r.json is not None + assert len(r.json["data"]) == 2 + assert r.json["data"][0]["data"]["scenario"][0] == "scenario2" + assert r.json["data"][1]["data"]["scenario"][0] == "scenario1" r = self.app.get("/api/v2.0/results/latest?testcases=" + self.ref_testcase_name) - data = json.loads(r.data) - assert len(data["data"]) == 1 - assert data["data"][0]["data"]["scenario"][0] == "scenario2" + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0]["data"]["scenario"][0] == "scenario2" def test_get_results_latest_distinct_on_more_specific_cases_1(self): """This test requires PostgreSQL, because DISTINCT ON does work differently in SQLite""" @@ -1114,9 +993,9 @@ def test_get_results_latest_distinct_on_more_specific_cases_1(self): ) r = self.app.get("/api/v2.0/results/latest?item=grub&_distinct_on=scenario") - data = json.loads(r.data) - assert len(data["data"]) == 4 + assert r.json is not None + assert len(r.json["data"]) == 4 def test_get_results_latest_distinct_on_more_specific_cases_2(self): """This test requires PostgreSQL, because DISTINCT ON does work differently in SQLite""" @@ -1148,9 +1027,9 @@ def test_get_results_latest_distinct_on_more_specific_cases_2(self): ) r = self.app.get("/api/v2.0/results/latest?item=grub&_distinct_on=scenario") - data = json.loads(r.data) - assert len(data["data"]) == 5 + assert r.json is not None + assert len(r.json["data"]) == 5 def test_get_results_latest_distinct_on_more_specific_cases_3(self): """This test requires PostgreSQL, because DISTINCT ON does work differently in SQLite""" @@ -1186,15 +1065,15 @@ def test_get_results_latest_distinct_on_more_specific_cases_3(self): ) r = self.app.get("/api/v2.0/results/latest?item=grub&_distinct_on=scenario") - data = json.loads(r.data) + assert r.json is not None items = [ ( x["data"].get("scenario", [None])[0], x["testcase"]["name"], x["outcome"], ) - for x in data["data"] + for x in r.json["data"] ] assert items == [ ("s_1", "tc_1", "INFO"), @@ -1217,17 +1096,17 @@ def test_get_results_latest_distinct_on_with_scenario_not_defined(self): + self.ref_testcase_name + "&_distinct_on=scenario" ) - data = json.loads(r.data) - assert len(data["data"]) == 1 - assert data["data"][0]["outcome"] == "FAILED" + assert r.json is not None + assert len(r.json["data"]) == 1 + assert r.json["data"][0]["outcome"] == "FAILED" def test_get_results_latest_distinct_on_wrong_params(self): r = self.app.get("/api/v2.0/results/latest?_distinct_on=scenario") - data = json.loads(r.data) assert r.status_code == 400 + assert r.json is not None assert ( - data["message"] + r.json["message"] == "Please, provide at least one filter beside '_distinct_on'" ) @@ -1246,9 +1125,9 @@ def test_message_publication(self): def test_get_outcomes_on_landing_page(self): r = self.app.get("/api/v2.0/") - data = json.loads(r.data) assert r.status_code == 300 - assert data["outcomes"] == [ + assert r.json is not None + assert r.json["outcomes"] == [ "PASSED", "INFO", "FAILED", @@ -1260,8 +1139,8 @@ def test_healthcheck_success(self): r = self.app.get("/api/v2.0/healthcheck") assert r.status_code == 200 - data = json.loads(r.data) - assert data.get("message") == "Health check OK" + assert r.json is not None + assert r.json.get("message") == "Health check OK" def test_healthcheck_fail(self): with patch("resultsdb.controllers.api_v2.db") as db: @@ -1269,5 +1148,5 @@ def test_healthcheck_fail(self): r = self.app.get("/api/v2.0/healthcheck") assert r.status_code == 503 - data = json.loads(r.data) - assert data.get("message") == "Unable to communicate with database" + assert r.json is not None + assert r.json.get("message") == "Unable to communicate with database" diff --git a/tests/functest_create_fedmsg.py b/tests/functest_create_fedmsg.py index 09b7463..4bdac08 100644 --- a/tests/functest_create_fedmsg.py +++ b/tests/functest_create_fedmsg.py @@ -70,7 +70,7 @@ def setup_method(self, method): "arch": self.ref_result_arch, "moo": ["boo", "woof"], } - self.ref_result_ref_url = "http://example.com/testing.result" + self.ref_result_ref_url = "https://example.com/testing.result" self.ref_result_obj = MyResult( 0, self.ref_testcase_name, diff --git a/tox.ini b/tox.ini index 6bfda52..8042954 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,7 @@ minversion=2.0 python_functions=test should python_files=test_* functest_* addopts= - --cov=resultsdb + --cov=. --cov-config=.coveragerc --cov-report=term-missing