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 from catalogue.utils import get_dynamic_path
439 out = get_dynamic_path(None, 'test-custom', ext='pdf')
440 absoulute_path = path.join(settings.MEDIA_ROOT, out)
442 if not path.exists(path.dirname(absoulute_path)):
443 makedirs(path.dirname(absoulute_path))
445 build_custom_pdf(self.book.id,
446 customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out)
447 self.assertTrue(path.exists(absoulute_path))