From: Radek Czajka Date: Sat, 15 Dec 2018 21:01:12 +0000 (+0100) Subject: Remove unused dependency on nose. Move to default tests discovery. X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/4298f7948e8963176debf5877fce30c49ae4e3ad?hp=a70cbcf401eb1ebc0009cc1ce9d0d8e664cc9642 Remove unused dependency on nose. Move to default tests discovery. --- diff --git a/.gitignore b/.gitignore index ed1bedc89..a1c1ad15a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ src/wolnelektury/static/scss/*.css coverage.xml pip-log.txt nosetests.xml +/htmlcov # Mac OS X garbage .DS_Store diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5ef3ba7e4 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +.ONESHELL: +test: + cd src + coverage run --branch --source='.' ./manage.py test; true + rm -rf ../htmlcov + coverage html -d ../htmlcov.new + rm -rf ../htmlcov + mv ../htmlcov.new ../htmlcov + coverage report + rm .coverage diff --git a/README.md b/README.md index 340ae0477..5b39ff9cb 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ How to deploy (development version) 1. Checkout the source code from Github and enter the directory 2. Install libraries (we recommend using pip): - pip install -r requirements.txt + pip install -r requirements/requirements.txt git submodule update --init 3. Setup your local configuration based on settings.py. You need to generate a new SECRET_KEY, database stuff and domain related stuff. diff --git a/requirements/requirements-test.txt b/requirements/requirements-test.txt index 87aa0fe38..794632d4d 100644 --- a/requirements/requirements-test.txt +++ b/requirements/requirements-test.txt @@ -1,6 +1,4 @@ -i https://py.mdrn.pl:8443/simple/ -nose>=1.3.7 -django-nose>=1.4.2,<1.5 -nosexcover +coverage mock diff --git a/src/catalogue/tests/__init__.py b/src/catalogue/tests/__init__.py index 4eb8e8dd6..e69de29bb 100644 --- a/src/catalogue/tests/__init__.py +++ b/src/catalogue/tests/__init__.py @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from catalogue.tests.book_import import * -from catalogue.tests.bookmedia import * -from catalogue.tests.cover import * -from catalogue.tests.tags import * -from catalogue.tests.templatetags import * -from .visit import * diff --git a/src/catalogue/tests/book_import.py b/src/catalogue/tests/book_import.py deleted file mode 100644 index a4452686c..000000000 --- a/src/catalogue/tests/book_import.py +++ /dev/null @@ -1,432 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from django.core.files.base import ContentFile -from catalogue.test_utils import * -from catalogue import models -from librarian import WLURI - -from nose.tools import raises -from os import path, makedirs - - -class BookImportLogicTests(WLTestCase): - - def setUp(self): - WLTestCase.setUp(self) - self.book_info = BookInfoStub( - url=WLURI.from_slug(u"default-book"), - about=u"http://wolnelektury.pl/example/URI/default_book", - title=u"Default Book", - author=PersonStub(("Jim",), "Lazy"), - kind="X-Kind", - genre="X-Genre", - epoch="X-Epoch", - language=u"pol", - ) - - self.expected_tags = [ - ('author', 'jim-lazy'), - ('genre', 'x-genre'), - ('epoch', 'x-epoch'), - ('kind', 'x-kind'), - ] - self.expected_tags.sort() - - def test_empty_book(self): - book_text = "" - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - - self.assertEqual(book.title, "Default Book") - self.assertEqual(book.slug, "default-book") - self.assert_(book.parent is None) - self.assertFalse(book.has_html_file()) - - # no fragments generated - self.assertEqual(book.fragments.count(), 0) - - # TODO: this should be filled out probably... - self.assertEqual(book.wiki_link, '') - self.assertEqual(book.gazeta_link, '') - self.assertEqual(book.description, '') - - tags = [(tag.category, tag.slug) for tag in book.tags] - tags.sort() - - self.assertEqual(tags, self.expected_tags) - - def test_not_quite_empty_book(self): - """ Not empty, but without any real text. - - Should work like any other non-empty book. - """ - - book_text = """ - - Nic - - """ - - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.assertTrue(book.has_html_file()) - - def test_book_with_fragment(self): - book_text = """ - - LoveAla ma kota - - """ - - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.assertTrue(book.has_html_file()) - - self.assertEqual(book.fragments.count(), 1) - self.assertEqual(book.fragments.all()[0].text, u'

Ala ma kota

\n') - - self.assert_(('theme', 'love') in [(tag.category, tag.slug) for tag in book.fragments.all()[0].tags]) - - def test_book_with_empty_theme(self): - """ empty themes should be ignored """ - - book_text = """ - - , Love , , Ala ma kota - - """ - - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.assert_([('theme', 'love')], - book.fragments.all()[0].tags.filter(category='theme').values_list('category', 'slug')) - - def test_book_with_no_theme(self): - """ fragments with no themes shouldn't be created at all """ - - book_text = """ - - Ala ma kota - - """ - - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.assertEqual(book.fragments.count(), 0) - self.assertEqual(book.tags.filter(category='theme').count(), 0) - - @raises(ValueError) - def test_book_with_invalid_slug(self): - """ Book with invalid characters in slug shouldn't be imported """ - self.book_info.url = WLURI.from_slug(u"default_book") - book_text = "" - models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - - def test_book_replace_title(self): - book_text = """""" - models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.book_info.title = u"Extraordinary" - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True) - - tags = [(tag.category, tag.slug) for tag in book.tags] - tags.sort() - - self.assertEqual(tags, self.expected_tags) - - def test_book_replace_author(self): - book_text = """""" - models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen") - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True) - - tags = [(tag.category, tag.slug) for tag in book.tags] - tags.sort() - - self.expected_tags.remove(('author', 'jim-lazy')) - self.expected_tags.append(('author', 'hans-christian-andersen')) - self.expected_tags.sort() - - self.assertEqual(tags, self.expected_tags) - - # the old tag shouldn't disappear - models.Tag.objects.get(slug="jim-lazy", category="author") - - def test_book_remove_fragment(self): - book_text = """ - - - LoveAla ma kota - HatredTo kot Ali - - - """ - book_text_after = """ - - - LoveAla ma kota - To kot Ali - - - """ - - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - self.assertEqual(book.fragments.count(), 2) - book = models.Book.from_text_and_meta(ContentFile(book_text_after), self.book_info, overwrite=True) - self.assertEqual(book.fragments.count(), 1) - - def test_multiple_tags(self): - book_text = """""" - self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"), - self.book_info.kinds = self.book_info.kind, 'Y-Kind', - self.book_info.genres = self.book_info.genre, 'Y-Genre', - self.book_info.epochs = self.book_info.epoch, 'Y-Epoch', - - self.expected_tags.extend([ - ('author', 'joe-dilligent'), - ('genre', 'y-genre'), - ('epoch', 'y-epoch'), - ('kind', 'y-kind'), - ]) - self.expected_tags.sort() - - book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) - tags = [(tag.category, tag.slug) for tag in book.tags] - tags.sort() - - self.assertEqual(tags, self.expected_tags) - - -class ChildImportTests(WLTestCase): - - def setUp(self): - WLTestCase.setUp(self) - self.child_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Joe",), "Doe"), - **info_args("Child") - ) - - self.parent_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Jim",), "Lazy"), - parts=[self.child_info.url], - **info_args("Parent") - ) - - def test_child(self): - text = """""" - child = models.Book.from_text_and_meta(ContentFile(text), self.child_info) - parent = models.Book.from_text_and_meta(ContentFile(text), self.parent_info) - author = parent.tags.get(category='author') - books = self.client.get(author.get_absolute_url()).context['object_list'] - self.assertEqual(len(books), 1, "Only parent book should be visible on author's page") - - def test_child_replace(self): - parent_text = """""" - child_text = """ - - PiesAla ma kota - - """ - child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info) - parent = models.Book.from_text_and_meta(ContentFile(parent_text), self.parent_info) - child_text = """ - - KotAla ma kota - - """ - child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info, overwrite=True) - themes = parent.related_themes() - self.assertEqual(['Kot'], [tag.name for tag in themes], 'wrong related theme list') - - -class TreeImportTest(WLTestCase): - def setUp(self): - WLTestCase.setUp(self) - self.child_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Joe",), "Doe"), - **info_args("Child") - ) - self.CHILD_TEXT = """ - - Pies - Ala ma kota - - """ - self.child = models.Book.from_text_and_meta( - ContentFile(self.CHILD_TEXT), self.child_info) - - self.book_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Joe",), "Doe"), - parts=[self.child_info.url], - **info_args("Book") - ) - self.BOOK_TEXT = """""" - self.book = models.Book.from_text_and_meta( - ContentFile(self.BOOK_TEXT), self.book_info) - - self.parent_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Jim",), "Lazy"), - parts=[self.book_info.url], - **info_args("Parent") - ) - self.PARENT_TEXT = """""" - self.parent = models.Book.from_text_and_meta( - ContentFile(self.PARENT_TEXT), self.parent_info) - - def test_ok(self): - self.assertEqual( - list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']), - [self.parent], - u"There should be only parent on common tag page." - ) - # pies = models.Tag.objects.get(slug='pies') - themes = self.parent.related_themes() - self.assertEqual(len(themes), 1, u"There should be child theme in parent theme counter.") - # TODO: book_count is deprecated, update here. - # epoch = models.Tag.objects.get(slug='x-epoch') - # self.assertEqual(epoch.book_count, 1, u"There should be only parent in common tag's counter.") - - def test_child_republish(self): - child_text = """ - - Pies, Kot - Ala ma kota - - """ - models.Book.from_text_and_meta( - ContentFile(child_text), self.child_info, overwrite=True) - self.assertEqual( - list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']), - [self.parent], - u"There should only be parent on common tag page." - ) - # pies = models.Tag.objects.get(slug='pies') - # kot = models.Tag.objects.get(slug='kot') - self.assertEqual(len(self.parent.related_themes()), 2, - u"There should be child themes in parent theme counter.") - # TODO: book_count is deprecated, update here. - # epoch = models.Tag.objects.get(slug='x-epoch') - # self.assertEqual(epoch.book_count, 1, u"There should only be parent in common tag's counter.") - - def test_book_change_child(self): - second_child_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='Other-Kind', - author=PersonStub(("Joe",), "Doe"), - **info_args("Second Child") - ) - second_child_text = """ - - Kot - Ala ma kota - - """ - # Import a second child. - second_child = models.Book.from_text_and_meta( - ContentFile(second_child_text), second_child_info) - # The book has only this new child now. - self.book_info.parts = [second_child_info.url] - self.book = models.Book.from_text_and_meta( - ContentFile(self.BOOK_TEXT), self.book_info, overwrite=True) - - self.assertEqual( - set(self.client.get('/katalog/gatunek/x-genre/').context['object_list']), - {self.parent, self.child}, - u"There should be parent and old child on common tag page." - ) - # kot = models.Tag.objects.get(slug='kot') - self.assertEqual(len(self.parent.related_themes()), 1, - u"There should only be new child themes in parent theme counter.") - # # book_count deprecated, update test. - # epoch = models.Tag.objects.get(slug='x-epoch') - # self.assertEqual(epoch.book_count, 2, - # u"There should be parent and old child in common tag's counter.") - self.assertEqual( - list(self.client.get('/katalog/lektura/parent/motyw/kot/').context['fragments']), - [second_child.fragments.all()[0]], - u"There should be new child's fragments on parent's theme page." - ) - self.assertEqual( - list(self.client.get('/katalog/lektura/parent/motyw/pies/').context['fragments']), - [], - u"There should be no old child's fragments on parent's theme page." - ) - - -class MultilingualBookImportTest(WLTestCase): - def setUp(self): - WLTestCase.setUp(self) - common_uri = WLURI.from_slug('common-slug') - - self.pol_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Joe",), "Doe"), - variant_of=common_uri, - **info_args(u"Książka") - ) - - self.eng_info = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Joe",), "Doe"), - variant_of=common_uri, - **info_args("A book", "eng") - ) - - def test_multilingual_import(self): - book_text = """A""" - - models.Book.from_text_and_meta(ContentFile(book_text), self.pol_info) - models.Book.from_text_and_meta(ContentFile(book_text), self.eng_info) - - self.assertEqual( - set([b.language for b in models.Book.objects.all()]), - {'pol', 'eng'}, - 'Books imported in wrong languages.' - ) - - -class BookImportGenerateTest(WLTestCase): - def setUp(self): - WLTestCase.setUp(self) - xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml') - self.book = models.Book.from_xml_file(xml) - - def test_gen_pdf(self): - self.book.pdf_file.build() - book = models.Book.objects.get(pk=self.book.pk) - self.assertTrue(path.exists(book.pdf_file.path)) - - def test_gen_pdf_parent(self): - """This book contains a child.""" - xml = path.join(path.dirname(__file__), "files/fraszki.xml") - parent = models.Book.from_xml_file(xml) - parent.pdf_file.build() - parent = models.Book.objects.get(pk=parent.pk) - self.assertTrue(path.exists(parent.pdf_file.path)) - - def test_custom_pdf(self): - from catalogue.tasks import build_custom_pdf - out = 'test-custom.pdf' - absoulute_path = path.join(settings.MEDIA_ROOT, out) - - if not path.exists(path.dirname(absoulute_path)): - makedirs(path.dirname(absoulute_path)) - - build_custom_pdf(self.book.id, customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out) - self.assertTrue(path.exists(absoulute_path)) diff --git a/src/catalogue/tests/bookmedia.py b/src/catalogue/tests/bookmedia.py deleted file mode 100644 index 263e48d9a..000000000 --- a/src/catalogue/tests/bookmedia.py +++ /dev/null @@ -1,134 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from os.path import basename, exists -from unittest import skip - -from django.core.files.base import ContentFile - -from catalogue.test_utils import * -from catalogue import models, utils - - -class BookMediaTests(WLTestCase): - - def setUp(self): - WLTestCase.setUp(self) - self.file = ContentFile('X') - self.file2 = ContentFile('Y') - self.book = models.Book.objects.create(slug='test-book', title='Test') - - def set_title(self, title): - self.book.title = title - self.book.save() - - def test_diacritics(self): - bm = models.BookMedia(book=self.book, type="ogg", name=u"Zażółć gęślą jaźń") - self.set_title(bm.name) - bm.file.save(None, self.file) - self.assertEqual(basename(bm.file.name), 'zazolc-gesla-jazn.ogg') - - def test_long_name(self): - bm = models.BookMedia( - book=self.book, type="ogg", - name="Some very very very very very very very very very very very very very very very very long file name") - self.set_title(bm.name) - bm.file.save(bm.name, self.file) - - # reload to see what was really saved - bm = models.BookMedia.objects.get(pk=bm.pk) - self.assertEqual(bm.file.size, 1) - - def test_overwrite(self): - """ - File gets overwritten with same filename on update. - """ - - bm = models.BookMedia(book=self.book, type='ogg', name="Some media") - self.set_title(bm.name) - bm.file.save(None, self.file) - bm.file.save(None, self.file2) - - self.assertEqual(bm.file.read(), 'Y') - self.assertEqual(basename(bm.file.name), 'some-media.ogg') - - @skip('broken, but is it needed?') - def test_no_clobber(self): - """ - File save doesn't clobber some other media with similar name. - """ - - bm = models.BookMedia(book=self.book, type='ogg', name=u"Tytul") - self.set_title(bm.name) - bm.file.save(None, self.file) - bm2 = models.BookMedia(book=self.book, type='ogg', name=u"Tytuł") - self.set_title(bm2.name) - bm2.file.save(None, self.file2) - self.assertEqual(basename(bm.file.name), 'tytul.ogg') - self.assertNotEqual(basename(bm2.file.name), 'tytul.ogg') - self.assertEqual(bm.file.read(), 'X') - self.assertEqual(bm2.file.read(), 'Y') - - def test_change_name(self): - """ - File name reflects name change. - """ - - bm = models.BookMedia(book=self.book, type='ogg', name="Title") - self.set_title(bm.name) - bm.file.save(None, self.file) - self.set_title("Other Title") - bm.save() - self.assertEqual(basename(bm.file.name), 'other-title.ogg') - self.assertEqual(bm.file.read(), 'X') - - @skip('broken, but is it needed?') - def test_change_name_no_clobber(self): - """ - File name after change won't clobber some other file - with similar name. - """ - - bm = models.BookMedia(book=self.book, type='ogg', name="Title") - self.set_title(bm.name) - bm.file.save(None, self.file) - bm2 = models.BookMedia(book=self.book, type='ogg', name="Other title") - self.set_title(bm2.name) - bm2.file.save(None, self.file2) - self.set_title("Title") - bm2.save() - self.assertNotEqual(basename(bm2.file.name), 'title.ogg') - self.assertEqual(bm.file.read(), 'X') - self.assertEqual(bm2.file.read(), 'Y') - - def test_zip_audiobooks(self): - paths = [ - (None, join(dirname(__file__), "files/fraszka-do-anusie.xml")), - (None, join(dirname(__file__), "files/fraszki.xml")), - ] - - url = utils.create_zip(paths, 'test-zip-slug') - self.assertEqual("zip/test-zip-slug.zip", url) - self.assertTrue(exists(join(settings.MEDIA_ROOT, url))) - - utils.remove_zip('test-zip-slug') - self.assertFalse(exists(join(settings.MEDIA_ROOT, url))) - - def test_remove_zip_on_media_change(self): - bm = models.BookMedia(book=self.book, type='ogg', name="Title") - self.set_title(bm.name) - bm.file.save(None, self.file) - bm.save() - - zip_url = self.book.zip_audiobooks('ogg') - self.assertEqual('zip/'+self.book.slug+'_ogg.zip', zip_url) - self.assertTrue(exists(join(settings.MEDIA_ROOT, zip_url))) - - bm2 = models.BookMedia(book=self.book, type='ogg', name="Other title") - self.set_title(bm2.name) - bm2.file.save(None, self.file2) - self.set_title("Title") - bm2.save() - # was the audiobook zip deleted? - self.assertFalse(exists(join(settings.MEDIA_ROOT, zip_url))) diff --git a/src/catalogue/tests/cover.py b/src/catalogue/tests/cover.py deleted file mode 100755 index 8c5d04718..000000000 --- a/src/catalogue/tests/cover.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from django.core.files.base import ContentFile -from catalogue.test_utils import BookInfoStub, PersonStub, info_args, WLTestCase -from catalogue.models import Book -from mock import patch - - -class CoverTests(WLTestCase): - """Checks in parent_cover_changed is properly called.""" - def setUp(self): - WLTestCase.setUp(self) - self.TEXT = """""" - self.child = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Joe",), "Doe"), - **info_args("Child") - ) - - self.parent = BookInfoStub( - genre='X-Genre', - epoch='X-Epoch', - kind='X-Kind', - author=PersonStub(("Jim",), "Lazy"), - cover_url="http://example.com/cover.jpg", - parts=[self.child.url], - **info_args("Parent") - ) - - @patch.object(Book, 'parent_cover_changed', autospec=True) - def test_simple_import(self, parent_cover_changed): - child = Book.from_text_and_meta(ContentFile(self.TEXT), self.child) - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent) - parent_cover_changed.assert_called_with(child) - - # Now reimport parent. - parent_cover_changed.reset_mock() - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) - self.assertEqual(parent_cover_changed.call_count, 0) - - # Now change cover in parent. - parent_cover_changed.reset_mock() - self.parent.cover_url = "http://example.com/other-cover.jpg" - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) - parent_cover_changed.assert_called_with(child) - - @patch.object(Book, 'parent_cover_changed', autospec=True) - def test_change_cover(self, parent_cover_changed): - child = Book.from_text_and_meta(ContentFile(self.TEXT), self.child) - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent) - parent_cover_changed.assert_called_with(child) - - @patch.object(Book, 'parent_cover_changed', autospec=True) - def test_new_child(self, parent_cover_changed): - # Add parent without child first. - parts, self.parent.parts = self.parent.parts, [] - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent) - - # Now import child and reimport parent. - child = Book.from_text_and_meta(ContentFile(self.TEXT), self.child) - self.parent.parts = parts - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) - parent_cover_changed.assert_called_with(child) - - # Now remove the child. - parent_cover_changed.reset_mock() - self.parent.parts = [] - parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) - parent_cover_changed.assert_called_with(child) diff --git a/src/catalogue/tests/files/fraszka-do-anusie.xml b/src/catalogue/tests/files/fraszka-do-anusie.xml old mode 100755 new mode 100644 diff --git a/src/catalogue/tests/files/fraszki.xml b/src/catalogue/tests/files/fraszki.xml old mode 100755 new mode 100644 diff --git a/src/catalogue/tests/tags.py b/src/catalogue/tests/tags.py deleted file mode 100644 index d5aa72c49..000000000 --- a/src/catalogue/tests/tags.py +++ /dev/null @@ -1,284 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from unittest import skip - -from django.core.files.base import ContentFile -from django.test import Client -from catalogue import models -from catalogue.test_utils import * - - -class BooksByTagTests(WLTestCase): - """ tests the /katalog/category/tag page for found books """ - - def setUp(self): - WLTestCase.setUp(self) - author = PersonStub(("Common",), "Man") - - # grandchild - self.gchild_info = BookInfoStub(genre='Genre', epoch='Epoch', kind='Kind', author=author, - **info_args("GChild")) - # child - self.child_info = BookInfoStub(genre='Genre', epoch='Epoch', kind='Other Kind', author=author, - parts=[self.gchild_info.url], - **info_args("Child")) - # parent - self.parent_info = BookInfoStub(genre='Genre', epoch='Epoch', kind='Kind', author=author, - parts=[self.child_info.url], - **info_args("Parent")) - - self.book_file = ContentFile('') - - def test_nonexistent_tag(self): - """ Looking for a non-existent tag should yield 404 """ - self.assertEqual(404, self.client.get('/katalog/autor/czeslaw-milosz/').status_code) - - def test_book_tag(self): - """ Looking for a book tag isn't permitted """ - models.Book.from_text_and_meta(self.book_file, self.gchild_info) - self.assertEqual(404, self.client.get('/katalog/gchild/').status_code) - - def test_tag_empty(self): - """ Tag with no books should return no books """ - models.Book.from_text_and_meta(self.book_file, self.gchild_info) - models.Tag.objects.create(name='Empty tag', slug='empty', category='author') - - context = self.client.get('/katalog/autor/empty/').context - self.assertEqual(0, len(context['object_list'])) - - def test_tag_eliminate(self): - """ Filtering by tag should only yield top-level qualifying books. """ - for info in self.gchild_info, self.child_info, self.parent_info: - models.Book.from_text_and_meta(self.book_file, info) - - # all three qualify - context = self.client.get('/katalog/gatunek/genre/').context - self.assertEqual([book.title for book in context['object_list']], - ['Parent']) - - # parent and gchild qualify, child doesn't - context = self.client.get('/katalog/rodzaj/kind/').context - self.assertEqual([book.title for book in context['object_list']], - ['Parent']) - - # Filtering by child's tag should yield the child - context = self.client.get('/katalog/rodzaj/other-kind/').context - self.assertEqual([book.title for book in context['object_list']], - ['Child']) - - -class TagRelatedTagsTests(WLTestCase): - """ tests the /katalog/category/tag/ page for related tags """ - - def setUp(self): - WLTestCase.setUp(self) - self.client = Client() - author = PersonStub(("Common",), "Man") - - gchild_info = BookInfoStub(author=author, genre="GchildGenre", epoch='Epoch', kind="Kind", - **info_args(u"GChild")) - child1_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind", - parts=[gchild_info.url], - **info_args(u"Child1")) - child2_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind", - **info_args(u"Child2")) - parent_info = BookInfoStub(author=author, genre="Genre", epoch='Epoch', kind="Kind", - parts=[child1_info.url, child2_info.url], - **info_args(u"Parent")) - - for info in gchild_info, child1_info, child2_info, parent_info: - book_text = """ - - Theme, %sTheme - Ala ma kota - - - """ % info.title.encode('utf-8') - book = models.Book.from_text_and_meta(ContentFile(book_text), info) - book.save() - - tag_empty = models.Tag(name='Empty tag', slug='empty', category='author') - tag_empty.save() - - def test_empty(self): - """ empty tag should have no related tags """ - - cats = self.client.get('/katalog/autor/empty/').context['categories'] - self.assertEqual({k: v for (k, v) in cats.items() if v}, {}, 'tags related to empty tag') - - def test_has_related(self): - """ related own and descendants' tags should be generated """ - - cats = self.client.get('/katalog/rodzaj/kind/').context['categories'] - self.assertTrue('Common Man' in [tag.name for tag in cats['author']], - 'missing `author` related tag') - self.assertTrue('Epoch' in [tag.name for tag in cats['epoch']], - 'missing `epoch` related tag') - self.assertFalse(cats.get("kind", False), - "There should be no child-only related `kind` tags") - self.assertTrue("Genre" in [tag.name for tag in cats['genre']], - 'missing `genre` related tag') - self.assertFalse("ChildGenre" in [tag.name for tag in cats['genre']], - "There should be no child-only related `genre` tags") - self.assertTrue("GchildGenre" in [tag.name for tag in cats['genre']], - "missing grandchild's related tag") - self.assertTrue('Theme' in [tag.name for tag in cats['theme']], - "missing related theme") - self.assertFalse('Child1Theme' in [tag.name for tag in cats['theme']], - "There should be no child-only related `theme` tags") - self.assertTrue('GChildTheme' in [tag.name for tag in cats['theme']], - "missing grandchild's related theme") - - def test_related_differ(self): - """ related tags shouldn't include filtering tags """ - - response = self.client.get('/katalog/rodzaj/kind/') - cats = response.context['categories'] - self.assertFalse(cats.get('kind', False), - 'filtering tag wrongly included in related') - cats = self.client.get('/katalog/motyw/theme/').context['categories'] - self.assertFalse('Theme' in [tag.name for tag in cats['theme']], - 'filtering theme wrongly included in related') - - def test_parent_tag_once(self): - """ if parent and descendants have a common tag, count it only once """ - - cats = self.client.get('/katalog/rodzaj/kind/').context['categories'] - self.assertEqual([(tag.name, tag.count) for tag in cats['epoch']], - [('Epoch', 1)], - 'wrong related tag epoch tag on tag page') - - def test_siblings_tags_count(self): - """ if children have tags and parent hasn't, count the children """ - - cats = self.client.get('/katalog/epoka/epoch/').context['categories'] - self.assertTrue( - ('ChildKind', 2) in [(tag.name, tag.count) for tag in cats['kind']], - 'wrong related kind tags on tag page, got: ' + - unicode([(tag.name, tag.count) for tag in cats['kind']])) - - # all occurencies of theme should be counted - self.assertTrue(('Theme', 4) in [(tag.name, tag.count) for tag in cats['theme']], - 'wrong related theme count') - - def test_query_child_tag(self): - """ - If child and parent have a common tag, but parent isn't included - in the result, child should still count. - """ - cats = self.client.get('/katalog/gatunek/childgenre/').context['categories'] - self.assertTrue(('Epoch', 2) in [(tag.name, tag.count) for tag in cats['epoch']], - 'wrong related kind tags on tag page, got: ' + - unicode([(tag.name, tag.count) for tag in cats['epoch']])) - - -class CleanTagRelationTests(WLTestCase): - """ tests for tag relations cleaning after deleting things """ - - def setUp(self): - WLTestCase.setUp(self) - author = PersonStub(("Common",), "Man") - - book_info = BookInfoStub(author=author, genre="G", epoch='E', kind="K", **info_args(u"Book")) - book_text = """ - ThemeAla ma kota - - - """ - self.book = models.Book.from_text_and_meta(ContentFile(book_text), book_info) - - @skip('Not implemented and not priority') - def test_delete_objects(self): - """ there should be no related tags left after deleting some objects """ - - models.Book.objects.all().delete() - cats = self.client.get('/katalog/rodzaj/k/').context['categories'] - self.assertEqual({k: v for (k, v) in cats.items() if v}, {}) - self.assertEqual(models.Fragment.objects.all().count(), 0, - "orphaned fragments left") - self.assertEqual(models.Tag.intermediary_table_model.objects.all().count(), 0, - "orphaned TagRelation objects left") - - def test_deleted_tag(self): - """ there should be no tag relations left after deleting tags """ - - models.Tag.objects.all().delete() - self.assertEqual(len(self.book.related_themes()), 0) - self.assertEqual(models.Tag.intermediary_table_model.objects.all().count(), 0, - "orphaned TagRelation objects left") - - -class TestIdenticalTag(WLTestCase): - - def setUp(self): - WLTestCase.setUp(self) - author = PersonStub((), "Tag") - - self.book_info = BookInfoStub(author=author, genre="tag", epoch='tag', kind="tag", **info_args(u"tag")) - self.book_text = """ - - - tagAla ma kota - - - - """ - - def test_book_tags(self): - """ there should be all related tags in relevant categories """ - book = models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info) - - related_themes = book.related_themes() - for category in 'author', 'kind', 'genre', 'epoch': - self.assertTrue('tag' in book.tags.filter(category=category).values_list('slug', flat=True), - 'missing related tag for %s' % category) - self.assertTrue('tag' in [tag.slug for tag in related_themes]) - - def test_qualified_url(self): - models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info) - categories = {'author': 'autor', 'theme': 'motyw', 'epoch': 'epoka', 'kind': 'rodzaj', 'genre': 'gatunek'} - for cat, localcat in categories.iteritems(): - context = self.client.get('/katalog/%s/tag/' % localcat).context - self.assertEqual(1, len(context['object_list'])) - self.assertNotEqual({}, context['categories']) - self.assertFalse(context['categories'].get(cat, False)) - - -class BookTagsTests(WLTestCase): - """ tests the /katalog/lektura/book/ page for related tags """ - - def setUp(self): - WLTestCase.setUp(self) - author1 = PersonStub(("Common",), "Man") - author2 = PersonStub(("Jim",), "Lazy") - - child_info = BookInfoStub(authors=(author1, author2), genre="ChildGenre", epoch='Epoch', kind="ChildKind", - **info_args(u"Child")) - parent_info = BookInfoStub(author=author1, genre="Genre", epoch='Epoch', kind="Kind", - parts=[child_info.url], - **info_args(u"Parent")) - - for info in child_info, parent_info: - book_text = """ - - Theme, %sTheme - Ala ma kota - - - """ % info.title.encode('utf-8') - models.Book.from_text_and_meta(ContentFile(book_text), info) - - def test_book_tags(self): - """ book should have own tags and whole tree's themes """ - - book = models.Book.objects.get(slug='parent') - related_themes = book.related_themes() - - self.assertEqual([t.slug for t in book.authors()], - ['common-man']) - self.assertEqual([t.slug for t in book.tags.filter(category='kind')], - ['kind']) - self.assertEqual([(tag.name, tag.count) for tag in related_themes], - [('ChildTheme', 1), ('ParentTheme', 1), ('Theme', 2)]) diff --git a/src/catalogue/tests/templatetags.py b/src/catalogue/tests/templatetags.py deleted file mode 100644 index c69472fac..000000000 --- a/src/catalogue/tests/templatetags.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from catalogue import models -from catalogue.templatetags import catalogue_tags -from catalogue.test_utils import * -from django.core.files.base import ContentFile - - -class BookDescTests(WLTestCase): - """ tests book_title template tag """ - - def setUp(self): - WLTestCase.setUp(self) - authors = PersonStub(("Common",), "Man"), PersonStub(("Jane",), "Doe") - - child_info = BookInfoStub(authors=authors, genre="Genre", epoch='Epoch', kind="Kind", - **info_args(u"Child")) - parent_info = BookInfoStub(authors=authors, genre="Genre", epoch='Epoch', kind="Kind", - parts=[child_info.url], - **info_args(u"Parent")) - - self.child = models.Book.from_text_and_meta(ContentFile(''), child_info) - models.Book.from_text_and_meta(ContentFile(''), parent_info) - self.child = models.Book.objects.get(pk=self.child.pk) - - def test_book_desc(self): - """ book description should return authors, ancestors, book """ - self.assertEqual(catalogue_tags.book_title(self.child), 'Jane Doe, Common Man, Parent, Child') diff --git a/src/catalogue/tests/test_book_import.py b/src/catalogue/tests/test_book_import.py new file mode 100644 index 000000000..da5e58621 --- /dev/null +++ b/src/catalogue/tests/test_book_import.py @@ -0,0 +1,431 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django.core.files.base import ContentFile +from catalogue.test_utils import * +from catalogue import models +from librarian import WLURI + +from os import path, makedirs + + +class BookImportLogicTests(WLTestCase): + + def setUp(self): + WLTestCase.setUp(self) + self.book_info = BookInfoStub( + url=WLURI.from_slug(u"default-book"), + about=u"http://wolnelektury.pl/example/URI/default_book", + title=u"Default Book", + author=PersonStub(("Jim",), "Lazy"), + kind="X-Kind", + genre="X-Genre", + epoch="X-Epoch", + language=u"pol", + ) + + self.expected_tags = [ + ('author', 'jim-lazy'), + ('genre', 'x-genre'), + ('epoch', 'x-epoch'), + ('kind', 'x-kind'), + ] + self.expected_tags.sort() + + def test_empty_book(self): + book_text = "" + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + + self.assertEqual(book.title, "Default Book") + self.assertEqual(book.slug, "default-book") + self.assert_(book.parent is None) + self.assertFalse(book.has_html_file()) + + # no fragments generated + self.assertEqual(book.fragments.count(), 0) + + # TODO: this should be filled out probably... + self.assertEqual(book.wiki_link, '') + self.assertEqual(book.gazeta_link, '') + self.assertEqual(book.description, '') + + tags = [(tag.category, tag.slug) for tag in book.tags] + tags.sort() + + self.assertEqual(tags, self.expected_tags) + + def test_not_quite_empty_book(self): + """ Not empty, but without any real text. + + Should work like any other non-empty book. + """ + + book_text = """ + + Nic + + """ + + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.assertTrue(book.has_html_file()) + + def test_book_with_fragment(self): + book_text = """ + + LoveAla ma kota + + """ + + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.assertTrue(book.has_html_file()) + + self.assertEqual(book.fragments.count(), 1) + self.assertEqual(book.fragments.all()[0].text, u'

Ala ma kota

\n') + + self.assert_(('theme', 'love') in [(tag.category, tag.slug) for tag in book.fragments.all()[0].tags]) + + def test_book_with_empty_theme(self): + """ empty themes should be ignored """ + + book_text = """ + + , Love , , Ala ma kota + + """ + + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.assert_([('theme', 'love')], + book.fragments.all()[0].tags.filter(category='theme').values_list('category', 'slug')) + + def test_book_with_no_theme(self): + """ fragments with no themes shouldn't be created at all """ + + book_text = """ + + Ala ma kota + + """ + + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.assertEqual(book.fragments.count(), 0) + self.assertEqual(book.tags.filter(category='theme').count(), 0) + + def test_book_with_invalid_slug(self): + """ Book with invalid characters in slug shouldn't be imported """ + self.book_info.url = WLURI.from_slug(u"default_book") + book_text = "" + with self.assertRaises(ValueError): + models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + + def test_book_replace_title(self): + book_text = """""" + models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.book_info.title = u"Extraordinary" + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True) + + tags = [(tag.category, tag.slug) for tag in book.tags] + tags.sort() + + self.assertEqual(tags, self.expected_tags) + + def test_book_replace_author(self): + book_text = """""" + models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen") + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True) + + tags = [(tag.category, tag.slug) for tag in book.tags] + tags.sort() + + self.expected_tags.remove(('author', 'jim-lazy')) + self.expected_tags.append(('author', 'hans-christian-andersen')) + self.expected_tags.sort() + + self.assertEqual(tags, self.expected_tags) + + # the old tag shouldn't disappear + models.Tag.objects.get(slug="jim-lazy", category="author") + + def test_book_remove_fragment(self): + book_text = """ + + + LoveAla ma kota + HatredTo kot Ali + + + """ + book_text_after = """ + + + LoveAla ma kota + To kot Ali + + + """ + + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + self.assertEqual(book.fragments.count(), 2) + book = models.Book.from_text_and_meta(ContentFile(book_text_after), self.book_info, overwrite=True) + self.assertEqual(book.fragments.count(), 1) + + def test_multiple_tags(self): + book_text = """""" + self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"), + self.book_info.kinds = self.book_info.kind, 'Y-Kind', + self.book_info.genres = self.book_info.genre, 'Y-Genre', + self.book_info.epochs = self.book_info.epoch, 'Y-Epoch', + + self.expected_tags.extend([ + ('author', 'joe-dilligent'), + ('genre', 'y-genre'), + ('epoch', 'y-epoch'), + ('kind', 'y-kind'), + ]) + self.expected_tags.sort() + + book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info) + tags = [(tag.category, tag.slug) for tag in book.tags] + tags.sort() + + self.assertEqual(tags, self.expected_tags) + + +class ChildImportTests(WLTestCase): + + def setUp(self): + WLTestCase.setUp(self) + self.child_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Joe",), "Doe"), + **info_args("Child") + ) + + self.parent_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Jim",), "Lazy"), + parts=[self.child_info.url], + **info_args("Parent") + ) + + def test_child(self): + text = """""" + child = models.Book.from_text_and_meta(ContentFile(text), self.child_info) + parent = models.Book.from_text_and_meta(ContentFile(text), self.parent_info) + author = parent.tags.get(category='author') + books = self.client.get(author.get_absolute_url()).context['object_list'] + self.assertEqual(len(books), 1, "Only parent book should be visible on author's page") + + def test_child_replace(self): + parent_text = """""" + child_text = """ + + PiesAla ma kota + + """ + child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info) + parent = models.Book.from_text_and_meta(ContentFile(parent_text), self.parent_info) + child_text = """ + + KotAla ma kota + + """ + child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info, overwrite=True) + themes = parent.related_themes() + self.assertEqual(['Kot'], [tag.name for tag in themes], 'wrong related theme list') + + +class TreeImportTest(WLTestCase): + def setUp(self): + WLTestCase.setUp(self) + self.child_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Joe",), "Doe"), + **info_args("Child") + ) + self.CHILD_TEXT = """ + + Pies + Ala ma kota + + """ + self.child = models.Book.from_text_and_meta( + ContentFile(self.CHILD_TEXT), self.child_info) + + self.book_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Joe",), "Doe"), + parts=[self.child_info.url], + **info_args("Book") + ) + self.BOOK_TEXT = """""" + self.book = models.Book.from_text_and_meta( + ContentFile(self.BOOK_TEXT), self.book_info) + + self.parent_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Jim",), "Lazy"), + parts=[self.book_info.url], + **info_args("Parent") + ) + self.PARENT_TEXT = """""" + self.parent = models.Book.from_text_and_meta( + ContentFile(self.PARENT_TEXT), self.parent_info) + + def test_ok(self): + self.assertEqual( + list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']), + [self.parent], + u"There should be only parent on common tag page." + ) + # pies = models.Tag.objects.get(slug='pies') + themes = self.parent.related_themes() + self.assertEqual(len(themes), 1, u"There should be child theme in parent theme counter.") + # TODO: book_count is deprecated, update here. + # epoch = models.Tag.objects.get(slug='x-epoch') + # self.assertEqual(epoch.book_count, 1, u"There should be only parent in common tag's counter.") + + def test_child_republish(self): + child_text = """ + + Pies, Kot + Ala ma kota + + """ + models.Book.from_text_and_meta( + ContentFile(child_text), self.child_info, overwrite=True) + self.assertEqual( + list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']), + [self.parent], + u"There should only be parent on common tag page." + ) + # pies = models.Tag.objects.get(slug='pies') + # kot = models.Tag.objects.get(slug='kot') + self.assertEqual(len(self.parent.related_themes()), 2, + u"There should be child themes in parent theme counter.") + # TODO: book_count is deprecated, update here. + # epoch = models.Tag.objects.get(slug='x-epoch') + # self.assertEqual(epoch.book_count, 1, u"There should only be parent in common tag's counter.") + + def test_book_change_child(self): + second_child_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='Other-Kind', + author=PersonStub(("Joe",), "Doe"), + **info_args("Second Child") + ) + second_child_text = """ + + Kot + Ala ma kota + + """ + # Import a second child. + second_child = models.Book.from_text_and_meta( + ContentFile(second_child_text), second_child_info) + # The book has only this new child now. + self.book_info.parts = [second_child_info.url] + self.book = models.Book.from_text_and_meta( + ContentFile(self.BOOK_TEXT), self.book_info, overwrite=True) + + self.assertEqual( + set(self.client.get('/katalog/gatunek/x-genre/').context['object_list']), + {self.parent, self.child}, + u"There should be parent and old child on common tag page." + ) + # kot = models.Tag.objects.get(slug='kot') + self.assertEqual(len(self.parent.related_themes()), 1, + u"There should only be new child themes in parent theme counter.") + # # book_count deprecated, update test. + # epoch = models.Tag.objects.get(slug='x-epoch') + # self.assertEqual(epoch.book_count, 2, + # u"There should be parent and old child in common tag's counter.") + self.assertEqual( + list(self.client.get('/katalog/lektura/parent/motyw/kot/').context['fragments']), + [second_child.fragments.all()[0]], + u"There should be new child's fragments on parent's theme page." + ) + self.assertEqual( + list(self.client.get('/katalog/lektura/parent/motyw/pies/').context['fragments']), + [], + u"There should be no old child's fragments on parent's theme page." + ) + + +class MultilingualBookImportTest(WLTestCase): + def setUp(self): + WLTestCase.setUp(self) + common_uri = WLURI.from_slug('common-slug') + + self.pol_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Joe",), "Doe"), + variant_of=common_uri, + **info_args(u"Książka") + ) + + self.eng_info = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Joe",), "Doe"), + variant_of=common_uri, + **info_args("A book", "eng") + ) + + def test_multilingual_import(self): + book_text = """A""" + + models.Book.from_text_and_meta(ContentFile(book_text), self.pol_info) + models.Book.from_text_and_meta(ContentFile(book_text), self.eng_info) + + self.assertEqual( + set([b.language for b in models.Book.objects.all()]), + {'pol', 'eng'}, + 'Books imported in wrong languages.' + ) + + +class BookImportGenerateTest(WLTestCase): + def setUp(self): + WLTestCase.setUp(self) + xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml') + self.book = models.Book.from_xml_file(xml) + + def test_gen_pdf(self): + self.book.pdf_file.build() + book = models.Book.objects.get(pk=self.book.pk) + self.assertTrue(path.exists(book.pdf_file.path)) + + def test_gen_pdf_parent(self): + """This book contains a child.""" + xml = path.join(path.dirname(__file__), "files/fraszki.xml") + parent = models.Book.from_xml_file(xml) + parent.pdf_file.build() + parent = models.Book.objects.get(pk=parent.pk) + self.assertTrue(path.exists(parent.pdf_file.path)) + + def test_custom_pdf(self): + from catalogue.tasks import build_custom_pdf + out = 'test-custom.pdf' + absoulute_path = path.join(settings.MEDIA_ROOT, out) + + if not path.exists(path.dirname(absoulute_path)): + makedirs(path.dirname(absoulute_path)) + + build_custom_pdf(self.book.id, customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out) + self.assertTrue(path.exists(absoulute_path)) diff --git a/src/catalogue/tests/test_bookmedia.py b/src/catalogue/tests/test_bookmedia.py new file mode 100644 index 000000000..263e48d9a --- /dev/null +++ b/src/catalogue/tests/test_bookmedia.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from os.path import basename, exists +from unittest import skip + +from django.core.files.base import ContentFile + +from catalogue.test_utils import * +from catalogue import models, utils + + +class BookMediaTests(WLTestCase): + + def setUp(self): + WLTestCase.setUp(self) + self.file = ContentFile('X') + self.file2 = ContentFile('Y') + self.book = models.Book.objects.create(slug='test-book', title='Test') + + def set_title(self, title): + self.book.title = title + self.book.save() + + def test_diacritics(self): + bm = models.BookMedia(book=self.book, type="ogg", name=u"Zażółć gęślą jaźń") + self.set_title(bm.name) + bm.file.save(None, self.file) + self.assertEqual(basename(bm.file.name), 'zazolc-gesla-jazn.ogg') + + def test_long_name(self): + bm = models.BookMedia( + book=self.book, type="ogg", + name="Some very very very very very very very very very very very very very very very very long file name") + self.set_title(bm.name) + bm.file.save(bm.name, self.file) + + # reload to see what was really saved + bm = models.BookMedia.objects.get(pk=bm.pk) + self.assertEqual(bm.file.size, 1) + + def test_overwrite(self): + """ + File gets overwritten with same filename on update. + """ + + bm = models.BookMedia(book=self.book, type='ogg', name="Some media") + self.set_title(bm.name) + bm.file.save(None, self.file) + bm.file.save(None, self.file2) + + self.assertEqual(bm.file.read(), 'Y') + self.assertEqual(basename(bm.file.name), 'some-media.ogg') + + @skip('broken, but is it needed?') + def test_no_clobber(self): + """ + File save doesn't clobber some other media with similar name. + """ + + bm = models.BookMedia(book=self.book, type='ogg', name=u"Tytul") + self.set_title(bm.name) + bm.file.save(None, self.file) + bm2 = models.BookMedia(book=self.book, type='ogg', name=u"Tytuł") + self.set_title(bm2.name) + bm2.file.save(None, self.file2) + self.assertEqual(basename(bm.file.name), 'tytul.ogg') + self.assertNotEqual(basename(bm2.file.name), 'tytul.ogg') + self.assertEqual(bm.file.read(), 'X') + self.assertEqual(bm2.file.read(), 'Y') + + def test_change_name(self): + """ + File name reflects name change. + """ + + bm = models.BookMedia(book=self.book, type='ogg', name="Title") + self.set_title(bm.name) + bm.file.save(None, self.file) + self.set_title("Other Title") + bm.save() + self.assertEqual(basename(bm.file.name), 'other-title.ogg') + self.assertEqual(bm.file.read(), 'X') + + @skip('broken, but is it needed?') + def test_change_name_no_clobber(self): + """ + File name after change won't clobber some other file + with similar name. + """ + + bm = models.BookMedia(book=self.book, type='ogg', name="Title") + self.set_title(bm.name) + bm.file.save(None, self.file) + bm2 = models.BookMedia(book=self.book, type='ogg', name="Other title") + self.set_title(bm2.name) + bm2.file.save(None, self.file2) + self.set_title("Title") + bm2.save() + self.assertNotEqual(basename(bm2.file.name), 'title.ogg') + self.assertEqual(bm.file.read(), 'X') + self.assertEqual(bm2.file.read(), 'Y') + + def test_zip_audiobooks(self): + paths = [ + (None, join(dirname(__file__), "files/fraszka-do-anusie.xml")), + (None, join(dirname(__file__), "files/fraszki.xml")), + ] + + url = utils.create_zip(paths, 'test-zip-slug') + self.assertEqual("zip/test-zip-slug.zip", url) + self.assertTrue(exists(join(settings.MEDIA_ROOT, url))) + + utils.remove_zip('test-zip-slug') + self.assertFalse(exists(join(settings.MEDIA_ROOT, url))) + + def test_remove_zip_on_media_change(self): + bm = models.BookMedia(book=self.book, type='ogg', name="Title") + self.set_title(bm.name) + bm.file.save(None, self.file) + bm.save() + + zip_url = self.book.zip_audiobooks('ogg') + self.assertEqual('zip/'+self.book.slug+'_ogg.zip', zip_url) + self.assertTrue(exists(join(settings.MEDIA_ROOT, zip_url))) + + bm2 = models.BookMedia(book=self.book, type='ogg', name="Other title") + self.set_title(bm2.name) + bm2.file.save(None, self.file2) + self.set_title("Title") + bm2.save() + # was the audiobook zip deleted? + self.assertFalse(exists(join(settings.MEDIA_ROOT, zip_url))) diff --git a/src/catalogue/tests/test_cover.py b/src/catalogue/tests/test_cover.py new file mode 100644 index 000000000..8c5d04718 --- /dev/null +++ b/src/catalogue/tests/test_cover.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django.core.files.base import ContentFile +from catalogue.test_utils import BookInfoStub, PersonStub, info_args, WLTestCase +from catalogue.models import Book +from mock import patch + + +class CoverTests(WLTestCase): + """Checks in parent_cover_changed is properly called.""" + def setUp(self): + WLTestCase.setUp(self) + self.TEXT = """""" + self.child = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Joe",), "Doe"), + **info_args("Child") + ) + + self.parent = BookInfoStub( + genre='X-Genre', + epoch='X-Epoch', + kind='X-Kind', + author=PersonStub(("Jim",), "Lazy"), + cover_url="http://example.com/cover.jpg", + parts=[self.child.url], + **info_args("Parent") + ) + + @patch.object(Book, 'parent_cover_changed', autospec=True) + def test_simple_import(self, parent_cover_changed): + child = Book.from_text_and_meta(ContentFile(self.TEXT), self.child) + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent) + parent_cover_changed.assert_called_with(child) + + # Now reimport parent. + parent_cover_changed.reset_mock() + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) + self.assertEqual(parent_cover_changed.call_count, 0) + + # Now change cover in parent. + parent_cover_changed.reset_mock() + self.parent.cover_url = "http://example.com/other-cover.jpg" + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) + parent_cover_changed.assert_called_with(child) + + @patch.object(Book, 'parent_cover_changed', autospec=True) + def test_change_cover(self, parent_cover_changed): + child = Book.from_text_and_meta(ContentFile(self.TEXT), self.child) + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent) + parent_cover_changed.assert_called_with(child) + + @patch.object(Book, 'parent_cover_changed', autospec=True) + def test_new_child(self, parent_cover_changed): + # Add parent without child first. + parts, self.parent.parts = self.parent.parts, [] + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent) + + # Now import child and reimport parent. + child = Book.from_text_and_meta(ContentFile(self.TEXT), self.child) + self.parent.parts = parts + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) + parent_cover_changed.assert_called_with(child) + + # Now remove the child. + parent_cover_changed.reset_mock() + self.parent.parts = [] + parent = Book.from_text_and_meta(ContentFile(self.TEXT), self.parent, overwrite=True) + parent_cover_changed.assert_called_with(child) diff --git a/src/catalogue/tests/test_tags.py b/src/catalogue/tests/test_tags.py new file mode 100644 index 000000000..d5aa72c49 --- /dev/null +++ b/src/catalogue/tests/test_tags.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from unittest import skip + +from django.core.files.base import ContentFile +from django.test import Client +from catalogue import models +from catalogue.test_utils import * + + +class BooksByTagTests(WLTestCase): + """ tests the /katalog/category/tag page for found books """ + + def setUp(self): + WLTestCase.setUp(self) + author = PersonStub(("Common",), "Man") + + # grandchild + self.gchild_info = BookInfoStub(genre='Genre', epoch='Epoch', kind='Kind', author=author, + **info_args("GChild")) + # child + self.child_info = BookInfoStub(genre='Genre', epoch='Epoch', kind='Other Kind', author=author, + parts=[self.gchild_info.url], + **info_args("Child")) + # parent + self.parent_info = BookInfoStub(genre='Genre', epoch='Epoch', kind='Kind', author=author, + parts=[self.child_info.url], + **info_args("Parent")) + + self.book_file = ContentFile('') + + def test_nonexistent_tag(self): + """ Looking for a non-existent tag should yield 404 """ + self.assertEqual(404, self.client.get('/katalog/autor/czeslaw-milosz/').status_code) + + def test_book_tag(self): + """ Looking for a book tag isn't permitted """ + models.Book.from_text_and_meta(self.book_file, self.gchild_info) + self.assertEqual(404, self.client.get('/katalog/gchild/').status_code) + + def test_tag_empty(self): + """ Tag with no books should return no books """ + models.Book.from_text_and_meta(self.book_file, self.gchild_info) + models.Tag.objects.create(name='Empty tag', slug='empty', category='author') + + context = self.client.get('/katalog/autor/empty/').context + self.assertEqual(0, len(context['object_list'])) + + def test_tag_eliminate(self): + """ Filtering by tag should only yield top-level qualifying books. """ + for info in self.gchild_info, self.child_info, self.parent_info: + models.Book.from_text_and_meta(self.book_file, info) + + # all three qualify + context = self.client.get('/katalog/gatunek/genre/').context + self.assertEqual([book.title for book in context['object_list']], + ['Parent']) + + # parent and gchild qualify, child doesn't + context = self.client.get('/katalog/rodzaj/kind/').context + self.assertEqual([book.title for book in context['object_list']], + ['Parent']) + + # Filtering by child's tag should yield the child + context = self.client.get('/katalog/rodzaj/other-kind/').context + self.assertEqual([book.title for book in context['object_list']], + ['Child']) + + +class TagRelatedTagsTests(WLTestCase): + """ tests the /katalog/category/tag/ page for related tags """ + + def setUp(self): + WLTestCase.setUp(self) + self.client = Client() + author = PersonStub(("Common",), "Man") + + gchild_info = BookInfoStub(author=author, genre="GchildGenre", epoch='Epoch', kind="Kind", + **info_args(u"GChild")) + child1_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind", + parts=[gchild_info.url], + **info_args(u"Child1")) + child2_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind", + **info_args(u"Child2")) + parent_info = BookInfoStub(author=author, genre="Genre", epoch='Epoch', kind="Kind", + parts=[child1_info.url, child2_info.url], + **info_args(u"Parent")) + + for info in gchild_info, child1_info, child2_info, parent_info: + book_text = """ + + Theme, %sTheme + Ala ma kota + + + """ % info.title.encode('utf-8') + book = models.Book.from_text_and_meta(ContentFile(book_text), info) + book.save() + + tag_empty = models.Tag(name='Empty tag', slug='empty', category='author') + tag_empty.save() + + def test_empty(self): + """ empty tag should have no related tags """ + + cats = self.client.get('/katalog/autor/empty/').context['categories'] + self.assertEqual({k: v for (k, v) in cats.items() if v}, {}, 'tags related to empty tag') + + def test_has_related(self): + """ related own and descendants' tags should be generated """ + + cats = self.client.get('/katalog/rodzaj/kind/').context['categories'] + self.assertTrue('Common Man' in [tag.name for tag in cats['author']], + 'missing `author` related tag') + self.assertTrue('Epoch' in [tag.name for tag in cats['epoch']], + 'missing `epoch` related tag') + self.assertFalse(cats.get("kind", False), + "There should be no child-only related `kind` tags") + self.assertTrue("Genre" in [tag.name for tag in cats['genre']], + 'missing `genre` related tag') + self.assertFalse("ChildGenre" in [tag.name for tag in cats['genre']], + "There should be no child-only related `genre` tags") + self.assertTrue("GchildGenre" in [tag.name for tag in cats['genre']], + "missing grandchild's related tag") + self.assertTrue('Theme' in [tag.name for tag in cats['theme']], + "missing related theme") + self.assertFalse('Child1Theme' in [tag.name for tag in cats['theme']], + "There should be no child-only related `theme` tags") + self.assertTrue('GChildTheme' in [tag.name for tag in cats['theme']], + "missing grandchild's related theme") + + def test_related_differ(self): + """ related tags shouldn't include filtering tags """ + + response = self.client.get('/katalog/rodzaj/kind/') + cats = response.context['categories'] + self.assertFalse(cats.get('kind', False), + 'filtering tag wrongly included in related') + cats = self.client.get('/katalog/motyw/theme/').context['categories'] + self.assertFalse('Theme' in [tag.name for tag in cats['theme']], + 'filtering theme wrongly included in related') + + def test_parent_tag_once(self): + """ if parent and descendants have a common tag, count it only once """ + + cats = self.client.get('/katalog/rodzaj/kind/').context['categories'] + self.assertEqual([(tag.name, tag.count) for tag in cats['epoch']], + [('Epoch', 1)], + 'wrong related tag epoch tag on tag page') + + def test_siblings_tags_count(self): + """ if children have tags and parent hasn't, count the children """ + + cats = self.client.get('/katalog/epoka/epoch/').context['categories'] + self.assertTrue( + ('ChildKind', 2) in [(tag.name, tag.count) for tag in cats['kind']], + 'wrong related kind tags on tag page, got: ' + + unicode([(tag.name, tag.count) for tag in cats['kind']])) + + # all occurencies of theme should be counted + self.assertTrue(('Theme', 4) in [(tag.name, tag.count) for tag in cats['theme']], + 'wrong related theme count') + + def test_query_child_tag(self): + """ + If child and parent have a common tag, but parent isn't included + in the result, child should still count. + """ + cats = self.client.get('/katalog/gatunek/childgenre/').context['categories'] + self.assertTrue(('Epoch', 2) in [(tag.name, tag.count) for tag in cats['epoch']], + 'wrong related kind tags on tag page, got: ' + + unicode([(tag.name, tag.count) for tag in cats['epoch']])) + + +class CleanTagRelationTests(WLTestCase): + """ tests for tag relations cleaning after deleting things """ + + def setUp(self): + WLTestCase.setUp(self) + author = PersonStub(("Common",), "Man") + + book_info = BookInfoStub(author=author, genre="G", epoch='E', kind="K", **info_args(u"Book")) + book_text = """ + ThemeAla ma kota + + + """ + self.book = models.Book.from_text_and_meta(ContentFile(book_text), book_info) + + @skip('Not implemented and not priority') + def test_delete_objects(self): + """ there should be no related tags left after deleting some objects """ + + models.Book.objects.all().delete() + cats = self.client.get('/katalog/rodzaj/k/').context['categories'] + self.assertEqual({k: v for (k, v) in cats.items() if v}, {}) + self.assertEqual(models.Fragment.objects.all().count(), 0, + "orphaned fragments left") + self.assertEqual(models.Tag.intermediary_table_model.objects.all().count(), 0, + "orphaned TagRelation objects left") + + def test_deleted_tag(self): + """ there should be no tag relations left after deleting tags """ + + models.Tag.objects.all().delete() + self.assertEqual(len(self.book.related_themes()), 0) + self.assertEqual(models.Tag.intermediary_table_model.objects.all().count(), 0, + "orphaned TagRelation objects left") + + +class TestIdenticalTag(WLTestCase): + + def setUp(self): + WLTestCase.setUp(self) + author = PersonStub((), "Tag") + + self.book_info = BookInfoStub(author=author, genre="tag", epoch='tag', kind="tag", **info_args(u"tag")) + self.book_text = """ + + + tagAla ma kota + + + + """ + + def test_book_tags(self): + """ there should be all related tags in relevant categories """ + book = models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info) + + related_themes = book.related_themes() + for category in 'author', 'kind', 'genre', 'epoch': + self.assertTrue('tag' in book.tags.filter(category=category).values_list('slug', flat=True), + 'missing related tag for %s' % category) + self.assertTrue('tag' in [tag.slug for tag in related_themes]) + + def test_qualified_url(self): + models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info) + categories = {'author': 'autor', 'theme': 'motyw', 'epoch': 'epoka', 'kind': 'rodzaj', 'genre': 'gatunek'} + for cat, localcat in categories.iteritems(): + context = self.client.get('/katalog/%s/tag/' % localcat).context + self.assertEqual(1, len(context['object_list'])) + self.assertNotEqual({}, context['categories']) + self.assertFalse(context['categories'].get(cat, False)) + + +class BookTagsTests(WLTestCase): + """ tests the /katalog/lektura/book/ page for related tags """ + + def setUp(self): + WLTestCase.setUp(self) + author1 = PersonStub(("Common",), "Man") + author2 = PersonStub(("Jim",), "Lazy") + + child_info = BookInfoStub(authors=(author1, author2), genre="ChildGenre", epoch='Epoch', kind="ChildKind", + **info_args(u"Child")) + parent_info = BookInfoStub(author=author1, genre="Genre", epoch='Epoch', kind="Kind", + parts=[child_info.url], + **info_args(u"Parent")) + + for info in child_info, parent_info: + book_text = """ + + Theme, %sTheme + Ala ma kota + + + """ % info.title.encode('utf-8') + models.Book.from_text_and_meta(ContentFile(book_text), info) + + def test_book_tags(self): + """ book should have own tags and whole tree's themes """ + + book = models.Book.objects.get(slug='parent') + related_themes = book.related_themes() + + self.assertEqual([t.slug for t in book.authors()], + ['common-man']) + self.assertEqual([t.slug for t in book.tags.filter(category='kind')], + ['kind']) + self.assertEqual([(tag.name, tag.count) for tag in related_themes], + [('ChildTheme', 1), ('ParentTheme', 1), ('Theme', 2)]) diff --git a/src/catalogue/tests/test_templatetags.py b/src/catalogue/tests/test_templatetags.py new file mode 100644 index 000000000..c69472fac --- /dev/null +++ b/src/catalogue/tests/test_templatetags.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from catalogue import models +from catalogue.templatetags import catalogue_tags +from catalogue.test_utils import * +from django.core.files.base import ContentFile + + +class BookDescTests(WLTestCase): + """ tests book_title template tag """ + + def setUp(self): + WLTestCase.setUp(self) + authors = PersonStub(("Common",), "Man"), PersonStub(("Jane",), "Doe") + + child_info = BookInfoStub(authors=authors, genre="Genre", epoch='Epoch', kind="Kind", + **info_args(u"Child")) + parent_info = BookInfoStub(authors=authors, genre="Genre", epoch='Epoch', kind="Kind", + parts=[child_info.url], + **info_args(u"Parent")) + + self.child = models.Book.from_text_and_meta(ContentFile(''), child_info) + models.Book.from_text_and_meta(ContentFile(''), parent_info) + self.child = models.Book.objects.get(pk=self.child.pk) + + def test_book_desc(self): + """ book description should return authors, ancestors, book """ + self.assertEqual(catalogue_tags.book_title(self.child), 'Jane Doe, Common Man, Parent, Child') diff --git a/src/catalogue/tests/test_visit.py b/src/catalogue/tests/test_visit.py new file mode 100644 index 000000000..5e640adad --- /dev/null +++ b/src/catalogue/tests/test_visit.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from catalogue import models +from catalogue.test_utils import BookInfoStub, PersonStub, WLTestCase, info_args +from django.core.files.base import ContentFile + + +class VisitTest(WLTestCase): + """Simply create some objects and visit some views.""" + + def setUp(self): + WLTestCase.setUp(self) + author = PersonStub(("Jane",), "Doe") + book_info = BookInfoStub(author=author, genre="Genre", + epoch='Epoch', kind="Kind", **info_args(u"A book")) + self.book = models.Book.from_text_and_meta(ContentFile(''' + + + + + Theme + Test + + + + + '''), book_info) + self.collection = models.Collection.objects.create( + title='Biblioteczka Boya', slug='boy', book_slugs='a-book') + + def test_visit_urls(self): + """ book description should return authors, ancestors, book """ + url_map = { + 200: [ + '', + 'lektury/', + 'lektury/boy/', + 'nowe/', + 'lektura/a-book/', + 'lektura/a-book.html', + 'lektura/a-book/motyw/theme/', + 'motyw/theme/', + 'autor/jane-doe/', + # 'autor/jane-doe/gatunek/genre/', + # 'autor/jane-doe/gatunek/genre/motyw/theme/', + 'b/%d/mini.pl.html' % self.book.pk, + 'b/%d/mini_nolink.pl.html' % self.book.pk, + 'b/%d/short.pl.html' % self.book.pk, + 'b/%d/wide.pl.html' % self.book.pk, + 'f/%d/promo.pl.html' % self.book.fragments.all()[0].pk, + 'f/%d/short.pl.html' % self.book.fragments.all()[0].pk, + ], + 404: [ + 'lektury/nonexistent/', # Nonexistent Collection. + 'lektura/nonexistent/', # Nonexistent Book. + 'lektura/nonexistent.html', # Nonexistent Book's HTML. + 'lektura/nonexistent/motyw/theme/', # Nonexistent Book's theme. + 'lektura/a-book/motyw/nonexistent/', # Nonexistent theme in a Book. + 'autor/nonexistent/', # Nonexistent author. + 'motyw/nonexistent/', # Nonexistent theme. + 'zh.json', # Nonexistent language. + 'b/%d/mini.pl.html' % (self.book.pk + 100), # Nonexistent book. + 'b/%d/mini_nolink.pl.html' % (self.book.pk + 100), # Nonexistent book. + 'b/%d/short.pl.html' % (self.book.pk + 100), # Nonexistent book. + 'b/%d/wide.pl.html' % (self.book.pk + 100), # Nonexistent book. + 'f/%d/promo.pl.html' % (self.book.fragments.all()[0].pk + 100), # Nonexistent fragment. + 'f/%d/short.pl.html' % (self.book.fragments.all()[0].pk + 100), # Nonexistent fragment. + ] + } + prefix = '/katalog/' + for expected_status, urls in url_map.items(): + for url in urls: + print(url) + status = self.client.get(prefix + url).status_code + self.assertEqual( + status, expected_status, + "Wrong status code for '%s'. Expected %d, got %d." % (prefix + url, expected_status, status)) diff --git a/src/catalogue/tests/visit.py b/src/catalogue/tests/visit.py deleted file mode 100644 index 5e640adad..000000000 --- a/src/catalogue/tests/visit.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from catalogue import models -from catalogue.test_utils import BookInfoStub, PersonStub, WLTestCase, info_args -from django.core.files.base import ContentFile - - -class VisitTest(WLTestCase): - """Simply create some objects and visit some views.""" - - def setUp(self): - WLTestCase.setUp(self) - author = PersonStub(("Jane",), "Doe") - book_info = BookInfoStub(author=author, genre="Genre", - epoch='Epoch', kind="Kind", **info_args(u"A book")) - self.book = models.Book.from_text_and_meta(ContentFile(''' - - - - - Theme - Test - - - - - '''), book_info) - self.collection = models.Collection.objects.create( - title='Biblioteczka Boya', slug='boy', book_slugs='a-book') - - def test_visit_urls(self): - """ book description should return authors, ancestors, book """ - url_map = { - 200: [ - '', - 'lektury/', - 'lektury/boy/', - 'nowe/', - 'lektura/a-book/', - 'lektura/a-book.html', - 'lektura/a-book/motyw/theme/', - 'motyw/theme/', - 'autor/jane-doe/', - # 'autor/jane-doe/gatunek/genre/', - # 'autor/jane-doe/gatunek/genre/motyw/theme/', - 'b/%d/mini.pl.html' % self.book.pk, - 'b/%d/mini_nolink.pl.html' % self.book.pk, - 'b/%d/short.pl.html' % self.book.pk, - 'b/%d/wide.pl.html' % self.book.pk, - 'f/%d/promo.pl.html' % self.book.fragments.all()[0].pk, - 'f/%d/short.pl.html' % self.book.fragments.all()[0].pk, - ], - 404: [ - 'lektury/nonexistent/', # Nonexistent Collection. - 'lektura/nonexistent/', # Nonexistent Book. - 'lektura/nonexistent.html', # Nonexistent Book's HTML. - 'lektura/nonexistent/motyw/theme/', # Nonexistent Book's theme. - 'lektura/a-book/motyw/nonexistent/', # Nonexistent theme in a Book. - 'autor/nonexistent/', # Nonexistent author. - 'motyw/nonexistent/', # Nonexistent theme. - 'zh.json', # Nonexistent language. - 'b/%d/mini.pl.html' % (self.book.pk + 100), # Nonexistent book. - 'b/%d/mini_nolink.pl.html' % (self.book.pk + 100), # Nonexistent book. - 'b/%d/short.pl.html' % (self.book.pk + 100), # Nonexistent book. - 'b/%d/wide.pl.html' % (self.book.pk + 100), # Nonexistent book. - 'f/%d/promo.pl.html' % (self.book.fragments.all()[0].pk + 100), # Nonexistent fragment. - 'f/%d/short.pl.html' % (self.book.fragments.all()[0].pk + 100), # Nonexistent fragment. - ] - } - prefix = '/katalog/' - for expected_status, urls in url_map.items(): - for url in urls: - print(url) - status = self.client.get(prefix + url).status_code - self.assertEqual( - status, expected_status, - "Wrong status code for '%s'. Expected %d, got %d." % (prefix + url, expected_status, status)) diff --git a/src/oai/tests/__init__.py b/src/oai/tests/__init__.py index 561ef604a..e69de29bb 100644 --- a/src/oai/tests/__init__.py +++ b/src/oai/tests/__init__.py @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from oai.tests.oaipmhapi import * diff --git a/src/oai/tests/files/antygona.xml b/src/oai/tests/files/antygona.xml old mode 100755 new mode 100644 diff --git a/src/oai/tests/files/lubie-kiedy-kobieta.xml b/src/oai/tests/files/lubie-kiedy-kobieta.xml old mode 100755 new mode 100644 diff --git a/src/oai/tests/oaipmhapi.py b/src/oai/tests/oaipmhapi.py deleted file mode 100644 index 938624b86..000000000 --- a/src/oai/tests/oaipmhapi.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from catalogue.test_utils import WLTestCase -from catalogue import models -from oai.handlers import * -from oaipmh.server import * -from os import path -from oaipmh.metadata import MetadataRegistry - - -class BookMetadataTest(WLTestCase): - def setUp(self): - super(BookMetadataTest, self).setUp() - xml = path.join(path.dirname(__file__), 'files/lubie-kiedy-kobieta.xml') - self.book = models.Book.from_xml_file(xml) - - xml = path.join(path.dirname(__file__), 'files/antygona.xml') - self.book2 = models.Book.from_xml_file(xml) - - mr = MetadataRegistry() - self.catalogue = Catalogue(mr) - - mr.registerWriter('oai_dc', oai_dc_writer) - nsmap = {'oai_dc': NS_OAIDC, 'dc': NS_DC, 'xsi': NS_XSI} - self.xml = XMLTreeServer(self.catalogue, mr, nsmap) - - # def test_get_record(self): - # self.xml.getRecord(identifier='lubie-kiedy-kobieta', metadataPrefix='oai_dc') - # self.xml.listRecords(metadataPrefix='oai_dc') - # - # def test_selecting(self): - # records, token = self.catalogue.listRecords(**{'set': 'epoch:starozytnosc'}) diff --git a/src/oai/tests/test_oaipmhapi.py b/src/oai/tests/test_oaipmhapi.py new file mode 100644 index 000000000..938624b86 --- /dev/null +++ b/src/oai/tests/test_oaipmhapi.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from catalogue.test_utils import WLTestCase +from catalogue import models +from oai.handlers import * +from oaipmh.server import * +from os import path +from oaipmh.metadata import MetadataRegistry + + +class BookMetadataTest(WLTestCase): + def setUp(self): + super(BookMetadataTest, self).setUp() + xml = path.join(path.dirname(__file__), 'files/lubie-kiedy-kobieta.xml') + self.book = models.Book.from_xml_file(xml) + + xml = path.join(path.dirname(__file__), 'files/antygona.xml') + self.book2 = models.Book.from_xml_file(xml) + + mr = MetadataRegistry() + self.catalogue = Catalogue(mr) + + mr.registerWriter('oai_dc', oai_dc_writer) + nsmap = {'oai_dc': NS_OAIDC, 'dc': NS_DC, 'xsi': NS_XSI} + self.xml = XMLTreeServer(self.catalogue, mr, nsmap) + + # def test_get_record(self): + # self.xml.getRecord(identifier='lubie-kiedy-kobieta', metadataPrefix='oai_dc') + # self.xml.listRecords(metadataPrefix='oai_dc') + # + # def test_selecting(self): + # records, token = self.catalogue.listRecords(**{'set': 'epoch:starozytnosc'}) diff --git a/src/opds/tests/__init__.py b/src/opds/tests/__init__.py old mode 100755 new mode 100644 index 339bfaa37..e69de29bb --- a/src/opds/tests/__init__.py +++ b/src/opds/tests/__init__.py @@ -1,62 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from unittest import skipIf -from lxml import etree -from django.conf import settings -import catalogue -from catalogue.test_utils import WLTestCase, get_fixture -from catalogue.models import Book -from librarian import WLURI, XMLNamespace -from search.index import Index - -AtomNS = XMLNamespace("http://www.w3.org/2005/Atom") - - -@skipIf(getattr(settings, 'NO_SEARCH_INDEX', False), u'Requires search server and NO_SEARCH_INDEX=False.') -class OpdsSearchTests(WLTestCase): - """Tests search feed in OPDS..""" - def setUp(self): - WLTestCase.setUp(self) - index = Index() - index.index.delete_all() - index.index.commit() - - self.do_doktora = Book.from_xml_file( - get_fixture('do-doktora.xml')) - self.do_anusie = Book.from_xml_file( - get_fixture('fraszka-do-anusie.xml', catalogue)) - - def assert_finds(self, query, books): - """Takes a query and tests against books expected to be found.""" - tree = etree.fromstring( - self.client.get('/opds/search/?%s' % query).content) - elem_ids = tree.findall('.//%s/%s' % (AtomNS('entry'), AtomNS('id'))) - slugs = [WLURI(elem.text).slug for elem in elem_ids] - self.assertEqual(set(slugs), set(b.slug for b in books), u"OPDS search '%s' failed." % query) - - def test_opds_search_simple(self): - """Do a simple q= test, also emulate dumb OPDS clients.""" - both = {self.do_doktora, self.do_anusie} - self.assert_finds('q=fraszka', both) - self.assert_finds('q=fraszka&author={opds:author}', both) - - def test_opds_search_title(self): - """Search by title.""" - both = {self.do_doktora, self.do_anusie} - self.assert_finds('title=fraszka', both) - self.assert_finds('title=fraszka', both) - self.assert_finds('q=title:doktora', [self.do_doktora]) - - def test_opds_search_author(self): - """Search by author.""" - self.assert_finds('q=fraszka&author=Kochanowski', [self.do_doktora]) - self.assert_finds('q=fraszka+author:Kochanowski', [self.do_doktora]) - self.assert_finds('q=Kochanowski', [self.do_doktora]) - - def test_opds_search_translator(self): - """Search by translator.""" - self.assert_finds('q=fraszka&translator=Fikcyjny', [self.do_doktora]) - self.assert_finds('q=fraszka+translator:Fikcyjny', [self.do_doktora]) - self.assert_finds('q=Fikcyjny', [self.do_doktora]) diff --git a/src/opds/tests/test_opds.py b/src/opds/tests/test_opds.py new file mode 100644 index 000000000..339bfaa37 --- /dev/null +++ b/src/opds/tests/test_opds.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from unittest import skipIf +from lxml import etree +from django.conf import settings +import catalogue +from catalogue.test_utils import WLTestCase, get_fixture +from catalogue.models import Book +from librarian import WLURI, XMLNamespace +from search.index import Index + +AtomNS = XMLNamespace("http://www.w3.org/2005/Atom") + + +@skipIf(getattr(settings, 'NO_SEARCH_INDEX', False), u'Requires search server and NO_SEARCH_INDEX=False.') +class OpdsSearchTests(WLTestCase): + """Tests search feed in OPDS..""" + def setUp(self): + WLTestCase.setUp(self) + index = Index() + index.index.delete_all() + index.index.commit() + + self.do_doktora = Book.from_xml_file( + get_fixture('do-doktora.xml')) + self.do_anusie = Book.from_xml_file( + get_fixture('fraszka-do-anusie.xml', catalogue)) + + def assert_finds(self, query, books): + """Takes a query and tests against books expected to be found.""" + tree = etree.fromstring( + self.client.get('/opds/search/?%s' % query).content) + elem_ids = tree.findall('.//%s/%s' % (AtomNS('entry'), AtomNS('id'))) + slugs = [WLURI(elem.text).slug for elem in elem_ids] + self.assertEqual(set(slugs), set(b.slug for b in books), u"OPDS search '%s' failed." % query) + + def test_opds_search_simple(self): + """Do a simple q= test, also emulate dumb OPDS clients.""" + both = {self.do_doktora, self.do_anusie} + self.assert_finds('q=fraszka', both) + self.assert_finds('q=fraszka&author={opds:author}', both) + + def test_opds_search_title(self): + """Search by title.""" + both = {self.do_doktora, self.do_anusie} + self.assert_finds('title=fraszka', both) + self.assert_finds('title=fraszka', both) + self.assert_finds('q=title:doktora', [self.do_doktora]) + + def test_opds_search_author(self): + """Search by author.""" + self.assert_finds('q=fraszka&author=Kochanowski', [self.do_doktora]) + self.assert_finds('q=fraszka+author:Kochanowski', [self.do_doktora]) + self.assert_finds('q=Kochanowski', [self.do_doktora]) + + def test_opds_search_translator(self): + """Search by translator.""" + self.assert_finds('q=fraszka&translator=Fikcyjny', [self.do_doktora]) + self.assert_finds('q=fraszka+translator:Fikcyjny', [self.do_doktora]) + self.assert_finds('q=Fikcyjny', [self.do_doktora]) diff --git a/src/picture/tests/__init__.py b/src/picture/tests/__init__.py index b2e50b00f..e69de29bb 100644 --- a/src/picture/tests/__init__.py +++ b/src/picture/tests/__init__.py @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from picture.tests.picture_import import * diff --git a/src/picture/tests/picture_import.py b/src/picture/tests/picture_import.py deleted file mode 100644 index 022b33c62..000000000 --- a/src/picture/tests/picture_import.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from __future__ import with_statement - -from os import path -from picture.models import Picture -from catalogue.test_utils import WLTestCase - - -class PictureTest(WLTestCase): - - def test_import(self): - picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml")) - - themes = set() - for area in picture.areas.all(): - themes.update([ - (tag.category, tag.name) - for tag in area.tags if tag.category in (u'theme', u'thing')]) - assert themes == {(u'theme', u'nieporządek'), (u'thing', u'Kosmos')}, \ - 'Bad themes on Picture areas: %s' % themes - - pic_themes = set([tag.name for tag in picture.tags if tag.category in ('theme', 'thing')]) - assert not pic_themes, 'Unwanted themes set on Pictures: %s' % pic_themes - - picture.delete() - - def test_import_with_explicit_image(self): - picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml"), - path.join(path.dirname(__file__), "files/kandinsky-composition-viii.png")) - - picture.delete() - - def test_import_2(self): - picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml"), - path.join(path.dirname(__file__), "files/kandinsky-composition-viii.png"), - overwrite=True) - cats = set([t.category for t in picture.tags]) - assert 'epoch' in cats - assert 'kind' in cats diff --git a/src/picture/tests/test_picture_import.py b/src/picture/tests/test_picture_import.py new file mode 100644 index 000000000..022b33c62 --- /dev/null +++ b/src/picture/tests/test_picture_import.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from __future__ import with_statement + +from os import path +from picture.models import Picture +from catalogue.test_utils import WLTestCase + + +class PictureTest(WLTestCase): + + def test_import(self): + picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml")) + + themes = set() + for area in picture.areas.all(): + themes.update([ + (tag.category, tag.name) + for tag in area.tags if tag.category in (u'theme', u'thing')]) + assert themes == {(u'theme', u'nieporządek'), (u'thing', u'Kosmos')}, \ + 'Bad themes on Picture areas: %s' % themes + + pic_themes = set([tag.name for tag in picture.tags if tag.category in ('theme', 'thing')]) + assert not pic_themes, 'Unwanted themes set on Pictures: %s' % pic_themes + + picture.delete() + + def test_import_with_explicit_image(self): + picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml"), + path.join(path.dirname(__file__), "files/kandinsky-composition-viii.png")) + + picture.delete() + + def test_import_2(self): + picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml"), + path.join(path.dirname(__file__), "files/kandinsky-composition-viii.png"), + overwrite=True) + cats = set([t.category for t in picture.tags]) + assert 'epoch' in cats + assert 'kind' in cats