def test_link001_event(dash_dcc): app = Dash(__name__) app.layout = html.Div([ dcc.Link("Page 1", id="link1", href="/page-1"), dcc.Location(id="url", refresh=False), html.Div(id="content"), ]) @app.callback(Output("content", "children"), [Input("url", "pathname")]) def display_page(pathname): if pathname is None or pathname == "/page-1": return html.Div("1", id="div1") elif pathname == "/": return html.Div("base", id="div0") else: return "404" dash_dcc.start_server(app) dash_dcc.driver.execute_script(""" window.addEventListener('_dashprivate_pushstate', function() { window._test_link_event_counter = (window._test_link_event_counter || 0) + 1; }); window.addEventListener('_dashprivate_historychange', function() { window._test_history_event_counter = (window._test_history_event_counter || 0) + 1; }); """) dash_dcc.wait_for_element_by_id("div0") dash_dcc.find_element("#link1").click() dash_dcc.wait_for_element_by_id("div1") link_counter = dash_dcc.driver.execute_script(""" return window._test_link_event_counter; """) history_counter = dash_dcc.driver.execute_script(""" return window._test_history_event_counter; """) assert link_counter == 1 assert history_counter == 1 assert dash_dcc.get_logs() == []
def test_mkdw006_toggle_mathjax(dash_dcc, is_eager): app = Dash(__name__, eager_loading=is_eager) gravity = "$F=\\frac{Gm_1m_2}{r^2}$" app.layout = html.Div( [ html.Button("Toggle MathJax", id="btn"), dcc.Markdown( f""" # Test MathJax Toggling {gravity} """, id="md", ), ] ) @app.callback( Output("md", "mathjax"), Input("btn", "n_clicks"), prevent_initial_call=True ) def toggle(n): return (n or 0) % 2 != 0 dash_dcc.start_server(app) # Initial state: no MathJax loaded or rendered, unformatted text is shown dash_dcc.wait_for_contains_text("#md", gravity) dash_dcc.wait_for_no_elements("#md svg") assert not dash_dcc.driver.execute_script("return !!window.MathJax") btn = dash_dcc.find_element("#btn") btn.click() # One click: MathJax is rendered, unformatted text is gone dash_dcc.wait_for_element("#md svg") assert gravity not in dash_dcc._get_element("#md").text assert dash_dcc.driver.execute_script("return !!window.MathJax") btn.click() # Second click: Back to initial state except that MathJax library is still loaded dash_dcc.wait_for_contains_text("#md", gravity) dash_dcc.wait_for_no_elements("#md svg") assert dash_dcc.driver.execute_script("return !!window.MathJax")
def test_ddcf001_clearable_false_single(dash_duo): app = Dash(__name__) app.layout = html.Div([ dcc.Dropdown( id="my-unclearable-dropdown", options=[ { "label": "New York City", "value": "NYC" }, { "label": "Montreal", "value": "MTL" }, { "label": "San Francisco", "value": "SF" }, ], value="MTL", clearable=False, ), html.Div(id="dropdown-value", style={ "height": "10px", "width": "10px" }), ]) @app.callback( Output("dropdown-value", "children"), [Input("my-unclearable-dropdown", "value")], ) def update_value(val): return val dash_duo.start_server(app) dropdown = dash_duo.find_element("#my-unclearable-dropdown input") dropdown.send_keys(Keys.BACKSPACE) dash_duo.find_element("#dropdown-value").click() assert len(dash_duo.find_element("#dropdown-value").text) > 0 assert dash_duo.get_logs() == []
def test_rdsi001_state_and_inputs(dash_duo): app = Dash(__name__) app.layout = html.Div([ dcc.Input(value="Initial Input", id="input"), dcc.Input(value="Initial State", id="state"), html.Div(id="output"), ]) call_count = Value("i", 0) @app.callback( Output("output", "children"), [Input("input", "value")], [State("state", "value")], ) def update_output(input, state): call_count.value += 1 return 'input="{}", state="{}"'.format(input, state) dash_duo.start_server(app) def input_(): return dash_duo.find_element("#input") def output_(): return dash_duo.find_element("#output") assert (output_().text == 'input="Initial Input", state="Initial State"' ), "callback gets called with initial input" input_().send_keys("x") wait.until(lambda: call_count.value == 2, timeout=1) assert (output_().text == 'input="Initial Inputx", state="Initial State"' ), "output get updated with key `x`" dash_duo.find_element("#state").send_keys("z") time.sleep(0.5) assert call_count.value == 2, "state not trigger callback with 0.5 wait" assert (output_().text == 'input="Initial Inputx", state="Initial State"' ), "output remains the same as last step" input_().send_keys("y") wait.until(lambda: call_count.value == 3, timeout=1) assert (output_().text == 'input="Initial Inputxy", state="Initial Statez"' ), "both input and state value get updated by input callback"
def test_cbsc001_simple_callback(dash_duo): lock = Lock() app = Dash(__name__) app.layout = html.Div( [ dcc.Input(id="input", value="initial value"), html.Div(html.Div([1.5, None, "string", html.Div(id="output-1")])), ] ) call_count = Value("i", 0) percy_ss = Value("b", False) @app.callback(Output("output-1", "children"), [Input("input", "value")]) def update_output(value): with lock: if not percy_ss.value: call_count.value = call_count.value + 1 return value def snapshot(name): percy_ss.value = os.getenv("PERCY_ENABLE", "") != "" dash_duo.percy_snapshot(name=name) percy_ss.value = False dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output-1", "initial value") snapshot("simple-callback-initial") input_ = dash_duo.find_element("#input") dash_duo.clear_input(input_) for key in "hello world": with lock: input_.send_keys(key) dash_duo.wait_for_text_to_equal("#output-1", "hello world") snapshot("simple-callback-hello-world") assert call_count.value == 2 + len("hello world"), "initial count + each key stroke" assert not dash_duo.redux_state_is_loading assert dash_duo.get_logs() == []
def test_intv001_interval(dash_dcc): app = Dash(__name__) app.layout = html.Div([ html.Div(id="output"), dcc.Interval(id="interval", interval=1, max_intervals=2), ]) @app.callback(Output("output", "children"), [Input("interval", "n_intervals")]) def update_text(n): return str(n) dash_dcc.start_server(app) time.sleep(5) dash_dcc.wait_for_text_to_equal("#output", "2") assert dash_dcc.get_logs() == []
def export_data_controllers(get_uuid: Callable) -> None: @callback( Output(get_uuid("download-dataframe"), "data"), Input({ "request": "table_data", "table_id": ALL }, "data_requested"), State({"table_id": ALL}, "data"), State({"table_id": ALL}, "columns"), State({ "request": "table_data", "table_id": ALL }, "id"), State({"table_id": ALL}, "id"), prevent_initial_call=True, ) def _export_table_data( _data_requested: list, table_data: list, table_columns: list, button_ids: list, table_ids: list, ) -> Callable: ctx = callback_context.triggered[0] export_clicks = { id_value["table_id"]: n_clicks for id_value, n_clicks in zip(button_ids, _data_requested) } table_to_extract = [ x for x in export_clicks.keys() if x in ctx["prop_id"] ] if not table_to_extract or export_clicks[table_to_extract[0]] is None: raise PreventUpdate index = [x["table_id"] for x in table_ids].index(table_to_extract[0]) table_data = table_data[index] table_columns = [x["name"] for x in table_columns[index]] return dcc.send_data_frame( pd.DataFrame(data=table_data, columns=table_columns).to_excel, "VolumetricAnalysis.xlsx", index=False, )
def test_grva001_candlestick(dash_dcc, is_eager): app = Dash(__name__, eager_loading=is_eager) app.layout = html.Div( [ html.Button(id="button", children="Update Candlestick", n_clicks=0), dcc.Graph(id="graph"), ] ) @app.callback(Output("graph", "figure"), [Input("button", "n_clicks")]) def update_graph(n_clicks): return { "data": [ { "open": [1] * 5, "high": [3] * 5, "low": [0] * 5, "close": [2] * 5, "x": [n_clicks] * 5, "type": "candlestick", } ] } dash_dcc.start_server(app=app) button = dash_dcc.wait_for_element("#button") # wait for Graph to be ready WebDriverWait(dash_dcc.driver, 10).until( EC.visibility_of_element_located((By.CSS_SELECTOR, "#graph .main-svg")) ) is_eager = "eager" if is_eager else "lazy" button.click() time.sleep(1) dash_dcc.percy_snapshot(f"candlestick - 1 click ({is_eager})") button.click() time.sleep(1) dash_dcc.percy_snapshot(f"candlestick - 2 click ({is_eager})") assert dash_dcc.get_logs() == []
def test_dvpc001_prop_check_errors_with_path(dash_duo): app = Dash(__name__, eager_loading=True) app.layout = html.Div( [html.Div(id="content"), dcc.Location(id="location")]) @app.callback(Output("content", "children"), [Input("location", "pathname")]) def display_content(pathname): if pathname is None or pathname == "/": return "Initial state" test_case = test_cases[pathname.strip("/")] return html.Div(id="new-component", children=test_case["component"](**test_case["props"])) dash_duo.start_server( app, debug=True, use_reloader=False, use_debugger=True, dev_tools_hot_reload=False, ) for tc in test_cases: route_url = "{}/{}".format(dash_duo.server_url, tc) dash_duo.wait_for_page(url=route_url) fail = test_cases[tc]["fail"] logs = test_cases[tc].get("logs", fail) if fail: dash_duo.wait_for_element(".test-devtools-error-toggle").click() dash_duo.wait_for_element(".dash-fe-error__info") dash_duo.percy_snapshot("devtools validation exception: {}".format( test_cases[tc]["name"])) else: dash_duo.wait_for_element("#new-component") dash_duo.wait_for_no_elements(".test-devtools-error-toggle") if logs: assert dash_duo.get_logs(), tc else: assert dash_duo.get_logs() == [], tc
def test_llgo001_location_logout(dash_dcc): app = Dash(__name__) @app.server.route("/_logout", methods=["POST"]) def on_logout(): rep = flask.redirect("/logged-out") rep.set_cookie("logout-cookie", "", 0) return rep app.layout = html.Div([ html.H2("Logout test"), dcc.Location(id="location"), html.Div(id="content") ]) @app.callback(Output("content", "children"), [Input("location", "pathname")]) def on_location(location_path): if location_path is None: raise PreventUpdate if "logged-out" in location_path: return "Logged out" else: @flask.after_this_request def _insert_cookie(rep): rep.set_cookie("logout-cookie", "logged-in") return rep return dcc.LogoutButton(id="logout-btn", logout_url="/_logout") dash_dcc.start_server(app) time.sleep(1) dash_dcc.percy_snapshot("Core Logout button") assert dash_dcc.driver.get_cookie("logout-cookie")["value"] == "logged-in" dash_dcc.wait_for_element("#logout-btn").click() dash_dcc.wait_for_text_to_equal("#content", "Logged out") assert not dash_dcc.driver.get_cookie("logout-cookie") assert dash_dcc.get_logs() == []
def test_link002_scroll(dash_dcc): app = Dash(__name__) app.layout = html.Div([ dcc.Location(id="test-url", refresh=False), html.Div( id="push-to-bottom", children=[], style={ "display": "block", "height": "200vh" }, ), html.Div(id="page-content"), dcc.Link("Test link", href="/test-link", id="test-link"), ]) call_count = Value("i", 0) @app.callback(Output("page-content", "children"), [Input("test-url", "pathname")]) def display_page(pathname): call_count.value = call_count.value + 1 return f"You are on page {pathname}" dash_dcc.start_server(app) wait.until(lambda: call_count.value == 1, 3) test_link = dash_dcc.wait_for_element("#test-link") test_link.send_keys(Keys.NULL) test_link.click() dash_dcc.wait_for_text_to_equal("#page-content", "You are on page /test-link") wait.until( lambda: test_link.get_attribute("href") == f"http://localhost:{dash_dcc.server.port}/test-link", 3, ) wait.until(lambda: call_count.value == 2, 3) assert dash_dcc.get_logs() == []
def input_range_app(): app = Dash(__name__) app.layout = html.Div([ dcc.Input( id="range", type="number", min=10, max=10000, step=3, placeholder="input with range", ), html.Div(id="out"), ]) @app.callback(Output("out", "children"), [Input("range", "value")]) def range_out(val): return val yield app
def test_loca001_callbacks(dash_dcc): app = Dash(__name__) app.layout = html.Div( [ dcc.Location(id="location", refresh=False), html.A("Anchor Link 1", href="#div"), html.Div(id="div"), ] ) @app.callback(Output("div", "children"), [Input("location", "pathname")]) def update_path(path): return path dash_dcc.start_server(app) dash_dcc.wait_for_text_to_equal("#div", "/") assert dash_dcc.get_logs() == []
def test_lipa001_path(dash_dcc): app = Dash(__name__) app.layout = html.Div([ dcc.Link("Relative Path", id="link1", href="google.com"), dcc.Location(id="url", refresh=False), html.Div(id="content"), ]) @app.callback(Output("content", "children"), Input("url", "pathname")) def display_children(children): return children dash_dcc.start_server(app) dash_dcc.wait_for_element("#link1").click() dash_dcc.wait_for_text_to_equal("#content", "/google.com") assert dash_dcc.get_logs() == []
def run(self): df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv") self.df = Payload(df) dash_app = Dash(__name__) dash_app.layout = html.Div( [ dcc.Graph(id="graph-with-slider"), dcc.Slider( df["year"].min(), df["year"].max(), step=None, value=df["year"].min(), marks={str(year): str(year) for year in df["year"].unique()}, id="year-slider", ), ] ) @dash_app.callback(Output("graph-with-slider", "figure"), Input("year-slider", "value")) def update_figure(selected_year): self.selected_year = selected_year filtered_df = df[df.year == selected_year] fig = px.scatter( filtered_df, x="gdpPercap", y="lifeExp", size="pop", color="continent", hover_name="country", log_x=True, size_max=55, ) fig.update_layout(transition_duration=500) return fig dash_app.run_server(host=self.host, port=self.port)
def test_clsd009_clientside_callback_context_triggered(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div([ html.Button("btn0", id="btn0"), html.Button("btn1:0", id={"btn1": 0}), html.Button("btn1:1", id={"btn1": 1}), html.Button("btn1:2", id={"btn1": 2}), html.Div(id="output-clientside", style={"font-family": "monospace"}), ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="triggered_to_str"), Output("output-clientside", "children"), [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output-clientside", "") dash_duo.find_element("#btn0").click() dash_duo.wait_for_text_to_equal( "#output-clientside", "btn0.n_clicks = 1", ) dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.wait_for_text_to_equal("#output-clientside", '{"btn1":0}.n_clicks = 2') dash_duo.find_element("button[id*='btn1\":2']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", '{"btn1":2}.n_clicks = 1', )
def test_clsd005_clientside_fails_when_returning_a_promise(dash_duo): app = Dash(__name__, assets_folder="assets") app.layout = html.Div([ html.Div(id="input", children="hello"), html.Div(id="side-effect"), html.Div(id="output", children="output"), ]) app.clientside_callback( ClientsideFunction("clientside", "side_effect_and_return_a_promise"), Output("output", "children"), [Input("input", "children")], ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#input", "hello") dash_duo.wait_for_text_to_equal("#side-effect", "side effect") dash_duo.wait_for_text_to_equal("#output", "output")
def test_cbsc010_event_properties(dash_duo): app = Dash(__name__) app.layout = html.Div([html.Button("Click Me", id="button"), html.Div(id="output")]) call_count = Value("i", 0) @app.callback(Output("output", "children"), [Input("button", "n_clicks")]) def update_output(n_clicks): if not n_clicks: raise PreventUpdate call_count.value += 1 return "Click" dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", "") assert call_count.value == 0 dash_duo.find_element("#button").click() dash_duo.wait_for_text_to_equal("#output", "Click") assert call_count.value == 1
def test_clsd018_clientside_inline_async_function(dash_duo): app = Dash(__name__) app.layout = html.Div([ html.Div(id="input", children=["initial"]), html.Div(id="output-div"), ]) app.clientside_callback( """ async function(input) { return input + "-inline"; } """, Output("output-div", "children"), Input("input", "children"), ) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output-div", "initial-inline")
def test_grva007_external_plotlyjs_prevents_lazy(dash_dcc): app = Dash( __name__, eager_loading=False, external_scripts=["https://unpkg.com/plotly.js/dist/plotly.min.js"], ) app.layout = html.Div(id="div", children=[html.Button(id="btn")]) @app.callback(Output("div", "children"), [Input("btn", "n_clicks")]) def load_chart(n_clicks): if n_clicks is None: raise PreventUpdate return dcc.Graph(id="output", figure={"data": [{"y": [3, 1, 2]}]}) dash_dcc.start_server( app, debug=True, use_reloader=False, use_debugger=True, dev_tools_hot_reload=False, ) # Give time for the async dependency to be requested (if any) time.sleep(2) scripts = dash_dcc.driver.find_elements(By.CSS_SELECTOR, "script") assert findSyncPlotlyJs(scripts) is None assert findAsyncPlotlyJs(scripts) is None dash_dcc.find_element("#btn").click() # Give time for the async dependency to be requested (if any) time.sleep(2) scripts = dash_dcc.driver.find_elements(By.CSS_SELECTOR, "script") assert findSyncPlotlyJs(scripts) is None assert findAsyncPlotlyJs(scripts) is None assert dash_dcc.get_logs() == []
def test_cbsc009_callback_using_unloaded_async_component_and_graph(dash_duo): app = Dash(__name__) app.layout = FragmentComponent([ CollapseComponent([AsyncComponent(id="async", value="A")]), html.Button("n", id="n"), DelayedEventComponent(id="d"), html.Div("Output init", id="output"), ]) @app.callback( Output("output", "children"), Input("n", "n_clicks"), Input("d", "n_clicks"), Input("async", "value"), ) def content(n, d, v): return json.dumps([n, d, v]) dash_duo.start_server(app) wait.until( lambda: dash_duo.find_element("#output").text == '[null, null, "A"]', 3) dash_duo.wait_for_element("#d").click() wait.until( lambda: dash_duo.find_element("#output").text == '[null, 1, "A"]', 3, ) dash_duo.wait_for_element("#n").click() wait.until( lambda: dash_duo.find_element("#output").text == '[1, 1, "A"]', 3, ) dash_duo.wait_for_element("#d").click() wait.until( lambda: dash_duo.find_element("#output").text == '[1, 2, "A"]', 3, )
def test_slsl010_range_loading_state(dash_dcc): lock = Lock() app = Dash(__name__) app.layout = html.Div([ html.Button(id="test-btn"), html.Label(id="test-div", children=["Horizontal Range Slider"]), dcc.RangeSlider( id="horizontal-range-slider", min=0, max=9, marks={ i: "Label {}".format(i) if i == 1 else str(i) for i in range(1, 6) }, value=[4, 6], ), ]) @app.callback(Output("horizontal-range-slider", "value"), [Input("test-btn", "n_clicks")]) def delayed_value(children): with lock: return [4, 6] with lock: dash_dcc.start_server(app) dash_dcc.wait_for_element( '#horizontal-range-slider[data-dash-is-loading="true"]') dash_dcc.wait_for_element( '#horizontal-range-slider:not([data-dash-is-loading="true"])') with lock: dash_dcc.wait_for_element("#test-btn").click() dash_dcc.wait_for_element( '#horizontal-range-slider[data-dash-is-loading="true"]') dash_dcc.wait_for_element( '#horizontal-range-slider:not([data-dash-is-loading="true"])') assert dash_dcc.get_logs() == []
def test_cbcx001_modified_response(dash_duo): app = Dash(__name__) app.layout = html.Div([dcc.Input(id="input", value="ab"), html.Div(id="output")]) @app.callback(Output("output", "children"), [Input("input", "value")]) def update_output(value): callback_context.response.set_cookie("dash_cookie", value + " - cookie") return value + " - output" dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", "ab - output") input1 = dash_duo.find_element("#input") input1.send_keys("cd") dash_duo.wait_for_text_to_equal("#output", "abcd - output") cookie = dash_duo.driver.get_cookie("dash_cookie") # cookie gets json encoded assert cookie["value"] == '"abcd - cookie"' assert not dash_duo.get_logs()
def test_dvct001_callback_timing(dash_thread_server): app = Dash(__name__) app.layout = html.Div() @app.callback(Output("x", "p"), Input("y", "q")) def x(y): callback_context.record_timing("pancakes", 1.23) sleep(0.5) return y dash_thread_server(app, debug=True, use_reloader=False, use_debugger=True) response = requests.post( dash_thread_server.url + "/_dash-update-component", json={ "output": "x.p", "outputs": { "id": "x", "property": "p" }, "inputs": [{ "id": "y", "property": "q", "value": 9 }], "changedPropIds": ["y.q"], }, ) # eg 'Server-Timing': '__dash_server;dur=505, pancakes;dur=1230' assert "Server-Timing" in response.headers st = response.headers["Server-Timing"] times = { k: int(float(v)) for k, v in [p.split(";dur=") for p in st.split(", ")] } assert "__dash_server" in times assert times["__dash_server"] >= 500 # 0.5 sec wait assert "pancakes" in times assert times["pancakes"] == 1230
def test_mkdw007_load_mathjax(dash_dcc, is_eager): app = Dash(__name__, eager_loading=is_eager) gravity = "$F=\\frac{Gm_1m_2}{r^2}$" app.layout = html.Div( [ html.Button("Add Second MathJax", id="btn"), dcc.Markdown( f""" # No Math Rendering Here! {gravity} """, id="md", mathjax=False, ), html.Div("initial", id="out"), ] ) @app.callback( Output("out", "children"), Input("btn", "n_clicks"), prevent_initial_call=True ) def add_math(n): return dcc.Markdown(f"# Math!\n{gravity}", id="md2", mathjax=True) dash_dcc.start_server(app) # Initial state: no MathJax loaded or rendered, unformatted text is shown dash_dcc.wait_for_contains_text("#md", gravity) dash_dcc.wait_for_no_elements("#md svg") assert not dash_dcc.driver.execute_script("return !!window.MathJax") btn = dash_dcc.find_element("#btn") btn.click() # One click: MathJax is loaded and rendered on the second, unformatted text is gone dash_dcc.wait_for_element("#md2 svg") assert gravity not in dash_dcc._get_element("#md2").text assert dash_dcc.driver.execute_script("return !!window.MathJax")
def test_click_simple(dash_duo): call_count = Value("i", 0) app = Dash(__name__) app.layout = html.Div([ html.Div(id="container"), html.Button("Click", id="button", n_clicks=0), html.Iframe(id="video", allow="fullscreen", referrerPolicy="origin"), ]) @app.callback( Output("container", "children"), Input("button", "n_clicks"), # The new percy runner loads the page, so to get consistent behavior for # call_count we need to skip the initial call prevent_initial_call=True, ) def update_output(n_clicks): call_count.value += 1 return "clicked {} times".format(n_clicks) dash_duo.start_server(app) dash_duo.find_element("#container") assert call_count.value == 0 dash_duo.percy_snapshot("html button initialization") dash_duo.find_element("#button").click() dash_duo.wait_for_text_to_equal("#container", "clicked 1 times") assert call_count.value == 1 dash_duo.percy_snapshot("html button click") assert not dash_duo.get_logs() assert dash_duo.find_element("#video").get_attribute( "allow") == "fullscreen" assert dash_duo.find_element("#video").get_attribute( "referrerpolicy") == "origin"
def test_ldcp001_loading_component_initialization(dash_dcc): lock = Lock() app = Dash(__name__) app.layout = html.Div( [dcc.Loading([html.Div(id="div-1")], className="loading")], id="root") @app.callback(Output("div-1", "children"), [Input("root", "n_clicks")]) def updateDiv(children): with lock: return "content" with lock: dash_dcc.start_server(app) dash_dcc.find_element(".loading .dash-spinner") # ensure inner component is also mounted dash_dcc.wait_for_text_to_equal("#div-1", "") dash_dcc.wait_for_text_to_equal("#div-1", "content") assert dash_dcc.get_logs() == []
def app_with_errors(): darkly = ( "https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/darkly/bootstrap.min.css" ) app = Dash(__name__, external_stylesheets=[darkly]) app.layout = html.Div([ html.Button(id="python", children="Python exception", n_clicks=0), html.Div(id="output"), ]) @app.callback(Output("output", "children"), [Input("python", "n_clicks")]) def update_output(n_clicks): if n_clicks == 1: return bad_sub() elif n_clicks == 2: raise Exception("Special 2 clicks exception") def bad_sub(): return 1 / 0 return app
def test_ldcp007_class_and_style_props(dash_dcc): lock = Lock() app = Dash(__name__) app.layout = html.Div([ html.Button("click", id="btn"), dcc.Loading( id="loading", className="spinner-class", parent_className="parent-class", style={"background-color": "rgb(255,192,203)"}, # rgb(240, 248, 255) = aliceblue parent_style={"border": "3px solid rgb(240, 248, 255)"}, children=html.Div(id="loading-child"), ), ]) @app.callback(Output("loading-child", "children"), [Input("btn", "n_clicks")]) def updateDiv(n_clicks): if n_clicks is None: return with lock: return "sample text content" dash_dcc.start_server(app) dash_dcc.wait_for_style_to_equal(".parent-class", "border-color", "rgb(240, 248, 255)") with lock: button = dash_dcc.find_element("#btn") button.click() dash_dcc.wait_for_style_to_equal(".spinner-class", "background-color", "rgba(255, 192, 203, 1)") assert dash_dcc.get_logs() == []
def test_inin017_late_component_register(dash_duo): app = Dash() app.layout = html.Div([ html.Button("Click me to put a dcc ", id="btn-insert"), html.Div(id="output") ]) @app.callback(Output("output", "children"), [Input("btn-insert", "n_clicks")]) def update_output(value): if value is None: raise PreventUpdate return dcc.Input(id="inserted-input") dash_duo.start_server(app) btn = dash_duo.find_element("#btn-insert") btn.click() dash_duo.find_element("#inserted-input")