coverage.xml
pip-log.txt
nosetests.xml
+/htmlcov
# Mac OS X garbage
.DS_Store
--- /dev/null
+.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
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.
-i https://py.mdrn.pl:8443/simple/
-nose>=1.3.7
-django-nose>=1.4.2,<1.5
-nosexcover
+coverage
mock
-# -*- 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 *
+++ /dev/null
-# -*- 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 = "<utwor />"
- 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 = """<utwor>
- <liryka_l>
- <nazwa_utworu>Nic</nazwa_utworu>
- </liryka_l></utwor>
- """
-
- 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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
-
- 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'<p class="paragraph">Ala ma kota</p>\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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01"> , Love , , </motyw>Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
-
- 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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
-
- 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 = "<utwor />"
- models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
-
- def test_book_replace_title(self):
- book_text = """<utwor />"""
- 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 = """<utwor />"""
- 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 = """<utwor>
- <opowiadanie>
- <akap>
- <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
- <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
- </akap>
- </opowiadanie></utwor>
- """
- book_text_after = """<utwor>
- <opowiadanie>
- <akap>
- <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
- To kot Ali
- </akap>
- </opowiadanie></utwor>
- """
-
- 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 = """<utwor />"""
- 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 = """<utwor />"""
- 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 = """<utwor />"""
- child_text = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01">Pies</motyw>Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
- 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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01">Kot</motyw>Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
- 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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01">Pies</motyw>
- Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
- 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 = """<utwor />"""
- 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 = """<utwor />"""
- 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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01">Pies, Kot</motyw>
- Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
- 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 = """<utwor>
- <opowiadanie>
- <akap><begin id="m01" /><motyw id="m01">Kot</motyw>
- Ala ma kota<end id="m01" /></akap>
- </opowiadanie></utwor>
- """
- # 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 = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
-
- 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))
+++ /dev/null
-# -*- 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)))
+++ /dev/null
-# -*- 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 = """<utwor />"""
- 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)
+++ /dev/null
-# -*- 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('<utwor />')
-
- 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 = """<utwor><opowiadanie><akap>
- <begin id="m01" />
- <motyw id="m01">Theme, %sTheme</motyw>
- Ala ma kota
- <end id="m01" />
- </akap></opowiadanie></utwor>
- """ % 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 = """<utwor><opowiadanie><akap>
- <begin id="m01" /><motyw id="m01">Theme</motyw>Ala ma kota
- <end id="m01" />
- </akap></opowiadanie></utwor>
- """
- 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 = """<utwor>
- <opowiadanie>
- <akap>
- <begin id="m01" /><motyw id="m01">tag</motyw>Ala ma kota<end id="m01" />
- </akap>
- </opowiadanie>
- </utwor>
- """
-
- 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 = """<utwor><opowiadanie><akap>
- <begin id="m01" />
- <motyw id="m01">Theme, %sTheme</motyw>
- Ala ma kota
- <end id="m01" />
- </akap></opowiadanie></utwor>
- """ % 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)])
+++ /dev/null
-# -*- 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('<utwor/>'), child_info)
- models.Book.from_text_and_meta(ContentFile('<utwor/>'), 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')
--- /dev/null
+# -*- 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 = "<utwor />"
+ 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 = """<utwor>
+ <liryka_l>
+ <nazwa_utworu>Nic</nazwa_utworu>
+ </liryka_l></utwor>
+ """
+
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+
+ 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'<p class="paragraph">Ala ma kota</p>\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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01"> , Love , , </motyw>Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+
+ 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 = "<utwor />"
+ with self.assertRaises(ValueError):
+ models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
+
+ def test_book_replace_title(self):
+ book_text = """<utwor />"""
+ 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 = """<utwor />"""
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap>
+ <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
+ <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
+ </akap>
+ </opowiadanie></utwor>
+ """
+ book_text_after = """<utwor>
+ <opowiadanie>
+ <akap>
+ <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
+ To kot Ali
+ </akap>
+ </opowiadanie></utwor>
+ """
+
+ 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 = """<utwor />"""
+ 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 = """<utwor />"""
+ 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 = """<utwor />"""
+ child_text = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01">Pies</motyw>Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01">Kot</motyw>Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01">Pies</motyw>
+ Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+ 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 = """<utwor />"""
+ 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 = """<utwor />"""
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01">Pies, Kot</motyw>
+ Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap><begin id="m01" /><motyw id="m01">Kot</motyw>
+ Ala ma kota<end id="m01" /></akap>
+ </opowiadanie></utwor>
+ """
+ # 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 = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
+
+ 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))
--- /dev/null
+# -*- 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)))
--- /dev/null
+# -*- 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 = """<utwor />"""
+ 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)
--- /dev/null
+# -*- 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('<utwor />')
+
+ 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 = """<utwor><opowiadanie><akap>
+ <begin id="m01" />
+ <motyw id="m01">Theme, %sTheme</motyw>
+ Ala ma kota
+ <end id="m01" />
+ </akap></opowiadanie></utwor>
+ """ % 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 = """<utwor><opowiadanie><akap>
+ <begin id="m01" /><motyw id="m01">Theme</motyw>Ala ma kota
+ <end id="m01" />
+ </akap></opowiadanie></utwor>
+ """
+ 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 = """<utwor>
+ <opowiadanie>
+ <akap>
+ <begin id="m01" /><motyw id="m01">tag</motyw>Ala ma kota<end id="m01" />
+ </akap>
+ </opowiadanie>
+ </utwor>
+ """
+
+ 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 = """<utwor><opowiadanie><akap>
+ <begin id="m01" />
+ <motyw id="m01">Theme, %sTheme</motyw>
+ Ala ma kota
+ <end id="m01" />
+ </akap></opowiadanie></utwor>
+ """ % 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)])
--- /dev/null
+# -*- 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('<utwor/>'), child_info)
+ models.Book.from_text_and_meta(ContentFile('<utwor/>'), 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')
--- /dev/null
+# -*- 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('''
+ <utwor>
+ <opowiadanie>
+ <akap>
+ <begin id="b1" />
+ <motyw id="m1">Theme</motyw>
+ Test
+ <end id="e1" />
+ </akap>
+ </opowiadanie>
+ </utwor>
+ '''), 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))
+++ /dev/null
-# -*- 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('''
- <utwor>
- <opowiadanie>
- <akap>
- <begin id="b1" />
- <motyw id="m1">Theme</motyw>
- Test
- <end id="e1" />
- </akap>
- </opowiadanie>
- </utwor>
- '''), 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))
-# -*- 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 *
+++ /dev/null
-# -*- 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'})
--- /dev/null
+# -*- 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'})
-# -*- 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])
--- /dev/null
+# -*- 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])
-# -*- 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 *
+++ /dev/null
-# -*- 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
--- /dev/null
+# -*- 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