diff --git a/geniza/entities/admin.py b/geniza/entities/admin.py index d2eb328ea..c08a0f684 100644 --- a/geniza/entities/admin.py +++ b/geniza/entities/admin.py @@ -421,7 +421,7 @@ class PersonDocumentRelationTypeAdmin(TabbedTranslationAdmin, admin.ModelAdmin): def merge_person_document_relation_types(self, request, queryset=None): """Admin action to merge selected person-document relation types. This action redirects to an intermediate page, which displays a form to - review for confirmation and choose the primary person before merging. + review for confirmation and choose the primary type before merging. """ selected = request.POST.getlist("_selected_action") if len(selected) < 2: diff --git a/geniza/entities/tests/test_entities_forms.py b/geniza/entities/tests/test_entities_forms.py index 44e2895e8..196840730 100644 --- a/geniza/entities/tests/test_entities_forms.py +++ b/geniza/entities/tests/test_entities_forms.py @@ -6,11 +6,12 @@ from geniza.corpus.forms import FacetChoiceField from geniza.entities.forms import ( PersonChoiceField, + PersonDocumentRelationTypeMergeForm, PersonListForm, PersonMergeForm, PlaceListForm, ) -from geniza.entities.models import Name, Person, PersonRole +from geniza.entities.models import Name, Person, PersonDocumentRelationType, PersonRole class TestPersonChoiceField: @@ -51,6 +52,31 @@ def test_init(self): assert people.last() not in mergeform.fields["primary_person"].queryset +class TestPersonDocumentRelationTypeMergeForm: + @pytest.mark.django_db + def test_init(self): + # adapted from TestPersonMergeForm + + # no error if ids not specified + PersonDocumentRelationTypeMergeForm() + + # create test records + PersonDocumentRelationType.objects.bulk_create( + [PersonDocumentRelationType(name=f"test{i}") for i in range(4)] + ) + # initialize with ids for all but the last + types = PersonDocumentRelationType.objects.all().order_by("pk") + ids = list(types.values_list("id", flat=True)) + mergeform = PersonDocumentRelationTypeMergeForm(ids=ids[:-1]) + # total should have all but one type + assert ( + mergeform.fields["primary_relation_type"].queryset.count() + == types.count() - 1 + ) + # last type should not be an available choice + assert types.last() not in mergeform.fields["primary_relation_type"].queryset + + @pytest.mark.django_db class TestPersonListForm: def test_set_choices_from_facets(self, person, person_diacritic): diff --git a/geniza/entities/tests/test_entities_views.py b/geniza/entities/tests/test_entities_views.py index c4e2e251c..a735f2bd5 100644 --- a/geniza/entities/tests/test_entities_views.py +++ b/geniza/entities/tests/test_entities_views.py @@ -25,6 +25,7 @@ ) from geniza.entities.views import ( PersonAutocompleteView, + PersonDocumentRelationTypeMerge, PersonListView, PersonMerge, PlaceAutocompleteView, @@ -110,6 +111,91 @@ def test_person_merge(self, admin_client, client): assert "test message" in messages +class TestPersonDocumentRelationTypeMergeView: + # adapted from TestPersonMergeView + @pytest.mark.django_db + def test_get_success_url(self): + rel_type = PersonDocumentRelationType.objects.create(name="test") + merge_view = PersonDocumentRelationTypeMerge() + merge_view.primary_relation_type = rel_type + + resolved_url = resolve(merge_view.get_success_url()) + assert "admin" in resolved_url.app_names + assert resolved_url.url_name == "entities_persondocumentrelationtype_change" + assert resolved_url.kwargs["object_id"] == str(rel_type.pk) + + def test_get_initial(self): + merge_view = PersonDocumentRelationTypeMerge() + merge_view.request = Mock(GET={"ids": "12,23,456,7"}) + + initial = merge_view.get_initial() + assert merge_view.ids == [12, 23, 456, 7] + # lowest id selected as default primary type + assert initial["primary_relation_type"] == 7 + + # Test when no ids are provided (a user shouldn't get here, + # but shouldn't raise an error.) + merge_view.request = Mock(GET={"ids": ""}) + initial = merge_view.get_initial() + assert merge_view.ids == [] + merge_view.request = Mock(GET={}) + initial = merge_view.get_initial() + assert merge_view.ids == [] + + def test_get_form_kwargs(self): + merge_view = PersonDocumentRelationTypeMerge() + merge_view.request = Mock(GET={"ids": "12,23,456,7"}) + form_kwargs = merge_view.get_form_kwargs() + assert form_kwargs["ids"] == merge_view.ids + + def test_person_merge(self, admin_client, client): + # Ensure that the merge view is not visible to public + response = client.get(reverse("admin:person-document-relation-type-merge")) + assert response.status_code == 302 + assert response.url.startswith("/accounts/login/") + + # create test records to merge + rel_type = PersonDocumentRelationType.objects.create(name="test") + dupe_rel_type = PersonDocumentRelationType.objects.create(name="test2") + + idstring = ",".join(str(id) for id in [rel_type.id, dupe_rel_type.id]) + + # GET should display choices + response = admin_client.get( + reverse("admin:person-document-relation-type-merge"), {"ids": idstring} + ) + assert response.status_code == 200 + + # POST should merge + merge_url = "%s?ids=%s" % ( + reverse("admin:person-document-relation-type-merge"), + idstring, + ) + response = admin_client.post( + merge_url, {"primary_relation_type": rel_type.id}, follow=True + ) + TestCase().assertRedirects( + response, + reverse( + "admin:entities_persondocumentrelationtype_change", args=[rel_type.id] + ), + ) + message = list(response.context.get("messages"))[0] + assert message.tags == "success" + assert "Successfully merged" in message.message + assert f"with {str(rel_type)} (id = {rel_type.pk})" in message.message + + with patch.object(PersonDocumentRelationType, "merge_with") as mock_merge_with: + # should catch ValidationError and send back to form with error msg + mock_merge_with.side_effect = ValidationError("test message") + response = admin_client.post( + merge_url, {"primary_relation_type": rel_type.id}, follow=True + ) + TestCase().assertRedirects(response, merge_url) + messages = [str(msg) for msg in list(response.context["messages"])] + assert "test message" in messages + + class TestPersonAutocompleteView: @pytest.mark.django_db def test_get_queryset(self):