94 lines
3.9 KiB
Python
94 lines
3.9 KiB
Python
from dataclasses import dataclass
|
|
from unittest.case import skipIf
|
|
from unittest import mock
|
|
|
|
from django.db.models import F
|
|
from django.test.testcases import TestCase
|
|
from django.test.utils import tag
|
|
|
|
from django_records.adjuncts import MutValue, FixedValue, PostProcess
|
|
from django_records.handlers import RecordDictHandler
|
|
|
|
|
|
try:
|
|
from .models import Celestial
|
|
from .galaxy import Stars
|
|
celestials_installed = True
|
|
except RuntimeError:
|
|
celestials_installed = False
|
|
|
|
|
|
@dataclass
|
|
class Entity:
|
|
id: int
|
|
|
|
|
|
@dataclass
|
|
class SpaceRock:
|
|
id: int
|
|
name: str
|
|
orbits_name: str
|
|
is_moon: bool
|
|
|
|
|
|
@tag('library')
|
|
@skipIf(not celestials_installed, "Celestials Testpackage not installed into INSTALLED_APPS.")
|
|
class TestQueryBuilder(TestCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
Stars.create_sol(context=self)
|
|
|
|
def test_records(self):
|
|
entities = Celestial.objects.filter(orbits__name='Sol', celestial_type__lte=4).records(Entity)
|
|
self.assertEqual(len(entities), len(self.planets))
|
|
|
|
# test whether we really return dataclass as result, even with first.
|
|
self.assertIsInstance(entities.first(), Entity)
|
|
|
|
# find moons. test whether i can use entities to do an SQL query. works because i have only one key.
|
|
self.assertEqual(len(self.moons), Celestial.objects.filter(orbits__in=entities).count())
|
|
|
|
# this is pretty much the same as
|
|
self.assertEqual(len(self.moons), len(Celestial.objects.filter(
|
|
orbits__in=Celestial.objects.filter(orbits__name='Sol', celestial_type__lte=4)).values_list('id', flat=True)))
|
|
|
|
def test_handler_dict(self):
|
|
entities = Celestial.objects.filter(orbits__name='Sol', celestial_type__lte=4).records(RecordDictHandler())
|
|
self.assertEqual(len(entities), len(self.planets))
|
|
self.assertIsInstance(entities.first(), dict)
|
|
|
|
def test_MutValue(self):
|
|
|
|
# this tests whether our own celestial type or the celestial type of what we orbit is correct for being a moon. parameter is a dictionary.
|
|
is_moon = lambda entry: True if 5 > (entry.get('celestial_type') or 0) > 1 and 5 > (entry.get('orbits_type') or 0) > 1 else False
|
|
|
|
entities = Celestial.objects.records(SpaceRock, # we want our output to be a SpaceRock dataclass.
|
|
'celestial_type', # we include the key celestial_type into our query.
|
|
id=FixedValue(None), # we blank out id to test FixedValue working.
|
|
orbits_name=F('orbits__name'), # we set our custom orbits_name to a related field value
|
|
orbits_type=F('orbits__celestial_type'), # our MutValue needs this data.
|
|
is_moon=MutValue(is_moon)) # MutValue over result
|
|
|
|
self.assertEqual(len(entities), len(self.celestials))
|
|
|
|
for idx, entity in enumerate(entities):
|
|
dbdata = self.celestials[idx]
|
|
model = Celestial.objects.filter(id=dbdata.id).first()
|
|
self.assertEqual(entity.name, dbdata.name)
|
|
self.assertIsNone(entity.id)
|
|
self.assertEqual(entity.is_moon, model.is_moon)
|
|
|
|
def test_post_process(self):
|
|
side_effect = lambda x:x
|
|
post_process_one = mock.Mock(side_effect=side_effect)
|
|
post_process_two = mock.Mock(side_effect=side_effect)
|
|
|
|
entities = Celestial.objects.all().records(Entity,
|
|
post_process_one=PostProcess(post_process_one),
|
|
post_process_two=PostProcess(post_process_two))
|
|
|
|
self.assertEqual(len(entities), len(self.celestials))
|
|
self.assertEqual(post_process_one.call_count, len(self.celestials))
|
|
self.assertEqual(post_process_two.call_count, len(self.celestials))
|