Files
enviPy-bayer/tests/views/test_user_views.py
Tobias O d06bd0d4fd [Feature] Minimal IUCLID export (#338)
This is an initial implementation that creates a working minimal .i6z document.
It passes schema validation and can be imported into IUCLID.

Caveat:
IUCLID files target individual compounds.
Pathway is not actually covered by the format.

It can be added in either soil or water and soil OECD endpoints.
**I currently only implemented the soil endpoint for all data.**

This sort of works, and I can report all degradation products in a pathway (not a nice view, but we can report many transformation products and add a diagram attachment in the future).

Adding additional information is an absolute pain, as we need to explicitly map each type of information to the relevant OECD field.
I use the XSD scheme for validation, but unfortunately the IUCLID parser is not fully compliant and requires a specific order, etc.

The workflow is: finding the AI structure from the XSD scheme -> make the scheme validation pass -> upload to IUCLID to get obscure error messages -> guess what could be wrong -> repeat 💣

New specifications get released once per year, so we will have to update accordingly.
I believe that this should be a more expensive feature, as it requires significant effort to uphold.

Currently implemented for root compound only in SOIL:

- Soil Texture 2
- Soil Texture 1
- pH value
- Half-life per soil sample / scenario (mapped to disappearance; not sure about that).
- CEC
- Organic Matter (only Carbon)
- Moisture content
- Humidity

<img width="2123" alt="image.png" src="attachments/d29830e1-65ef-4136-8939-1825e0959c62">
<img width="2124" alt="image.png" src="attachments/ac9de2ac-bf68-4ba4-b40b-82f810a9de93">
<img width="2139" alt="image.png" src="attachments/5674c7e6-865e-420e-974a-6b825b331e6c">

Reviewed-on: enviPath/enviPy#338
Co-authored-by: Tobias O <tobias.olenyi@envipath.com>
Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
2026-04-07 19:46:12 +12:00

111 lines
3.6 KiB
Python

from urllib.parse import quote
from django.conf import settings as s
from django.test import TestCase, override_settings
from django.urls import reverse
from epdb.logic import PackageManager
from epdb.models import Package, User
_LOGIN_REQUIRED_MW = "epdb.middleware.login_required_middleware.LoginRequiredMiddleware"
def _middleware_with_login_required():
mw = list(s.MIDDLEWARE)
return mw if _LOGIN_REQUIRED_MW in mw else [*mw, _LOGIN_REQUIRED_MW]
@override_settings(MODEL_DIR=s.FIXTURE_DIRS[0] / "models", CELERY_TASK_ALWAYS_EAGER=True)
class UserViewTest(TestCase):
fixtures = ["test_fixtures_incl_model.jsonl.gz"]
@classmethod
def setUpClass(cls):
super(UserViewTest, cls).setUpClass()
cls.user = User.objects.get(username="anonymous")
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
cls.BBD_SUBSET = Package.objects.get(name="Fixtures")
def test_login_with_valid_credentials(self):
response = self.client.post(
reverse("login"),
{
"username": "user0",
"password": "SuperSafe",
},
)
self.assertRedirects(response, reverse("index"))
self.assertTrue(response.wsgi_request.user.is_authenticated)
def test_login_with_invalid_credentials(self):
response = self.client.post(
reverse("login"),
{
"username": "user0",
"password": "wrongpassword",
},
)
self.assertEqual(response.status_code, 200)
self.assertFalse(response.wsgi_request.user.is_authenticated)
@override_settings(ADMIN_APPROVAL_REQUIRED=True)
def test_register(self):
response = self.client.post(
reverse("register"),
{
"username": "user1",
"email": "user1@envipath.com",
"password": "SuperSafe",
"rpassword": "SuperSafe",
},
)
self.assertEqual(response.status_code, 200)
self.assertContains(
response,
"Your account has been created! An admin will activate it soon!",
)
def test_register_password_mismatch(self):
response = self.client.post(
reverse("register"),
{
"username": "user1",
"email": "user1@envipath.com",
"password": "SuperSafe",
"rpassword": "SuperSaf3",
},
)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Registration failed, provided passwords differ")
def test_logout(self):
response = self.client.post(
reverse("login"), {"username": "user0", "password": "SuperSafe", "login": "true"}
)
self.assertTrue(response.wsgi_request.user.is_authenticated)
response = self.client.post(
reverse("logout"),
{
"logout": "true",
},
)
self.assertFalse(response.wsgi_request.user.is_authenticated)
@override_settings(MIDDLEWARE=_middleware_with_login_required())
def test_next_param_properly_handled(self):
packages_url = reverse("packages")
response = self.client.get(packages_url)
self.assertRedirects(
response,
f"{s.LOGIN_URL}?next={quote(packages_url)}",
fetch_redirect_response=False,
)
response = self.client.post(
reverse("login"),
{"username": "user0", "password": "SuperSafe", "login": "true", "next": packages_url},
)
self.assertRedirects(response, packages_url)