diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml new file mode 100644 index 00000000..3ce368ec --- /dev/null +++ b/.github/workflows/django-tests.yml @@ -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 diff --git a/bookwyrm/tests/incoming/test_follow.py b/bookwyrm/tests/incoming/test_follow.py index 51ab3c43..50e47d88 100644 --- a/bookwyrm/tests/incoming/test_follow.py +++ b/bookwyrm/tests/incoming/test_follow.py @@ -1,3 +1,4 @@ +from unittest.mock import patch from django.test import TestCase from bookwyrm import models, incoming @@ -27,7 +28,8 @@ class IncomingFollow(TestCase): "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 = models.Notification.objects.get() @@ -55,7 +57,8 @@ class IncomingFollow(TestCase): self.local_user.manually_approves_followers = True self.local_user.save() - incoming.handle_follow(activity) + with patch('bookwyrm.broadcast.broadcast_task.delay') as _: + incoming.handle_follow(activity) # notification created notification = models.Notification.objects.get() @@ -81,7 +84,8 @@ class IncomingFollow(TestCase): "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 notifications = models.Notification.objects.all() diff --git a/bookwyrm/tests/models/test_user_model.py b/bookwyrm/tests/models/test_user_model.py index 203c558d..e82f91be 100644 --- a/bookwyrm/tests/models/test_user_model.py +++ b/bookwyrm/tests/models/test_user_model.py @@ -27,9 +27,13 @@ class User(TestCase): shelves = models.Shelf.objects.filter(user=self.user).all() self.assertEqual(len(shelves), 3) 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] - 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): diff --git a/bookwyrm/tests/outgoing/test_follow.py b/bookwyrm/tests/outgoing/test_follow.py index 82a476f6..89e677ab 100644 --- a/bookwyrm/tests/outgoing/test_follow.py +++ b/bookwyrm/tests/outgoing/test_follow.py @@ -1,3 +1,4 @@ +from unittest.mock import patch from django.test import TestCase from bookwyrm import models, outgoing @@ -22,7 +23,9 @@ class Following(TestCase): def test_handle_follow(self): 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() self.assertEqual(rel.user_subject, self.local_user) @@ -33,7 +36,8 @@ class Following(TestCase): def test_handle_unfollow(self): self.remote_user.followers.add(self.local_user) 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) @@ -45,7 +49,8 @@ class Following(TestCase): ) rel_id = rel.id - outgoing.handle_accept(rel) + with patch('bookwyrm.broadcast.broadcast_task.delay') as _: + outgoing.handle_accept(rel) # request should be deleted self.assertEqual( models.UserFollowRequest.objects.filter(id=rel_id).count(), 0 @@ -61,7 +66,8 @@ class Following(TestCase): ) rel_id = rel.id - outgoing.handle_reject(rel) + with patch('bookwyrm.broadcast.broadcast_task.delay') as _: + outgoing.handle_reject(rel) # request should be deleted self.assertEqual( models.UserFollowRequest.objects.filter(id=rel_id).count(), 0 diff --git a/bookwyrm/tests/outgoing/test_shelving.py b/bookwyrm/tests/outgoing/test_shelving.py index 0b85b671..5567784e 100644 --- a/bookwyrm/tests/outgoing/test_shelving.py +++ b/bookwyrm/tests/outgoing/test_shelving.py @@ -1,3 +1,4 @@ +from unittest.mock import patch from django.test import TestCase from bookwyrm import models, outgoing @@ -26,7 +27,8 @@ class Shelving(TestCase): 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 self.assertEqual(self.shelf.books.get(), self.book) @@ -34,7 +36,8 @@ class Shelving(TestCase): def test_handle_shelve_to_read(self): 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 self.assertEqual(shelf.books.get(), self.book) @@ -42,7 +45,8 @@ class Shelving(TestCase): def test_handle_shelve_reading(self): 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 self.assertEqual(shelf.books.get(), self.book) @@ -50,7 +54,8 @@ class Shelving(TestCase): def test_handle_shelve_read(self): 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 self.assertEqual(shelf.books.get(), self.book) @@ -59,5 +64,6 @@ class Shelving(TestCase): self.shelf.books.add(self.book) self.shelf.save() 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) diff --git a/bookwyrm/tests/test_signing.py b/bookwyrm/tests/test_signing.py index 5170b416..a5039306 100644 --- a/bookwyrm/tests/test_signing.py +++ b/bookwyrm/tests/test_signing.py @@ -2,6 +2,7 @@ import time from collections import namedtuple from urllib.parse import urlsplit import pathlib +from unittest.mock import patch import json import responses @@ -63,12 +64,14 @@ class Signature(TestCase): send_data=None, digest=None, date=None): + ''' sends a follow request to the "rat" user ''' now = date or http_date() data = json.dumps(get_follow_data(sender, self.rat)) digest = digest or make_digest(data) signature = make_signature( 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): response = self.send_test_request(sender=self.mouse) @@ -104,8 +107,9 @@ class Signature(TestCase): status=200 ) - response = self.send_test_request(sender=self.fake_remote) - self.assertEqual(response.status_code, 200) + with patch('bookwyrm.remote_user.get_remote_reviews.delay') as _: + response = self.send_test_request(sender=self.fake_remote) + self.assertEqual(response.status_code, 200) @responses.activate def test_key_needs_refresh(self): @@ -141,21 +145,22 @@ class Signature(TestCase): json=data, status=200) - # Key correct: - response = self.send_test_request(sender=self.fake_remote) - self.assertEqual(response.status_code, 200) + with patch('bookwyrm.remote_user.get_remote_reviews.delay') as _: + # Key correct: + response = self.send_test_request(sender=self.fake_remote) + self.assertEqual(response.status_code, 200) - # Old key is cached, so still works: - response = self.send_test_request(sender=self.fake_remote) - self.assertEqual(response.status_code, 200) + # Old key is cached, so still works: + response = self.send_test_request(sender=self.fake_remote) + self.assertEqual(response.status_code, 200) - # Try with new key: - response = self.send_test_request(sender=new_sender) - self.assertEqual(response.status_code, 200) + # Try with new key: + response = self.send_test_request(sender=new_sender) + self.assertEqual(response.status_code, 200) - # Now the old key will fail: - response = self.send_test_request(sender=self.fake_remote) - self.assertEqual(response.status_code, 401) + # Now the old key will fail: + response = self.send_test_request(sender=self.fake_remote) + self.assertEqual(response.status_code, 401) @responses.activate @@ -172,23 +177,26 @@ class Signature(TestCase): @pytest.mark.integration def test_changed_data(self): '''Message data must match the digest header.''' - response = self.send_test_request( - self.mouse, - send_data=get_follow_data(self.mouse, self.cat)) - self.assertEqual(response.status_code, 401) + with patch('bookwyrm.remote_user.fetch_user_data') as _: + response = self.send_test_request( + self.mouse, + send_data=get_follow_data(self.mouse, self.cat)) + self.assertEqual(response.status_code, 401) @pytest.mark.integration def test_invalid_digest(self): - response = self.send_test_request( - self.mouse, - digest='SHA-256=AAAAAAAAAAAAAAAAAA') - self.assertEqual(response.status_code, 401) + with patch('bookwyrm.remote_user.fetch_user_data') as _: + response = self.send_test_request( + self.mouse, + digest='SHA-256=AAAAAAAAAAAAAAAAAA') + self.assertEqual(response.status_code, 401) @pytest.mark.integration def test_old_message(self): '''Old messages should be rejected to prevent replay attacks.''' - response = self.send_test_request( - self.mouse, - date=http_date(time.time() - 301) - ) - self.assertEqual(response.status_code, 401) + with patch('bookwyrm.remote_user.fetch_user_data') as _: + response = self.send_test_request( + self.mouse, + date=http_date(time.time() - 301) + ) + self.assertEqual(response.status_code, 401) diff --git a/bw-dev b/bw-dev index 6d74924f..53c8e52d 100755 --- a/bw-dev +++ b/bw-dev @@ -61,7 +61,8 @@ case "$1" in ;; migrate) execweb python manage.py rename_app fedireads bookwyrm - execweb python manage.py "$@" + shift 1 + execweb python manage.py migrate "$@" ;; bash) execweb bash