add import script from notion
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
from app.models import Box, Item, SubItem
|
||||
from app.notion_import import (
|
||||
ImportSummary,
|
||||
ParsedBox,
|
||||
ParsedItem,
|
||||
ParsedSubItem,
|
||||
apply_import,
|
||||
extract_page_id,
|
||||
parse_notion_blocks,
|
||||
)
|
||||
|
||||
|
||||
def make_heading_2(text: str) -> dict:
|
||||
return {
|
||||
"type": "heading_2",
|
||||
"heading_2": {"rich_text": [{"plain_text": text}]},
|
||||
"_children": [],
|
||||
}
|
||||
|
||||
|
||||
def make_bullet(text: str, children: list[dict] | None = None) -> dict:
|
||||
return {
|
||||
"type": "bulleted_list_item",
|
||||
"bulleted_list_item": {"rich_text": [{"plain_text": text}]},
|
||||
"_children": children or [],
|
||||
}
|
||||
|
||||
|
||||
def make_image_block() -> dict:
|
||||
return {"type": "image", "image": {}, "_children": []}
|
||||
|
||||
|
||||
def test_extract_page_id_from_notion_url():
|
||||
url = "https://www.notion.so/workspace/My-Page-1234567890abcdef1234567890abcdef?pvs=4"
|
||||
|
||||
page_id = extract_page_id(url)
|
||||
|
||||
assert page_id == "12345678-90ab-cdef-1234-567890abcdef"
|
||||
|
||||
|
||||
def test_parse_heading_2_as_box():
|
||||
summary = parse_notion_blocks([make_heading_2("厨房箱")])
|
||||
|
||||
assert summary.box_count == 1
|
||||
assert summary.boxes[0].name == "厨房箱"
|
||||
|
||||
|
||||
def test_parse_first_level_bullet_as_item():
|
||||
blocks = [make_heading_2("客厅箱"), make_bullet("锅具")]
|
||||
|
||||
summary = parse_notion_blocks(blocks)
|
||||
|
||||
assert summary.item_count == 1
|
||||
assert summary.boxes[0].items[0].name == "锅具"
|
||||
assert summary.boxes[0].items[0].is_container is False
|
||||
|
||||
|
||||
def test_parse_bullet_with_children_as_container_item_and_subitems():
|
||||
blocks = [
|
||||
make_heading_2("电子箱"),
|
||||
make_bullet("配件盒", children=[make_bullet("USB 线"), make_bullet("转接头")]),
|
||||
]
|
||||
|
||||
summary = parse_notion_blocks(blocks)
|
||||
|
||||
item = summary.boxes[0].items[0]
|
||||
assert item.name == "配件盒"
|
||||
assert item.is_container is True
|
||||
assert [subitem.name for subitem in item.subitems] == ["USB 线", "转接头"]
|
||||
|
||||
|
||||
def test_parse_second_level_bullets_as_subitems():
|
||||
blocks = [
|
||||
make_heading_2("文件箱"),
|
||||
make_bullet("文件袋", children=[make_bullet("合同"), make_bullet("护照复印件")]),
|
||||
]
|
||||
|
||||
summary = parse_notion_blocks(blocks)
|
||||
|
||||
assert summary.subitem_count == 2
|
||||
assert summary.boxes[0].items[0].subitems[1].name == "护照复印件"
|
||||
|
||||
|
||||
def test_parse_deeper_than_supported_levels_adds_warning():
|
||||
blocks = [
|
||||
make_heading_2("测试箱"),
|
||||
make_bullet(
|
||||
"外层袋",
|
||||
children=[make_bullet("内层物品", children=[make_bullet("更深一层")])],
|
||||
),
|
||||
]
|
||||
|
||||
summary = parse_notion_blocks(blocks)
|
||||
|
||||
assert summary.container_item_count == 1
|
||||
assert any("超出支持层级" in warning for warning in summary.warnings)
|
||||
|
||||
|
||||
def test_parse_non_text_media_block_adds_skip_warning():
|
||||
blocks = [make_heading_2("照片箱"), make_image_block()]
|
||||
|
||||
summary = parse_notion_blocks(blocks)
|
||||
|
||||
assert any("这版不导入图片或媒体" in warning for warning in summary.warnings)
|
||||
|
||||
|
||||
def test_dry_run_parse_does_not_write_database(db_session):
|
||||
blocks = [make_heading_2("厨房箱"), make_bullet("锅")]
|
||||
|
||||
summary = parse_notion_blocks(blocks)
|
||||
|
||||
assert summary.box_count == 1
|
||||
assert db_session.query(Box).count() == 0
|
||||
assert db_session.query(Item).count() == 0
|
||||
assert db_session.query(SubItem).count() == 0
|
||||
|
||||
|
||||
def test_apply_import_writes_expected_structure(db_session):
|
||||
summary = ImportSummary(
|
||||
boxes=[
|
||||
ParsedBox(
|
||||
name="主卧箱",
|
||||
items=[
|
||||
ParsedItem(name="衣服", is_container=False),
|
||||
ParsedItem(
|
||||
name="收纳袋",
|
||||
is_container=True,
|
||||
subitems=[ParsedSubItem(name="袜子"), ParsedSubItem(name="围巾")],
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
counts = apply_import(summary, db_session)
|
||||
|
||||
assert counts == {"boxes": 1, "items": 2, "subitems": 2}
|
||||
assert db_session.query(Box).count() == 1
|
||||
assert db_session.query(Item).count() == 2
|
||||
assert db_session.query(SubItem).count() == 2
|
||||
|
||||
container_item = db_session.query(Item).filter_by(name="收纳袋").one()
|
||||
assert container_item.is_container is True
|
||||
Reference in New Issue
Block a user