1 # -*- coding: utf-8 -*-
 
   2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 
   3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 
   5 from django.conf import settings
 
   7 from django.core.files.base import ContentFile
 
   8 from catalogue.test_utils import *
 
   9 from catalogue import models
 
  10 from librarian import WLURI
 
  12 from nose.tools import raises
 
  13 from os import path, makedirs
 
  15 class BookImportLogicTests(WLTestCase):
 
  18         WLTestCase.setUp(self)
 
  19         self.book_info = BookInfoStub(
 
  20             url=WLURI.from_slug(u"default-book"),
 
  21             about=u"http://wolnelektury.pl/example/URI/default_book",
 
  22             title=u"Default Book",
 
  23             author=PersonStub(("Jim",), "Lazy"),
 
  30         self.expected_tags = [
 
  31            ('author', 'jim-lazy'),
 
  36         self.expected_tags.sort()
 
  38     def test_empty_book(self):
 
  39         BOOK_TEXT = "<utwor />"
 
  40         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
  42         self.assertEqual(book.title, "Default Book")
 
  43         self.assertEqual(book.slug, "default-book")
 
  44         self.assert_(book.parent is None)
 
  45         self.assertFalse(book.has_html_file())
 
  47         # no fragments generated
 
  48         self.assertEqual(book.fragments.count(), 0)
 
  50         # TODO: this should be filled out probably...
 
  51         self.assertEqual(book.wiki_link, '')
 
  52         self.assertEqual(book.gazeta_link, '')
 
  53         self.assertEqual(book.description, '')
 
  55         tags = [ (tag.category, tag.slug) for tag in book.tags ]
 
  58         self.assertEqual(tags, self.expected_tags)
 
  60     def test_not_quite_empty_book(self):
 
  61         """ Not empty, but without any real text.
 
  63         Should work like any other non-empty book.
 
  66         BOOK_TEXT = """<utwor>
 
  68             <nazwa_utworu>Nic</nazwa_utworu>
 
  72         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
  73         self.assertTrue(book.has_html_file())
 
  75     def test_book_with_fragment(self):
 
  76         BOOK_TEXT = """<utwor>
 
  78             <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
 
  79         </opowiadanie></utwor>
 
  82         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
  83         self.assertTrue(book.has_html_file())
 
  85         self.assertEqual(book.fragments.count(), 1)
 
  86         self.assertEqual(book.fragments.all()[0].text, u'<p class="paragraph">Ala ma kota</p>\n')
 
  88         self.assert_(('theme', 'love') in [ (tag.category, tag.slug) for tag in book.fragments.all()[0].tags ])
 
  90     def test_book_with_empty_theme(self):
 
  91         """ empty themes should be ignored """
 
  93         BOOK_TEXT = """<utwor>
 
  95             <akap><begin id="m01" /><motyw id="m01"> , Love , , </motyw>Ala ma kota<end id="m01" /></akap>
 
  96         </opowiadanie></utwor>
 
  99         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 100         self.assert_([('theme', 'love')],
 
 101                          [ (tag.category, tag.slug) for tag in book.fragments.all()[0].tags.filter(category='theme') ])
 
 103     def test_book_with_no_theme(self):
 
 104         """ fragments with no themes shouldn't be created at all """
 
 106         BOOK_TEXT = """<utwor>
 
 108             <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
 
 109         </opowiadanie></utwor>
 
 112         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 113         self.assertEqual(book.fragments.count(), 0)
 
 114         self.assertEqual(book.tags.filter(category='theme').count(), 0)
 
 117     def test_book_with_invalid_slug(self):
 
 118         """ Book with invalid characters in slug shouldn't be imported """
 
 119         self.book_info.url = WLURI.from_slug(u"default_book")
 
 120         BOOK_TEXT = "<utwor />"
 
 121         models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 123     def test_book_replace_title(self):
 
 124         BOOK_TEXT = """<utwor />"""
 
 125         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 126         self.book_info.title = u"Extraordinary"
 
 127         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info, overwrite=True)
 
 129         tags = [ (tag.category, tag.slug) for tag in book.tags ]
 
 132         self.assertEqual(tags, self.expected_tags)
 
 134     def test_book_replace_author(self):
 
 135         BOOK_TEXT = """<utwor />"""
 
 136         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 137         self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
 
 138         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info, overwrite=True)
 
 140         tags = [ (tag.category, tag.slug) for tag in book.tags ]
 
 143         self.expected_tags.remove(('author', 'jim-lazy'))
 
 144         self.expected_tags.append(('author', 'hans-christian-andersen'))
 
 145         self.expected_tags.sort()
 
 147         self.assertEqual(tags, self.expected_tags)
 
 149         # the old tag shouldn't disappear
 
 150         models.Tag.objects.get(slug="jim-lazy", category="author")
 
 152     def test_book_remove_fragment(self):
 
 153         BOOK_TEXT = """<utwor>
 
 156                 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
 
 157                 <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
 
 159         </opowiadanie></utwor>
 
 161         BOOK_TEXT_AFTER = """<utwor>
 
 164                 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
 
 167         </opowiadanie></utwor>
 
 170         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 171         self.assertEqual(book.fragments.count(), 2)
 
 172         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT_AFTER), self.book_info, overwrite=True)
 
 173         self.assertEqual(book.fragments.count(), 1)
 
 175     def test_multiple_tags(self):
 
 176         BOOK_TEXT = """<utwor />"""
 
 177         self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"),
 
 178         self.book_info.kinds = self.book_info.kind, 'Y-Kind',
 
 179         self.book_info.genres = self.book_info.genre, 'Y-Genre',
 
 180         self.book_info.epochs = self.book_info.epoch, 'Y-Epoch',
 
 182         self.expected_tags.extend([
 
 183            ('author', 'joe-dilligent'),
 
 184            ('genre', 'y-genre'),
 
 185            ('epoch', 'y-epoch'),
 
 188         self.expected_tags.sort()
 
 190         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
 
 191         tags = [ (tag.category, tag.slug) for tag in book.tags ]
 
 194         self.assertEqual(tags, self.expected_tags)
 
 197 class ChildImportTests(WLTestCase):
 
 200         WLTestCase.setUp(self)
 
 201         self.child_info = BookInfoStub(
 
 205             author=PersonStub(("Joe",), "Doe"),
 
 209         self.parent_info = BookInfoStub(
 
 213             author=PersonStub(("Jim",), "Lazy"),
 
 214             parts=[self.child_info.url],
 
 215             **info_args("Parent")
 
 218     def test_child(self):
 
 219         TEXT = """<utwor />"""
 
 220         child = models.Book.from_text_and_meta(ContentFile(TEXT), self.child_info)
 
 221         parent = models.Book.from_text_and_meta(ContentFile(TEXT), self.parent_info)
 
 222         author = parent.tags.get(category='author')
 
 223         books = self.client.get(author.get_absolute_url()).context['object_list']
 
 224         self.assertEqual(len(books), 1,
 
 225                         "Only parent book should be visible on author's page")
 
 227     def test_child_replace(self):
 
 228         PARENT_TEXT = """<utwor />"""
 
 229         CHILD_TEXT = """<utwor>
 
 231             <akap><begin id="m01" /><motyw id="m01">Pies</motyw>Ala ma kota<end id="m01" /></akap>
 
 232         </opowiadanie></utwor>
 
 234         child = models.Book.from_text_and_meta(ContentFile(CHILD_TEXT), self.child_info)
 
 235         parent = models.Book.from_text_and_meta(ContentFile(PARENT_TEXT), self.parent_info)
 
 236         CHILD_TEXT = """<utwor>
 
 238             <akap><begin id="m01" /><motyw id="m01">Kot</motyw>Ala ma kota<end id="m01" /></akap>
 
 239         </opowiadanie></utwor>
 
 241         child = models.Book.from_text_and_meta(ContentFile(CHILD_TEXT), self.child_info, overwrite=True)
 
 242         themes = parent.related_themes()
 
 243         self.assertEqual(['Kot'], [tag.name for tag in themes],
 
 244                         'wrong related theme list')
 
 247 class TreeImportTest(WLTestCase):
 
 249         WLTestCase.setUp(self)
 
 250         self.child_info = BookInfoStub(
 
 254             author=PersonStub(("Joe",), "Doe"),
 
 257         self.CHILD_TEXT = """<utwor>
 
 259             <akap><begin id="m01" /><motyw id="m01">Pies</motyw>
 
 260                 Ala ma kota<end id="m01" /></akap>
 
 261         </opowiadanie></utwor>
 
 263         self.child = models.Book.from_text_and_meta(
 
 264             ContentFile(self.CHILD_TEXT), self.child_info)
 
 266         self.book_info = BookInfoStub(
 
 270             author=PersonStub(("Joe",), "Doe"),
 
 271             parts=[self.child_info.url],
 
 274         self.BOOK_TEXT = """<utwor />"""
 
 275         self.book = models.Book.from_text_and_meta(
 
 276             ContentFile(self.BOOK_TEXT), self.book_info)
 
 278         self.parent_info = BookInfoStub(
 
 282             author=PersonStub(("Jim",), "Lazy"),
 
 283             parts=[self.book_info.url],
 
 284             **info_args("Parent")
 
 286         self.PARENT_TEXT = """<utwor />"""
 
 287         self.parent = models.Book.from_text_and_meta(
 
 288             ContentFile(self.PARENT_TEXT), self.parent_info)
 
 292                 list(self.client.get('/katalog/gatunek/x-genre/'
 
 293                     ).context['object_list']),
 
 295                 u"There should be only parent on common tag page."
 
 297         pies = models.Tag.objects.get(slug='pies')
 
 298         self.assertEqual(self.parent.theme_counter, {pies.pk: 1},
 
 299                 u"There should be child theme in parent theme counter."
 
 301         epoch = models.Tag.objects.get(slug='x-epoch')
 
 302         self.assertEqual(epoch.book_count, 1,
 
 303                 u"There should be only parent in common tag's counter."
 
 306     def test_child_republish(self):
 
 307         CHILD_TEXT = """<utwor>
 
 309             <akap><begin id="m01" /><motyw id="m01">Pies, Kot</motyw>
 
 310                 Ala ma kota<end id="m01" /></akap>
 
 311         </opowiadanie></utwor>
 
 313         models.Book.from_text_and_meta(
 
 314             ContentFile(CHILD_TEXT), self.child_info, overwrite=True)
 
 316                 list(self.client.get('/katalog/gatunek/x-genre/'
 
 317                     ).context['object_list']),
 
 319                 u"There should only be parent on common tag page."
 
 321         pies = models.Tag.objects.get(slug='pies')
 
 322         kot = models.Tag.objects.get(slug='kot')
 
 323         self.assertEqual(self.parent.theme_counter, {pies.pk: 1, kot.pk: 1},
 
 324                 u"There should be child themes in parent theme counter."
 
 326         epoch = models.Tag.objects.get(slug='x-epoch')
 
 327         self.assertEqual(epoch.book_count, 1,
 
 328                 u"There should only be parent in common tag's counter."
 
 331     def test_book_change_child(self):
 
 332         second_child_info = BookInfoStub(
 
 336             author=PersonStub(("Joe",), "Doe"),
 
 337             **info_args("Second Child")
 
 339         SECOND_CHILD_TEXT = """<utwor>
 
 341             <akap><begin id="m01" /><motyw id="m01">Kot</motyw>
 
 342                 Ala ma kota<end id="m01" /></akap>
 
 343         </opowiadanie></utwor>
 
 345         # Import a second child.
 
 346         second_child = models.Book.from_text_and_meta(
 
 347             ContentFile(SECOND_CHILD_TEXT), second_child_info)
 
 348         # The book has only this new child now.
 
 349         self.book_info.parts = [second_child_info.url]
 
 350         self.book = models.Book.from_text_and_meta(
 
 351             ContentFile(self.BOOK_TEXT), self.book_info, overwrite=True)
 
 354                 set(self.client.get('/katalog/gatunek/x-genre/'
 
 355                     ).context['object_list']),
 
 356                 set([self.parent, self.child]),
 
 357                 u"There should be parent and old child on common tag page."
 
 359         kot = models.Tag.objects.get(slug='kot')
 
 360         self.assertEqual(self.parent.theme_counter, {kot.pk: 1},
 
 361                 u"There should only be new child themes in parent theme counter."
 
 363         epoch = models.Tag.objects.get(slug='x-epoch')
 
 364         self.assertEqual(epoch.book_count, 2,
 
 365                 u"There should be parent and old child in common tag's counter."
 
 368                 list(self.client.get('/katalog/lektura/parent/motyw/kot/'
 
 369                     ).context['fragments']),
 
 370                 [second_child.fragments.all()[0]],
 
 371                 u"There should be new child's fragments on parent's theme page."
 
 374                 list(self.client.get('/katalog/lektura/parent/motyw/pies/'
 
 375                     ).context['fragments']),
 
 377                 u"There should be no old child's fragments on parent's theme page."
 
 381 class MultilingualBookImportTest(WLTestCase):
 
 383         WLTestCase.setUp(self)
 
 384         common_uri = WLURI.from_slug('common-slug')
 
 386         self.pol_info = BookInfoStub(
 
 390             author=PersonStub(("Joe",), "Doe"),
 
 391             variant_of=common_uri,
 
 392             **info_args(u"Książka")
 
 395         self.eng_info = BookInfoStub(
 
 399             author=PersonStub(("Joe",), "Doe"),
 
 400             variant_of=common_uri,
 
 401             **info_args("A book", "eng")
 
 404     def test_multilingual_import(self):
 
 405         BOOK_TEXT = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
 
 407         book1 = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.pol_info)
 
 408         book2 = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.eng_info)
 
 411                 set([b.language for b in models.Book.objects.all()]),
 
 413                 'Books imported in wrong languages.'
 
 417 class BookImportGenerateTest(WLTestCase):
 
 419         WLTestCase.setUp(self)
 
 420         xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml')
 
 421         self.book = models.Book.from_xml_file(xml)
 
 423     def test_gen_pdf(self):
 
 424         self.book.pdf_file.build()
 
 425         book = models.Book.objects.get(pk=self.book.pk)
 
 426         self.assertTrue(path.exists(book.pdf_file.path))
 
 428     def test_gen_pdf_parent(self):
 
 429         """This book contains a child."""
 
 430         xml = path.join(path.dirname(__file__), "files/fraszki.xml")
 
 431         parent = models.Book.from_xml_file(xml)
 
 432         parent.pdf_file.build()
 
 433         parent = models.Book.objects.get(pk=parent.pk)
 
 434         self.assertTrue(path.exists(parent.pdf_file.path))
 
 436     def test_custom_pdf(self):
 
 437         from catalogue.tasks import build_custom_pdf
 
 438         out = 'test-custom.pdf'
 
 439         absoulute_path = path.join(settings.MEDIA_ROOT, out)
 
 441         if not path.exists(path.dirname(absoulute_path)):
 
 442             makedirs(path.dirname(absoulute_path))
 
 444         build_custom_pdf(self.book.id,
 
 445             customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out)
 
 446         self.assertTrue(path.exists(absoulute_path))