|
12 | 12 | import dash
|
13 | 13 |
|
14 | 14 | from dash.dependencies import Input, Output
|
15 |
| -from dash.exceptions import PreventUpdate, CallbackException |
| 15 | +from dash.exceptions import ( |
| 16 | + PreventUpdate, CallbackException, MissingCallbackContextException |
| 17 | +) |
16 | 18 | from .IntegrationTests import IntegrationTests
|
17 | 19 | from .utils import assert_clean_console, invincible, wait_for
|
18 | 20 |
|
@@ -571,3 +573,45 @@ def failure(children):
|
571 | 573 | 'Same output and input: input-output.children',
|
572 | 574 | context.exception.args[0]
|
573 | 575 | )
|
| 576 | + |
| 577 | + def test_callback_context(self): |
| 578 | + app = dash.Dash(__name__) |
| 579 | + |
| 580 | + btns = ['btn-{}'.format(x) for x in range(1, 6)] |
| 581 | + |
| 582 | + app.layout = html.Div([ |
| 583 | + html.Div([ |
| 584 | + html.Button(x, id=x) for x in btns |
| 585 | + ]), |
| 586 | + html.Div(id='output'), |
| 587 | + ]) |
| 588 | + |
| 589 | + @app.callback(Output('output', 'children'), |
| 590 | + [Input(x, 'n_clicks') for x in btns]) |
| 591 | + def on_click(*args): |
| 592 | + if not dash.callback_context.triggered: |
| 593 | + raise PreventUpdate |
| 594 | + trigger = dash.callback_context.triggered[0] |
| 595 | + return 'Just clicked {} for the {} time!'.format( |
| 596 | + trigger['prop_id'].split('.')[0], trigger['value'] |
| 597 | + ) |
| 598 | + |
| 599 | + self.startServer(app) |
| 600 | + |
| 601 | + btn_elements = [ |
| 602 | + self.wait_for_element_by_id(x) for x in btns |
| 603 | + ] |
| 604 | + |
| 605 | + for i in range(1, 5): |
| 606 | + for j, btn in enumerate(btns): |
| 607 | + btn_elements[j].click() |
| 608 | + self.wait_for_text_to_equal( |
| 609 | + '#output', |
| 610 | + 'Just clicked {} for the {} time!'.format( |
| 611 | + btn, i |
| 612 | + ) |
| 613 | + ) |
| 614 | + |
| 615 | + def test_no_callback_context(self): |
| 616 | + with self.assertRaises(MissingCallbackContextException): |
| 617 | + no_context = dash.callback_context.inputs |
0 commit comments