1 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
4 from django.core.files.base import ContentFile
5 from catalogue.test_utils import *
6 from catalogue import models
7 from librarian import WLURI
9 from os import path, makedirs
12 class BookImportLogicTests(WLTestCase):
15 WLTestCase.setUp(self)
16 self.book_info = BookInfoStub(
17 url=WLURI("default-book"),
18 about="http://wolnelektury.pl/example/URI/default_book",
20 author=PersonStub(("Jim",), "Lazy"),
27 self.expected_tags = [
28 ('author', 'jim-lazy'),
33 self.expected_tags.sort()
35 def test_empty_book(self):
36 book_text = "<utwor />"
37 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
38 book.refresh_from_db()
40 self.assertEqual(book.title, "Default Book")
41 self.assertEqual(book.slug, "default-book")
42 self.assertTrue(book.parent is None)
43 self.assertFalse(book.has_html_file())
45 # no fragments generated
46 self.assertEqual(book.fragments.count(), 0)
48 # TODO: this should be filled out probably...
49 self.assertEqual(book.wiki_link, '')
50 self.assertEqual(book.gazeta_link, '')
51 self.assertEqual(book.description, '')
53 tags = [(tag.category, tag.slug) for tag in book.tags]
56 self.assertEqual(tags, self.expected_tags)
58 def test_not_quite_empty_book(self):
59 """ Not empty, but without any real text.
61 Should work like any other non-empty book.
64 book_text = """<utwor>
66 <nazwa_utworu>Nic</nazwa_utworu>
70 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
71 book.refresh_from_db()
72 self.assertTrue(book.has_html_file())
74 def test_book_with_fragment(self):
75 book_text = """<utwor>
77 <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
78 </opowiadanie></utwor>
81 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
82 book.refresh_from_db()
83 self.assertTrue(book.has_html_file())
85 self.assertEqual(book.fragments.count(), 1)
86 self.assertEqual(book.fragments.all()[0].text, '<p class="paragraph">Ala ma kota</p>\n')
88 self.assertTrue(('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)
103 book.fragments.all()[0].tags.filter(
105 ).values_list('category', 'slug')
109 def test_book_with_no_theme(self):
110 """ fragments with no themes shouldn't be created at all """
112 book_text = """<utwor>
114 <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
115 </opowiadanie></utwor>
118 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
119 self.assertEqual(book.fragments.count(), 0)
120 self.assertEqual(book.tags.filter(category='theme').count(), 0)
122 def test_book_with_invalid_slug(self):
123 """ Book with invalid characters in slug shouldn't be imported """
124 self.book_info.url = WLURI("default_book")
125 book_text = "<utwor />"
126 with self.assertRaises(ValueError):
127 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
129 def test_book_replace_title(self):
130 book_text = """<utwor />"""
131 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
132 self.book_info.title = "Extraordinary"
133 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True)
135 tags = [(tag.category, tag.slug) for tag in book.tags]
138 self.assertEqual(tags, self.expected_tags)
140 def test_book_replace_author(self):
141 book_text = """<utwor />"""
142 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
143 self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
144 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True)
146 tags = [(tag.category, tag.slug) for tag in book.tags]
149 self.expected_tags.remove(('author', 'jim-lazy'))
150 self.expected_tags.append(('author', 'hans-christian-andersen'))
151 self.expected_tags.sort()
153 self.assertEqual(tags, self.expected_tags)
155 # the old tag shouldn't disappear
156 models.Tag.objects.get(slug="jim-lazy", category="author")
158 def test_book_remove_fragment(self):
159 book_text = """<utwor>
162 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
163 <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
165 </opowiadanie></utwor>
167 book_text_after = """<utwor>
170 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
173 </opowiadanie></utwor>
176 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
177 self.assertEqual(book.fragments.count(), 2)
178 book = models.Book.from_text_and_meta(ContentFile(book_text_after), self.book_info, overwrite=True)
179 self.assertEqual(book.fragments.count(), 1)
181 def test_multiple_tags(self):
182 book_text = """<utwor />"""
183 self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"),
184 self.book_info.kinds = self.book_info.kind, 'Y-Kind',
185 self.book_info.genres = self.book_info.genre, 'Y-Genre',
186 self.book_info.epochs = self.book_info.epoch, 'Y-Epoch',
188 self.expected_tags.extend([
189 ('author', 'joe-dilligent'),
190 ('genre', 'y-genre'),
191 ('epoch', 'y-epoch'),
194 self.expected_tags.sort()
196 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
197 tags = [(tag.category, tag.slug) for tag in book.tags]
200 self.assertEqual(tags, self.expected_tags)
203 class ChildImportTests(WLTestCase):
206 WLTestCase.setUp(self)
207 self.child_info = BookInfoStub(
211 author=PersonStub(("Joe",), "Doe"),
215 self.parent_info = BookInfoStub(
219 author=PersonStub(("Jim",), "Lazy"),
220 parts=[self.child_info.url],
221 **info_args("Parent")
224 def test_child(self):
225 text = """<utwor />"""
226 child = models.Book.from_text_and_meta(ContentFile(text), self.child_info)
227 parent = models.Book.from_text_and_meta(ContentFile(text), self.parent_info)
228 author = parent.tags.get(category='author')
229 books = self.client.get(author.get_absolute_url()).context['object_list']
230 self.assertEqual(len(books), 1, "Only parent book should be visible on author's page")
232 def test_child_replace(self):
233 parent_text = """<utwor />"""
234 child_text = """<utwor>
236 <akap><begin id="m01" /><motyw id="m01">Pies</motyw>Ala ma kota<end id="m01" /></akap>
237 </opowiadanie></utwor>
239 child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info)
240 parent = models.Book.from_text_and_meta(ContentFile(parent_text), self.parent_info)
241 child_text = """<utwor>
243 <akap><begin id="m01" /><motyw id="m01">Kot</motyw>Ala ma kota<end id="m01" /></akap>
244 </opowiadanie></utwor>
246 child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info, overwrite=True)
247 themes = parent.related_themes()
248 self.assertEqual(['Kot'], [tag.name for tag in themes], 'wrong related theme list')
251 class TreeImportTest(WLTestCase):
253 WLTestCase.setUp(self)
254 self.child_info = BookInfoStub(
258 author=PersonStub(("Joe",), "Doe"),
261 self.CHILD_TEXT = """<utwor>
263 <akap><begin id="m01" /><motyw id="m01">Pies</motyw>
264 Ala ma kota<end id="m01" /></akap>
265 </opowiadanie></utwor>
267 self.child = models.Book.from_text_and_meta(
268 ContentFile(self.CHILD_TEXT), self.child_info)
270 self.book_info = BookInfoStub(
274 author=PersonStub(("Joe",), "Doe"),
275 parts=[self.child_info.url],
278 self.BOOK_TEXT = """<utwor />"""
279 self.book = models.Book.from_text_and_meta(
280 ContentFile(self.BOOK_TEXT), self.book_info)
282 self.parent_info = BookInfoStub(
286 author=PersonStub(("Jim",), "Lazy"),
287 parts=[self.book_info.url],
288 **info_args("Parent")
290 self.PARENT_TEXT = """<utwor />"""
291 self.parent = models.Book.from_text_and_meta(
292 ContentFile(self.PARENT_TEXT), self.parent_info)
296 list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
298 "There should be only parent on common tag page."
300 # pies = models.Tag.objects.get(slug='pies')
301 themes = self.parent.related_themes()
302 self.assertEqual(len(themes), 1, "There should be child theme in parent theme counter.")
303 # TODO: book_count is deprecated, update here.
304 # epoch = models.Tag.objects.get(slug='x-epoch')
305 # self.assertEqual(epoch.book_count, 1, "There should be only parent in common tag's counter.")
307 def test_child_republish(self):
308 child_text = """<utwor>
310 <akap><begin id="m01" /><motyw id="m01">Pies, Kot</motyw>
311 Ala ma kota<end id="m01" /></akap>
312 </opowiadanie></utwor>
314 models.Book.from_text_and_meta(
315 ContentFile(child_text), self.child_info, overwrite=True)
317 list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
319 "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(len(self.parent.related_themes()), 2,
324 "There should be child themes in parent theme counter.")
325 # TODO: book_count is deprecated, update here.
326 # epoch = models.Tag.objects.get(slug='x-epoch')
327 # self.assertEqual(epoch.book_count, 1, "There should only be parent in common tag's counter.")
329 def test_book_change_child(self):
330 second_child_info = BookInfoStub(
334 author=PersonStub(("Joe",), "Doe"),
335 **info_args("Second Child")
337 second_child_text = """<utwor>
339 <akap><begin id="m01" /><motyw id="m01">Kot</motyw>
340 Ala ma kota<end id="m01" /></akap>
341 </opowiadanie></utwor>
343 # Import a second child.
344 second_child = models.Book.from_text_and_meta(
345 ContentFile(second_child_text), second_child_info)
346 # The book has only this new child now.
347 self.book_info.parts = [second_child_info.url]
348 self.book = models.Book.from_text_and_meta(
349 ContentFile(self.BOOK_TEXT), self.book_info, overwrite=True)
352 set(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
353 {self.parent, self.child},
354 "There should be parent and old child on common tag page."
356 # kot = models.Tag.objects.get(slug='kot')
357 self.assertEqual(len(self.parent.related_themes()), 1,
358 "There should only be new child themes in parent theme counter.")
359 # # book_count deprecated, update test.
360 # epoch = models.Tag.objects.get(slug='x-epoch')
361 # self.assertEqual(epoch.book_count, 2,
362 # "There should be parent and old child in common tag's counter.")
364 list(self.client.get('/katalog/lektura/parent/motyw/kot/').context['fragments']),
365 [second_child.fragments.all()[0]],
366 "There should be new child's fragments on parent's theme page."
369 list(self.client.get('/katalog/lektura/parent/motyw/pies/').context['fragments']),
371 "There should be no old child's fragments on parent's theme page."
375 class MultilingualBookImportTest(WLTestCase):
377 WLTestCase.setUp(self)
378 common_uri = WLURI('common-slug')
380 self.pol_info = BookInfoStub(
384 author=PersonStub(("Joe",), "Doe"),
385 variant_of=common_uri,
386 **info_args("Książka")
389 self.eng_info = BookInfoStub(
393 author=PersonStub(("Joe",), "Doe"),
394 variant_of=common_uri,
395 **info_args("A book", "eng")
398 def test_multilingual_import(self):
399 book_text = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
401 models.Book.from_text_and_meta(ContentFile(book_text), self.pol_info)
402 models.Book.from_text_and_meta(ContentFile(book_text), self.eng_info)
405 {b.language for b in models.Book.objects.all()},
407 'Books imported in wrong languages.'
411 class BookImportGenerateTest(WLTestCase):
413 WLTestCase.setUp(self)
414 xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml')
415 self.book = models.Book.from_xml_file(xml)
417 def test_gen_pdf(self):
418 self.book.pdf_file.build()
419 book = models.Book.objects.get(pk=self.book.pk)
420 self.assertTrue(path.exists(book.pdf_file.path))
422 def test_gen_pdf_parent(self):
423 """This book contains a child."""
424 xml = path.join(path.dirname(__file__), "files/fraszki.xml")
425 parent = models.Book.from_xml_file(xml)
426 parent.pdf_file.build()
427 parent = models.Book.objects.get(pk=parent.pk)
428 self.assertTrue(path.exists(parent.pdf_file.path))
430 def test_custom_pdf(self):
431 from catalogue.tasks import build_custom_pdf
432 out = 'test-custom.pdf'
433 absoulute_path = path.join(settings.MEDIA_ROOT, out)
435 if not path.exists(path.dirname(absoulute_path)):
436 makedirs(path.dirname(absoulute_path))
438 build_custom_pdf(self.book.id, customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out)
439 self.assertTrue(path.exists(absoulute_path))