Source code for app_utils.testdata_factories

"""This module provides factories for generating test objects from Django and AA Models.

Important: You need to add the dependency ``factory_boy`` to your test environment.
"""

from typing import Generic, TypeVar

import factory
import factory.fuzzy

from django.contrib.auth import get_user_model
from django.db.models import Max

from allianceauth.eveonline.models import (
    EveAllianceInfo,
    EveCharacter,
    EveCorporationInfo,
)
from allianceauth.tests.auth_utils import AuthUtils

from .testing import add_character_to_user

T = TypeVar("T")
User = get_user_model()


[docs] class BaseMetaFactory(Generic[T], factory.base.FactoryMetaClass): def __call__(cls, *args, **kwargs) -> T: return super().__call__(*args, **kwargs)
# django
[docs] class UserFactory(factory.django.DjangoModelFactory, metaclass=BaseMetaFactory[User]): """Generate a User object. Args: permissions: List of permission names (optional), e.g. ``["moonmining.basic_access"]`` """ class Meta: model = User django_get_or_create = ("username",) exclude = ("_generated_name",) _generated_name = factory.Faker("name") username = factory.LazyAttribute(lambda obj: obj._generated_name.replace(" ", "_")) first_name = factory.LazyAttribute(lambda obj: obj._generated_name.split(" ")[0]) last_name = factory.LazyAttribute(lambda obj: obj._generated_name.split(" ")[1]) email = factory.LazyAttribute( lambda obj: f"{obj.first_name.lower()}.{obj.last_name.lower()}@example.com" ) @factory.post_generation def permissions(obj, create, extracted, **kwargs): """Set default permissions. Overwrite with `permissions=["app.perm1"]`.""" if not create: return permissions = extracted or [] for permission_name in permissions: AuthUtils.add_permission_to_user_by_name(permission_name, obj) @classmethod def _after_postgeneration(cls, obj, create, results=None): """Reset permission cache to force an update.""" super()._after_postgeneration(obj, create, results) if hasattr(obj, "_perm_cache"): del obj._perm_cache if hasattr(obj, "_user_perm_cache"): del obj._user_perm_cache
# auth
[docs] class EveAllianceInfoFactory( factory.django.DjangoModelFactory, metaclass=BaseMetaFactory[EveAllianceInfo] ): """Generate an EveAllianceInfo object.""" class Meta: model = EveAllianceInfo django_get_or_create = ("alliance_id", "alliance_name") alliance_name = factory.Faker("catch_phrase") alliance_ticker = factory.LazyAttribute(lambda obj: obj.alliance_name[:4].upper()) executor_corp_id = 0 @factory.lazy_attribute def alliance_id(self): last_id = ( EveAllianceInfo.objects.aggregate(Max("alliance_id"))["alliance_id__max"] or 99_000_000 ) return last_id + 1
[docs] class EveCorporationInfoFactory( factory.django.DjangoModelFactory, metaclass=BaseMetaFactory[EveCorporationInfo] ): """Generate an EveCorporationInfo object.""" class Meta: model = EveCorporationInfo django_get_or_create = ("corporation_id", "corporation_name") corporation_name = factory.Faker("catch_phrase") corporation_ticker = factory.LazyAttribute( lambda obj: obj.corporation_name[:4].upper() ) member_count = factory.fuzzy.FuzzyInteger(1000) @factory.lazy_attribute def corporation_id(self): last_id = ( EveCorporationInfo.objects.aggregate(Max("corporation_id"))[ "corporation_id__max" ] or 98_000_000 ) return last_id + 1 @factory.post_generation def create_alliance(obj, create, extracted, **kwargs): if not create or extracted is False or obj.alliance: return obj.alliance = EveAllianceInfoFactory(executor_corp_id=obj.corporation_id)
[docs] class EveCharacterFactory( factory.django.DjangoModelFactory, metaclass=BaseMetaFactory[EveCharacter] ): """Generate an EveCharacter object.""" class Meta: model = EveCharacter django_get_or_create = ("character_id", "character_name") exclude = ("corporation",) character_name = factory.Faker("name") corporation = factory.SubFactory(EveCorporationInfoFactory) corporation_id = factory.LazyAttribute(lambda obj: obj.corporation.corporation_id) corporation_name = factory.LazyAttribute( lambda obj: obj.corporation.corporation_name ) corporation_ticker = factory.LazyAttribute( lambda obj: obj.corporation.corporation_ticker ) @factory.lazy_attribute def character_id(self): last_id = ( EveCharacter.objects.aggregate(Max("character_id"))["character_id__max"] or 90_000_000 ) return last_id + 1 @factory.lazy_attribute def alliance_id(self): return ( self.corporation.alliance.alliance_id if self.corporation.alliance else None ) @factory.lazy_attribute def alliance_name(self): return ( self.corporation.alliance.alliance_name if self.corporation.alliance else "" ) @factory.lazy_attribute def alliance_ticker(self): return ( self.corporation.alliance.alliance_ticker if self.corporation.alliance else "" )
[docs] class UserMainFactory(UserFactory): """Generate a User object with main character. Args: main_character__character: EveCharacter object to be used as main (optional) main_character__scopes: List of ESI scope names (optional), e.g. ``["esi-characters.read_contacts.v1"]`` """ @factory.post_generation def main_character(obj, create, _extracted, **kwargs): if not create: return if "character" in kwargs: # TODO: maybe use extracted directly here? character = kwargs["character"] else: character_name = f"{obj.first_name} {obj.last_name}" character = EveCharacterFactory(character_name=character_name) scopes = kwargs.get("scopes", None) add_character_to_user( user=obj, character=character, is_main=True, scopes=scopes )