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")