code: def test_gsr_gui(driver, gsr_figure):
      from pytest_cov.embed import cleanup_on_sigterm
  
      cleanup_on_sigterm()
  
      port = 9032
      proc = multiprocessing.Process(
          target=gsr_figure.show_dash,
          kwargs=dict(mode="external", port=port),
      )
      proc.start()
  
      try:
          time.sleep(1)
          fr = FigureResamplerGUITests(driver, port=port)
          time.sleep(1)
          fr.go_to_page()
  
          # box based zooms
          fr.drag_and_zoom("xy", x0=0.25, x1=0.5, y0=0.25, y1=0.5)
          fr.drag_and_zoom("x2y3", x0=0.3, x1=0.7, y0=0.1, y1=1)
  
          # Note: we have shared-xaxes so all traces will be updated using this command
          fr.clear_requests(sleep_time_s=1)
          fr.drag_and_zoom("x2y3", x0=0.25, x1=0.5, y0=0.2, y1=0.2)
          time.sleep(1)
          RequestParser.browser_independent_single_callback_request_assert(
              fr=fr,
              relayout_keys=[
                  "xaxis.range[0]",
                  "xaxis.range[1]",
                  "xaxis2.range[0]",
                  "xaxis2.range[1]",
              ],
              n_updated_traces=7,
          )
  
          # A toggle operation
          # This does not trigger the relayout callback, no new requests should be made
          fr.clear_requests(sleep_time_s=1)
          fr.click_legend_item("EDA_Phasic")
          time.sleep(0.2)
          fr.click_legend_item("SCR peaks")
          time.sleep(1)
          assert (
              len(
                  RequestParser.filter_callback_requests(
                      fr.get_requests()
                  )
              )
              == 0
          )
  
          # A reset axes operation resets the front-end view to the global data view
          fr.clear_requests(sleep_time_s=1)
          fr.reset_axes()
          time.sleep(1)
          RequestParser.browser_independent_single_callback_request_assert(
              fr=fr,
              relayout_keys=[
                  "xaxis.autorange",
                  "xaxis2.autorange",
                  "xaxis.showspikes",
                  "xaxis2.showspikes",
              ],
              n_updated_traces=7,
          )
  
          # y remains the same - zoom horizontally
          fr.clear_requests(sleep_time_s=1)
          fr.drag_and_zoom("x2y3", x0=0.25, x1=0.5, y0=0.3, y1=0.3)
  
          # y remains the same - zom horizontally
          fr.drag_and_zoom("xy", x0=0.4, x1=0.5, y0=0.5, y1=0.5)
          fr.drag_and_zoom("x2y3", x0=0.95, x1=0.5, y0=0.95, y1=0.95)
          fr.click_legend_item("EDA_lf_cleaned_tonic")
          fr.drag_and_zoom("xy", x0=0.05, x1=0.5, y0=0.95, y1=0.95)
          fr.drag_and_zoom("x2y3", x0=0.05, x1=0.5, y0=0.95, y1=0.95)
  
          # scale vertically
          # This will trigger a relayout callback, however as only y-values are updated,
          # no new data points will be send to the front-end and a - NO CONTENT response
          # will be returned.
          fr.clear_requests(sleep_time_s=1)
          fr.drag_and_zoom("x2y3", x0=0.2, x1=0.2, y0=0.1, y1=0.5)
          time.sleep(1)
          vertical_requests = RequestParser.filter_callback_requests(
              fr.get_requests()
          )
          assert len(vertical_requests) == 1
          assert vertical_requests[0].response.status_code == 204
  
          # autoscale
          # we autoscale to the current front-end view, no updated dat will be sent from
          # the server to the front-end, however, a callback will still be made, but
          # will return a 204 response status (no content), as we do not need new data
          # to autoscale to the current front-end view.
          fr.clear_requests(sleep_time_s=1)
          fr.autoscale()
          time.sleep(1)
          autoscale_requests = RequestParser.filter_callback_requests(
              fr.get_requests()
          )
          assert len(autoscale_requests) == 1
          assert autoscale_requests[0].response.status_code == 204
  
          fr.reset_axes()
          time.sleep(0.2)
  
          if (
              len(driver.get_log("browser")) > 0
          ):  # Check no errors in the browser
              for entry in driver.get_log("browser"):
                  print(entry)
                  if not entry["level"] == "INFO":
                      # Only WebGL warnings are allowed
                      assert entry["level"] == "warning"
                      assert entry["message"].contains("WebGL")
      except Exception as e:
          raise e
      finally:
          proc.terminate()
  
file_path: plotly-resampler/tests/test_figure_resampler_selenium.py
imports: import multiprocessing
  import time
  from plotly_resampler.figure_resampler import FigureResampler
  from .fr_selenium import FigureResamplerGUITests, RequestParser
label_desc: Use image node_id 4 for calling a global function with example usage: test_gsr_gui(driver, gsr_figure) without return types