From 5c0de7f70baa761f9d8ec3da6c0e47c742666e28 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Oct 2025 20:29:11 +0000 Subject: [PATCH] Add comprehensive tests for Groups API (24 tests) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- tests/aio/test_async_groups.py | 211 +++++++++++++++++++++++++++++++++ tests/endpoints/test_groups.py | 203 +++++++++++++++++++++++++++++++ tests/models/test_group.py | 109 +++++++++++++++++ 3 files changed, 523 insertions(+) create mode 100644 tests/aio/test_async_groups.py create mode 100644 tests/endpoints/test_groups.py create mode 100644 tests/models/test_group.py diff --git a/tests/aio/test_async_groups.py b/tests/aio/test_async_groups.py new file mode 100644 index 0000000..ffc7f08 --- /dev/null +++ b/tests/aio/test_async_groups.py @@ -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) diff --git a/tests/endpoints/test_groups.py b/tests/endpoints/test_groups.py new file mode 100644 index 0000000..3e91a31 --- /dev/null +++ b/tests/endpoints/test_groups.py @@ -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) diff --git a/tests/models/test_group.py b/tests/models/test_group.py new file mode 100644 index 0000000..a4bec07 --- /dev/null +++ b/tests/models/test_group.py @@ -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