utils.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. """Helper utilities for integration tests."""
  2. from __future__ import annotations
  3. from contextlib import contextmanager
  4. from typing import Generator, Iterator
  5. from selenium.webdriver.remote.webdriver import WebDriver
  6. from reflex.testing import AppHarness
  7. @contextmanager
  8. def poll_for_navigation(
  9. driver: WebDriver, timeout: int = 5
  10. ) -> Generator[None, None, None]:
  11. """Wait for driver url to change.
  12. Use as a contextmanager, and apply the navigation event inside the context
  13. block, polling will occur after the context block exits.
  14. Args:
  15. driver: WebDriver instance.
  16. timeout: Time to wait for url to change.
  17. Yields:
  18. None
  19. """
  20. prev_url = driver.current_url
  21. yield
  22. AppHarness._poll_for(lambda: prev_url != driver.current_url, timeout=timeout)
  23. class LocalStorage:
  24. """Class to access local storage.
  25. https://stackoverflow.com/a/46361900
  26. """
  27. storage_key = "localStorage"
  28. def __init__(self, driver: WebDriver):
  29. """Initialize the class.
  30. Args:
  31. driver: WebDriver instance.
  32. """
  33. self.driver = driver
  34. def __len__(self) -> int:
  35. """Get the number of items in local storage.
  36. Returns:
  37. The number of items in local storage.
  38. """
  39. return int(
  40. self.driver.execute_script(f"return window.{self.storage_key}.length;")
  41. )
  42. def items(self) -> dict[str, str]:
  43. """Get all items in local storage.
  44. Returns:
  45. A dict mapping keys to values.
  46. """
  47. return self.driver.execute_script(
  48. f"var ls = window.{self.storage_key}, items = {{}}; "
  49. "for (var i = 0, k; i < ls.length; ++i) "
  50. " items[k = ls.key(i)] = ls.getItem(k); "
  51. "return items; "
  52. )
  53. def keys(self) -> list[str]:
  54. """Get all keys in local storage.
  55. Returns:
  56. A list of keys.
  57. """
  58. return self.driver.execute_script(
  59. f"var ls = window.{self.storage_key}, keys = []; "
  60. "for (var i = 0; i < ls.length; ++i) "
  61. " keys[i] = ls.key(i); "
  62. "return keys; "
  63. )
  64. def get(self, key) -> str:
  65. """Get a key from local storage.
  66. Args:
  67. key: The key to get.
  68. Returns:
  69. The value of the key.
  70. """
  71. return self.driver.execute_script(
  72. f"return window.{self.storage_key}.getItem(arguments[0]);", key
  73. )
  74. def set(self, key, value) -> None:
  75. """Set a key in local storage.
  76. Args:
  77. key: The key to set.
  78. value: The value to set the key to.
  79. """
  80. self.driver.execute_script(
  81. f"window.{self.storage_key}.setItem(arguments[0], arguments[1]);",
  82. key,
  83. value,
  84. )
  85. def has(self, key) -> bool:
  86. """Check if key is in local storage.
  87. Args:
  88. key: The key to check.
  89. Returns:
  90. True if key is in local storage, False otherwise.
  91. """
  92. return key in self
  93. def remove(self, key) -> None:
  94. """Remove a key from local storage.
  95. Args:
  96. key: The key to remove.
  97. """
  98. self.driver.execute_script(
  99. f"window.{self.storage_key}.removeItem(arguments[0]);", key
  100. )
  101. def clear(self) -> None:
  102. """Clear all local storage."""
  103. self.driver.execute_script(f"window.{self.storage_key}.clear();")
  104. def __getitem__(self, key) -> str:
  105. """Get a key from local storage.
  106. Args:
  107. key: The key to get.
  108. Returns:
  109. The value of the key.
  110. Raises:
  111. KeyError: If key is not in local storage.
  112. """
  113. value = self.get(key)
  114. if value is None:
  115. raise KeyError(key)
  116. return value
  117. def __setitem__(self, key, value) -> None:
  118. """Set a key in local storage.
  119. Args:
  120. key: The key to set.
  121. value: The value to set the key to.
  122. """
  123. self.set(key, value)
  124. def __contains__(self, key) -> bool:
  125. """Check if key is in local storage.
  126. Args:
  127. key: The key to check.
  128. Returns:
  129. True if key is in local storage, False otherwise.
  130. """
  131. return self.has(key)
  132. def __iter__(self) -> Iterator[str]:
  133. """Iterate over the keys in local storage.
  134. Returns:
  135. An iterator over the items in local storage.
  136. """
  137. return iter(self.keys())
  138. class SessionStorage(LocalStorage):
  139. """Class to access session storage.
  140. https://stackoverflow.com/a/46361900
  141. """
  142. storage_key = "sessionStorage"