-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OCT-2249: Add unit tests for /projects & improve searching (#627)
## Description ## Definition of Done 1. [ ] If required, the desciption of your change is added to the [QA changelog](https://www.notion.so/octantapp/Changelog-for-the-QA-d96fa3b411cf488bb1d8d9a598d88281) 2. [ ] Acceptance criteria are met. 3. [ ] PR is manually tested before the merge by developer(s). - [ ] Happy path is manually checked. 4. [ ] PR is manually tested by QA when their assistance is required (1). - [ ] Octant Areas & Test Cases are checked for impact and updated if required (2). 5. [ ] Unit tests are added unless there is a reason to omit them. 6. [ ] Automated tests are added when required. 7. [ ] The code is merged. 8. [ ] Tech documentation is added / updated, reviewed and approved (including mandatory approval by a code owner, should such exist for changed files). - [ ] BE: Swagger documentation is updated. 9. [ ] When required by QA: - [ ] Deployed to the relevant environment. - [ ] Passed system tests. --- (1) Developer(s) in coordination with QA decide whether it's required. For small tickets introducing small changes QA assistance is most probably not required. (2) [Octant Areas & Test Cases](https://docs.google.com/spreadsheets/d/1cRe6dxuKJV3a4ZskAwWEPvrFkQm6rEfyUCYwLTYw_Cc).
- Loading branch information
1 parent
562f1b1
commit 4c860fd
Showing
12 changed files
with
413 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from async_factory_boy.factory.sqlalchemy import AsyncSQLAlchemyFactory | ||
from factory import LazyAttribute | ||
|
||
from app.infrastructure.database.models import ProjectsDetails | ||
from tests.v2.factories.base import FactorySetBase | ||
from tests.v2.factories.helpers import generate_random_eip55_address | ||
from v2.core.types import Address | ||
|
||
|
||
class ProjectsDetailsFactory(AsyncSQLAlchemyFactory): | ||
class Meta: | ||
model = ProjectsDetails | ||
sqlalchemy_session_persistence = "commit" | ||
|
||
address = LazyAttribute(lambda _: generate_random_eip55_address()) | ||
name = None | ||
epoch = None | ||
|
||
|
||
class ProjectsDetailsFactorySet(FactorySetBase): | ||
_factories = {"projects_details": ProjectsDetailsFactory} | ||
|
||
async def create( | ||
self, | ||
name: str, | ||
epoch: int, | ||
address: Address | None = None, | ||
) -> ProjectsDetails: | ||
factory_kwargs = { | ||
"address": address, | ||
"name": name, | ||
"epoch": epoch, | ||
} | ||
|
||
if address is not None: | ||
factory_kwargs["address"] = address | ||
|
||
projects_details = await ProjectsDetailsFactory.create(**factory_kwargs) | ||
|
||
return projects_details |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from tests.v2.fake_contracts.helpers import FakeProjectsContractDetails | ||
|
||
|
||
class FakeProjectsContract: | ||
def __init__(self, projects_details_for_contract: FakeProjectsContractDetails): | ||
self.projects_details_for_contract = projects_details_for_contract | ||
|
||
async def get_project_addresses(self, epoch_number: int) -> list[str]: | ||
filtered_projects_details = list( | ||
filter( | ||
lambda project_details: project_details.epoch_number == epoch_number, | ||
self.projects_details_for_contract.projects_details, | ||
) | ||
) | ||
return list( | ||
map( | ||
lambda project_details: project_details.address, | ||
filtered_projects_details, | ||
) | ||
) | ||
|
||
async def get_project_cid(self) -> str: | ||
return self.projects_details_for_contract.projects_cid |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import pytest | ||
|
||
from tests.v2.fake_contracts.conftest import ( # noqa: F401 | ||
fake_projects_contract_factory, | ||
) | ||
|
||
from tests.v2.factories.helpers import generate_random_eip55_address | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def multiple_project_details_simple() -> list: | ||
details = [ | ||
{ | ||
"name": "test_project1", | ||
"epoch": 3, | ||
"address": generate_random_eip55_address(), | ||
}, | ||
{ | ||
"name": "test_project2", | ||
"epoch": 2, | ||
"address": generate_random_eip55_address(), | ||
}, | ||
{ | ||
"name": "test_project3", | ||
"epoch": 1, | ||
"address": generate_random_eip55_address(), | ||
}, | ||
] | ||
|
||
return details | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def multiple_project_details_various() -> list: | ||
details = [ | ||
{ | ||
"name": "test_project1", | ||
"epoch": 3, | ||
"address": generate_random_eip55_address(), | ||
}, | ||
{ | ||
"name": "octant_project2", | ||
"epoch": 2, | ||
"address": generate_random_eip55_address(), | ||
}, | ||
{ | ||
"name": "great_project3", | ||
"epoch": 1, | ||
"address": generate_random_eip55_address(), | ||
}, | ||
] | ||
return details |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
from http import HTTPStatus | ||
|
||
import pytest | ||
from httpx import AsyncClient | ||
from sqlalchemy.ext.asyncio import AsyncSession | ||
|
||
from tests.v2.factories import FactoriesAggregator | ||
from tests.v2.factories.helpers import generate_random_eip55_address | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_returns_empty_project_details( | ||
fast_client: AsyncClient, fast_session: AsyncSession | ||
): | ||
async with fast_client as client: | ||
resp = await client.get("projects/details?epochs=1&searchPhrases=test") | ||
assert resp.status_code == HTTPStatus.OK | ||
assert resp.json() == {"projectsDetails": []} | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_returns_correct_project_details_for_single_filter( | ||
fast_client: AsyncClient, factories: FactoriesAggregator | ||
): | ||
single_details = { | ||
"name": "test_project1", | ||
"epoch": 3, | ||
"address": generate_random_eip55_address(), | ||
} | ||
|
||
await factories.projects_details.create(**single_details) | ||
|
||
async with fast_client as client: | ||
resp = await client.get("projects/details?epochs=3&searchPhrases=test_project") | ||
assert resp.status_code == HTTPStatus.OK | ||
assert resp.json() == { | ||
"projectsDetails": [ | ||
{ | ||
"name": single_details["name"], | ||
"epoch": str(single_details["epoch"]), | ||
"address": single_details["address"], | ||
} | ||
] | ||
} | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_returns_correct_project_details_for_many_epochs( | ||
fast_client: AsyncClient, | ||
factories: FactoriesAggregator, | ||
multiple_project_details_simple: list, | ||
): | ||
details = multiple_project_details_simple | ||
|
||
for detail in details: | ||
await factories.projects_details.create(**detail) | ||
|
||
async with fast_client as client: | ||
resp = await client.get("projects/details?epochs=1,2,3&searchPhrases=test") | ||
assert resp.status_code == HTTPStatus.OK | ||
|
||
assert resp.json() == { | ||
"projectsDetails": [ | ||
{ | ||
"name": details[2]["name"], | ||
"epoch": str(details[2]["epoch"]), | ||
"address": details[2]["address"], | ||
}, | ||
{ | ||
"name": details[1]["name"], | ||
"epoch": str(details[1]["epoch"]), | ||
"address": details[1]["address"], | ||
}, | ||
{ | ||
"name": details[0]["name"], | ||
"epoch": str(details[0]["epoch"]), | ||
"address": details[0]["address"], | ||
}, | ||
] | ||
} | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_returns_correct_project_details_for_many_epochs_and_search_phrases( | ||
fast_client: AsyncClient, | ||
factories: FactoriesAggregator, | ||
multiple_project_details_various: list, | ||
): | ||
details = multiple_project_details_various | ||
|
||
for detail in details: | ||
await factories.projects_details.create(**detail) | ||
|
||
async with fast_client as client: | ||
resp = await client.get( | ||
"projects/details?epochs=1,2,3&searchPhrases=test,octant,great" | ||
) | ||
assert resp.status_code == HTTPStatus.OK | ||
|
||
assert resp.json() == { | ||
"projectsDetails": [ | ||
{ | ||
"name": details[2]["name"], | ||
"epoch": str(details[2]["epoch"]), | ||
"address": details[2]["address"], | ||
}, | ||
{ | ||
"name": details[1]["name"], | ||
"epoch": str(details[1]["epoch"]), | ||
"address": details[1]["address"], | ||
}, | ||
{ | ||
"name": details[0]["name"], | ||
"epoch": str(details[0]["epoch"]), | ||
"address": details[0]["address"], | ||
}, | ||
] | ||
} | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_returns_not_duplicated_project_details_for_words_from_the_same_project( | ||
fast_client: AsyncClient, | ||
factories: FactoriesAggregator, | ||
multiple_project_details_various: list, | ||
): | ||
details = multiple_project_details_various | ||
words = "test,project1" | ||
|
||
for detail in details: | ||
await factories.projects_details.create(**detail) | ||
|
||
async with fast_client as client: | ||
resp = await client.get(f"projects/details?epochs=3&searchPhrases={words}") | ||
assert resp.status_code == HTTPStatus.OK | ||
assert resp.json() == { | ||
"projectsDetails": [ | ||
{ | ||
"name": details[0]["name"], | ||
"epoch": str(details[0]["epoch"]), | ||
"address": details[0]["address"], | ||
} | ||
] | ||
} |
Oops, something went wrong.