153 lines
4.7 KiB
Python
153 lines
4.7 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import uuid
|
|
from contextlib import contextmanager
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from sqlalchemy import select, text
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.domains.auth.models import User, UserRole
|
|
from app.domains.media.models import MediaAsset, MediaAssetType
|
|
from app.domains.orders.models import Order, OrderLine, OrderStatus
|
|
from app.domains.products.models import CadFile, Product
|
|
from app.domains.rendering.models import OutputType
|
|
|
|
from tests.db_test_utils import sync_test_session as sync_test_session_ctx
|
|
|
|
|
|
@pytest.fixture
|
|
def sync_session():
|
|
with sync_test_session_ctx() as session:
|
|
yield session
|
|
|
|
|
|
def _seed_order_line(session: Session, tmp_path: Path) -> OrderLine:
|
|
step_path = tmp_path / "parts" / "bearing.step"
|
|
step_path.parent.mkdir(parents=True, exist_ok=True)
|
|
step_path.write_text("STEP", encoding="utf-8")
|
|
|
|
user = User(
|
|
id=uuid.uuid4(),
|
|
email=f"publish-{uuid.uuid4().hex[:8]}@test.local",
|
|
password_hash="hash",
|
|
full_name="Publish Tester",
|
|
role=UserRole.admin,
|
|
is_active=True,
|
|
)
|
|
cad_file = CadFile(
|
|
id=uuid.uuid4(),
|
|
original_name="bearing.step",
|
|
stored_path=str(step_path),
|
|
file_hash=f"hash-{uuid.uuid4().hex}",
|
|
)
|
|
product = Product(
|
|
id=uuid.uuid4(),
|
|
pim_id="P-2000",
|
|
name="Bearing Publish",
|
|
category_key="bearings",
|
|
cad_file_id=cad_file.id,
|
|
cad_file=cad_file,
|
|
)
|
|
output_type = OutputType(
|
|
id=uuid.uuid4(),
|
|
name="HQ Still",
|
|
renderer="blender",
|
|
output_format="png",
|
|
render_settings={"width": 1600, "height": 900},
|
|
)
|
|
order = Order(
|
|
id=uuid.uuid4(),
|
|
order_number=f"ORD-{uuid.uuid4().hex[:8]}",
|
|
status=OrderStatus.processing,
|
|
created_by=user.id,
|
|
)
|
|
line = OrderLine(
|
|
id=uuid.uuid4(),
|
|
order_id=order.id,
|
|
product_id=product.id,
|
|
product=product,
|
|
output_type_id=output_type.id,
|
|
output_type=output_type,
|
|
render_status="processing",
|
|
)
|
|
|
|
session.add_all([user, cad_file, product, output_type, order, line])
|
|
session.commit()
|
|
return line
|
|
|
|
|
|
def test_publish_asset_canonicalizes_still_outputs(sync_session, tmp_path, monkeypatch):
|
|
from app.config import settings
|
|
from app.domains.rendering.tasks import publish_asset
|
|
|
|
upload_dir = tmp_path / "uploads"
|
|
monkeypatch.setattr(settings, "upload_dir", str(upload_dir))
|
|
|
|
line = _seed_order_line(sync_session, tmp_path)
|
|
source_output = tmp_path / "parts" / "renders" / "line.png"
|
|
source_output.parent.mkdir(parents=True, exist_ok=True)
|
|
source_output.write_bytes(b"png")
|
|
|
|
@contextmanager
|
|
def _session_ctx():
|
|
yield sync_session
|
|
|
|
monkeypatch.setattr("app.core.db_utils.get_sync_session", _session_ctx)
|
|
|
|
asset_id = publish_asset.run(
|
|
str(line.id),
|
|
"still",
|
|
str(source_output),
|
|
render_config={"renderer": "blender", "engine_used": "cycles"},
|
|
)
|
|
|
|
sync_session.expire_all()
|
|
stored_line = sync_session.get(OrderLine, line.id)
|
|
stored_asset = sync_session.execute(
|
|
select(MediaAsset).where(MediaAsset.id == uuid.UUID(asset_id))
|
|
).scalar_one()
|
|
|
|
assert stored_line.result_path == f"{upload_dir}/renders/{line.id}/Bearing_Publish_HQ_Still.png"
|
|
assert Path(stored_line.result_path).is_file()
|
|
assert stored_asset.storage_key == f"renders/{line.id}/Bearing_Publish_HQ_Still.png"
|
|
assert stored_asset.asset_type == MediaAssetType.still
|
|
|
|
|
|
def test_publish_asset_canonicalizes_blend_storage_key_without_touching_order_line(sync_session, tmp_path, monkeypatch):
|
|
from app.config import settings
|
|
from app.domains.rendering.tasks import publish_asset
|
|
|
|
upload_dir = tmp_path / "uploads"
|
|
monkeypatch.setattr(settings, "upload_dir", str(upload_dir))
|
|
|
|
line = _seed_order_line(sync_session, tmp_path)
|
|
source_output = tmp_path / "parts" / "bearing_production.blend"
|
|
source_output.parent.mkdir(parents=True, exist_ok=True)
|
|
source_output.write_bytes(b"blend")
|
|
|
|
@contextmanager
|
|
def _session_ctx():
|
|
yield sync_session
|
|
|
|
monkeypatch.setattr("app.core.db_utils.get_sync_session", _session_ctx)
|
|
|
|
asset_id = publish_asset.run(
|
|
str(line.id),
|
|
"blend_production",
|
|
str(source_output),
|
|
render_config={"artifact_type": "blend_production"},
|
|
)
|
|
|
|
sync_session.expire_all()
|
|
stored_line = sync_session.get(OrderLine, line.id)
|
|
stored_asset = sync_session.execute(
|
|
select(MediaAsset).where(MediaAsset.id == uuid.UUID(asset_id))
|
|
).scalar_one()
|
|
|
|
assert stored_line.result_path is None
|
|
assert stored_asset.storage_key == str(source_output)
|
|
assert stored_asset.asset_type == MediaAssetType.blend_production
|