From 5e3704d6c3850d9624eb0bd984bf0cc7f1a7f01d Mon Sep 17 00:00:00 2001 From: Jay Varner Date: Mon, 3 Jun 2024 13:03:39 -0400 Subject: [PATCH] Add tests for bulk metadata edit. --- .pylintrc | 100 ------------------ .../manifests/fixtures/metadata-update.csv | 3 + apps/iiif/manifests/tests/test_forms.py | 26 ++++- apps/iiif/manifests/tests/test_views.py | 47 +++++++- apps/iiif/manifests/views.py | 11 +- apps/ingest/fixtures/metadata.csv | 4 +- 6 files changed, 81 insertions(+), 110 deletions(-) create mode 100644 apps/iiif/manifests/fixtures/metadata-update.csv diff --git a/.pylintrc b/.pylintrc index 505260c8f..92423c0ee 100644 --- a/.pylintrc +++ b/.pylintrc @@ -47,99 +47,6 @@ unsafe-load-any-extension=no # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED confidence= -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=print-statement, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - non-ascii-bytes-literal, - invalid-unicode-literal, - raw-checker-failed, - bad-inline-option, - locally-disabled, - locally-enabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - deprecated-itertools-function, - deprecated-types-field, - next-method-defined, - dict-items-not-iterating, - dict-keys-not-iterating, - dict-values-not-iterating, - deprecated-operator-function, - deprecated-urllib-function, - xreadlines-attribute, - deprecated-sys-function, - exception-escape, - comprehension-escape, - too-many-ancestors, - logging-format-interpolation, - logging-fstring-interpolation - # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where @@ -333,13 +240,6 @@ max-line-length=100 # Maximum number of lines in a module max-module-lines=1000 -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma, - dict-separator - # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no diff --git a/apps/iiif/manifests/fixtures/metadata-update.csv b/apps/iiif/manifests/fixtures/metadata-update.csv new file mode 100644 index 000000000..9c8ad8796 --- /dev/null +++ b/apps/iiif/manifests/fixtures/metadata-update.csv @@ -0,0 +1,3 @@ +pid,Label,Summary,Author,Published city,Published date,Publisher,Related,ssdl:shortTitle,ssdl:titleOnSource,ssdl:spatialCoverageFast,ssdl:spatialCoverageFastUri +1925-Temple-EMU,The Temple Star,This is a test!,"Unseld, B. C. (Bradley Carl), 1843-1923;Kieffer, Aldine S., 1840-1904","Singer's Glen, VA",1930,Ruebush & Kieffer (Firm),http://sounding-spirit-sftp-upload.s3-website-us-east-1.amazonaws.com/PDF/pilot/1925-Temple-EMU.pdf,The Temple Star,"THE TEMPLE STAR: | —FOR— | SINGING SCHOOLS, CONVENTIONS, CHOIRS, DAY SCHOOLS, | AND MUSICAL SOCIETIES. | —CONTAINING— | THEORETICAL STATEMENTS OF THE PRINCIPLES OF VOCAL MUSIC, | BY B. C. UNSELD, OF THE VIRGINIA NORMAL MUSIC SCHOOL, | GLEES AND SONGS FOR THE SINGING SCHOOL---HYMN TUNES, SABBATH SCHOOL | MUSIC, ANTHEMS AND CHANTS. | Edited by ALDINE S. KIEFFER, Author of ""The Starry Crown,"" Schoolday Singer,"" ""Glad Hosannas,"" etc. | SINGER'S GLEN, VA: | Published BY RUEBUSH, KIEFFER & CO. | (1877.) | Entered according to Act of Congress, in the year 1877, by RUEBUSH, KIEFFER & CO., in the Office of the Librarian of Congress at Washington.",Virginia--Singers Glen,http://id.worldcat.org/fast/1278794 +1829-Chahta-UTL,Chahta Uba Isht Taloa,This is a test!,,"Atlanta, GA",1981,Crocker & Brewster,,,,, \ No newline at end of file diff --git a/apps/iiif/manifests/tests/test_forms.py b/apps/iiif/manifests/tests/test_forms.py index e6143a052..52dda9b86 100644 --- a/apps/iiif/manifests/tests/test_forms.py +++ b/apps/iiif/manifests/tests/test_forms.py @@ -1,6 +1,11 @@ +import os from django.test import TestCase +from django.test.client import RequestFactory +from django.conf import settings +from django.core import files +from django.core.files.uploadedfile import SimpleUploadedFile from .factories import ManifestFactory -from ..forms import ManifestAdminForm +from ..forms import ManifestAdminForm, ManifestCSVImportForm class TestManifestForms(TestCase): def test_form_with_no_canvases(self): @@ -17,3 +22,22 @@ def test_form_with_canvases(self): self.assertTrue(manifest.canvas_set.exists()) form = ManifestAdminForm(instance=manifest) self.assertEqual(form.fields['start_canvas'].queryset.count(), manifest.canvas_set.count()) + + def test_bulk_metadata_form(self): + file_path = os.path.join( + settings.APPS_DIR, + 'iiif', + 'manifests', + 'fixtures', + 'metadata-update.csv' + ) + with open(file_path, 'rb') as metadata_file: + content = SimpleUploadedFile( + name='metadata-update.csv', + content=metadata_file.read() + ) + + csv_form = ManifestCSVImportForm(files={'csv_file': content}) + csv_form.is_valid() + csv_form.clean() + self.assertTrue(csv_form.is_valid()) diff --git a/apps/iiif/manifests/tests/test_views.py b/apps/iiif/manifests/tests/test_views.py index cb8259102..8110aa262 100644 --- a/apps/iiif/manifests/tests/test_views.py +++ b/apps/iiif/manifests/tests/test_views.py @@ -1,9 +1,10 @@ -''' -''' import json +import os from datetime import datetime, timezone from django.test import TestCase, Client from django.test import RequestFactory +from django.core.files.uploadedfile import SimpleUploadedFile + from django.conf import settings from django.contrib.admin.sites import AdminSite from django.contrib.auth import get_user_model @@ -11,9 +12,9 @@ from django.core.serializers import serialize from ..admin import ManifestAdmin -from ..views import AddToCollectionsView, ManifestSitemap, ManifestRis +from ..views import AddToCollectionsView, ManifestSitemap, ManifestRis, MetadataImportView from ..models import Manifest -from ..forms import ManifestsCollectionsForm +from ..forms import ManifestsCollectionsForm, ManifestCSVImportForm from .factories import ManifestFactory, EmptyManifestFactory from ...canvases.models import Canvas from ...canvases.tests.factories import CanvasFactory @@ -121,6 +122,8 @@ def test_multiple_starting_canvases(self): assert first_canvas.pid in manifest['thumbnail']['@id'] def test_no_starting_canvases(self): + """_summary_ + """ manifest = ManifestFactory.create() try: manifest.canvas_set.all().get(is_starting_page=True) @@ -175,3 +178,39 @@ def test_add_to_collections_view_function(self): view.add_manifests_to_collections(form) assert len(manifest1.collections.all()) == 2 assert len(manifest2.collections.all()) == 2 + + def test_bulk_metadata_update(self): + """ + Should update manifest metadata from CSV file. + """ + + manifests = [ + ManifestFactory.create(pid='1925-Temple-EMU'), + ManifestFactory.create(pid='1829-Chahta-UTL') + ] + + self.assertNotEqual(manifests[0].label, 'The Temple Star') + self.assertNotEqual(manifests[1].label, 'Chahta Uba Isht Taloa') + + file_path = os.path.join( + settings.APPS_DIR, + 'iiif', + 'manifests', + 'fixtures', + 'metadata-update.csv' + ) + with open(file_path, 'rb') as metadata_file: + content = SimpleUploadedFile( + name='metadata-update.csv', + content=metadata_file.read() + ) + + csv_form = ManifestCSVImportForm(files={'csv_file': content}) + view = MetadataImportView() + view.request = self.factory.get('/') + view.form_valid(csv_form) + + manifests[0].refresh_from_db() + manifests[1].refresh_from_db() + self.assertEqual(manifests[0].label, 'The Temple Star') + self.assertEqual(manifests[1].label, 'Chahta Uba Isht Taloa') diff --git a/apps/iiif/manifests/views.py b/apps/iiif/manifests/views.py index 07ce81927..3642ae210 100644 --- a/apps/iiif/manifests/views.py +++ b/apps/iiif/manifests/views.py @@ -1,4 +1,6 @@ """Django views for manifests""" + +import os import csv from io import StringIO import json @@ -173,6 +175,7 @@ def get_context_data(self, **kwargs): def form_valid(self, form): """Read the CSV file and, find associated manifests, and update metadata""" + form.is_valid() csv_file = form.cleaned_data.get('csv_file') csv_io = StringIO(csv_file.read().decode('utf-8')) reader = csv.DictReader(normalize_header(csv_io)) @@ -190,7 +193,9 @@ def form_valid(self, form): def get_success_url(self): """Return to the manifest change list with a success message""" - messages.add_message( - self.request, messages.SUCCESS, 'Successfully updated manifests' - ) + # https://stackoverflow.com/questions/11938164/why-dont-my-django-unittests-know-that-messagemiddleware-is-installed + if os.environ['DJANGO_ENV'] != 'test': + messages.add_message( + self.request, messages.SUCCESS, 'Successfully updated manifests' + ) return reverse('admin:manifests_manifest_changelist') diff --git a/apps/ingest/fixtures/metadata.csv b/apps/ingest/fixtures/metadata.csv index 35814bde6..087862bc1 100644 --- a/apps/ingest/fixtures/metadata.csv +++ b/apps/ingest/fixtures/metadata.csv @@ -1,2 +1,2 @@ -Filename,Label,Summary,Author,Published city,Published date,Publisher -no_meta_file,Test Bundle,Test file,Test author,Test City,2021,Pubilsher test \ No newline at end of file +pid,Filename,Label,Summary,Author,Published city,Published date,Publisher +1875-Gospel-UTL-1-jt1,no_meta_file,Test Bundle,Test file,Test author,Test City,2021,Pubilsher test \ No newline at end of file