arcade-mcp/toolkits/confluence/tests/test_utils.py
Sam Partee b6b4cd0a4c
🏗️ Restructure: Multi-Package Architecture + uv Migration (#412)
### Overview
Major restructuring from monolithic `arcade-ai` package to modular
library architecture with standardized uv-based dependency management.

![arcade-ai Monorepo
(2)](https://github.com/user-attachments/assets/25f102b0-bb87-4a04-9701-d227d05664b1)

### New Package Structure
- **`arcade-tdk`** - Lightweight toolkit development kit (core
decorators, auth)
- **`arcade-core`** - Core execution engine and catalog functionality  
- **`arcade-serve`** - FastAPI/MCP server components
- **`arcade-ai`** - Meta package that includes CLI functionality.
Optionally include evals via the `evals` extra. Optionally include all
packages via the `all` extra.

### Key Benefits
- **Lighter Dependencies**: Toolkits now depend only on `arcade-tdk` (~2
deps) vs full `arcade-ai` (~30+ deps)
- **Faster Builds**: uv provides 10-100x faster dependency resolution
and installation
- **Better Modularity**: Clear separation of concerns, consumers import
only what they need
- **Standard Tooling**: Eliminates custom poetry scripts, uses standard
Python packaging

### Migration Impact
- All 20 toolkits converted from poetry → uv with `arcade-tdk`
dependencies plus `arcade-ai[evals]` and `arcade-serve` dev
dependencies. When developing locally, devs should install toolkits via
`make install-local`.
- Modern Python 3.10+ type hints throughout
- Standardized build system with hatchling backend
- Enhanced Makefile with robust toolkit management commands
- Removed `arcade dev` CLI command
- Reduce the number of files created by `arcade new` and add an option
to not generate a tests and evals folder.

This foundation enables faster development cycles and cleaner dependency
chains for the growing toolkit ecosystem.

### Todo After this PR is merged
- [ ] Post-merge workflow(s) (release & publish containers, etc)
- [ ] Release order plan. @EricGustin suggests releasing in the
following order:
    1. `arcade-core` version 0.1.0
    2. `arcade-serve` version 0.1.0 and `arcade-tdk` version 0.1.0
    3. `arcade-ai` version 2.0.0
4. Patch release for all toolkits (all changes in toolkits are internal
refactors)
- [ ] [Update docs](https://github.com/ArcadeAI/docs/pull/318)

---------

Co-authored-by: Eric Gustin <eric@arcade.dev>
Co-authored-by: Eric Gustin <34000337+EricGustin@users.noreply.github.com>
2025-06-11 16:48:17 -07:00

195 lines
8.1 KiB
Python

import pytest
from arcade_tdk.errors import RetryableToolError, ToolExecutionError
from arcade_confluence.utils import build_child_url, build_hierarchy, validate_ids
@pytest.mark.parametrize(
"ids, max_length, expected_error",
[
(None, 250, None),
(["123", "456"], 250, None),
(["123", "foo"], 250, ToolExecutionError),
(["123", "456"], 1, RetryableToolError),
],
)
def test_validate_ids(ids: list[str], max_length: int, expected_error: Exception | None) -> None:
if expected_error:
with pytest.raises(expected_error):
validate_ids(ids, max_length)
else:
validate_ids(ids, max_length)
@pytest.mark.parametrize(
"base_url, child, expected",
[
( # Published page
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT",
{"type": "page", "title": "Test Title-1", "id": "123", "status": "current"},
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT/pages/123/Test+Title-1",
),
( # Draft page
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT",
{"type": "page", "title": "Test Title-1", "id": "123", "status": "draft"},
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT/pages/edit-v2/123",
),
( # Whiteboard
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT",
{"type": "whiteboard", "title": "Test Title-1", "id": "123", "status": "current"},
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT/whiteboard/123",
),
( # Database
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT",
{"type": "database", "title": "Test Title-1", "id": "123", "status": "current"},
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT/database/123",
),
( # Embed
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT",
{"type": "embed", "title": "Test Title-1", "id": "123", "status": "current"},
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT/embed/123",
),
( # Folder
"https://tes.atlassian.net/wiki/spaces/SOFTWAREDEVELOPMENT",
{"type": "folder", "title": "Test Title-1", "id": "123", "status": "current"},
None, # Folders don't have URLs
),
],
)
def test_build_child_url(base_url: str, child: dict, expected: str) -> None:
assert build_child_url(base_url, child) == expected
@pytest.mark.parametrize(
"input_transformed_children, input_parent_id, input_parent_node, expected_parent_node",
[
( # Parent node is a leaf
[],
"2195457",
{
"title": "A One Sentence Story About Trees",
"id": "2195457",
"type": "page",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2195457/A+One+Sentence+Story+About+Trees",
"children": [],
},
{
"title": "A One Sentence Story About Trees",
"id": "2195457",
"type": "page",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2195457/A+One+Sentence+Story+About+Trees",
"children": [],
},
),
(
[
{
"title": "The Importance of Trees",
"id": "2555906",
"type": "page",
"parent_id": "2162740",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2555906/The+Importance+of+Trees",
"children": [],
"status": "current",
},
{
"title": "Erics page",
"id": "2686977",
"type": "page",
"parent_id": "2555906",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2686977/Erics+page",
"children": [],
"status": "current",
},
{
"title": "Erics page",
"id": "2719745",
"type": "page",
"parent_id": "2555906",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/edit-v2/2719745",
"children": [],
"status": "draft",
},
{
"title": "Execute tools",
"id": "2621441",
"type": "page",
"parent_id": "2162740",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2621441/Execute+tools",
"children": [],
"status": "current",
},
],
"2162740",
{
"title": "Trees",
"id": "2162740",
"type": "page",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2162740/Trees",
"children": [],
},
{
"title": "Trees",
"id": "2162740",
"type": "page",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2162740/Trees",
"children": [
{
"title": "The Importance of Trees",
"id": "2555906",
"type": "page",
"parent_id": "2162740",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2555906/The+Importance+of+Trees",
"children": [
{
"title": "Erics page",
"id": "2686977",
"type": "page",
"parent_id": "2555906",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2686977/Erics+page",
"children": [],
"status": "current",
},
{
"title": "Erics page",
"id": "2719745",
"type": "page",
"parent_id": "2555906",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/edit-v2/2719745",
"children": [],
"status": "draft",
},
],
"status": "current",
},
{
"title": "Execute tools",
"id": "2621441",
"type": "page",
"parent_id": "2162740",
"parent_type": "TODO",
"url": "https://ericconfluence.atlassian.net/wiki/spaces/SOFTWAREDE/pages/2621441/Execute+tools",
"children": [],
"status": "current",
},
],
},
),
],
)
def test_build_hierarchy(
input_transformed_children: list[dict],
input_parent_id: int,
input_parent_node: dict,
expected_parent_node: dict,
) -> None:
# build_hierarchy modifies the input_parent_node in-place
build_hierarchy(input_transformed_children, input_parent_id, input_parent_node)
assert input_parent_node == expected_parent_node