mirror of
https://github.com/stack-auth/stack.git
synced 2026-07-20 21:29:36 +08:00
test: add failing tests for team membership, invitations, and profiles
- Tests for add_team_member, remove_team_member - Tests for send/list/revoke team invitations - Tests for list_team_member_profiles and get_team_member_profile - Async equivalents for all membership/invitation/profile operations
This commit is contained in:
@@ -1028,3 +1028,296 @@ class TestAsyncGetTeamByApiKey:
|
||||
team = await app.get_team_by_api_key("invalid")
|
||||
assert team is None
|
||||
await app.aclose()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Team membership test data
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
TEAM_MEMBER_PROFILE_JSON = {
|
||||
"userId": "user-1",
|
||||
"displayName": "Alice",
|
||||
"profileImageUrl": None,
|
||||
}
|
||||
|
||||
TEAM_MEMBER_PROFILE_JSON_2 = {
|
||||
"userId": "user-2",
|
||||
"displayName": "Bob",
|
||||
"profileImageUrl": "https://img.example.com/bob.png",
|
||||
}
|
||||
|
||||
TEAM_MEMBER_PROFILES_LIST_JSON = {
|
||||
"items": [TEAM_MEMBER_PROFILE_JSON, TEAM_MEMBER_PROFILE_JSON_2]
|
||||
}
|
||||
|
||||
INVITATION_JSON = {
|
||||
"id": "inv-1",
|
||||
"recipientEmail": "[email protected]",
|
||||
"expiresAtMillis": 1700100000000,
|
||||
}
|
||||
|
||||
INVITATION_JSON_2 = {
|
||||
"id": "inv-2",
|
||||
"recipientEmail": "[email protected]",
|
||||
"expiresAtMillis": 1700200000000,
|
||||
}
|
||||
|
||||
INVITATIONS_LIST_JSON = {"items": [INVITATION_JSON, INVITATION_JSON_2]}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# StackServerApp - add_team_member / remove_team_member
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestAddTeamMember:
|
||||
@respx.mock
|
||||
def test_add_team_member(self) -> None:
|
||||
route = respx.post(
|
||||
f"{API_PREFIX}/team-memberships/team-1/user-1"
|
||||
).mock(return_value=httpx.Response(200))
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = app.add_team_member("team-1", "user-1")
|
||||
assert result is None
|
||||
assert route.called
|
||||
|
||||
|
||||
class TestRemoveTeamMember:
|
||||
@respx.mock
|
||||
def test_remove_team_member(self) -> None:
|
||||
route = respx.delete(
|
||||
f"{API_PREFIX}/team-memberships/team-1/user-1"
|
||||
).mock(return_value=httpx.Response(200))
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = app.remove_team_member("team-1", "user-1")
|
||||
assert result is None
|
||||
assert route.called
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# StackServerApp - team invitations
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestSendTeamInvitation:
|
||||
@respx.mock
|
||||
def test_send_team_invitation_basic(self) -> None:
|
||||
route = respx.post(
|
||||
f"{API_PREFIX}/team-invitations/send-code"
|
||||
).mock(return_value=httpx.Response(200))
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = app.send_team_invitation("team-1", "[email protected]")
|
||||
assert result is None
|
||||
import json
|
||||
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["email"] == "[email protected]"
|
||||
assert body["team_id"] == "team-1"
|
||||
|
||||
@respx.mock
|
||||
def test_send_team_invitation_with_callback_url(self) -> None:
|
||||
route = respx.post(
|
||||
f"{API_PREFIX}/team-invitations/send-code"
|
||||
).mock(return_value=httpx.Response(200))
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
app.send_team_invitation(
|
||||
"team-1", "[email protected]", callback_url="https://example.com/accept"
|
||||
)
|
||||
import json
|
||||
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["callback_url"] == "https://example.com/accept"
|
||||
|
||||
|
||||
class TestListTeamInvitations:
|
||||
@respx.mock
|
||||
def test_list_team_invitations(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/teams/team-1/invitations").mock(
|
||||
return_value=httpx.Response(200, json=INVITATIONS_LIST_JSON)
|
||||
)
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
invitations = app.list_team_invitations("team-1")
|
||||
assert len(invitations) == 2
|
||||
assert invitations[0].id == "inv-1"
|
||||
assert invitations[0].recipient_email == "[email protected]"
|
||||
assert invitations[1].id == "inv-2"
|
||||
|
||||
|
||||
class TestRevokeTeamInvitation:
|
||||
@respx.mock
|
||||
def test_revoke_team_invitation(self) -> None:
|
||||
route = respx.delete(
|
||||
f"{API_PREFIX}/teams/team-1/invitations/inv-1"
|
||||
).mock(return_value=httpx.Response(200))
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = app.revoke_team_invitation("team-1", "inv-1")
|
||||
assert result is None
|
||||
assert route.called
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# StackServerApp - team member profiles
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestListTeamMemberProfiles:
|
||||
@respx.mock
|
||||
def test_list_team_member_profiles(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/team-member-profiles").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json=TEAM_MEMBER_PROFILES_LIST_JSON
|
||||
)
|
||||
)
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
profiles = app.list_team_member_profiles("team-1")
|
||||
assert len(profiles) == 2
|
||||
assert profiles[0].user_id == "user-1"
|
||||
assert profiles[0].display_name == "Alice"
|
||||
assert profiles[1].user_id == "user-2"
|
||||
|
||||
|
||||
class TestGetTeamMemberProfile:
|
||||
@respx.mock
|
||||
def test_get_team_member_profile_found(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/team-member-profiles").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json=TEAM_MEMBER_PROFILES_LIST_JSON
|
||||
)
|
||||
)
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
profile = app.get_team_member_profile("team-1", "user-2")
|
||||
assert profile is not None
|
||||
assert profile.user_id == "user-2"
|
||||
assert profile.display_name == "Bob"
|
||||
|
||||
@respx.mock
|
||||
def test_get_team_member_profile_not_found(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/team-member-profiles").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json=TEAM_MEMBER_PROFILES_LIST_JSON
|
||||
)
|
||||
)
|
||||
app = StackServerApp(project_id="proj", secret_server_key="sk")
|
||||
profile = app.get_team_member_profile("team-1", "nonexistent")
|
||||
assert profile is None
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# AsyncStackServerApp - membership, invitations, profiles
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestAsyncAddTeamMember:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_team_member(self) -> None:
|
||||
respx.post(f"{API_PREFIX}/team-memberships/team-1/user-1").mock(
|
||||
return_value=httpx.Response(200)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = await app.add_team_member("team-1", "user-1")
|
||||
assert result is None
|
||||
await app.aclose()
|
||||
|
||||
|
||||
class TestAsyncRemoveTeamMember:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_remove_team_member(self) -> None:
|
||||
respx.delete(f"{API_PREFIX}/team-memberships/team-1/user-1").mock(
|
||||
return_value=httpx.Response(200)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = await app.remove_team_member("team-1", "user-1")
|
||||
assert result is None
|
||||
await app.aclose()
|
||||
|
||||
|
||||
class TestAsyncSendTeamInvitation:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_team_invitation(self) -> None:
|
||||
route = respx.post(
|
||||
f"{API_PREFIX}/team-invitations/send-code"
|
||||
).mock(return_value=httpx.Response(200))
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = await app.send_team_invitation("team-1", "[email protected]")
|
||||
assert result is None
|
||||
import json
|
||||
|
||||
body = json.loads(route.calls[0].request.content)
|
||||
assert body["email"] == "[email protected]"
|
||||
assert body["team_id"] == "team-1"
|
||||
await app.aclose()
|
||||
|
||||
|
||||
class TestAsyncListTeamInvitations:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_team_invitations(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/teams/team-1/invitations").mock(
|
||||
return_value=httpx.Response(200, json=INVITATIONS_LIST_JSON)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
invitations = await app.list_team_invitations("team-1")
|
||||
assert len(invitations) == 2
|
||||
assert invitations[0].id == "inv-1"
|
||||
await app.aclose()
|
||||
|
||||
|
||||
class TestAsyncRevokeTeamInvitation:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_revoke_team_invitation(self) -> None:
|
||||
respx.delete(f"{API_PREFIX}/teams/team-1/invitations/inv-1").mock(
|
||||
return_value=httpx.Response(200)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
result = await app.revoke_team_invitation("team-1", "inv-1")
|
||||
assert result is None
|
||||
await app.aclose()
|
||||
|
||||
|
||||
class TestAsyncListTeamMemberProfiles:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_team_member_profiles(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/team-member-profiles").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json=TEAM_MEMBER_PROFILES_LIST_JSON
|
||||
)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
profiles = await app.list_team_member_profiles("team-1")
|
||||
assert len(profiles) == 2
|
||||
assert profiles[0].user_id == "user-1"
|
||||
await app.aclose()
|
||||
|
||||
|
||||
class TestAsyncGetTeamMemberProfile:
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_team_member_profile_found(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/team-member-profiles").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json=TEAM_MEMBER_PROFILES_LIST_JSON
|
||||
)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
profile = await app.get_team_member_profile("team-1", "user-2")
|
||||
assert profile is not None
|
||||
assert profile.display_name == "Bob"
|
||||
await app.aclose()
|
||||
|
||||
@respx.mock
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_team_member_profile_not_found(self) -> None:
|
||||
respx.get(f"{API_PREFIX}/team-member-profiles").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json=TEAM_MEMBER_PROFILES_LIST_JSON
|
||||
)
|
||||
)
|
||||
app = AsyncStackServerApp(project_id="proj", secret_server_key="sk")
|
||||
profile = await app.get_team_member_profile("team-1", "nonexistent")
|
||||
assert profile is None
|
||||
await app.aclose()
|
||||
|
||||
Reference in New Issue
Block a user