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