Пример #1
0
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() == []
Пример #2
0
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")
Пример #3
0
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() == []
Пример #4
0
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"
Пример #5
0
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() == []
Пример #6
0
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,
        )
Пример #8
0
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() == []
Пример #9
0
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
Пример #10
0
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() == []
Пример #11
0
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() == []
Пример #12
0
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
Пример #13
0
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() == []
Пример #14
0
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() == []
Пример #15
0
    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)
Пример #16
0
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',
    )
Пример #17
0
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")
Пример #18
0
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
Пример #19
0
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")
Пример #20
0
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() == []
Пример #21
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)

    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,
    )
Пример #22
0
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() == []
Пример #23
0
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()
Пример #24
0
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
Пример #25
0
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")
Пример #26
0
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"
Пример #27
0
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() == []
Пример #28
0
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
Пример #29
0
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() == []
Пример #30
0
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")