1
0

test_serving_files.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import re
  2. from pathlib import Path
  3. import httpx
  4. import pytest
  5. import requests
  6. from nicegui import __version__, app, ui
  7. from nicegui.testing import Screen
  8. from .test_helpers import TEST_DIR
  9. IMAGE_FILE = Path(TEST_DIR).parent / 'examples' / 'slideshow' / 'slides' / 'slide1.jpg'
  10. VIDEO_FILE = Path(TEST_DIR) / 'media' / 'test.mp4'
  11. @pytest.fixture(autouse=True)
  12. def provide_media_files():
  13. if not VIDEO_FILE.exists():
  14. VIDEO_FILE.parent.mkdir(exist_ok=True)
  15. url = 'https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4'
  16. with httpx.stream('GET', url) as response:
  17. with open(VIDEO_FILE, 'wb') as file:
  18. for chunk in response.iter_raw():
  19. file.write(chunk)
  20. def assert_video_file_streaming(path: str) -> None:
  21. with httpx.Client() as http_client:
  22. r = http_client.get(
  23. path if 'http' in path else f'http://localhost:{Screen.PORT}{path}',
  24. headers={'Range': 'bytes=0-1000'},
  25. )
  26. assert r.status_code == 206
  27. assert r.headers['Accept-Ranges'] == 'bytes'
  28. assert r.headers['Content-Range'].startswith('bytes 0-1000/')
  29. assert r.headers['Content-Length'] == '1001'
  30. assert r.headers['Content-Type'] == 'video/mp4'
  31. def test_media_files_can_be_streamed(screen: Screen):
  32. app.add_media_files('/media', Path(TEST_DIR) / 'media')
  33. screen.open('/')
  34. assert_video_file_streaming('/media/test.mp4')
  35. def test_adding_single_media_file(screen: Screen):
  36. url_path = app.add_media_file(local_file=VIDEO_FILE)
  37. screen.open('/')
  38. assert_video_file_streaming(url_path)
  39. @pytest.mark.parametrize('url_path', ['/static', '/static/'])
  40. def test_get_from_static_files_dir(url_path: str, screen: Screen):
  41. app.add_static_files(url_path, Path(TEST_DIR).parent)
  42. screen.open('/')
  43. with httpx.Client() as http_client:
  44. r = http_client.get(f'http://localhost:{Screen.PORT}/static/examples/slideshow/slides/slide1.jpg')
  45. assert r.status_code == 200
  46. assert 'max-age=' in r.headers['Cache-Control']
  47. def test_404_for_non_existing_static_file(screen: Screen):
  48. app.add_static_files('/static', Path(TEST_DIR))
  49. screen.open('/')
  50. with httpx.Client() as http_client:
  51. r = http_client.get(f'http://localhost:{Screen.PORT}/static/does_not_exist.jpg')
  52. screen.assert_py_logger('WARNING', re.compile('.*does_not_exist.jpg not found'))
  53. assert r.status_code == 404
  54. assert 'static/_nicegui' not in r.text, 'should use root_path, see https://github.com/zauberzeug/nicegui/issues/2570'
  55. def test_adding_single_static_file(screen: Screen):
  56. url_path = app.add_static_file(local_file=IMAGE_FILE)
  57. screen.open('/')
  58. with httpx.Client() as http_client:
  59. r = http_client.get(f'http://localhost:{Screen.PORT}{url_path}')
  60. assert r.status_code == 200
  61. assert 'max-age=' in r.headers['Cache-Control']
  62. def test_auto_serving_file_from_image_source(screen: Screen):
  63. ui.image(IMAGE_FILE)
  64. screen.open('/')
  65. img = screen.find_by_tag('img')
  66. assert '/_nicegui/auto/static/' in img.get_attribute('src')
  67. screen.wait(0.5)
  68. assert screen.selenium.execute_script("""
  69. return arguments[0].complete &&
  70. typeof arguments[0].naturalWidth != "undefined" &&
  71. arguments[0].naturalWidth > 0
  72. """, img), 'image should load successfully'
  73. def test_auto_serving_file_from_video_source(screen: Screen):
  74. ui.video(VIDEO_FILE)
  75. screen.open('/')
  76. video = screen.find_by_tag('video')
  77. assert '/_nicegui/auto/media/' in video.get_attribute('src')
  78. assert_video_file_streaming(video.get_attribute('src'))
  79. def test_mimetypes_of_static_files(screen: Screen):
  80. screen.open('/')
  81. response = requests.get(f'http://localhost:{Screen.PORT}/_nicegui/{__version__}/static/vue.global.js', timeout=5)
  82. assert response.status_code == 200
  83. assert response.headers['Content-Type'].startswith('text/javascript')
  84. response = requests.get(f'http://localhost:{Screen.PORT}/_nicegui/{__version__}/static/nicegui.css', timeout=5)
  85. assert response.status_code == 200
  86. assert response.headers['Content-Type'].startswith('text/css')