108 lines
4.0 KiB
Python
108 lines
4.0 KiB
Python
|
|
"""Fixture payloads for ``POST /usercenter/dept/tree`` (Task 2.0).
|
||
|
|
|
||
|
|
yunke's dept/tree endpoint follows the same convention as the permissions API:
|
||
|
|
nodes carry ``id`` / ``pId`` / ``name``, and the tree MAY be delivered either
|
||
|
|
as a flat list of nodes or as a nested tree (each node optionally carrying a
|
||
|
|
``children`` array). The scraper must flatten both shapes into one flat list
|
||
|
|
of nodes and reconstruct ``parent_id`` from ``pId``.
|
||
|
|
|
||
|
|
This cassette provides TWO realistic capture-shaped payloads so the scraper
|
||
|
|
tests can prove both shapes flatten to the SAME set of nodes:
|
||
|
|
|
||
|
|
* ``NESTED_TREE_PAYLOAD`` — a root with two children, one of which has its own
|
||
|
|
sub-child (3 levels deep). Nested via ``children``.
|
||
|
|
* ``FLAT_TREE_PAYLOAD`` — the exact same 4 nodes delivered as a flat list
|
||
|
|
(parent links carried by ``pId``).
|
||
|
|
|
||
|
|
Both decode to the same 4 departments with the same ids / parents / names /
|
||
|
|
paths, so the scraper test can swap the envelope and re-assert.
|
||
|
|
|
||
|
|
The 4 nodes:
|
||
|
|
root "Sales" (id="1", pId="0")
|
||
|
|
├── "East" (id="1.1", pId="1")
|
||
|
|
│ └── "TeamA" (id="1.1.1", pId="1.1")
|
||
|
|
└── "North" (id="1.2", pId="1")
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# The canonical 4 nodes (single source of truth for both shapes below)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
# Root has pId="0" — the common yunke convention for "no parent". The scraper
|
||
|
|
# treats any falsy pId (None / "" / "0") OR an unknown pId as "root".
|
||
|
|
ROOT_NODE: dict[str, Any] = {"id": "1", "pId": "0", "name": "Sales"}
|
||
|
|
EAST_NODE: dict[str, Any] = {"id": "1.1", "pId": "1", "name": "East"}
|
||
|
|
TEAMA_NODE: dict[str, Any] = {"id": "1.1.1", "pId": "1.1", "name": "TeamA"}
|
||
|
|
NORTH_NODE: dict[str, Any] = {"id": "1.2", "pId": "1", "name": "North"}
|
||
|
|
|
||
|
|
# All four nodes, in a stable order matching a depth-first traversal of the
|
||
|
|
# nested tree. Tests assert the scraper yields exactly these (order is not
|
||
|
|
# load-bearing — tests compare as sets where appropriate).
|
||
|
|
ALL_NODES: list[dict[str, Any]] = [ROOT_NODE, EAST_NODE, TEAMA_NODE, NORTH_NODE]
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Nested envelope — root carries children, recursively
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
NESTED_TREE_NODES: list[dict[str, Any]] = [
|
||
|
|
{
|
||
|
|
**ROOT_NODE,
|
||
|
|
"children": [
|
||
|
|
{
|
||
|
|
**EAST_NODE,
|
||
|
|
"children": [{**TEAMA_NODE}],
|
||
|
|
},
|
||
|
|
{**NORTH_NODE},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Flat envelope — every node at the top level, parents via pId
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
FLAT_TREE_NODES: list[dict[str, Any]] = [
|
||
|
|
{**ROOT_NODE},
|
||
|
|
{**EAST_NODE},
|
||
|
|
{**TEAMA_NODE},
|
||
|
|
{**NORTH_NODE},
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
def make_dept_tree_response(
|
||
|
|
nodes: list[dict[str, Any]],
|
||
|
|
*,
|
||
|
|
nested_in_data_object: bool = False,
|
||
|
|
trace_id: str = "trace-dept",
|
||
|
|
) -> dict[str, Any]:
|
||
|
|
"""Build a capture-shaped ``dept/tree`` response envelope.
|
||
|
|
|
||
|
|
The yunke dept/tree response top-level is the standard envelope
|
||
|
|
``{message, code:"10000", success, traceId, data}``. The shape of ``data``
|
||
|
|
itself varies between captures — be defensive:
|
||
|
|
|
||
|
|
* ``data`` is the node list directly (the common case), OR
|
||
|
|
* ``data`` is an object wrapping the node list under ``children`` /
|
||
|
|
``list`` / etc.
|
||
|
|
|
||
|
|
The ``nested_in_data_object`` flag selects the second variant for the
|
||
|
|
"wrapped data object" path so a test can prove the scraper unwraps it.
|
||
|
|
The default (``False``) emits the most common flat-data array shape.
|
||
|
|
"""
|
||
|
|
data: Any = list(nodes)
|
||
|
|
if nested_in_data_object:
|
||
|
|
data = {"children": list(nodes)}
|
||
|
|
return {
|
||
|
|
"message": "调用成功",
|
||
|
|
"code": "10000",
|
||
|
|
"success": True,
|
||
|
|
"traceId": trace_id,
|
||
|
|
"data": data,
|
||
|
|
}
|