- Added librarian as a submodule.
[wolnelektury.git] / apps / catalogue / tests / tags.py
1 # -*- coding: utf-8 -*-
2 from catalogue import models
3 from catalogue.test_utils import *
4 from django.core.files.base import ContentFile
5 from slughifi import slughifi
6
7 from nose.tools import raises
8
9 def info_args(title):
10     """ generate some keywords for comfortable BookInfoCreation  """
11     slug = unicode(slughifi(title))
12     return {
13         'title': unicode(title),
14         'slug': slug,
15         'url': u"http://wolnelektury.pl/example/%s" % slug,
16         'about': u"http://wolnelektury.pl/example/URI/%s" % slug,
17     }
18
19
20 class BooksByTagTests(WLTestCase):
21     """ tests the /katalog/tag page for found books """
22
23     def setUp(self):
24         WLTestCase.setUp(self)
25         author = PersonStub(("Common",), "Man")
26         tags = dict(genre='G', epoch='E', author=author, kind="K")
27
28         # grandchild
29         kwargs = info_args(u"GChild")
30         kwargs.update(tags)
31         gchild_info = BookInfoStub(**kwargs)
32         # child
33         kwargs = info_args(u"Child")
34         kwargs.update(tags)
35         child_info = BookInfoStub(parts=[gchild_info.url], **kwargs)
36         # other grandchild
37         kwargs = info_args(u"Different GChild")
38         kwargs.update(tags)
39         diffgchild_info = BookInfoStub(**kwargs)
40         # other child
41         kwargs = info_args(u"Different Child")
42         kwargs.update(tags)
43         kwargs['kind'] = 'K2'
44         diffchild_info = BookInfoStub(parts=[diffgchild_info.url], **kwargs)
45         # parent
46         kwargs = info_args(u"Parent")
47         kwargs.update(tags)
48         parent_info = BookInfoStub(parts=[child_info.url, diffchild_info.url], **kwargs)
49
50         # create the books
51         book_file = ContentFile('<utwor />')
52         for info in gchild_info, child_info, diffgchild_info, diffchild_info, parent_info:
53             book = models.Book.from_text_and_meta(book_file, info)
54
55         # useful tags
56         self.author = models.Tag.objects.get(name='Common Man', category='author')
57         models.Tag.objects.create(name='Empty tag', slug='empty', category='author')
58
59     def test_nonexistent_tag(self):
60         """ Looking for a non-existent tag should yield 404 """
61         # NOTE: this yields a false positive, 'cause of URL change
62         self.assertEqual(404, self.client.get('/katalog/czeslaw_milosz/').status_code)
63
64     def test_book_tag(self):
65         """ Looking for a book tag isn't permitted """
66         self.assertEqual(404, self.client.get('/katalog/parent/').status_code)
67
68     def test_tag_empty(self):
69         """ Tag with no books should return no books """
70         context = self.client.get('/katalog/empty/').context
71         self.assertEqual(0, len(context['object_list']))
72
73     def test_tag_common(self):
74         """ Filtering by tag should only yield top-level books. """
75         context = self.client.get('/katalog/%s/' % self.author.slug).context
76         self.assertEqual([book.title for book in context['object_list']],
77                          ['Parent'])
78
79     def test_tag_child(self):
80         """ Filtering by child's tag should yield the child """
81         context = self.client.get('/katalog/k2/').context
82         self.assertEqual([book.title for book in context['object_list']],
83                          ['Different Child'])
84
85     def test_tag_child_jump(self):
86         """ Of parent and grandchild, only parent should be returned. """
87         context = self.client.get('/katalog/k/').context
88         self.assertEqual([book.title for book in context['object_list']],
89                          ['Parent'])
90
91
92 class TagRelatedTagsTests(WLTestCase):
93     """ tests the /katalog/tag/ page for related tags """
94
95     def setUp(self):
96         WLTestCase.setUp(self)
97         author = PersonStub(("Common",), "Man")
98
99         gchild_info = BookInfoStub(author=author, genre="GchildGenre", epoch='Epoch', kind="Kind",
100                                    **info_args(u"GChild"))
101         child1_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind",
102                                    parts=[gchild_info.url],
103                                    **info_args(u"Child1"))
104         child2_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind",
105                                    **info_args(u"Child2"))
106         parent_info = BookInfoStub(author=author, genre="Genre", epoch='Epoch', kind="Kind",
107                                    parts=[child1_info.url, child2_info.url],
108                                    **info_args(u"Parent"))
109
110         for info in gchild_info, child1_info, child2_info, parent_info:
111             book_text = """<utwor><opowiadanie><akap>
112                 <begin id="m01" />
113                     <motyw id="m01">Theme, %sTheme</motyw>
114                     Ala ma kota
115                 <end id="m01" />
116                 </akap></opowiadanie></utwor>
117                 """ % info.title.encode('utf-8')
118             book = models.Book.from_text_and_meta(ContentFile(book_text), info)
119             book.save()
120
121         tag_empty = models.Tag(name='Empty tag', slug='empty', category='author')
122         tag_empty.save()
123
124     def test_empty(self):
125         """ empty tag should have no related tags """
126
127         cats = self.client.get('/katalog/empty/').context['categories']
128         self.assertEqual(cats, {}, 'tags related to empty tag')
129
130     def test_has_related(self):
131         """ related own and descendants' tags should be generated """
132
133         cats = self.client.get('/katalog/kind/').context['categories']
134         self.assertTrue('Common Man' in [tag.name for tag in cats['author']],
135                         'missing `author` related tag')
136         self.assertTrue('Epoch' in [tag.name for tag in cats['epoch']],
137                         'missing `epoch` related tag')
138         self.assertTrue("ChildKind" in [tag.name for tag in cats['kind']],
139                         "missing `kind` related tag")
140         self.assertTrue("Genre" in [tag.name for tag in cats['genre']],
141                         'missing `genre` related tag')
142         self.assertTrue("ChildGenre" in [tag.name for tag in cats['genre']],
143                         "missing child's related tag")
144         self.assertTrue("GchildGenre" in [tag.name for tag in cats['genre']],
145                         "missing grandchild's related tag")
146         self.assertTrue('Theme' in [tag.name for tag in cats['theme']],
147                         "missing related theme")
148         self.assertTrue('Child1Theme' in [tag.name for tag in cats['theme']],
149                         "missing child's related theme")
150         self.assertTrue('GChildTheme' in [tag.name for tag in cats['theme']],
151                         "missing grandchild's related theme")
152
153
154     def test_related_differ(self):
155         """ related tags shouldn't include filtering tags """
156
157         cats = self.client.get('/katalog/kind/').context['categories']
158         self.assertFalse('Kind' in [tag.name for tag in cats['kind']],
159                          'filtering tag wrongly included in related')
160         cats = self.client.get('/katalog/theme/').context['categories']
161         self.assertFalse('Theme' in [tag.name for tag in cats['theme']],
162                          'filtering theme wrongly included in related')
163
164
165     def test_parent_tag_once(self):
166         """ if parent and descendants have a common tag, count it only once """
167
168         cats = self.client.get('/katalog/kind/').context['categories']
169         self.assertEqual([(tag.name, tag.count) for tag in cats['epoch']],
170                          [('Epoch', 1)],
171                          'wrong related tag epoch tag on tag page')
172
173
174     def test_siblings_tags_add(self):
175         """ if children have tags and parent hasn't, count the children """
176
177         cats = self.client.get('/katalog/epoch/').context['categories']
178         self.assertTrue(('ChildKind', 2) in [(tag.name, tag.count) for tag in cats['kind']],
179                     'wrong related kind tags on tag page')
180
181     def test_themes_add(self):
182         """ all occurencies of theme should be counted """
183
184         cats = self.client.get('/katalog/epoch/').context['categories']
185         self.assertTrue(('Theme', 4) in [(tag.name, tag.count) for tag in cats['theme']],
186                     'wrong related theme count')
187
188
189 class CleanTagRelationTests(WLTestCase):
190     """ tests for tag relations cleaning after deleting things """
191
192     def setUp(self):
193         WLTestCase.setUp(self)
194         author = PersonStub(("Common",), "Man")
195
196         book_info = BookInfoStub(author=author, genre="G", epoch='E', kind="K",
197                                    **info_args(u"Book"))
198         book_text = """<utwor><opowiadanie><akap>
199             <begin id="m01" /><motyw id="m01">Theme</motyw>Ala ma kota
200             <end id="m01" />
201             </akap></opowiadanie></utwor>
202             """
203         book = models.Book.from_text_and_meta(ContentFile(book_text), book_info)
204
205     def test_delete_objects(self):
206         """ there should be no related tags left after deleting some objects """
207
208         models.Book.objects.all().delete()
209         cats = self.client.get('/katalog/k/').context['categories']
210         self.assertEqual(cats, {})
211
212     def test_deleted_tag(self):
213         """ there should be no tag relations left after deleting tags """
214
215         models.Tag.objects.all().delete()
216         cats = self.client.get('/katalog/lektura/book/').context['categories']
217         self.assertEqual(cats, {})
218
219
220 class TestIdenticalTag(WLTestCase):
221
222     def setUp(self):
223         WLTestCase.setUp(self)
224         author = PersonStub((), "Tag")
225
226         self.book_info = BookInfoStub(author=author,
227                                  genre="tag",
228                                  epoch='tag',
229                                  kind="tag",
230                                    **info_args(u"tag"))
231         self.book_text = """<utwor>
232             <opowiadanie>
233             <akap>
234                 <begin id="m01" /><motyw id="m01">tag</motyw>Ala ma kota<end id="m01" />
235             </akap>
236             </opowiadanie>
237             </utwor>
238         """
239
240
241     def test_book_tags(self):
242         """ there should be all related tags in relevant categories """
243         models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info)
244
245         cats = self.client.get('/katalog/lektura/tag/').context['categories']
246         for category in 'author', 'kind', 'genre', 'epoch', 'theme':
247             self.assertTrue('tag' in [tag.name for tag in cats[category]],
248                             'missing related tag for %s' % category)
249
250     def test_qualified_url(self):
251         models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info)
252         categories = {'author': 'autor', 'theme': 'motyw', 'epoch': 'epoka', 'kind':'rodzaj', 'genre':'gatunek'}
253         for cat, localcat in categories.iteritems():
254             context = self.client.get('/katalog/%s/tag/' % localcat).context
255             self.assertEqual(1, len(context['object_list']))
256             self.assertNotEqual({}, context['categories'])
257             self.assertFalse(cat in context['categories'])