test_pages.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import asyncio
  2. from time import time
  3. from uuid import uuid4
  4. import justpy.htmlcomponents
  5. from nicegui import task_logger, ui
  6. from starlette.requests import Request
  7. from .screen import Screen
  8. def test_page(screen: Screen):
  9. @ui.page('/')
  10. def page():
  11. ui.label('Hello, world!')
  12. screen.open('/')
  13. screen.should_contain('NiceGUI')
  14. screen.should_contain('Hello, world!')
  15. def test_shared_page(screen: Screen):
  16. @ui.page('/', shared=True)
  17. def page():
  18. ui.label('Hello, world!')
  19. screen.open('/')
  20. screen.should_contain('NiceGUI')
  21. screen.should_contain('Hello, world!')
  22. def test_auto_index_page(screen: Screen):
  23. ui.label('Hello, world!')
  24. screen.open('/')
  25. screen.should_contain('NiceGUI')
  26. screen.should_contain('Hello, world!')
  27. def test_custom_title(screen: Screen):
  28. @ui.page('/', title='My Custom Title')
  29. def page():
  30. ui.label('Hello, world!')
  31. screen.open('/')
  32. screen.should_contain('My Custom Title')
  33. screen.should_contain('Hello, world!')
  34. def test_route_with_custom_path(screen: Screen):
  35. @ui.page('/test_route')
  36. def page():
  37. ui.label('page with custom path')
  38. screen.open('/test_route')
  39. screen.should_contain('page with custom path')
  40. def test_auto_index_page_with_link_to_subpage(screen: Screen):
  41. ui.link('link to subpage', '/subpage')
  42. @ui.page('/subpage')
  43. def page():
  44. ui.label('the subpage')
  45. screen.open('/')
  46. screen.click('link to subpage')
  47. screen.should_contain('the subpage')
  48. def test_link_to_page_by_passing_function(screen: Screen):
  49. @ui.page('/subpage')
  50. def page():
  51. ui.label('the subpage')
  52. ui.link('link to subpage', page)
  53. screen.open('/')
  54. screen.click('link to subpage')
  55. screen.should_contain('the subpage')
  56. def test_creating_new_page_after_startup(screen: Screen):
  57. screen.start_server()
  58. @ui.page('/late_page')
  59. def page():
  60. ui.label('page created after startup')
  61. screen.open('/late_page')
  62. screen.should_contain('page created after startup')
  63. def test_shared_and_individual_pages(screen: Screen):
  64. @ui.page('/individual_page')
  65. def individual_page():
  66. ui.label(f'individual page with uuid {uuid4()}')
  67. @ui.page('/shared_page', shared=True)
  68. def shared_page():
  69. ui.label(f'shared page with uuid {uuid4()}')
  70. screen.open('/shared_page')
  71. uuid1 = screen.find('shared page').text.split()[-1]
  72. screen.open('/shared_page')
  73. uuid2 = screen.find('shared page').text.split()[-1]
  74. assert uuid1 == uuid2
  75. screen.open('/individual_page')
  76. uuid1 = screen.find('individual page').text.split()[-1]
  77. screen.open('/individual_page')
  78. uuid2 = screen.find('individual page').text.split()[-1]
  79. assert uuid1 != uuid2
  80. def test_on_page_ready_event(screen: Screen):
  81. '''This feature was introduced to fix #50; see https://github.com/zauberzeug/nicegui/issues/50#issuecomment-1210962617.'''
  82. async def load() -> None:
  83. label.text = 'loading...'
  84. # NOTE we can not use asyncio.create_task() here because we are on a different thread than the nicegui event loop
  85. task_logger.create_task(takes_a_while())
  86. async def takes_a_while() -> None:
  87. await asyncio.sleep(0.1)
  88. label.text = 'delayed data has been loaded'
  89. @ui.page('/', on_page_ready=load)
  90. def page():
  91. global label
  92. label = ui.label()
  93. screen.open('/')
  94. screen.should_contain('delayed data has been loaded')
  95. def test_customized_page(screen: Screen):
  96. trace = []
  97. class custom_page(ui.page):
  98. def __init__(self, route: str, **kwargs):
  99. super().__init__(route, title='My Customized Page', **kwargs)
  100. trace.append('init')
  101. async def connected(self, request: Request) -> None:
  102. await super().connected(request)
  103. assert isinstance(request, Request)
  104. trace.append('connected')
  105. async def header(self) -> None:
  106. assert isinstance(self.page.view, justpy.htmlcomponents.Div), \
  107. 'we should be able to access the underlying JustPy view'
  108. await super().header()
  109. trace.append('header')
  110. async def footer(self) -> None:
  111. await super().footer()
  112. trace.append('footer')
  113. @custom_page('/', dark=True)
  114. def mainpage():
  115. trace.append('content')
  116. ui.label('Hello, world!')
  117. screen.open('/')
  118. screen.should_contain('Hello, world!')
  119. screen.should_contain('My Customized Page')
  120. assert 'body--dark' in screen.get_tags('body')[0].get_attribute('class')
  121. assert trace == ['init', 'connected', 'header', 'content', 'footer']
  122. def test_shared_page_with_request_parameter_raises_exception(screen: Screen):
  123. @ui.page('/', shared=True)
  124. def page(request: Request):
  125. ui.label('Hello, world!')
  126. screen.open('/')
  127. screen.should_contain('501')
  128. screen.should_contain('Server error')
  129. def test_adding_elements_in_on_page_ready_event(screen: Screen):
  130. @ui.page('/', on_page_ready=lambda: ui.markdown('Hello, world!'))
  131. def page():
  132. pass
  133. screen.open('/')
  134. screen.should_contain('Hello, world!')
  135. def test_pageready_after_yield_on_async_page(screen: Screen):
  136. @ui.page('/')
  137. async def page():
  138. ui.label('before')
  139. yield
  140. await asyncio.sleep(1)
  141. ui.label('after')
  142. screen.open('/')
  143. screen.should_contain('before')
  144. screen.should_not_contain('after')
  145. screen.wait(1)
  146. screen.should_contain('after')
  147. def test_pageready_after_yield_on_non_async_page(screen: Screen):
  148. @ui.page('/')
  149. def page():
  150. t = time()
  151. yield
  152. ui.label(f'loading page took {time() - t:.2f} seconds')
  153. screen.open('/')
  154. timing = screen.find('loading page took')
  155. assert 0 < float(timing.text.split()[-2]) < 1
  156. def test_pageready_after_yield_on_shared_page_raises_exception(screen: Screen):
  157. @ui.page('/', shared=True)
  158. def page():
  159. yield
  160. screen.open('/')
  161. screen.should_contain('501')
  162. screen.should_contain('Server error')