test_stl_thumbnail.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. """Unit tests for the STL thumbnail service."""
  2. import tempfile
  3. from pathlib import Path
  4. import pytest
  5. def _check_trimesh_available():
  6. """Check if trimesh is available for import."""
  7. try:
  8. import trimesh
  9. return True
  10. except ImportError:
  11. return False
  12. class TestStlThumbnailService:
  13. """Tests for STL thumbnail generation service."""
  14. def test_generate_stl_thumbnail_imports_available(self):
  15. """Test that required imports are available."""
  16. try:
  17. import matplotlib
  18. import trimesh
  19. assert trimesh is not None
  20. assert matplotlib is not None
  21. except ImportError as e:
  22. pytest.skip(f"Required dependencies not installed: {e}")
  23. def test_generate_stl_thumbnail_returns_none_on_missing_deps(self):
  24. """Test graceful degradation when dependencies are missing."""
  25. from backend.app.services.stl_thumbnail import generate_stl_thumbnail
  26. with tempfile.TemporaryDirectory() as tmpdir:
  27. stl_path = Path(tmpdir) / "test.stl"
  28. thumbnails_dir = Path(tmpdir)
  29. # Create a dummy STL file (will fail to parse)
  30. stl_path.write_text("invalid stl content")
  31. # Should return None on failure, not raise
  32. result = generate_stl_thumbnail(stl_path, thumbnails_dir)
  33. assert result is None
  34. @pytest.mark.skipif(
  35. not _check_trimesh_available(),
  36. reason="trimesh not installed",
  37. )
  38. def test_generate_stl_thumbnail_with_simple_cube(self):
  39. """Test thumbnail generation with a simple cube STL."""
  40. from backend.app.services.stl_thumbnail import generate_stl_thumbnail
  41. with tempfile.TemporaryDirectory() as tmpdir:
  42. stl_path = Path(tmpdir) / "cube.stl"
  43. thumbnails_dir = Path(tmpdir)
  44. # Create a simple ASCII STL cube
  45. stl_content = """solid cube
  46. facet normal 0 0 -1
  47. outer loop
  48. vertex 0 0 0
  49. vertex 1 0 0
  50. vertex 1 1 0
  51. endloop
  52. endfacet
  53. facet normal 0 0 -1
  54. outer loop
  55. vertex 0 0 0
  56. vertex 1 1 0
  57. vertex 0 1 0
  58. endloop
  59. endfacet
  60. facet normal 0 0 1
  61. outer loop
  62. vertex 0 0 1
  63. vertex 1 1 1
  64. vertex 1 0 1
  65. endloop
  66. endfacet
  67. facet normal 0 0 1
  68. outer loop
  69. vertex 0 0 1
  70. vertex 0 1 1
  71. vertex 1 1 1
  72. endloop
  73. endfacet
  74. facet normal 0 -1 0
  75. outer loop
  76. vertex 0 0 0
  77. vertex 1 0 1
  78. vertex 1 0 0
  79. endloop
  80. endfacet
  81. facet normal 0 -1 0
  82. outer loop
  83. vertex 0 0 0
  84. vertex 0 0 1
  85. vertex 1 0 1
  86. endloop
  87. endfacet
  88. facet normal 1 0 0
  89. outer loop
  90. vertex 1 0 0
  91. vertex 1 0 1
  92. vertex 1 1 1
  93. endloop
  94. endfacet
  95. facet normal 1 0 0
  96. outer loop
  97. vertex 1 0 0
  98. vertex 1 1 1
  99. vertex 1 1 0
  100. endloop
  101. endfacet
  102. facet normal 0 1 0
  103. outer loop
  104. vertex 0 1 0
  105. vertex 1 1 0
  106. vertex 1 1 1
  107. endloop
  108. endfacet
  109. facet normal 0 1 0
  110. outer loop
  111. vertex 0 1 0
  112. vertex 1 1 1
  113. vertex 0 1 1
  114. endloop
  115. endfacet
  116. facet normal -1 0 0
  117. outer loop
  118. vertex 0 0 0
  119. vertex 0 1 0
  120. vertex 0 1 1
  121. endloop
  122. endfacet
  123. facet normal -1 0 0
  124. outer loop
  125. vertex 0 0 0
  126. vertex 0 1 1
  127. vertex 0 0 1
  128. endloop
  129. endfacet
  130. endsolid cube"""
  131. stl_path.write_text(stl_content)
  132. result = generate_stl_thumbnail(stl_path, thumbnails_dir)
  133. # Should return a path to the generated thumbnail
  134. if result:
  135. assert Path(result).exists()
  136. assert Path(result).suffix == ".png"
  137. # If result is None, dependencies might not be fully functional
  138. # which is acceptable
  139. def test_generate_stl_thumbnail_nonexistent_file(self):
  140. """Test thumbnail generation with nonexistent file."""
  141. from backend.app.services.stl_thumbnail import generate_stl_thumbnail
  142. with tempfile.TemporaryDirectory() as tmpdir:
  143. stl_path = Path(tmpdir) / "nonexistent.stl"
  144. thumbnails_dir = Path(tmpdir)
  145. result = generate_stl_thumbnail(stl_path, thumbnails_dir)
  146. assert result is None
  147. def test_generate_stl_thumbnail_empty_file(self):
  148. """Test thumbnail generation with empty file."""
  149. from backend.app.services.stl_thumbnail import generate_stl_thumbnail
  150. with tempfile.TemporaryDirectory() as tmpdir:
  151. stl_path = Path(tmpdir) / "empty.stl"
  152. thumbnails_dir = Path(tmpdir)
  153. # Create empty file
  154. stl_path.write_bytes(b"")
  155. result = generate_stl_thumbnail(stl_path, thumbnails_dir)
  156. assert result is None
  157. class TestStlThumbnailConstants:
  158. """Tests for STL thumbnail service constants."""
  159. def test_bambu_green_color(self):
  160. """Test that Bambu green color is defined."""
  161. from backend.app.services.stl_thumbnail import BAMBU_GREEN
  162. assert BAMBU_GREEN == "#00AE42"
  163. def test_background_color(self):
  164. """Test that background color is defined."""
  165. from backend.app.services.stl_thumbnail import BACKGROUND_COLOR
  166. assert BACKGROUND_COLOR == "#1a1a1a"
  167. def test_max_vertices_threshold(self):
  168. """Test that max vertices threshold is defined."""
  169. from backend.app.services.stl_thumbnail import MAX_VERTICES
  170. assert MAX_VERTICES == 100000