From d08ddff278b602059016e9b6db4b64519175cd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Fredrik=20Ki=C3=A6r?= Date: Mon, 24 Feb 2020 14:42:38 +0000 Subject: [PATCH] Add webviz pytest fixture --- .gitignore | 1 + setup.py | 1 + tests/test_table_plotter.py | 66 ++++++++++++------- webviz_config/testing/__init__.py | 0 .../testing/_monitor_builtin_open.py | 52 +++++++++++++++ webviz_config/testing/plugin.py | 31 +++++++++ 6 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 webviz_config/testing/__init__.py create mode 100644 webviz_config/testing/_monitor_builtin_open.py create mode 100644 webviz_config/testing/plugin.py diff --git a/.gitignore b/.gitignore index 3b8b674e..20e4fd97 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ webviz_config/_docs/static/*.js webviz_config/_docs/static/*.css !webviz_config/_docs/static/webviz-doc.js !webviz_config/_docs/static/webviz-doc.css +geckodriver.log diff --git a/setup.py b/setup.py index 8753cbb7..9f9ccc81 100644 --- a/setup.py +++ b/setup.py @@ -75,6 +75,7 @@ def get_long_description() -> str: "TablePlotter = webviz_config.generic_plugins._table_plotter:TablePlotter", "PivotTable = webviz_config.generic_plugins._pivot_table:PivotTable", ], + "pytest11": ["webviz = webviz_config.testing.plugin"], }, install_requires=[ "bleach>=3.1", diff --git a/tests/test_table_plotter.py b/tests/test_table_plotter.py index 06d1f717..eef0e9e2 100644 --- a/tests/test_table_plotter.py +++ b/tests/test_table_plotter.py @@ -21,27 +21,31 @@ def test_table_plotter(dash_duo: DashComposite) -> None: app.layout = page.layout dash_duo.start_server(app) - # Wait for the app to render(there is probably a better way...) - time.sleep(5) + plugin = TablePlotter(app, csv_file=CSV_FILE) + app.layout = plugin.layout + dash_duo.start_server(app) # Checking that no plot options are defined - assert page.plot_options == {} + assert plugin.plot_options == {} + # Check that filter is not active - assert not page.use_filter + assert not plugin.use_filter # Checking that the correct plot type is initialized - plot_dd = dash_duo.find_element("#" + page.uuid("plottype")) + plot_dd = dash_duo.find_element("#" + plugin.uuid("plottype")) assert plot_dd.text == "scatter" # Checking that only the relevant options are shown - for plot_option in page.plot_args.keys(): - plot_option_dd = dash_duo.find_element("#" + page.uuid(f"div-{plot_option}")) - if plot_option not in page.plots["scatter"]: - assert plot_option_dd.get_attribute("style") == "display: none;" + for plot_option in plugin.plot_args.keys(): + if plot_option not in plugin.plots["scatter"]: + dash_duo.find_element("#" + plugin.uuid(f"div-{plot_option}")) + dash_duo.wait_for_style_to_equal( + "#" + plugin.uuid(f"div-{plot_option}"), style="display", val="none" + ) # Checking that options are initialized correctly for option in ["x", "y"]: - plot_option_dd = dash_duo.find_element("#" + page.uuid(f"dropdown-{option}")) + plot_option_dd = dash_duo.find_element("#" + plugin.uuid(f"dropdown-{option}")) assert plot_option_dd.text == "Well" @@ -58,28 +62,30 @@ def test_table_plotter_filter(dash_duo: DashComposite) -> None: app.layout = page.layout dash_duo.start_server(app) - # Wait for the app to render(there is probably a better way...) - time.sleep(5) + dash_duo.start_server(app) # Checking that no plot options are defined - assert page.plot_options == {} + assert plugin.plot_options == {} + # Check that filter is active - assert page.use_filter - assert page.filter_cols == ["Well"] + assert plugin.use_filter + assert plugin.filter_cols == ["Well"] # Checking that the correct plot type is initialized - plot_dd = dash_duo.find_element("#" + page.uuid("plottype")) + plot_dd = dash_duo.find_element("#" + plugin.uuid("plottype")) assert plot_dd.text == "scatter" # Checking that only the relevant options are shown - for plot_option in page.plot_args.keys(): - plot_option_dd = dash_duo.find_element("#" + page.uuid(f"div-{plot_option}")) - if plot_option not in page.plots["scatter"]: - assert "display: none;" in plot_option_dd.get_attribute("style") + for plot_option in plugin.plot_args.keys(): + if plot_option not in plugin.plots["scatter"]: + dash_duo.find_element("#" + plugin.uuid(f"div-{plot_option}")) + dash_duo.wait_for_style_to_equal( + "#" + plugin.uuid(f"div-{plot_option}"), style="display", val="none" + ) # Checking that options are initialized correctly for option in ["x", "y"]: - plot_option_dd = dash_duo.find_element("#" + page.uuid(f"dropdown-{option}")) + plot_option_dd = dash_duo.find_element("#" + plugin.uuid(f"dropdown-{option}")) assert plot_option_dd.text == "Well" @@ -105,12 +111,22 @@ def test_initialized_table_plotter(dash_duo: DashComposite) -> None: app.layout = page.layout dash_duo.start_server(app) - # Wait for the app to render(there is probably a better way...) + plot_options = { + "x": "Well", + "y": "Initial reservoir pressure (bar)", + "size": "Average permeability (D)", + "facet_col": "Segment", + } + + plugin = TablePlotter(app, csv_file=CSV_FILE, lock=True, plot_options=plot_options) + app.layout = plugin.layout + + dash_duo.start_server(app) # Checking that plot options are defined - assert page.plot_options == plot_options - assert page.lock + assert plugin.plot_options == plot_options + assert plugin.lock # Checking that the selectors are hidden - selector_row = dash_duo.find_element("#" + page.uuid("selector-row")) + selector_row = dash_duo.find_element("#" + plugin.uuid("selector-row")) assert "display: none;" in selector_row.get_attribute("style") diff --git a/webviz_config/testing/__init__.py b/webviz_config/testing/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/webviz_config/testing/_monitor_builtin_open.py b/webviz_config/testing/_monitor_builtin_open.py new file mode 100644 index 00000000..cbf656ed --- /dev/null +++ b/webviz_config/testing/_monitor_builtin_open.py @@ -0,0 +1,52 @@ +import io +import site +import inspect +import importlib +import warnings +from pathlib import Path + +WHITELISTED_FILENAMES = ["geckodriver.log", ".pytest-sugar.conf"] +WHITELISTED_PREFIXES = ["/tmp"] + site.PREFIXES +WHITELISTED_POSTFIXES = [str(Path(".plotly" / Path(".config"))), ".py", ".json"] +WHITELISTED_CONTAINS = [ + ".pytest_cache", + "__pycache__", + ".cache", + ".egg-info", + "/dev/null", +] + +import builtins + +FUNCTIONS = [ + ("builtins", "open", "filepath"), + ("pandas", "read_csv", "filepath"), + ("xtgeo", "Well", "self"), +] + + +class MonitorBuiltinOpen: + def __init__(self): + self._original_functions = [ + getattr(importlib.import_module(module), function) + for module, function, _ in FUNCTIONS + ] + + def stop_monitoring(self): + pass + # builtins.open = self._original_open + # io.open = self._original_open + + def start_monitoring(self): + pass + # def wrapped_open(*args, **kwargs): + # path = str(args[0]) + # if Path(path).name not in WHITELISTED_FILENAMES and str(Path(path).parent) != "." and all([part not in path for part in WHITELISTED_CONTAINS]) and all([not path.startswith(prefix) for prefix in WHITELISTED_PREFIXES]) and all([not path.endswith(postfix) for postfix in WHITELISTED_POSTFIXES]): + # raise RuntimeError(f"File {path} opened, which is not white-listed as a 'portable' location.") + # return self._original_open(*args, **kwargs) + + # builtins.open = wrapped_open + # io.open = wrapped_open + + +monitor_builtin_open = MonitorBuiltinOpen() diff --git a/webviz_config/testing/plugin.py b/webviz_config/testing/plugin.py new file mode 100644 index 00000000..4cddb483 --- /dev/null +++ b/webviz_config/testing/plugin.py @@ -0,0 +1,31 @@ +import pytest + +import dash +from dash_html_components import Div + +from ._monitor_builtin_open import monitor_builtin_open +from ..common_cache import CACHE +from ..themes import default_theme + + +class WebvizSinglePlugin: + def __init__(self): + self._app = dash.Dash(__name__) + self._configure_app() + + def _configure_app(self): + self._app.config.suppress_callback_exceptions = True + CACHE.init_app(self._app.server) + self._app.webviz_settings = {"theme": default_theme} + + def check_portability(self): + monitor_builtin_open.start_monitoring() + + @property + def app(self): + return self._app + + +@pytest.fixture +def webviz_single_plugin(): + return WebvizSinglePlugin()