Skip to content

Commit

Permalink
Add test for document and page API filters
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanw committed Oct 31, 2022
1 parent 8929369 commit 89313b0
Show file tree
Hide file tree
Showing 5 changed files with 658 additions and 4 deletions.
28 changes: 25 additions & 3 deletions filingcabinet/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ class PageDocumentFilterset(filters.FilterSet):
to_field_name="pk",
method="filter_collection",
)
directory = filters.ModelChoiceFilter(
queryset=(CollectionDirectory.objects.all().select_related("collection")),
null_label="",
null_value=NULL_VALUE,
method="filter_directory",
)
portal = filters.ModelChoiceFilter(
queryset=DocumentPortal.objects.filter(public=True),
to_field_name="pk",
Expand All @@ -141,8 +147,10 @@ class PageDocumentFilterset(filters.FilterSet):
to_field_name="pk",
method="filter_document",
)
number = filters.NumberFilter(
method="filter_number",
number = filters.NumberFilter(field_name="number", lookup_expr="exact")

created_at = filters.DateFromToRangeFilter(
method="filter_created_at",
)

class Meta:
Expand Down Expand Up @@ -173,10 +181,21 @@ def filter_tag(self, qs, name, value):
def filter_collection(self, qs, name, collection):
if not collection.can_read(self.request):
return qs.none()
qs = qs.filter(document__collections=collection)
qs = qs.filter(document__in=collection.documents.all())
qs = self.apply_data_filters(qs, collection.settings.get("filters", []))
return qs

def filter_directory(self, qs, name, directory):
if NULL_VALUE == directory:
return qs.filter(
document__filingcabinet_collectiondocument__directory__isnull=True
)
if not directory.collection.can_read(self.request):
return qs.none()
return qs.filter(
document__filingcabinet_collectiondocument__directory=directory
).order_by("document__filingcabinet_collectiondocument__order")

def filter_document(self, qs, name, value):
if not value.can_read(self.request):
return qs.none()
Expand All @@ -187,6 +206,9 @@ def filter_portal(self, qs, name, portal):
qs = self.apply_data_filters(qs, portal.settings.get("filters", []))
return qs

def filter_number(self, qs, name, value):
return qs.filter(number=value)

def apply_data_filters(self, qs, filters):
for filt in filters:
if not filt["key"].startswith("data."):
Expand Down
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from pytest_factoryboy import register

from .factories import (
CollectionDirectoryFactory,
DocumentCollectionFactory,
DocumentFactory,
DocumentPortalFactory,
PageFactory,
UserFactory,
)
Expand All @@ -14,6 +16,8 @@
register(DocumentFactory)
register(DocumentCollectionFactory)
register(PageFactory)
register(CollectionDirectoryFactory)
register(DocumentPortalFactory)

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

Expand Down
19 changes: 18 additions & 1 deletion tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import factory

from filingcabinet import get_document_model, get_documentcollection_model
from filingcabinet.models import Page
from filingcabinet.models import CollectionDirectory, DocumentPortal, Page

Document = get_document_model()
DocumentCollection = get_documentcollection_model()
Expand Down Expand Up @@ -38,3 +38,20 @@ class Meta:
title = factory.Sequence(lambda n: "DocumentCollection {}".format(n))
slug = factory.LazyAttribute(lambda o: slugify(o.title))
user = factory.SubFactory(UserFactory)


class CollectionDirectoryFactory(factory.django.DjangoModelFactory):
class Meta:
model = CollectionDirectory

collection = factory.SubFactory(DocumentCollectionFactory)
name = factory.Sequence(lambda n: "CollectionDirectory {}".format(n))
depth = 0


class DocumentPortalFactory(factory.django.DjangoModelFactory):
class Meta:
model = DocumentPortal

title = factory.Sequence(lambda n: "DocumentPortal {}".format(n))
slug = factory.LazyAttribute(lambda o: slugify(o.title))
250 changes: 250 additions & 0 deletions tests/test_document_api_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
from datetime import datetime, timedelta, timezone

import pytest

from filingcabinet.models import CollectionDocument


@pytest.mark.django_db
def test_document_api(client, document_factory):
document_factory.create_batch(10, public=True)
response = client.get("/api/document/")
assert response.status_code == 200
assert len(response.json()["objects"]) == 10


@pytest.mark.django_db
def test_document_api_filter_collection_directory(
client,
document_factory,
document_collection_factory,
collection_directory_factory,
dummy_user,
):
collection = document_collection_factory.create(user=dummy_user)
collection_dir = collection_directory_factory.create(
collection=collection, user=dummy_user
)

document_factory.create_batch(5, public=True, user=dummy_user)

# Put some documents in collection, first in directory
documents = document_factory.create_batch(10, public=True, user=dummy_user)
CollectionDocument.objects.create(
collection=collection,
document=documents[0],
directory=collection_dir,
)
collection.documents.add(*documents[1:])

response = client.get("/api/document/?collection={}".format(collection.pk))
assert response.status_code == 200
data = response.json()
assert len(data["objects"]) == 10

response = client.get(
"/api/document/?collection={}&directory=-".format(collection.pk)
)
assert response.status_code == 200
data = response.json()
assert len(data["objects"]) == 9
assert documents[0].id not in {d["id"] for d in data["objects"]}

response = client.get(
"/api/document/?collection={}&directory={}".format(
collection.pk, collection_dir.pk
)
)
assert response.status_code == 200
data = response.json()
assert len(data["objects"]) == 1
assert data["objects"][0]["id"] == documents[0].pk

collection.public = False
collection.save()

response = client.get("/api/document/?collection={}".format(collection.pk))
data = response.json()
assert len(data["objects"]) == 0

response = client.get("/api/document/?directory={}".format(collection_dir.pk))
data = response.json()
assert len(data["objects"]) == 0

# Login as user
client.force_login(dummy_user)

response = client.get("/api/document/?collection={}".format(collection.pk))
data = response.json()
assert len(data["objects"]) == 10

response = client.get("/api/document/?directory={}".format(collection_dir.pk))
data = response.json()
assert len(data["objects"]) == 1


@pytest.mark.django_db
def test_document_api_filter_id(
client,
document_factory,
):

documents = document_factory.create_batch(5, public=True)

response = client.get(
"/api/document/?ids={},{}".format(documents[0].pk, documents[1].pk)
)
data = response.json()
assert len(data["objects"]) == 2
assert documents[0].id in {d["id"] for d in data["objects"]}
assert documents[1].id in {d["id"] for d in data["objects"]}

# Filter is ignored on bad input
response = client.get(
"/api/document/?ids={},{},a".format(documents[0].pk, documents[1].pk)
)
data = response.json()
assert len(data["objects"]) == 5


@pytest.mark.django_db
def test_document_api_filter_portal(client, document_factory, document_portal_factory):
portal = document_portal_factory.create(public=False)
document_factory.create_batch(5, public=True, portal=portal)

response = client.get("/api/document/?portal={}".format(portal.pk))
assert response.status_code == 400

portal.public = True
portal.save()

response = client.get("/api/document/?portal={}".format(portal.pk))
data = response.json()
assert response.status_code == 200
assert len(data["objects"]) == 5


@pytest.mark.django_db
def test_document_api_filter_data_filters(
client, document_factory, document_portal_factory
):
publisher_value = "wd1"
portal = document_portal_factory.create(
public=True,
settings={
"filters": [
{
"id": "publisher",
"key": "data.publisher",
"type": "choice",
"facet": False,
"label": {"en": "publisher"},
"choices": [
{"label": {"en": "Some Label"}, "value": publisher_value},
],
},
{
"id": "index",
"key": "data.index",
"type": "choice",
"datatype": "int",
"label": {"en": "index"},
"choices": [],
},
{
"id": "date",
"key": "created_at",
"type": "daterange",
"label": {"en": "date"},
},
]
},
)
documents = document_factory.create_batch(5, public=True, portal=portal)
documents[0].data["publisher"] = "wd1"
documents[0].data["index"] = 42
documents[0].save()

documents[1].data["publisher"] = "wd1"
documents[1].data["index"] = 23
documents[1].save()

response = client.get("/api/document/?portal={}&data.publisher=".format(portal.pk))
data = response.json()
assert response.status_code == 200
assert len(data["objects"]) == 5

response = client.get(
"/api/document/?portal={}&data.publisher={}".format(portal.pk, publisher_value)
)
data = response.json()
assert response.status_code == 200
assert len(data["objects"]) == 2
assert data["objects"][0]["id"] == documents[0].pk

response = client.get(
"/api/document/?portal={}&data.publisher={}&data.index={}".format(
portal.pk, publisher_value, "a"
)
)
data = response.json()
assert response.status_code == 200
assert len(data["objects"]) == 2
assert data["objects"][0]["id"] == documents[0].pk

response = client.get(
"/api/document/?portal={}&data.publisher={}&data.index={}".format(
portal.pk, publisher_value, 42
)
)
data = response.json()
assert response.status_code == 200
assert len(data["objects"]) == 1
assert data["objects"][0]["id"] == documents[0].pk


@pytest.mark.django_db
def test_document_api_filter_tags(
client,
document_factory,
):

documents = document_factory.create_batch(5, public=True)
documents[0].tags.add("tag1")

response = client.get("/api/document/?tag=tag1")
data = response.json()
assert len(data["objects"]) == 1
assert documents[0].id in {d["id"] for d in data["objects"]}


@pytest.mark.django_db
def test_document_api_filter_created_at(
client,
document_factory,
):

week = timedelta(days=7)
date = datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
documents = document_factory.create_batch(5, public=True, created_at=date)
documents[0].created_at = date + week
documents[0].save()
documents[1].published_at = date + week
documents[1].save()

query_date_after = (date + timedelta(days=3)).date().isoformat()

response = client.get("/api/document/?created_at_after={}".format(query_date_after))
data = response.json()
assert len(data["objects"]) == 2
ids = {d["id"] for d in data["objects"]}
assert documents[0].id in ids
assert documents[1].id in ids

response = client.get(
"/api/document/?created_at_before={}".format(query_date_after)
)
data = response.json()
assert len(data["objects"]) == 3
ids = {d["id"] for d in data["objects"]}
assert {documents[2].id, documents[3].id, documents[4].id} == ids
Loading

0 comments on commit 89313b0

Please sign in to comment.