test_archive_page_runs.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. """What the archive page shows of each print (archive redesign P4).
  2. The page lists an archive's prints with what is each print's own: its note,
  3. its finish photos and its video. Plates of one archive keep their own videos,
  4. so each print's video has a route of its own; a caller limited to some
  5. printers gets only their prints' media.
  6. """
  7. from __future__ import annotations
  8. import pytest
  9. from backend.app.models.archive import PrintArchive
  10. from backend.app.models.print_log import PrintLogEntry
  11. from backend.tests.integration.test_archive_scope_per_run import DIR, _url, files, plates # noqa: F401
  12. pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
  13. async def _runs(async_client, plates, headers) -> dict[int, dict]:
  14. response = await async_client.get(_url(plates, "/runs"), headers=headers)
  15. assert response.status_code == 200, response.text
  16. return {r["id"]: r for r in response.json()["items"]}
  17. async def test_each_print_carries_its_own_media_and_note(async_client, db_session, plates):
  18. first = await db_session.get(PrintLogEntry, plates.first)
  19. first.notes = "brim lifted"
  20. await db_session.commit()
  21. runs = await _runs(async_client, plates, plates.admin)
  22. assert (runs[plates.first]["photos"], runs[plates.first]["timelapse_path"], runs[plates.first]["notes"]) == (
  23. ["finish_a.jpg"],
  24. f"{DIR}/a.mp4",
  25. "brim lifted",
  26. )
  27. assert runs[plates.second]["photos"] == ["finish_b.jpg"]
  28. async def test_a_photo_removed_from_the_archive_is_no_prints_any_more(async_client, db_session, plates):
  29. archive = await db_session.get(PrintArchive, plates.archive)
  30. archive.photos = ["finish_b.jpg", "0a1b2c3d.jpg"]
  31. await db_session.commit()
  32. runs = await _runs(async_client, plates, plates.admin)
  33. assert runs[plates.first]["photos"] is None
  34. assert runs[plates.second]["photos"] == ["finish_b.jpg"]
  35. async def test_each_print_plays_its_own_video(async_client, files, plates):
  36. (files / DIR / "a.mp4").write_bytes(b"plate one")
  37. (files / DIR / "b.mp4").write_bytes(b"plate two")
  38. first = await async_client.get(_url(plates, f"/runs/{plates.first}/timelapse"), headers=plates.admin)
  39. second = await async_client.get(_url(plates, f"/runs/{plates.second}/timelapse"), headers=plates.admin)
  40. assert (first.status_code, first.content) == (200, b"plate one")
  41. assert (second.status_code, second.content) == (200, b"plate two")
  42. async def test_a_print_outside_the_callers_printers_plays_nothing(async_client, plates):
  43. assert (
  44. await async_client.get(_url(plates, f"/runs/{plates.first}/timelapse"), headers=plates.of_a)
  45. ).status_code == 200
  46. assert (
  47. await async_client.get(_url(plates, f"/runs/{plates.second}/timelapse"), headers=plates.of_a)
  48. ).status_code == 404
  49. async def test_a_print_of_another_archive_plays_nothing(async_client, db_session, plates):
  50. other = PrintArchive(filename="o.3mf", file_path=f"{DIR}/o.3mf", file_size=1, print_name="o")
  51. db_session.add(other)
  52. await db_session.commit()
  53. response = await async_client.get(
  54. f"/api/v1/archives/{other.id}/runs/{plates.first}/timelapse", headers=plates.admin
  55. )
  56. assert response.status_code == 404
  57. async def test_a_video_outside_the_data_dir_is_not_served(async_client, db_session, files, plates):
  58. outside = files.parent / "secret.mp4"
  59. outside.write_bytes(b"no")
  60. first = await db_session.get(PrintLogEntry, plates.first)
  61. first.timelapse_path = "../secret.mp4"
  62. await db_session.commit()
  63. response = await async_client.get(_url(plates, f"/runs/{plates.first}/timelapse"), headers=plates.admin)
  64. assert response.status_code == 404
  65. async def test_a_print_gets_its_own_note(async_client, db_session, plates):
  66. response = await async_client.patch(
  67. f"/api/v1/print-log/{plates.first}", json={"notes": " brim lifted "}, headers=plates.admin
  68. )
  69. assert response.status_code == 200, response.text
  70. assert response.json()["notes"] == "brim lifted"
  71. cleared = await async_client.patch(f"/api/v1/print-log/{plates.first}", json={"notes": ""}, headers=plates.admin)
  72. assert cleared.json()["notes"] is None
  73. # The file's note is the archive's own, untouched.
  74. archive = await db_session.get(PrintArchive, plates.archive)
  75. await db_session.refresh(archive)
  76. assert archive.notes is None
  77. async def test_a_print_outside_the_callers_printers_takes_no_note(async_client, plates):
  78. response = await async_client.patch(f"/api/v1/print-log/{plates.second}", json={"notes": "x"}, headers=plates.of_a)
  79. assert response.status_code == 404
  80. async def test_the_print_log_names_the_deleted_archives_of_its_prints(async_client, db_session, plates):
  81. archive = await db_session.get(PrintArchive, plates.archive)
  82. archive.deleted_at = archive.created_at
  83. await db_session.commit()
  84. response = await async_client.get("/api/v1/print-log/", headers=plates.admin)
  85. assert response.json()["deleted_archive_ids"] == [plates.archive]