diff --git a/.flake8 b/.flake8 index e8114cc..5fe961e 100644 --- a/.flake8 +++ b/.flake8 @@ -6,5 +6,5 @@ max-complexity = 18 select = B,C,E,F,W,T4,B9,Q0,N8,VNE exclude = **migrations + .venv venv - tests diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dba3fd4..dcc8f72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,5 @@ name: Test - on: pull_request: branches: @@ -9,8 +8,34 @@ on: jobs: test: runs-on: ubuntu-latest + environment: ".env" timeout-minutes: 15 + services: + postgres: + image: postgres:15 + env: + POSTGRES_DB: ${{ secrets.POSTGRES_DB }} + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + POSTGRES_HOST_AUTH_METHOD: "trust" + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + redis: + image: redis:7 + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - name: Checkout repository uses: actions/checkout@v3 @@ -31,5 +56,48 @@ jobs: - name: Run flake8 run: flake8 -# - name: Run unit tests -# run: python manage.py test + - name: Make migrations + env: + POSTGRES_HOST: 127.0.0.1 + POSTGRES_DB: ${{ secrets.POSTGRES_DB }} + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + POSTGRES_PORT: 5432 + SECRET_KEY: ${{ secrets.SECRET_KEY }} + run: | + python manage.py makemigrations users + python manage.py makemigrations library + python manage.py makemigrations payment + + - name: Run migrations + env: + POSTGRES_HOST: 127.0.0.1 + POSTGRES_DB: ${{ secrets.POSTGRES_DB }} + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + POSTGRES_PORT: 5432 + SECRET_KEY: ${{ secrets.SECRET_KEY }} + run: | + python manage.py migrate users + python manage.py migrate library + python manage.py migrate payment + python manage.py migrate + + + - name: Run unit tests + env: + POSTGRES_HOST: 127.0.0.1 + POSTGRES_DB: ${{ secrets.POSTGRES_DB }} + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + POSTGRES_PORT: 5432 + SECRET_KEY: ${{ secrets.SECRET_KEY }} + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} + REDIS_HOST: "127.0.0.1" + REDIS_PORT: "6379" + STRIPE_PUBLIC_KEY: ${{ secrets.STRIPE_PUBLIC_KEY }} + STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} + STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }} + + run: python manage.py test \ No newline at end of file diff --git a/config/asgi.py b/config/asgi.py index 50a54f1..856079b 100644 --- a/config/asgi.py +++ b/config/asgi.py @@ -1,12 +1,3 @@ -""" -ASGI config for config project. - -It exposes the ASGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/ -""" - import os from django.core.asgi import get_asgi_application diff --git a/config/wsgi.py b/config/wsgi.py index 190f99c..8509335 100644 --- a/config/wsgi.py +++ b/config/wsgi.py @@ -1,12 +1,3 @@ -""" -WSGI config for config project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/ -""" - import os from django.core.wsgi import get_wsgi_application diff --git a/fixtures/initial_data.json b/fixtures/initial_data.json index 1805b92..7c7e17e 100644 --- a/fixtures/initial_data.json +++ b/fixtures/initial_data.json @@ -3,7 +3,7 @@ "model": "users.user", "pk": 1, "fields": { - "password": "pbkdf2_sha256$1200000$osjeKfZEdWyzpUB6E4MOfD$/44JNiC4B3QkpY9lHmKtGIWDWd5Dt89fIxH/UK11fHI=", + "password": "pbkdf2_sha256$1200000$vBjfJ5vodjFb8FJturiV0J$rmsxK3EtJUsru6Duw2Ap0uXALUN5pt8x1DzxuhBzKuI=", "is_superuser": true, "email": "admin@test.com", "is_staff": true, @@ -17,7 +17,7 @@ "model": "users.user", "pk": 2, "fields": { - "password": "pbkdf2_sha256$1200000$P09N9FkNeCOqZAEWJhDwXX$mUuiQiKBSn1vjnr+wWGdoTH2gP0zzQjHtDQhEPc2Eb8=", + "password": "pbkdf2_sha256$1200000$vBjfJ5vodjFb8FJturiV0J$rmsxK3EtJUsru6Duw2Ap0uXALUN5pt8x1DzxuhBzKuI=", "is_superuser": false, "email": "user@test.com", "is_staff": false, diff --git a/library/admin.py b/library/admin.py index 8c38f3f..694323f 100644 --- a/library/admin.py +++ b/library/admin.py @@ -1,3 +1 @@ from django.contrib import admin - -# Register your models here. diff --git a/library/serializers.py b/library/serializers.py index 77d806f..a4df28c 100644 --- a/library/serializers.py +++ b/library/serializers.py @@ -1,4 +1,3 @@ -from django.db import transaction from django.utils import timezone from rest_framework import serializers from library.models import Borrowing, Book diff --git a/library/tests/test_borrowing_api_auth_permissions.py b/library/tests/test_borrowing_api_auth_permissions.py index f27c902..19787bb 100644 --- a/library/tests/test_borrowing_api_auth_permissions.py +++ b/library/tests/test_borrowing_api_auth_permissions.py @@ -17,8 +17,9 @@ def borrowing_detail_url(borrowing_id: int) -> str: return reverse("library:borrowing-detail", args=[borrowing_id]) + def get_results(data): - return data["results"] if isinstance(data, dict) and "results" in data else data + return data["results"] if isinstance(data, dict) and "results" in data else data # noqa class BorrowingAuthPermissionsTests(TestCase): diff --git a/library/tests/test_borrowing_api_create_return.py b/library/tests/test_borrowing_api_create_return.py index 96e42fb..f620379 100644 --- a/library/tests/test_borrowing_api_create_return.py +++ b/library/tests/test_borrowing_api_create_return.py @@ -46,7 +46,7 @@ def _payload(self, book_id: int): return { "book": book_id, "expected_return_date": ( - timezone.localdate() + timedelta(days=7)).isoformat(), + timezone.localdate() + timedelta(days=7)).isoformat(), } def _mock_stripe_session(self, mock_create_session): @@ -70,7 +70,7 @@ def test_create_borrowing_requires_auth(self): # ---- Create borrowing ---- @patch("library.serializers.create_payment_session") - def test_create_borrowing_decreases_inventory_and_attaches_user(self, mock_create_session): + def test_create_borrowing_decreases_inventory_and_attaches_user(self, mock_create_session): # noqa self._mock_stripe_session(mock_create_session) self.client.force_authenticate(user=self.user) diff --git a/notifications/admin.py b/notifications/admin.py index 8c38f3f..e69de29 100644 --- a/notifications/admin.py +++ b/notifications/admin.py @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/notifications/models.py b/notifications/models.py index 71a8362..e69de29 100644 --- a/notifications/models.py +++ b/notifications/models.py @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/notifications/tests/test_notifications.py b/notifications/tests/test_notifications.py index 3a30b90..4895b1d 100644 --- a/notifications/tests/test_notifications.py +++ b/notifications/tests/test_notifications.py @@ -30,9 +30,9 @@ def test_notify_task_called_on_borrowing_create(self): "expected_return_date": "2030-01-20" } - with patch("notifications.tasks.notify_new_borrowing.delay") as mocked_task: + with patch("notifications.tasks.notify_new_borrowing.delay") as mocked_task: # noqa response = client.post( - reverse("library:borrowing-list-create"), + reverse("library:borrowing-list"), payload ) diff --git a/notifications/views.py b/notifications/views.py index 91ea44a..e69de29 100644 --- a/notifications/views.py +++ b/notifications/views.py @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/payment/services.py b/payment/services.py index 8c5c2d9..c99ede7 100644 --- a/payment/services.py +++ b/payment/services.py @@ -29,7 +29,7 @@ def create_payment_session(borrowing, is_fee: bool = False): "quantity": 1, } ], - success_url="http://127.0.0.1:8000/api/success/?session_id={CHECKOUT_SESSION_ID}", + success_url="http://127.0.0.1:8000/api/success/?session_id={CHECKOUT_SESSION_ID}", # noqa cancel_url="http://127.0.0.1:8000/api/cancel/", ) diff --git a/payment/tests/test_payment_api.py b/payment/tests/test_payment_api.py index 8d7cad9..e02b083 100644 --- a/payment/tests/test_payment_api.py +++ b/payment/tests/test_payment_api.py @@ -142,6 +142,6 @@ def test_correct_fee_price(self): session = create_payment_session(self.exp_borrowing) price = session.total_price / 100 days = ( - self.exp_borrowing.actual_return_date - self.exp_borrowing.expected_return_date).days + self.exp_borrowing.actual_return_date - self.exp_borrowing.expected_return_date).days # noqa calculate_total = days * self.book.daily_fee self.assertEqual(price, calculate_total) diff --git a/payment/urls.py b/payment/urls.py index 87ecf08..dc42774 100644 --- a/payment/urls.py +++ b/payment/urls.py @@ -5,7 +5,7 @@ PaymentViewSet, StripeWebhookView, payment_success, - payment_cancel + payment_cancel, ) app_name = "payment" diff --git a/payment/views.py b/payment/views.py index 65105dc..c932968 100644 --- a/payment/views.py +++ b/payment/views.py @@ -43,9 +43,7 @@ def get_queryset(self): def payment_success(request): session_id = request.GET.get("session_id") - return HttpResponse( - f"✅ Payment successful! Session ID: {session_id}" - ) + return HttpResponse(f"✅ Payment successful! Session ID: {session_id}") def payment_cancel(request): diff --git a/pyproject.toml b/pyproject.toml index 25dbc0b..68f7d83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ exclude = ''' /( migrations | venv + | .venv | tests )/ ''' diff --git a/users/tests/test_models.py b/users/tests/test_models.py index cf33d81..028eb2d 100644 --- a/users/tests/test_models.py +++ b/users/tests/test_models.py @@ -7,7 +7,10 @@ def test_create_user_with_email_successful(self): """Test creating user with email""" email = "test@example.com" password = "password123" - user = get_user_model().objects.create_user(email=email, password=password) + user = get_user_model().objects.create_user( + email=email, + password=password + ) self.assertEqual(user.email, email) self.assertTrue(user.check_password(password)) diff --git a/users/tests/test_serializers.py b/users/tests/test_serializers.py index 53735fa..70fc158 100644 --- a/users/tests/test_serializers.py +++ b/users/tests/test_serializers.py @@ -26,7 +26,6 @@ def test_user_serializer_validation(self): self.assertFalse(serializer.is_valid()) self.assertIn("password", serializer.errors) - def test_user_serializer_update(self): """Test user serializer update""" user = get_user_model().objects.create_user("old@ex.com", "pass123") diff --git a/users/tests/test_views.py b/users/tests/test_views.py index 722bb18..5f18e2e 100644 --- a/users/tests/test_views.py +++ b/users/tests/test_views.py @@ -7,7 +7,10 @@ class ViewTests(APITestCase): def setUp(self): self.url = reverse("users:manage") - self.user = get_user_model().objects.create_user("test@ex.com", "pass12345") + self.user = get_user_model().objects.create_user( + "test@ex.com", + "pass12345" + ) def test_retrieve_user_unauthorized(self): """Test anonim retrieve user data (401)"""