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.core.files.base import ContentFile
6 from catalogue.test_utils import *
7 from catalogue import models
8 from librarian import WLURI
10 from os import path, makedirs
13 class BookImportLogicTests(WLTestCase):
16 WLTestCase.setUp(self)
17 self.book_info = BookInfoStub(
18 url=WLURI.from_slug(u"default-book"),
19 about=u"http://wolnelektury.pl/example/URI/default_book",
20 title=u"Default Book",
21 author=PersonStub(("Jim",), "Lazy"),
28 self.expected_tags = [
29 ('author', 'jim-lazy'),
34 self.expected_tags.sort()
36 def test_empty_book(self):
37 book_text = "<utwor />"
38 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
39 book.refresh_from_db()
41 self.assertEqual(book.title, "Default Book")
42 self.assertEqual(book.slug, "default-book")
43 self.assert_(book.parent is None)
44 self.assertFalse(book.has_html_file())
46 # no fragments generated
47 self.assertEqual(book.fragments.count(), 0)
49 # TODO: this should be filled out probably...
50 self.assertEqual(book.wiki_link, '')
51 self.assertEqual(book.gazeta_link, '')
52 self.assertEqual(book.description, '')
54 tags = [(tag.category, tag.slug) for tag in book.tags]
57 self.assertEqual(tags, self.expected_tags)
59 def test_not_quite_empty_book(self):
60 """ Not empty, but without any real text.
62 Should work like any other non-empty book.
65 book_text = """<utwor>
67 <nazwa_utworu>Nic</nazwa_utworu>
71 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
72 book.refresh_from_db()
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 book.refresh_from_db()
84 self.assertTrue(book.has_html_file())
86 self.assertEqual(book.fragments.count(), 1)
87 self.assertEqual(book.fragments.all()[0].text, u'<p class="paragraph">Ala ma kota</p>\n')
89 self.assert_(('theme', 'love') in [(tag.category, tag.slug) for tag in book.fragments.all()[0].tags])
91 def test_book_with_empty_theme(self):
92 """ empty themes should be ignored """
94 book_text = """<utwor>
96 <akap><begin id="m01" /><motyw id="m01"> , Love , , </motyw>Ala ma kota<end id="m01" /></akap>
97 </opowiadanie></utwor>
100 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
101 self.assert_([('theme', 'love')],
102 book.fragments.all()[0].tags.filter(category='theme').values_list('category', 'slug'))
104 def test_book_with_no_theme(self):
105 """ fragments with no themes shouldn't be created at all """
107 book_text = """<utwor>
109 <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
110 </opowiadanie></utwor>
113 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
114 self.assertEqual(book.fragments.count(), 0)
115 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 with self.assertRaises(ValueError):
122 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
124 def test_book_replace_title(self):
125 book_text = """<utwor />"""
126 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
127 self.book_info.title = u"Extraordinary"
128 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True)
130 tags = [(tag.category, tag.slug) for tag in book.tags]
133 self.assertEqual(tags, self.expected_tags)
135 def test_book_replace_author(self):
136 book_text = """<utwor />"""
137 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
138 self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
139 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True)
141 tags = [(tag.category, tag.slug) for tag in book.tags]
144 self.expected_tags.remove(('author', 'jim-lazy'))
145 self.expected_tags.append(('author', 'hans-christian-andersen'))
146 self.expected_tags.sort()
148 self.assertEqual(tags, self.expected_tags)
150 # the old tag shouldn't disappear
151 models.Tag.objects.get(slug="jim-lazy", category="author")
153 def test_book_remove_fragment(self):
154 book_text = """<utwor>
157 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
158 <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
160 </opowiadanie></utwor>
162 book_text_after = """<utwor>
165 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
168 </opowiadanie></utwor>
171 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
172 self.assertEqual(book.fragments.count(), 2)
173 book = models.Book.from_text_and_meta(ContentFile(book_text_after), self.book_info, overwrite=True)
174 self.assertEqual(book.fragments.count(), 1)
176 def test_multiple_tags(self):
177 book_text = """<utwor />"""
178 self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"),
179 self.book_info.kinds = self.book_info.kind, 'Y-Kind',
180 self.book_info.genres = self.book_info.genre, 'Y-Genre',
181 self.book_info.epochs = self.book_info.epoch, 'Y-Epoch',
183 self.expected_tags.extend([
184 ('author', 'joe-dilligent'),
185 ('genre', 'y-genre'),
186 ('epoch', 'y-epoch'),
189 self.expected_tags.sort()
191 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
192 tags = [(tag.category, tag.slug) for tag in book.tags]
195 self.assertEqual(tags, self.expected_tags)
198 class ChildImportTests(WLTestCase):
201 WLTestCase.setUp(self)
202 self.child_info = BookInfoStub(
206 author=PersonStub(("Joe",), "Doe"),
210 self.parent_info = BookInfoStub(
214 author=PersonStub(("Jim",), "Lazy"),
215 parts=[self.child_info.url],
216 **info_args("Parent")
219 def test_child(self):
220 text = """<utwor />"""
221 child = models.Book.from_text_and_meta(ContentFile(text), self.child_info)
222 parent = models.Book.from_text_and_meta(ContentFile(text), self.parent_info)
223 author = parent.tags.get(category='author')
224 books = self.client.get(author.get_absolute_url()).context['object_list']
225 self.assertEqual(len(books), 1, "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], 'wrong related theme list')
246 class TreeImportTest(WLTestCase):
248 WLTestCase.setUp(self)
249 self.child_info = BookInfoStub(
253 author=PersonStub(("Joe",), "Doe"),
256 self.CHILD_TEXT = """<utwor>
258 <akap><begin id="m01" /><motyw id="m01">Pies</motyw>
259 Ala ma kota<end id="m01" /></akap>
260 </opowiadanie></utwor>
262 self.child = models.Book.from_text_and_meta(
263 ContentFile(self.CHILD_TEXT), self.child_info)
265 self.book_info = BookInfoStub(
269 author=PersonStub(("Joe",), "Doe"),
270 parts=[self.child_info.url],
273 self.BOOK_TEXT = """<utwor />"""
274 self.book = models.Book.from_text_and_meta(
275 ContentFile(self.BOOK_TEXT), self.book_info)
277 self.parent_info = BookInfoStub(
281 author=PersonStub(("Jim",), "Lazy"),
282 parts=[self.book_info.url],
283 **info_args("Parent")
285 self.PARENT_TEXT = """<utwor />"""
286 self.parent = models.Book.from_text_and_meta(
287 ContentFile(self.PARENT_TEXT), self.parent_info)
291 list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
293 u"There should be only parent on common tag page."
295 # pies = models.Tag.objects.get(slug='pies')
296 themes = self.parent.related_themes()
297 self.assertEqual(len(themes), 1, u"There should be child theme in parent theme counter.")
298 # TODO: book_count is deprecated, update here.
299 # epoch = models.Tag.objects.get(slug='x-epoch')
300 # self.assertEqual(epoch.book_count, 1, u"There should be only parent in common tag's counter.")
302 def test_child_republish(self):
303 child_text = """<utwor>
305 <akap><begin id="m01" /><motyw id="m01">Pies, Kot</motyw>
306 Ala ma kota<end id="m01" /></akap>
307 </opowiadanie></utwor>
309 models.Book.from_text_and_meta(
310 ContentFile(child_text), self.child_info, overwrite=True)
312 list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
314 u"There should only be parent on common tag page."
316 # pies = models.Tag.objects.get(slug='pies')
317 # kot = models.Tag.objects.get(slug='kot')
318 self.assertEqual(len(self.parent.related_themes()), 2,
319 u"There should be child themes in parent theme counter.")
320 # TODO: book_count is deprecated, update here.
321 # epoch = models.Tag.objects.get(slug='x-epoch')
322 # self.assertEqual(epoch.book_count, 1, u"There should only be parent in common tag's counter.")
324 def test_book_change_child(self):
325 second_child_info = BookInfoStub(
329 author=PersonStub(("Joe",), "Doe"),
330 **info_args("Second Child")
332 second_child_text = """<utwor>
334 <akap><begin id="m01" /><motyw id="m01">Kot</motyw>
335 Ala ma kota<end id="m01" /></akap>
336 </opowiadanie></utwor>
338 # Import a second child.
339 second_child = models.Book.from_text_and_meta(
340 ContentFile(second_child_text), second_child_info)
341 # The book has only this new child now.
342 self.book_info.parts = [second_child_info.url]
343 self.book = models.Book.from_text_and_meta(
344 ContentFile(self.BOOK_TEXT), self.book_info, overwrite=True)
347 set(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
348 {self.parent, self.child},
349 u"There should be parent and old child on common tag page."
351 # kot = models.Tag.objects.get(slug='kot')
352 self.assertEqual(len(self.parent.related_themes()), 1,
353 u"There should only be new child themes in parent theme counter.")
354 # # book_count deprecated, update test.
355 # epoch = models.Tag.objects.get(slug='x-epoch')
356 # self.assertEqual(epoch.book_count, 2,
357 # u"There should be parent and old child in common tag's counter.")
359 list(self.client.get('/katalog/lektura/parent/motyw/kot/').context['fragments']),
360 [second_child.fragments.all()[0]],
361 u"There should be new child's fragments on parent's theme page."
364 list(self.client.get('/katalog/lektura/parent/motyw/pies/').context['fragments']),
366 u"There should be no old child's fragments on parent's theme page."
370 class MultilingualBookImportTest(WLTestCase):
372 WLTestCase.setUp(self)
373 common_uri = WLURI.from_slug('common-slug')
375 self.pol_info = BookInfoStub(
379 author=PersonStub(("Joe",), "Doe"),
380 variant_of=common_uri,
381 **info_args(u"Książka")
384 self.eng_info = BookInfoStub(
388 author=PersonStub(("Joe",), "Doe"),
389 variant_of=common_uri,
390 **info_args("A book", "eng")
393 def test_multilingual_import(self):
394 book_text = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
396 models.Book.from_text_and_meta(ContentFile(book_text), self.pol_info)
397 models.Book.from_text_and_meta(ContentFile(book_text), self.eng_info)
400 set([b.language for b in models.Book.objects.all()]),
402 'Books imported in wrong languages.'
406 class BookImportGenerateTest(WLTestCase):
408 WLTestCase.setUp(self)
409 xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml')
410 self.book = models.Book.from_xml_file(xml)
412 def test_gen_pdf(self):
413 self.book.pdf_file.build()
414 book = models.Book.objects.get(pk=self.book.pk)
415 self.assertTrue(path.exists(book.pdf_file.path))
417 def test_gen_pdf_parent(self):
418 """This book contains a child."""
419 xml = path.join(path.dirname(__file__), "files/fraszki.xml")
420 parent = models.Book.from_xml_file(xml)
421 parent.pdf_file.build()
422 parent = models.Book.objects.get(pk=parent.pk)
423 self.assertTrue(path.exists(parent.pdf_file.path))
425 def test_custom_pdf(self):
426 from catalogue.tasks import build_custom_pdf
427 out = 'test-custom.pdf'
428 absoulute_path = path.join(settings.MEDIA_ROOT, out)
430 if not path.exists(path.dirname(absoulute_path)):
431 makedirs(path.dirname(absoulute_path))
433 build_custom_pdf(self.book.id, customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out)
434 self.assertTrue(path.exists(absoulute_path))