Files
enviPy-bayer/tests/views/test_package_views.py
Liam Brydon 901de4640c [Fix] Stereochemistry prediction handling (#228 and #238) (#250)
**This pull request will need a separate migration pull-request**

I have added an alert box in two places when the user tries to predict with stereo chemistry.

When a user predicts a pathway with stereo chemistry an alert box is shown in that node's hover.
To do this I added two new fields. Pathway now has a "predicted" BooleanField indicating whether it was predicted or not. It is set to True if the pathway mode for prediction is "predict" or "incremental" and False if it is "build". I think it is a flag that could be useful in the future, perhaps for analysing how many predicted pathways are in enviPath?
Node now has a `stereo_removed` BooleanField which is set to True if the Node's parent Pathways has "predicted" as true and the node SMILES has stereochemistry.
<img width="500" alt="{927AC9FF-DBC9-4A19-9E6E-0EDD3B08C7AC}.png" src="attachments/69ea29bc-c2d2-4cd2-8e98-aae5c5737f69">

When a user does a prediction on a model's page it shows at the top of the list. This did not require any new fields as the entered SMILES does not get saved anywhere.
<img width="500" alt="{BED66F12-5F07-419E-AAA6-FE1FE5B4F266}.png" src="attachments/5fcc3a9b-4d1a-4e48-acac-76b7571f6507">

I think the alert box is an alright solution but if you have a great idea for something that looks/fits better please change it or let me know.

Co-authored-by: Tim Lorsbach <tim@lorsba.ch>
Reviewed-on: enviPath/enviPy#250
Co-authored-by: Liam Brydon <lbry121@aucklanduni.ac.nz>
Co-committed-by: Liam Brydon <lbry121@aucklanduni.ac.nz>
2025-12-03 10:19:34 +13:00

260 lines
8.7 KiB
Python

from django.conf import settings as s
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings, tag
from django.urls import reverse
from epdb.logic import UserManager
from epdb.models import (
Group,
GroupPackagePermission,
License,
Permission,
UserPackagePermission,
)
Package = s.GET_PACKAGE_MODEL()
@override_settings(MODEL_DIR=s.FIXTURE_DIRS[0] / "models", CELERY_TASK_ALWAYS_EAGER=True)
class PackageViewTest(TestCase):
fixtures = ["test_fixtures_incl_model.jsonl.gz"]
@classmethod
def setUpClass(cls):
super(PackageViewTest, cls).setUpClass()
cls.user1 = UserManager.create_user(
"user1",
"user1@envipath.com",
"SuperSafe",
set_setting=False,
add_to_group=True,
is_active=True,
)
cls.user2 = UserManager.create_user(
"user2",
"user2@envipath.com",
"SuperSafe",
set_setting=False,
add_to_group=True,
is_active=True,
)
# Create the default license set.
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
for cc_string in cc_strings:
if not License.objects.filter(cc_string=cc_string).exists():
new_license = License()
new_license.cc_string = cc_string
new_license.link = f"https://creativecommons.org/licenses/{cc_string}/4.0/"
new_license.image_link = f"https://licensebuttons.net/l/{cc_string}/4.0/88x31.png"
new_license.save()
def setUp(self):
self.client.force_login(self.user1)
def test_create_package(self):
response = self.client.post(
reverse("packages"),
{
"package-name": "Test Package",
"package-description": "Just a Description",
},
)
self.assertEqual(response.status_code, 302)
package_url = response.url
p = Package.objects.get(url=package_url)
self.assertEqual(p.name, "Test Package")
self.assertEqual(p.description, "Just a Description")
upp = UserPackagePermission.objects.get(package=p, user=self.user1)
self.assertEqual(upp.permission, Permission.ALL[0])
def test_import_package(self):
file = SimpleUploadedFile(
"Fixture_Package.json",
open(s.FIXTURE_DIRS[0] / "Fixture_Package.json", "rb").read(),
content_type="application/json",
)
response = self.client.post(
reverse("packages"), {"file": file, "hidden": "import-package-json"}
)
self.assertEqual(response.status_code, 302)
package_url = response.url
p = Package.objects.get(url=package_url)
self.assertEqual(p.pathways.count(), 22)
self.assertEqual(p.rules.count(), 45)
self.assertEqual(p.compounds.count(), 223)
self.assertEqual(p.reactions.count(), 212)
upp = UserPackagePermission.objects.get(package=p, user=self.user1)
self.assertEqual(upp.permission, Permission.ALL[0])
@tag("slow")
def test_import_legacy_package(self):
file = SimpleUploadedFile(
"EAWAG-BBD.json",
open(s.FIXTURE_DIRS[0] / "packages" / "2025-07-18" / "EAWAG-BBD.json", "rb").read(),
content_type="application/json",
)
response = self.client.post(
reverse("packages"), {"file": file, "hidden": "import-legacy-package-json"}
)
self.assertEqual(response.status_code, 302)
package_url = response.url
p = Package.objects.get(url=package_url)
self.assertEqual(p.pathways.count(), 219)
self.assertEqual(p.rules.count(), 498)
self.assertEqual(p.compounds.count(), 1399)
self.assertEqual(p.reactions.count(), 1480)
self.assertEqual(p.scenarios.count(), 1914)
upp = UserPackagePermission.objects.get(package=p, user=self.user1)
self.assertEqual(upp.permission, Permission.ALL[0])
def test_edit_package(self):
response = self.client.post(
reverse("packages"),
{
"package-name": "Test Package",
"package-description": "Just a Description",
},
)
self.assertEqual(response.status_code, 302)
package_url = response.url
self.client.post(
package_url,
{
"package-name": "New Name",
"package-description": "New Description",
},
)
p = Package.objects.get(url=package_url)
self.assertEqual(p.name, "New Name")
self.assertEqual(p.description, "New Description")
def test_edit_package_permissions(self):
response = self.client.post(
reverse("packages"),
{
"package-name": "Test Package",
"package-description": "Just a Description",
},
)
self.assertEqual(response.status_code, 302)
package_url = response.url
p = Package.objects.get(url=package_url)
with self.assertRaises(UserPackagePermission.DoesNotExist):
UserPackagePermission.objects.get(package=p, user=self.user2)
self.client.post(
package_url,
{
"grantee": self.user2.url,
"read": "on",
"write": "on",
},
)
upp = UserPackagePermission.objects.get(package=p, user=self.user2)
self.assertEqual(upp.permission, Permission.WRITE[0])
def test_publish_package(self):
response = self.client.post(
reverse("packages"),
{
"package-name": "Test Package",
"package-description": "Just a Description",
},
)
self.assertEqual(response.status_code, 302)
package_url = response.url
p = Package.objects.get(url=package_url)
self.client.post(package_url, {"hidden": "publish-package"})
self.assertEqual(Group.objects.filter(public=True).count(), 1)
g = Group.objects.get(public=True)
gpp = GroupPackagePermission.objects.get(package=p, group=g)
self.assertEqual(gpp.permission, Permission.READ[0])
def test_set_package_license(self):
response = self.client.post(
reverse("packages"),
{
"package-name": "Test Package",
"package-description": "Just a Description",
},
)
package_url = response.url
p = Package.objects.get(url=package_url)
self.client.post(package_url, {"license": "no-license"})
self.assertIsNone(p.license)
# Test other possible licenses
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
for cc_string in cc_strings:
self.client.post(package_url, {"license": cc_string})
# Without this, the instance of p doesn't have the license. However, the one retrieved with get does
p = Package.objects.get(url=package_url)
self.assertEqual(
p.license.link, f"https://creativecommons.org/licenses/{cc_string}/4.0/"
)
# Test again to ensure that Licenses are reused
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
for cc_string in cc_strings:
self.client.post(package_url, {"license": cc_string})
# Without this, the instance of p doesn't have the license. However, the one retrieved with get does
p = Package.objects.get(url=package_url)
self.assertEqual(
p.license.link, f"https://creativecommons.org/licenses/{cc_string}/4.0/"
)
self.assertEqual(License.objects.count(), len(cc_strings))
def test_delete_package(self):
response = self.client.post(
reverse("packages"),
{
"package-name": "Test Package",
"package-description": "Just a Description",
},
)
package_url = response.url
p = Package.objects.get(url=package_url)
p.delete()
response = self.client.get(package_url)
self.assertEqual(response.status_code, 404)
def test_delete_default_package(self):
self.client.force_login(self.user1)
# Try to delete the default package
response = self.client.post(self.user1.default_package.url, {"hidden": "delete"})
self.assertEqual(response.status_code, 400)
self.assertTrue(
"You cannot delete the default package. "
"If you want to delete this package you have to "
"set another default package first" in response.content.decode()
)