From 92d0adf99598fa55eed62e9ac29c194b52ae4a69 Mon Sep 17 00:00:00 2001
From: Maximilian Moser <maximilian.moser@tuwien.ac.at>
Date: Fri, 3 Jan 2025 02:52:02 +0100
Subject: [PATCH] Add tests for the curation consent setting

---
 tests/conftest.py              | 66 ++++++++++++++++++++++++++++++++--
 tests/test_curation_consent.py | 54 ++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 2 deletions(-)
 create mode 100644 tests/test_curation_consent.py

diff --git a/tests/conftest.py b/tests/conftest.py
index 58a9c75..ebebb97 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -13,24 +13,86 @@ fixtures are available.
 
 
 import pytest
+from flask_security.utils import hash_password, login_user
+from flask_webpackext.manifest import (
+    JinjaManifest,
+    JinjaManifestEntry,
+    JinjaManifestLoader,
+)
 from invenio_access.permissions import system_identity
-from invenio_app.factory import create_api
+from invenio_accounts.testutils import login_user_via_session
+from invenio_app.factory import create_app as create_invenio
 from invenio_records_resources.proxies import current_service_registry
 from invenio_vocabularies.proxies import current_service as vocab_svc
 
 
+#
+# Mock the webpack manifest to avoid having to compile the full assets.
+#
+class MockJinjaManifest(JinjaManifest):
+    """Mock manifest."""
+
+    def __getitem__(self, key):
+        """Get a manifest entry."""
+        return JinjaManifestEntry(key, [key])
+
+    def __getattr__(self, name):
+        """Get a manifest entry."""
+        return JinjaManifestEntry(name, [name])
+
+
+class MockManifestLoader(JinjaManifestLoader):
+    """Manifest loader creating a mocked manifest."""
+
+    def load(self, filepath):
+        """Load the manifest."""
+        return MockJinjaManifest()
+
+
 @pytest.fixture(scope="module")
 def create_app(instance_path):
     """Create test app."""
-    return create_api
+    return create_invenio
 
 
 @pytest.fixture(scope="module")
 def app_config(app_config):
     """Testing configuration."""
+    app_config["MAIL_SUPPRESS_SEND"] = True
+    app_config["WEBPACKEXT_MANIFEST_LOADER"] = MockManifestLoader
     return app_config
 
 
+@pytest.fixture()
+def users(app, db):
+    """Create example user."""
+    with db.session.begin_nested():
+        datastore = app.extensions["security"].datastore
+        user1 = datastore.create_user(
+            email="info@inveniosoftware.org",
+            password=hash_password("password"),
+            active=True,
+        )
+        user2 = datastore.create_user(
+            email="ser-testalot@inveniosoftware.org",
+            password=hash_password("beetlesmasher"),
+            active=True,
+        )
+
+    db.session.commit()
+    return [user1, user2]
+
+
+@pytest.fixture()
+def client_with_login(client, users):
+    """A test client for the app with a logged-in user."""
+    user = users[0]
+    login_user(user)
+    login_user_via_session(client, email=user.email)
+    client._user = user
+    return client
+
+
 @pytest.fixture()
 def affiliations(db):
     """Creates the required affiliations vocabulary for the tests."""
diff --git a/tests/test_curation_consent.py b/tests/test_curation_consent.py
new file mode 100644
index 0000000..6839c32
--- /dev/null
+++ b/tests/test_curation_consent.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2025 TU Wien.
+#
+# Invenio-Config-TUW is free software; you can redistribute it and/or modify
+# it under the terms of the MIT License; see LICENSE file for more details.
+
+"""Tests for the per-user curation consent flag."""
+
+import pytest
+from invenio_accounts.proxies import current_datastore
+
+
+def test_curation_setting(users):
+    """Test setting the curation consent flag for users."""
+    user = users[0]
+    preferences = user.preferences or {}
+    assert "curation_consent" not in preferences
+
+    # try setting it to valid values
+    user.preferences = {**preferences, "curation_consent": False}
+    assert user.preferences.get("curation_consent") is False
+    user.preferences = {**preferences, "curation_consent": True}
+    assert user.preferences.get("curation_consent") is True
+
+    # setting it to an invalid value shouldn't work
+    with pytest.raises(ValueError):
+        user.preferences = {**user.preferences, "curation_consent": object()}
+
+
+def test_curation_preferences_form(client_with_login):
+    """Test the curation settings for a user."""
+    assert "curation_consent" not in (client_with_login._user.preferences or {})
+    response = client_with_login.get("/account/settings/curation/")
+    assert response.status_code == 200
+
+    # give consent for curation
+    response = client_with_login.post(
+        "/account/settings/curation/",
+        data={"preferences-curation-consent": "on", "submit": "preferences-curation-"},
+    )
+    user = current_datastore.get_user(client_with_login._user.email)
+    assert response.status_code == 200
+    assert user.preferences.get("curation_consent") is True
+
+    # withdraw consent for curation
+    # (omitting the checkbox value will evaluate it to `False`)
+    response = client_with_login.post(
+        "/account/settings/curation/",
+        data={"submit": "preferences-curation-"},
+    )
+    user = current_datastore.get_user(client_with_login._user.email)
+    assert response.status_code == 200
+    assert user.preferences.get("curation_consent") is False
-- 
GitLab