You've already forked RekomenciBackend
add edit resume
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
from collections.abc import AsyncIterable, AsyncIterator
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import cast
|
||||
|
||||
import pytest
|
||||
from dishka import AsyncContainer
|
||||
from fastapi import FastAPI
|
||||
|
||||
from template_project.web_api.configuration import load_configuration
|
||||
from template_project.web_api.entry_point import make_server
|
||||
@@ -14,20 +16,23 @@ from tests.web_api.ioc import make_ioc
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
async def dishka_container(backend: Any) -> AsyncIterable[AsyncContainer]:
|
||||
async def dishka_container(backend: FastAPI) -> AsyncIterable[AsyncContainer]:
|
||||
path = Path(os.environ["CONFIGURATION_PATH"])
|
||||
configuration = load_configuration(path)
|
||||
ioc = make_ioc(configuration)
|
||||
ioc = make_ioc(configuration, backend)
|
||||
yield ioc
|
||||
await ioc.close()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
async def backend() -> AsyncIterator[None]:
|
||||
async def backend() -> AsyncIterator[FastAPI]:
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
logging.getLogger("httpcore").setLevel(logging.WARNING)
|
||||
|
||||
configuration = load_configuration(Path(os.environ["CONFIGURATION_PATH"]))
|
||||
server = make_server(configuration)
|
||||
asyncio.create_task(server.serve()) # type: ignore[unused-awaitable]
|
||||
yield
|
||||
yield cast(FastAPI, server.config.app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
from typing import Final
|
||||
|
||||
from dirty_equals import IsDict, IsUUID
|
||||
from dirty_equals import IsDict, IsPartialDict, IsUUID
|
||||
from dishka import FromDishka
|
||||
from uuid_utils.compat import uuid7
|
||||
|
||||
from tests.web_api.helpers import is_not_found_response, is_success_response, is_unauthorized_response
|
||||
from tests.web_api.helpers import (
|
||||
is_forbidden_response,
|
||||
is_not_found_response,
|
||||
is_success_response,
|
||||
is_unauthorized_response,
|
||||
)
|
||||
from tests.web_api.ioc import DatabaseClearer, inject
|
||||
from tests.web_api.test_api_gateway import TestApiGateway
|
||||
|
||||
@@ -129,3 +134,123 @@ async def test_not_found_get_resume(
|
||||
resume_id=str(uuid7()),
|
||||
)
|
||||
assert is_not_found_response(response)
|
||||
|
||||
|
||||
@inject
|
||||
async def test_success_edit_resume(
|
||||
unique_email: str,
|
||||
test_api_gateway: FromDishka[TestApiGateway],
|
||||
database_clearer: FromDishka[DatabaseClearer],
|
||||
) -> None:
|
||||
await database_clearer.clear()
|
||||
|
||||
response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
|
||||
access_token = response_sign_up.json()["access_token"]
|
||||
|
||||
response = await test_api_gateway.create_resume(
|
||||
access_token=access_token,
|
||||
about_me="About me",
|
||||
experience_type="noExperience",
|
||||
key_skills=["i love lisp", "i love rust"],
|
||||
position="Position",
|
||||
)
|
||||
resume_id = response.json()["resume_id"]
|
||||
response = await test_api_gateway.edit_resume(
|
||||
access_token=access_token,
|
||||
resume_id=resume_id,
|
||||
about_me="Updated about me",
|
||||
experience_type="between1And3",
|
||||
key_skills=["i love python"],
|
||||
position="Updated Position",
|
||||
)
|
||||
assert is_success_response(response)
|
||||
assert response.json() == IsPartialDict(
|
||||
position="Updated Position",
|
||||
about_me="Updated about me",
|
||||
key_skills=["i love python"],
|
||||
experience_type="between1And3",
|
||||
)
|
||||
|
||||
|
||||
@inject
|
||||
async def test_unauthorized_edit_resume(
|
||||
unique_email: str,
|
||||
test_api_gateway: FromDishka[TestApiGateway],
|
||||
database_clearer: FromDishka[DatabaseClearer],
|
||||
) -> None:
|
||||
await database_clearer.clear()
|
||||
|
||||
response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
|
||||
access_token = response_sign_up.json()["access_token"]
|
||||
|
||||
response = await test_api_gateway.create_resume(
|
||||
access_token=access_token,
|
||||
about_me="About me",
|
||||
experience_type="noExperience",
|
||||
key_skills=["i love lisp", "i love rust"],
|
||||
position="Position",
|
||||
)
|
||||
resume_id = response.json()["resume_id"]
|
||||
response = await test_api_gateway.edit_resume(
|
||||
access_token="...",
|
||||
resume_id=resume_id,
|
||||
about_me="Updated about me",
|
||||
experience_type="between1And3",
|
||||
key_skills=["i love python"],
|
||||
position="Updated Position",
|
||||
)
|
||||
assert is_unauthorized_response(response)
|
||||
|
||||
|
||||
@inject
|
||||
async def test_not_found_edit_resume(
|
||||
unique_email: str,
|
||||
test_api_gateway: FromDishka[TestApiGateway],
|
||||
database_clearer: FromDishka[DatabaseClearer],
|
||||
) -> None:
|
||||
await database_clearer.clear()
|
||||
|
||||
response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
|
||||
access_token = response_sign_up.json()["access_token"]
|
||||
|
||||
response = await test_api_gateway.edit_resume(
|
||||
access_token=access_token,
|
||||
resume_id=str(uuid7()),
|
||||
about_me="Updated about me",
|
||||
experience_type="between1And3",
|
||||
key_skills=["i love python"],
|
||||
position="Updated Position",
|
||||
)
|
||||
assert is_not_found_response(response)
|
||||
|
||||
|
||||
@inject
|
||||
async def test_forbidden_edit_resume(
|
||||
unique_email: str,
|
||||
test_api_gateway: FromDishka[TestApiGateway],
|
||||
database_clearer: FromDishka[DatabaseClearer],
|
||||
) -> None:
|
||||
await database_clearer.clear()
|
||||
|
||||
response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
|
||||
|
||||
response = await test_api_gateway.create_resume(
|
||||
access_token=response_sign_up.json()["access_token"],
|
||||
about_me="About me",
|
||||
experience_type="noExperience",
|
||||
key_skills=["i love lisp", "i love rust"],
|
||||
position="Position",
|
||||
)
|
||||
|
||||
response_other_sign_up = await test_api_gateway.sign_up_email("f" + unique_email, DEFAULT_PASSWORD)
|
||||
|
||||
response = await test_api_gateway.edit_resume(
|
||||
access_token=response_other_sign_up.json()["access_token"],
|
||||
resume_id=response.json()["resume_id"],
|
||||
about_me="Updated about me",
|
||||
experience_type="between1And3",
|
||||
key_skills=["i love python"],
|
||||
position="Updated Position",
|
||||
)
|
||||
|
||||
assert is_forbidden_response(response)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from collections.abc import Callable
|
||||
from collections.abc import AsyncIterable, Callable
|
||||
from inspect import Parameter
|
||||
from typing import Final
|
||||
|
||||
@@ -13,7 +13,8 @@ from dishka import (
|
||||
)
|
||||
from dishka.integrations.base import wrap_injection
|
||||
from dishka.integrations.fastapi import FastapiProvider
|
||||
from httpx import AsyncClient
|
||||
from fastapi import FastAPI
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
@@ -71,11 +72,13 @@ class TestProvider(Provider):
|
||||
database_clearer = provide(DatabaseClearer)
|
||||
|
||||
@provide
|
||||
def http_client(self) -> AsyncClient:
|
||||
return AsyncClient(base_url="http://backend:8080")
|
||||
async def http_client(self, app: FastAPI) -> AsyncIterable[AsyncClient]:
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as client:
|
||||
yield client
|
||||
|
||||
|
||||
def make_ioc(configuration: Configuration) -> AsyncContainer:
|
||||
def make_ioc(configuration: Configuration, app: FastAPI) -> AsyncContainer:
|
||||
return make_async_container(
|
||||
IdPProvider(),
|
||||
FactoryProvider(),
|
||||
@@ -97,6 +100,7 @@ def make_ioc(configuration: Configuration) -> AsyncContainer:
|
||||
FirebaseConfiguration: configuration.firebase,
|
||||
Configuration: configuration,
|
||||
S3Config: configuration.s3,
|
||||
FastAPI: app,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -78,3 +78,27 @@ class TestApiGateway:
|
||||
f"/resume/{resume_id}",
|
||||
headers=make_auth_headers(access_token),
|
||||
)
|
||||
|
||||
async def edit_resume(
|
||||
self,
|
||||
access_token: str,
|
||||
resume_id: str,
|
||||
position: str | None = None,
|
||||
about_me: str | None = None,
|
||||
key_skills: list[str] | None = None,
|
||||
experience_type: str | None = None,
|
||||
) -> Response:
|
||||
return await self._client.patch(
|
||||
f"/resume/{resume_id}",
|
||||
json={
|
||||
key: value
|
||||
for key, value in {
|
||||
"position": position,
|
||||
"about_me": about_me,
|
||||
"key_skills": key_skills,
|
||||
"experience_type": experience_type,
|
||||
}.items()
|
||||
if value is not None
|
||||
},
|
||||
headers=make_auth_headers(access_token),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user