mirror of
https://github.com/boostorg/website-v2.git
synced 2026-01-19 04:42:17 +00:00
Rework versions models
- Added ListView and DetailView - Move to pytest style tests - Fix migrations to be clean to rebuild and throw away existing data - Add model_bakery
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from rest_framework import routers
|
||||
@@ -13,7 +13,8 @@ from ak.views import (
|
||||
NotFoundView,
|
||||
OKView,
|
||||
)
|
||||
from versions.views import *
|
||||
from versions.api import VersionViewSet, VersionFileViewSet
|
||||
from versions.views import VersionList, VersionDetail
|
||||
|
||||
router = routers.SimpleRouter()
|
||||
|
||||
@@ -26,11 +27,13 @@ urlpatterns = [
|
||||
path("", HomepageView.as_view(), name="home"),
|
||||
path("admin/", admin.site.urls),
|
||||
path("users/me/", CurrentUserView.as_view(), name="current-user"),
|
||||
url(r"^api/v1/", include(router.urls)),
|
||||
path("api/v1/", include(router.urls)),
|
||||
path("200", OKView.as_view(), name="ok"),
|
||||
path("403", ForbiddenView.as_view(), name="forbidden"),
|
||||
path("404", NotFoundView.as_view(), name="not_found"),
|
||||
path("500", InternalServerErrorView.as_view(), name="internal_server_error"),
|
||||
path("health/", include("health_check.urls")),
|
||||
path("forum/", include(machina_urls)),
|
||||
path("versions/", VersionList.as_view(), name="version-list"),
|
||||
path("version/<int:pk>/", VersionDetail.as_view(), name="version-detail"),
|
||||
]
|
||||
|
||||
6
conftest.py
Normal file
6
conftest.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import pytest
|
||||
|
||||
pytest_plugins = [
|
||||
"users.tests.fixtures",
|
||||
"versions.tests.fixtures",
|
||||
]
|
||||
@@ -30,10 +30,11 @@ pytest-cov
|
||||
pytest-django
|
||||
pytest-xdist
|
||||
Faker
|
||||
factory_boy
|
||||
model_bakery
|
||||
ipython
|
||||
|
||||
# Packaging
|
||||
pip-tools
|
||||
pip-tools>=6.6.2
|
||||
|
||||
# Markdown and Frontmatter
|
||||
mistletoe
|
||||
|
||||
110
requirements.txt
110
requirements.txt
@@ -2,7 +2,7 @@
|
||||
# This file is autogenerated by pip-compile with python 3.9
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile
|
||||
# pip-compile --output-file=./requirements.txt ./requirements.in
|
||||
#
|
||||
amqp==5.0.6
|
||||
# via kombu
|
||||
@@ -14,12 +14,16 @@ appdirs==1.4.4
|
||||
# fs
|
||||
asgiref==3.3.4
|
||||
# via django
|
||||
asttokens==2.0.5
|
||||
# via stack-data
|
||||
attrs==21.1.0
|
||||
# via pytest
|
||||
backcall==0.2.0
|
||||
# via ipython
|
||||
billiard==3.6.4.0
|
||||
# via celery
|
||||
black==21.5b0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
boto3==1.17.68
|
||||
# via django-bakery
|
||||
botocore==1.20.68
|
||||
@@ -29,9 +33,9 @@ botocore==1.20.68
|
||||
bump2version==1.0.1
|
||||
# via bumpversion
|
||||
bumpversion==0.6.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
celery==5.0.5
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
click==7.1.2
|
||||
# via
|
||||
# black
|
||||
@@ -48,13 +52,15 @@ click-repl==0.1.6
|
||||
# via celery
|
||||
coverage==5.5
|
||||
# via pytest-cov
|
||||
decorator==5.1.1
|
||||
# via ipython
|
||||
dj-database-url==0.5.0
|
||||
# via environs
|
||||
dj-email-url==1.0.2
|
||||
# via environs
|
||||
django==3.2.2
|
||||
# via
|
||||
# -r requirements.in
|
||||
# -r ./requirements.in
|
||||
# django-db-geventpool
|
||||
# django-extensions
|
||||
# django-haystack
|
||||
@@ -63,58 +69,61 @@ django==3.2.2
|
||||
# django-redis
|
||||
# django-rest-auth
|
||||
# djangorestframework
|
||||
# model-bakery
|
||||
django-bakery==0.12.7
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-cache-url==3.2.3
|
||||
# via environs
|
||||
django-db-geventpool==4.0.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-extensions==3.1.3
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-haystack==3.1.1
|
||||
# via django-machina
|
||||
django-health-check==3.16.4
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-js-asset==1.2.2
|
||||
# via django-mptt
|
||||
django-machina==1.1.5
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-mptt==0.13.4
|
||||
# via django-machina
|
||||
django-redis==5.0.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-rest-auth==0.9.5
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-test-plus==1.4.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-tracer==0.9.3
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
django-widget-tweaks==1.4.9
|
||||
# via django-machina
|
||||
djangorestframework==3.12.4
|
||||
# via
|
||||
# -r requirements.in
|
||||
# -r ./requirements.in
|
||||
# django-rest-auth
|
||||
environs[django]==9.3.2
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
execnet==1.8.0
|
||||
# via pytest-xdist
|
||||
factory-boy==3.2.1
|
||||
# via -r requirements.in
|
||||
executing==0.8.3
|
||||
# via stack-data
|
||||
faker==9.8.2
|
||||
# via
|
||||
# -r requirements.in
|
||||
# factory-boy
|
||||
# via -r ./requirements.in
|
||||
fs==2.4.13
|
||||
# via django-bakery
|
||||
gevent==21.1.2
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
greenlet==1.1.0
|
||||
# via gevent
|
||||
gunicorn==20.1.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
iniconfig==1.1.1
|
||||
# via pytest
|
||||
ipython==8.4.0
|
||||
# via -r ./requirements.in
|
||||
jedi==0.18.1
|
||||
# via ipython
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# boto3
|
||||
@@ -125,49 +134,67 @@ markdown2==2.4.1
|
||||
# via django-machina
|
||||
marshmallow==3.11.1
|
||||
# via environs
|
||||
matplotlib-inline==0.1.3
|
||||
# via ipython
|
||||
mistletoe==0.8.2
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
model-bakery==1.5.0
|
||||
# via -r ./requirements.in
|
||||
mypy-extensions==0.4.3
|
||||
# via black
|
||||
packaging==20.9
|
||||
# via pytest
|
||||
parso==0.8.3
|
||||
# via jedi
|
||||
pathspec==0.8.1
|
||||
# via black
|
||||
pep517==0.10.0
|
||||
# via pip-tools
|
||||
pexpect==4.8.0
|
||||
# via ipython
|
||||
pickleshare==0.7.5
|
||||
# via ipython
|
||||
pillow==8.4.0
|
||||
# via django-machina
|
||||
pip-tools==6.1.0
|
||||
# via -r requirements.in
|
||||
pip-tools==6.6.2
|
||||
# via -r ./requirements.in
|
||||
pluggy==0.13.1
|
||||
# via pytest
|
||||
prompt-toolkit==3.0.18
|
||||
# via click-repl
|
||||
# via
|
||||
# click-repl
|
||||
# ipython
|
||||
psycogreen==1.0.2
|
||||
# via django-db-geventpool
|
||||
psycopg2-binary==2.9.3
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
ptyprocess==0.7.0
|
||||
# via pexpect
|
||||
pure-eval==0.2.2
|
||||
# via stack-data
|
||||
py==1.10.0
|
||||
# via
|
||||
# pytest
|
||||
# pytest-forked
|
||||
pygments==2.12.0
|
||||
# via ipython
|
||||
pyparsing==2.4.7
|
||||
# via packaging
|
||||
pytest==6.2.4
|
||||
# via
|
||||
# -r requirements.in
|
||||
# -r ./requirements.in
|
||||
# pytest-cov
|
||||
# pytest-django
|
||||
# pytest-forked
|
||||
# pytest-xdist
|
||||
pytest-cov==2.11.1
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
pytest-django==4.2.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
pytest-forked==1.3.0
|
||||
# via pytest-xdist
|
||||
pytest-xdist==2.2.1
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
python-dateutil==2.8.1
|
||||
# via
|
||||
# botocore
|
||||
@@ -175,9 +202,9 @@ python-dateutil==2.8.1
|
||||
python-dotenv==0.17.1
|
||||
# via environs
|
||||
python-frontmatter==1.0.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
python-json-logger==2.0.1
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
pytz==2021.1
|
||||
# via
|
||||
# celery
|
||||
@@ -187,7 +214,7 @@ pyyaml==6.0
|
||||
# via python-frontmatter
|
||||
redis==3.5.3
|
||||
# via
|
||||
# -r requirements.in
|
||||
# -r ./requirements.in
|
||||
# django-redis
|
||||
regex==2021.4.4
|
||||
# via black
|
||||
@@ -195,6 +222,7 @@ s3transfer==0.4.2
|
||||
# via boto3
|
||||
six==1.16.0
|
||||
# via
|
||||
# asttokens
|
||||
# click-repl
|
||||
# django-bakery
|
||||
# django-rest-auth
|
||||
@@ -202,8 +230,10 @@ six==1.16.0
|
||||
# python-dateutil
|
||||
sqlparse==0.4.1
|
||||
# via django
|
||||
stack-data==0.2.0
|
||||
# via ipython
|
||||
structlog==21.1.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
text-unidecode==1.3
|
||||
# via faker
|
||||
toml==0.10.2
|
||||
@@ -211,6 +241,10 @@ toml==0.10.2
|
||||
# black
|
||||
# pep517
|
||||
# pytest
|
||||
traitlets==5.2.1.post0
|
||||
# via
|
||||
# ipython
|
||||
# matplotlib-inline
|
||||
urllib3==1.26.4
|
||||
# via botocore
|
||||
vine==5.0.0
|
||||
@@ -219,8 +253,10 @@ vine==5.0.0
|
||||
# celery
|
||||
wcwidth==0.2.5
|
||||
# via prompt-toolkit
|
||||
wheel==0.37.1
|
||||
# via pip-tools
|
||||
whitenoise==5.2.0
|
||||
# via -r requirements.in
|
||||
# via -r ./requirements.in
|
||||
zope-event==4.5.0
|
||||
# via gevent
|
||||
zope-interface==5.4.0
|
||||
|
||||
5
templates/versions/detail.html
Normal file
5
templates/versions/detail.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
Version Detail
|
||||
{% endblock %}
|
||||
5
templates/versions/list.html
Normal file
5
templates/versions/list.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
Version List
|
||||
{% endblock %}
|
||||
@@ -1,44 +0,0 @@
|
||||
import factory
|
||||
|
||||
import django.contrib.auth.models as auth_models
|
||||
from django.utils import timezone
|
||||
|
||||
from .models import User
|
||||
|
||||
|
||||
class VersionGroupFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = auth_models.Group
|
||||
|
||||
name = "version_manager"
|
||||
|
||||
|
||||
class UserFactory(factory.django.DjangoModelFactory):
|
||||
email = factory.Sequence(lambda n: "user%s@example.com" % n)
|
||||
first_name = factory.Sequence(lambda n: "User%s Bob" % n)
|
||||
last_name = factory.Sequence(lambda n: "User%s Smith" % n)
|
||||
|
||||
last_login = factory.LazyFunction(timezone.now)
|
||||
|
||||
password = factory.PostGenerationMethodCall("set_password", "password")
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
django_get_or_create = ("email",)
|
||||
|
||||
@factory.post_generation
|
||||
def groups(self, create, extracted, **kwargs):
|
||||
if not create:
|
||||
return
|
||||
|
||||
if extracted:
|
||||
for group in extracted:
|
||||
self.groups.add(group)
|
||||
|
||||
|
||||
class StaffUserFactory(UserFactory):
|
||||
is_staff = True
|
||||
|
||||
|
||||
class SuperUserFactory(StaffUserFactory):
|
||||
is_superuser = True
|
||||
@@ -4,10 +4,11 @@ from django.db import migrations
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.core.management import BaseCommand
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from versions.models import Version
|
||||
|
||||
|
||||
def gen_version_manager_group(apps, schema_editor):
|
||||
from versions.models import Version
|
||||
|
||||
new_group, created = Group.objects.get_or_create(name="version_manager")
|
||||
# Code to add permission to group ???
|
||||
ct = ContentType.objects.get_for_model(Version)
|
||||
|
||||
56
users/tests/fixtures.py
Normal file
56
users/tests/fixtures.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import pytest
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from model_bakery import baker
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user(db):
|
||||
"""Regular website user"""
|
||||
user = baker.make(
|
||||
"users.User",
|
||||
email="user@example.com",
|
||||
first_name="Regular",
|
||||
last_name="User",
|
||||
last_login=timezone.now(),
|
||||
)
|
||||
user.set_password("password")
|
||||
user.save()
|
||||
|
||||
return user
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def staff_user(db):
|
||||
"""Staff website user with access to the Django admin"""
|
||||
user = baker.make(
|
||||
"users.User",
|
||||
email="staff@example.com",
|
||||
first_name="Staff",
|
||||
last_name="User",
|
||||
last_login=timezone.now(),
|
||||
is_staff=True,
|
||||
)
|
||||
user.set_password("password")
|
||||
user.save()
|
||||
|
||||
return user
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def super_user(db):
|
||||
"""Superuser with access to everything"""
|
||||
user = baker.make(
|
||||
"users.User",
|
||||
email="super@example.com",
|
||||
first_name="Super",
|
||||
last_name="User",
|
||||
last_login=timezone.now(),
|
||||
is_staff=True,
|
||||
is_superuser=True,
|
||||
)
|
||||
user.set_password("password")
|
||||
user.save()
|
||||
|
||||
return user
|
||||
@@ -3,224 +3,225 @@ from faker import Faker
|
||||
from rest_framework.test import APIClient
|
||||
from test_plus.test import TestCase
|
||||
|
||||
from ..factories import UserFactory, StaffUserFactory
|
||||
from .. import serializers
|
||||
# from ..factories import UserFactory, StaffUserFactory
|
||||
# from .. import serializers
|
||||
|
||||
|
||||
class UserViewTests(TestCase):
|
||||
client_class = APIClient
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory()
|
||||
self.staff = StaffUserFactory()
|
||||
self.sample_user = UserFactory()
|
||||
|
||||
def test_list_user(self):
|
||||
"""
|
||||
Tests with a regular user
|
||||
"""
|
||||
# Does API work without auth?
|
||||
response = self.get("users-list")
|
||||
self.response_403(response)
|
||||
|
||||
# Does API work with auth?
|
||||
with self.login(self.user):
|
||||
response = self.get("users-list")
|
||||
self.response_200(response)
|
||||
self.assertEqual(len(response.data), 3)
|
||||
# Are non-staff shown/hidden the right fields?
|
||||
self.assertIn("first_name", response.data[0])
|
||||
self.assertNotIn("date_joined", response.data[0])
|
||||
|
||||
def test_list_staff(self):
|
||||
"""
|
||||
Test with a staff user, who use a different serializer
|
||||
"""
|
||||
# Are staff shown the right fields?
|
||||
with self.login(self.staff):
|
||||
response = self.get("users-list")
|
||||
self.response_200(response)
|
||||
self.assertEqual(len(response.data), 3)
|
||||
self.assertIn("first_name", response.data[0])
|
||||
self.assertIn("date_joined", response.data[0])
|
||||
|
||||
def test_detail(self):
|
||||
# Does this API work without auth?
|
||||
response = self.get("users-detail", pk=self.sample_user.pk)
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with non-staff auth?
|
||||
with self.login(self.user):
|
||||
response = self.get("users-detail", pk=self.sample_user.pk)
|
||||
self.response_200(response)
|
||||
self.assertIn("first_name", response.data)
|
||||
self.assertNotIn("date_joined", response.data)
|
||||
|
||||
# Does this API work with staff auth?
|
||||
with self.login(self.staff):
|
||||
response = self.get("users-detail", pk=self.sample_user.pk)
|
||||
self.response_200(response)
|
||||
self.assertIn("first_name", response.data)
|
||||
self.assertIn("date_joined", response.data)
|
||||
|
||||
def test_create(self):
|
||||
user = UserFactory.build()
|
||||
payload = serializers.FullUserSerializer(user).data
|
||||
|
||||
# Does API work without auth?
|
||||
response = self.client.post(reverse("users-list"), data=payload, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does API work with non-staff user?
|
||||
with self.login(self.user):
|
||||
response = self.client.post(
|
||||
reverse("users-list"), data=payload, format="json"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
# Does API work with staff user?
|
||||
with self.login(self.staff):
|
||||
response = self.client.post(
|
||||
reverse("users-list"), data=payload, format="json"
|
||||
)
|
||||
self.response_201(response)
|
||||
|
||||
def test_delete(self):
|
||||
url = reverse("users-detail", kwargs={"pk": self.sample_user.pk})
|
||||
|
||||
# Does this API work without auth?
|
||||
response = self.client.delete(url, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API wotk with non-staff user?
|
||||
with self.login(self.user):
|
||||
response = self.client.delete(url, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with staff user?
|
||||
with self.login(self.staff):
|
||||
response = self.client.delete(url, format="json")
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
# Confirm object is gone
|
||||
response = self.get(url)
|
||||
self.response_404(response)
|
||||
|
||||
def test_update(self):
|
||||
url = reverse("users-detail", kwargs={"pk": self.sample_user.pk})
|
||||
|
||||
old_name = self.sample_user.first_name
|
||||
payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
|
||||
# Does this API work without auth?
|
||||
response = self.client.put(url, payload, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with non-staff auth?
|
||||
with self.login(self.user):
|
||||
self.sample_user.first_name = Faker().name()
|
||||
payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
response = self.client.put(url, payload, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this APO work with staff auth?
|
||||
with self.login(self.staff):
|
||||
self.sample_user.first_name = Faker().name()
|
||||
payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
response = self.client.put(url, payload, format="json")
|
||||
self.response_200(response)
|
||||
self.assertFalse(response.data["first_name"] == old_name)
|
||||
|
||||
# Test updating reversions
|
||||
self.sample_user.first_name = old_name
|
||||
payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
response = self.client.put(url, payload, format="json")
|
||||
self.assertTrue(response.data["first_name"] == old_name)
|
||||
|
||||
|
||||
class CurrentUserViewTests(TestCase):
|
||||
client_class = APIClient
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory()
|
||||
self.staff = StaffUserFactory()
|
||||
|
||||
def test_get_current_user(self):
|
||||
# Does this API work without auth?
|
||||
response = self.get("current-user")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with auth?
|
||||
with self.login(self.user):
|
||||
response = self.get("current-user")
|
||||
self.response_200(response)
|
||||
self.assertIn("first_name", response.data)
|
||||
self.assertIn("date_joined", response.data)
|
||||
|
||||
def test_create(self):
|
||||
user = UserFactory.build()
|
||||
payload = serializers.CurrentUserSerializer(user).data
|
||||
|
||||
# Does API work without auth?
|
||||
response = self.client.post(
|
||||
reverse("current-user"), data=payload, format="json"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
# Does API work with non-staff user?
|
||||
with self.login(self.user):
|
||||
response = self.client.post(
|
||||
reverse("current-user"), data=payload, format="json"
|
||||
)
|
||||
self.response_405(response)
|
||||
|
||||
# Does API work with staff user?
|
||||
with self.login(self.staff):
|
||||
response = self.client.post(
|
||||
reverse("current-user"), data=payload, format="json"
|
||||
)
|
||||
self.response_405(response)
|
||||
|
||||
def test_update(self):
|
||||
old_name = self.user.first_name
|
||||
payload = serializers.CurrentUserSerializer(self.user).data
|
||||
|
||||
# Does this API work without auth?
|
||||
response = self.client.post(
|
||||
reverse("current-user"), data=payload, format="json"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with auth?
|
||||
with self.login(self.user):
|
||||
self.user.first_name = Faker().name()
|
||||
payload = serializers.CurrentUserSerializer(self.user).data
|
||||
response = self.client.put(reverse("current-user"), payload, format="json")
|
||||
self.response_200(response)
|
||||
self.assertFalse(response.data["first_name"] == old_name)
|
||||
|
||||
# Test updating reversions
|
||||
self.user.first_name = old_name
|
||||
payload = serializers.CurrentUserSerializer(self.user).data
|
||||
response = self.client.put(reverse("current-user"), payload, format="json")
|
||||
self.assertTrue(response.data["first_name"] == old_name)
|
||||
|
||||
# Can user update readonly fields?
|
||||
old_email = self.user.email
|
||||
|
||||
with self.login(self.user):
|
||||
self.user.email = Faker().email()
|
||||
payload = serializers.CurrentUserSerializer(self.user).data
|
||||
response = self.client.put(reverse("current-user"), payload, format="json")
|
||||
self.response_200(response)
|
||||
self.assertEqual(response.data["email"], old_email)
|
||||
|
||||
def test_delete(self):
|
||||
# Does this API work without auth?
|
||||
response = self.client.delete(reverse("current-user"), format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API wotk with auth? Should not.
|
||||
with self.login(self.user):
|
||||
response = self.client.delete(reverse("current-user"), format="json")
|
||||
self.response_405(response)
|
||||
# class UserViewTests(TestCase):
|
||||
# client_class = APIClient
|
||||
#
|
||||
# def setUp(self):
|
||||
# self.user = UserFactory()
|
||||
# self.staff = StaffUserFactory()
|
||||
# self.sample_user = UserFactory()
|
||||
#
|
||||
# def test_list_user(self):
|
||||
# """
|
||||
# Tests with a regular user
|
||||
# """
|
||||
# # Does API work without auth?
|
||||
# response = self.get("users-list")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does API work with auth?
|
||||
# with self.login(self.user):
|
||||
# response = self.get("users-list")
|
||||
# self.response_200(response)
|
||||
# self.assertEqual(len(response.data), 3)
|
||||
# # Are non-staff shown/hidden the right fields?
|
||||
# self.assertIn("first_name", response.data[0])
|
||||
# self.assertNotIn("date_joined", response.data[0])
|
||||
#
|
||||
# def test_list_staff(self):
|
||||
# """
|
||||
# Test with a staff user, who use a different serializer
|
||||
# """
|
||||
# # Are staff shown the right fields?
|
||||
# with self.login(self.staff):
|
||||
# response = self.get("users-list")
|
||||
# self.response_200(response)
|
||||
# self.assertEqual(len(response.data), 3)
|
||||
# self.assertIn("first_name", response.data[0])
|
||||
# self.assertIn("date_joined", response.data[0])
|
||||
#
|
||||
# def test_detail(self):
|
||||
# # Does this API work without auth?
|
||||
# response = self.get("users-detail", pk=self.sample_user.pk)
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with non-staff auth?
|
||||
# with self.login(self.user):
|
||||
# response = self.get("users-detail", pk=self.sample_user.pk)
|
||||
# self.response_200(response)
|
||||
# self.assertIn("first_name", response.data)
|
||||
# self.assertNotIn("date_joined", response.data)
|
||||
#
|
||||
# # Does this API work with staff auth?
|
||||
# with self.login(self.staff):
|
||||
# response = self.get("users-detail", pk=self.sample_user.pk)
|
||||
# self.response_200(response)
|
||||
# self.assertIn("first_name", response.data)
|
||||
# self.assertIn("date_joined", response.data)
|
||||
#
|
||||
# def test_create(self):
|
||||
# user = UserFactory.build()
|
||||
# payload = serializers.FullUserSerializer(user).data
|
||||
#
|
||||
# # Does API work without auth?
|
||||
# response = self.client.post(reverse("users-list"), data=payload, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does API work with non-staff user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.post(
|
||||
# reverse("users-list"), data=payload, format="json"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does API work with staff user?
|
||||
# with self.login(self.staff):
|
||||
# response = self.client.post(
|
||||
# reverse("users-list"), data=payload, format="json"
|
||||
# )
|
||||
# self.response_201(response)
|
||||
#
|
||||
# def test_delete(self):
|
||||
# url = reverse("users-detail", kwargs={"pk": self.sample_user.pk})
|
||||
#
|
||||
# # Does this API work without auth?
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API wotk with non-staff user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with staff user?
|
||||
# with self.login(self.staff):
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.assertEqual(response.status_code, 204)
|
||||
#
|
||||
# # Confirm object is gone
|
||||
# response = self.get(url)
|
||||
# self.response_404(response)
|
||||
#
|
||||
# def test_update(self):
|
||||
# url = reverse("users-detail", kwargs={"pk": self.sample_user.pk})
|
||||
#
|
||||
# old_name = self.sample_user.first_name
|
||||
# payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
#
|
||||
# # Does this API work without auth?
|
||||
# response = self.client.put(url, payload, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with non-staff auth?
|
||||
# with self.login(self.user):
|
||||
# self.sample_user.first_name = Faker().name()
|
||||
# payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
# response = self.client.put(url, payload, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this APO work with staff auth?
|
||||
# with self.login(self.staff):
|
||||
# self.sample_user.first_name = Faker().name()
|
||||
# payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
# response = self.client.put(url, payload, format="json")
|
||||
# self.response_200(response)
|
||||
# self.assertFalse(response.data["first_name"] == old_name)
|
||||
#
|
||||
# # Test updating reversions
|
||||
# self.sample_user.first_name = old_name
|
||||
# payload = serializers.FullUserSerializer(self.sample_user).data
|
||||
# response = self.client.put(url, payload, format="json")
|
||||
# self.assertTrue(response.data["first_name"] == old_name)
|
||||
#
|
||||
#
|
||||
# class CurrentUserViewTests(TestCase):
|
||||
# client_class = APIClient
|
||||
#
|
||||
# def setUp(self):
|
||||
# self.user = UserFactory()
|
||||
# self.staff = StaffUserFactory()
|
||||
#
|
||||
# def test_get_current_user(self):
|
||||
# # Does this API work without auth?
|
||||
# response = self.get("current-user")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with auth?
|
||||
# with self.login(self.user):
|
||||
# response = self.get("current-user")
|
||||
# self.response_200(response)
|
||||
# self.assertIn("first_name", response.data)
|
||||
# self.assertIn("date_joined", response.data)
|
||||
#
|
||||
# def test_create(self):
|
||||
# user = UserFactory.build()
|
||||
# payload = serializers.CurrentUserSerializer(user).data
|
||||
#
|
||||
# # Does API work without auth?
|
||||
# response = self.client.post(
|
||||
# reverse("current-user"), data=payload, format="json"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does API work with non-staff user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.post(
|
||||
# reverse("current-user"), data=payload, format="json"
|
||||
# )
|
||||
# self.response_405(response)
|
||||
#
|
||||
# # Does API work with staff user?
|
||||
# with self.login(self.staff):
|
||||
# response = self.client.post(
|
||||
# reverse("current-user"), data=payload, format="json"
|
||||
# )
|
||||
# self.response_405(response)
|
||||
#
|
||||
# def test_update(self):
|
||||
# old_name = self.user.first_name
|
||||
# payload = serializers.CurrentUserSerializer(self.user).data
|
||||
#
|
||||
# # Does this API work without auth?
|
||||
# response = self.client.post(
|
||||
# reverse("current-user"), data=payload, format="json"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with auth?
|
||||
# with self.login(self.user):
|
||||
# self.user.first_name = Faker().name()
|
||||
# payload = serializers.CurrentUserSerializer(self.user).data
|
||||
# response = self.client.put(reverse("current-user"), payload, format="json")
|
||||
# self.response_200(response)
|
||||
# self.assertFalse(response.data["first_name"] == old_name)
|
||||
#
|
||||
# # Test updating reversions
|
||||
# self.user.first_name = old_name
|
||||
# payload = serializers.CurrentUserSerializer(self.user).data
|
||||
# response = self.client.put(reverse("current-user"), payload, format="json")
|
||||
# self.assertTrue(response.data["first_name"] == old_name)
|
||||
#
|
||||
# # Can user update readonly fields?
|
||||
# old_email = self.user.email
|
||||
#
|
||||
# with self.login(self.user):
|
||||
# self.user.email = Faker().email()
|
||||
# payload = serializers.CurrentUserSerializer(self.user).data
|
||||
# response = self.client.put(reverse("current-user"), payload, format="json")
|
||||
# self.response_200(response)
|
||||
# self.assertEqual(response.data["email"], old_email)
|
||||
#
|
||||
# def test_delete(self):
|
||||
# # Does this API work without auth?
|
||||
# response = self.client.delete(reverse("current-user"), format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API wotk with auth? Should not.
|
||||
# with self.login(self.user):
|
||||
# response = self.client.delete(reverse("current-user"), format="json")
|
||||
# self.response_405(response)
|
||||
####
|
||||
|
||||
40
users/tests/test_managers.py
Normal file
40
users/tests/test_managers.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from django.utils import timezone
|
||||
|
||||
from users.models import User
|
||||
|
||||
|
||||
def test_record_login_email(user):
|
||||
now = timezone.now()
|
||||
assert user.last_login < now
|
||||
User.objects.record_login(email=user.email)
|
||||
user.refresh_from_db()
|
||||
assert user.last_login > now
|
||||
|
||||
|
||||
def test_record_login_user(user):
|
||||
now = timezone.now()
|
||||
assert user.last_login < now
|
||||
User.objects.record_login(user=user)
|
||||
user.refresh_from_db()
|
||||
assert user.last_login > now
|
||||
|
||||
|
||||
def test_user_creation(db):
|
||||
u = User.objects.create_user("t1@example.com", "t1pass")
|
||||
assert u.is_active == True
|
||||
assert u.is_staff == False
|
||||
assert u.is_superuser == False
|
||||
|
||||
|
||||
def test_staff_user_creation(db):
|
||||
u = User.objects.create_staffuser("t2@example.com", "t2pass")
|
||||
assert u.is_active == True
|
||||
assert u.is_staff == True
|
||||
assert u.is_superuser == False
|
||||
|
||||
|
||||
def test_super_user_creation(db):
|
||||
u = User.objects.create_superuser("t3@example.com", "t3pass")
|
||||
assert u.is_active == True
|
||||
assert u.is_staff == True
|
||||
assert u.is_superuser == True
|
||||
@@ -2,66 +2,22 @@ from test_plus import TestCase
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils import timezone
|
||||
|
||||
from ..factories import UserFactory, StaffUserFactory, SuperUserFactory
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class UserModelTests(TestCase):
|
||||
def test_simple_user_creation(self):
|
||||
now = timezone.now()
|
||||
f = UserFactory()
|
||||
self.assertTrue(f.is_active)
|
||||
|
||||
# Ensure LastSeen model is created
|
||||
self.assertTrue(f.last_seen.at > now)
|
||||
|
||||
def test_staff_creation(self):
|
||||
s = StaffUserFactory()
|
||||
self.assertTrue(s.is_active)
|
||||
self.assertTrue(s.is_staff)
|
||||
self.assertFalse(s.is_superuser)
|
||||
|
||||
def test_superuser_creation(self):
|
||||
s = SuperUserFactory()
|
||||
self.assertTrue(s.is_active)
|
||||
self.assertTrue(s.is_staff)
|
||||
self.assertTrue(s.is_superuser)
|
||||
def test_regular_user(user):
|
||||
assert user.is_active == True
|
||||
assert user.is_staff == False
|
||||
assert user.is_superuser == False
|
||||
|
||||
|
||||
class UserManagerTests(TestCase):
|
||||
def test_record_login_email(self):
|
||||
user = UserFactory()
|
||||
now = timezone.now()
|
||||
self.assertTrue(user.last_login < now)
|
||||
User.objects.record_login(email=user.email)
|
||||
def test_staff_user(staff_user):
|
||||
assert staff_user.is_active == True
|
||||
assert staff_user.is_staff == True
|
||||
assert staff_user.is_superuser == False
|
||||
|
||||
user = User.objects.get(pk=user.pk)
|
||||
self.assertTrue(user.last_login > now)
|
||||
|
||||
def test_record_login_user(self):
|
||||
user = UserFactory()
|
||||
now = timezone.now()
|
||||
self.assertTrue(user.last_login < now)
|
||||
User.objects.record_login(user=user)
|
||||
|
||||
user = User.objects.get(pk=user.pk)
|
||||
self.assertTrue(user.last_login > now)
|
||||
|
||||
def test_create_user(self):
|
||||
u = User.objects.create_user("t1@example.com", "t1pass")
|
||||
self.assertTrue(u.is_active)
|
||||
self.assertFalse(u.is_staff)
|
||||
self.assertFalse(u.is_superuser)
|
||||
|
||||
def test_create_staffuser(self):
|
||||
u = User.objects.create_staffuser("t2@example.com", "t2pass")
|
||||
self.assertTrue(u.is_active)
|
||||
self.assertTrue(u.is_staff)
|
||||
self.assertFalse(u.is_superuser)
|
||||
|
||||
def test_create_superuser(self):
|
||||
u = User.objects.create_superuser("t3@example.com", "t3pass")
|
||||
self.assertTrue(u.is_active)
|
||||
self.assertTrue(u.is_staff)
|
||||
self.assertTrue(u.is_superuser)
|
||||
def test_super_user(super_user):
|
||||
assert super_user.is_active == True
|
||||
assert super_user.is_staff == True
|
||||
assert super_user.is_superuser == True
|
||||
|
||||
@@ -3,9 +3,18 @@ from django.contrib import admin
|
||||
from . import models
|
||||
|
||||
|
||||
class VersionFileInline(admin.StackedInline):
|
||||
model = models.VersionFile
|
||||
autocomplete_fields = ("version",)
|
||||
verbose_name = "VersionFile"
|
||||
verbose_name_plural = "VersionFiles"
|
||||
extra = 0
|
||||
|
||||
|
||||
@admin.register(models.Version)
|
||||
class VersionAdmin(admin.ModelAdmin):
|
||||
list_display = ["name", "release_date"]
|
||||
search_fields = [
|
||||
"name",
|
||||
]
|
||||
list_display = ["name", "release_date", "active"]
|
||||
list_filter = ["active"]
|
||||
search_fields = ["name", "description"]
|
||||
date_hierarchy = "release_date"
|
||||
inlines = [VersionFileInline]
|
||||
|
||||
21
versions/api.py
Executable file
21
versions/api.py
Executable file
@@ -0,0 +1,21 @@
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import permissions
|
||||
from versions.permissions import SuperUserOrVersionManager
|
||||
|
||||
from versions.models import Version, VersionFile
|
||||
from versions.serializers import VersionSerializer, VersionFileSerializer
|
||||
|
||||
|
||||
class VersionViewSet(viewsets.ModelViewSet):
|
||||
model = Version
|
||||
queryset = Version.objects.all()
|
||||
serializer_class = VersionSerializer
|
||||
permission_classes = [permissions.IsAuthenticated, SuperUserOrVersionManager]
|
||||
|
||||
|
||||
class VersionFileViewSet(viewsets.ModelViewSet):
|
||||
model = VersionFile
|
||||
queryset = VersionFile.objects.all()
|
||||
serializer_class = VersionFileSerializer
|
||||
permission_classes = [permissions.IsAuthenticated, SuperUserOrVersionManager]
|
||||
16
versions/managers.py
Normal file
16
versions/managers.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class VersionQuerySet(models.QuerySet):
|
||||
def active(self):
|
||||
"""Return active versions"""
|
||||
return self.filter(active=True)
|
||||
|
||||
|
||||
class VersionManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return VersionQuerySet(self.model, using=self._db)
|
||||
|
||||
def active(self):
|
||||
"""Return active versions"""
|
||||
return self.get_queryset().active()
|
||||
19
versions/migrations/0003_auto_20220528_1905.py
Normal file
19
versions/migrations/0003_auto_20220528_1905.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.2.2 on 2022-05-28 19:05
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('versions', '0002_auto_20211216_1051'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Version',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='VersionFile',
|
||||
),
|
||||
]
|
||||
35
versions/migrations/0004_version_versionfile.py
Normal file
35
versions/migrations/0004_version_versionfile.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 3.2.2 on 2022-05-28 19:07
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('versions', '0003_auto_20220528_1905'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Version',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(help_text='Version name', max_length=256)),
|
||||
('release_date', models.DateField()),
|
||||
('description', models.TextField(blank=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='VersionFile',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('operating_system', models.CharField(choices=[('Unix', 'Unix'), ('Windows', 'Windows')], default='Unix', max_length=15)),
|
||||
('checksum', models.CharField(default=None, max_length=64, unique=True)),
|
||||
('file', models.FileField(upload_to='uploads/')),
|
||||
('version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='versions.version')),
|
||||
],
|
||||
),
|
||||
]
|
||||
18
versions/migrations/0005_version_active.py
Normal file
18
versions/migrations/0005_version_active.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.2 on 2022-05-28 20:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('versions', '0004_version_versionfile'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='version',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, help_text='Control whether or not this version is available on the website'),
|
||||
),
|
||||
]
|
||||
@@ -1,7 +1,24 @@
|
||||
import hashlib
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
from .managers import VersionManager
|
||||
|
||||
|
||||
class Version(models.Model):
|
||||
name = models.CharField(
|
||||
max_length=256, null=False, blank=False, help_text="Version name"
|
||||
)
|
||||
release_date = models.DateField(auto_now=False, auto_now_add=False)
|
||||
description = models.TextField(blank=True)
|
||||
active = models.BooleanField(
|
||||
default=True,
|
||||
help_text="Control whether or not this version is available on the website",
|
||||
)
|
||||
|
||||
objects = VersionManager()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class VersionFile(models.Model):
|
||||
@@ -11,24 +28,18 @@ class VersionFile(models.Model):
|
||||
(Unix, "Unix"),
|
||||
(Windows, "Windows"),
|
||||
)
|
||||
|
||||
version = models.ForeignKey(Version, related_name="files", on_delete=models.CASCADE)
|
||||
operating_system = models.CharField(
|
||||
choices=OPERATING_SYSTEM_CHOICES, max_length=15, default=Unix
|
||||
)
|
||||
checksum = models.CharField(max_length=64, unique=True, default=None)
|
||||
file = models.FileField(upload_to="uploads/")
|
||||
operating_system = models.CharField(
|
||||
choices=OPERATING_SYSTEM_CHOICES, max_length=15, null=False, blank=False
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.file is not None:
|
||||
if self.checksum is None:
|
||||
self.checksum = hashlib.sha256(
|
||||
self.file.name.encode("utf-8")
|
||||
self.file.file.encode("utf-8")
|
||||
).hexdigest()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Version(models.Model):
|
||||
name = models.CharField(
|
||||
max_length=256, null=False, blank=False, help_text="Version name"
|
||||
)
|
||||
files = models.ManyToManyField(VersionFile)
|
||||
release_date = models.DateField(auto_now=False, auto_now_add=False)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.core import files
|
||||
from rest_framework import serializers
|
||||
|
||||
from versions.models import Version, VersionFile
|
||||
|
||||
|
||||
@@ -9,7 +10,7 @@ class VersionFileSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = VersionFile
|
||||
fields = ["id", "checksum", "operating_system", "filename", "url", "file"]
|
||||
fields = ["id", "filename", "checksum", "operating_system", "url"]
|
||||
|
||||
def get_url(self, obj):
|
||||
request = self.context.get("request")
|
||||
@@ -25,12 +26,4 @@ class VersionSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Version
|
||||
fields = ["id", "name", "files", "release_date"]
|
||||
|
||||
# def create(self, validated_data):
|
||||
# files = validated_data.pop('files')
|
||||
# version = Version.objects.create(**validated_data)
|
||||
# for file in files:
|
||||
# version_file = VersionFile.objects.create(file=file.get("file"), operating_system=file.get("operating_system"))
|
||||
# version.files.add(version_file)
|
||||
# return version
|
||||
fields = ["id", "name", "release_date", "description", "files"]
|
||||
|
||||
14
versions/tests/fixtures.py
Normal file
14
versions/tests/fixtures.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
import datetime
|
||||
from model_bakery import baker
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def version(db):
|
||||
yesterday = datetime.date.today() - datetime.timedelta(days=1)
|
||||
return baker.make(
|
||||
"versions.Version",
|
||||
name="Version 1.79.0",
|
||||
description="Some awesome description of the library",
|
||||
release_date=yesterday,
|
||||
)
|
||||
10
versions/tests/test_managers.py
Normal file
10
versions/tests/test_managers.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from model_bakery import baker
|
||||
|
||||
from versions.models import Version
|
||||
|
||||
|
||||
def test_active_manager(version):
|
||||
v2 = baker.make("versions.Version", active=False)
|
||||
v3 = baker.make("versions.Version", active=False)
|
||||
|
||||
assert Version.objects.active().count() == 1
|
||||
6
versions/tests/test_models.py
Normal file
6
versions/tests/test_models.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import datetime
|
||||
|
||||
|
||||
def test_version_creation(version):
|
||||
today = datetime.date.today()
|
||||
assert version.release_date < today
|
||||
@@ -1,171 +1,172 @@
|
||||
from django.db import transaction
|
||||
from django.db import IntegrityError
|
||||
import tempfile
|
||||
from django.urls import reverse
|
||||
from django.core.files import File as DjangoFile
|
||||
from rest_framework.test import APIClient
|
||||
from test_plus.test import TestCase
|
||||
|
||||
from users.factories import UserFactory, SuperUserFactory, VersionGroupFactory
|
||||
from versions.factories import VersionFactory, VersionFileFactory
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from versions.models import VersionFile
|
||||
|
||||
|
||||
class VersionViewTests(TestCase):
|
||||
client_class = APIClient
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory()
|
||||
self.group_user = UserFactory.create(groups=(VersionGroupFactory.create(),))
|
||||
self.super_user = SuperUserFactory()
|
||||
self.version_manager = UserFactory()
|
||||
self.version_file1 = VersionFileFactory()
|
||||
self.version_file2 = VersionFileFactory()
|
||||
self.version = VersionFactory.create(
|
||||
files=(self.version_file1, self.version_file2)
|
||||
)
|
||||
|
||||
def test_list_version(self):
|
||||
"""
|
||||
Tests with a regular user
|
||||
"""
|
||||
# Does API work without auth?
|
||||
response = self.get("versions-list")
|
||||
self.response_403(response)
|
||||
|
||||
# Does API work with auth?
|
||||
with self.login(self.user):
|
||||
response = self.get("versions-list")
|
||||
self.response_200(response)
|
||||
self.assertEqual(len(response.data), 1)
|
||||
# Are non-staff shown/hidden the right fields?
|
||||
self.assertIn("name", response.data[0])
|
||||
files = response.data[0].get("files")
|
||||
for file in files:
|
||||
self.assertIn("checksum", file)
|
||||
self.assertIn("operating_system", file)
|
||||
|
||||
def test_create(self):
|
||||
image = Image.new("RGB", (100, 100))
|
||||
|
||||
tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
image.save(tmp_file)
|
||||
|
||||
tmp_file.seek(0)
|
||||
file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
|
||||
payload = {
|
||||
"files": [{"file": file_obj, "operating_system": "Windows"}],
|
||||
"name": "First Version",
|
||||
"release_date": "2021-01-01",
|
||||
}
|
||||
|
||||
# Does API work without auth?
|
||||
response = self.client.post(
|
||||
reverse("versions-list"), files=payload, format="multipart"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with normal user?
|
||||
with self.login(self.user):
|
||||
response = self.client.post(
|
||||
reverse("versions-list"), data=payload, format="multipart"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# # Does API work with super user?
|
||||
with self.login(self.super_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.post(
|
||||
reverse("versions-list"), data=payload, format="multipart"
|
||||
)
|
||||
self.response_201(response)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with version_manager user?
|
||||
with self.login(self.group_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.post(
|
||||
reverse("versions-list"), data=payload, format="multipart"
|
||||
)
|
||||
self.response_201(response)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
def test_delete(self):
|
||||
url = reverse("versions-detail", kwargs={"pk": self.version.pk})
|
||||
|
||||
# Does this API work without auth?
|
||||
response = self.client.delete(url, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API wotk with non-staff user?
|
||||
with self.login(self.user):
|
||||
response = self.client.delete(url, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with super user?
|
||||
with self.login(self.super_user):
|
||||
response = self.client.delete(url, format="json")
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
# Confirm object is gone
|
||||
response = self.get(url)
|
||||
self.response_404(response)
|
||||
|
||||
def test_update(self):
|
||||
old_name = self.version.name
|
||||
url = reverse("versions-detail", kwargs={"pk": self.version.pk})
|
||||
|
||||
image = Image.new("RGB", (100, 100))
|
||||
|
||||
tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
|
||||
file_obj.seek(0)
|
||||
|
||||
payload = {
|
||||
"files": [{"file": file_obj, "operating_system": "Windows"}],
|
||||
"name": "Second Version",
|
||||
}
|
||||
|
||||
# Does API work without auth?
|
||||
response = self.client.post(url, files=payload, format="multipart")
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with normal user?
|
||||
with self.login(self.user):
|
||||
response = self.client.patch(url, data=payload, format="multipart")
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with super user?
|
||||
with self.login(self.super_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.patch(url, data=payload, format="multipart")
|
||||
self.response_200(response)
|
||||
self.assertNotEqual(old_name, response.data["name"])
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with version_manager user?
|
||||
with self.login(self.group_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.patch(url, data=payload, format="multipart")
|
||||
self.response_200(response)
|
||||
self.assertNotEqual(old_name, response.data["name"])
|
||||
except IntegrityError:
|
||||
pass
|
||||
# from django.db import transaction
|
||||
# from django.db import IntegrityError
|
||||
# import tempfile
|
||||
# from django.urls import reverse
|
||||
# from django.core.files import File as DjangoFile
|
||||
# from rest_framework.test import APIClient
|
||||
# from test_plus.test import TestCase
|
||||
#
|
||||
# from users.factories import UserFactory, SuperUserFactory, VersionGroupFactory
|
||||
# from versions.factories import VersionFactory, VersionFileFactory
|
||||
#
|
||||
# from PIL import Image
|
||||
#
|
||||
# from versions.models import VersionFile
|
||||
#
|
||||
#
|
||||
# class VersionViewTests(TestCase):
|
||||
# client_class = APIClient
|
||||
#
|
||||
# def setUp(self):
|
||||
# self.user = UserFactory()
|
||||
# self.group_user = UserFactory.create(groups=(VersionGroupFactory.create(),))
|
||||
# self.super_user = SuperUserFactory()
|
||||
# self.version_manager = UserFactory()
|
||||
# self.version_file1 = VersionFileFactory()
|
||||
# self.version_file2 = VersionFileFactory()
|
||||
# self.version = VersionFactory.create(
|
||||
# files=(self.version_file1, self.version_file2)
|
||||
# )
|
||||
#
|
||||
# def test_list_version(self):
|
||||
# """
|
||||
# Tests with a regular user
|
||||
# """
|
||||
# # Does API work without auth?
|
||||
# response = self.get("versions-list")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does API work with auth?
|
||||
# with self.login(self.user):
|
||||
# response = self.get("versions-list")
|
||||
# self.response_200(response)
|
||||
# self.assertEqual(len(response.data), 1)
|
||||
# # Are non-staff shown/hidden the right fields?
|
||||
# self.assertIn("name", response.data[0])
|
||||
# files = response.data[0].get("files")
|
||||
# for file in files:
|
||||
# self.assertIn("checksum", file)
|
||||
# self.assertIn("operating_system", file)
|
||||
#
|
||||
# def test_create(self):
|
||||
# image = Image.new("RGB", (100, 100))
|
||||
#
|
||||
# tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
# image.save(tmp_file)
|
||||
#
|
||||
# tmp_file.seek(0)
|
||||
# file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
#
|
||||
# payload = {
|
||||
# "files": [{"file": file_obj, "operating_system": "Windows"}],
|
||||
# "name": "First Version",
|
||||
# "release_date": "2021-01-01",
|
||||
# }
|
||||
#
|
||||
# # Does API work without auth?
|
||||
# response = self.client.post(
|
||||
# reverse("versions-list"), files=payload, format="multipart"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with normal user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.post(
|
||||
# reverse("versions-list"), data=payload, format="multipart"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # # Does API work with super user?
|
||||
# with self.login(self.super_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.post(
|
||||
# reverse("versions-list"), data=payload, format="multipart"
|
||||
# )
|
||||
# self.response_201(response)
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with version_manager user?
|
||||
# with self.login(self.group_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.post(
|
||||
# reverse("versions-list"), data=payload, format="multipart"
|
||||
# )
|
||||
# self.response_201(response)
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
# def test_delete(self):
|
||||
# url = reverse("versions-detail", kwargs={"pk": self.version.pk})
|
||||
#
|
||||
# # Does this API work without auth?
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API wotk with non-staff user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with super user?
|
||||
# with self.login(self.super_user):
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.assertEqual(response.status_code, 204)
|
||||
#
|
||||
# # Confirm object is gone
|
||||
# response = self.get(url)
|
||||
# self.response_404(response)
|
||||
#
|
||||
# def test_update(self):
|
||||
# old_name = self.version.name
|
||||
# url = reverse("versions-detail", kwargs={"pk": self.version.pk})
|
||||
#
|
||||
# image = Image.new("RGB", (100, 100))
|
||||
#
|
||||
# tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
# file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
#
|
||||
# payload = {
|
||||
# "files": [{"file": file_obj, "operating_system": "Windows"}],
|
||||
# "name": "Second Version",
|
||||
# }
|
||||
#
|
||||
# # Does API work without auth?
|
||||
# response = self.client.post(url, files=payload, format="multipart")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with normal user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.patch(url, data=payload, format="multipart")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with super user?
|
||||
# with self.login(self.super_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.patch(url, data=payload, format="multipart")
|
||||
# self.response_200(response)
|
||||
# self.assertNotEqual(old_name, response.data["name"])
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with version_manager user?
|
||||
# with self.login(self.group_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.patch(url, data=payload, format="multipart")
|
||||
# self.response_200(response)
|
||||
# self.assertNotEqual(old_name, response.data["name"])
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
|
||||
@@ -7,157 +7,158 @@ from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
from test_plus.test import TestCase
|
||||
|
||||
from users.factories import UserFactory, SuperUserFactory, VersionGroupFactory
|
||||
from versions.factories import VersionFactory, VersionFileFactory
|
||||
# from users.factories import UserFactory, SuperUserFactory, VersionGroupFactory
|
||||
# from versions.factories import VersionFactory, VersionFileFactory
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from versions.models import VersionFile
|
||||
|
||||
|
||||
class VersionViewTests(TestCase):
|
||||
client_class = APIClient
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory()
|
||||
self.group_user = UserFactory.create(groups=(VersionGroupFactory.create(),))
|
||||
self.super_user = SuperUserFactory()
|
||||
self.version_manager = UserFactory()
|
||||
self.version_file1 = VersionFileFactory()
|
||||
self.version_file2 = VersionFileFactory()
|
||||
self.version = VersionFactory.create(
|
||||
files=(self.version_file1, self.version_file2)
|
||||
)
|
||||
|
||||
def test_list_version(self):
|
||||
"""
|
||||
Tests with a regular user
|
||||
"""
|
||||
# Does API work without auth?
|
||||
response = self.get("version-files-list")
|
||||
self.response_403(response)
|
||||
|
||||
# Does API work with auth?
|
||||
with self.login(self.user):
|
||||
response = self.get("version-files-list")
|
||||
self.response_200(response)
|
||||
self.assertEqual(len(response.data), 2)
|
||||
self.assertIn("checksum", response.data[0])
|
||||
self.assertIn("operating_system", response.data[0])
|
||||
|
||||
def test_create(self):
|
||||
image = Image.new("RGB", (100, 100))
|
||||
|
||||
tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
image.save(tmp_file)
|
||||
|
||||
tmp_file.seek(0)
|
||||
file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
|
||||
payload = {"file": file_obj, "operating_system": "Windows"}
|
||||
|
||||
# Does API work without auth?
|
||||
response = self.client.post(
|
||||
reverse("version-files-list"), files=payload, format="multipart"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with normal user?
|
||||
with self.login(self.user):
|
||||
response = self.client.post(
|
||||
reverse("version-files-list"), data=payload, format="multipart"
|
||||
)
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# # Does API work with super user?
|
||||
with self.login(self.super_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.post(
|
||||
reverse("version-files-list"), data=payload, format="multipart"
|
||||
)
|
||||
self.response_201(response)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with version_manager user?
|
||||
with self.login(self.group_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.post(
|
||||
reverse("version-files-list"), data=payload, format="multipart"
|
||||
)
|
||||
self.response_201(response)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
def test_delete(self):
|
||||
url = reverse("version-files-detail", kwargs={"pk": self.version_file1.pk})
|
||||
|
||||
# Does this API work without auth?
|
||||
response = self.client.delete(url, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API wotk with non-staff user?
|
||||
with self.login(self.user):
|
||||
response = self.client.delete(url, format="json")
|
||||
self.response_403(response)
|
||||
|
||||
# Does this API work with super user?
|
||||
with self.login(self.super_user):
|
||||
response = self.client.delete(url, format="json")
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
# Confirm object is gone
|
||||
response = self.get(url)
|
||||
self.response_404(response)
|
||||
|
||||
def test_update(self):
|
||||
url = reverse("version-files-detail", kwargs={"pk": self.version_file2.pk})
|
||||
|
||||
image = Image.new("RGB", (100, 100))
|
||||
|
||||
tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
image.save(tmp_file)
|
||||
|
||||
tmp_file.seek(0)
|
||||
file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
|
||||
file_obj.seek(0)
|
||||
|
||||
payload = {
|
||||
"file": file_obj,
|
||||
}
|
||||
|
||||
# Does API work without auth?
|
||||
response = self.client.post(url, files=payload, format="multipart")
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with normal user?
|
||||
with self.login(self.user):
|
||||
response = self.client.patch(url, data=payload, format="multipart")
|
||||
self.response_403(response)
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with super user?
|
||||
with self.login(self.super_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.patch(url, data=payload, format="multipart")
|
||||
self.response_200(response)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
file_obj.seek(0)
|
||||
# Does API work with version_manager user?
|
||||
with self.login(self.group_user):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
response = self.client.patch(url, data=payload, format="multipart")
|
||||
self.response_200(response)
|
||||
except IntegrityError:
|
||||
pass
|
||||
# class VersionViewTests(TestCase):
|
||||
# client_class = APIClient
|
||||
#
|
||||
# def setUp(self):
|
||||
# self.user = UserFactory()
|
||||
# self.group_user = UserFactory.create(groups=(VersionGroupFactory.create(),))
|
||||
# self.super_user = SuperUserFactory()
|
||||
# self.version_manager = UserFactory()
|
||||
# self.version_file1 = VersionFileFactory()
|
||||
# self.version_file2 = VersionFileFactory()
|
||||
# self.version = VersionFactory.create(
|
||||
# files=(self.version_file1, self.version_file2)
|
||||
# )
|
||||
#
|
||||
# def test_list_version(self):
|
||||
# """
|
||||
# Tests with a regular user
|
||||
# """
|
||||
# # Does API work without auth?
|
||||
# response = self.get("version-files-list")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does API work with auth?
|
||||
# with self.login(self.user):
|
||||
# response = self.get("version-files-list")
|
||||
# self.response_200(response)
|
||||
# self.assertEqual(len(response.data), 2)
|
||||
# self.assertIn("checksum", response.data[0])
|
||||
# self.assertIn("operating_system", response.data[0])
|
||||
#
|
||||
# def test_create(self):
|
||||
# image = Image.new("RGB", (100, 100))
|
||||
#
|
||||
# tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
# image.save(tmp_file)
|
||||
#
|
||||
# tmp_file.seek(0)
|
||||
# file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
#
|
||||
# payload = {"file": file_obj, "operating_system": "Windows"}
|
||||
#
|
||||
# # Does API work without auth?
|
||||
# response = self.client.post(
|
||||
# reverse("version-files-list"), files=payload, format="multipart"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with normal user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.post(
|
||||
# reverse("version-files-list"), data=payload, format="multipart"
|
||||
# )
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # # Does API work with super user?
|
||||
# with self.login(self.super_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.post(
|
||||
# reverse("version-files-list"), data=payload, format="multipart"
|
||||
# )
|
||||
# self.response_201(response)
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with version_manager user?
|
||||
# with self.login(self.group_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.post(
|
||||
# reverse("version-files-list"), data=payload, format="multipart"
|
||||
# )
|
||||
# self.response_201(response)
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
# def test_delete(self):
|
||||
# url = reverse("version-files-detail", kwargs={"pk": self.version_file1.pk})
|
||||
#
|
||||
# # Does this API work without auth?
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API wotk with non-staff user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# # Does this API work with super user?
|
||||
# with self.login(self.super_user):
|
||||
# response = self.client.delete(url, format="json")
|
||||
# self.assertEqual(response.status_code, 204)
|
||||
#
|
||||
# # Confirm object is gone
|
||||
# response = self.get(url)
|
||||
# self.response_404(response)
|
||||
#
|
||||
# def test_update(self):
|
||||
# url = reverse("version-files-detail", kwargs={"pk": self.version_file2.pk})
|
||||
#
|
||||
# image = Image.new("RGB", (100, 100))
|
||||
#
|
||||
# tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg")
|
||||
# image.save(tmp_file)
|
||||
#
|
||||
# tmp_file.seek(0)
|
||||
# file_obj = DjangoFile(open(tmp_file.name, mode="rb"), name="tmp_file")
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
#
|
||||
# payload = {
|
||||
# "file": file_obj,
|
||||
# }
|
||||
#
|
||||
# # Does API work without auth?
|
||||
# response = self.client.post(url, files=payload, format="multipart")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with normal user?
|
||||
# with self.login(self.user):
|
||||
# response = self.client.patch(url, data=payload, format="multipart")
|
||||
# self.response_403(response)
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with super user?
|
||||
# with self.login(self.super_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.patch(url, data=payload, format="multipart")
|
||||
# self.response_200(response)
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
#
|
||||
# file_obj.seek(0)
|
||||
# # Does API work with version_manager user?
|
||||
# with self.login(self.group_user):
|
||||
# try:
|
||||
# with transaction.atomic():
|
||||
# response = self.client.patch(url, data=payload, format="multipart")
|
||||
# self.response_200(response)
|
||||
# except IntegrityError:
|
||||
# pass
|
||||
##
|
||||
|
||||
7
versions/tests/test_views.py
Normal file
7
versions/tests/test_views.py
Normal file
@@ -0,0 +1,7 @@
|
||||
def test_version_list(version, tp):
|
||||
res = tp.get("version-list")
|
||||
tp.response_200(res)
|
||||
print(res.context)
|
||||
objs = res.context["version_list"]
|
||||
assert len(objs) == 1
|
||||
assert version in objs
|
||||
@@ -1,21 +1,19 @@
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import permissions
|
||||
from versions.permissions import SuperUserOrVersionManager
|
||||
from django.views.generic import ListView, DetailView
|
||||
|
||||
from versions.models import Version, VersionFile
|
||||
from versions.serializers import VersionSerializer, VersionFileSerializer
|
||||
|
||||
|
||||
class VersionViewSet(viewsets.ModelViewSet):
|
||||
class VersionList(ListView):
|
||||
"""Web display of list of Versions"""
|
||||
|
||||
model = Version
|
||||
queryset = Version.objects.all()
|
||||
serializer_class = VersionSerializer
|
||||
permission_classes = [permissions.IsAuthenticated, SuperUserOrVersionManager]
|
||||
queryset = Version.objects.active()
|
||||
template_name = "versions/list.html"
|
||||
|
||||
|
||||
class VersionFileViewSet(viewsets.ModelViewSet):
|
||||
model = VersionFile
|
||||
queryset = VersionFile.objects.all()
|
||||
serializer_class = VersionFileSerializer
|
||||
permission_classes = [permissions.IsAuthenticated, SuperUserOrVersionManager]
|
||||
class VersionDetail(DetailView):
|
||||
"""Web display of list of Versions"""
|
||||
|
||||
model = Version
|
||||
queryset = Version.objects.active()
|
||||
template_name = "versions/detail.html"
|
||||
|
||||
Reference in New Issue
Block a user