More API testing.
[wolnelektury.git] / src / api / tests / tests.py
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.
4 #
5 from os import path
6 import json
7
8 from django.core.files.uploadedfile import SimpleUploadedFile
9 from django.test import TestCase
10 from django.test.utils import override_settings
11
12 from catalogue.models import Book, Tag
13 from picture.forms import PictureImportForm
14 from picture.models import Picture
15 import picture.tests
16
17
18 @override_settings(
19     NO_SEARCH_INDEX=True,
20     CACHES={'default': {
21         'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}},
22 )
23 class ApiTest(TestCase):
24     def load_json(self, url):
25         content = self.client.get(url).content
26         try:
27             data = json.loads(content)
28         except ValueError:
29             self.fail('No JSON could be decoded: %s' % content)
30         return data
31
32     def assert_json_response(self, url, name):
33         data = self.load_json(url)
34         with open(path.join(path.dirname(__file__), 'res', 'responses', name)) as f:
35             good_data = json.load(f)
36         self.assertEqual(data, good_data, json.dumps(data, indent=4))
37
38     def assert_slugs(self, url, slugs):
39         have_slugs = [x['slug'] for x in self.load_json(url)]
40         self.assertEqual(have_slugs, slugs, have_slugs)
41
42
43 class BookTests(ApiTest):
44
45     def setUp(self):
46         self.tag = Tag.objects.create(category='author', slug='joe')
47         self.book = Book.objects.create(title='A Book', slug='a-book')
48         self.book_tagged = Book.objects.create(title='Tagged Book', slug='tagged-book')
49         self.book_tagged.tags = [self.tag]
50         self.book_tagged.save()
51
52     def test_book_list(self):
53         books = self.load_json('/api/books/')
54         self.assertEqual(len(books), 2,
55                          'Wrong book list.')
56
57     def test_tagged_books(self):
58         books = self.load_json('/api/authors/joe/books/')
59
60         self.assertEqual([b['title'] for b in books], [self.book_tagged.title],
61                          'Wrong tagged book list.')
62
63     def test_detail(self):
64         book = self.load_json('/api/books/a-book/')
65         self.assertEqual(book['title'], self.book.title,
66                          'Wrong book details.')
67
68
69 class TagTests(ApiTest):
70
71     def setUp(self):
72         self.tag = Tag.objects.create(category='author', slug='joe', name='Joe')
73         self.book = Book.objects.create(title='A Book', slug='a-book')
74         self.book.tags = [self.tag]
75         self.book.save()
76
77     def test_tag_list(self):
78         tags = self.load_json('/api/authors/')
79         self.assertEqual(len(tags), 1,
80                          'Wrong tag list.')
81
82     def test_tag_detail(self):
83         tag = self.load_json('/api/authors/joe/')
84         self.assertEqual(tag['name'], self.tag.name,
85                          'Wrong tag details.')
86
87
88 class PictureTests(ApiTest):
89     def test_publish(self):
90         slug = "kandinsky-composition-viii"
91         xml = SimpleUploadedFile(
92             'composition8.xml', open(path.join(picture.tests.__path__[0], "files", slug + ".xml")).read())
93         img = SimpleUploadedFile(
94             'kompozycja-8.png', open(path.join(picture.tests.__path__[0], "files", slug + ".png")).read())
95
96         import_form = PictureImportForm({}, {
97             'picture_xml_file': xml,
98             'picture_image_file': img
99             })
100
101         assert import_form.is_valid()
102         if import_form.is_valid():
103             import_form.save()
104
105         Picture.objects.get(slug=slug)
106
107
108 class BooksTests(ApiTest):
109     fixtures = ['test-books.yaml']
110
111     def test_books(self):
112         self.assert_json_response('/api/books/', 'books.json')
113         self.assert_json_response('/api/books/?new_api=true', 'books.json')
114
115         self.assert_slugs('/api/audiobooks/', ['parent'])
116         self.assert_slugs('/api/daisy/', ['parent'])
117         self.assert_slugs('/api/newest/', ['parent'])
118         self.assert_slugs('/api/parent_books/', ['parent'])
119         self.assert_slugs('/api/recommended/', ['parent'])
120
121         # Book paging.
122         self.assert_slugs('/api/books/after/grandchild/count/1/', ['parent'])
123         self.assert_slugs('/api/books/?new_api=true&after=$grandchild$3&count=1', ['parent'])
124
125         # By tag.
126         self.assert_slugs('/api/authors/john-doe/books/', ['parent'])
127         self.assert_slugs('/api/genres/sonet/books/?authors=john-doe', ['parent'])
128         # It is probably a mistake that this doesn't filter:
129         self.assert_slugs('/api/books/?authors=john-doe', ['child', 'grandchild', 'parent'])
130
131         # Parent books by tag.
132         # Notice this contains a grandchild, if a child doesn't have the tag.
133         # This probably isn't really intended behavior and should be redefined.
134         self.assert_slugs('/api/genres/sonet/parent_books/', ['grandchild', 'parent'])
135
136     def test_ebooks(self):
137         self.assert_json_response('/api/ebooks/', 'ebooks.json')
138
139     def test_filter_books(self):
140         self.assert_json_response('/api/filter-books/', 'filter-books.json')
141         self.assert_slugs(
142             '/api/filter-books/?lektura=false&preview=false',
143             ['child', 'grandchild', 'parent'])
144         self.assert_slugs(
145             '/api/filter-books/?lektura=true',
146             [])
147
148         Book.objects.filter(slug='child').update(preview=True)
149         self.assert_slugs('/api/filter-books/?preview=true', ['child'])
150         self.assert_slugs('/api/filter-books/?preview=false', ['grandchild', 'parent'])
151
152         self.assert_slugs('/api/filter-books/?audiobook=true', ['parent'])
153         self.assert_slugs('/api/filter-books/?audiobook=false', ['child', 'grandchild'])
154
155         self.assert_slugs('/api/filter-books/?genres=wiersz', ['child'])
156
157         self.assert_slugs('/api/filter-books/?search=parent', ['parent'])
158
159     def test_collections(self):
160         self.assert_json_response('/api/collections/', 'collections.json')
161         self.assert_json_response('/api/collections/a-collection/', 'collection.json')
162
163     def test_book(self):
164         self.assert_json_response('/api/books/parent/', 'books-parent.json')
165         self.assert_json_response('/api/books/child/', 'books-child.json')
166         self.assert_json_response('/api/books/grandchild/', 'books-grandchild.json')
167
168     def test_tags(self):
169         # List of tags by category.
170         self.assert_json_response('/api/genres/', 'tags.json')
171
172     def test_fragments(self):
173         # This is not supported, though it probably should be.
174         #self.assert_json_response('/api/books/child/fragments/', 'fragments.json')
175
176         self.assert_json_response('/api/genres/wiersz/fragments/', 'fragments.json')
177         self.assert_json_response('/api/genres/wiersz/fragments/', 'fragments.json')
178
179         self.assert_json_response('/api/books/child/fragments/an-anchor/', 'fragment.json')
180
181
182 class BlogTests(ApiTest):
183     def test_get(self):
184         self.assertEqual(self.load_json('/api/blog/'), [])
185
186
187 class PreviewTests(ApiTest):
188     def unauth(self):
189         self.assert_json_response('/api/preview/', 'preview.json')
190
191