Add comprehensive tests for Groups API (24 tests)
Tests include: - Group model validation (8 tests) - Group, GroupCreate, GroupUpdate models - Field validation, name validation - Minimal and full field tests - Sync GroupsEndpoint (8 tests) - List, get, create, update, delete operations - User assignment/unassignment operations - Validation error handling - Async AsyncGroupsEndpoint (8 tests) - Complete async coverage matching sync API - All CRUD operations tested - User management operations All 24 tests passing. Achieves comprehensive coverage for Groups API. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
211
tests/aio/test_async_groups.py
Normal file
211
tests/aio/test_async_groups.py
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
"""Tests for async Groups endpoint."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock, Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from wikijs.aio.endpoints import AsyncGroupsEndpoint
|
||||||
|
from wikijs.exceptions import APIError, ValidationError
|
||||||
|
from wikijs.models import Group, GroupCreate, GroupUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class TestAsyncGroupsEndpoint:
|
||||||
|
"""Test AsyncGroupsEndpoint class."""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client(self):
|
||||||
|
"""Create mock async client."""
|
||||||
|
mock_client = Mock()
|
||||||
|
mock_client.base_url = "https://wiki.example.com"
|
||||||
|
mock_client._request = AsyncMock()
|
||||||
|
return mock_client
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def endpoint(self, client):
|
||||||
|
"""Create AsyncGroupsEndpoint instance."""
|
||||||
|
return AsyncGroupsEndpoint(client)
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_list_groups(self, endpoint):
|
||||||
|
"""Test listing groups."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Administrators",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": ["manage:system"],
|
||||||
|
"pageRules": [],
|
||||||
|
"users": [],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
groups = await endpoint.list()
|
||||||
|
|
||||||
|
assert len(groups) == 1
|
||||||
|
assert isinstance(groups[0], Group)
|
||||||
|
assert groups[0].name == "Administrators"
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_group(self, endpoint):
|
||||||
|
"""Test getting a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"single": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Administrators",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": ["manage:system"],
|
||||||
|
"pageRules": [],
|
||||||
|
"users": [{"id": 1, "name": "Admin", "email": "admin@example.com"}],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
group = await endpoint.get(1)
|
||||||
|
|
||||||
|
assert isinstance(group, Group)
|
||||||
|
assert group.id == 1
|
||||||
|
assert len(group.users) == 1
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_create_group(self, endpoint):
|
||||||
|
"""Test creating a group."""
|
||||||
|
group_data = GroupCreate(name="Editors", permissions=["read:pages"])
|
||||||
|
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"create": {
|
||||||
|
"responseResult": {"succeeded": True},
|
||||||
|
"group": {
|
||||||
|
"id": 2,
|
||||||
|
"name": "Editors",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": ["read:pages"],
|
||||||
|
"pageRules": [],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
group = await endpoint.create(group_data)
|
||||||
|
|
||||||
|
assert isinstance(group, Group)
|
||||||
|
assert group.name == "Editors"
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_update_group(self, endpoint):
|
||||||
|
"""Test updating a group."""
|
||||||
|
update_data = GroupUpdate(name="Senior Editors")
|
||||||
|
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"update": {
|
||||||
|
"responseResult": {"succeeded": True},
|
||||||
|
"group": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Senior Editors",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": [],
|
||||||
|
"pageRules": [],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-02T00:00:00Z",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
group = await endpoint.update(1, update_data)
|
||||||
|
|
||||||
|
assert group.name == "Senior Editors"
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_delete_group(self, endpoint):
|
||||||
|
"""Test deleting a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"delete": {
|
||||||
|
"responseResult": {"succeeded": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
result = await endpoint.delete(1)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_assign_user(self, endpoint):
|
||||||
|
"""Test assigning a user to a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"assignUser": {
|
||||||
|
"responseResult": {"succeeded": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
result = await endpoint.assign_user(group_id=1, user_id=5)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_unassign_user(self, endpoint):
|
||||||
|
"""Test removing a user from a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"unassignUser": {
|
||||||
|
"responseResult": {"succeeded": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = AsyncMock(return_value=mock_response)
|
||||||
|
|
||||||
|
result = await endpoint.unassign_user(group_id=1, user_id=5)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_validation_errors(self, endpoint):
|
||||||
|
"""Test validation errors."""
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
await endpoint.get(0)
|
||||||
|
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
await endpoint.delete(-1)
|
||||||
|
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
await endpoint.assign_user(0, 1)
|
||||||
203
tests/endpoints/test_groups.py
Normal file
203
tests/endpoints/test_groups.py
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
"""Tests for Groups endpoint."""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from wikijs.endpoints import GroupsEndpoint
|
||||||
|
from wikijs.exceptions import APIError, ValidationError
|
||||||
|
from wikijs.models import Group, GroupCreate, GroupUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class TestGroupsEndpoint:
|
||||||
|
"""Test GroupsEndpoint class."""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client(self):
|
||||||
|
"""Create mock client."""
|
||||||
|
mock_client = Mock()
|
||||||
|
mock_client.base_url = "https://wiki.example.com"
|
||||||
|
mock_client._request = Mock()
|
||||||
|
return mock_client
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def endpoint(self, client):
|
||||||
|
"""Create GroupsEndpoint instance."""
|
||||||
|
return GroupsEndpoint(client)
|
||||||
|
|
||||||
|
def test_list_groups(self, endpoint):
|
||||||
|
"""Test listing groups."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Administrators",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": ["manage:system"],
|
||||||
|
"pageRules": [],
|
||||||
|
"users": [],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
groups = endpoint.list()
|
||||||
|
|
||||||
|
assert len(groups) == 1
|
||||||
|
assert isinstance(groups[0], Group)
|
||||||
|
assert groups[0].name == "Administrators"
|
||||||
|
|
||||||
|
def test_get_group(self, endpoint):
|
||||||
|
"""Test getting a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"single": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Administrators",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": ["manage:system"],
|
||||||
|
"pageRules": [],
|
||||||
|
"users": [{"id": 1, "name": "Admin", "email": "admin@example.com"}],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
group = endpoint.get(1)
|
||||||
|
|
||||||
|
assert isinstance(group, Group)
|
||||||
|
assert group.id == 1
|
||||||
|
assert len(group.users) == 1
|
||||||
|
|
||||||
|
def test_create_group(self, endpoint):
|
||||||
|
"""Test creating a group."""
|
||||||
|
group_data = GroupCreate(name="Editors", permissions=["read:pages"])
|
||||||
|
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"create": {
|
||||||
|
"responseResult": {"succeeded": True},
|
||||||
|
"group": {
|
||||||
|
"id": 2,
|
||||||
|
"name": "Editors",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": ["read:pages"],
|
||||||
|
"pageRules": [],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-01T00:00:00Z",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
group = endpoint.create(group_data)
|
||||||
|
|
||||||
|
assert isinstance(group, Group)
|
||||||
|
assert group.name == "Editors"
|
||||||
|
|
||||||
|
def test_update_group(self, endpoint):
|
||||||
|
"""Test updating a group."""
|
||||||
|
update_data = GroupUpdate(name="Senior Editors")
|
||||||
|
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"update": {
|
||||||
|
"responseResult": {"succeeded": True},
|
||||||
|
"group": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Senior Editors",
|
||||||
|
"isSystem": False,
|
||||||
|
"redirectOnLogin": "/",
|
||||||
|
"permissions": [],
|
||||||
|
"pageRules": [],
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z",
|
||||||
|
"updatedAt": "2024-01-02T00:00:00Z",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
group = endpoint.update(1, update_data)
|
||||||
|
|
||||||
|
assert group.name == "Senior Editors"
|
||||||
|
|
||||||
|
def test_delete_group(self, endpoint):
|
||||||
|
"""Test deleting a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"delete": {
|
||||||
|
"responseResult": {"succeeded": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
result = endpoint.delete(1)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
def test_assign_user(self, endpoint):
|
||||||
|
"""Test assigning a user to a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"assignUser": {
|
||||||
|
"responseResult": {"succeeded": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
result = endpoint.assign_user(group_id=1, user_id=5)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
def test_unassign_user(self, endpoint):
|
||||||
|
"""Test removing a user from a group."""
|
||||||
|
mock_response = {
|
||||||
|
"data": {
|
||||||
|
"groups": {
|
||||||
|
"unassignUser": {
|
||||||
|
"responseResult": {"succeeded": True}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoint._post = Mock(return_value=mock_response)
|
||||||
|
|
||||||
|
result = endpoint.unassign_user(group_id=1, user_id=5)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
def test_validation_errors(self, endpoint):
|
||||||
|
"""Test validation errors."""
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
endpoint.get(0)
|
||||||
|
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
endpoint.delete(-1)
|
||||||
|
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
endpoint.assign_user(0, 1)
|
||||||
109
tests/models/test_group.py
Normal file
109
tests/models/test_group.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
"""Tests for Group data models."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
from wikijs.models import Group, GroupCreate, GroupUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class TestGroup:
|
||||||
|
"""Test Group model."""
|
||||||
|
|
||||||
|
def test_group_creation_minimal(self):
|
||||||
|
"""Test creating a group with minimal fields."""
|
||||||
|
group = Group(
|
||||||
|
id=1,
|
||||||
|
name="Administrators",
|
||||||
|
created_at="2024-01-01T00:00:00Z",
|
||||||
|
updated_at="2024-01-01T00:00:00Z",
|
||||||
|
)
|
||||||
|
assert group.id == 1
|
||||||
|
assert group.name == "Administrators"
|
||||||
|
assert group.is_system is False
|
||||||
|
assert group.permissions == []
|
||||||
|
assert group.page_rules == []
|
||||||
|
assert group.users == []
|
||||||
|
|
||||||
|
def test_group_creation_full(self):
|
||||||
|
"""Test creating a group with all fields."""
|
||||||
|
group = Group(
|
||||||
|
id=1,
|
||||||
|
name="Editors",
|
||||||
|
is_system=False,
|
||||||
|
redirect_on_login="/dashboard",
|
||||||
|
permissions=["read:pages", "write:pages"],
|
||||||
|
page_rules=[
|
||||||
|
{"id": "1", "path": "/docs/*", "roles": ["write"], "match": "START"}
|
||||||
|
],
|
||||||
|
users=[{"id": 1, "name": "John Doe", "email": "john@example.com"}],
|
||||||
|
created_at="2024-01-01T00:00:00Z",
|
||||||
|
updated_at="2024-01-01T00:00:00Z",
|
||||||
|
)
|
||||||
|
assert group.name == "Editors"
|
||||||
|
assert group.redirect_on_login == "/dashboard"
|
||||||
|
assert len(group.permissions) == 2
|
||||||
|
assert len(group.page_rules) == 1
|
||||||
|
assert len(group.users) == 1
|
||||||
|
|
||||||
|
def test_group_name_validation(self):
|
||||||
|
"""Test name validation."""
|
||||||
|
# Too short
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
Group(
|
||||||
|
id=1,
|
||||||
|
name="",
|
||||||
|
created_at="2024-01-01T00:00:00Z",
|
||||||
|
updated_at="2024-01-01T00:00:00Z",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Too long
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
Group(
|
||||||
|
id=1,
|
||||||
|
name="x" * 256,
|
||||||
|
created_at="2024-01-01T00:00:00Z",
|
||||||
|
updated_at="2024-01-01T00:00:00Z",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGroupCreate:
|
||||||
|
"""Test GroupCreate model."""
|
||||||
|
|
||||||
|
def test_group_create_minimal(self):
|
||||||
|
"""Test creating group with minimal fields."""
|
||||||
|
group_data = GroupCreate(name="Test Group")
|
||||||
|
assert group_data.name == "Test Group"
|
||||||
|
assert group_data.permissions == []
|
||||||
|
assert group_data.page_rules == []
|
||||||
|
|
||||||
|
def test_group_create_full(self):
|
||||||
|
"""Test creating group with all fields."""
|
||||||
|
group_data = GroupCreate(
|
||||||
|
name="Test Group",
|
||||||
|
redirect_on_login="/home",
|
||||||
|
permissions=["read:pages"],
|
||||||
|
page_rules=[{"path": "/*", "roles": ["read"]}],
|
||||||
|
)
|
||||||
|
assert group_data.redirect_on_login == "/home"
|
||||||
|
assert len(group_data.permissions) == 1
|
||||||
|
|
||||||
|
def test_group_create_name_validation(self):
|
||||||
|
"""Test name validation."""
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
GroupCreate(name="")
|
||||||
|
|
||||||
|
|
||||||
|
class TestGroupUpdate:
|
||||||
|
"""Test GroupUpdate model."""
|
||||||
|
|
||||||
|
def test_group_update_empty(self):
|
||||||
|
"""Test empty update."""
|
||||||
|
update_data = GroupUpdate()
|
||||||
|
assert update_data.name is None
|
||||||
|
assert update_data.permissions is None
|
||||||
|
|
||||||
|
def test_group_update_partial(self):
|
||||||
|
"""Test partial update."""
|
||||||
|
update_data = GroupUpdate(name="Updated Name")
|
||||||
|
assert update_data.name == "Updated Name"
|
||||||
|
assert update_data.permissions is None
|
||||||
Reference in New Issue
Block a user