Page MenuHomeSoftware Heritage

D7817.diff
No OneTemporary

D7817.diff

diff --git a/swh/graphql/resolvers/origin.py b/swh/graphql/resolvers/origin.py
--- a/swh/graphql/resolvers/origin.py
+++ b/swh/graphql/resolvers/origin.py
@@ -1,3 +1,8 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
from swh.graphql.backends import archive
from .base_connection import BaseConnection
diff --git a/swh/graphql/server.py b/swh/graphql/server.py
--- a/swh/graphql/server.py
+++ b/swh/graphql/server.py
@@ -1,3 +1,8 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
import os
from typing import Any, Dict, Optional
@@ -58,7 +63,8 @@
config_path = os.environ.get("SWH_CONFIG_FILENAME")
graphql_cfg = load_and_check_config(config_path)
- if graphql_cfg.get("server-type") == "asgi":
+ server_type = graphql_cfg.get("server-type")
+ if server_type == "asgi":
from ariadne.asgi import GraphQL
application = GraphQL(schema)
diff --git a/swh/graphql/tests/conftest.py b/swh/graphql/tests/conftest.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/tests/conftest.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+
+from ariadne import graphql_sync
+from flask import Flask, jsonify, request
+import pytest
+
+from swh.graphql import server as app_server
+from swh.graphql.app import schema
+from swh.storage import get_storage as get_swhstorage
+
+from .data import populate_dummy_data
+
+
+@pytest.fixture
+def storage():
+ storage = get_swhstorage(cls="memory")
+ # set the global var to use the in-memory storage
+ app_server.storage = storage
+ # populate the in-memory storage
+ populate_dummy_data(storage)
+
+
+@pytest.fixture
+def test_app(storage):
+ app = Flask(__name__)
+
+ @app.route("/", methods=["POST"])
+ def graphql_server():
+ # GraphQL queries are always sent as POST
+ data = request.get_json()
+ success, result = graphql_sync(
+ schema, data, context_value=request, debug=app.debug
+ )
+ status_code = 200 if success else 400
+ return jsonify(result), status_code
+
+ yield app
+
+
+@pytest.fixture
+def client(test_app):
+ with test_app.test_client() as client:
+ yield client
diff --git a/swh/graphql/tests/data.py b/swh/graphql/tests/data.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/tests/data.py
@@ -0,0 +1,105 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+# This module will be removed once the test data
+# generation in SWH-wb moved to a shared location
+# or to a new test data project
+
+from datetime import timedelta
+
+from swh.model.model import Origin, OriginVisit, OriginVisitStatus, Snapshot
+from swh.storage.utils import now
+
+
+def populate_dummy_data(storage):
+ origins = get_origins()
+ visits = get_visits(origins)
+ snapshots = get_snapshots()
+ status = get_visit_status(visits, snapshots)
+
+ storage.origin_add(origins)
+ storage.origin_visit_add(visits)
+ storage.snapshot_add(snapshots)
+ storage.origin_visit_status_add(status)
+
+
+def get_origins():
+ # Return two dummy origins
+ return [
+ Origin(url="http://example.com/forge1"),
+ Origin(url="http://example.com/forge2"),
+ ]
+
+
+def get_visits(origins):
+ # Return two visits each for an origin
+ origin1, origin2 = origins
+ return [
+ OriginVisit(
+ origin=origin1.url,
+ date=now() - timedelta(minutes=200),
+ type="git",
+ visit=1,
+ ),
+ OriginVisit(
+ origin=origin1.url,
+ date=now(),
+ type="git",
+ visit=2,
+ ),
+ OriginVisit(
+ origin=origin2.url,
+ date=now() - timedelta(minutes=500),
+ type="hg",
+ visit=1,
+ ),
+ OriginVisit(
+ origin=origin2.url,
+ date=now(),
+ type="hg",
+ visit=2,
+ ),
+ ]
+
+
+def get_visit_status(visits, snapshots):
+ # Return one status per visit, adding only empty statpshots for now
+ visit1, visit2, visit3, visit4 = visits
+ (empty_snapshot,) = snapshots
+ return [
+ OriginVisitStatus(
+ origin=visit1.origin,
+ visit=visit1.visit,
+ date=visit1.date,
+ status="full",
+ snapshot=empty_snapshot.id,
+ ),
+ OriginVisitStatus(
+ origin=visit2.origin,
+ visit=visit2.visit,
+ date=visit1.date,
+ status="full",
+ snapshot=empty_snapshot.id,
+ ),
+ OriginVisitStatus(
+ origin=visit3.origin,
+ visit=visit3.visit,
+ date=visit3.date,
+ status="full",
+ snapshot=empty_snapshot.id,
+ ),
+ OriginVisitStatus(
+ origin=visit4.origin,
+ visit=visit4.visit,
+ date=visit4.date,
+ status="full",
+ snapshot=empty_snapshot.id,
+ ),
+ ]
+
+
+def get_snapshots():
+ empty_snapshot = Snapshot(branches={})
+ return [empty_snapshot]
diff --git a/swh/graphql/tests/functional/test_origin_connection.py b/swh/graphql/tests/functional/test_origin_connection.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/tests/functional/test_origin_connection.py
@@ -0,0 +1,54 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+from .utils import get_query_response
+
+
+def test_get(client):
+ query_str = """
+ {
+ origins(first: 10) {
+ nodes {
+ url
+ }
+ }
+ }
+ """
+ data, _ = get_query_response(client, query_str)
+ assert len(data["origins"]["nodes"]) == 2
+
+
+def test_get_filter_by_pattern(client):
+ query_str = """
+ {
+ origins(first: 10, urlPattern: "forge1") {
+ nodes {
+ url
+ }
+ }
+ }
+ """
+ data, _ = get_query_response(client, query_str)
+ assert len(data["origins"]["nodes"]) == 1
+
+
+def test_basic_pagination(client):
+ query_str = """
+ {
+ origins(first: 2) {
+ nodes {
+ id
+ }
+ pageInfo {
+ hasNextPage
+ endCursor
+ }
+ }
+ }
+ """
+
+ data, _ = get_query_response(client, query_str)
+ assert len(data["origins"]["nodes"]) == 2
+ assert data["origins"]["pageInfo"] == {"hasNextPage": False, "endCursor": None}
diff --git a/swh/graphql/tests/functional/test_origin_node.py b/swh/graphql/tests/functional/test_origin_node.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/tests/functional/test_origin_node.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+from .utils import get_query_response
+
+
+def test_invalid_get(client):
+ query_str = """
+ {
+ origin(url: "http://example.com/forge1/") {
+ url
+ }
+ }
+ """
+ data, errors = get_query_response(client, query_str)
+ assert data["origin"] is None
+ assert len(errors) == 1
+ assert errors[0]["message"] == "Requested object is not available"
+
+
+def test_get(client):
+ query_str = """
+ {
+ origin(url: "http://example.com/forge1") {
+ url
+ id
+ visits(first: 10) {
+ nodes {
+ id
+ }
+ }
+ latestVisit {
+ visitId
+ }
+ snapshots(first: 2) {
+ nodes {
+ id
+ }
+ }
+ }
+ }
+ """
+ data, _ = get_query_response(client, query_str)
+ origin = data["origin"]
+ assert origin["url"] == "http://example.com/forge1"
+ assert len(origin["visits"]["nodes"]) == 2
+ assert origin["latestVisit"]["visitId"] == 2
+ assert len(origin["snapshots"]["nodes"]) == 1
diff --git a/swh/graphql/tests/functional/utils.py b/swh/graphql/tests/functional/utils.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/tests/functional/utils.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2022 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+import json
+
+
+def get_query_response(client, query_str):
+ response = client.post("/", json={"query": query_str})
+ assert response.status_code == 200, response.data
+ result = json.loads(response.data)
+ return result.get("data"), result.get("errors")

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 3, 1:57 PM (3 d, 3 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3223577

Event Timeline