test_library_print_name.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """Tests for library files displaying the filename, not the embedded 3MF Title (#1489).
  2. The 3MF ``<metadata name="Title">`` is the in-app project title — generic
  3. ("Exported 3D Model") for a Bambu Studio "Save As", a marketing title for a
  4. MakerWorld download — never the filename the user saved as. The FileManager
  5. keyed its display name / search / sort off ``file_metadata.print_name``, so
  6. storing the Title made every card show the wrong name. ``_without_print_name``
  7. strips it on import; ``_migrate_drop_library_print_name`` clears it from rows
  8. imported before the fix.
  9. """
  10. from sqlalchemy import select
  11. from backend.app.api.routes.library import _without_print_name
  12. from backend.app.core.database import _migrate_drop_library_print_name
  13. from backend.app.models.library import LibraryFile
  14. # --- _without_print_name ---------------------------------------------------
  15. def test_strips_print_name_keeps_siblings():
  16. cleaned = _without_print_name({"print_name": "Exported 3D Model", "print_time_seconds": 100})
  17. assert cleaned == {"print_time_seconds": 100}
  18. def test_none_passes_through():
  19. assert _without_print_name(None) is None
  20. def test_dict_without_print_name_returned_unchanged():
  21. meta = {"print_time_seconds": 50}
  22. # No copy needed when there's nothing to strip — same object back.
  23. assert _without_print_name(meta) is meta
  24. def test_does_not_mutate_input():
  25. original = {"print_name": "Whatever", "filament_used_grams": 12}
  26. cleaned = _without_print_name(original)
  27. assert original == {"print_name": "Whatever", "filament_used_grams": 12} # untouched
  28. assert cleaned == {"filament_used_grams": 12}
  29. def test_print_name_only_collapses_to_empty_dict():
  30. assert _without_print_name({"print_name": "Exported 3D Model"}) == {}
  31. # --- _migrate_drop_library_print_name --------------------------------------
  32. async def test_migration_strips_print_name_from_existing_rows(db_session, monkeypatch):
  33. """Rows imported before the fix get print_name cleared; siblings and rows
  34. that never had it are untouched. Idempotent on a second run.
  35. The test DB is SQLite; is_sqlite() reads settings.database_url (not the
  36. test engine), so pin it to exercise the SQLite branch deterministically.
  37. The PostgreSQL branch is verified against a real PG instance separately."""
  38. monkeypatch.setattr("backend.app.core.database.is_sqlite", lambda: True)
  39. db_session.add_all(
  40. [
  41. LibraryFile(
  42. filename="halloween.3mf",
  43. file_path="/a",
  44. file_type="3mf",
  45. file_size=1,
  46. file_metadata={"print_name": "Haunted House", "print_time_seconds": 100},
  47. ),
  48. LibraryFile(
  49. filename="no_meta.3mf",
  50. file_path="/b",
  51. file_type="3mf",
  52. file_size=1,
  53. file_metadata={"print_time_seconds": 50},
  54. ),
  55. LibraryFile(
  56. filename="null_meta.3mf",
  57. file_path="/c",
  58. file_type="3mf",
  59. file_size=1,
  60. file_metadata=None,
  61. ),
  62. ]
  63. )
  64. await db_session.commit()
  65. conn = await db_session.connection()
  66. await _migrate_drop_library_print_name(conn)
  67. await _migrate_drop_library_print_name(conn) # idempotent
  68. db_session.expire_all()
  69. rows = (await db_session.execute(select(LibraryFile).order_by(LibraryFile.filename))).scalars().all()
  70. by_name = {r.filename: r for r in rows}
  71. assert by_name["halloween.3mf"].file_metadata == {"print_time_seconds": 100}
  72. assert by_name["no_meta.3mf"].file_metadata == {"print_time_seconds": 50}
  73. assert by_name["null_meta.3mf"].file_metadata is None