forked from mirrors/bookwyrm
Merge pull request #367 from mouse-reeve/test-ci
Adds django test runner
This commit is contained in:
commit
0f851e15bb
7 changed files with 140 additions and 43 deletions
68
.github/workflows/django-tests.yml
vendored
Normal file
68
.github/workflows/django-tests.yml
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
name: Run Python Tests
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
max-parallel: 4
|
||||||
|
matrix:
|
||||||
|
db: [postgres]
|
||||||
|
python-version: [3.9]
|
||||||
|
include:
|
||||||
|
- db: postgres
|
||||||
|
db_port: 5432
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:10
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: hunter2
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
- name: Run Tests
|
||||||
|
env:
|
||||||
|
DB: ${{ matrix.db }}
|
||||||
|
DB_HOST: 127.0.0.1
|
||||||
|
DB_PORT: ${{ matrix.db_port }}
|
||||||
|
DB_PASSWORD: hunter2
|
||||||
|
SECRET_KEY: beepbeep
|
||||||
|
DEBUG: true
|
||||||
|
DOMAIN: your.domain.here
|
||||||
|
OL_URL: https://openlibrary.org
|
||||||
|
BOOKWYRM_DATABASE_BACKEND: postgres
|
||||||
|
MEDIA_ROOT: images/
|
||||||
|
POSTGRES_PASSWORD: hunter2
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_DB: github_actions
|
||||||
|
POSTGRES_HOST: 127.0.0.1
|
||||||
|
CELERY_BROKER: ""
|
||||||
|
CELERY_RESULT_BACKEND: ""
|
||||||
|
EMAIL_HOST: "smtp.mailgun.org"
|
||||||
|
EMAIL_PORT: 587
|
||||||
|
EMAIL_HOST_USER: ""
|
||||||
|
EMAIL_HOST_PASSWORD: ""
|
||||||
|
EMAIL_USE_TLS: true
|
||||||
|
run: |
|
||||||
|
python manage.py test
|
|
@ -1,3 +1,4 @@
|
||||||
|
from unittest.mock import patch
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from bookwyrm import models, incoming
|
from bookwyrm import models, incoming
|
||||||
|
@ -27,7 +28,8 @@ class IncomingFollow(TestCase):
|
||||||
"object": "http://local.com/user/mouse"
|
"object": "http://local.com/user/mouse"
|
||||||
}
|
}
|
||||||
|
|
||||||
incoming.handle_follow(activity)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
incoming.handle_follow(activity)
|
||||||
|
|
||||||
# notification created
|
# notification created
|
||||||
notification = models.Notification.objects.get()
|
notification = models.Notification.objects.get()
|
||||||
|
@ -55,7 +57,8 @@ class IncomingFollow(TestCase):
|
||||||
self.local_user.manually_approves_followers = True
|
self.local_user.manually_approves_followers = True
|
||||||
self.local_user.save()
|
self.local_user.save()
|
||||||
|
|
||||||
incoming.handle_follow(activity)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
incoming.handle_follow(activity)
|
||||||
|
|
||||||
# notification created
|
# notification created
|
||||||
notification = models.Notification.objects.get()
|
notification = models.Notification.objects.get()
|
||||||
|
@ -81,7 +84,8 @@ class IncomingFollow(TestCase):
|
||||||
"object": "http://local.com/user/nonexistent-user"
|
"object": "http://local.com/user/nonexistent-user"
|
||||||
}
|
}
|
||||||
|
|
||||||
incoming.handle_follow(activity)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
incoming.handle_follow(activity)
|
||||||
|
|
||||||
# do nothing
|
# do nothing
|
||||||
notifications = models.Notification.objects.all()
|
notifications = models.Notification.objects.all()
|
||||||
|
|
|
@ -27,9 +27,13 @@ class User(TestCase):
|
||||||
shelves = models.Shelf.objects.filter(user=self.user).all()
|
shelves = models.Shelf.objects.filter(user=self.user).all()
|
||||||
self.assertEqual(len(shelves), 3)
|
self.assertEqual(len(shelves), 3)
|
||||||
names = [s.name for s in shelves]
|
names = [s.name for s in shelves]
|
||||||
self.assertEqual(names, ['To Read', 'Currently Reading', 'Read'])
|
self.assertTrue('To Read' in names)
|
||||||
|
self.assertTrue('Currently Reading' in names)
|
||||||
|
self.assertTrue('Read' in names)
|
||||||
ids = [s.identifier for s in shelves]
|
ids = [s.identifier for s in shelves]
|
||||||
self.assertEqual(ids, ['to-read', 'reading', 'read'])
|
self.assertTrue('to-read' in ids)
|
||||||
|
self.assertTrue('reading' in ids)
|
||||||
|
self.assertTrue('read' in ids)
|
||||||
|
|
||||||
|
|
||||||
def test_activitypub_serialize(self):
|
def test_activitypub_serialize(self):
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from unittest.mock import patch
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from bookwyrm import models, outgoing
|
from bookwyrm import models, outgoing
|
||||||
|
@ -22,7 +23,9 @@ class Following(TestCase):
|
||||||
def test_handle_follow(self):
|
def test_handle_follow(self):
|
||||||
self.assertEqual(models.UserFollowRequest.objects.count(), 0)
|
self.assertEqual(models.UserFollowRequest.objects.count(), 0)
|
||||||
|
|
||||||
outgoing.handle_follow(self.local_user, self.remote_user)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_follow(self.local_user, self.remote_user)
|
||||||
|
|
||||||
rel = models.UserFollowRequest.objects.get()
|
rel = models.UserFollowRequest.objects.get()
|
||||||
|
|
||||||
self.assertEqual(rel.user_subject, self.local_user)
|
self.assertEqual(rel.user_subject, self.local_user)
|
||||||
|
@ -33,7 +36,8 @@ class Following(TestCase):
|
||||||
def test_handle_unfollow(self):
|
def test_handle_unfollow(self):
|
||||||
self.remote_user.followers.add(self.local_user)
|
self.remote_user.followers.add(self.local_user)
|
||||||
self.assertEqual(self.remote_user.followers.count(), 1)
|
self.assertEqual(self.remote_user.followers.count(), 1)
|
||||||
outgoing.handle_unfollow(self.local_user, self.remote_user)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_unfollow(self.local_user, self.remote_user)
|
||||||
|
|
||||||
self.assertEqual(self.remote_user.followers.count(), 0)
|
self.assertEqual(self.remote_user.followers.count(), 0)
|
||||||
|
|
||||||
|
@ -45,7 +49,8 @@ class Following(TestCase):
|
||||||
)
|
)
|
||||||
rel_id = rel.id
|
rel_id = rel.id
|
||||||
|
|
||||||
outgoing.handle_accept(rel)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_accept(rel)
|
||||||
# request should be deleted
|
# request should be deleted
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
models.UserFollowRequest.objects.filter(id=rel_id).count(), 0
|
models.UserFollowRequest.objects.filter(id=rel_id).count(), 0
|
||||||
|
@ -61,7 +66,8 @@ class Following(TestCase):
|
||||||
)
|
)
|
||||||
rel_id = rel.id
|
rel_id = rel.id
|
||||||
|
|
||||||
outgoing.handle_reject(rel)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_reject(rel)
|
||||||
# request should be deleted
|
# request should be deleted
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
models.UserFollowRequest.objects.filter(id=rel_id).count(), 0
|
models.UserFollowRequest.objects.filter(id=rel_id).count(), 0
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from unittest.mock import patch
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from bookwyrm import models, outgoing
|
from bookwyrm import models, outgoing
|
||||||
|
@ -26,7 +27,8 @@ class Shelving(TestCase):
|
||||||
|
|
||||||
|
|
||||||
def test_handle_shelve(self):
|
def test_handle_shelve(self):
|
||||||
outgoing.handle_shelve(self.user, self.book, self.shelf)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_shelve(self.user, self.book, self.shelf)
|
||||||
# make sure the book is on the shelf
|
# make sure the book is on the shelf
|
||||||
self.assertEqual(self.shelf.books.get(), self.book)
|
self.assertEqual(self.shelf.books.get(), self.book)
|
||||||
|
|
||||||
|
@ -34,7 +36,8 @@ class Shelving(TestCase):
|
||||||
def test_handle_shelve_to_read(self):
|
def test_handle_shelve_to_read(self):
|
||||||
shelf = models.Shelf.objects.get(identifier='to-read')
|
shelf = models.Shelf.objects.get(identifier='to-read')
|
||||||
|
|
||||||
outgoing.handle_shelve(self.user, self.book, shelf)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_shelve(self.user, self.book, shelf)
|
||||||
# make sure the book is on the shelf
|
# make sure the book is on the shelf
|
||||||
self.assertEqual(shelf.books.get(), self.book)
|
self.assertEqual(shelf.books.get(), self.book)
|
||||||
|
|
||||||
|
@ -42,7 +45,8 @@ class Shelving(TestCase):
|
||||||
def test_handle_shelve_reading(self):
|
def test_handle_shelve_reading(self):
|
||||||
shelf = models.Shelf.objects.get(identifier='reading')
|
shelf = models.Shelf.objects.get(identifier='reading')
|
||||||
|
|
||||||
outgoing.handle_shelve(self.user, self.book, shelf)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_shelve(self.user, self.book, shelf)
|
||||||
# make sure the book is on the shelf
|
# make sure the book is on the shelf
|
||||||
self.assertEqual(shelf.books.get(), self.book)
|
self.assertEqual(shelf.books.get(), self.book)
|
||||||
|
|
||||||
|
@ -50,7 +54,8 @@ class Shelving(TestCase):
|
||||||
def test_handle_shelve_read(self):
|
def test_handle_shelve_read(self):
|
||||||
shelf = models.Shelf.objects.get(identifier='read')
|
shelf = models.Shelf.objects.get(identifier='read')
|
||||||
|
|
||||||
outgoing.handle_shelve(self.user, self.book, shelf)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_shelve(self.user, self.book, shelf)
|
||||||
# make sure the book is on the shelf
|
# make sure the book is on the shelf
|
||||||
self.assertEqual(shelf.books.get(), self.book)
|
self.assertEqual(shelf.books.get(), self.book)
|
||||||
|
|
||||||
|
@ -59,5 +64,6 @@ class Shelving(TestCase):
|
||||||
self.shelf.books.add(self.book)
|
self.shelf.books.add(self.book)
|
||||||
self.shelf.save()
|
self.shelf.save()
|
||||||
self.assertEqual(self.shelf.books.count(), 1)
|
self.assertEqual(self.shelf.books.count(), 1)
|
||||||
outgoing.handle_unshelve(self.user, self.book, self.shelf)
|
with patch('bookwyrm.broadcast.broadcast_task.delay') as _:
|
||||||
|
outgoing.handle_unshelve(self.user, self.book, self.shelf)
|
||||||
self.assertEqual(self.shelf.books.count(), 0)
|
self.assertEqual(self.shelf.books.count(), 0)
|
||||||
|
|
|
@ -2,6 +2,7 @@ import time
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from urllib.parse import urlsplit
|
from urllib.parse import urlsplit
|
||||||
import pathlib
|
import pathlib
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import responses
|
import responses
|
||||||
|
@ -63,12 +64,14 @@ class Signature(TestCase):
|
||||||
send_data=None,
|
send_data=None,
|
||||||
digest=None,
|
digest=None,
|
||||||
date=None):
|
date=None):
|
||||||
|
''' sends a follow request to the "rat" user '''
|
||||||
now = date or http_date()
|
now = date or http_date()
|
||||||
data = json.dumps(get_follow_data(sender, self.rat))
|
data = json.dumps(get_follow_data(sender, self.rat))
|
||||||
digest = digest or make_digest(data)
|
digest = digest or make_digest(data)
|
||||||
signature = make_signature(
|
signature = make_signature(
|
||||||
signer or sender, self.rat.inbox, now, digest)
|
signer or sender, self.rat.inbox, now, digest)
|
||||||
return self.send(signature, now, send_data or data, digest)
|
with patch('bookwyrm.incoming.handle_follow.delay') as _:
|
||||||
|
return self.send(signature, now, send_data or data, digest)
|
||||||
|
|
||||||
def test_correct_signature(self):
|
def test_correct_signature(self):
|
||||||
response = self.send_test_request(sender=self.mouse)
|
response = self.send_test_request(sender=self.mouse)
|
||||||
|
@ -104,8 +107,9 @@ class Signature(TestCase):
|
||||||
status=200
|
status=200
|
||||||
)
|
)
|
||||||
|
|
||||||
response = self.send_test_request(sender=self.fake_remote)
|
with patch('bookwyrm.remote_user.get_remote_reviews.delay') as _:
|
||||||
self.assertEqual(response.status_code, 200)
|
response = self.send_test_request(sender=self.fake_remote)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
def test_key_needs_refresh(self):
|
def test_key_needs_refresh(self):
|
||||||
|
@ -141,21 +145,22 @@ class Signature(TestCase):
|
||||||
json=data,
|
json=data,
|
||||||
status=200)
|
status=200)
|
||||||
|
|
||||||
# Key correct:
|
with patch('bookwyrm.remote_user.get_remote_reviews.delay') as _:
|
||||||
response = self.send_test_request(sender=self.fake_remote)
|
# Key correct:
|
||||||
self.assertEqual(response.status_code, 200)
|
response = self.send_test_request(sender=self.fake_remote)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
# Old key is cached, so still works:
|
# Old key is cached, so still works:
|
||||||
response = self.send_test_request(sender=self.fake_remote)
|
response = self.send_test_request(sender=self.fake_remote)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
# Try with new key:
|
# Try with new key:
|
||||||
response = self.send_test_request(sender=new_sender)
|
response = self.send_test_request(sender=new_sender)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
# Now the old key will fail:
|
# Now the old key will fail:
|
||||||
response = self.send_test_request(sender=self.fake_remote)
|
response = self.send_test_request(sender=self.fake_remote)
|
||||||
self.assertEqual(response.status_code, 401)
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
|
|
||||||
@responses.activate
|
@responses.activate
|
||||||
|
@ -172,23 +177,26 @@ class Signature(TestCase):
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
def test_changed_data(self):
|
def test_changed_data(self):
|
||||||
'''Message data must match the digest header.'''
|
'''Message data must match the digest header.'''
|
||||||
response = self.send_test_request(
|
with patch('bookwyrm.remote_user.fetch_user_data') as _:
|
||||||
self.mouse,
|
response = self.send_test_request(
|
||||||
send_data=get_follow_data(self.mouse, self.cat))
|
self.mouse,
|
||||||
self.assertEqual(response.status_code, 401)
|
send_data=get_follow_data(self.mouse, self.cat))
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
def test_invalid_digest(self):
|
def test_invalid_digest(self):
|
||||||
response = self.send_test_request(
|
with patch('bookwyrm.remote_user.fetch_user_data') as _:
|
||||||
self.mouse,
|
response = self.send_test_request(
|
||||||
digest='SHA-256=AAAAAAAAAAAAAAAAAA')
|
self.mouse,
|
||||||
self.assertEqual(response.status_code, 401)
|
digest='SHA-256=AAAAAAAAAAAAAAAAAA')
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
def test_old_message(self):
|
def test_old_message(self):
|
||||||
'''Old messages should be rejected to prevent replay attacks.'''
|
'''Old messages should be rejected to prevent replay attacks.'''
|
||||||
response = self.send_test_request(
|
with patch('bookwyrm.remote_user.fetch_user_data') as _:
|
||||||
self.mouse,
|
response = self.send_test_request(
|
||||||
date=http_date(time.time() - 301)
|
self.mouse,
|
||||||
)
|
date=http_date(time.time() - 301)
|
||||||
self.assertEqual(response.status_code, 401)
|
)
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
3
bw-dev
3
bw-dev
|
@ -61,7 +61,8 @@ case "$1" in
|
||||||
;;
|
;;
|
||||||
migrate)
|
migrate)
|
||||||
execweb python manage.py rename_app fedireads bookwyrm
|
execweb python manage.py rename_app fedireads bookwyrm
|
||||||
execweb python manage.py "$@"
|
shift 1
|
||||||
|
execweb python manage.py migrate "$@"
|
||||||
;;
|
;;
|
||||||
bash)
|
bash)
|
||||||
execweb bash
|
execweb bash
|
||||||
|
|
Loading…
Reference in a new issue