96 lines
3.1 KiB
Python
96 lines
3.1 KiB
Python
from __future__ import annotations
|
||
|
||
import hashlib
|
||
import json
|
||
import unittest
|
||
from pathlib import Path
|
||
|
||
from booking_ingestion.md_fixture import (
|
||
build_fixture_parse_result,
|
||
parse_fixture_markdown,
|
||
)
|
||
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
FIXTURE_PATH = (
|
||
ROOT / "outputs" / "res_comment_20260727" /
|
||
"RES_COMMENT_TYPE_OF_ROOM.md"
|
||
)
|
||
CONTRACT_PATH = (
|
||
ROOT / "database" / "contracts" /
|
||
"booking-row-parse-result.schema.json"
|
||
)
|
||
|
||
|
||
class BookingFixtureParserTests(unittest.TestCase):
|
||
def test_real_fixture_preserves_every_source_row(self):
|
||
document = parse_fixture_markdown(
|
||
FIXTURE_PATH.read_text(encoding="utf-8")
|
||
)
|
||
self.assertEqual(len(document.rows), 867)
|
||
self.assertEqual(document.worksheet_count, 6)
|
||
self.assertEqual(document.distinct_group_code_count, 348)
|
||
self.assertEqual(
|
||
sum(row.no_of_rooms for row in document.rows),
|
||
867,
|
||
)
|
||
repeated = len(document.rows) - document.distinct_group_code_count
|
||
self.assertEqual(repeated, 519)
|
||
coordinates = {
|
||
(row.worksheet, row.row_no) for row in document.rows
|
||
}
|
||
self.assertEqual(len(coordinates), 867)
|
||
|
||
def test_group_code_is_not_unique_or_merged(self):
|
||
document = parse_fixture_markdown(
|
||
FIXTURE_PATH.read_text(encoding="utf-8")
|
||
)
|
||
rows = [
|
||
row for row in document.rows
|
||
if row.group_code_key == "LT260718KB"
|
||
]
|
||
self.assertEqual(len(rows), 12)
|
||
self.assertEqual({row.type_of_room_raw for row in rows}, {"DBL"})
|
||
self.assertEqual(sum(row.no_of_rooms for row in rows), 12)
|
||
|
||
def test_simple_fixture_row_maps_to_one_room_item(self):
|
||
document = parse_fixture_markdown(
|
||
FIXTURE_PATH.read_text(encoding="utf-8")
|
||
)
|
||
rule_sha = hashlib.sha256(b"test-rule").hexdigest()
|
||
result = build_fixture_parse_result(
|
||
document.rows[0],
|
||
rule_sha256=rule_sha,
|
||
)
|
||
self.assertEqual(result["status"], "accepted")
|
||
self.assertEqual(result["no_of_rooms"], 1)
|
||
self.assertEqual(len(result["room_items"]), 1)
|
||
self.assertEqual(result["room_items"][0]["quantity"], 1)
|
||
self.assertEqual(result["errors"], [])
|
||
|
||
def test_contract_is_valid_json_and_declares_required_fields(self):
|
||
schema = json.loads(CONTRACT_PATH.read_text(encoding="utf-8"))
|
||
self.assertEqual(schema["$schema"], (
|
||
"https://json-schema.org/draft/2020-12/schema"
|
||
))
|
||
required = set(schema["required"])
|
||
self.assertIn("source_row", required)
|
||
self.assertIn("room_items", required)
|
||
self.assertIn("no_of_rooms", required)
|
||
|
||
def test_duplicate_source_coordinate_is_rejected(self):
|
||
text = """
|
||
# GOURP_CODE、TYPE OF ROOM 与数量
|
||
来源文件:`source.xlsx`
|
||
房型映射文件:`mapping.xlsx`
|
||
## 工作表:SHEET
|
||
| 第 2 行 | G1 | DBL | 1 |
|
||
| 第 2 行 | G2 | TWN | 1 |
|
||
"""
|
||
with self.assertRaisesRegex(ValueError, "duplicate"):
|
||
parse_fixture_markdown(text)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|