904c1bf1d7a2f37cef212a53e31d88647697fe43
[wolnelektury.git] / apps / catalogue / tests / book_import.py
1 # -*- coding: utf-8 -*-
2 from __future__ import with_statement
3
4 from django.core.files.base import ContentFile, File
5 from catalogue.test_utils import *
6 from catalogue import models
7 from librarian import WLURI
8
9 from nose.tools import raises
10 from os import path, makedirs
11
12 class BookImportLogicTests(WLTestCase):
13
14     def setUp(self):
15         WLTestCase.setUp(self)
16         self.book_info = BookInfoStub(
17             url=WLURI.from_slug(u"default-book"),
18             about=u"http://wolnelektury.pl/example/URI/default_book",
19             title=u"Default Book",
20             author=PersonStub(("Jim",), "Lazy"),
21             kind="X-Kind",
22             genre="X-Genre",
23             epoch="X-Epoch",
24             language=u"pol",
25         )
26
27         self.expected_tags = [
28            ('author', 'jim-lazy'),
29            ('genre', 'x-genre'),
30            ('epoch', 'x-epoch'),
31            ('kind', 'x-kind'),
32         ]
33         self.expected_tags.sort()
34
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
39         self.assertEqual(book.title, "Default Book")
40         self.assertEqual(book.slug, "default-book")
41         self.assert_(book.parent is None)
42         self.assertFalse(book.has_html_file())
43
44         # no fragments generated
45         self.assertEqual(book.fragments.count(), 0)
46
47         # TODO: this should be filled out probably...
48         self.assertEqual(book.wiki_link, '')
49         self.assertEqual(book.gazeta_link, '')
50         self.assertEqual(book.description, '')
51
52         tags = [ (tag.category, tag.slug) for tag in book.tags ]
53         tags.sort()
54
55         self.assertEqual(tags, self.expected_tags)
56
57     def test_not_quite_empty_book(self):
58         """ Not empty, but without any real text.
59
60         Should work like any other non-empty book.
61         """
62
63         BOOK_TEXT = """<utwor>
64         <liryka_l>
65             <nazwa_utworu>Nic</nazwa_utworu>
66         </liryka_l></utwor>
67         """
68
69         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
70         self.assertTrue(book.has_html_file())
71
72     def test_book_with_fragment(self):
73         BOOK_TEXT = """<utwor>
74         <opowiadanie>
75             <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
76         </opowiadanie></utwor>
77         """
78
79         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
80         self.assertTrue(book.has_html_file())
81
82         self.assertEqual(book.fragments.count(), 1)
83         self.assertEqual(book.fragments.all()[0].text, u'<p class="paragraph">Ala ma kota</p>\n')
84
85         self.assert_(('theme', 'love') in [ (tag.category, tag.slug) for tag in book.fragments.all()[0].tags ])
86
87     def test_book_with_empty_theme(self):
88         """ empty themes should be ignored """
89
90         BOOK_TEXT = """<utwor>
91         <opowiadanie>
92             <akap><begin id="m01" /><motyw id="m01"> , Love , , </motyw>Ala ma kota<end id="m01" /></akap>
93         </opowiadanie></utwor>
94         """
95
96         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
97         self.assert_([('theme', 'love')],
98                          [ (tag.category, tag.slug) for tag in book.fragments.all()[0].tags.filter(category='theme') ])
99
100     def test_book_with_no_theme(self):
101         """ fragments with no themes shouldn't be created at all """
102
103         BOOK_TEXT = """<utwor>
104         <opowiadanie>
105             <akap><begin id="m01" /><motyw id="m01"></motyw>Ala ma kota<end id="m01" /></akap>
106         </opowiadanie></utwor>
107         """
108
109         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
110         self.assertEqual(book.fragments.count(), 0)
111         self.assertEqual(book.tags.filter(category='theme').count(), 0)
112
113     @raises(ValueError)
114     def test_book_with_invalid_slug(self):
115         """ Book with invalid characters in slug shouldn't be imported """
116         self.book_info.url = WLURI.from_slug(u"default_book")
117         BOOK_TEXT = "<utwor />"
118         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
119
120     def test_book_replace_title(self):
121         BOOK_TEXT = """<utwor />"""
122         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
123         self.book_info.title = u"Extraordinary"
124         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info, overwrite=True)
125
126         tags = [ (tag.category, tag.slug) for tag in book.tags ]
127         tags.sort()
128
129         self.assertEqual(tags, self.expected_tags)
130
131     def test_book_replace_author(self):
132         BOOK_TEXT = """<utwor />"""
133         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
134         self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
135         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info, overwrite=True)
136
137         tags = [ (tag.category, tag.slug) for tag in book.tags ]
138         tags.sort()
139
140         self.expected_tags.remove(('author', 'jim-lazy'))
141         self.expected_tags.append(('author', 'hans-christian-andersen'))
142         self.expected_tags.sort()
143
144         self.assertEqual(tags, self.expected_tags)
145
146         # the old tag shouldn't disappear
147         models.Tag.objects.get(slug="jim-lazy", category="author")
148
149     def test_book_remove_fragment(self):
150         BOOK_TEXT = """<utwor>
151         <opowiadanie>
152             <akap>
153                 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
154                 <begin id="m02" /><motyw id="m02">Hatred</motyw>To kot Ali<end id="m02" />
155             </akap>
156         </opowiadanie></utwor>
157         """
158         BOOK_TEXT_AFTER = """<utwor>
159         <opowiadanie>
160             <akap>
161                 <begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" />
162                 To kot Ali
163             </akap>
164         </opowiadanie></utwor>
165         """
166
167         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
168         self.assertEqual(book.fragments.count(), 2)
169         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT_AFTER), self.book_info, overwrite=True)
170         self.assertEqual(book.fragments.count(), 1)
171
172     def test_multiple_tags(self):
173         BOOK_TEXT = """<utwor />"""
174         self.book_info.authors = self.book_info.author, PersonStub(("Joe",), "Dilligent"),
175         self.book_info.kinds = self.book_info.kind, 'Y-Kind',
176         self.book_info.genres = self.book_info.genre, 'Y-Genre',
177         self.book_info.epochs = self.book_info.epoch, 'Y-Epoch',
178
179         self.expected_tags.extend([
180            ('author', 'joe-dilligent'),
181            ('genre', 'y-genre'),
182            ('epoch', 'y-epoch'),
183            ('kind', 'y-kind'),
184         ])
185         self.expected_tags.sort()
186
187         book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
188         tags = [ (tag.category, tag.slug) for tag in book.tags ]
189         tags.sort()
190
191         self.assertEqual(tags, self.expected_tags)
192
193
194 class ChildImportTests(WLTestCase):
195
196     def setUp(self):
197         WLTestCase.setUp(self)
198         self.child_info = BookInfoStub(
199             genre='X-Genre',
200             epoch='X-Epoch',
201             kind='X-Kind',
202             author=PersonStub(("Joe",), "Doe"),
203             **info_args("Child")
204         )
205
206         self.parent_info = BookInfoStub(
207             genre='X-Genre',
208             epoch='X-Epoch',
209             kind='X-Kind',
210             author=PersonStub(("Jim",), "Lazy"),
211             parts=[self.child_info.url],
212             **info_args("Parent")
213         )
214
215     def test_child(self):
216         TEXT = """<utwor />"""
217         child = models.Book.from_text_and_meta(ContentFile(TEXT), self.child_info)
218         parent = models.Book.from_text_and_meta(ContentFile(TEXT), self.parent_info)
219         author = parent.tags.get(category='author')
220         books = self.client.get(author.get_absolute_url()).context['object_list']
221         self.assertEqual(len(books), 1,
222                         "Only parent book should be visible on author's page")
223
224     def test_child_replace(self):
225         PARENT_TEXT = """<utwor />"""
226         CHILD_TEXT = """<utwor>
227         <opowiadanie>
228             <akap><begin id="m01" /><motyw id="m01">Pies</motyw>Ala ma kota<end id="m01" /></akap>
229         </opowiadanie></utwor>
230         """
231         child = models.Book.from_text_and_meta(ContentFile(CHILD_TEXT), self.child_info)
232         parent = models.Book.from_text_and_meta(ContentFile(PARENT_TEXT), self.parent_info)
233         CHILD_TEXT = """<utwor>
234         <opowiadanie>
235             <akap><begin id="m01" /><motyw id="m01">Kot</motyw>Ala ma kota<end id="m01" /></akap>
236         </opowiadanie></utwor>
237         """
238         child = models.Book.from_text_and_meta(ContentFile(CHILD_TEXT), self.child_info, overwrite=True)
239         themes = parent.related_themes()
240         self.assertEqual(['Kot'], [tag.name for tag in themes],
241                         'wrong related theme list')
242
243
244 class MultilingualBookImportTest(WLTestCase):
245     def setUp(self):
246         WLTestCase.setUp(self)
247         common_uri = WLURI.from_slug('common-slug')
248
249         self.pol_info = BookInfoStub(
250             genre='X-Genre',
251             epoch='X-Epoch',
252             kind='X-Kind',
253             author=PersonStub(("Joe",), "Doe"),
254             variant_of=common_uri,
255             **info_args(u"Książka")
256         )
257
258         self.eng_info = BookInfoStub(
259             genre='X-Genre',
260             epoch='X-Epoch',
261             kind='X-Kind',
262             author=PersonStub(("Joe",), "Doe"),
263             variant_of=common_uri,
264             **info_args("A book", "eng")
265         )
266
267     def test_multilingual_import(self):
268         BOOK_TEXT = """<utwor><opowiadanie><akap>A</akap></opowiadanie></utwor>"""
269
270         book1 = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.pol_info)
271         book2 = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.eng_info)
272
273         self.assertEqual(
274                 set([b.language for b in models.Book.objects.all()]),
275                 set(['pol', 'eng']),
276                 'Books imported in wrong languages.'
277             )
278
279
280 class BookImportGenerateTest(WLTestCase):
281     def setUp(self):
282         WLTestCase.setUp(self)
283         xml = path.join(path.dirname(__file__), 'files/fraszka-do-anusie.xml')
284         self.book = models.Book.from_xml_file(xml)
285
286     def test_gen_pdf(self):
287         self.book.build_pdf()
288         book = models.Book.objects.get(pk=self.book.pk)
289         self.assertTrue(path.exists(book.pdf_file.path))
290
291     def test_gen_pdf_parent(self):
292         """This book contains a child."""
293         xml = path.join(path.dirname(__file__), "files/fraszki.xml")
294         parent = models.Book.from_xml_file(xml)
295         parent.build_pdf()
296         parent = models.Book.objects.get(pk=parent.pk)
297         self.assertTrue(path.exists(parent.pdf_file.path))
298
299     def test_custom_pdf(self):
300         from catalogue.utils import build_custom_pdf
301         out = models.get_dynamic_path(None, 'test-custom', ext='pdf')
302         absoulute_path = path.join(settings.MEDIA_ROOT, out)
303         
304         if not path.exists(path.dirname(absoulute_path)):
305             makedirs(path.dirname(absoulute_path))
306
307         build_custom_pdf(self.book.id,
308             customizations=['nofootnotes', '13pt', 'a4paper'], file_name=out)
309         self.assertTrue(path.exists(absoulute_path))