From: Radek Czajka Date: Tue, 15 Jan 2019 23:34:07 +0000 (+0100) Subject: Some tests for various API endpoints. X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/f3e9066b40546163f0df4678702ca4d7d31f9f84?ds=sidebyside;hp=b6acaa277803adf1f39dd61b362ca499b1bb6064 Some tests for various API endpoints. --- diff --git a/src/api/tests.py b/src/api/tests.py deleted file mode 100644 index e02120de8..000000000 --- a/src/api/tests.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from os import path - -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import TestCase -from django.test.utils import override_settings -import json - -from catalogue.models import Book, Tag -from picture.forms import PictureImportForm -from picture.models import Picture -import picture.tests - - -@override_settings( - NO_SEARCH_INDEX=True, - CACHES={'default': { - 'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}, - SSIFY_CACHE_ALIASES=['default'], - SSIFY_RENDER=True, -) -class ApiTest(TestCase): - def load_json(self, url): - content = self.client.get(url).content - try: - data = json.loads(content) - except ValueError: - self.fail('No JSON could be decoded: %s' % content) - return data - - -class BookTests(ApiTest): - - def setUp(self): - self.tag = Tag.objects.create(category='author', slug='joe') - self.book = Book.objects.create(title='A Book', slug='a-book') - self.book_tagged = Book.objects.create(title='Tagged Book', slug='tagged-book') - self.book_tagged.tags = [self.tag] - self.book_tagged.save() - - def test_book_list(self): - books = self.load_json('/api/books/') - self.assertEqual(len(books), 2, - 'Wrong book list.') - - def test_tagged_books(self): - books = self.load_json('/api/authors/joe/books/') - - self.assertEqual([b['title'] for b in books], [self.book_tagged.title], - 'Wrong tagged book list.') - - def test_detail(self): - book = self.load_json('/api/books/a-book/') - self.assertEqual(book['title'], self.book.title, - 'Wrong book details.') - - -class TagTests(ApiTest): - - def setUp(self): - self.tag = Tag.objects.create(category='author', slug='joe', name='Joe') - self.book = Book.objects.create(title='A Book', slug='a-book') - self.book.tags = [self.tag] - self.book.save() - - def test_tag_list(self): - tags = self.load_json('/api/authors/') - self.assertEqual(len(tags), 1, - 'Wrong tag list.') - - def test_tag_detail(self): - tag = self.load_json('/api/authors/joe/') - self.assertEqual(tag['name'], self.tag.name, - 'Wrong tag details.') - - -class PictureTests(ApiTest): - def test_publish(self): - slug = "kandinsky-composition-viii" - xml = SimpleUploadedFile( - 'composition8.xml', open(path.join(picture.tests.__path__[0], "files", slug + ".xml")).read()) - img = SimpleUploadedFile( - 'kompozycja-8.png', open(path.join(picture.tests.__path__[0], "files", slug + ".png")).read()) - - import_form = PictureImportForm({}, { - 'picture_xml_file': xml, - 'picture_image_file': img - }) - - assert import_form.is_valid() - if import_form.is_valid(): - import_form.save() - - Picture.objects.get(slug=slug) diff --git a/src/api/tests/__init__.py b/src/api/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/api/tests/res/responses/audiobooks.json b/src/api/tests/res/responses/audiobooks.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/api/tests/res/responses/audiobooks.json @@ -0,0 +1 @@ +[] diff --git a/src/api/tests/res/responses/blog.json b/src/api/tests/res/responses/blog.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/api/tests/res/responses/blog.json @@ -0,0 +1 @@ +[] diff --git a/src/api/tests/res/responses/collections.json b/src/api/tests/res/responses/collections.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/api/tests/res/responses/collections.json @@ -0,0 +1 @@ +[] diff --git a/src/api/tests/res/responses/daisy.json b/src/api/tests/res/responses/daisy.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/api/tests/res/responses/daisy.json @@ -0,0 +1 @@ +[] diff --git a/src/api/tests/res/responses/ebooks.json b/src/api/tests/res/responses/ebooks.json new file mode 100644 index 000000000..70084ef6c --- /dev/null +++ b/src/api/tests/res/responses/ebooks.json @@ -0,0 +1,35 @@ +[ + { + "fb2": "", + "mobi": "", + "author": "", + "cover": "", + "href": "https://example.com/api/books/child/", + "pdf": "", + "txt": "", + "slug": "child", + "epub": "" + }, + { + "fb2": "https://example.com/media/fb2/grandchild.fb2", + "mobi": "", + "author": "", + "cover": "", + "href": "https://example.com/api/books/grandchild/", + "pdf": "", + "txt": "https://example.com/media/txt/grandchild.txt", + "slug": "grandchild", + "epub": "" + }, + { + "fb2": "", + "mobi": "https://example.com/media/mobi/parent.mobi", + "author": "John Doe", + "cover": "cover/parent.jpg", + "href": "https://example.com/api/books/parent/", + "pdf": "https://example.com/media/pdf/parent.pdf", + "txt": "", + "slug": "parent", + "epub": "https://example.com/media/epub/parent.epub" + } +] diff --git a/src/api/tests/res/responses/filter-books.json b/src/api/tests/res/responses/filter-books.json new file mode 100644 index 000000000..db41287ea --- /dev/null +++ b/src/api/tests/res/responses/filter-books.json @@ -0,0 +1,50 @@ +[ + { + "kind": "", + "full_sort_key": "$child$2", + "cover_color": "#000000", + "author": "", + "url": "https://example.com/katalog/lektura/child/", + "has_audio": false, + "cover": "", + "epoch": "", + "href": "https://example.com/api/books/child/", + "key": "book$child", + "genre": "", + "simple_thumb": "", + "slug": "child", + "cover_thumb": "" + }, + { + "kind": "", + "full_sort_key": "$grandchild$3", + "cover_color": "#000000", + "author": "", + "url": "https://example.com/katalog/lektura/grandchild/", + "has_audio": false, + "cover": "", + "epoch": "", + "href": "https://example.com/api/books/grandchild/", + "key": "book$grandchild", + "genre": "", + "simple_thumb": "", + "slug": "grandchild", + "cover_thumb": "" + }, + { + "kind": "Liryka", + "full_sort_key": "john doe$parent$1", + "cover_color": "#a6820a", + "author": "John Doe", + "url": "https://example.com/katalog/lektura/parent/", + "has_audio": false, + "cover": "cover/parent.jpg", + "epoch": "Barok", + "href": "https://example.com/api/books/parent/", + "key": "book$parent", + "genre": "Sonet", + "simple_thumb": "https://example.com/media/cover/parent_cover_api_thumb.jpg", + "slug": "parent", + "cover_thumb": "https://example.com/media/cover/parent.jpg-139x193" + } +] diff --git a/src/api/tests/res/responses/newest.json b/src/api/tests/res/responses/newest.json new file mode 100644 index 000000000..8abde743f --- /dev/null +++ b/src/api/tests/res/responses/newest.json @@ -0,0 +1,17 @@ +[ + { + "kind": "Liryka", + "full_sort_key": "john doe$parent$1", + "cover_color": "#a6820a", + "author": "John Doe", + "url": "https://example.com/katalog/lektura/parent/", + "has_audio": false, + "cover": "cover/parent.jpg", + "epoch": "Barok", + "href": "https://example.com/api/books/parent/", + "genre": "Sonet", + "simple_thumb": "https://example.com/media/cover/parent_cover_api_thumb.jpg", + "slug": "parent", + "cover_thumb": "https://example.com/media/cover/parent.jpg-139x193" + } +] diff --git a/src/api/tests/res/responses/preview.json b/src/api/tests/res/responses/preview.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/api/tests/res/responses/preview.json @@ -0,0 +1 @@ +[] diff --git a/src/api/tests/res/responses/recommended.json b/src/api/tests/res/responses/recommended.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/api/tests/res/responses/recommended.json @@ -0,0 +1 @@ +[] diff --git a/src/api/tests/tests.py b/src/api/tests/tests.py new file mode 100644 index 000000000..32d394e70 --- /dev/null +++ b/src/api/tests/tests.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from os import path +import json + +from django.core.files.uploadedfile import SimpleUploadedFile +from django.test import TestCase +from django.test.utils import override_settings + +from catalogue.models import Book, Tag +from picture.forms import PictureImportForm +from picture.models import Picture +import picture.tests + + +@override_settings( + NO_SEARCH_INDEX=True, + CACHES={'default': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}, +) +class ApiTest(TestCase): + def load_json(self, url): + content = self.client.get(url).content + try: + data = json.loads(content) + except ValueError: + self.fail('No JSON could be decoded: %s' % content) + return data + + def assert_json_response(self, url, name): + data = self.load_json(url) + with open(path.join(path.dirname(__file__), 'res', 'responses', name)) as f: + good_data = json.load(f) + self.assertEqual(data, good_data, json.dumps(data, indent=4)) + + +class BookTests(ApiTest): + + def setUp(self): + self.tag = Tag.objects.create(category='author', slug='joe') + self.book = Book.objects.create(title='A Book', slug='a-book') + self.book_tagged = Book.objects.create(title='Tagged Book', slug='tagged-book') + self.book_tagged.tags = [self.tag] + self.book_tagged.save() + + def test_book_list(self): + books = self.load_json('/api/books/') + self.assertEqual(len(books), 2, + 'Wrong book list.') + + def test_tagged_books(self): + books = self.load_json('/api/authors/joe/books/') + + self.assertEqual([b['title'] for b in books], [self.book_tagged.title], + 'Wrong tagged book list.') + + def test_detail(self): + book = self.load_json('/api/books/a-book/') + self.assertEqual(book['title'], self.book.title, + 'Wrong book details.') + + +class TagTests(ApiTest): + + def setUp(self): + self.tag = Tag.objects.create(category='author', slug='joe', name='Joe') + self.book = Book.objects.create(title='A Book', slug='a-book') + self.book.tags = [self.tag] + self.book.save() + + def test_tag_list(self): + tags = self.load_json('/api/authors/') + self.assertEqual(len(tags), 1, + 'Wrong tag list.') + + def test_tag_detail(self): + tag = self.load_json('/api/authors/joe/') + self.assertEqual(tag['name'], self.tag.name, + 'Wrong tag details.') + + +class PictureTests(ApiTest): + def test_publish(self): + slug = "kandinsky-composition-viii" + xml = SimpleUploadedFile( + 'composition8.xml', open(path.join(picture.tests.__path__[0], "files", slug + ".xml")).read()) + img = SimpleUploadedFile( + 'kompozycja-8.png', open(path.join(picture.tests.__path__[0], "files", slug + ".png")).read()) + + import_form = PictureImportForm({}, { + 'picture_xml_file': xml, + 'picture_image_file': img + }) + + assert import_form.is_valid() + if import_form.is_valid(): + import_form.save() + + Picture.objects.get(slug=slug) + + +class URLTests(ApiTest): + fixtures = ['test-books.yaml'] + + def test_get(self): + # book lists + self.assert_json_response('/api/audiobooks/', 'audiobooks.json') + self.assert_json_response('/api/daisy/', 'daisy.json') + self.assert_json_response('/api/ebooks/', 'ebooks.json') + self.assert_json_response('/api/filter-books/', 'filter-books.json') + self.assert_json_response('/api/newest/', 'newest.json') + + self.assert_json_response('/api/blog/', 'blog.json') + self.assert_json_response('/api/preview/', 'preview.json') + self.assert_json_response('/api/recommended/', 'recommended.json') + + self.assert_json_response('/api/collections/', 'collections.json') diff --git a/src/catalogue/fixtures/collection-boy.json b/src/catalogue/fixtures/collection-boy.json deleted file mode 100644 index 1328b132b..000000000 --- a/src/catalogue/fixtures/collection-boy.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "pk": "promo", - "model": "chunks.chunk", - "fields": { - "content": "

\r\n\r\n\r\nOh Boy!\r\n\r\n\r\n

\r\n\r\n\r\nBiblioteczka Boya\r\n\r\n\r\n

\r\n\r\n\r\n

T\u0142umaczenia literatury francuskiej i nie tylko.

\r\n\r\n

Biblioteczka Boya \u21d2

\r\n\r\n\r\n
", - "description": "boks promocyjny na g\u0142\u00f3wnej" - } - }, - { - "pk": "boy", - "model": "catalogue.collection", - "fields": { - "book_slugs": "http://www.wolnelektury.pl/katalog/lektura/piesn-o-rolandzie/\nhttp://www.wolnelektury.pl/katalog/lektura/wielki-testament/\nhttp://www.wolnelektury.pl/katalog/lektura/skapiec/\nhttp://www.wolnelektury.pl/katalog/lektura/mieszczanin-szlachcicem/\nhttp://www.wolnelektury.pl/katalog/lektura/kandyd/\nhttp://www.wolnelektury.pl/katalog/lektura/rozprawa-o-metodzie/\nhttp://www.wolnelektury.pl/katalog/lektura/listy-perskie/\nhttp://www.wolnelektury.pl/katalog/lektura/spowiedz-dzieciecia-wieku/\nhttp://www.wolnelektury.pl/katalog/lektura/ubu-krol/\nhttp://www.wolnelektury.pl/katalog/lektura/legenda-o-tristanie-i-izoldzie/\nhttp://www.wolnelektury.pl/katalog/lektura/boy-swietoszek/\nhttp://www.wolnelektury.pl/katalog/lektura/mizantrop/\nhttp://www.wolnelektury.pl/katalog/lektura/kubus-fatalista-i-jego-pan/\nhttp://www.wolnelektury.pl/katalog/lektura/mysli/\nhttp://www.wolnelektury.pl/katalog/lektura/o-duchu-praw/\nhttp://www.wolnelektury.pl/katalog/lektura/proby/\nhttp://www.wolnelektury.pl/katalog/lektura/w-strone-swanna/\nhttp://www.wolnelektury.pl/katalog/lektura/gargantua-i-pantagruel/", - "description": "", - "title": "Biblioteczka Boya" - } - } -] \ No newline at end of file diff --git a/src/catalogue/fixtures/test-books.yaml b/src/catalogue/fixtures/test-books.yaml new file mode 100644 index 000000000..43ca447e9 --- /dev/null +++ b/src/catalogue/fixtures/test-books.yaml @@ -0,0 +1,96 @@ +- model: catalogue.book + pk: 1 + fields: + slug: parent + sort_key: parent + sort_key_author: john doe + epub_file: epub/parent.epub + mobi_file: mobi/parent.mobi + pdf_file: pdf/parent.pdf + cover: cover/parent.jpg + cover_api_thumb: cover/parent_cover_api_thumb.jpg + created_at: "1970-01-03 0:0Z" + changed_at: "1970-01-03 0:0Z" + extra_info: "{\"epoch\": \"Barok\"}" +- model: catalogue.book + pk: 2 + fields: + slug: child + sort_key: child + parent: 1 + created_at: "1970-01-02 0:0Z" + changed_at: "1970-01-02 0:0Z" +- model: catalogue.book + pk: 3 + fields: + slug: grandchild + sort_key: grandchild + parent: 2 + txt_file: txt/grandchild.txt + html_file: html/grandchild.html + fb2_file: fb2/grandchild.fb2 + created_at: "1970-01-01 0:0Z" + changed_at: "1970-01-01 0:0Z" + +- model: catalogue.tag + pk: 1 + fields: + slug: john-doe + sort_key: john doe + category: author + name: John Doe + created_at: "1970-01-03 0:0Z" + changed_at: "1970-01-03 0:0Z" +- model: catalogue.tag + pk: 2 + fields: + slug: liryka + sort_key: liryka + category: kind + name: Liryka + created_at: "1970-01-03 0:0Z" + changed_at: "1970-01-03 0:0Z" +- model: catalogue.tag + pk: 3 + fields: + slug: barok + sort_key: barok + category: epoch + name: Barok + created_at: "1970-01-03 0:0Z" + changed_at: "1970-01-03 0:0Z" +- model: catalogue.tag + pk: 4 + fields: + slug: sonet + sort_key: sonet + category: genre + name: Sonet + created_at: "1970-01-03 0:0Z" + changed_at: "1970-01-03 0:0Z" + +- model: catalogue.tagrelation + pk: 1 + fields: + tag: 1 + content_type: ['catalogue', 'book'] + object_id: 1 +- model: catalogue.tagrelation + pk: 2 + fields: + tag: 2 + content_type: ['catalogue', 'book'] + object_id: 1 +- model: catalogue.tagrelation + pk: 3 + fields: + tag: 3 + content_type: ['catalogue', 'book'] + object_id: 1 +- model: catalogue.tagrelation + pk: 4 + fields: + tag: 4 + content_type: ['catalogue', 'book'] + object_id: 1 + diff --git a/src/manage.py b/src/manage.py index c1c055b1e..d69b6e5f5 100755 --- a/src/manage.py +++ b/src/manage.py @@ -8,7 +8,11 @@ sys.path = [ ] + sys.path if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wolnelektury.settings") + os.environ.setdefault( + "DJANGO_SETTINGS_MODULE", + "wolnelektury.settings.test" + if 'test' in sys.argv + else "wolnelektury.settings") from django.core.management import execute_from_command_line diff --git a/src/wolnelektury/settings/test.py b/src/wolnelektury/settings/test.py new file mode 100644 index 000000000..0de27c7a7 --- /dev/null +++ b/src/wolnelektury/settings/test.py @@ -0,0 +1,3 @@ +from wolnelektury.settings import * + +THUMBNAIL_BACKEND = 'wolnelektury.test_utils.DummyThumbnailBackend' diff --git a/src/wolnelektury/test_utils.py b/src/wolnelektury/test_utils.py new file mode 100644 index 000000000..f22eb9898 --- /dev/null +++ b/src/wolnelektury/test_utils.py @@ -0,0 +1,7 @@ +class DummyThumbnailBackend: + class DummyThumbnail: + def __init__(self, url): + self.url = url + + def get_thumbnail(self, file_, geometry_string, **options): + return self.DummyThumbnail(url='-'.join((file_.url, geometry_string)))