Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

2nd homework #75

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 70 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ dennis = "^1.1"
dump-env = "^1.3"
ipython = "^8.15"
import-linter = "^1.11"
mixer = "^7.2.2"
httpretty = "^1.1.4"

[tool.poetry.group.docs]
optional = true
Expand Down
4 changes: 4 additions & 0 deletions server/apps/pictures/templates/pictures/pages/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ <h3>Профиль</h3>
<input type="hidden" name="url" value="{{ picture.url }}" />
<button type="submit">Добавить в избранное</button>
</form>
<form method="post" action="{% url 'pictures:remove_favourite' picture_id=picture.id %}">
{% csrf_token %}
<button type="submit">Удалить из избранного</button>
</form>
</div>
<hr />
{% endfor %}
Expand Down
3 changes: 2 additions & 1 deletion server/apps/pictures/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.urls import path

from server.apps.pictures.views import DashboardView, FavouritePicturesView
from server.apps.pictures.views import DashboardView, FavouritePicturesView, FavouriteDeleteView

app_name = 'pictures'

urlpatterns = [
path('dashboard', DashboardView.as_view(), name='dashboard'),
path('favourites', FavouritePicturesView.as_view(), name='favourites'),
path('favourites/<int:picture_id>', FavouriteDeleteView.as_view(), name='remove_favourite'),
]
14 changes: 12 additions & 2 deletions server/apps/pictures/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import QuerySet
from django.http import HttpResponse
from django.urls import reverse_lazy
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse_lazy, reverse
from django.views import View
from django.views.generic import CreateView, ListView, TemplateView

from server.apps.pictures.container import container
Expand Down Expand Up @@ -70,3 +71,12 @@ def get_queryset(self) -> QuerySet[FavouritePicture]:
"""Return matching pictures."""
list_favourites = container.instantiate(favourites_list.FavouritesList)
return list_favourites(self.request.user.id)


@final
@dispatch_decorator(login_required)
class FavouriteDeleteView(View):

def post(self, request, picture_id):
FavouritePicture.objects.filter(foreign_id=picture_id, user=request.user).delete()
return HttpResponseRedirect(reverse('pictures:dashboard'))
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ DJANGO_SETTINGS_MODULE = server.settings
# You should adjust this value to be as low as possible.
# Configuration:
# https://pypi.org/project/pytest-timeout/
timeout = 5
timeout = 3

# Strict `@xfail` by default:
xfail_strict = true
Expand Down
21 changes: 21 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,31 @@
1. https://docs.python.org/3/library/doctest.html
2. https://docs.pytest.org/en/latest/doctest.html
"""
import pytest

pytest_plugins = [
# Should be the first custom one:
'plugins.django_settings',

# TODO: add your own plugins here!
]


@pytest.fixture()
def mixer():
"""Util for create models."""
from mixer.backend.django import mixer # noqa: WPS433 names conflict
return mixer


@pytest.fixture()
def exists_user(mixer):
"""User registered in system."""
return mixer.blend('identity.User')


@pytest.fixture()
def user_client(exists_user, client):
"""Registered user HTTP client."""
client.force_login(exists_user)
return client
16 changes: 16 additions & 0 deletions tests/test_apps/test_identity/test_create_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pytest

from server.apps.identity.models import User

pytestmark = [
pytest.mark.django_db,
]


def test_without_email():
"""Test create user via manager with incorrect email."""
with pytest.raises(ValueError, match='Users must have an email address'):
User.objects.create_user( # noqa: S106 not secure issue
email='',
password='SeCr3t',
)
35 changes: 35 additions & 0 deletions tests/test_apps/test_identity/test_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from http import HTTPStatus

import pytest

from server.apps.identity.models import User

pytestmark = [
pytest.mark.django_db,
]


def test(client):
"""Test get login page."""
got = client.get('/identity/login')

assert got.status_code == HTTPStatus.OK


def test_registration(client):
"""Test registration."""
got = client.post('/identity/registration', data={
'email': '[email protected]',
'first_name': 'My name',
'last_name': 'My name',
'date_of_birth': '1970-09-18',
'address': 'My name',
'job_title': 'My name',
'phone': 'My name',
'password1': 'My name',
'password2': 'My name',
})

assert got.status_code == HTTPStatus.FOUND
assert got.headers['location'] == '/identity/login'
assert User.objects.count() == 1
52 changes: 52 additions & 0 deletions tests/test_apps/test_identity/test_placeholder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import datetime

import httpretty
import pytest

from server.apps.identity.intrastructure.services.placeholder import (
LeadCreate,
LeadUpdate,
UserResponse,
)

pytestmark = [
pytest.mark.django_db,
]


@httpretty.activate(allow_net_connect=False, verbose=True)
def test_create(mixer):
"""Test LeadCreate object."""
httpretty.register_uri(
httpretty.POST,
'https://domain.com/users',
body='{"id": 1}',
)
got = LeadCreate('https://domain.com', 5)(user=mixer.blend('identity.User'))

assert got == UserResponse(id=1)


@httpretty.activate(allow_net_connect=False, verbose=True)
def test_create_with_birthday(mixer, faker):
"""Test LeadCreate object with birthday."""
httpretty.register_uri(
httpretty.POST, 'https://domain.com/users', body='{"id": 1}',
)
got = LeadCreate('https://domain.com', 5)(user=mixer.blend(
'identity.User',
date_of_birth=datetime.datetime(1965, 6, 14), # noqa: WPS432
))

assert got == UserResponse(id=1)


@httpretty.activate(allow_net_connect=False, verbose=True)
def test_update(mixer):
"""Test LeadUpdate object."""
httpretty.register_uri(
httpretty.PATCH, 'https://domain.com/users/1', body='{"id": 1}',
)
LeadUpdate('https://domain.com', 5)(
user=mixer.blend('identity.User', lead_id=1),
)
18 changes: 18 additions & 0 deletions tests/test_apps/test_identity/test_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.http import HttpResponse
from django.shortcuts import render
from django.test import RequestFactory

from server.apps.identity.intrastructure.django.forms import RegistrationForm


def test_registration():
"""Test registration template."""
page = render(
RequestFactory().get('/identity/registration'),
'identity/pages/registration.html',
{
'form': RegistrationForm(),
},
)

assert isinstance(page, HttpResponse)
Loading
Loading