diff --git a/test/conftest.py b/test/conftest.py index e5ab2a0..aae96dd 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -212,6 +212,45 @@ def generate_query_and_status(params) -> list[tuple[str, int]]: return query_and_status +def generate_body_and_status(params: dict[str, str]) -> list[tuple[dict, int]]: + possible_values_int = [0, -1, 42, "banana", ""] + possible_values_str = [0] + + defaults = [{param: 1 for param in params.keys()}] + + # Missing params + body_list = [ + {key: ("valid string" if params[key] == "str" else 1) for key in combo} + for r in range(len(defaults[0].keys()) + 1) + for combo in combinations(defaults[0].keys(), r) + ] + + # Complete body as default for generating invalid checks + default_body = body_list.pop(-1) + + # Generates checks for each param being invalid + for param, typ in params.items(): + if typ == "int": + possible_values = possible_values_int + elif typ == "str": + possible_values = possible_values_str + else: + raise TypeError(f"Unknown type {typ}") + for value in possible_values: + new_record = default_body.copy() + new_record[param] = value + body_list.append(new_record) + + body_and_status = [] + + # Assign expected status + for body in body_list: + # ID 42 is used to represent a non-existent entry. So it should 404. + status = 404 if 42 in body.values() else 422 + body_and_status.append((body, status)) + return body_and_status + + def get_testable_routes(): routes = [] diff --git a/test/test_iam.py b/test/test_iam.py index 03b4548..d879b26 100644 --- a/test/test_iam.py +++ b/test/test_iam.py @@ -3,8 +3,7 @@ import pytest from httpx import AsyncClient -from .conftest import generate_query_and_status - +from .conftest import generate_query_and_status, generate_body_and_status pytestmark = [ pytest.mark.iam_module, @@ -259,32 +258,7 @@ async def test_post_group_success(default_client: AsyncClient): @pytest.mark.parametrize( "body, expected_status", - [ - ({"organisation_id": 1, "name": "Org One Group"}, 409), - ( - {"organisation_id": 42, "name": "new group"}, - 404, - ), # Non-existent organisation, valid name - ( - {"organisation_id": "banana", "name": "new group"}, - 422, - ), # Invalid organisation ID, valid name - ( - {"organisation_id": "", "name": "new group"}, - 422, - ), # Blank organisation ID, valid name - ( - {"organisation_id": -1, "name": "new group"}, - 422, - ), # Negative organisation ID, valid name - ({"name": 1}, 422), # Only name - ({}, 422), # Blank body - ({"organisation_id": "", "name": ""}, 422), # Both blank - ({"organisation_id": 1, "name": 42}, 422), # Valid organisation, invalid name - ({"organisation_id": 1, "name": ""}, 422), # Valid organisation, blank name - ({"organisation_id": 1, "name": "hi"}, 422), # Valid organisation, small name - ({"organisation_id": 1}, 422), # Only organisation ID - ], + generate_body_and_status({"organisation_id": "int", "name": "str"}), ) @pytest.mark.anyio async def test_post_group_status_checks( @@ -295,6 +269,15 @@ async def test_post_group_status_checks( assert resp.status_code == expected_status +@pytest.mark.anyio +async def test_post_group_conflict(default_client: AsyncClient): + resp = await default_client.post( + "/iam/group", json={"organisation_id": 1, "name": "Org One Group"} + ) + + assert resp.status_code == 409 + + @pytest.mark.anyio async def test_put_group_perm_success(default_client: AsyncClient): resp = await default_client.put( @@ -322,67 +305,9 @@ async def test_put_group_perm_success(default_client: AsyncClient): @pytest.mark.parametrize( "body, expected_status", - [ - ( - {"organisation_id": 42, "group_id": 1, "permission_id": 1}, - 404, - ), # Non-existent organisation - ( - {"organisation_id": "banana", "group_id": 1, "permission_id": 1}, - 422, - ), # Invalid organisation ID - ( - {"organisation_id": "", "group_id": 1, "permission_id": 1}, - 422, - ), # Blank organisation ID - ( - {"organisation_id": -1, "group_id": 1, "permission_id": 1}, - 422, - ), # Negative organisation ID - ( - {"organisation_id": 1, "group_id": 42, "permission_id": 1}, - 404, - ), # Non-existent group - ( - {"organisation_id": 1, "group_id": "banana", "permission_id": 1}, - 422, - ), # Invalid group ID - ( - {"organisation_id": 1, "group_id": "", "permission_id": 1}, - 422, - ), # Blank group ID - ( - {"organisation_id": 1, "group_id": -1, "permission_id": 1}, - 422, - ), # Negative group ID - ( - {"organisation_id": 1, "group_id": 1, "permission_id": 42}, - 404, - ), # Non-existent permission - ( - {"organisation_id": 1, "group_id": 1, "permission_id": "banana"}, - 422, - ), # Invalid permission ID - ( - {"organisation_id": 1, "group_id": 1, "permission_id": ""}, - 422, - ), # Blank permission ID - ( - {"organisation_id": 1, "group_id": 1, "permission_id": -1}, - 422, - ), # Negative permission ID - ({}, 422), # Blank body - ({"permission_id": 1}, 422), # Only permission - ({"organisation_id": 1}, 422), # Only organisation - ({"group_id": 1}, 422), # Only group - ({"organisation_id": 1, "permission_id": 1}, 422), # Missing group - ({"group_id": 1, "permission_id": 1}, 422), # Missing organisation - ({"organisation_id": 1, "group_id": 1}, 422), # Missing permission - ( - {"organisation_id": 1, "group_id": 1, "permission_id": 1}, - 409, - ), # Permission already in group - ], + generate_body_and_status( + {"organisation_id": "int", "group_id": "int", "permission_id": "int"} + ), ) @pytest.mark.anyio async def test_put_group_perm_status_checks( @@ -393,6 +318,16 @@ async def test_put_group_perm_status_checks( assert resp.status_code == expected_status +@pytest.mark.anyio +async def test_put_group_perm_conflict(default_client: AsyncClient): + resp = await default_client.put( + "/iam/group/permission", + json={"organisation_id": 1, "group_id": 1, "permission_id": 1}, + ) + + assert resp.status_code == 409 + + @pytest.mark.parametrize( "body", [ @@ -434,54 +369,9 @@ async def test_put_group_user_success(default_client: AsyncClient): @pytest.mark.parametrize( "body, expected_status", - [ - ( - {"organisation_id": 42, "group_id": 1, "user_id": 1}, - 404, - ), # Non-existent organisation - ( - {"organisation_id": "banana", "group_id": 1, "user_id": 1}, - 422, - ), # Invalid organisation ID - ( - {"organisation_id": "", "group_id": 1, "user_id": 1}, - 422, - ), # Blank organisation ID - ( - {"organisation_id": -1, "group_id": 1, "user_id": 1}, - 422, - ), # Negative organisation ID - ( - {"organisation_id": 1, "group_id": 42, "user_id": 1}, - 404, - ), # Non-existent group - ( - {"organisation_id": 1, "group_id": "banana", "user_id": 1}, - 422, - ), # Invalid group ID - ({"organisation_id": 1, "group_id": "", "user_id": 1}, 422), # Blank group ID - ( - {"organisation_id": 1, "group_id": -1, "user_id": 1}, - 422, - ), # Negative group ID - ( - {"organisation_id": 1, "group_id": 1, "user_id": 42}, - 404, - ), # Non-existent user - ( - {"organisation_id": 1, "group_id": 1, "user_id": "banana"}, - 422, - ), # Invalid user ID - ({"organisation_id": 1, "group_id": 1, "user_id": ""}, 422), # Blank user ID - ({"organisation_id": 1, "group_id": 1, "user_id": -1}, 422), # Negative user ID - ({}, 422), # Blank body - ({"user_id": 1}, 422), # Only user - ({"organisation_id": 1}, 422), # Only organisation - ({"group_id": 1}, 422), # Only group - ({"organisation_id": 1, "user_id": 1}, 422), # Missing group - ({"group_id": 1, "user_id": 1}, 422), # Missing organisation - ({"organisation_id": 1, "group_id": 1}, 422), # Missing user - ], + generate_body_and_status( + {"organisation_id": "int", "group_id": "int", "user_id": "int"} + ), ) @pytest.mark.anyio async def test_put_group_user_status_checks( diff --git a/test/test_service.py b/test/test_service.py index 0114748..b874a89 100644 --- a/test/test_service.py +++ b/test/test_service.py @@ -5,8 +5,7 @@ import pytest from httpx import AsyncClient -from .conftest import generate_query_and_status - +from .conftest import generate_query_and_status, generate_body_and_status pytestmark = [ pytest.mark.service_module, @@ -51,12 +50,7 @@ async def test_post_service_success(default_client: AsyncClient): @pytest.mark.parametrize( - "body, expected_status", - [ - ({"name": "Test Service"}, 409), - ({"name": 42}, 422), - ({}, 422), - ], + "body, expected_status", generate_body_and_status({"name": "str"}) ) @pytest.mark.anyio async def test_post_service_status_checks( @@ -67,6 +61,13 @@ async def test_post_service_status_checks( assert resp.status_code == expected_status +@pytest.mark.anyio +async def test_post_service_conflict(default_client: AsyncClient): + resp = await default_client.post("/service", json={"name": "Test Service"}) + + assert resp.status_code == 409 + + @pytest.mark.anyio async def test_patch_service_success(default_client: AsyncClient): resp = await default_client.patch("/service/key", json={"service_id": 1}) @@ -82,12 +83,7 @@ async def test_patch_service_success(default_client: AsyncClient): @pytest.mark.parametrize( "body, expected_status", - [ - ({"service_id": 42}, 404), - ({"service_id": "Test Service"}, 422), - ({"service_id": ""}, 422), - ({}, 422), - ], + generate_body_and_status({"service_id": "int"}), ) @pytest.mark.anyio async def test_patch_services_status_checks(