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 nose.tools import raises
11 from os import path, makedirs
14 class BookImportLogicTests(WLTestCase):
17 WLTestCase.setUp(self)
18 self.book_info = BookInfoStub(
19 url=WLURI.from_slug(u"default-book"),
20 about=u"http://wolnelektury.pl/example/URI/default_book",
21 title=u"Default Book",
22 author=PersonStub(("Jim",), "Lazy"),
29 self.expected_tags = [
30 ('author', 'jim-lazy'),
35 self.expected_tags.sort()
37 def test_empty_book(self):
38 book_text = "<utwor />"
39 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
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 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 self.assertTrue(book.has_html_file())
84 self.assertEqual(book.fragments.count(), 1)
85 self.assertEqual(book.fragments.all()[0].text, u'<p class="paragraph">Ala ma kota</p>\n')
87 self.assert_(('theme', 'love') in [(tag.category, tag.slug) for tag in book.fragments.all()[0].tags])
89 def test_book_with_empty_theme(self):
90 """ empty themes should be ignored """
92 book_text = """<utwor>
94 <akap><begin id="m01" /><motyw id="m01"> , Love , , </motyw>Ala ma kota<end id="m01" /></akap>
95 </opowiadanie></utwor>
98 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
99 self.assert_([('theme', 'love')],
100 book.fragments.all()[0].tags.filter(category='theme').values_list('category', 'slug'))
102 def test_book_with_no_theme(self):
103 """ fragments with no themes shouldn't be created at all """
105 book_text = """<utwor>
107 <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
108 </opowiadanie></utwor>
111 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
112 self.assertEqual(book.fragments.count(), 0)
113 self.assertEqual(book.tags.filter(category='theme').count(), 0)
116 def test_book_with_invalid_slug(self):
117 """ Book with invalid characters in slug shouldn't be imported """
118 self.book_info.url = WLURI.from_slug(u"default_book")
119 book_text = "<utwor />"
120 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
122 def test_book_replace_title(self):
123 book_text = """<utwor />"""
124 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
125 self.book_info.title = u"Extraordinary"
126 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True)
128 tags = [(tag.category, tag.slug) for tag in book.tags]
131 self.assertEqual(tags, self.expected_tags)
133 def test_book_replace_author(self):
134 book_text = """<utwor />"""
135 models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
136 self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
137 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info, overwrite=True)
139 tags = [(tag.category, tag.slug) for tag in book.tags]
142 self.expected_tags.remove(('author', 'jim-lazy'))
143 self.expected_tags.append(('author', 'hans-christian-andersen'))
144 self.expected_tags.sort()
146 self.assertEqual(tags, self.expected_tags)
148 # the old tag shouldn't disappear
149 models.Tag.objects.get(slug="jim-lazy", category="author")
151 def test_book_remove_fragment(self):
152 book_text = """<utwor>
155 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
156 <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
158 </opowiadanie></utwor>
160 book_text_after = """<utwor>
163 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
166 </opowiadanie></utwor>
169 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
170 self.assertEqual(book.fragments.count(), 2)
171 book = models.Book.from_text_and_meta(ContentFile(book_text_after), self.book_info, overwrite=True)
172 self.assertEqual(book.fragments.count(), 1)
174 def test_multiple_tags(self):
175 book_text = """<utwor />"""
176 self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"),
177 self.book_info.kinds = self.book_info.kind, 'Y-Kind',
178 self.book_info.genres = self.book_info.genre, 'Y-Genre',
179 self.book_info.epochs = self.book_info.epoch, 'Y-Epoch',
181 self.expected_tags.extend([
182 ('author', 'joe-dilligent'),
183 ('genre', 'y-genre'),
184 ('epoch', 'y-epoch'),
187 self.expected_tags.sort()
189 book = models.Book.from_text_and_meta(ContentFile(book_text), self.book_info)
190 tags = [(tag.category, tag.slug) for tag in book.tags]
193 self.assertEqual(tags, self.expected_tags)
196 class ChildImportTests(WLTestCase):
199 WLTestCase.setUp(self)
200 self.child_info = BookInfoStub(
204 author=PersonStub(("Joe",), "Doe"),
208 self.parent_info = BookInfoStub(
212 author=PersonStub(("Jim",), "Lazy"),
213 parts=[self.child_info.url],
214 **info_args("Parent")
217 def test_child(self):
218 text = """<utwor />"""
219 child = models.Book.from_text_and_meta(ContentFile(text), self.child_info)
220 parent = models.Book.from_text_and_meta(ContentFile(text), self.parent_info)
221 author = parent.tags.get(category='author')
222 books = self.client.get(author.get_absolute_url()).context['object_list']
223 self.assertEqual(len(books), 1, "Only parent book should be visible on author's page")
225 def test_child_replace(self):
226 parent_text = """<utwor />"""
227 child_text = """<utwor>
229 <akap><begin id="m01" /><motyw id="m01">Pies</motyw>Ala ma kota<end id="m01" /></akap>
230 </opowiadanie></utwor>
232 child = models.Book.from_text_and_meta(ContentFile(child_text), self.child_info)
233 parent = models.Book.from_text_and_meta(ContentFile(parent_text), self.parent_info)
234 child_text = """<utwor>
236 <akap><begin id="m01" /><motyw id="m01">Kot</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, overwrite=True)
240 themes = parent.related_themes()
241 self.assertEqual(['Kot'], [tag.name for tag in themes], 'wrong related theme list')
244 class TreeImportTest(WLTestCase):
246 WLTestCase.setUp(self)
247 self.child_info = BookInfoStub(
251 author=PersonStub(("Joe",), "Doe"),
254 self.CHILD_TEXT = """<utwor>
256 <akap><begin id="m01" /><motyw id="m01">Pies</motyw>
257 Ala ma kota<end id="m01" /></akap>
258 </opowiadanie></utwor>
260 self.child = models.Book.from_text_and_meta(
261 ContentFile(self.CHILD_TEXT), self.child_info)
263 self.book_info = BookInfoStub(
267 author=PersonStub(("Joe",), "Doe"),
268 parts=[self.child_info.url],
271 self.BOOK_TEXT = """<utwor />"""
272 self.book = models.Book.from_text_and_meta(
273 ContentFile(self.BOOK_TEXT), self.book_info)
275 self.parent_info = BookInfoStub(
279 author=PersonStub(("Jim",), "Lazy"),
280 parts=[self.book_info.url],
281 **info_args("Parent")
283 self.PARENT_TEXT = """<utwor />"""
284 self.parent = models.Book.from_text_and_meta(
285 ContentFile(self.PARENT_TEXT), self.parent_info)
289 list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
291 u"There should be only parent on common tag page."
293 # pies = models.Tag.objects.get(slug='pies')
294 themes = self.parent.related_themes()
295 self.assertEqual(len(themes), 1, u"There should be child theme in parent theme counter.")
296 # TODO: book_count is deprecated, update here.
297 # epoch = models.Tag.objects.get(slug='x-epoch')
298 # self.assertEqual(epoch.book_count, 1, u"There should be only parent in common tag's counter.")
300 def test_child_republish(self):
301 child_text = """<utwor>
303 <akap><begin id="m01" /><motyw id="m01">Pies, Kot</motyw>
304 Ala ma kota<end id="m01" /></akap>
305 </opowiadanie></utwor>
307 models.Book.from_text_and_meta(
308 ContentFile(child_text), self.child_info, overwrite=True)
310 list(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
312 u"There should only be parent on common tag page."
314 # pies = models.Tag.objects.get(slug='pies')
315 # kot = models.Tag.objects.get(slug='kot')
316 self.assertEqual(len(self.parent.related_themes()), 2,
317 u"There should be child themes in parent theme counter.")
318 # TODO: book_count is deprecated, update here.
319 # epoch = models.Tag.objects.get(slug='x-epoch')
320 # self.assertEqual(epoch.book_count, 1, u"There should only be parent in common tag's counter.")
322 def test_book_change_child(self):
323 second_child_info = BookInfoStub(
327 author=PersonStub(("Joe",), "Doe"),
328 **info_args("Second Child")
330 second_child_text = """<utwor>
332 <akap><begin id="m01" /><motyw id="m01">Kot</motyw>
333 Ala ma kota<end id="m01" /></akap>
334 </opowiadanie></utwor>
336 # Import a second child.
337 second_child = models.Book.from_text_and_meta(
338 ContentFile(second_child_text), second_child_info)
339 # The book has only this new child now.
340 self.book_info.parts = [second_child_info.url]
341 self.book = models.Book.from_text_and_meta(
342 ContentFile(self.BOOK_TEXT), self.book_info, overwrite=True)
345 set(self.client.get('/katalog/gatunek/x-genre/').context['object_list']),
346 {self.parent, self.child},
347 u"There should be parent and old child on common tag page."
349 # kot = models.Tag.objects.get(slug='kot')
350 self.assertEqual(len(self.parent.related_themes()), 1,
351 u"There should only be new child themes in parent theme counter.")
352 # # book_count deprecated, update test.
353 # epoch = models.Tag.objects.get(slug='x-epoch')
354 # self.assertEqual(epoch.book_count, 2,
355 # u"There should be parent and old child in common tag's counter.")
357 list(self.client.get('/katalog/lektura/parent/motyw/kot/').context['fragments']),
358 [second_child.fragments.all()[0]],
359 u"There should be new child's fragments on parent's theme page."
362 list(self.client.get('/katalog/lektura/parent/motyw/pies/').context['fragments']),
364 u"There should be no old child's fragments on parent's theme page."
368 class MultilingualBookImportTest(WLTestCase):
370 WLTestCase.setUp(self)
371 common_uri = WLURI.from_slug('common-slug')
373 self.pol_info = BookInfoStub(
377 author=PersonStub(("Joe",), "Doe"),
378 variant_of=common_uri,
379 **info_args(u"Książka")
382 self.eng_info = BookInfoStub(
386 author=PersonStub(("Joe",), "Doe"),
387 variant_of=common_uri,
388 **info_args("A book", "eng")
391 def test_multilingual_import(self):
392 book_text = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
394 models.Book.from_text_and_meta(ContentFile(book_text), self.pol_info)
395 models.Book.from_text_and_meta(ContentFile(book_text), self.eng_info)
398 set([b.language for b in models.Book.objects.all()]),
400 'Books imported in wrong languages.'
404 class BookImportGenerateTest(WLTestCase):
406 WLTestCase.setUp(self)
407 xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml')
408 self.book = models.Book.from_xml_file(xml)
410 def test_gen_pdf(self):
411 self.book.pdf_file.build()
412 book = models.Book.objects.get(pk=self.book.pk)
413 self.assertTrue(path.exists(book.pdf_file.path))
415 def test_gen_pdf_parent(self):
416 """This book contains a child."""
417 xml = path.join(path.dirname(__file__), "files/fraszki.xml")
418 parent = models.Book.from_xml_file(xml)
419 parent.pdf_file.build()
420 parent = models.Book.objects.get(pk=parent.pk)
421 self.assertTrue(path.exists(parent.pdf_file.path))
423 def test_custom_pdf(self):
424 from catalogue.tasks import build_custom_pdf
425 out = 'test-custom.pdf'
426 absoulute_path = path.join(settings.MEDIA_ROOT, out)
428 if not path.exists(path.dirname(absoulute_path)):
429 makedirs(path.dirname(absoulute_path))
431 build_custom_pdf(self.book.id, customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out)
432 self.assertTrue(path.exists(absoulute_path))