def buttons(get_uuid: Callable) -> html.Div: uuid = get_uuid(WellOverviewLayoutElements.CHARTTYPE_BUTTON) return html.Div( style={"margin-bottom": "20px"}, children=[ html.Button( "Bar Chart", className="webviz-inplace-vol-btn", id={ "id": uuid, "button": "bar" }, ), html.Button( "Pie Chart", className="webviz-inplace-vol-btn", id={ "id": uuid, "button": "pie" }, ), html.Button( "Stacked Area Chart", className="webviz-inplace-vol-btn", id={ "id": uuid, "button": "area" }, ), ], )
def test_clsd011_clientside_callback_context_inputs_list(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="inputs_list_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", ('[{"id":"btn0","property":"n_clicks"},' '[{"id":{"btn1":0},"property":"n_clicks"},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("#btn0").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks"},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) 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", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks","value":2},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("button[id*='btn1\":2']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks","value":2},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks","value":1}]]'), )
def test_click_prev(dash_duo): call_count = Value("i", 0) timestamp_1 = Value("d", -5) timestamp_2 = Value("d", -5) app = Dash(__name__) app.layout = html.Div([ html.Div("Initial", id="container"), html.Button("Click", id="button-1", n_clicks=0, n_clicks_timestamp=-1), html.Button("Click", id="button-2", n_clicks=0, n_clicks_timestamp=-1), ]) @app.callback( Output("container", "children"), [ Input("button-1", "n_clicks"), Input("button-1", "n_clicks_timestamp"), Input("button-2", "n_clicks"), Input("button-2", "n_clicks_timestamp"), ], prevent_initial_call=True, ) def update_output(*args): print(args) call_count.value += 1 timestamp_1.value = args[1] timestamp_2.value = args[3] return "{}, {}".format(args[0], args[2]) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#container", "Initial") assert timestamp_1.value == -5 assert timestamp_2.value == -5 assert call_count.value == 0 dash_duo.find_element("#button-1").click() dash_duo.wait_for_text_to_equal("#container", "1, 0") assert timestamp_1.value > ((time.time() - (24 * 60 * 60)) * 1000) assert timestamp_2.value == -1 assert call_count.value == 1 prev_timestamp_1 = timestamp_1.value dash_duo.find_element("#button-2").click() dash_duo.wait_for_text_to_equal("#container", "1, 1") assert timestamp_1.value == prev_timestamp_1 assert timestamp_2.value > ((time.time() - 24 * 60 * 60) * 1000) assert call_count.value == 2 prev_timestamp_2 = timestamp_2.value dash_duo.find_element("#button-2").click() dash_duo.wait_for_text_to_equal("#container", "1, 2") assert timestamp_1.value == prev_timestamp_1 assert timestamp_2.value > prev_timestamp_2 assert timestamp_2.value > timestamp_1.value assert call_count.value == 3 assert not dash_duo.get_logs()
def updateDiv(n_clicks): if n_clicks is None: return with lock: return html.Div([ html.Button(id="btn-2"), dcc.Loading([html.Button(id="btn-3")], className="loading-1"), ])
def test_ldcp004_nested_loading_components(dash_dcc): lock = Lock() app = Dash(__name__) app.layout = html.Div( [ dcc.Loading( [ html.Button(id="btn-1"), dcc.Loading([html.Button(id="btn-2")], className="loading-2"), ], className="loading-1", ) ], id="root", ) @app.callback(Output("btn-1", "children"), [Input("btn-2", "n_clicks")]) def updateDiv1(n_clicks): if n_clicks is not None: with lock: return "changed 1" return "content 1" @app.callback(Output("btn-2", "children"), [Input("btn-1", "n_clicks")]) def updateDiv2(n_clicks): if n_clicks is not None: with lock: return "changed 2" return "content 2" dash_dcc.start_server(app) dash_dcc.wait_for_text_to_equal("#btn-1", "content 1") dash_dcc.wait_for_text_to_equal("#btn-2", "content 2") with lock: dash_dcc.find_element("#btn-1").click() dash_dcc.find_element(".loading-2 .dash-spinner") dash_dcc.wait_for_text_to_equal("#btn-2", "") dash_dcc.wait_for_text_to_equal("#btn-2", "changed 2") with lock: dash_dcc.find_element("#btn-2").click() dash_dcc.find_element(".loading-1 .dash-spinner") dash_dcc.wait_for_text_to_equal("#btn-1", "") dash_dcc.wait_for_text_to_equal("#btn-1", "changed 1") assert dash_dcc.get_logs() == []
def test_cbsc014_multiple_properties_update_at_same_time_on_same_component( dash_duo): call_count = Value("i", 0) timestamp_1 = Value("d", -5) timestamp_2 = Value("d", -5) app = Dash(__name__) app.layout = html.Div([ html.Div(id="container"), html.Button("Click", id="button-1", n_clicks=0, n_clicks_timestamp=-1), html.Button("Click", id="button-2", n_clicks=0, n_clicks_timestamp=-1), ]) @app.callback( Output("container", "children"), Input("button-1", "n_clicks"), Input("button-1", "n_clicks_timestamp"), Input("button-2", "n_clicks"), Input("button-2", "n_clicks_timestamp"), ) def update_output(n1, t1, n2, t2): call_count.value += 1 timestamp_1.value = t1 timestamp_2.value = t2 return "{}, {}".format(n1, n2) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#container", "0, 0") assert timestamp_1.value == -1 assert timestamp_2.value == -1 assert call_count.value == 1 dash_duo.percy_snapshot("Dash button-1 initialization 1") dash_duo.find_element("#button-1").click() dash_duo.wait_for_text_to_equal("#container", "1, 0") assert timestamp_1.value > ((time.time() - (24 * 60 * 60)) * 1000) assert timestamp_2.value == -1 assert call_count.value == 2 dash_duo.percy_snapshot("Dash button-1 click") prev_timestamp_1 = timestamp_1.value dash_duo.find_element("#button-2").click() dash_duo.wait_for_text_to_equal("#container", "1, 1") assert timestamp_1.value == prev_timestamp_1 assert timestamp_2.value > ((time.time() - 24 * 60 * 60) * 1000) assert call_count.value == 3 dash_duo.percy_snapshot("Dash button-2 click") prev_timestamp_2 = timestamp_2.value dash_duo.find_element("#button-2").click() dash_duo.wait_for_text_to_equal("#container", "1, 2") assert timestamp_1.value == prev_timestamp_1 assert timestamp_2.value > prev_timestamp_2 assert timestamp_2.value > timestamp_1.value assert call_count.value == 4 dash_duo.percy_snapshot("Dash button-2 click again")
def make_layout(n_clicks): if n_clicks is not None: return html.Div([ dcc.Input(id="input", value="hello, world"), html.Button(id="run-button", children="Run"), html.Button(id="cancel-button", children="Cancel"), html.Div(id="status", children="Finished"), html.Div(id="result", children="No results"), ]) else: return []
def test_stda002_nested_data(dash_dcc): app = Dash(__name__) nested = {"nested": {"nest": "much"}} nested_list = dict(my_list=[1, 2, 3]) app.layout = html.Div([ dcc.Store(id="store", storage_type="local"), html.Button("set object as key", id="obj-btn"), html.Button("set list as key", id="list-btn"), html.Output(id="output"), ]) @app.callback( Output("store", "data"), [ Input("obj-btn", "n_clicks_timestamp"), Input("list-btn", "n_clicks_timestamp"), ], ) def on_obj_click(obj_ts, list_ts): if obj_ts is None and list_ts is None: raise PreventUpdate # python 3 got the default props bug. plotly/dash#396 if (obj_ts and not list_ts) or obj_ts > list_ts: return nested else: return nested_list @app.callback( Output("output", "children"), [Input("store", "modified_timestamp")], [State("store", "data")], ) def on_ts(ts, data): if ts is None: raise PreventUpdate return json.dumps(data) dash_dcc.start_server(app) obj_btn = dash_dcc.wait_for_element("#obj-btn") list_btn = dash_dcc.find_element("#list-btn") obj_btn.click() dash_dcc.wait_for_text_to_equal("#output", json.dumps(nested)) # it would of crashed the app before adding the recursive check. list_btn.click() dash_dcc.wait_for_text_to_equal("#output", json.dumps(nested_list)) assert dash_dcc.get_logs() == []
def store_app(): app = Dash(__name__) app.uuid = UUID app.layout = html.Div([ dcc.Store(id="memory", storage_type="memory", data=app.uuid), dcc.Store(id="local", storage_type="local"), dcc.Store(id="session", storage_type="session"), html.Button("click me", id="btn"), html.Button("clear data", id="clear-btn"), html.Div(id="output"), ]) @app.callback( Output("output", "children"), [Input("memory", "modified_timestamp")], [State("memory", "data")], ) def write_memory(modified_ts, data): if data is None: return "" return json.dumps(data) @app.callback( [ Output("local", "clear_data"), Output("memory", "clear_data"), Output("session", "clear_data"), ], [Input("clear-btn", "n_clicks")], ) def on_clear(n_clicks): if n_clicks is None: raise PreventUpdate return True, True, True @app.callback( [ Output("memory", "data"), Output("local", "data"), Output("session", "data") ], [Input("btn", "n_clicks")], ) def on_click(n_clicks): if n_clicks is None: raise PreventUpdate return ({"n_clicks": n_clicks}, ) * 3 yield app
def test_intv002_restart(dash_dcc): app = Dash(__name__) app.layout = html.Div([ dcc.Interval( id="interval", interval=100, n_intervals=0, max_intervals=-1, ), html.Button("Start", id="start", n_clicks_timestamp=-1), html.Button("Stop", id="stop", n_clicks_timestamp=-1), html.Div(id="output"), ]) @app.callback( Output("interval", "max_intervals"), [ Input("start", "n_clicks_timestamp"), Input("stop", "n_clicks_timestamp"), ], ) def start_stop(start, stop): if start < stop: return 0 else: return -1 @app.callback(Output("output", "children"), [Input("interval", "n_intervals")]) def display_data(n_intervals): return f"Updated {n_intervals}" dash_dcc.start_server(app) wait.until(lambda: dash_dcc.find_element("#output").text != "Updated 0", 3) dash_dcc.find_element("#stop").click() time.sleep(2) text_now = dash_dcc.find_element("#output").text time.sleep(2) text_later = dash_dcc.find_element("#output").text assert text_now == text_later dash_dcc.find_element("#start").click() wait.until(lambda: dash_dcc.find_element("#output").text != text_later, 3) assert dash_dcc.get_logs() == []
def settings_layout(self) -> wcc.FlexBox: """Layout for color and other settings""" return wcc.Frame( style={"width": "40%"}, children=[ html.Div( style={"width": "100%"}, children=wcc.Dropdown( label="Seismic cube", id=self.uuid("cube"), options=[{ "label": Path(cube).stem, "value": cube } for cube in self.segyfiles], value=self.segyfiles[0], clearable=False, ), ), html.Div(children=[ wcc.Label(children="Set colorscale", ), wcc.ColorScales( id=self.uuid("color-scale"), colorscale=self.initial_colors, nSwatches=12, ), ], ), html.Div(children=[ wcc.RangeSlider( label="Color range", id=self.uuid("color-values"), min=self.init_state["min_value"], max=self.init_state["max_value"], value=[ self.init_state["min_value"], self.init_state["max_value"], ], tooltip={"placement": "bottom"}, step=calculate_slider_step( min_value=self.init_state["min_value"], max_value=self.init_state["max_value"], steps=100, ), ), ], ), html.Button(id=self.uuid("color-reset"), children="Reset Range"), html.Button(id=self.uuid("zoom"), children="Reset zoom"), ], )
def test_cbsc005_children_types(dash_duo, engine): with json_engine(engine): app = Dash() app.layout = html.Div([html.Button(id="btn"), html.Div("init", id="out")]) outputs = [ [None, ""], ["a string", "a string"], [123, "123"], [123.45, "123.45"], [[6, 7, 8], "678"], [["a", "list", "of", "strings"], "alistofstrings"], [["strings", 2, "numbers"], "strings2numbers"], [["a string", html.Div("and a div")], "a string\nand a div"], ] @app.callback(Output("out", "children"), [Input("btn", "n_clicks")]) def set_children(n): if n is None or n > len(outputs): return no_update return outputs[n - 1][0] dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#out", "init") for children, text in outputs: dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#out", text)
def test_cbsc003_callback_with_unloaded_async_component(dash_duo): app = Dash() app.layout = html.Div( children=[ dcc.Tabs( children=[ dcc.Tab( children=[ html.Button(id="btn", children="Update Input"), html.Div(id="output", children=["Hello"]), ] ), dcc.Tab(children=dash_table.DataTable(id="other-table")), ] ) ] ) @app.callback(Output("output", "children"), [Input("btn", "n_clicks")]) def update_out(n_clicks): if n_clicks is None: raise PreventUpdate return "Bye" dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", "Hello") dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", "Bye") assert dash_duo.get_logs() == []
def test_cbpu002_multi_output_no_update(dash_duo): app = Dash(__name__) app.layout = html.Div([ html.Button("B", "btn"), html.P("initial1", "n1"), html.P("initial2", "n2"), html.P("initial3", "n3"), ]) @app.callback( [ Output("n1", "children"), Output("n2", "children"), Output("n3", "children") ], [Input("btn", "n_clicks")], ) def show_clicks(n): # partial or complete cancellation of updates via no_update return [ no_update if n and n > 4 else n, no_update if n and n > 2 else n, # make a new instance, to mock up caching and restoring no_update copy(no_update), ] dash_duo.start_server(app) dash_duo.multiple_click("#btn", 10, 0.2) dash_duo.wait_for_text_to_equal("#n1", "4") dash_duo.wait_for_text_to_equal("#n2", "2") dash_duo.wait_for_text_to_equal("#n3", "initial3")
def html_button(icon="play_circle_filled", text="Start", id=" ", style={}): new_style = {"margin-top": "10px"} new_style.update(style) return html.Button(children=html_icon(icon, text), id=id, className="btn", style=new_style)
def test_upca001_upload_children_gallery(dash_dcc): app = Dash(__name__) app.layout = html.Div([ html.Div(id="waitfor"), html.Label("Empty"), dcc.Upload(), html.Label("Button"), dcc.Upload(html.Button("Upload File")), html.Label("Text"), dcc.Upload("Upload File"), html.Label("Link"), dcc.Upload(html.A("Upload File")), html.Label("Style"), dcc.Upload( ["Drag and Drop or ", html.A("Select a File")], style={ "width": "100%", "height": "60px", "lineHeight": "60px", "borderWidth": "1px", "borderStyle": "dashed", "borderRadius": "5px", "textAlign": "center", }, ), ]) dash_dcc.start_server(app) time.sleep(0.5) dash_dcc.percy_snapshot("upca001 children gallery") assert dash_dcc.get_logs() == []
def test_rdps006_move_on_page(dash_duo): app = Dash(__name__) app.layout = html.Div( [html.Button("move table", id="move-table"), html.Div(id="container")] ) @app.callback(Output("container", "children"), [Input("move-table", "n_clicks")]) def move_table(n): children = [html.Div("div 0", id="div0"), simple_table()] for i in range(1, (n or 0) + 1): children = [ html.Div("div {}".format(i), id="div{}".format(i)), html.Div(children), ] return children def find_last_div(n): dash_duo.wait_for_text_to_equal("#div{}".format(n), "div {}".format(n)) assert len(dash_duo.find_elements("#div{}".format(n + 1))) == 0 dash_duo.start_server(app) find_last_div(0) check_table_names(dash_duo, ["a", "b"]) rename_and_hide(dash_duo) check_table_names(dash_duo, [NEW_NAME]) for i in range(1, 5): dash_duo.find_element("#move-table").click() find_last_div(i) check_table_names(dash_duo, [NEW_NAME])
def test_cbmt001_called_multiple_times_and_out_of_order(dash_duo): app = Dash(__name__) app.layout = html.Div( [html.Button("Click", id="input", n_clicks=0), html.Div(id="output")] ) call_count = Value("i", 0) @app.callback(Output("output", "children"), [Input("input", "n_clicks")]) def update_output(n_clicks): call_count.value = call_count.value + 1 if n_clicks == 1: time.sleep(1) return n_clicks dash_duo.start_server(app) dash_duo.multiple_click("#input", clicks=3) time.sleep(3) assert call_count.value == 4, "get called 4 times" assert dash_duo.find_element("#output").text == "3", "clicked button 3 times" assert not dash_duo.redux_state_is_loading assert dash_duo.get_logs() == []
def test_cbcx004_triggered_backward_compat(dash_duo): app = Dash(__name__) app.layout = html.Div( [html.Button("click!", id="btn"), html.Div(id="out")]) @app.callback(Output("out", "children"), [Input("btn", "n_clicks")]) def report_triggered(n): triggered = callback_context.triggered bool_val = "truthy" if triggered else "falsy" split_propid = json.dumps(triggered[0]["prop_id"].split(".")) full_val = json.dumps(triggered) return "triggered is {}, has prop/id {}, and full value {}".format( bool_val, split_propid, full_val) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal( "#out", 'triggered is falsy, has prop/id ["", ""], and full value ' '[{"prop_id": ".", "value": null}]', ) dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal( "#out", 'triggered is truthy, has prop/id ["btn", "n_clicks"], and full value ' '[{"prop_id": "btn.n_clicks", "value": 1}]', )
def test_cbcx002_triggered(dash_duo): app = Dash(__name__) btns = ["btn-{}".format(x) for x in range(1, 6)] app.layout = html.Div([ html.Div([html.Button(btn, id=btn) for btn in btns]), html.Div(id="output") ]) @app.callback(Output("output", "children"), [Input(x, "n_clicks") for x in btns]) def on_click(*args): if not callback_context.triggered: raise PreventUpdate trigger = callback_context.triggered[0] return "Just clicked {} for the {} time!".format( trigger["prop_id"].split(".")[0], trigger["value"]) dash_duo.start_server(app) for i in range(1, 5): for btn in btns: dash_duo.find_element("#" + btn).click() dash_duo.wait_for_text_to_equal( "#output", "Just clicked {} for the {} time!".format(btn, i))
def test_cbcx008_triggered_id_pmc(dash_duo): app = Dash() app.layout = html.Div([ html.Button("Click me", id={ "type": "btn", "index": "myindex" }), html.Div(id="output"), ]) @app.callback(Output("output", "children"), Input({ "type": "btn", "index": ALL }, "n_clicks")) def func(n_clicks): if ctx.triggered: triggered_id, dict_id = next(iter(ctx.triggered_prop_ids.items())) assert dict_id == ctx.triggered_id if dict_id == {"type": "btn", "index": "myindex"}: return dict_id["index"] dash_duo.start_server(app) dash_duo.find_element( '#\\{\\"index\\"\\:\\"myindex\\"\\,\\"type\\"\\:\\"btn\\"\\}').click() dash_duo.wait_for_text_to_equal("#output", "myindex")
def test_rdps004_show_hide(dash_duo): app = Dash(__name__) app.layout = html.Div( [html.Button("Show/Hide", id="toggle-table"), html.Div(id="container")] ) @app.callback(Output("container", "children"), [Input("toggle-table", "n_clicks")]) def toggle_table(n): if (n or 0) % 2: return "nope" return simple_table( persistence_type="memory", persistence=1 if (n or 0) < 3 else 2 ) dash_duo.start_server(app) check_table_names(dash_duo, ["a", "b"]) rename_and_hide(dash_duo) check_table_names(dash_duo, [NEW_NAME]) dash_duo.find_element("#toggle-table").click() # table is gone dash_duo.wait_for_text_to_equal("#container", "nope") dash_duo.find_element("#toggle-table").click() # table is back, with persisted props check_table_names(dash_duo, [NEW_NAME]) dash_duo.find_element("#toggle-table").click() # gone again dash_duo.wait_for_text_to_equal("#container", "nope") dash_duo.find_element("#toggle-table").click() # table is back, new persistence val so props not persisted check_table_names(dash_duo, ["a", "b"])
def test_rdps013_persisted_props_nested(dash_duo): # testing persistenceTransforms with generated test components # with persisted prop and persisted nested prop app = dash.Dash(__name__) app.layout = html.Div( [ html.Button("click me", id="btn"), html.Div(id="container1"), html.Div(id="container2"), ] ) @app.callback(Output("container1", "children"), [Input("btn", "n_clicks")]) def update_container(n_clicks): return MyPersistedComponent(id="component-propName", persistence=True) @app.callback(Output("container2", "children"), [Input("btn", "n_clicks")]) def update_container2(n_clicks): return MyPersistedComponentNested(id="component-propPart", persistence=True) dash_duo.start_server(app) # send lower case strings to test components dash_duo.find_element("#component-propName").send_keys("alpaca") dash_duo.find_element("#component-propPart").send_keys("artichoke") dash_duo.find_element("#btn").click() # persistenceTransforms should return upper case strings dash_duo.wait_for_text_to_equal("#component-propName", "ALPACA") dash_duo.wait_for_text_to_equal("#component-propPart", "ARTICHOKE")
def test_rdps008_unsaved_part_changed(dash_duo): app = Dash(__name__) app.layout = html.Div( [html.Button("toggle deletable", id="deletable"), html.Div(id="container")] ) @app.callback(Output("container", "children"), [Input("deletable", "n_clicks")]) def toggle_deletable(n): if (n or 0) % 2: return simple_table(columns=table_columns(("a", "b"), deletable=True)) return simple_table() dash_duo.start_server(app) check_table_names(dash_duo, ["a", "b"]) rename_and_hide(dash_duo) check_table_names(dash_duo, [NEW_NAME]) assert len(dash_duo.find_elements(".column-header--delete")) == 0 dash_duo.find_element("#deletable").click() # column names still persisted when columns.deletable changed # because extracted name list didn't change check_table_names(dash_duo, [NEW_NAME]) assert len(dash_duo.find_elements(".column-header--delete")) == 1 dash_duo.find_element("#deletable").click() check_table_names(dash_duo, [NEW_NAME]) assert len(dash_duo.find_elements(".column-header--delete")) == 0
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) dash_duo.wait_for_text_to_equal("#output", '[null, null, "A"]') dash_duo.wait_for_element("#d").click() dash_duo.wait_for_text_to_equal("#output", '[null, 1, "A"]') dash_duo.wait_for_element("#n").click() dash_duo.wait_for_text_to_equal("#output", '[1, 1, "A"]') dash_duo.wait_for_element("#d").click() dash_duo.wait_for_text_to_equal("#output", '[1, 2, "A"]')
def test_dvui004_width_props(dash_duo): app = Dash(__name__) app.layout = html.Div( [html.Button(["Click me!"], id="btn"), WidthComponent(id="width")] ) @app.callback(Output("width", "width"), Input("btn", "n_clicks")) def get_width(n_clicks): n_clicks = n_clicks if n_clicks is not None else 0 return (n_clicks + 1) * 10 dash_duo.start_server( app, debug=True, use_reloader=False, use_debugger=True, dev_tools_hot_reload=False, ) dash_duo.find_element(".dash-debug-menu").click() sleep(1) # wait for debug menu opening animation dash_duo.find_element(".dash-debug-menu__button--callbacks").click() sleep(3) # wait for callback graph to draw assert dash_duo.get_logs() == []
def test_cbmt006_derived_props(dash_duo): app = Dash(__name__) app.layout = html.Div([ html.Div(id="output"), html.Button("click", id="btn"), dcc.Store(id="store") ]) @app.callback( Output("output", "children"), [Input("store", "modified_timestamp")], [State("store", "data")], ) def on_data(ts, data): return data @app.callback(Output("store", "data"), [Input("btn", "n_clicks")]) def on_click(n_clicks): return n_clicks or 0 dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", "0") dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", "1") dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", "2")
def get_app2(): app = dash.Dash(__name__) app.layout = html.Div([ html.Button("i=20", id="button", n_clicks=0), DataTable( id="table", page_size=5, columns=[{ "name": "i", "id": "i" }, { "name": "square", "id": "square" }], data=[{ "i": i, "square": i**2 } for i in range(50 + 1)], page_current=5, ), dcc.Graph(), ]) @app.callback(Output("table", "data"), Input("button", "n_clicks")) def update_table_data(n): return ([{ "i": i, "square": i**2 } for i in range(20 + 1)] if n > 0 else dash.no_update) return app
def test_cbcx007_triggered_id(dash_duo): app = Dash(__name__) btns = ["btn-{}".format(x) for x in range(1, 6)] app.layout = html.Div([ html.Div([html.Button(btn, id=btn) for btn in btns]), html.Div(id="output") ]) @app.callback(Output("output", "children"), [Input(x, "n_clicks") for x in btns]) def on_click(*args): if not ctx.triggered: raise PreventUpdate for btn in btns: if btn in ctx.triggered_prop_ids.values(): assert btn == ctx.triggered_id return f"Just clicked {btn}" dash_duo.start_server(app) for i in range(1, 5): for btn in btns: dash_duo.find_element("#" + btn).click() dash_duo.wait_for_text_to_equal("#output", f"Just clicked {btn}")
def test_rdps005_persisted_props(dash_duo): app = Dash(__name__) app.layout = html.Div( [ html.Button("toggle persisted_props", id="toggle-table"), html.Div(id="container"), ] ) @app.callback(Output("container", "children"), [Input("toggle-table", "n_clicks")]) def toggle_table(n): if (n or 0) % 2: return simple_table(persisted_props=["data", "columns.name"]) return simple_table() dash_duo.start_server(app) check_table_names(dash_duo, ["a", "b"]) rename_and_hide(dash_duo) check_table_names(dash_duo, [NEW_NAME]) dash_duo.find_element("#toggle-table").click() # hidden_columns not persisted check_table_names(dash_duo, [NEW_NAME, "b"]) dash_duo.find_element("#toggle-table").click() # back to original persisted_props hidden_columns returns check_table_names(dash_duo, [NEW_NAME])