Skip to content

Commit

Permalink
refactor folder unittests out of demoapp
Browse files Browse the repository at this point in the history
  • Loading branch information
jrief committed Jan 9, 2025
1 parent 7c1580f commit d530fa9
Show file tree
Hide file tree
Showing 12 changed files with 418 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,22 @@ jobs:
matrix:
python-version: ["3.11", "3.12"]
django-version: ["5.2.*"]
node-version: ["18.x"]
with-cte: [true, false]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
npm install --include=dev
python -m pip install --upgrade pip
python -m pip install https://github.com/django/django/archive/refs/heads/main.zip
python -m pip install django-cte django-entangled ffmpeg-python pillow reportlab svglib
python -m pip install django-entangled ffmpeg-python pillow reportlab svglib
python -m pip install beautifulsoup4 coverage Faker lxml pytest pytest-django pytest-cov
- name: Build Client
run: |
npm run compilescss
npm run esbuild
- if: ${{ matrix.with-cte }}
run: python -m pip install django-cte
- name: Test with pytest
run: |
python -m pytest -v demoapp/unittests
python -m pytest -v unittests
153 changes: 0 additions & 153 deletions demoapp/unittests/test_folder_admin.py

This file was deleted.

48 changes: 24 additions & 24 deletions finder/admin/folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.db.models import QuerySet, Subquery

from django.forms.widgets import Media
from django.http.response import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound, JsonResponse
from django.http.response import HttpResponse, HttpResponseNotAllowed, HttpResponseNotFound, JsonResponse
from django.templatetags.static import static
from django.urls import path, reverse
from django.utils.translation import gettext
Expand Down Expand Up @@ -175,8 +175,12 @@ def get_model_admin(self, mime_type):
return self._model_admin_cache[mime_type]

def fetch_inodes(self, request, folder_id):
if not (current_folder := self.get_object(request, folder_id)):
return HttpResponseNotFound(f"Folder {folder_id} not found.")
if request.method != 'GET':
return HttpResponseNotAllowed(f"Method {request.method} not allowed. Only GET requests are allowed.")
try:
current_folder = self.get_object(request, folder_id)
except ObjectDoesNotExist:
return HttpResponseNotFound(f"FolderModel<{folder_id}> not found.")
if search_query := request.GET.get('q'):
inode_qs = self.search_for_inodes(request, current_folder, search_query)
else:
Expand Down Expand Up @@ -204,11 +208,13 @@ def search_for_inodes(self, request, current_folder, search_query, **lookup):

def upload_file(self, request, folder_id):
if request.method != 'POST':
return HttpResponseBadRequest(f"Method {request.method} not allowed. Only POST requests are allowed.")
if not (folder := self.get_object(request, folder_id)):
return HttpResponseNotFound(f"Folder {folder_id} not found.")
return HttpResponseNotAllowed(f"Method {request.method} not allowed. Only POST requests are allowed.")
try:
folder = self.get_object(request, folder_id)
except ObjectDoesNotExist:
return HttpResponseNotFound(f"FolderModel<{folder_id}> not found.")
if request.content_type != 'multipart/form-data' or 'upload_file' not in request.FILES:
return HttpResponseBadRequest("Bad encoding type or missing payload.")
return HttpResponse("Bad encoding type or missing payload.", status=415)
model = FileModel.objects.get_model_for(request.FILES['upload_file'].content_type)
new_file = model.objects.create_from_upload(
request.FILES['upload_file'],
Expand All @@ -223,33 +229,27 @@ def update_inode(self, request, folder_id):
body = json.loads(request.body)
try:
obj = self.get_object(request, body['id'])
except (InodeModel.DoesNotExist, KeyError):
return HttpResponseNotFound(f"Inode(id={body.get('id', '<missing>')}) not found.")
except (ObjectDoesNotExist, KeyError):
return HttpResponseNotFound(f"InodeModel<id={body.get('id', '<missing>')}> not found.")
current_folder = self.get_object(request, folder_id)
inode_name = body['name']
try:
filename_validator(inode_name)
except ValidationError as exc:
return HttpResponseBadRequest(exc.messages[0], status=409)
return HttpResponse(exc.messages[0], status=409)
if current_folder.listdir(name=inode_name, is_folder=True).exists():
msg = gettext("A folder named “{name}” already exists.")
return HttpResponseBadRequest(msg.format(name=inode_name), status=409)
return HttpResponse(msg.format(name=inode_name), status=409)
update_values = {}
for field in self.get_fields(request, obj):
if field in body and body[field] != getattr(obj, field):
setattr(obj, field, body[field])
update_values[field] = body[field]
if update_values:
obj.save(update_fields=list(update_values.keys()))
favorite_folders = self.get_favorite_folders(request, current_folder)
if update_values:
for folder in favorite_folders:
if folder['id'] == obj.id:
folder.update(update_values)
break
return JsonResponse({
'new_inode': self.serialize_inode(obj),
'favorite_folders': favorite_folders,
'favorite_folders': self.get_favorite_folders(request, current_folder),
})

def copy_inodes(self, request, folder_id):
Expand All @@ -263,7 +263,7 @@ def copy_inodes(self, request, folder_id):
try:
inode.copy_to(current_folder, owner=request.user)
except RecursionError as exc:
return HttpResponseBadRequest(str(exc), status=409)
return HttpResponse(str(exc), status=409)
return JsonResponse({
'inodes': list(self.get_inodes(request, parent=current_folder)),
})
Expand Down Expand Up @@ -291,7 +291,7 @@ def move_inodes(self, request, folder_id):
proxy_obj.validate_constraints()
proxy_obj._meta.model.objects.filter(id=entry['id']).update(parent=target_folder)
except ValidationError as exc:
return HttpResponseBadRequest(exc.messages[0], status=409)
return HttpResponse(exc.messages[0], status=409)
return JsonResponse({
'inodes': list(self.get_inodes(request, parent=target_folder)),
})
Expand All @@ -303,7 +303,7 @@ def delete_inodes(self, request, folder_id):
current_folder = self.get_object(request, folder_id)
trash_folder = self.get_trash_folder(request)
if current_folder.id == trash_folder.id:
return HttpResponseBadRequest("Cannot move inodes from trash folder into itself.")
return HttpResponse("Cannot move inodes from trash folder into itself.", status=409)
inode_ids = body.get('inode_ids', [])
for entry in FolderModel.objects.filter_unified(id__in=inode_ids):
inode = FolderModel.objects.get_inode(id=entry['id'])
Expand All @@ -324,7 +324,7 @@ def delete_inodes(self, request, folder_id):

def undo_discarded_inodes(self, request):
if request.method != 'POST':
return HttpResponseBadRequest(f"Method {request.method} not allowed. Only POST requests are allowed.")
return HttpResponseNotAllowed(f"Method {request.method} not allowed. Only POST requests are allowed.")
body = json.loads(request.body)
trash_folder = self.get_trash_folder(request)
discarded_inodes = DiscardedInode.objects.filter(inode__in=body.get('inode_ids', []))
Expand All @@ -337,7 +337,7 @@ def undo_discarded_inodes(self, request):

def erase_trash_folder(self, request):
if request.method != 'DELETE':
return HttpResponseBadRequest(f"Method {request.method} not allowed. Only DELETE requests are allowed.")
return HttpResponseNotAllowed(f"Method {request.method} not allowed. Only DELETE requests are allowed.")
trash_folder_entries = self.get_trash_folder(request).listdir()
DiscardedInode.objects.filter(inode__in=list(trash_folder_entries.values_list('id', flat=True))).delete()
for entry in trash_folder_entries:
Expand All @@ -360,7 +360,7 @@ def add_folder(self, request, folder_id):
body = json.loads(request.body)
if parent_folder.listdir(name=body['name'], is_folder=True).exists():
msg = gettext("A folder named “{name}” already exists.")
return HttpResponseBadRequest(msg.format(name=body['name']), status=409)
return HttpResponse(msg.format(name=body['name']), status=409)
new_folder = FolderModel.objects.create(
name=body['name'],
parent=parent_folder,
Expand Down
18 changes: 14 additions & 4 deletions finder/admin/inode.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import json

from django.core.exceptions import ObjectDoesNotExist

from django.contrib import admin
from django.contrib.sites.shortcuts import get_current_site
from django.db.models.expressions import F, Value
from django.db.models.fields import BooleanField
from django.http.response import HttpResponseBadRequest, HttpResponseNotFound, HttpResponseRedirect, JsonResponse
from django.http.response import (
HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, HttpResponseNotFound, HttpResponseRedirect,
JsonResponse,
)
from django.middleware.csrf import get_token
from django.template.response import TemplateResponse
from django.urls import path, reverse
Expand Down Expand Up @@ -32,10 +37,15 @@ def get_object(self, request, inode_id, *args):

def check_for_valid_post_request(self, request, folder_id):
if request.method != 'POST':
return HttpResponseBadRequest(f"Method {request.method} not allowed. Only POST requests are allowed.")
return HttpResponseNotAllowed(f"Method {request.method} not allowed. Only POST requests are allowed.")
if request.content_type != 'application/json':
return HttpResponseBadRequest(f"Invalid content-type {request.content_type}. Only application/json is allowed.")
if self.get_object(request, folder_id) is None:
return HttpResponse(
f"Invalid content-type {request.content_type}. Only application/json is allowed.",
status=415,
)
try:
self.get_object(request, folder_id)
except ObjectDoesNotExist:
return HttpResponseNotFound(f"Folder with id “{folder_id}” not found.")

def toggle_pin(self, request, folder_id):
Expand Down
2 changes: 1 addition & 1 deletion demoapp/pytest.ini → pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[pytest]
DJANGO_SETTINGS_MODULE = demoapp.settings
DJANGO_SETTINGS_MODULE = unittests.settings
django_find_project = false
addopts = --tb=native
File renamed without changes.
8 changes: 3 additions & 5 deletions demoapp/unittests/conftest.py → unittests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@
from django.contrib.admin.sites import site as admin_site
from django.urls import reverse

from finder.models.realm import RealmModel
from finder.models.folder import FolderModel

from ..utils import create_random_image
from .utils import create_random_image

os.environ.setdefault('DJANGO_ALLOW_ASYNC_UNSAFE', 'true')


@pytest.fixture(autouse=True, scope='session')
def create_assets():
os.makedirs(settings.BASE_DIR / 'workdir/assets', exist_ok=True)
for counter in range(10):
image = create_random_image()
image.save(settings.BASE_DIR / 'workdir/assets' / f'image_{counter:01d}.png')
image = create_random_image()
image.save(settings.BASE_DIR / 'workdir/assets' / f'demo_image.png')

Check failure on line 20 in unittests/conftest.py

View workflow job for this annotation

GitHub Actions / flake8

f-string is missing placeholders


@pytest.fixture(scope='session')
Expand Down
File renamed without changes.
Loading

0 comments on commit d530fa9

Please sign in to comment.