diff --git a/poetry.lock b/poetry.lock index ebbbafa3..a0f96f56 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -839,7 +839,7 @@ files = [ django = "*" django-stubs-ext = ">=4.2.2" mypy = [ - {version = ">=1.0.0", optional = true, markers = "extra != \"compatible-mypy\""}, + {version = ">=1.0.0"}, {version = "==1.5.*", optional = true, markers = "extra == \"compatible-mypy\""}, ] types-pytz = "*" @@ -1034,6 +1034,20 @@ files = [ [package.extras] tests = ["asttokens", "littleutils", "pytest", "rich"] +[[package]] +name = "faker" +version = "12.0.1" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.6" +files = [ + {file = "Faker-12.0.1-py3-none-any.whl", hash = "sha256:1dc2811f20e163892fefe7006f2ce00778f8099a40aee265bfa60a13400de63d"}, + {file = "Faker-12.0.1.tar.gz", hash = "sha256:aa7103805ae793277abbb85da9f6f05e76a1a295a9384a8e17c2fba2b3a690cb"}, +] + +[package.dependencies] +python-dateutil = ">=2.4" + [[package]] name = "flake8" version = "6.1.0" @@ -1450,6 +1464,16 @@ files = [ {file = "html_void_elements-0.1.0-py3-none-any.whl", hash = "sha256:784cf39db03cdeb017320d9301009f8f3480f9d7b254d0974272e80e0cb5e0d2"}, ] +[[package]] +name = "httpretty" +version = "1.1.4" +description = "HTTP client mock for Python" +optional = false +python-versions = ">=3" +files = [ + {file = "httpretty-1.1.4.tar.gz", hash = "sha256:20de0e5dd5a18292d36d928cc3d6e52f8b2ac73daec40d41eb62dee154933b68"}, +] + [[package]] name = "hypothesis" version = "6.84.2" @@ -1844,6 +1868,23 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "mixer" +version = "7.2.2" +description = "Mixer -- Is a fixtures replacement. Supported Django ORM, SqlAlchemy ORM, Mongoengine ODM and custom python objects." +optional = false +python-versions = ">=3.7" +files = [ + {file = "mixer-7.2.2-py3-none-any.whl", hash = "sha256:8089b8e2d00288c77e622936198f5dd03c8ac1603a1530a4f870dc213363b2ae"}, + {file = "mixer-7.2.2.tar.gz", hash = "sha256:9b3f1a261b56d8f2394f39955f83adbc7ff3ab4bb1065ebfec19a10d3e8501e0"}, +] + +[package.dependencies] +Faker = ">=5.4.0,<12.1" + +[package.extras] +tests = ["Django (>=3.0)", "Flask (>=1.0)", "Marshmallow (>=3.9)", "SQLAlchemy (>=1.1.4)", "flask-sqlalchemy (>=2.1)", "mongoengine (>=0.10.1)", "peewee (>=3.7.0)", "pony (>=0.7)", "psycopg2-binary (>=2.8.4)", "pytest"] + [[package]] name = "more-itertools" version = "10.1.0" @@ -2543,6 +2584,20 @@ files = [ [package.dependencies] pytest = ">=5.0.0" +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "python-decouple" version = "3.8" @@ -2583,6 +2638,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2590,8 +2646,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2608,6 +2671,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2615,6 +2679,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2831,7 +2896,8 @@ files = [ {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, @@ -3442,4 +3508,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [metadata] lock-version = "2.0" python-versions = "3.11.5" -content-hash = "b6f24d93edb443bee450e4b8200340134cc77eb2441c980e0ea264df4b23da94" +content-hash = "bf5cfa374e3a32eef8c395bf8cf25f3cf13a853cf57f31692627c27a6a380f24" diff --git a/pyproject.toml b/pyproject.toml index 19bbf6e4..0ac3d41c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 diff --git a/server/apps/pictures/templates/pictures/pages/dashboard.html b/server/apps/pictures/templates/pictures/pages/dashboard.html index efdd78de..b5e0cf52 100644 --- a/server/apps/pictures/templates/pictures/pages/dashboard.html +++ b/server/apps/pictures/templates/pictures/pages/dashboard.html @@ -51,6 +51,10 @@

Профиль

+
+ {% csrf_token %} + +

{% endfor %} diff --git a/server/apps/pictures/urls.py b/server/apps/pictures/urls.py index e750c1b3..b4357c06 100644 --- a/server/apps/pictures/urls.py +++ b/server/apps/pictures/urls.py @@ -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/', FavouriteDeleteView.as_view(), name='remove_favourite'), ] diff --git a/server/apps/pictures/views.py b/server/apps/pictures/views.py index a52a3b9f..b47bab84 100644 --- a/server/apps/pictures/views.py +++ b/server/apps/pictures/views.py @@ -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 @@ -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')) diff --git a/setup.cfg b/setup.cfg index 34c14369..11be7f65 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 diff --git a/tests/conftest.py b/tests/conftest.py index 96baa556..f9555dd9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ 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: @@ -12,3 +13,23 @@ # 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 diff --git a/tests/test_apps/test_identity/test_create_user.py b/tests/test_apps/test_identity/test_create_user.py new file mode 100644 index 00000000..165f8595 --- /dev/null +++ b/tests/test_apps/test_identity/test_create_user.py @@ -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', + ) diff --git a/tests/test_apps/test_identity/test_login.py b/tests/test_apps/test_identity/test_login.py new file mode 100644 index 00000000..6583b97a --- /dev/null +++ b/tests/test_apps/test_identity/test_login.py @@ -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': 'my@email.com', + '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 diff --git a/tests/test_apps/test_identity/test_placeholder.py b/tests/test_apps/test_identity/test_placeholder.py new file mode 100644 index 00000000..1aec0c45 --- /dev/null +++ b/tests/test_apps/test_identity/test_placeholder.py @@ -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), + ) diff --git a/tests/test_apps/test_identity/test_templates.py b/tests/test_apps/test_identity/test_templates.py new file mode 100644 index 00000000..c8a1fcce --- /dev/null +++ b/tests/test_apps/test_identity/test_templates.py @@ -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) diff --git a/tests/test_apps/test_identity/test_update_user.py b/tests/test_apps/test_identity/test_update_user.py new file mode 100644 index 00000000..9674397d --- /dev/null +++ b/tests/test_apps/test_identity/test_update_user.py @@ -0,0 +1,30 @@ +from http import HTTPStatus + +import pytest + +pytestmark = [ + pytest.mark.django_db, +] + + +def test_get(user_client): + """Test get form for update user.""" + got = user_client.get('/identity/update') + + assert got.status_code == HTTPStatus.OK + + +def test_update(user_client): + """Test update exists user.""" + got = user_client.post('/identity/update', data={ + 'email': 'my@email.com', + 'first_name': 'My name', + 'last_name': 'My name', + 'date_of_birth': '1970-09-18', + 'address': 'My name', + 'job_title': 'My name', + 'phone': 'My name', + }) + + assert got.status_code == HTTPStatus.FOUND + assert got.headers['location'] == '/identity/update' diff --git a/tests/test_apps/test_pictures/test_dashboard.py b/tests/test_apps/test_pictures/test_dashboard.py new file mode 100644 index 00000000..1c4c3720 --- /dev/null +++ b/tests/test_apps/test_pictures/test_dashboard.py @@ -0,0 +1,54 @@ +from http import HTTPStatus + +import pytest + +from server.apps.pictures.models import FavouritePicture + +pytestmark = [ + pytest.mark.django_db, +] + + +@pytest.fixture() +def existed_picture(exists_user, mixer): + return mixer.blend('pictures.FavouritePicture', user=exists_user) + + +def test_get(user_client): + """Test get pictures dashboard.""" + got = user_client.get('/pictures/dashboard') + + assert got.status_code == HTTPStatus.OK + + +def test_create(user_client, exists_user): + """Test add picture to favourite.""" + got = user_client.post('/pictures/dashboard', data={ + 'foreign_id': 1, + 'url': 'https://via.placeholder.com/600/92c952', + }) + + assert got.status_code == HTTPStatus.FOUND + assert got.headers['location'] == '/pictures/dashboard' + assert FavouritePicture.objects.filter( + user_id=exists_user.id, + foreign_id=1, + url='https://via.placeholder.com/600/92c952', + ).count() == 1 + + +@pytest.mark.usefixtures() +def test_delete(user_client, exists_user, existed_picture): + """Test delete picture from favourite.""" + got = user_client.delete('/pictures/favourites/{0}'.format(existed_picture.foreign_id)) + + assert got.status_code == HTTPStatus.FOUND + assert got.headers['location'] == '/pictures/dashboard' + assert FavouritePicture.objects.count() == 0 + + +def test_get_favourites(user_client): + """Test get favourite pictures.""" + got = user_client.get('/pictures/favourites') + + assert got.status_code == HTTPStatus.OK diff --git a/tests/test_apps/test_pictures/test_forms.py b/tests/test_apps/test_pictures/test_forms.py new file mode 100644 index 00000000..ac724a1e --- /dev/null +++ b/tests/test_apps/test_pictures/test_forms.py @@ -0,0 +1,12 @@ +import pytest + +from server.apps.pictures.intrastructure.django.forms import FavouritesForm + +pytestmark = [ + pytest.mark.django_db, +] + + +def test_favourites_form(exists_user): + """Test favourites form.""" + FavouritesForm(user=exists_user).save(False) diff --git a/tests/test_apps/test_pictures/test_models.py b/tests/test_apps/test_pictures/test_models.py new file mode 100644 index 00000000..bff10e9c --- /dev/null +++ b/tests/test_apps/test_pictures/test_models.py @@ -0,0 +1,20 @@ +import pytest + +pytestmark = [ + pytest.mark.django_db, +] + + +@pytest.fixture() +def favour_picture(mixer, exists_user): + """Favourite picture.""" + return mixer.blend( + 'pictures.FavouritePicture', + user_id=exists_user.id, + foreign_id=10, + ) + + +def test_str(favour_picture, exists_user): + """Test FavouritePicture string representation.""" + assert str(favour_picture) == ''.format(exists_user.id) diff --git a/tests/test_apps/test_pictures/test_pictures_templates.py b/tests/test_apps/test_pictures/test_pictures_templates.py new file mode 100644 index 00000000..ede7b269 --- /dev/null +++ b/tests/test_apps/test_pictures/test_pictures_templates.py @@ -0,0 +1,37 @@ +import pytest +from django.http import HttpResponse +from django.shortcuts import render +from django.test import RequestFactory + +pytestmark = [ + pytest.mark.django_db, +] + + +@pytest.fixture() +def favourite_pictures(mixer): + """Exists favourite pictures.""" + return mixer.cycle(5).blend('pictures.FavouritePicture') + + +def test_registration(favourite_pictures): + """Test register favourite picture template.""" + page = render( + RequestFactory().get('/pictures/favourites'), + 'pictures/pages/favourites.html', + { + 'object_list': favourite_pictures, + }, + ) + + assert isinstance(page, HttpResponse) + + +def test_index(): + """Test index page template.""" + page = render( + RequestFactory().get('/pictures'), + 'pictures/pages/index.html', + ) + + assert isinstance(page, HttpResponse) diff --git a/tests/test_server/test_common_templates.py b/tests/test_server/test_common_templates.py new file mode 100644 index 00000000..3e457ddd --- /dev/null +++ b/tests/test_server/test_common_templates.py @@ -0,0 +1,24 @@ +import pytest +from django.http import HttpResponse +from django.shortcuts import render +from django.test import RequestFactory + +pytestmark = [ + pytest.mark.django_db, +] + + +def test_base(): + """Test base template.""" + page = render(RequestFactory().get('/'), 'common/_base.html') + + assert isinstance(page, HttpResponse) + + +def test_messages(): + """Test messages template.""" + page = render(RequestFactory().get('/'), 'common/includes/messages.html', { + 'messages': ['First', 'second'], + }) + + assert isinstance(page, HttpResponse)