Merge branch 'main' into validate-username
This commit is contained in:
@ -1,60 +1,114 @@
|
||||
''' testing book data connectors '''
|
||||
from unittest.mock import patch
|
||||
from django.test import TestCase
|
||||
import responses
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.connectors import abstract_connector
|
||||
from bookwyrm.connectors.abstract_connector import Mapping
|
||||
from bookwyrm.connectors.openlibrary import Connector
|
||||
from bookwyrm.settings import DOMAIN
|
||||
|
||||
|
||||
class AbstractConnector(TestCase):
|
||||
''' generic code for connecting to outside data sources '''
|
||||
def setUp(self):
|
||||
self.book = models.Edition.objects.create(title='Example Edition')
|
||||
|
||||
models.Connector.objects.create(
|
||||
''' we need an example connector '''
|
||||
self.connector_info = models.Connector.objects.create(
|
||||
identifier='example.com',
|
||||
connector_file='openlibrary',
|
||||
base_url='https://example.com',
|
||||
books_url='https:/example.com',
|
||||
covers_url='https://example.com',
|
||||
books_url='https://example.com/books',
|
||||
covers_url='https://example.com/covers',
|
||||
search_url='https://example.com/search?q=',
|
||||
)
|
||||
self.connector = Connector('example.com')
|
||||
|
||||
self.data = {
|
||||
'title': 'Unused title',
|
||||
'ASIN': 'A00BLAH',
|
||||
'isbn_10': '1234567890',
|
||||
'isbn_13': 'blahhh',
|
||||
'blah': 'bip',
|
||||
'format': 'hardcover',
|
||||
'series': ['one', 'two'],
|
||||
work_data = {
|
||||
'id': 'abc1',
|
||||
'title': 'Test work',
|
||||
'type': 'work',
|
||||
'openlibraryKey': 'OL1234W',
|
||||
}
|
||||
self.connector.key_mappings = [
|
||||
Mapping('isbn_10'),
|
||||
Mapping('isbn_13'),
|
||||
Mapping('lccn'),
|
||||
Mapping('asin'),
|
||||
self.work_data = work_data
|
||||
edition_data = {
|
||||
'id': 'abc2',
|
||||
'title': 'Test edition',
|
||||
'type': 'edition',
|
||||
'openlibraryKey': 'OL1234M',
|
||||
}
|
||||
self.edition_data = edition_data
|
||||
|
||||
class TestConnector(abstract_connector.AbstractConnector):
|
||||
''' nothing added here '''
|
||||
def format_search_result(self, search_result):
|
||||
return search_result
|
||||
def parse_search_data(self, data):
|
||||
return data
|
||||
def is_work_data(self, data):
|
||||
return data['type'] == 'work'
|
||||
def get_edition_from_work_data(self, data):
|
||||
return edition_data
|
||||
def get_work_from_edition_data(self, data):
|
||||
return work_data
|
||||
def get_authors_from_data(self, data):
|
||||
return []
|
||||
def expand_book_data(self, book):
|
||||
pass
|
||||
self.connector = TestConnector('example.com')
|
||||
self.connector.book_mappings = [
|
||||
Mapping('id'),
|
||||
Mapping('title'),
|
||||
Mapping('openlibraryKey'),
|
||||
]
|
||||
|
||||
|
||||
def test_create_mapping(self):
|
||||
mapping = Mapping('isbn')
|
||||
self.assertEqual(mapping.local_field, 'isbn')
|
||||
self.assertEqual(mapping.remote_field, 'isbn')
|
||||
self.assertEqual(mapping.formatter('bb'), 'bb')
|
||||
self.book = models.Edition.objects.create(
|
||||
title='Test Book', remote_id='https://example.com/book/1234',
|
||||
openlibrary_key='OL1234M')
|
||||
|
||||
|
||||
def test_create_mapping_with_remote(self):
|
||||
mapping = Mapping('isbn', remote_field='isbn13')
|
||||
self.assertEqual(mapping.local_field, 'isbn')
|
||||
self.assertEqual(mapping.remote_field, 'isbn13')
|
||||
self.assertEqual(mapping.formatter('bb'), 'bb')
|
||||
def test_abstract_connector_init(self):
|
||||
''' barebones connector for search with defaults '''
|
||||
self.assertIsInstance(self.connector.book_mappings, list)
|
||||
|
||||
|
||||
def test_create_mapping_with_formatter(self):
|
||||
formatter = lambda x: 'aa' + x
|
||||
mapping = Mapping('isbn', formatter=formatter)
|
||||
self.assertEqual(mapping.local_field, 'isbn')
|
||||
self.assertEqual(mapping.remote_field, 'isbn')
|
||||
self.assertEqual(mapping.formatter, formatter)
|
||||
self.assertEqual(mapping.formatter('bb'), 'aabb')
|
||||
def test_is_available(self):
|
||||
''' this isn't used.... '''
|
||||
self.assertTrue(self.connector.is_available())
|
||||
self.connector.max_query_count = 1
|
||||
self.connector.connector.query_count = 2
|
||||
self.assertFalse(self.connector.is_available())
|
||||
|
||||
|
||||
def test_get_or_create_book_existing(self):
|
||||
''' find an existing book by remote/origin id '''
|
||||
self.assertEqual(models.Book.objects.count(), 1)
|
||||
self.assertEqual(
|
||||
self.book.remote_id, 'https://%s/book/%d' % (DOMAIN, self.book.id))
|
||||
self.assertEqual(
|
||||
self.book.origin_id, 'https://example.com/book/1234')
|
||||
|
||||
# dedupe by origin id
|
||||
result = self.connector.get_or_create_book(
|
||||
'https://example.com/book/1234')
|
||||
self.assertEqual(models.Book.objects.count(), 1)
|
||||
self.assertEqual(result, self.book)
|
||||
|
||||
# dedupe by remote id
|
||||
result = self.connector.get_or_create_book(
|
||||
'https://%s/book/%d' % (DOMAIN, self.book.id))
|
||||
self.assertEqual(models.Book.objects.count(), 1)
|
||||
self.assertEqual(result, self.book)
|
||||
|
||||
@responses.activate
|
||||
def test_get_or_create_book_deduped(self):
|
||||
''' load remote data and deduplicate '''
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://example.com/book/abcd',
|
||||
json=self.edition_data
|
||||
)
|
||||
with patch(
|
||||
'bookwyrm.connectors.abstract_connector.load_more_data.delay'):
|
||||
result = self.connector.get_or_create_book(
|
||||
'https://example.com/book/abcd')
|
||||
self.assertEqual(result, self.book)
|
||||
self.assertEqual(models.Edition.objects.count(), 1)
|
||||
self.assertEqual(models.Edition.objects.count(), 1)
|
||||
|
100
bookwyrm/tests/connectors/test_abstract_minimal_connector.py
Normal file
100
bookwyrm/tests/connectors/test_abstract_minimal_connector.py
Normal file
@ -0,0 +1,100 @@
|
||||
''' testing book data connectors '''
|
||||
from django.test import TestCase
|
||||
import responses
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.connectors import abstract_connector
|
||||
from bookwyrm.connectors.abstract_connector import Mapping, SearchResult
|
||||
|
||||
|
||||
class AbstractConnector(TestCase):
|
||||
''' generic code for connecting to outside data sources '''
|
||||
def setUp(self):
|
||||
''' we need an example connector '''
|
||||
self.connector_info = models.Connector.objects.create(
|
||||
identifier='example.com',
|
||||
connector_file='openlibrary',
|
||||
base_url='https://example.com',
|
||||
books_url='https://example.com/books',
|
||||
covers_url='https://example.com/covers',
|
||||
search_url='https://example.com/search?q=',
|
||||
)
|
||||
|
||||
class TestConnector(abstract_connector.AbstractMinimalConnector):
|
||||
''' nothing added here '''
|
||||
def format_search_result(self, search_result):
|
||||
return search_result
|
||||
def get_or_create_book(self, remote_id):
|
||||
pass
|
||||
def parse_search_data(self, data):
|
||||
return data
|
||||
self.test_connector = TestConnector('example.com')
|
||||
|
||||
|
||||
def test_abstract_minimal_connector_init(self):
|
||||
''' barebones connector for search with defaults '''
|
||||
connector = self.test_connector
|
||||
self.assertEqual(connector.connector, self.connector_info)
|
||||
self.assertEqual(connector.base_url, 'https://example.com')
|
||||
self.assertEqual(connector.books_url, 'https://example.com/books')
|
||||
self.assertEqual(connector.covers_url, 'https://example.com/covers')
|
||||
self.assertEqual(connector.search_url, 'https://example.com/search?q=')
|
||||
self.assertIsNone(connector.name)
|
||||
self.assertEqual(connector.identifier, 'example.com')
|
||||
self.assertIsNone(connector.max_query_count)
|
||||
self.assertFalse(connector.local)
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_search(self):
|
||||
''' makes an http request to the outside service '''
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://example.com/search?q=a%20book%20title',
|
||||
json=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'],
|
||||
status=200)
|
||||
results = self.test_connector.search('a book title')
|
||||
self.assertEqual(len(results), 10)
|
||||
self.assertEqual(results[0], 'a')
|
||||
self.assertEqual(results[1], 'b')
|
||||
self.assertEqual(results[2], 'c')
|
||||
|
||||
|
||||
def test_search_result(self):
|
||||
''' a class that stores info about a search result '''
|
||||
result = SearchResult(
|
||||
title='Title',
|
||||
key='https://example.com/book/1',
|
||||
author='Author Name',
|
||||
year='1850',
|
||||
connector=self.test_connector,
|
||||
)
|
||||
# there's really not much to test here, it's just a dataclass
|
||||
self.assertEqual(result.confidence, 1)
|
||||
self.assertEqual(result.title, 'Title')
|
||||
|
||||
|
||||
def test_create_mapping(self):
|
||||
''' maps remote fields for book data to bookwyrm activitypub fields '''
|
||||
mapping = Mapping('isbn')
|
||||
self.assertEqual(mapping.local_field, 'isbn')
|
||||
self.assertEqual(mapping.remote_field, 'isbn')
|
||||
self.assertEqual(mapping.formatter('bb'), 'bb')
|
||||
|
||||
|
||||
def test_create_mapping_with_remote(self):
|
||||
''' the remote field is different than the local field '''
|
||||
mapping = Mapping('isbn', remote_field='isbn13')
|
||||
self.assertEqual(mapping.local_field, 'isbn')
|
||||
self.assertEqual(mapping.remote_field, 'isbn13')
|
||||
self.assertEqual(mapping.formatter('bb'), 'bb')
|
||||
|
||||
|
||||
def test_create_mapping_with_formatter(self):
|
||||
''' a function is provided to modify the data '''
|
||||
formatter = lambda x: 'aa' + x
|
||||
mapping = Mapping('isbn', formatter=formatter)
|
||||
self.assertEqual(mapping.local_field, 'isbn')
|
||||
self.assertEqual(mapping.remote_field, 'isbn')
|
||||
self.assertEqual(mapping.formatter, formatter)
|
||||
self.assertEqual(mapping.formatter('bb'), 'aabb')
|
@ -31,6 +31,7 @@ class BookWyrmConnector(TestCase):
|
||||
|
||||
|
||||
def test_format_search_result(self):
|
||||
''' create a SearchResult object from search response json '''
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/fr_search.json')
|
||||
search_data = json.loads(datafile.read_bytes())
|
||||
@ -43,3 +44,4 @@ class BookWyrmConnector(TestCase):
|
||||
self.assertEqual(result.key, 'https://example.com/book/122')
|
||||
self.assertEqual(result.author, 'Susanna Clarke')
|
||||
self.assertEqual(result.year, 2017)
|
||||
self.assertEqual(result.connector, self.connector)
|
||||
|
@ -1,12 +1,18 @@
|
||||
''' interface between the app and various connectors '''
|
||||
from django.test import TestCase
|
||||
|
||||
from bookwyrm import books_manager, models
|
||||
from bookwyrm.connectors.bookwyrm_connector import Connector as BookWyrmConnector
|
||||
from bookwyrm.connectors.self_connector import Connector as SelfConnector
|
||||
from bookwyrm import models
|
||||
from bookwyrm.connectors import connector_manager
|
||||
from bookwyrm.connectors.bookwyrm_connector \
|
||||
import Connector as BookWyrmConnector
|
||||
from bookwyrm.connectors.self_connector \
|
||||
import Connector as SelfConnector
|
||||
|
||||
|
||||
class Book(TestCase):
|
||||
class ConnectorManager(TestCase):
|
||||
''' interface between the app and various connectors '''
|
||||
def setUp(self):
|
||||
''' we'll need some books and a connector info entry '''
|
||||
self.work = models.Work.objects.create(
|
||||
title='Example Work'
|
||||
)
|
||||
@ -28,53 +34,50 @@ class Book(TestCase):
|
||||
covers_url='http://test.com/',
|
||||
)
|
||||
|
||||
def test_get_edition(self):
|
||||
edition = books_manager.get_edition(self.edition.id)
|
||||
self.assertEqual(edition, self.edition)
|
||||
|
||||
|
||||
def test_get_edition_work(self):
|
||||
edition = books_manager.get_edition(self.work.id)
|
||||
self.assertEqual(edition, self.edition)
|
||||
|
||||
|
||||
def test_get_or_create_connector(self):
|
||||
''' loads a connector if the data source is known or creates one '''
|
||||
remote_id = 'https://example.com/object/1'
|
||||
connector = books_manager.get_or_create_connector(remote_id)
|
||||
connector = connector_manager.get_or_create_connector(remote_id)
|
||||
self.assertIsInstance(connector, BookWyrmConnector)
|
||||
self.assertEqual(connector.identifier, 'example.com')
|
||||
self.assertEqual(connector.base_url, 'https://example.com')
|
||||
|
||||
same_connector = books_manager.get_or_create_connector(remote_id)
|
||||
same_connector = connector_manager.get_or_create_connector(remote_id)
|
||||
self.assertEqual(connector.identifier, same_connector.identifier)
|
||||
|
||||
def test_get_connectors(self):
|
||||
''' load all connectors '''
|
||||
remote_id = 'https://example.com/object/1'
|
||||
books_manager.get_or_create_connector(remote_id)
|
||||
connectors = list(books_manager.get_connectors())
|
||||
connector_manager.get_or_create_connector(remote_id)
|
||||
connectors = list(connector_manager.get_connectors())
|
||||
self.assertEqual(len(connectors), 2)
|
||||
self.assertIsInstance(connectors[0], SelfConnector)
|
||||
self.assertIsInstance(connectors[1], BookWyrmConnector)
|
||||
|
||||
def test_search(self):
|
||||
results = books_manager.search('Example')
|
||||
''' search all connectors '''
|
||||
results = connector_manager.search('Example')
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertIsInstance(results[0]['connector'], SelfConnector)
|
||||
self.assertEqual(len(results[0]['results']), 1)
|
||||
self.assertEqual(results[0]['results'][0].title, 'Example Edition')
|
||||
|
||||
def test_local_search(self):
|
||||
results = books_manager.local_search('Example')
|
||||
''' search only the local database '''
|
||||
results = connector_manager.local_search('Example')
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0].title, 'Example Edition')
|
||||
|
||||
def test_first_search_result(self):
|
||||
result = books_manager.first_search_result('Example')
|
||||
''' only get one search result '''
|
||||
result = connector_manager.first_search_result('Example')
|
||||
self.assertEqual(result.title, 'Example Edition')
|
||||
no_result = books_manager.first_search_result('dkjfhg')
|
||||
no_result = connector_manager.first_search_result('dkjfhg')
|
||||
self.assertIsNone(no_result)
|
||||
|
||||
def test_load_connector(self):
|
||||
connector = books_manager.load_connector(self.connector)
|
||||
''' load a connector object from the database entry '''
|
||||
connector = connector_manager.load_connector(self.connector)
|
||||
self.assertIsInstance(connector, SelfConnector)
|
||||
self.assertEqual(connector.identifier, 'test_connector')
|
@ -1,9 +1,10 @@
|
||||
''' testing book data connectors '''
|
||||
import json
|
||||
import pathlib
|
||||
from dateutil import parser
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.test import TestCase
|
||||
import pytz
|
||||
import responses
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.connectors.openlibrary import Connector
|
||||
@ -11,10 +12,13 @@ from bookwyrm.connectors.openlibrary import get_languages, get_description
|
||||
from bookwyrm.connectors.openlibrary import pick_default_edition, \
|
||||
get_openlibrary_key
|
||||
from bookwyrm.connectors.abstract_connector import SearchResult
|
||||
from bookwyrm.connectors.connector_manager import ConnectorException
|
||||
|
||||
|
||||
class Openlibrary(TestCase):
|
||||
''' test loading data from openlibrary.org '''
|
||||
def setUp(self):
|
||||
''' creates the connector we'll use '''
|
||||
models.Connector.objects.create(
|
||||
identifier='openlibrary.org',
|
||||
name='OpenLibrary',
|
||||
@ -37,19 +41,85 @@ class Openlibrary(TestCase):
|
||||
self.edition_list_data = json.loads(edition_list_file.read_bytes())
|
||||
|
||||
|
||||
def test_get_remote_id_from_data(self):
|
||||
''' format the remote id from the data '''
|
||||
data = {'key': '/work/OL1234W'}
|
||||
result = self.connector.get_remote_id_from_data(data)
|
||||
self.assertEqual(result, 'https://openlibrary.org/work/OL1234W')
|
||||
# error handlding
|
||||
with self.assertRaises(ConnectorException):
|
||||
self.connector.get_remote_id_from_data({})
|
||||
|
||||
|
||||
def test_is_work_data(self):
|
||||
''' detect if the loaded json is a work '''
|
||||
self.assertEqual(self.connector.is_work_data(self.work_data), True)
|
||||
self.assertEqual(self.connector.is_work_data(self.edition_data), False)
|
||||
|
||||
|
||||
def test_pick_default_edition(self):
|
||||
edition = pick_default_edition(self.edition_list_data['entries'])
|
||||
self.assertEqual(edition['key'], '/books/OL9788823M')
|
||||
@responses.activate
|
||||
def test_get_edition_from_work_data(self):
|
||||
''' loads a list of editions '''
|
||||
data = {'key': '/work/OL1234W'}
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/work/OL1234W/editions',
|
||||
json={'entries': []},
|
||||
status=200)
|
||||
with patch('bookwyrm.connectors.openlibrary.pick_default_edition') \
|
||||
as pick_edition:
|
||||
pick_edition.return_value = 'hi'
|
||||
result = self.connector.get_edition_from_work_data(data)
|
||||
self.assertEqual(result, 'hi')
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_get_work_from_edition_data(self):
|
||||
''' loads a list of editions '''
|
||||
data = {'works': [{'key': '/work/OL1234W'}]}
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/work/OL1234W',
|
||||
json={'hi': 'there'},
|
||||
status=200)
|
||||
result = self.connector.get_work_from_edition_data(data)
|
||||
self.assertEqual(result, {'hi': 'there'})
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_get_authors_from_data(self):
|
||||
''' find authors in data '''
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/authors/OL382982A',
|
||||
json={'hi': 'there'},
|
||||
status=200)
|
||||
results = self.connector.get_authors_from_data(self.work_data)
|
||||
for result in results:
|
||||
self.assertIsInstance(result, models.Author)
|
||||
|
||||
|
||||
def test_get_cover_url(self):
|
||||
''' formats a url that should contain the cover image '''
|
||||
blob = ['image']
|
||||
result = self.connector.get_cover_url(blob)
|
||||
self.assertEqual(
|
||||
result, 'https://covers.openlibrary.org/b/id/image-L.jpg')
|
||||
|
||||
def test_parse_search_result(self):
|
||||
''' extract the results from the search json response '''
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ol_search.json')
|
||||
search_data = json.loads(datafile.read_bytes())
|
||||
result = self.connector.parse_search_data(search_data)
|
||||
self.assertIsInstance(result, list)
|
||||
self.assertEqual(len(result), 2)
|
||||
|
||||
|
||||
def test_format_search_result(self):
|
||||
''' translate json from openlibrary into SearchResult '''
|
||||
datafile = pathlib.Path(__file__).parent.joinpath('../data/ol_search.json')
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ol_search.json')
|
||||
search_data = json.loads(datafile.read_bytes())
|
||||
results = self.connector.parse_search_data(search_data)
|
||||
self.assertIsInstance(results, list)
|
||||
@ -57,22 +127,66 @@ class Openlibrary(TestCase):
|
||||
result = self.connector.format_search_result(results[0])
|
||||
self.assertIsInstance(result, SearchResult)
|
||||
self.assertEqual(result.title, 'This Is How You Lose the Time War')
|
||||
self.assertEqual(result.key, 'https://openlibrary.org/works/OL20639540W')
|
||||
self.assertEqual(
|
||||
result.key, 'https://openlibrary.org/works/OL20639540W')
|
||||
self.assertEqual(result.author, 'Amal El-Mohtar, Max Gladstone')
|
||||
self.assertEqual(result.year, 2019)
|
||||
self.assertEqual(result.connector, self.connector)
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_load_edition_data(self):
|
||||
''' format url from key and make request '''
|
||||
key = 'OL1234W'
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/works/OL1234W/editions',
|
||||
json={'hi': 'there'}
|
||||
)
|
||||
result = self.connector.load_edition_data(key)
|
||||
self.assertEqual(result, {'hi': 'there'})
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_expand_book_data(self):
|
||||
''' given a book, get more editions '''
|
||||
work = models.Work.objects.create(
|
||||
title='Test Work', openlibrary_key='OL1234W')
|
||||
edition = models.Edition.objects.create(
|
||||
title='Test Edition', parent_work=work)
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/works/OL1234W/editions',
|
||||
json={'entries': []},
|
||||
)
|
||||
with patch(
|
||||
'bookwyrm.connectors.abstract_connector.AbstractConnector.' \
|
||||
'create_edition_from_data'):
|
||||
self.connector.expand_book_data(edition)
|
||||
self.connector.expand_book_data(work)
|
||||
|
||||
|
||||
def test_get_description(self):
|
||||
''' should do some cleanup on the description data '''
|
||||
description = get_description(self.work_data['description'])
|
||||
expected = 'First in the Old Kingdom/Abhorsen series.'
|
||||
self.assertEqual(description, expected)
|
||||
|
||||
|
||||
def test_get_openlibrary_key(self):
|
||||
''' extracts the uuid '''
|
||||
key = get_openlibrary_key('/books/OL27320736M')
|
||||
self.assertEqual(key, 'OL27320736M')
|
||||
|
||||
|
||||
def test_get_languages(self):
|
||||
''' looks up languages from a list '''
|
||||
languages = get_languages(self.edition_data['languages'])
|
||||
self.assertEqual(languages, ['English'])
|
||||
|
||||
|
||||
def test_get_ol_key(self):
|
||||
key = get_openlibrary_key('/books/OL27320736M')
|
||||
self.assertEqual(key, 'OL27320736M')
|
||||
def test_pick_default_edition(self):
|
||||
''' detect if the loaded json is an edition '''
|
||||
edition = pick_default_edition(self.edition_list_data['entries'])
|
||||
self.assertEqual(edition['key'], '/books/OL9788823M')
|
||||
|
@ -9,7 +9,9 @@ from bookwyrm.settings import DOMAIN
|
||||
|
||||
|
||||
class SelfConnector(TestCase):
|
||||
''' just uses local data '''
|
||||
def setUp(self):
|
||||
''' creating the connector '''
|
||||
models.Connector.objects.create(
|
||||
identifier=DOMAIN,
|
||||
name='Local',
|
||||
@ -22,58 +24,85 @@ class SelfConnector(TestCase):
|
||||
priority=1,
|
||||
)
|
||||
self.connector = Connector(DOMAIN)
|
||||
self.work = models.Work.objects.create(
|
||||
title='Example Work',
|
||||
)
|
||||
author = models.Author.objects.create(name='Anonymous')
|
||||
self.edition = models.Edition.objects.create(
|
||||
title='Edition of Example Work',
|
||||
published_date=datetime.datetime(1980, 5, 10, tzinfo=timezone.utc),
|
||||
parent_work=self.work,
|
||||
)
|
||||
self.edition.authors.add(author)
|
||||
models.Edition.objects.create(
|
||||
title='Another Edition',
|
||||
parent_work=self.work,
|
||||
series='Anonymous'
|
||||
)
|
||||
models.Edition.objects.create(
|
||||
title='More Editions',
|
||||
subtitle='The Anonymous Edition',
|
||||
parent_work=self.work,
|
||||
)
|
||||
|
||||
edition = models.Edition.objects.create(
|
||||
title='An Edition',
|
||||
parent_work=self.work
|
||||
)
|
||||
edition.authors.add(models.Author.objects.create(name='Fish'))
|
||||
|
||||
|
||||
def test_format_search_result(self):
|
||||
''' create a SearchResult '''
|
||||
author = models.Author.objects.create(name='Anonymous')
|
||||
edition = models.Edition.objects.create(
|
||||
title='Edition of Example Work',
|
||||
published_date=datetime.datetime(1980, 5, 10, tzinfo=timezone.utc),
|
||||
)
|
||||
edition.authors.add(author)
|
||||
result = self.connector.search('Edition of Example')[0]
|
||||
self.assertEqual(result.title, 'Edition of Example Work')
|
||||
self.assertEqual(result.key, self.edition.remote_id)
|
||||
self.assertEqual(result.key, edition.remote_id)
|
||||
self.assertEqual(result.author, 'Anonymous')
|
||||
self.assertEqual(result.year, 1980)
|
||||
self.assertEqual(result.connector, self.connector)
|
||||
|
||||
|
||||
def test_search_rank(self):
|
||||
''' prioritize certain results '''
|
||||
author = models.Author.objects.create(name='Anonymous')
|
||||
edition = models.Edition.objects.create(
|
||||
title='Edition of Example Work',
|
||||
published_date=datetime.datetime(1980, 5, 10, tzinfo=timezone.utc),
|
||||
parent_work=models.Work.objects.create(title='')
|
||||
)
|
||||
# author text is rank C
|
||||
edition.authors.add(author)
|
||||
|
||||
# series is rank D
|
||||
models.Edition.objects.create(
|
||||
title='Another Edition',
|
||||
series='Anonymous',
|
||||
parent_work=models.Work.objects.create(title='')
|
||||
)
|
||||
# subtitle is rank B
|
||||
models.Edition.objects.create(
|
||||
title='More Editions',
|
||||
subtitle='The Anonymous Edition',
|
||||
parent_work=models.Work.objects.create(title='')
|
||||
)
|
||||
# title is rank A
|
||||
models.Edition.objects.create(title='Anonymous')
|
||||
# doesn't rank in this search
|
||||
edition = models.Edition.objects.create(
|
||||
title='An Edition',
|
||||
parent_work=models.Work.objects.create(title='')
|
||||
)
|
||||
|
||||
results = self.connector.search('Anonymous')
|
||||
self.assertEqual(len(results), 2)
|
||||
self.assertEqual(results[0].title, 'More Editions')
|
||||
self.assertEqual(results[1].title, 'Edition of Example Work')
|
||||
self.assertEqual(len(results), 3)
|
||||
self.assertEqual(results[0].title, 'Anonymous')
|
||||
self.assertEqual(results[1].title, 'More Editions')
|
||||
self.assertEqual(results[2].title, 'Edition of Example Work')
|
||||
|
||||
|
||||
def test_search_default_filter(self):
|
||||
def test_search_multiple_editions(self):
|
||||
''' it should get rid of duplicate editions for the same work '''
|
||||
self.work.default_edition = self.edition
|
||||
self.work.save()
|
||||
work = models.Work.objects.create(title='Work Title')
|
||||
edition_1 = models.Edition.objects.create(
|
||||
title='Edition 1 Title', parent_work=work)
|
||||
edition_2 = models.Edition.objects.create(
|
||||
title='Edition 2 Title', parent_work=work)
|
||||
edition_3 = models.Edition.objects.create(
|
||||
title='Fish', parent_work=work)
|
||||
work.default_edition = edition_2
|
||||
work.save()
|
||||
|
||||
results = self.connector.search('Anonymous')
|
||||
# pick the best edition
|
||||
results = self.connector.search('Edition 1 Title')
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0].title, 'Edition of Example Work')
|
||||
self.assertEqual(results[0].key, edition_1.remote_id)
|
||||
|
||||
# pick the default edition when no match is best
|
||||
results = self.connector.search('Edition Title')
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0].key, edition_2.remote_id)
|
||||
|
||||
# only matches one edition, so no deduplication takes place
|
||||
results = self.connector.search('Fish')
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0].title, 'An Edition')
|
||||
self.assertEqual(results[0].key, edition_3.remote_id)
|
||||
|
4
bookwyrm/tests/data/goodreads.csv
Normal file
4
bookwyrm/tests/data/goodreads.csv
Normal file
@ -0,0 +1,4 @@
|
||||
Book Id,Title,Author,Author l-f,Additional Authors,ISBN,ISBN13,My Rating,Average Rating,Publisher,Binding,Number of Pages,Year Published,Original Publication Year,Date Read,Date Added,Bookshelves,Bookshelves with positions,Exclusive Shelf,My Review,Spoiler,Private Notes,Read Count,Recommended For,Recommended By,Owned Copies,Original Purchase Date,Original Purchase Location,Condition,Condition Description,BCID
|
||||
42036538,Gideon the Ninth (The Locked Tomb #1),Tamsyn Muir,"Muir, Tamsyn",,"=""1250313198""","=""9781250313195""",0,4.20,Tor,Hardcover,448,2019,2019,2020/10/25,2020/10/21,,,read,,,,1,,,0,,,,,
|
||||
52691223,Subcutanean,Aaron A. Reed,"Reed, Aaron A.",,"=""""","=""""",0,4.45,,Paperback,232,2020,,2020/03/06,2020/03/05,,,read,,,,1,,,0,,,,,
|
||||
28694510,Patisserie at Home,Mélanie Dupuis,"Dupuis, Mélanie",Anne Cazor,"=""0062445316""","=""9780062445315""",2,4.60,Harper Design,Hardcover,288,2016,,,2019/07/08,,,read,"mixed feelings",,,2,,,0,,,,,
|
|
@ -206,3 +206,15 @@ class BaseModel(TestCase):
|
||||
# test subclass match
|
||||
result = models.Status.find_existing_by_remote_id(
|
||||
'https://comment.net')
|
||||
|
||||
|
||||
def test_find_existing(self):
|
||||
''' match a blob of data to a model '''
|
||||
book = models.Edition.objects.create(
|
||||
title='Test edition',
|
||||
openlibrary_key='OL1234',
|
||||
)
|
||||
|
||||
result = models.Edition.find_existing(
|
||||
{'openlibraryKey': 'OL1234'})
|
||||
self.assertEqual(result, book)
|
||||
|
@ -1,9 +1,16 @@
|
||||
''' testing models '''
|
||||
import datetime
|
||||
import json
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.utils import timezone
|
||||
from django.test import TestCase
|
||||
import responses
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.connectors import connector_manager
|
||||
from bookwyrm.connectors.abstract_connector import SearchResult
|
||||
|
||||
|
||||
class ImportJob(TestCase):
|
||||
@ -55,11 +62,11 @@ class ImportJob(TestCase):
|
||||
'mouse', 'mouse@mouse.mouse', 'mouseword',
|
||||
local=True, localname='mouse')
|
||||
job = models.ImportJob.objects.create(user=user)
|
||||
models.ImportItem.objects.create(
|
||||
self.item_1 = models.ImportItem.objects.create(
|
||||
job=job, index=1, data=currently_reading_data)
|
||||
models.ImportItem.objects.create(
|
||||
self.item_2 = models.ImportItem.objects.create(
|
||||
job=job, index=2, data=read_data)
|
||||
models.ImportItem.objects.create(
|
||||
self.item_3 = models.ImportItem.objects.create(
|
||||
job=job, index=3, data=unknown_read_data)
|
||||
|
||||
|
||||
@ -73,8 +80,7 @@ class ImportJob(TestCase):
|
||||
def test_shelf(self):
|
||||
''' converts to the local shelf typology '''
|
||||
expected = 'reading'
|
||||
item = models.ImportItem.objects.get(index=1)
|
||||
self.assertEqual(item.shelf, expected)
|
||||
self.assertEqual(self.item_1.shelf, expected)
|
||||
|
||||
|
||||
def test_date_added(self):
|
||||
@ -92,21 +98,79 @@ class ImportJob(TestCase):
|
||||
|
||||
|
||||
def test_currently_reading_reads(self):
|
||||
''' infer currently reading dates where available '''
|
||||
expected = [models.ReadThrough(
|
||||
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))]
|
||||
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
|
||||
)]
|
||||
actual = models.ImportItem.objects.get(index=1)
|
||||
self.assertEqual(actual.reads[0].start_date, expected[0].start_date)
|
||||
self.assertEqual(actual.reads[0].finish_date, expected[0].finish_date)
|
||||
|
||||
def test_read_reads(self):
|
||||
actual = models.ImportItem.objects.get(index=2)
|
||||
self.assertEqual(actual.reads[0].start_date, datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))
|
||||
self.assertEqual(actual.reads[0].finish_date, datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc))
|
||||
''' infer read dates where available '''
|
||||
actual = self.item_2
|
||||
self.assertEqual(
|
||||
actual.reads[0].start_date,
|
||||
datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))
|
||||
self.assertEqual(
|
||||
actual.reads[0].finish_date,
|
||||
datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc))
|
||||
|
||||
def test_unread_reads(self):
|
||||
''' handle books with no read dates '''
|
||||
expected = []
|
||||
actual = models.ImportItem.objects.get(index=3)
|
||||
self.assertEqual(actual.reads, expected)
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_get_book_from_isbn(self):
|
||||
''' search and load books by isbn (9780356506999) '''
|
||||
connector_info = models.Connector.objects.create(
|
||||
identifier='openlibrary.org',
|
||||
name='OpenLibrary',
|
||||
connector_file='openlibrary',
|
||||
base_url='https://openlibrary.org',
|
||||
books_url='https://openlibrary.org',
|
||||
covers_url='https://covers.openlibrary.org',
|
||||
search_url='https://openlibrary.org/search?q=',
|
||||
priority=3,
|
||||
)
|
||||
connector = connector_manager.load_connector(connector_info)
|
||||
result = SearchResult(
|
||||
title='Test Result',
|
||||
key='https://openlibrary.org/works/OL1234W',
|
||||
author='An Author',
|
||||
year='1980',
|
||||
connector=connector,
|
||||
)
|
||||
|
||||
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'../data/ol_edition.json')
|
||||
bookdata = json.loads(datafile.read_bytes())
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/works/OL1234W',
|
||||
json=bookdata,
|
||||
status=200)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/works/OL15832982W',
|
||||
json=bookdata,
|
||||
status=200)
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/authors/OL382982A',
|
||||
json={'name': 'test author'},
|
||||
status=200)
|
||||
|
||||
with patch(
|
||||
'bookwyrm.connectors.abstract_connector.load_more_data.delay'):
|
||||
with patch(
|
||||
'bookwyrm.connectors.connector_manager.first_search_result'
|
||||
) as search:
|
||||
search.return_value = result
|
||||
book = self.item_1.get_book_from_isbn()
|
||||
|
||||
self.assertEqual(book.title, 'Sabriel')
|
||||
|
104
bookwyrm/tests/test_goodreads_import.py
Normal file
104
bookwyrm/tests/test_goodreads_import.py
Normal file
@ -0,0 +1,104 @@
|
||||
''' testing import '''
|
||||
from collections import namedtuple
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.test import TestCase
|
||||
import responses
|
||||
|
||||
from bookwyrm import goodreads_import, models
|
||||
from bookwyrm.settings import DOMAIN
|
||||
|
||||
class GoodreadsImport(TestCase):
|
||||
''' importing from goodreads csv '''
|
||||
def setUp(self):
|
||||
''' use a test csv '''
|
||||
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||
'data/goodreads.csv')
|
||||
self.csv = open(datafile, 'r')
|
||||
self.user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'password', local=True)
|
||||
|
||||
models.Connector.objects.create(
|
||||
identifier=DOMAIN,
|
||||
name='Local',
|
||||
local=True,
|
||||
connector_file='self_connector',
|
||||
base_url='https://%s' % DOMAIN,
|
||||
books_url='https://%s/book' % DOMAIN,
|
||||
covers_url='https://%s/images/covers' % DOMAIN,
|
||||
search_url='https://%s/search?q=' % DOMAIN,
|
||||
priority=1,
|
||||
)
|
||||
|
||||
|
||||
def test_create_job(self):
|
||||
''' creates the import job entry and checks csv '''
|
||||
import_job = goodreads_import.create_job(
|
||||
self.user, self.csv, False, 'public')
|
||||
self.assertEqual(import_job.user, self.user)
|
||||
self.assertEqual(import_job.include_reviews, False)
|
||||
self.assertEqual(import_job.privacy, 'public')
|
||||
|
||||
import_items = models.ImportItem.objects.filter(job=import_job).all()
|
||||
self.assertEqual(len(import_items), 3)
|
||||
self.assertEqual(import_items[0].index, 0)
|
||||
self.assertEqual(import_items[0].data['Book Id'], '42036538')
|
||||
self.assertEqual(import_items[1].index, 1)
|
||||
self.assertEqual(import_items[1].data['Book Id'], '52691223')
|
||||
self.assertEqual(import_items[2].index, 2)
|
||||
self.assertEqual(import_items[2].data['Book Id'], '28694510')
|
||||
|
||||
|
||||
def test_create_retry_job(self):
|
||||
''' trying again with items that didn't import '''
|
||||
import_job = goodreads_import.create_job(
|
||||
self.user, self.csv, False, 'unlisted')
|
||||
import_items = models.ImportItem.objects.filter(
|
||||
job=import_job
|
||||
).all()[:2]
|
||||
|
||||
retry = goodreads_import.create_retry_job(
|
||||
self.user, import_job, import_items)
|
||||
self.assertNotEqual(import_job, retry)
|
||||
self.assertEqual(retry.user, self.user)
|
||||
self.assertEqual(retry.include_reviews, False)
|
||||
self.assertEqual(retry.privacy, 'unlisted')
|
||||
|
||||
retry_items = models.ImportItem.objects.filter(job=retry).all()
|
||||
self.assertEqual(len(retry_items), 2)
|
||||
self.assertEqual(retry_items[0].index, 0)
|
||||
self.assertEqual(retry_items[0].data['Book Id'], '42036538')
|
||||
self.assertEqual(retry_items[1].index, 1)
|
||||
self.assertEqual(retry_items[1].data['Book Id'], '52691223')
|
||||
|
||||
|
||||
def test_start_import(self):
|
||||
''' begin loading books '''
|
||||
import_job = goodreads_import.create_job(
|
||||
self.user, self.csv, False, 'unlisted')
|
||||
MockTask = namedtuple('Task', ('id'))
|
||||
mock_task = MockTask(7)
|
||||
with patch('bookwyrm.goodreads_import.import_data.delay') as start:
|
||||
start.return_value = mock_task
|
||||
goodreads_import.start_import(import_job)
|
||||
import_job.refresh_from_db()
|
||||
self.assertEqual(import_job.task_id, '7')
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_import_data(self):
|
||||
''' resolve entry '''
|
||||
import_job = goodreads_import.create_job(
|
||||
self.user, self.csv, False, 'unlisted')
|
||||
book = models.Edition.objects.create(title='Test Book')
|
||||
|
||||
with patch(
|
||||
'bookwyrm.models.import_job.ImportItem.get_book_from_isbn'
|
||||
) as resolve:
|
||||
resolve.return_value = book
|
||||
with patch('bookwyrm.outgoing.handle_imported_book'):
|
||||
goodreads_import.import_data(import_job.id)
|
||||
|
||||
import_item = models.ImportItem.objects.get(job=import_job, index=0)
|
||||
self.assertEqual(import_item.book.id, book.id)
|
@ -273,6 +273,12 @@ class Incoming(TestCase):
|
||||
incoming.handle_create(activity)
|
||||
self.assertEqual(models.Status.objects.count(), 2)
|
||||
|
||||
def test_handle_create_unknown_type(self):
|
||||
''' folks send you all kinds of things '''
|
||||
activity = {'object': {'id': 'hi'}, 'type': 'Fish'}
|
||||
result = incoming.handle_create(activity)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_handle_create_remote_note_with_mention(self):
|
||||
''' should only create it under the right circumstances '''
|
||||
self.assertEqual(models.Status.objects.count(), 1)
|
||||
|
@ -1,19 +1,24 @@
|
||||
''' sending out activities '''
|
||||
import csv
|
||||
import json
|
||||
import pathlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.http import JsonResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
import responses
|
||||
|
||||
from bookwyrm import models, outgoing
|
||||
from bookwyrm import forms, models, outgoing
|
||||
from bookwyrm.settings import DOMAIN
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods
|
||||
class Outgoing(TestCase):
|
||||
''' sends out activities '''
|
||||
def setUp(self):
|
||||
''' we'll need some data '''
|
||||
self.factory = RequestFactory()
|
||||
with patch('bookwyrm.models.user.set_remote_server'):
|
||||
self.remote_user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'ratword',
|
||||
@ -47,6 +52,67 @@ class Outgoing(TestCase):
|
||||
)
|
||||
|
||||
|
||||
def test_outbox(self):
|
||||
''' returns user's statuses '''
|
||||
request = self.factory.get('')
|
||||
result = outgoing.outbox(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
|
||||
def test_outbox_bad_method(self):
|
||||
''' can't POST to outbox '''
|
||||
request = self.factory.post('')
|
||||
result = outgoing.outbox(request, 'mouse')
|
||||
self.assertEqual(result.status_code, 405)
|
||||
|
||||
def test_outbox_unknown_user(self):
|
||||
''' should 404 for unknown and remote users '''
|
||||
request = self.factory.post('')
|
||||
result = outgoing.outbox(request, 'beepboop')
|
||||
self.assertEqual(result.status_code, 405)
|
||||
result = outgoing.outbox(request, 'rat')
|
||||
self.assertEqual(result.status_code, 405)
|
||||
|
||||
def test_outbox_privacy(self):
|
||||
''' don't show dms et cetera in outbox '''
|
||||
models.Status.objects.create(
|
||||
content='PRIVATE!!', user=self.local_user, privacy='direct')
|
||||
models.Status.objects.create(
|
||||
content='bffs ONLY', user=self.local_user, privacy='followers')
|
||||
models.Status.objects.create(
|
||||
content='unlisted status', user=self.local_user, privacy='unlisted')
|
||||
models.Status.objects.create(
|
||||
content='look at this', user=self.local_user, privacy='public')
|
||||
|
||||
request = self.factory.get('')
|
||||
result = outgoing.outbox(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
data = json.loads(result.content)
|
||||
self.assertEqual(data['type'], 'OrderedCollection')
|
||||
self.assertEqual(data['totalItems'], 2)
|
||||
|
||||
def test_outbox_filter(self):
|
||||
''' if we only care about reviews, only get reviews '''
|
||||
models.Review.objects.create(
|
||||
content='look at this', name='hi', rating=1,
|
||||
book=self.book, user=self.local_user)
|
||||
models.Status.objects.create(
|
||||
content='look at this', user=self.local_user)
|
||||
|
||||
request = self.factory.get('', {'type': 'bleh'})
|
||||
result = outgoing.outbox(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
data = json.loads(result.content)
|
||||
self.assertEqual(data['type'], 'OrderedCollection')
|
||||
self.assertEqual(data['totalItems'], 2)
|
||||
|
||||
request = self.factory.get('', {'type': 'Review'})
|
||||
result = outgoing.outbox(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
data = json.loads(result.content)
|
||||
self.assertEqual(data['type'], 'OrderedCollection')
|
||||
self.assertEqual(data['totalItems'], 1)
|
||||
|
||||
|
||||
def test_handle_follow(self):
|
||||
''' send a follow request '''
|
||||
self.assertEqual(models.UserFollowRequest.objects.count(), 0)
|
||||
@ -192,3 +258,190 @@ class Outgoing(TestCase):
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_unshelve(self.local_user, self.book, self.shelf)
|
||||
self.assertEqual(self.shelf.books.count(), 0)
|
||||
|
||||
|
||||
def test_handle_imported_book(self):
|
||||
''' goodreads import added a book, this adds related connections '''
|
||||
shelf = self.local_user.shelf_set.filter(identifier='read').first()
|
||||
self.assertIsNone(shelf.books.first())
|
||||
|
||||
import_job = models.ImportJob.objects.create(user=self.local_user)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath('data/goodreads.csv')
|
||||
csv_file = open(datafile, 'r')
|
||||
for index, entry in enumerate(list(csv.DictReader(csv_file))):
|
||||
import_item = models.ImportItem.objects.create(
|
||||
job_id=import_job.id, index=index, data=entry, book=self.book)
|
||||
break
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_imported_book(
|
||||
self.local_user, import_item, False, 'public')
|
||||
|
||||
shelf.refresh_from_db()
|
||||
self.assertEqual(shelf.books.first(), self.book)
|
||||
|
||||
readthrough = models.ReadThrough.objects.get(user=self.local_user)
|
||||
self.assertEqual(readthrough.book, self.book)
|
||||
# I can't remember how to create dates and I don't want to look it up.
|
||||
self.assertEqual(readthrough.start_date.year, 2020)
|
||||
self.assertEqual(readthrough.start_date.month, 10)
|
||||
self.assertEqual(readthrough.start_date.day, 21)
|
||||
self.assertEqual(readthrough.finish_date.year, 2020)
|
||||
self.assertEqual(readthrough.finish_date.month, 10)
|
||||
self.assertEqual(readthrough.finish_date.day, 25)
|
||||
|
||||
|
||||
def test_handle_imported_book_already_shelved(self):
|
||||
''' goodreads import added a book, this adds related connections '''
|
||||
shelf = self.local_user.shelf_set.filter(identifier='to-read').first()
|
||||
models.ShelfBook.objects.create(
|
||||
shelf=shelf, added_by=self.local_user, book=self.book)
|
||||
|
||||
import_job = models.ImportJob.objects.create(user=self.local_user)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath('data/goodreads.csv')
|
||||
csv_file = open(datafile, 'r')
|
||||
for index, entry in enumerate(list(csv.DictReader(csv_file))):
|
||||
import_item = models.ImportItem.objects.create(
|
||||
job_id=import_job.id, index=index, data=entry, book=self.book)
|
||||
break
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_imported_book(
|
||||
self.local_user, import_item, False, 'public')
|
||||
|
||||
shelf.refresh_from_db()
|
||||
self.assertEqual(shelf.books.first(), self.book)
|
||||
self.assertIsNone(
|
||||
self.local_user.shelf_set.get(identifier='read').books.first())
|
||||
readthrough = models.ReadThrough.objects.get(user=self.local_user)
|
||||
self.assertEqual(readthrough.book, self.book)
|
||||
self.assertEqual(readthrough.start_date.year, 2020)
|
||||
self.assertEqual(readthrough.start_date.month, 10)
|
||||
self.assertEqual(readthrough.start_date.day, 21)
|
||||
self.assertEqual(readthrough.finish_date.year, 2020)
|
||||
self.assertEqual(readthrough.finish_date.month, 10)
|
||||
self.assertEqual(readthrough.finish_date.day, 25)
|
||||
|
||||
|
||||
def test_handle_imported_book_review(self):
|
||||
''' goodreads review import '''
|
||||
import_job = models.ImportJob.objects.create(user=self.local_user)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath('data/goodreads.csv')
|
||||
csv_file = open(datafile, 'r')
|
||||
entry = list(csv.DictReader(csv_file))[2]
|
||||
import_item = models.ImportItem.objects.create(
|
||||
job_id=import_job.id, index=0, data=entry, book=self.book)
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_imported_book(
|
||||
self.local_user, import_item, True, 'unlisted')
|
||||
review = models.Review.objects.get(book=self.book, user=self.local_user)
|
||||
self.assertEqual(review.content, 'mixed feelings')
|
||||
self.assertEqual(review.rating, 2)
|
||||
self.assertEqual(review.published_date.year, 2019)
|
||||
self.assertEqual(review.published_date.month, 7)
|
||||
self.assertEqual(review.published_date.day, 8)
|
||||
self.assertEqual(review.privacy, 'unlisted')
|
||||
|
||||
|
||||
def test_handle_imported_book_reviews_disabled(self):
|
||||
''' goodreads review import '''
|
||||
import_job = models.ImportJob.objects.create(user=self.local_user)
|
||||
datafile = pathlib.Path(__file__).parent.joinpath('data/goodreads.csv')
|
||||
csv_file = open(datafile, 'r')
|
||||
entry = list(csv.DictReader(csv_file))[2]
|
||||
import_item = models.ImportItem.objects.create(
|
||||
job_id=import_job.id, index=0, data=entry, book=self.book)
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_imported_book(
|
||||
self.local_user, import_item, False, 'unlisted')
|
||||
self.assertFalse(models.Review.objects.filter(
|
||||
book=self.book, user=self.local_user
|
||||
).exists())
|
||||
|
||||
|
||||
def test_handle_status(self):
|
||||
''' create a status '''
|
||||
form = forms.CommentForm({
|
||||
'content': 'hi',
|
||||
'user': self.local_user.id,
|
||||
'book': self.book.id,
|
||||
'privacy': 'public',
|
||||
})
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_status(self.local_user, form)
|
||||
status = models.Comment.objects.get()
|
||||
self.assertEqual(status.content, '<p>hi</p>')
|
||||
self.assertEqual(status.user, self.local_user)
|
||||
self.assertEqual(status.book, self.book)
|
||||
|
||||
def test_handle_status_reply(self):
|
||||
''' create a status in reply to an existing status '''
|
||||
user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'password', local=True)
|
||||
parent = models.Status.objects.create(
|
||||
content='parent status', user=self.local_user)
|
||||
form = forms.ReplyForm({
|
||||
'content': 'hi',
|
||||
'user': user.id,
|
||||
'reply_parent': parent.id,
|
||||
'privacy': 'public',
|
||||
})
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_status(user, form)
|
||||
status = models.Status.objects.get(user=user)
|
||||
self.assertEqual(status.content, '<p>hi</p>')
|
||||
self.assertEqual(status.user, user)
|
||||
self.assertEqual(
|
||||
models.Notification.objects.get().user, self.local_user)
|
||||
|
||||
def test_handle_status_mentions(self):
|
||||
''' @mention a user in a post '''
|
||||
user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'password', local=True)
|
||||
form = forms.CommentForm({
|
||||
'content': 'hi @rat',
|
||||
'user': self.local_user.id,
|
||||
'book': self.book.id,
|
||||
'privacy': 'public',
|
||||
})
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_status(self.local_user, form)
|
||||
status = models.Status.objects.get()
|
||||
self.assertEqual(
|
||||
status.content,
|
||||
'<p>hi <a href="%s">@rat</a></p>' % user.remote_id)
|
||||
self.assertEqual(list(status.mention_users.all()), [user])
|
||||
self.assertEqual(models.Notification.objects.get().user, user)
|
||||
|
||||
def test_handle_status_reply_with_mentions(self):
|
||||
''' reply to a post with an @mention'ed user '''
|
||||
user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'password', local=True)
|
||||
form = forms.CommentForm({
|
||||
'content': 'hi @rat@example.com',
|
||||
'user': self.local_user.id,
|
||||
'book': self.book.id,
|
||||
'privacy': 'public',
|
||||
})
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_status(self.local_user, form)
|
||||
status = models.Status.objects.get()
|
||||
|
||||
form = forms.ReplyForm({
|
||||
'content': 'right',
|
||||
'user': user,
|
||||
'privacy': 'public',
|
||||
'reply_parent': status.id
|
||||
})
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
outgoing.handle_status(user, form)
|
||||
|
||||
reply = models.Status.replies(status).first()
|
||||
self.assertEqual(reply.content, '<p>right</p>')
|
||||
self.assertEqual(reply.user, user)
|
||||
self.assertTrue(self.remote_user in reply.mention_users.all())
|
||||
self.assertTrue(self.local_user in reply.mention_users.all())
|
||||
|
@ -42,6 +42,9 @@ class ViewActions(TestCase):
|
||||
content='Test status',
|
||||
remote_id='https://example.com/status/1',
|
||||
)
|
||||
self.work = models.Work.objects.create(title='Test Work')
|
||||
self.book = models.Edition.objects.create(
|
||||
title='Test Book', parent_work=self.work)
|
||||
self.settings = models.SiteSettings.objects.create(id=1)
|
||||
self.factory = RequestFactory()
|
||||
|
||||
@ -352,3 +355,43 @@ class ViewActions(TestCase):
|
||||
author.refresh_from_db()
|
||||
self.assertEqual(author.name, 'Test Author')
|
||||
self.assertEqual(resp.template_name, 'edit_author.html')
|
||||
|
||||
|
||||
def test_tag(self):
|
||||
''' add a tag to a book '''
|
||||
request = self.factory.post(
|
||||
'', {
|
||||
'name': 'A Tag!?',
|
||||
'book': self.book.id,
|
||||
})
|
||||
request.user = self.local_user
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
actions.tag(request)
|
||||
|
||||
tag = models.Tag.objects.get()
|
||||
user_tag = models.UserTag.objects.get()
|
||||
self.assertEqual(tag.name, 'A Tag!?')
|
||||
self.assertEqual(tag.identifier, 'A+Tag%21%3F')
|
||||
self.assertEqual(user_tag.user, self.local_user)
|
||||
self.assertEqual(user_tag.book, self.book)
|
||||
|
||||
|
||||
def test_untag(self):
|
||||
''' remove a tag from a book '''
|
||||
tag = models.Tag.objects.create(name='A Tag!?')
|
||||
user_tag = models.UserTag.objects.create(
|
||||
user=self.local_user, book=self.book, tag=tag)
|
||||
request = self.factory.post(
|
||||
'', {
|
||||
'user': self.local_user.id,
|
||||
'book': self.book.id,
|
||||
'name': tag.name,
|
||||
})
|
||||
request.user = self.local_user
|
||||
|
||||
with patch('bookwyrm.broadcast.broadcast_task.delay'):
|
||||
actions.untag(request)
|
||||
|
||||
self.assertTrue(models.Tag.objects.filter(name='A Tag!?').exists())
|
||||
self.assertFalse(models.UserTag.objects.exists())
|
||||
|
567
bookwyrm/tests/test_views.py
Normal file
567
bookwyrm/tests/test_views.py
Normal file
@ -0,0 +1,567 @@
|
||||
''' test for app action functionality '''
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http import JsonResponse
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from bookwyrm import models, views
|
||||
from bookwyrm.connectors import abstract_connector
|
||||
from bookwyrm.settings import DOMAIN, USER_AGENT
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods
|
||||
class Views(TestCase):
|
||||
''' every response to a get request, html or json '''
|
||||
def setUp(self):
|
||||
''' we need basic test data and mocks '''
|
||||
self.factory = RequestFactory()
|
||||
self.work = models.Work.objects.create(title='Test Work')
|
||||
self.book = models.Edition.objects.create(
|
||||
title='Test Book', parent_work=self.work)
|
||||
models.Connector.objects.create(
|
||||
identifier='self',
|
||||
connector_file='self_connector',
|
||||
local=True
|
||||
)
|
||||
self.local_user = models.User.objects.create_user(
|
||||
'mouse', 'mouse@mouse.mouse', 'password', local=True)
|
||||
with patch('bookwyrm.models.user.set_remote_server.delay'):
|
||||
self.remote_user = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.com', 'ratword',
|
||||
local=False,
|
||||
remote_id='https://example.com/users/rat',
|
||||
inbox='https://example.com/users/rat/inbox',
|
||||
outbox='https://example.com/users/rat/outbox',
|
||||
)
|
||||
|
||||
|
||||
def test_get_edition(self):
|
||||
''' given an edition or a work, returns an edition '''
|
||||
self.assertEqual(
|
||||
views.get_edition(self.book.id), self.book)
|
||||
self.assertEqual(
|
||||
views.get_edition(self.work.id), self.book)
|
||||
|
||||
|
||||
def test_get_user_from_username(self):
|
||||
''' works for either localname or username '''
|
||||
self.assertEqual(
|
||||
views.get_user_from_username('mouse'), self.local_user)
|
||||
self.assertEqual(
|
||||
views.get_user_from_username('mouse@%s' % DOMAIN), self.local_user)
|
||||
with self.assertRaises(models.User.DoesNotExist):
|
||||
views.get_user_from_username('mojfse@example.com')
|
||||
|
||||
|
||||
def test_is_api_request(self):
|
||||
''' should it return html or json '''
|
||||
request = self.factory.get('/path')
|
||||
request.headers = {'Accept': 'application/json'}
|
||||
self.assertTrue(views.is_api_request(request))
|
||||
|
||||
request = self.factory.get('/path.json')
|
||||
request.headers = {'Accept': 'Praise'}
|
||||
self.assertTrue(views.is_api_request(request))
|
||||
|
||||
request = self.factory.get('/path')
|
||||
request.headers = {'Accept': 'Praise'}
|
||||
self.assertFalse(views.is_api_request(request))
|
||||
|
||||
|
||||
def test_home_tab(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.home_tab(request, 'local')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'feed.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_direct_messages_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.direct_messages_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'direct_messages.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_get_activity_feed(self):
|
||||
''' loads statuses '''
|
||||
rat = models.User.objects.create_user(
|
||||
'rat', 'rat@rat.rat', 'password', local=True)
|
||||
|
||||
public_status = models.Comment.objects.create(
|
||||
content='public status', book=self.book, user=self.local_user)
|
||||
direct_status = models.Status.objects.create(
|
||||
content='direct', user=self.local_user, privacy='direct')
|
||||
|
||||
rat_public = models.Status.objects.create(
|
||||
content='blah blah', user=rat)
|
||||
rat_unlisted = models.Status.objects.create(
|
||||
content='blah blah', user=rat, privacy='unlisted')
|
||||
remote_status = models.Status.objects.create(
|
||||
content='blah blah', user=self.remote_user)
|
||||
followers_status = models.Status.objects.create(
|
||||
content='blah', user=rat, privacy='followers')
|
||||
rat_mention = models.Status.objects.create(
|
||||
content='blah blah blah', user=rat, privacy='followers')
|
||||
rat_mention.mention_users.set([self.local_user])
|
||||
|
||||
statuses = views.get_activity_feed(self.local_user, 'home')
|
||||
self.assertEqual(len(statuses), 2)
|
||||
self.assertEqual(statuses[1], public_status)
|
||||
self.assertEqual(statuses[0], rat_mention)
|
||||
|
||||
statuses = views.get_activity_feed(
|
||||
self.local_user, 'home', model=models.Comment)
|
||||
self.assertEqual(len(statuses), 1)
|
||||
self.assertEqual(statuses[0], public_status)
|
||||
|
||||
statuses = views.get_activity_feed(self.local_user, 'local')
|
||||
self.assertEqual(len(statuses), 2)
|
||||
self.assertEqual(statuses[1], public_status)
|
||||
self.assertEqual(statuses[0], rat_public)
|
||||
|
||||
statuses = views.get_activity_feed(self.local_user, 'direct')
|
||||
self.assertEqual(len(statuses), 1)
|
||||
self.assertEqual(statuses[0], direct_status)
|
||||
|
||||
statuses = views.get_activity_feed(self.local_user, 'federated')
|
||||
self.assertEqual(len(statuses), 3)
|
||||
self.assertEqual(statuses[2], public_status)
|
||||
self.assertEqual(statuses[1], rat_public)
|
||||
self.assertEqual(statuses[0], remote_status)
|
||||
|
||||
statuses = views.get_activity_feed(self.local_user, 'friends')
|
||||
self.assertEqual(len(statuses), 2)
|
||||
self.assertEqual(statuses[1], public_status)
|
||||
self.assertEqual(statuses[0], rat_mention)
|
||||
|
||||
rat.followers.add(self.local_user)
|
||||
statuses = views.get_activity_feed(self.local_user, 'friends')
|
||||
self.assertEqual(len(statuses), 5)
|
||||
self.assertEqual(statuses[4], public_status)
|
||||
self.assertEqual(statuses[3], rat_public)
|
||||
self.assertEqual(statuses[2], rat_unlisted)
|
||||
self.assertEqual(statuses[1], followers_status)
|
||||
self.assertEqual(statuses[0], rat_mention)
|
||||
|
||||
|
||||
def test_search_json_response(self):
|
||||
''' searches local data only and returns book data in json format '''
|
||||
# we need a connector for this, sorry
|
||||
request = self.factory.get('', {'q': 'Test Book'})
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
response = views.search(request)
|
||||
self.assertIsInstance(response, JsonResponse)
|
||||
|
||||
data = json.loads(response.content)
|
||||
self.assertEqual(len(data), 1)
|
||||
self.assertEqual(data[0]['title'], 'Test Book')
|
||||
self.assertEqual(
|
||||
data[0]['key'], 'https://%s/book/%d' % (DOMAIN, self.book.id))
|
||||
|
||||
|
||||
def test_search_html_response(self):
|
||||
''' searches remote connectors '''
|
||||
class TestConnector(abstract_connector.AbstractMinimalConnector):
|
||||
''' nothing added here '''
|
||||
def format_search_result(self, search_result):
|
||||
pass
|
||||
def get_or_create_book(self, remote_id):
|
||||
pass
|
||||
def parse_search_data(self, data):
|
||||
pass
|
||||
models.Connector.objects.create(
|
||||
identifier='example.com',
|
||||
connector_file='openlibrary',
|
||||
base_url='https://example.com',
|
||||
books_url='https://example.com/books',
|
||||
covers_url='https://example.com/covers',
|
||||
search_url='https://example.com/search?q=',
|
||||
)
|
||||
connector = TestConnector('example.com')
|
||||
|
||||
search_result = abstract_connector.SearchResult(
|
||||
key='http://www.example.com/book/1',
|
||||
title='Gideon the Ninth',
|
||||
author='Tamsyn Muir',
|
||||
year='2019',
|
||||
connector=connector
|
||||
)
|
||||
|
||||
request = self.factory.get('', {'q': 'Test Book'})
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
with patch(
|
||||
'bookwyrm.connectors.connector_manager.search') as manager:
|
||||
manager.return_value = [search_result]
|
||||
response = views.search(request)
|
||||
self.assertIsInstance(response, TemplateResponse)
|
||||
self.assertEqual(response.template_name, 'search_results.html')
|
||||
self.assertEqual(
|
||||
response.context_data['book_results'][0].title, 'Gideon the Ninth')
|
||||
|
||||
|
||||
def test_search_html_response_users(self):
|
||||
''' searches remote connectors '''
|
||||
request = self.factory.get('', {'q': 'mouse'})
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
with patch('bookwyrm.connectors.connector_manager.search'):
|
||||
response = views.search(request)
|
||||
self.assertIsInstance(response, TemplateResponse)
|
||||
self.assertEqual(response.template_name, 'search_results.html')
|
||||
self.assertEqual(
|
||||
response.context_data['user_results'][0], self.local_user)
|
||||
|
||||
|
||||
def test_import_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.import_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'import.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_import_status(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
import_job = models.ImportJob.objects.create(user=self.local_user)
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.tasks.app.AsyncResult') as async_result:
|
||||
async_result.return_value = []
|
||||
result = views.import_status(request, import_job.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'import_status.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_login_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = AnonymousUser
|
||||
result = views.login_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'login.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
request.user = self.local_user
|
||||
result = views.login_page(request)
|
||||
self.assertEqual(result.url, '/')
|
||||
self.assertEqual(result.status_code, 302)
|
||||
|
||||
|
||||
def test_about_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.about_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'about.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_password_reset_request(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.password_reset_request(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'password_reset_request.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_password_reset(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
code = models.PasswordReset.objects.create(user=self.local_user)
|
||||
request = self.factory.get('')
|
||||
request.user = AnonymousUser
|
||||
result = views.password_reset(request, code.code)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'password_reset.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_invite_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
models.SiteInvite.objects.create(code='hi', user=self.local_user)
|
||||
request = self.factory.get('')
|
||||
request.user = AnonymousUser
|
||||
# why?? this is annoying.
|
||||
request.user.is_authenticated = False
|
||||
with patch('bookwyrm.models.site.SiteInvite.valid') as invite:
|
||||
invite.return_value = True
|
||||
result = views.invite_page(request, 'hi')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'invite.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_manage_invites(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
request.user.is_superuser = True
|
||||
result = views.manage_invites(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'manage_invites.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_notifications_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.notifications_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'notifications.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_user_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.user_page(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'user.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.user_page(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_followers_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.followers_page(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'followers.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.followers_page(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_following_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.following_page(request, 'mouse')
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'following.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.following_page(request, 'mouse')
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_status_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
status = models.Status.objects.create(
|
||||
content='hi', user=self.local_user)
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.status_page(request, 'mouse', status.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'status.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.status_page(request, 'mouse', status.id)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_replies_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
status = models.Status.objects.create(
|
||||
content='hi', user=self.local_user)
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.replies_page(request, 'mouse', status.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'status.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.replies_page(request, 'mouse', status.id)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_edit_profile_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
result = views.edit_profile_page(request)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'edit_user.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_book_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.book_page(request, self.book.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'book.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.book_page(request, self.book.id)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_edit_book_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
request.user.is_superuser = True
|
||||
result = views.edit_book_page(request, self.book.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'edit_book.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_edit_author_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
author = models.Author.objects.create(name='Test Author')
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
request.user.is_superuser = True
|
||||
result = views.edit_author_page(request, author.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'edit_author.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_editions_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.editions_page(request, self.work.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'editions.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.editions_page(request, self.work.id)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_author_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
author = models.Author.objects.create(name='Jessica')
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.author_page(request, author.id)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'author.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.author_page(request, author.id)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_tag_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
tag = models.Tag.objects.create(name='hi there')
|
||||
models.UserTag.objects.create(
|
||||
tag=tag, user=self.local_user, book=self.book)
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.tag_page(request, tag.identifier)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'tag.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
request = self.factory.get('')
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.tag_page(request, tag.identifier)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_shelf_page(self):
|
||||
''' there are so many views, this just makes sure it LOADS '''
|
||||
shelf = self.local_user.shelf_set.first()
|
||||
request = self.factory.get('')
|
||||
request.user = self.local_user
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = False
|
||||
result = views.shelf_page(
|
||||
request, self.local_user.username, shelf.identifier)
|
||||
self.assertIsInstance(result, TemplateResponse)
|
||||
self.assertEqual(result.template_name, 'shelf.html')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
with patch('bookwyrm.views.is_api_request') as is_api:
|
||||
is_api.return_value = True
|
||||
result = views.shelf_page(
|
||||
request, self.local_user.username, shelf.identifier)
|
||||
self.assertIsInstance(result, JsonResponse)
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
def test_is_bookwyrm_request(self):
|
||||
''' tests the function that checks if a request came from a bookwyrm instance '''
|
||||
request = self.factory.get('', {'q': 'Test Book'})
|
||||
self.assertFalse(views.is_bookworm_request(request))
|
||||
|
||||
request = self.factory.get('', {'q': 'Test Book'},
|
||||
HTTP_USER_AGENT="http.rb/4.4.1 (Mastodon/3.3.0; +https://mastodon.social/)")
|
||||
self.assertFalse(views.is_bookworm_request(request))
|
||||
|
||||
request = self.factory.get('', {'q': 'Test Book'}, HTTP_USER_AGENT=USER_AGENT)
|
||||
self.assertTrue(views.is_bookworm_request(request))
|
Reference in New Issue
Block a user