Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change TemplateWorkspace intended_workspace_type to intended_usage as TextField #518

Merged
merged 3 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions primed/miscellaneous_workspaces/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Forms for the `workspaces` app."""

from anvil_consortium_manager.adapters.workspace import workspace_adapter_registry
from anvil_consortium_manager.forms import Bootstrap5MediaFormMixin
from dal import autocomplete
from django import forms
Expand Down Expand Up @@ -62,23 +61,11 @@ class Meta:
class TemplateWorkspaceForm(forms.ModelForm):
"""Form for a TemplateWorkspace object."""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Set the intended_workspace_type options, excluding "template".
workspace_type_choices = [
(key, value)
for key, value in workspace_adapter_registry.get_registered_names().items()
if key != "template"
]
self.fields["intended_workspace_type"] = forms.ChoiceField(
choices=[("", "---------")] + workspace_type_choices
)

class Meta:
model = models.TemplateWorkspace
fields = (
"workspace",
"intended_workspace_type",
"intended_usage",
)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.2.11 on 2024-03-22 22:59

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("miscellaneous_workspaces", "0010_update_workspace_type_field"),
]

operations = [
migrations.RemoveField(
model_name="historicaltemplateworkspace",
name="intended_workspace_type",
),
migrations.RemoveField(
model_name="templateworkspace",
name="intended_workspace_type",
),
migrations.AddField(
model_name="historicaltemplateworkspace",
name="intended_usage",
field=models.TextField(default=""),
preserve_default=False,
),
migrations.AddField(
model_name="templateworkspace",
name="intended_usage",
field=models.TextField(default=""),
preserve_default=False,
),
]
24 changes: 1 addition & 23 deletions primed/miscellaneous_workspaces/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Model definitions for the `miscellaneous_workspaces` app."""

from anvil_consortium_manager.adapters.workspace import workspace_adapter_registry
from anvil_consortium_manager.models import BaseWorkspaceData, Workspace
from django.core.exceptions import ValidationError
from django.db import models
Expand All @@ -24,28 +23,7 @@ class ResourceWorkspace(RequesterModel, TimeStampedModel, BaseWorkspaceData):
class TemplateWorkspace(TimeStampedModel, BaseWorkspaceData):
"""A model to track template workspaces."""

intended_workspace_type = models.CharField(max_length=63)

def clean(self):
"""Custom cleaning checks.

- Verify that intended_workspace_type is one of the registered types, excluding this type."""
registered_workspace_types = workspace_adapter_registry.get_registered_names()
if self.intended_workspace_type:
if self.intended_workspace_type not in registered_workspace_types:
raise ValidationError(
{
"intended_workspace_type": "intended_workspace_type must be one of the registered types."
}
)
# We cannot import the adapter here because it would lead to a circular import, but we don't want
# to create a template workspace for TemplateWorkspaces. So check if the type is not "template".
elif self.intended_workspace_type == "template":
raise ValidationError(
{
"intended_workspace_type": "intended_workspace_type may not be 'template'."
}
)
intended_usage = models.TextField()


class OpenAccessWorkspace(RequesterModel, TimeStampedModel, BaseWorkspaceData):
Expand Down
15 changes: 2 additions & 13 deletions primed/miscellaneous_workspaces/tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import random

from anvil_consortium_manager.adapters.workspace import workspace_adapter_registry
from anvil_consortium_manager.tests.factories import WorkspaceFactory
from factory import Faker, SubFactory, lazy_attribute
from factory import Faker, SubFactory
from factory.django import DjangoModelFactory

from primed.users.tests.factories import UserFactory
Expand Down Expand Up @@ -53,19 +50,11 @@ class TemplateWorkspaceFactory(DjangoModelFactory):
WorkspaceFactory,
workspace_type=adapters.TemplateWorkspaceAdapter().get_type(),
)
intended_usage = Faker("sentence")

class Meta:
model = models.TemplateWorkspace

@lazy_attribute
def intended_workspace_type(self):
"""Select a random registered workspace_type other than template."""
registered_types = list(
workspace_adapter_registry.get_registered_adapters().keys()
)
registered_types.remove(adapters.TemplateWorkspaceAdapter().get_type())
return random.choice(registered_types)


class OpenAccessWorkspaceFactory(DjangoModelFactory):
"""A factory for the OpenAccessWorkspace model."""
Expand Down
62 changes: 11 additions & 51 deletions primed/miscellaneous_workspaces/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,15 @@ def test_valid(self):
"""Form is valid with necessary input."""
form_data = {
"workspace": self.workspace,
"intended_workspace_type": "resource",
"intended_usage": "Test usage",
}
form = self.form_class(data=form_data)
self.assertTrue(form.is_valid())

def test_invalid_missing_workspace(self):
"""Form is invalid when missing workspace."""
form_data = {
"intended_workspace_type": "resource",
"intended_usage": "Test usage",
}
form = self.form_class(data=form_data)
self.assertFalse(form.is_valid())
Expand All @@ -169,70 +169,30 @@ def test_invalid_missing_workspace(self):
self.assertEqual(len(form.errors["workspace"]), 1)
self.assertIn("required", form.errors["workspace"][0])

def test_invalid_missing_intended_workspace_type(self):
def test_invalid_missing_intended_usage(self):
"""Form is invalid if intended_workspace_type is missing."""
form_data = {
"workspace": self.workspace,
}
form = self.form_class(data=form_data)
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertIn("intended_workspace_type", form.errors)
self.assertEqual(len(form.errors["intended_workspace_type"]), 1)
self.assertIn("required", form.errors["intended_workspace_type"][0])
self.assertIn("intended_usage", form.errors)
self.assertEqual(len(form.errors["intended_usage"]), 1)
self.assertIn("required", form.errors["intended_usage"][0])

def test_invalid_blank_intended_workspace_type(self):
def test_invalid_blank_intended_usage(self):
"""Form is invalid if intended_workspace_type is missing."""
form_data = {
"workspace": self.workspace,
"intended_workspace_type": "",
"intended_usage": "",
}
form = self.form_class(data=form_data)
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertIn("intended_workspace_type", form.errors)
self.assertEqual(len(form.errors["intended_workspace_type"]), 1)
self.assertIn("required", form.errors["intended_workspace_type"][0])

def test_invalid_intended_workspace_type_template(self):
"""Form is invalid if intended_workspace_type is "template"."""
form_data = {
"workspace": self.workspace,
"intended_workspace_type": "template",
}
form = self.form_class(data=form_data)
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertIn("intended_workspace_type", form.errors)
self.assertEqual(len(form.errors["intended_workspace_type"]), 1)
self.assertIn("template", form.errors["intended_workspace_type"][0])

def test_invalid_workspace_type_unregistered_type(self):
"""Form is invalid if intended_workspace_type is not a registered type."""
form_data = {
"workspace": self.workspace,
"intended_workspace_type": "foo",
}
form = self.form_class(data=form_data)
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
self.assertIn("intended_workspace_type", form.errors)
self.assertEqual(len(form.errors["intended_workspace_type"]), 1)
self.assertIn("valid choice", form.errors["intended_workspace_type"][0])

def test_form_all_registered_adapters(self):
"""Form is invalid if intended_workspace_type is not a registered type."""
workspace_types = list(workspace_adapter_registry.get_registered_names().keys())
for workspace_type in workspace_types:
if workspace_type == "template":
pass
else:
form_data = {
"workspace": self.workspace,
"intended_workspace_type": workspace_type,
}
form = self.form_class(data=form_data)
self.assertTrue(form.is_valid())
self.assertIn("intended_usage", form.errors)
self.assertEqual(len(form.errors["intended_usage"]), 1)
self.assertIn("required", form.errors["intended_usage"][0])


class OpenAccessWorkspaceFormTest(TestCase):
Expand Down
79 changes: 2 additions & 77 deletions primed/miscellaneous_workspaces/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from primed.primed_anvil.tests.factories import AvailableDataFactory, StudyFactory
from primed.users.tests.factories import UserFactory

from .. import adapters, models
from .. import models
from . import factories


Expand Down Expand Up @@ -79,7 +79,7 @@ class TemplateWorkspaceTest(TestCase):
def test_model_saving(self):
"""Creation using the model constructor and .save() works."""
workspace = WorkspaceFactory.create()
instance = models.TemplateWorkspace(workspace=workspace)
instance = models.TemplateWorkspace(workspace=workspace, intended_usage="Test")
instance.save()
self.assertIsInstance(instance, models.TemplateWorkspace)

Expand All @@ -91,81 +91,6 @@ def test_str_method(self):
self.assertIsInstance(str(instance), str)
self.assertEqual(str(instance), "test-bp/test-ws")

def test_clean_missing_intended_workspace_type_missing(self):
workspace = WorkspaceFactory.create(
billing_project__name="test-bp", name="test-ws"
)
instance = models.TemplateWorkspace(workspace=workspace)
with self.assertRaises(ValidationError) as e:
instance.full_clean()
self.assertEqual(len(e.exception.message_dict), 1)
self.assertIn("intended_workspace_type", e.exception.message_dict)
self.assertEqual(len(e.exception.message_dict["intended_workspace_type"]), 1)
self.assertIn(
"cannot be blank", e.exception.message_dict["intended_workspace_type"][0]
)

def test_clean_intended_workspace_type_blank(self):
workspace = WorkspaceFactory.create(
billing_project__name="test-bp", name="test-ws"
)
instance = factories.TemplateWorkspaceFactory.build(
workspace=workspace,
intended_workspace_type="",
)
with self.assertRaises(ValidationError) as e:
instance.full_clean()
self.assertEqual(len(e.exception.message_dict), 1)
self.assertIn("intended_workspace_type", e.exception.message_dict)
self.assertEqual(len(e.exception.message_dict["intended_workspace_type"]), 1)
self.assertIn(
"cannot be blank", e.exception.message_dict["intended_workspace_type"][0]
)

def test_clean_intended_workspace_type_with_registered_adapter(self):
"""No ValidationError is raised if intended_workspace_type is a registered type."""
workspace = WorkspaceFactory.create(
billing_project__name="test-bp", name="test-ws"
)
instance = factories.TemplateWorkspaceFactory.build(workspace=workspace)
instance.full_clean()

def test_clean_intended_workspace_type_with_unregistered_adapter(self):
"""ValidationError is raised if intended_workspace_type is not a registered type."""
workspace = WorkspaceFactory.create(
billing_project__name="test-bp", name="test-ws"
)
instance = factories.TemplateWorkspaceFactory.build(
workspace=workspace, intended_workspace_type="foo"
)
with self.assertRaises(ValidationError) as e:
instance.full_clean()
self.assertEqual(len(e.exception.message_dict), 1)
self.assertIn("intended_workspace_type", e.exception.message_dict)
self.assertEqual(len(e.exception.message_dict["intended_workspace_type"]), 1)
self.assertIn(
"registered types", e.exception.message_dict["intended_workspace_type"][0]
)

def test_clean_intended_workspace_type_template(self):
"""ValidationError is raised if intended_workspace_type is set to "template"."""
workspace = WorkspaceFactory.create(
billing_project__name="test-bp", name="test-ws"
)
template_workspace_type = adapters.TemplateWorkspaceAdapter().get_type()
instance = factories.TemplateWorkspaceFactory.build(
workspace=workspace, intended_workspace_type=template_workspace_type
)
with self.assertRaises(ValidationError) as e:
instance.full_clean()
self.assertEqual(len(e.exception.message_dict), 1)
self.assertIn("intended_workspace_type", e.exception.message_dict)
self.assertEqual(len(e.exception.message_dict["intended_workspace_type"]), 1)
self.assertIn(
template_workspace_type,
e.exception.message_dict["intended_workspace_type"][0],
)


class OpenAccessWorkspaceTest(TestCase):
"""Tests for the OpenAccessWorkspace model."""
Expand Down
8 changes: 4 additions & 4 deletions primed/miscellaneous_workspaces/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ def test_creates_workspace(self):
"workspacedata-INITIAL_FORMS": 0,
"workspacedata-MIN_NUM_FORMS": 1,
"workspacedata-MAX_NUM_FORMS": 1,
"workspacedata-0-intended_workspace_type": "resource",
"workspacedata-0-intended_usage": "Test usage",
},
)
self.assertEqual(response.status_code, 302)
Expand All @@ -744,7 +744,7 @@ def test_creates_workspace(self):
self.assertEqual(models.TemplateWorkspace.objects.count(), 1)
new_workspace_data = models.TemplateWorkspace.objects.latest("pk")
self.assertEqual(new_workspace_data.workspace, new_workspace)
self.assertEqual(new_workspace_data.intended_workspace_type, "resource")
self.assertEqual(new_workspace_data.intended_usage, "Test usage")


class TemplateWorkspaceImportTest(AnVILAPIMockTestMixin, TestCase):
Expand Down Expand Up @@ -860,7 +860,7 @@ def test_creates_workspace(self):
"workspacedata-INITIAL_FORMS": 0,
"workspacedata-MIN_NUM_FORMS": 1,
"workspacedata-MAX_NUM_FORMS": 1,
"workspacedata-0-intended_workspace_type": "resource",
"workspacedata-0-intended_usage": "Test usage",
},
)
self.assertEqual(response.status_code, 302)
Expand All @@ -870,7 +870,7 @@ def test_creates_workspace(self):
self.assertEqual(models.TemplateWorkspace.objects.count(), 1)
new_workspace_data = models.TemplateWorkspace.objects.latest("pk")
self.assertEqual(new_workspace_data.workspace, new_workspace)
self.assertEqual(new_workspace_data.intended_workspace_type, "resource")
self.assertEqual(new_workspace_data.intended_usage, "Test usage")


class OpenAccessWorkspaceDetailTest(TestCase):
Expand Down
Loading