Skip to content

Commit

Permalink
- More tests
Browse files Browse the repository at this point in the history
- Added Event test factory
  • Loading branch information
onstabb committed Nov 17, 2023
1 parent 3e11b4e commit cd41452
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/candidates/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ def get_candidates(user: User, limit: int = 1) -> list[dict]:
{"age_difference":
{"$abs":
{"$dateDiff":
{"endDate": "$profile.birthday",
{"endDate": "$profile.birthdate",

"startDate": datetime(
user.profile.birthday.year, user.profile.birthday.month, user.profile.birthday.day
user.profile.birthdate.year, user.profile.birthdate.month, user.profile.birthdate.day
),
"unit": "year",
},
Expand Down
2 changes: 1 addition & 1 deletion src/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def init_db(**configuration) -> MongoClient:

Contact.register_delete_rule(User, 'initiator', mongoengine.DENY)
Contact.register_delete_rule(User, 'respondent', mongoengine.DENY)

# User.register_delete_rule(Contact, "contacts", mongoengine.CASCADE)

Event.register_delete_rule(User, 'subscribers', mongoengine.PULL)
User.register_delete_rule(Event, 'events', mongoengine.PULL)
Expand Down
4 changes: 2 additions & 2 deletions src/events/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from mongoengine import StringField, ListField, ReferenceField, DateTimeField

from location.models import LocationWithAddressMixin
from location.models import LocationMixin
from models import BaseDocument


class Event(BaseDocument, LocationWithAddressMixin):
class Event(BaseDocument, LocationMixin):
title = StringField(required=True) # type: str
description = StringField(required=True) # type: str

Expand Down
8 changes: 4 additions & 4 deletions src/events/routers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from fastapi import APIRouter, HTTPException, status
from fastapi import APIRouter, HTTPException, status, Query

from datehelpers import get_aware_datetime_now
from events import service
Expand All @@ -12,13 +12,13 @@


@router.get("", response_model=list[EventOut])
def get_actual_events(city_id: int):
return service.get_actual_events_in_city(city_id)
def get_events(city_id: int, only_future: bool = Query(alias="onlyFuture", default=True)):
return service.get_events_by_city_id(city_id, only_future=only_future)


@router.patch("/{event_id}", response_model=EventOut)
def accept_subscriber(event_id: PydanticObjectId, current_user: CurrentActiveCompletedUser):
event = service.get_event(event_id)
event = service.get_event_by_id(event_id)
if not event:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Event not found")

Expand Down
7 changes: 4 additions & 3 deletions src/events/schemas.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from pydantic import BaseModel, HttpUrl, AwareDatetime
from datetime import datetime

from pydantic import BaseModel, HttpUrl

from location.geopoint import GeoPoint


class EventLocationOut(BaseModel):
city_id: int
city: GeoPoint
current: GeoPoint
address: str

Expand All @@ -15,4 +16,4 @@ class EventOut(BaseModel):
description: str
location: EventLocationOut
image_urls: list[HttpUrl]
start_at: AwareDatetime
start_at: datetime
12 changes: 8 additions & 4 deletions src/events/service.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from bson import ObjectId

from datehelpers import get_aware_datetime_now
from events.models import Event
from models import PydanticObjectId
from users.models import User


def get_actual_events_in_city(city_id: int) -> list[Event]:
result = Event.objects(city_id=city_id, start_at__gt=get_aware_datetime_now())
def get_events_by_city_id(city_id: int, **filters) -> list[Event]:
if filters.pop("only_future", None):
filters.update(start_at__gt=get_aware_datetime_now())

result = Event.objects(location__city_id=city_id, **filters).exclude("subscribers")
return list(result)


Expand All @@ -21,5 +25,5 @@ def accept_subscriber(event: Event, user: User) -> Event:
return event


def get_event(event_id: PydanticObjectId | str) -> Event | None:
def get_event_by_id(event_id: ObjectId | str) -> Event | None:
return Event.get_one(id=event_id)
10 changes: 1 addition & 9 deletions src/location/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,13 @@ class Location(EmbeddedDocument):

city_id = IntField() # type: int
current = PointField(auto_index=False) # type: GeoPoint
address = StringField(null=True)

@property
def current_geo_json(self) -> MongoGeoPoint:
if isinstance(self.current, dict):
return self.current
return {"type": "Point", "coordinates": self.current}


class LocationWithAddress(Location):
address = StringField(required=True) # type: str


class LocationMixin:
location = EmbeddedDocumentField(Location, required=True, default=Location) # type: Location


class LocationWithAddressMixin:
location = EmbeddedDocumentField(LocationWithAddress, required=True, default=LocationWithAddress) # type: LocationWithAddress
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__all__ = ('DateOfBirth', 'Age')
__all__ = ('BirthDate', 'Age')

from datetime import date, datetime
from typing import Annotated
Expand All @@ -8,7 +8,7 @@
from userprofile import config


def validate_date_of_birth(value: date) -> date:
def validate_birthdate(value: date) -> date:
today: date = date.today()
year: int = value.year
if not value.replace(year=year + config.MIN_AGE) <= today <= value.replace(year=year + config.MAX_AGE):
Expand All @@ -23,5 +23,5 @@ def validate_age(value: int | date) -> int:
return value


DateOfBirth = Annotated[PastDate, AfterValidator(validate_date_of_birth)]
BirthDate = Annotated[PastDate, AfterValidator(validate_birthdate)]
Age = Annotated[PositiveInt, BeforeValidator(validate_age)]
2 changes: 1 addition & 1 deletion src/userprofile/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class UserProfile(EmbeddedDocument, LocationMixin):
name = StringField(required=True) # type: str
gender = EnumField(enum=Gender, required=True) # type: Gender
gender_preference = EnumField(enum=Gender, default=None, null=True) # type: Gender
birthday = DateField(required=True) # type: date
birthdate = DateField(required=True) # type: date
description = StringField(required=True) # type: str
residence_plan = EnumField(enum=ResidencePlan, required=True) # type: ResidencePlan
residence_length = EnumField(enum=ResidenceLength, required=True) # type: ResidenceLength
Expand Down
6 changes: 3 additions & 3 deletions src/userprofile/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from location.geopoint import GeoPoint
from location.schemas import LocationProjectBase
from userprofile import config as model_config
from userprofile.dateofbirth import DateOfBirth, Age
from userprofile.birthdate import BirthDate, Age

from userprofile.enums import Gender, ResidenceLength, ResidencePlan

Expand Down Expand Up @@ -40,7 +40,7 @@ class UserProfileBase(BaseModel):


class PrivateUserProfileIn(UserProfileBase):
birthday: DateOfBirth
birthdate: BirthDate
location: LocationIn


Expand All @@ -49,5 +49,5 @@ class PrivateUserProfileOut(PrivateUserProfileIn):


class PublicUserProfileOut(UserProfileBase):
age: Age = Field(validation_alias=AliasChoices("birthday", "age"))
age: Age = Field(validation_alias=AliasChoices("birthdate", "age"))
location: LocationOut
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
UserFactory,
ContactFactory,
ProfileFactory,
EventFactory,
)
from photos import config as file_config
from location.database import geonames_db
Expand Down Expand Up @@ -99,6 +100,11 @@ def userprofile_factory(db_config, city_db):
return ProfileFactory


@pytest.fixture(scope="session")
def event_factory(db_config, city_db):
return EventFactory


@pytest.fixture(scope="function")
def user(user_factory) -> User:
user: User = user_factory.create(active=True)
Expand Down
30 changes: 29 additions & 1 deletion tests/factories/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from contacts import service as contact_service
from contacts.models import Contact, Message, ContactState
from events.models import Event
from factories.helpers import build_json_dict
from location.database import geonames_db
from location.models import Location
Expand Down Expand Up @@ -46,6 +47,8 @@ class Params:
)




class LocationFactory(_BaseMongoEngineFactory):
class Meta:
model = Location
Expand All @@ -59,7 +62,7 @@ class Meta:
model = UserProfile

name = factory.Faker("user_name")
birthday = fuzzy.FuzzyDate(
birthdate = fuzzy.FuzzyDate(
start_date=datetime.date.today() - datetime.timedelta(days=365 * profile_config.MAX_AGE),
end_date=datetime.date.today() - datetime.timedelta(days=365 * profile_config.MIN_AGE),
)
Expand Down Expand Up @@ -113,3 +116,28 @@ class Meta:
model = Message

text = factory.Faker("paragraph", nb_sentences=4)


class EventFactory(_BaseMongoEngineFactory):
class Meta:
model = Event

title = factory.Faker("catch_phrase")
description = factory.Faker("paragraph", nb_sentences=5)
location = factory.SubFactory(LocationFactory, address=factory.Faker("address"))
start_at = factory.Faker("date_time_this_decade")
image_urls = factory.List([factory.Faker("image_url"), factory.Faker("image_url"), factory.Faker("image_url"),])

@factory.post_generation
def subscribers(self: Event, create: bool, extracted: list[User] | None, **kwargs) -> None:

if not create:
return

if extracted is None:
users: list[User] = UserFactory.create_batch(kwargs.pop("size", 1), events=[self], **kwargs)
else:
users = extracted

self.subscribers.extend(users)
self.save()
Empty file added tests/test_events/__init__.py
Empty file.
23 changes: 23 additions & 0 deletions tests/test_events/test_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import datehelpers
from events import service


def test_get_event_by_id(event_factory):
event = event_factory.create()
found_event = service.get_event_by_id(event.id)
assert event == found_event


def test_get_events_by_city_id(event_factory):
event = event_factory.create(start_at=datehelpers.get_aware_datetime_now(delta_days=1))
found_events = service.get_events_by_city_id(event.location.city_id, only_future=True)
assert event in found_events


def test_accept_subscriber(event_factory, user):
event = event_factory.create(subscribers=[])

service.accept_subscriber(event, user)

assert user in event.subscribers
assert event in user.events

0 comments on commit cd41452

Please sign in to comment.