From d38978b0e29c3e53586642576d603bc7c63dce41 Mon Sep 17 00:00:00 2001 From: blake hardee Date: Wed, 20 Nov 2024 16:28:52 -0500 Subject: [PATCH] finish tag implementation into services and resources. --- backend/api/resource.py | 45 +++++++-- backend/api/service.py | 38 ++++++- backend/api/tag.py | 22 +++++ backend/entities/resource_entity.py | 1 - backend/entities/service_entity.py | 1 + backend/models/resource_model.py | 2 +- backend/services/resource.py | 50 +++++++--- backend/services/service.py | 57 ++++++----- backend/services/tag.py | 86 ++++++++++++++-- backend/test/conftest.py | 7 ++ backend/test/services/fixtures.py | 14 +-- backend/test/services/resource_test.py | 104 +++++++++++++++++++- backend/test/services/resource_test_data.py | 28 +++++- backend/test/services/service_test.py | 41 +++++++- backend/test/services/service_test_data.py | 19 +++- 15 files changed, 442 insertions(+), 73 deletions(-) create mode 100644 backend/api/tag.py diff --git a/backend/api/resource.py b/backend/api/resource.py index 81d8b27..f68f98c 100644 --- a/backend/api/resource.py +++ b/backend/api/resource.py @@ -16,7 +16,7 @@ openapi_tags = { # TODO: Enable authorization by passing user uuid to API # TODO: Create custom exceptions @api.get("", response_model=List[Resource], tags=["Resource"]) -def get_all( +def get_all_resources( user_id: str, resource_svc: ResourceService = Depends(), user_svc: UserService = Depends(), @@ -27,7 +27,7 @@ def get_all( @api.get("/{id}", response_model=Resource, tags=["Resource"]) -def get_by_id( +def get__resource_by_id( user_id: str, id: int, resource_svc: ResourceService = Depends(), @@ -38,8 +38,8 @@ def get_by_id( return resource -@api.post("/", response_model=Resource, tags=["Resource"]) -def create_service( +@api.post("", response_model=Resource, tags=["Resource"]) +def create_resource( user_id: str, resource: Resource, resource_svc: ResourceService = Depends(), @@ -50,8 +50,8 @@ def create_service( return new_resource -@api.put("/{resource_id}", response_model=Resource, tags=["Resource"]) -def update_service( +@api.put("/{id}", response_model=Resource, tags=["Resource"]) +def update_resource( resource_id: int, user_id: str, resource: Resource, @@ -65,8 +65,8 @@ def update_service( return updated_resource -@api.delete("/{resource_id}", response_model=Resource, tags=["Resource"]) -def delete_service_tag_by_id( +@api.delete("/{id}", response_model=Resource, tags=["Resource"]) +def delete_resource_tag_by_id( resource_id: int, tag_id: int, user_id: str, @@ -79,3 +79,32 @@ def delete_service_tag_by_id( resource_svc.remove_tag(subject, resource, tag) return resource_svc.get_resource_by_id(resource_id) + + +@api.delete("/{resource_id}", tags=["Resource"]) +def delete_resource_by_id( + resource_id: int, + user_id: str, + resource_svc: ResourceService = Depends(), + user_svc: UserService = Depends(), +): + subject = user_svc.get_user_by_uuid(user_id) + resource = resource_svc.get_by_id(resource_id) + resource_svc.delete(subject, resource) + return + + +@api.get("/search/", response_model=List[Resource], tags=["Resource"]) +def get_service_by_slug( + slug: str, + user_id: str, + resource_svc: ResourceService = Depends(), + user_svc: UserService = Depends(), +): + subject = user_svc.get_user_by_uuid(user_id) + return resource_svc.get_by_slug(subject, slug) + + +@api.get("/tag/{tag_id}", response_model=List[Resource], tags=["Resource"]) +def get_resources_by_tag(tag_id: int, resource_svc: ResourceService = Depends()): + return resource_svc.get_by_tag_id(tag_id) diff --git a/backend/api/service.py b/backend/api/service.py index d6fd8d9..fa0e41b 100644 --- a/backend/api/service.py +++ b/backend/api/service.py @@ -1,4 +1,7 @@ from fastapi import APIRouter, Depends, HTTPException +from pytest import Session + +from backend.database import db_session from ..services import ServiceService, UserService, TagService from ..models import Service, Tag @@ -16,18 +19,17 @@ openapi_tags = { # TODO: Enable authorization by passing user uuid to API # TODO: Create custom exceptions @api.get("", response_model=List[Service], tags=["Service"]) -def get_all( +def get_all_services( user_id: str, service_svc: ServiceService = Depends(), user_svc: UserService = Depends(), ): subject = user_svc.get_user_by_uuid(user_id) - return service_svc.get_service_by_user(subject) @api.get("/{id}", response_model=Service, tags=["Service"]) -def get_by_id( +def get_service_by_id( user_id: str, id: int, service_svc: ServiceService = Depends(), @@ -38,7 +40,7 @@ def get_by_id( return service -@api.post("/", response_model=Service, tags=["Service"]) +@api.post("", response_model=Service, tags=["Service"]) def create_service( user_id: str, service: Service, @@ -65,7 +67,7 @@ def update_service( return updated_service -@api.delete("/{service_id}", response_model=Service, tags=["Service"]) +@api.delete("/{service_id}/{tag_id}", response_model=Service, tags=["Service"]) def delete_service_tag_by_id( service_id: int, tag_id: int, @@ -79,3 +81,29 @@ def delete_service_tag_by_id( service_svc.remove_tag(subject, service, tag) return service_svc.get_service_by_id(service_id) + + +@api.delete("/{service_id}", tags=["Service"]) +def delete_service_by_id( + service_id: int, + user_id: str, + service_svc: ServiceService = Depends(), + user_svc: UserService = Depends(), +): + subject = user_svc.get_user_by_uuid(user_id) + service = service_svc.get_service_by_id(service_id) + service_svc.delete(subject, service) + return + + +@api.get("/search/", response_model=List[Service], tags=["Service"]) +def get_service_by_slug( + slug: str, + service_svc: ServiceService = Depends(), +): + return service_svc.get_service_by_slug(slug) + + +@api.get("/tag/{tag_id}", response_model=List[Service], tags=["Service"]) +def get_services_by_tag(tag_id: int, service_svc: ServiceService = Depends()): + return service_svc.get_service_by_tag_id(tag_id) diff --git a/backend/api/tag.py b/backend/api/tag.py new file mode 100644 index 0000000..37e4b5c --- /dev/null +++ b/backend/api/tag.py @@ -0,0 +1,22 @@ +from typing import List +from fastapi import APIRouter, Depends + +from backend.models.resource_model import Resource +from backend.models.service_model import Service +from backend.models.tag_model import Tag +from backend.services.resource import ResourceService +from backend.services.service import ServiceService +from backend.services.tag import TagService + + +api = APIRouter(prefix="/api/tag") + +openapi_tags = { + "name": "Tag", + "description": "Tag getter and related operations.", +} + + +@api.get("", response_model=List[Tag], tags=["tags"]) +def get_all_tags(tag_service: TagService = Depends()): + return tag_service.all() diff --git a/backend/entities/resource_entity.py b/backend/entities/resource_entity.py index a710467..29d4a34 100644 --- a/backend/entities/resource_entity.py +++ b/backend/entities/resource_entity.py @@ -49,7 +49,6 @@ class ResourceEntity(EntityBase): return cls( id=model.id, - created_at=model.created_at, name=model.name, summary=model.summary, link=model.link, diff --git a/backend/entities/service_entity.py b/backend/entities/service_entity.py index 657a725..2360d2b 100644 --- a/backend/entities/service_entity.py +++ b/backend/entities/service_entity.py @@ -50,6 +50,7 @@ class ServiceEntity(EntityBase): summary=self.summary, requirements=self.requirements, program=self.program, + created_at=self.created_at, tags=[tag.tag.to_model() for tag in self.service_tags], ) diff --git a/backend/models/resource_model.py b/backend/models/resource_model.py index f12f31e..981f5ba 100644 --- a/backend/models/resource_model.py +++ b/backend/models/resource_model.py @@ -13,5 +13,5 @@ class Resource(BaseModel): summary: str = Field(..., max_length=300, description="The summary of the resource") link: str = Field(..., max_length=150, description="link to the resource") program: ProgramTypeEnum - created_at: Optional[datetime] + created_at: datetime | None = None tags: List[Tag] = [] diff --git a/backend/services/resource.py b/backend/services/resource.py index 1319d2e..a4d4ec2 100644 --- a/backend/services/resource.py +++ b/backend/services/resource.py @@ -1,12 +1,13 @@ +from typing import List from fastapi import Depends from backend.services.tag import TagService from ..database import db_session from sqlalchemy.orm import Session -from sqlalchemy import select +from sqlalchemy import and_, or_, select from ..models.resource_model import Resource from ..entities.resource_entity import ResourceEntity -from ..models.user_model import User, UserTypeEnum +from ..models.user_model import User, UserTypeEnum, ProgramTypeEnum from .exceptions import ProgramNotAssignedException, ResourceNotFoundException @@ -129,21 +130,20 @@ class ResourceService: ) resource_entity.name = resource.name - resource_entity.status = resource.status resource_entity.summary = resource.summary - resource_entity.requirements = resource.requirements resource_entity.program = resource.program + resource_entity.link = resource.link for tag in resource.tags: tag_entity = self._tag_service.get_or_create_tag(tag.content) - self._tag_service.add_tag_service( + self._tag_service.add_tag_resource( user, tag_entity, ResourceEntity.to_model(resource_entity) ) self._session.commit() return resource_entity.to_model() - def delete(self, user: User, id: int) -> None: + def delete(self, user: User, resource: Resource) -> None: """ Delete resource based on id that the user has access to @@ -154,12 +154,17 @@ class ResourceService: Raises: ResourceNotFoundException: If no resource is found with the corresponding id """ + + if user.role != UserTypeEnum.ADMIN: + raise ProgramNotAssignedException( + f"User is not {UserTypeEnum.ADMIN}, cannot delete service" + ) + resource = ( self._session.query(ResourceEntity) .filter( - ResourceEntity.id == id, - ResourceEntity.role == user.role, - ResourceEntity.group == user.group, + ResourceEntity.id == resource.id, + ResourceEntity.program.in_(user.program), ) .one_or_none() ) @@ -184,11 +189,30 @@ class ResourceService: Raises: ResourceNotFoundException if no resource is found with the corresponding slug """ - query = select(ResourceEntity).where( - ResourceEntity.title.ilike(f"%{search_string}%"), - ResourceEntity.role == user.role, - ResourceEntity.group == user.group, + query = select(ResourceEntity).filter( + and_( + ResourceEntity.program.in_(user.program), + or_( + ResourceEntity.name.ilike(f"%{search_string}%"), + ResourceEntity.summary.ilike(f"%{search_string}%"), + ), + ) ) entities = self._session.scalars(query).all() return [entity.to_model() for entity in entities] + + def get_by_program(self, user: User, program: ProgramTypeEnum): + if not user.program.__contains__(program): + raise ProgramNotAssignedException + + query = select(ResourceEntity).where(ResourceEntity.program == program) + entities = self._session.scalars(query).all() + return [entity.to_model() for entity in entities] + + def get_by_tag_id(self, tag_id: int) -> List[Resource]: + resource_ids = self._tag_service.get_all_resources_by_tagid(tag_id) + resources = [] + for id in resource_ids: + resources.append(self.get_by_id(id)) + return resources diff --git a/backend/services/service.py b/backend/services/service.py index a004ba4..971a1e0 100644 --- a/backend/services/service.py +++ b/backend/services/service.py @@ -6,7 +6,7 @@ from backend.entities.tag_entity import TagEntity from ..database import db_session from sqlalchemy.orm import Session -from sqlalchemy import func, select, and_, func, or_, exists, or_ +from sqlalchemy import func, select, and_, func, or_, exists, or_, any_ from backend.models.service_model import Service from backend.models.user_model import User @@ -16,7 +16,7 @@ from backend.services.exceptions import ( ServiceNotFoundException, ProgramNotAssignedException, ) -from . import TagService +from backend.services.tag import TagService from ..models import Tag @@ -56,14 +56,26 @@ class ServiceService: raise ServiceNotFoundException(f"Service with name: {name} does not exist") service = entity.to_model() - # service.tags.extend(TagService.get_tags_for_service(TagService, service)) return service + def get_service_by_slug(self, search_str: str) -> List[Service]: + """Service method getting services by slug.""" + query = select(ServiceEntity).filter( + or_( + ServiceEntity.name.ilike(f"%{search_str}%"), + ServiceEntity.status.ilike(f"%{search_str}%"), + ServiceEntity.summary.ilike(f"%{search_str}%"), + any_(ServiceEntity.requirements).ilike(f"%{search_str}%"), + ) + ) + entity = self._session.scalars(query).all() + + return [service.to_model() for service in entity] + def get_service_by_user(self, subject: User): """Service method getting all of the services that a user has access to based on role""" if subject.role != UserTypeEnum.VOLUNTEER: - query = select(ServiceEntity) - entities = self._session.scalars(query).all() + entities = self._session.query(ServiceEntity).all() return [service.to_model() for service in entities] else: @@ -84,8 +96,7 @@ class ServiceService: f"User is not {UserTypeEnum.ADMIN} or {UserTypeEnum.VOLUNTEER}, cannot get all" ) - query = select(ServiceEntity) - entities = self._session.scalars(query).all() + entities = self._session.query(ServiceEntity).all() services = [service.to_model() for service in entities] return services @@ -157,27 +168,29 @@ class ServiceService: raise ServiceNotFoundException( "The service you are searching for does not exist." ) - self._tag_service.delete_all_tags_service(service_entity.to_model()) + if self._tag_service.get_tags_for_service(service).count(Tag) != 0: + self._tag_service.delete_all_tags_service(service) + self._session.delete(service_entity) self._session.commit() + def get_service_by_tag_id(self, tag_id: int) -> List[Service]: + service_ids = self._tag_service.get_all_services_by_tagid(tag_id) + services = [] + for id in service_ids: + services.append(self.get_service_by_id(id)) + return services + + """ + Can be used, but both methods are achieved by update. + def add_tag(self, subject: User, service: Service, tag: Tag): service = self.get_service_by_id(service.id) tag = self._tag_service.get_tag_by_id(tag.id) self._tag_service.add_tag_service(subject, service.id, tag.id) def remove_tag(self, subject: User, service: Service, tag: Tag) -> None: - service_tag = ( - self._session.query(ServiceTagEntity) - .filter( - ServiceTagEntity.serviceId == service.id, - ServiceTagEntity.tagId == tag.id, - ) - .one_or_none() - ) - if service_tag is None: - raise Exception( - f"No tag with id {tag.id} found for service with id {service.id}." - ) - self._session.delete(service_tag) - self._session.commit() + serviceEntity = self.get_service_by_id(service.id) + tagEntity = self._tag_service.get_tag_by_id(tag.id) + self._tag_service.delete_tag_service(subject, tagEntity, serviceEntity) + """ diff --git a/backend/services/tag.py b/backend/services/tag.py index aae4038..f4437f2 100644 --- a/backend/services/tag.py +++ b/backend/services/tag.py @@ -1,3 +1,4 @@ +from typing import List from fastapi import Depends from backend.models.enum_for_models import UserTypeEnum @@ -7,7 +8,6 @@ from sqlalchemy import select from ..entities import TagEntity, ResourceTagEntity, ServiceTagEntity from ..models import User, Resource, Service, Tag, ResourceTag, ServiceTag from .exceptions import ProgramNotAssignedException, ResourceNotFoundException -from datetime import datetime class TagService: @@ -140,6 +140,30 @@ class TagService: self._session.rollback() # Rollback in case of error raise Exception("Failed to add tag to resource") from e + def delete_tag_resource(self, user: User, tag: Tag, resource: Resource) -> None: + """Deletes a tag from a service""" + + existing_tag = ( + self._session.query(ResourceTagEntity) + .filter( + ResourceTagEntity.tagId == tag.id, + ResourceTagEntity.resourceId == resource.id, + ) + .first() + ) + + if existing_tag == None: + raise Exception( + f"Tag with id {tag.id} does not exist for resource with id {resource.id}." + ) + + try: + self._session.delete(existing_tag) + self._session.commit() + except Exception as e: + self._session.rollback() # Rollback in case of error + raise Exception("Failed to delete tag to service") from e + def add_tag_service(self, user: User, tag: Tag, service: Service) -> None: """Adds a tag to a service""" @@ -168,15 +192,41 @@ class TagService: self._session.rollback() # Rollback in case of error raise Exception("Failed to add tag to service") from e + def delete_tag_service(self, user: User, tag: Tag, service: Service) -> None: + """Deletes a tag from a service""" + + existing_tag = ( + self._session.query(ServiceTagEntity) + .filter( + ServiceTagEntity.tagId == tag.id, + ServiceTagEntity.serviceId == service.id, + ) + .first() + ) + + if existing_tag == None: + raise Exception( + f"Tag with id {tag.id} does not exist for service with id {service.id}." + ) + + try: + self._session.delete(existing_tag) + self._session.commit() + except Exception as e: + self._session.rollback() # Rollback in case of error + raise Exception("Failed to delete tag to service") from e + def delete_all_tags_service(self, service: Service) -> None: """Deletes all service tags for a service""" - service_tags = self._session.query(ServiceTagEntity).filter( - ServiceTagEntity.serviceId == service.id + service_tags = ( + self._session.query(ServiceTagEntity) + .filter(ServiceTagEntity.serviceId == service.id) + .all() ) - if service_tags.count() == 0: - raise ResourceNotFoundException + if service_tags.count(ServiceTagEntity) == 0: + return service_tags.delete(synchronize_session=False) self._session.commit() @@ -184,12 +234,14 @@ class TagService: def delete_all_tags_resource(self, resource: Resource) -> None: """Deletes all resource tags for a resource""" - resource_tags = self._session.query(ResourceTagEntity).filter( - ResourceTagEntity.resourceId == resource.id + resource_tags = ( + self._session.query(ResourceTagEntity) + .filter(ResourceTagEntity.resourceId == resource.id) + .all() ) if resource_tags.count() == 0: - raise ResourceNotFoundException + return resource_tags.delete(synchronize_session=False) self._session.commit() @@ -213,3 +265,21 @@ class TagService: except Exception as e: self._session.rollback() raise Exception(f"Failed to create tag with content: {tag.content}") from e + + def get_all_services_by_tagid(self, tagId: int) -> List[int]: + services = ( + self._session.query(ServiceTagEntity) + .filter(ServiceTagEntity.tagId == tagId) + .all() + ) + + return [service.serviceId for service in services] + + def get_all_resources_by_tagid(self, tagId: int) -> List[int]: + resources = ( + self._session.query(ResourceTagEntity) + .filter(ResourceTagEntity.tagId == tagId) + .all() + ) + + return [resource.resourceId for resource in resources] diff --git a/backend/test/conftest.py b/backend/test/conftest.py index a435b52..d6e377d 100644 --- a/backend/test/conftest.py +++ b/backend/test/conftest.py @@ -14,6 +14,7 @@ from .services import ( from ..database import _engine_str from ..env import getenv from .. import entities +from ..services import TagService POSTGRES_DATABASE = f'{getenv("POSTGRES_DATABASE")}_test' POSTGRES_USER = getenv("POSTGRES_USER") @@ -65,3 +66,9 @@ def setup_insert_data_fixture(session: Session): resource_test_data.insert_fake_data(session) session.commit() yield + + +@pytest.fixture() +def tag_svc(session: Session): + """This fixture is used to test the TagService class""" + return TagService(session) diff --git a/backend/test/services/fixtures.py b/backend/test/services/fixtures.py index 7538330..ed5f3ed 100644 --- a/backend/test/services/fixtures.py +++ b/backend/test/services/fixtures.py @@ -13,18 +13,12 @@ def user_svc(session: Session): @pytest.fixture() -def tag_svc(session: Session): - """This fixture is used to test the TagService class""" - return TagService(session) - - -@pytest.fixture() -def service_svc(session: Session): +def service_svc(session: Session, tag_svc: TagService): """This fixture is used to test the ServiceService class""" - return ServiceService(session) + return ServiceService(session, tag_svc) @pytest.fixture() -def resource_svc(session: Session): +def resource_svc(session: Session, tag_svc: TagService): """This fixutre is used to test the ResourceService class""" - return ResourceService(session) + return ResourceService(session, tag_svc) diff --git a/backend/test/services/resource_test.py b/backend/test/services/resource_test.py index 5f5e8c1..7130b76 100644 --- a/backend/test/services/resource_test.py +++ b/backend/test/services/resource_test.py @@ -1,6 +1,12 @@ +from backend.models.enum_for_models import ProgramTypeEnum +from backend.models.resource_model import Resource +from backend.models.tag_model import Tag from backend.services import ResourceService, TagService +from backend.services.exceptions import ResourceNotFoundException from .user_test_data import admin -from .fixtures import resource_svc, tag_svc +from .fixtures import resource_svc +from backend.test.services import user_test_data, resource_test_data, tag_test_data +import pytest def test_temp(resource_svc: ResourceService, tag_svc: TagService): @@ -8,3 +14,99 @@ def test_temp(resource_svc: ResourceService, tag_svc: TagService): tags = tag_svc.all() print(tags) print(resources) + + +def test_list(resource_svc: ResourceService): + resource = resource_svc.get_resource_by_user(user_test_data.admin) + assert len(resource) == len(resource_test_data.resources) + assert isinstance(resource[0], Resource) + + +def test_get_by_name(resource_svc: ResourceService): + resource = resource_svc.get_by_slug(user_test_data.admin, "resource 1") + assert resource[0].name == resource_test_data.resource1.name + assert isinstance(resource[0], Resource) + + +def test_get_by_name_not_found(resource_svc: ResourceService): + resource = resource_svc.get_by_slug(user_test_data.admin, "resource 12") + assert len(resource) == 0 + + +def test_get_resource_by_user_admin(resource_svc: ResourceService): + resource = resource_svc.get_resource_by_user(user_test_data.admin) + assert len(resource) == len(resource_test_data.resources) + + +def test_get_resource_by_user_volun(resource_svc: ResourceService): + resource = resource_svc.get_resource_by_user(user_test_data.volunteer) + assert len(resource) == 2 + + +def test_get_by_program(resource_svc: ResourceService): + resources = resource_svc.get_by_program( + user_test_data.admin, ProgramTypeEnum.COMMUNITY + ) + for resource in resources: + assert resource.program == ProgramTypeEnum.COMMUNITY + assert isinstance(resource, Resource) + + +def test_create(resource_svc: ResourceService): + resource = resource_svc.create( + user_test_data.admin, resource_test_data.resource_to_create + ) + assert resource.name == resource_test_data.resource_to_create.name + assert isinstance(resource, Resource) + + +def test_update(resource_svc: ResourceService): + resource = resource_svc.update( + user_test_data.admin, resource_test_data.resource4_edit + ) + assert resource.name == resource_test_data.resource4_edit.name + assert isinstance(resource, Resource) + + +def test_update_with_tags(resource_svc: ResourceService): + resource = resource_svc.update(user_test_data.admin, resource_test_data.resource2) + assert len(resource.tags) == 2 + + +def test_update_not_found(resource_svc: ResourceService): + with pytest.raises(ResourceNotFoundException): + resource = resource_svc.update( + user_test_data.admin, resource_test_data.resource_to_create + ) + pytest.fail() + + +def test_delete(resource_svc: ResourceService): + resource_svc.delete(user_test_data.admin, resource_test_data.resource3) + resources = resource_svc.get_resource_by_user(user_test_data.admin) + assert len(resources) == len(resource_test_data.resources) - 1 + + +def test_delete_not_found(resource_svc: ResourceService): + with pytest.raises(ResourceNotFoundException): + resource_svc.delete(user_test_data.admin, resource_test_data.resource_10) + pytest.fail() + + +def test_create_resource_with_tags(resource_svc: ResourceService): + resource = Resource( + name="test resource", + summary="summary", + link="www.example.com", + program=ProgramTypeEnum.COMMUNITY, + tags=[Tag(content="resource tag")], + ) + resource_entity = resource_svc.create(user_test_data.admin, resource) + assert len(resource_entity.tags) == 1 + + +def test_update_tags_for_resource(resource_svc: ResourceService): + resourceEntity = resource_svc.update( + user_test_data.admin, resource_test_data.resource2_edit_tags + ) + assert len(resourceEntity.tags) == 1 diff --git a/backend/test/services/resource_test_data.py b/backend/test/services/resource_test_data.py index bb39266..9cebda8 100644 --- a/backend/test/services/resource_test_data.py +++ b/backend/test/services/resource_test_data.py @@ -4,6 +4,7 @@ from datetime import datetime from ...entities import ResourceEntity from ...models.enum_for_models import ProgramTypeEnum from ...models.resource_model import Resource +from .tag_test_data import * resource1 = Resource( id=1, @@ -20,7 +21,16 @@ resource2 = Resource( summary="Legal assistance resources", link="https://example.com/resource2", program=ProgramTypeEnum.COMMUNITY, - created_at=datetime(2023, 6, 2, 12, 30, 0), + tags=[tag1, tag2], +) + +resource2_edit_tags = Resource( + id=2, + name="Resource 2", + summary="Legal assistance resources", + link="https://example.com/resource2", + program=ProgramTypeEnum.COMMUNITY, + tags=[tag2], ) resource3 = Resource( @@ -41,6 +51,15 @@ resource4 = Resource( created_at=datetime(2023, 6, 4, 9, 15, 0), ) +resource4_edit = Resource( + id=4, + name="Resource 4 edited", + summary="Counseling and support groups", + link="https://example.com/resource4", + program=ProgramTypeEnum.DOMESTIC, + created_at=datetime(2023, 6, 4, 9, 15, 0), +) + resource5 = Resource( id=5, name="Resource 5", @@ -50,6 +69,13 @@ resource5 = Resource( created_at=datetime(2023, 6, 5, 11, 30, 0), ) +resource_to_create = Resource( + name="Created Resource", + summary="Resource Test Create", + link="https://example.com/", + program=ProgramTypeEnum.COMMUNITY, +) + resources = [resource1, resource2, resource3, resource4, resource5] resource_1 = Resource( diff --git a/backend/test/services/service_test.py b/backend/test/services/service_test.py index fe98518..6e6c197 100644 --- a/backend/test/services/service_test.py +++ b/backend/test/services/service_test.py @@ -1,3 +1,4 @@ +from backend.models.tag_model import Tag from backend.models.user_model import User from backend.entities.service_entity import ServiceEntity from ...models.enum_for_models import ProgramTypeEnum @@ -5,6 +6,7 @@ from backend.services.service import ServiceService from backend.services.exceptions import ServiceNotFoundException from . import service_test_data from . import user_test_data +from . import tag_test_data from .fixtures import service_svc, user_svc from backend.models.service_model import Service import pytest @@ -58,6 +60,11 @@ def test_update(service_svc: ServiceService): assert isinstance(service, Service) +def test_update_with_tags(service_svc: ServiceService): + service = service_svc.update(user_test_data.admin, service_test_data.service2) + assert len(service.tags) == 2 + + def test_update_not_found(service_svc: ServiceService): with pytest.raises(ServiceNotFoundException): service = service_svc.update( @@ -72,7 +79,37 @@ def test_delete(service_svc: ServiceService): assert len(services) == len(service_test_data.services) - 1 -"""def test_delete_not_found(service_svc: ServiceService): +def test_delete_not_found(service_svc: ServiceService): with pytest.raises(ServiceNotFoundException): service_svc.delete(user_test_data.admin, service_test_data.service_10) - pytest.fail()""" + pytest.fail() + + +def test_create_service_with_tags(service_svc: ServiceService): + service = Service( + name="test service", + status="open", + summary="summary", + requirements=["18 years or older"], + program=ProgramTypeEnum.COMMUNITY, + tags=[Tag(content="service tag")], + ) + service_entity = service_svc.create(user_test_data.admin, service) + assert len(service_entity.tags) == 1 + + +def test_update_tags_for_service(service_svc: ServiceService): + serviceEntity = service_svc.update( + user_test_data.admin, service_test_data.service2_update + ) + assert len(serviceEntity.tags) == 2 + + +def test_get_service_by_slug(service_svc: ServiceService): + services = service_svc.get_service_by_slug("service 1") + assert services[0].id == service_test_data.service1.id + + +def test_get_service_by_requirements_slug(service_svc: ServiceService): + services = service_svc.get_service_by_slug("safe places to stay") + assert services[0].id == service_test_data.service2.id diff --git a/backend/test/services/service_test_data.py b/backend/test/services/service_test_data.py index 6a14015..23d5a4f 100644 --- a/backend/test/services/service_test_data.py +++ b/backend/test/services/service_test_data.py @@ -4,7 +4,7 @@ from sqlalchemy.orm import Session from ...entities import ServiceEntity from ...models.enum_for_models import ProgramTypeEnum from ...models import Service, Tag -from .tag_test_data import tags +from .tag_test_data import * service1 = Service( id=1, @@ -13,6 +13,7 @@ service1 = Service( summary="presentation educating community on domestic violence", requirements=[""], program=ProgramTypeEnum.COMMUNITY, + tags=[tag1], ) service2 = Service( @@ -22,6 +23,17 @@ service2 = Service( summary="service finding safe places to stay", requirements=[""], program=ProgramTypeEnum.DOMESTIC, + tags=[tag1, tag2], +) + +service2_update = Service( + id=2, + name="service 2", + status="closed", + summary="service finding safe places to stay", + requirements=[""], + program=ProgramTypeEnum.DOMESTIC, + tags=[tag1, tag_to_create], ) service3 = Service( @@ -31,6 +43,7 @@ service3 = Service( summary="", requirements=[""], program=ProgramTypeEnum.DOMESTIC, + tags=[tags[0], tags[1], tags[2]], ) service4 = Service( @@ -40,6 +53,7 @@ service4 = Service( summary="community event", requirements=[""], program=ProgramTypeEnum.COMMUNITY, + tags=[Tag(content="Tag 4"), Tag(content="Tag 1")], ) service5 = Service( @@ -49,6 +63,7 @@ service5 = Service( summary="talk circle for victims of domestic violence", requirements=["18+"], program=ProgramTypeEnum.COMMUNITY, + tags=[Tag(content="Tag 5")], ) service6 = Service( @@ -58,6 +73,7 @@ service6 = Service( summary="program offering economic assistance", requirements=[""], program=ProgramTypeEnum.ECONOMIC, + tags=[Tag(content="Tag 6")], ) service_6_edit = Service( @@ -76,6 +92,7 @@ service7 = Service( summary="insert generic description", requirements=[""], program=ProgramTypeEnum.ECONOMIC, + tags=[Tag(content="Tag 7")], ) new_service = Service(