forked from cardosofelipe/fast-next-template
Add E2E tests for admin and organization workflows
- Introduced E2E tests for admin user and organization management workflows: user listing, creation, updates, bulk actions, and organization membership management. - Added comprehensive tests for organization CRUD operations, membership visibility, roles, and permission validation. - Expanded fixtures for superuser and member setup to streamline testing of admin-specific operations. - Verified pagination, filtering, and action consistency across admin endpoints.
This commit is contained in:
@@ -155,3 +155,175 @@ class TestOrganizationMembershipWorkflows:
|
||||
)
|
||||
|
||||
assert response.status_code in [403, 404]
|
||||
|
||||
|
||||
class TestOrganizationWithMembers:
|
||||
"""Test organization workflows using e2e_org_with_members fixture."""
|
||||
|
||||
async def test_owner_can_view_organization(self, e2e_client, e2e_org_with_members):
|
||||
"""Organization owner can view organization details."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/organizations/{org['org_id']}",
|
||||
headers={"Authorization": f"Bearer {org['owner']['tokens']['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["id"] == org["org_id"]
|
||||
assert data["name"] == org["org_name"]
|
||||
|
||||
async def test_member_can_view_organization(self, e2e_client, e2e_org_with_members):
|
||||
"""Organization member can view organization details."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/organizations/{org['org_id']}",
|
||||
headers={"Authorization": f"Bearer {org['member']['tokens']['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["id"] == org["org_id"]
|
||||
|
||||
async def test_owner_can_list_members(self, e2e_client, e2e_org_with_members):
|
||||
"""Organization owner can list members."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/organizations/{org['org_id']}/members",
|
||||
headers={"Authorization": f"Bearer {org['owner']['tokens']['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
# Should have owner + member = at least 2 members
|
||||
assert len(data) >= 2
|
||||
|
||||
async def test_member_can_list_members(self, e2e_client, e2e_org_with_members):
|
||||
"""Organization member can list members."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/organizations/{org['org_id']}/members",
|
||||
headers={"Authorization": f"Bearer {org['member']['tokens']['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
async def test_owner_appears_in_my_organizations(self, e2e_client, e2e_org_with_members):
|
||||
"""Owner sees organization in their organizations list."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
"/api/v1/organizations/me",
|
||||
headers={"Authorization": f"Bearer {org['owner']['tokens']['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
org_ids = [o["id"] for o in data]
|
||||
assert org["org_id"] in org_ids
|
||||
|
||||
async def test_member_appears_in_my_organizations(self, e2e_client, e2e_org_with_members):
|
||||
"""Member sees organization in their organizations list."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
"/api/v1/organizations/me",
|
||||
headers={"Authorization": f"Bearer {org['member']['tokens']['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
org_ids = [o["id"] for o in data]
|
||||
assert org["org_id"] in org_ids
|
||||
|
||||
async def test_owner_can_update_organization(self, e2e_client, e2e_org_with_members):
|
||||
"""Organization owner can update organization details."""
|
||||
org = e2e_org_with_members
|
||||
new_description = f"Updated at {uuid4().hex[:8]}"
|
||||
|
||||
response = await e2e_client.put(
|
||||
f"/api/v1/organizations/{org['org_id']}",
|
||||
headers={"Authorization": f"Bearer {org['owner']['tokens']['access_token']}"},
|
||||
json={"description": new_description},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["description"] == new_description
|
||||
|
||||
async def test_member_cannot_update_organization(self, e2e_client, e2e_org_with_members):
|
||||
"""Regular member cannot update organization details."""
|
||||
org = e2e_org_with_members
|
||||
|
||||
response = await e2e_client.put(
|
||||
f"/api/v1/organizations/{org['org_id']}",
|
||||
headers={"Authorization": f"Bearer {org['member']['tokens']['access_token']}"},
|
||||
json={"description": "Should fail"},
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
|
||||
async def test_non_member_cannot_view_organization(
|
||||
self, e2e_client, e2e_org_with_members
|
||||
):
|
||||
"""Non-members cannot view organization details."""
|
||||
org = e2e_org_with_members
|
||||
|
||||
# Create a new user who is not a member
|
||||
non_member_email = f"nonmember-{uuid4().hex[:8]}@example.com"
|
||||
tokens = await register_and_login(e2e_client, non_member_email)
|
||||
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/organizations/{org['org_id']}",
|
||||
headers={"Authorization": f"Bearer {tokens['access_token']}"},
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
|
||||
async def test_get_organization_by_slug(self, e2e_client, e2e_org_with_members):
|
||||
"""Organization can be retrieved by slug."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/organizations/slug/{org['org_slug']}",
|
||||
headers={
|
||||
"Authorization": f"Bearer {org['owner']['tokens']['access_token']}"
|
||||
},
|
||||
)
|
||||
|
||||
# May be 200 or 404/403 depending on implementation
|
||||
assert response.status_code in [200, 403, 404]
|
||||
|
||||
|
||||
class TestOrganizationAdminOperations:
|
||||
"""Test organization admin operations."""
|
||||
|
||||
async def test_admin_list_org_members_with_pagination(
|
||||
self, e2e_client, e2e_superuser, e2e_org_with_members
|
||||
):
|
||||
"""Admin can list org members with pagination."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/admin/organizations/{org['org_id']}/members",
|
||||
headers={
|
||||
"Authorization": f"Bearer {e2e_superuser['tokens']['access_token']}"
|
||||
},
|
||||
params={"page": 1, "limit": 10},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "data" in data
|
||||
assert "pagination" in data
|
||||
|
||||
async def test_admin_list_org_members_filter_active(
|
||||
self, e2e_client, e2e_superuser, e2e_org_with_members
|
||||
):
|
||||
"""Admin can filter org members by active status."""
|
||||
org = e2e_org_with_members
|
||||
response = await e2e_client.get(
|
||||
f"/api/v1/admin/organizations/{org['org_id']}/members",
|
||||
headers={
|
||||
"Authorization": f"Bearer {e2e_superuser['tokens']['access_token']}"
|
||||
},
|
||||
params={"is_active": True},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user