Skip to content

Commit

Permalink
beginning project tests
Browse files Browse the repository at this point in the history
formatting
  • Loading branch information
tcnichol committed Jul 30, 2024
1 parent a679d7c commit 9f2c8ac
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 45 deletions.
6 changes: 5 additions & 1 deletion backend/app/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Member(BaseModel):
user: UserOut
editor: bool = False


class ProjectBase(BaseModel):
id: PydanticObjectId = Field(default_factory=PydanticObjectId, alias="_id")
name: str
Expand All @@ -26,13 +27,16 @@ class ProjectBase(BaseModel):
creator: UserOut
users: List[Member] = []


class ProjectDB(Document, ProjectBase):
class Settings:
name = "projects"


class ProjectIn(ProjectBase):
pass


class ProjectOut(ProjectDB):
class Config:
fields = {"id": "id"}
fields = {"id": "id"}
142 changes: 98 additions & 44 deletions backend/app/routers/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@

clowder_bucket = os.getenv("MINIO_BUCKET_NAME", "clowder")


@router.post("", response_model=ProjectOut)
async def save_project(
project_in: ProjectIn,
user=Depends(get_current_user),
es: Elasticsearch = Depends(dependencies.get_elasticsearchclient),
):

project = ProjectDB(
**project_in.dict(),
creator=user,
Expand All @@ -58,31 +58,49 @@ async def save_project(
# TODO Add new entry to elasticsearch
return project.dict()


@router.post("/{project_id}/add_dataset/{dataset_id}", response_model=ProjectOut)
async def add_dataset(
project_id: str,
dataset_id: str,
project_id: str,
dataset_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if dataset := await DatasetDB.find_one(DatasetDB.id == PydanticObjectId(dataset_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
if (
dataset := await DatasetDB.find_one(
DatasetDB.id == PydanticObjectId(dataset_id)
)
is not None
):
if dataset_id not in project.dataset_ids:
project.dataset_ids.append(dataset_id)
await project.replace()
return project.dict()
raise HTTPException(status_code=404, detail=f"Dataset {dataset_id} not found")
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")


@router.post("/{project_id}/remove_dataset/{dataset_id}", response_model=ProjectOut)
async def remove_dataset(
project_id: str,
dataset_id: str,
project_id: str,
dataset_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if dataset := await DatasetDB.find_one(DatasetDB.id == PydanticObjectId(dataset_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
if (
dataset := await DatasetDB.find_one(
DatasetDB.id == PydanticObjectId(dataset_id)
)
is not None
):
if dataset_id in project.dataset_ids:
project.dataset_ids.remove(dataset_id)
await project.replace()
Expand All @@ -95,29 +113,46 @@ async def remove_dataset(

@router.post("/{project_id}/add_folder/{folder_id}", response_model=ProjectOut)
async def add_folder(
project_id: str,
folder_id: str,
project_id: str,
folder_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if folder := await FolderDB.find_one(FolderDB.id == PydanticObjectId(folder_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
if (
folder := await FolderDB.find_one(
FolderDB.id == PydanticObjectId(folder_id)
)
is not None
):
if folder_id not in project.folder_ids:
project.folder_ids.append(folder_id)
await project.replace()
return project.dict()
raise HTTPException(status_code=404, detail=f"Folder {folder_id} not found")
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")


@router.post("/{project_id}/remove_folder/{folder_id}", response_model=ProjectOut)
async def remove_folder(
project_id: str,
folder_id: str,
project_id: str,
folder_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if folder := await FolderDB.find_one(FolderDB.id == PydanticObjectId(folder_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
if (
folder := await FolderDB.find_one(
FolderDB.id == PydanticObjectId(folder_id)
)
is not None
):
if folder_id in project.folder_ids:
project.folder_ids.remove(folder_id)
await project.replace()
Expand All @@ -127,31 +162,45 @@ async def remove_folder(
raise HTTPException(status_code=404, detail=f"Folder {folder_id} not found")
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")


@router.post("/{project_id}/add_file/{file_id}", response_model=ProjectOut)
async def add_file(
project_id: str,
file_id: str,
project_id: str,
file_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if file := await FileDB.find_one(FileDB.id == PydanticObjectId(file_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
if (
file := await FileDB.find_one(FileDB.id == PydanticObjectId(file_id))
is not None
):
if file_id not in project.file_ids:
project.file_ids.append(file_id)
await project.replace()
return project.dict()
raise HTTPException(status_code=404, detail=f"File {file_id} not found")
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")


@router.post("/{project_id}/remove_file/{file_id}", response_model=ProjectOut)
async def remove_file(
project_id: str,
file_id: str,
project_id: str,
file_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if file := await FileDB.find_one(FileDB.id == PydanticObjectId(file_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
if (
file := await FileDB.find_one(FileDB.id == PydanticObjectId(file_id))
is not None
):
if file_id in project.file_ids:
project.file_ids.remove(file_id)
await project.replace()
Expand All @@ -170,9 +219,8 @@ async def get_projects(
mine: bool = False,
enable_admin: bool = False,
):

# TODO check if the current user is a member OR creator
query = (ProjectDB.creator.email == user_id)
query = ProjectDB.creator.email == user_id

projects_and_count = await ProjectDB.find(*query).to_list()

Expand All @@ -190,15 +238,21 @@ async def get_projects(

return page.dict()


@router.get("/{project_id}", response_model=ProjectOut)
async def get_project(
project_id: str,
):
if project := await ProjectDB.find_one(ProjectDB.id == PydanticObjectId(project_id)
) is not None:
if (
project := await ProjectDB.find_one(
ProjectDB.id == PydanticObjectId(project_id)
)
is not None
):
return project.dict()
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")


@router.delete("/{project_id}", response_model=ProjectOut)
async def delete_project(
project_id: str,
Expand All @@ -210,7 +264,7 @@ async def delete_project(
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")


@router.post("/{project_id}/add/{username}", response_model=ProjectOut)
@router.post("/{project_id}/add_member/{username}", response_model=ProjectOut)
async def add_member(
project_id: str,
username: str,
Expand All @@ -234,7 +288,8 @@ async def add_member(
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")
raise HTTPException(status_code=404, detail=f"User {username} not found")

@router.post("/{project_id}/remove/{username}", response_model=ProjectOut)

@router.post("/{project_id}/remove_member/{username}", response_model=ProjectOut)
async def remove_member(
project_id: str,
username: str,
Expand All @@ -255,4 +310,3 @@ async def remove_member(
await project.replace()
return project.dict()
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")

50 changes: 50 additions & 0 deletions backend/app/tests/test_projects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from app.config import settings
from app.tests.utils import (
create_dataset,
create_group,
create_user,
get_user_token,
user_alt,
create_project,
)
from fastapi.testclient import TestClient

member_alt = {"user": user_alt, "editor": False}


def test_create_project(client: TestClient, headers: dict):
create_project(client, headers)


def test_get_project(client: TestClient, headers: dict):
project_id = create_project(client, headers).get("id")
response = client.get(f"{settings.API_V2_STR}/projects/{project_id}", headers=headers)
assert response.status_code == 200
assert response.json().get("id") is not None


def test_delete_project(client: TestClient, headers: dict):
project_id = create_project(client, headers).get("id")
response = client.delete(
f"{settings.API_V2_STR}/projects/{project_id}", headers=headers
)
assert response.status_code == 200



def test_add_member(client: TestClient, headers: dict):
new_project = create_project(client, headers)
project_id = new_project.get("id")

create_user(client, headers)
new_project["users"].append(member_alt)

response = client.post(
f"{settings.API_V2_STR}/projects/{project_id}/add_member/{member_alt['user']['email']}",
headers=headers,
)

assert response.status_code == 200
assert response.json().get("id") is not None
for user in response.json().get("users"):
assert user.get("user").get("email") == member_alt["user"]["email"]
16 changes: 16 additions & 0 deletions backend/app/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
},
}

project_example = {
"name": "test_project",
"description": "This project is a test"
}

extractor_info_v1_example = {
"@context": "http://clowder.ncsa.illinois.edu/contexts/extractors.jsonld",
"name": "test.extractor_info_v1_example",
Expand Down Expand Up @@ -175,6 +180,17 @@ def create_dataset_with_custom_license(client: TestClient, headers: dict):
assert response.json().get("id") is not None
return response.json()

def create_project(client: TestClient, headers: dict):
"""Creates a test dataset and returns the JSON."""
response = client.post(
f"{settings.API_V2_STR}/projects",
headers=headers,
json=project_example,
)
assert response.status_code == 200
assert response.json().get("id") is not None
return response.json()


def upload_file(
client: TestClient,
Expand Down

0 comments on commit 9f2c8ac

Please sign in to comment.