|
5 | 5 | import dash_core_components as dcc
|
6 | 6 | from dash import Dash
|
7 | 7 | from dash.dependencies import Input, Output, State, ClientsideFunction, ALL
|
8 |
| -import dash |
| 8 | +from selenium.webdriver.common.keys import Keys |
9 | 9 |
|
10 | 10 |
|
11 | 11 | def test_clsd001_simple_clientside_serverside_callback(dash_duo):
|
@@ -377,48 +377,311 @@ def test_clsd009_clientside_callback_context_triggered(dash_duo):
|
377 | 377 | html.Button("btn1:0", id={"btn1": 0}),
|
378 | 378 | html.Button("btn1:1", id={"btn1": 1}),
|
379 | 379 | html.Button("btn1:2", id={"btn1": 2}),
|
380 |
| - html.Div(id="output-clientside"), |
| 380 | + html.Div(id="output-clientside", style={"font-family": "monospace"}), |
381 | 381 | ]
|
382 | 382 | )
|
383 | 383 |
|
384 | 384 | app.clientside_callback(
|
385 |
| - """ |
386 |
| - function (n_clicks0, n_clicks1) { |
387 |
| - console.log(dash_clientside.callback_context) |
388 |
| - return `triggered: ${JSON.stringify(dash_clientside.callback_context.triggered)}` |
389 |
| - } |
390 |
| - """, |
| 385 | + ClientsideFunction(namespace="clientside", function_name="triggered_to_str"), |
391 | 386 | Output("output-clientside", "children"),
|
392 |
| - [Input("btn0", "n_clicks"), |
393 |
| - Input({"btn1": ALL}, "n_clicks")], |
| 387 | + [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], |
394 | 388 | )
|
395 | 389 |
|
396 | 390 | dash_duo.start_server(app)
|
397 | 391 |
|
| 392 | + dash_duo.wait_for_text_to_equal("#output-clientside", ". = null") |
| 393 | + |
| 394 | + dash_duo.find_element("#btn0").click() |
| 395 | + |
398 | 396 | dash_duo.wait_for_text_to_equal(
|
399 |
| - "#output-clientside", r'triggered: [{"prop_id":".","value":null}]' |
| 397 | + "#output-clientside", "btn0.n_clicks = 1", |
| 398 | + ) |
| 399 | + |
| 400 | + dash_duo.find_element("button[id*='btn1\":0']").click() |
| 401 | + dash_duo.find_element("button[id*='btn1\":0']").click() |
| 402 | + |
| 403 | + dash_duo.wait_for_text_to_equal("#output-clientside", '{"btn1":0}.n_clicks = 2') |
| 404 | + |
| 405 | + dash_duo.find_element("button[id*='btn1\":2']").click() |
| 406 | + |
| 407 | + dash_duo.wait_for_text_to_equal( |
| 408 | + "#output-clientside", '{"btn1":2}.n_clicks = 1', |
| 409 | + ) |
| 410 | + |
| 411 | + |
| 412 | +def test_clsd010_clientside_callback_context_inputs(dash_duo): |
| 413 | + app = Dash(__name__, assets_folder="assets") |
| 414 | + |
| 415 | + app.layout = html.Div( |
| 416 | + [ |
| 417 | + html.Button("btn0", id="btn0"), |
| 418 | + html.Button("btn1:0", id={"btn1": 0}), |
| 419 | + html.Button("btn1:1", id={"btn1": 1}), |
| 420 | + html.Button("btn1:2", id={"btn1": 2}), |
| 421 | + html.Div(id="output-clientside", style={"font-family": "monospace"}), |
| 422 | + ] |
| 423 | + ) |
| 424 | + |
| 425 | + app.clientside_callback( |
| 426 | + ClientsideFunction(namespace="clientside", function_name="inputs_to_str"), |
| 427 | + Output("output-clientside", "children"), |
| 428 | + [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], |
| 429 | + ) |
| 430 | + |
| 431 | + dash_duo.start_server(app) |
| 432 | + |
| 433 | + dash_duo.wait_for_text_to_equal( |
| 434 | + "#output-clientside", |
| 435 | + ( |
| 436 | + "btn0.n_clicks = null, " |
| 437 | + '{"btn1":0}.n_clicks = null, ' |
| 438 | + '{"btn1":1}.n_clicks = null, ' |
| 439 | + '{"btn1":2}.n_clicks = null' |
| 440 | + ), |
400 | 441 | )
|
401 | 442 |
|
402 | 443 | dash_duo.find_element("#btn0").click()
|
403 | 444 |
|
404 | 445 | dash_duo.wait_for_text_to_equal(
|
405 | 446 | "#output-clientside",
|
406 |
| - r'triggered: [{"prop_id":"btn0.n_clicks","value":1}]', |
| 447 | + ( |
| 448 | + "btn0.n_clicks = 1, " |
| 449 | + '{"btn1":0}.n_clicks = null, ' |
| 450 | + '{"btn1":1}.n_clicks = null, ' |
| 451 | + '{"btn1":2}.n_clicks = null' |
| 452 | + ), |
407 | 453 | )
|
408 | 454 |
|
| 455 | + dash_duo.find_element("button[id*='btn1\":0']").click() |
409 | 456 | dash_duo.find_element("button[id*='btn1\":0']").click()
|
410 | 457 |
|
411 | 458 | dash_duo.wait_for_text_to_equal(
|
412 | 459 | "#output-clientside",
|
413 |
| - r'triggered: [{"prop_id":"{\"btn1\":0}.n_clicks","value":1}]', |
| 460 | + ( |
| 461 | + "btn0.n_clicks = 1, " |
| 462 | + '{"btn1":0}.n_clicks = 2, ' |
| 463 | + '{"btn1":1}.n_clicks = null, ' |
| 464 | + '{"btn1":2}.n_clicks = null' |
| 465 | + ), |
414 | 466 | )
|
415 | 467 |
|
416 | 468 | dash_duo.find_element("button[id*='btn1\":2']").click()
|
417 | 469 |
|
418 | 470 | dash_duo.wait_for_text_to_equal(
|
419 | 471 | "#output-clientside",
|
420 |
| - r'triggered: [{"prop_id":"{\"btn1\":2}.n_clicks","value":1}]', |
| 472 | + ( |
| 473 | + "btn0.n_clicks = 1, " |
| 474 | + '{"btn1":0}.n_clicks = 2, ' |
| 475 | + '{"btn1":1}.n_clicks = null, ' |
| 476 | + '{"btn1":2}.n_clicks = 1' |
| 477 | + ), |
| 478 | + ) |
| 479 | + |
| 480 | + |
| 481 | +def test_clsd011_clientside_callback_context_inputs_list(dash_duo): |
| 482 | + app = Dash(__name__, assets_folder="assets") |
| 483 | + |
| 484 | + app.layout = html.Div( |
| 485 | + [ |
| 486 | + html.Button("btn0", id="btn0"), |
| 487 | + html.Button("btn1:0", id={"btn1": 0}), |
| 488 | + html.Button("btn1:1", id={"btn1": 1}), |
| 489 | + html.Button("btn1:2", id={"btn1": 2}), |
| 490 | + html.Div(id="output-clientside", style={"font-family": "monospace"}), |
| 491 | + ] |
| 492 | + ) |
| 493 | + |
| 494 | + app.clientside_callback( |
| 495 | + ClientsideFunction(namespace="clientside", function_name="inputs_list_to_str"), |
| 496 | + Output("output-clientside", "children"), |
| 497 | + [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], |
| 498 | + ) |
| 499 | + |
| 500 | + dash_duo.start_server(app) |
| 501 | + |
| 502 | + dash_duo.wait_for_text_to_equal( |
| 503 | + "#output-clientside", |
| 504 | + ( |
| 505 | + '[{"id":"btn0","property":"n_clicks"},' |
| 506 | + '[{"id":{"btn1":0},"property":"n_clicks"},' |
| 507 | + '{"id":{"btn1":1},"property":"n_clicks"},' |
| 508 | + '{"id":{"btn1":2},"property":"n_clicks"}]]' |
| 509 | + ), |
| 510 | + ) |
| 511 | + |
| 512 | + dash_duo.find_element("#btn0").click() |
| 513 | + |
| 514 | + dash_duo.wait_for_text_to_equal( |
| 515 | + "#output-clientside", |
| 516 | + ( |
| 517 | + '[{"id":"btn0","property":"n_clicks","value":1},' |
| 518 | + '[{"id":{"btn1":0},"property":"n_clicks"},' |
| 519 | + '{"id":{"btn1":1},"property":"n_clicks"},' |
| 520 | + '{"id":{"btn1":2},"property":"n_clicks"}]]' |
| 521 | + ), |
| 522 | + ) |
| 523 | + |
| 524 | + dash_duo.find_element("button[id*='btn1\":0']").click() |
| 525 | + dash_duo.find_element("button[id*='btn1\":0']").click() |
| 526 | + |
| 527 | + dash_duo.wait_for_text_to_equal( |
| 528 | + "#output-clientside", |
| 529 | + ( |
| 530 | + '[{"id":"btn0","property":"n_clicks","value":1},' |
| 531 | + '[{"id":{"btn1":0},"property":"n_clicks","value":2},' |
| 532 | + '{"id":{"btn1":1},"property":"n_clicks"},' |
| 533 | + '{"id":{"btn1":2},"property":"n_clicks"}]]' |
| 534 | + ), |
421 | 535 | )
|
422 | 536 |
|
| 537 | + dash_duo.find_element("button[id*='btn1\":2']").click() |
| 538 | + |
| 539 | + dash_duo.wait_for_text_to_equal( |
| 540 | + "#output-clientside", |
| 541 | + ( |
| 542 | + '[{"id":"btn0","property":"n_clicks","value":1},' |
| 543 | + '[{"id":{"btn1":0},"property":"n_clicks","value":2},' |
| 544 | + '{"id":{"btn1":1},"property":"n_clicks"},' |
| 545 | + '{"id":{"btn1":2},"property":"n_clicks","value":1}]]' |
| 546 | + ), |
| 547 | + ) |
423 | 548 | # TODO: flush out these tests and make them look prettier.
|
424 | 549 | # Maybe one test for each of the callback_context properties?
|
| 550 | + |
| 551 | + |
| 552 | +def test_clsd012_clientside_callback_context_states(dash_duo): |
| 553 | + app = Dash(__name__, assets_folder="assets") |
| 554 | + |
| 555 | + app.layout = html.Div( |
| 556 | + [ |
| 557 | + dcc.Input(id="in0"), |
| 558 | + dcc.Input(id={"in1": 0}), |
| 559 | + dcc.Input(id={"in1": 1}), |
| 560 | + dcc.Input(id={"in1": 2}), |
| 561 | + html.Div(id="output-clientside", style={"font-family": "monospace"}), |
| 562 | + ] |
| 563 | + ) |
| 564 | + |
| 565 | + app.clientside_callback( |
| 566 | + ClientsideFunction(namespace="clientside", function_name="states_to_str"), |
| 567 | + Output("output-clientside", "children"), |
| 568 | + [Input("in0", "n_submit"), Input({"in1": ALL}, "n_submit")], |
| 569 | + [State("in0", "value"), State({"in1": ALL}, "value")], |
| 570 | + ) |
| 571 | + |
| 572 | + dash_duo.start_server(app) |
| 573 | + |
| 574 | + dash_duo.wait_for_text_to_equal( |
| 575 | + "#output-clientside", |
| 576 | + ( |
| 577 | + "in0.value = null, " |
| 578 | + '{"in1":0}.value = null, ' |
| 579 | + '{"in1":1}.value = null, ' |
| 580 | + '{"in1":2}.value = null' |
| 581 | + ), |
| 582 | + ) |
| 583 | + |
| 584 | + dash_duo.find_element("#in0").send_keys("test 0" + Keys.RETURN) |
| 585 | + |
| 586 | + dash_duo.wait_for_text_to_equal( |
| 587 | + "#output-clientside", |
| 588 | + ( |
| 589 | + "in0.value = test 0, " |
| 590 | + '{"in1":0}.value = null, ' |
| 591 | + '{"in1":1}.value = null, ' |
| 592 | + '{"in1":2}.value = null' |
| 593 | + ), |
| 594 | + ) |
| 595 | + |
| 596 | + dash_duo.find_element("input[id*='in1\":0']").send_keys("test 1" + Keys.RETURN) |
| 597 | + |
| 598 | + dash_duo.wait_for_text_to_equal( |
| 599 | + "#output-clientside", |
| 600 | + ( |
| 601 | + "in0.value = test 0, " |
| 602 | + '{"in1":0}.value = test 1, ' |
| 603 | + '{"in1":1}.value = null, ' |
| 604 | + '{"in1":2}.value = null' |
| 605 | + ), |
| 606 | + ) |
| 607 | + |
| 608 | + dash_duo.find_element("input[id*='in1\":2']").send_keys("test 2" + Keys.RETURN) |
| 609 | + |
| 610 | + dash_duo.wait_for_text_to_equal( |
| 611 | + "#output-clientside", |
| 612 | + ( |
| 613 | + "in0.value = test 0, " |
| 614 | + '{"in1":0}.value = test 1, ' |
| 615 | + '{"in1":1}.value = null, ' |
| 616 | + '{"in1":2}.value = test 2' |
| 617 | + ), |
| 618 | + ) |
| 619 | + |
| 620 | + |
| 621 | +def test_clsd013_clientside_callback_context_states_list(dash_duo): |
| 622 | + app = Dash(__name__, assets_folder="assets") |
| 623 | + |
| 624 | + app.layout = html.Div( |
| 625 | + [ |
| 626 | + dcc.Input(id="in0"), |
| 627 | + dcc.Input(id={"in1": 0}), |
| 628 | + dcc.Input(id={"in1": 1}), |
| 629 | + dcc.Input(id={"in1": 2}), |
| 630 | + html.Div(id="output-clientside", style={"font-family": "monospace"}), |
| 631 | + ] |
| 632 | + ) |
| 633 | + |
| 634 | + app.clientside_callback( |
| 635 | + ClientsideFunction(namespace="clientside", function_name="states_list_to_str"), |
| 636 | + Output("output-clientside", "children"), |
| 637 | + [Input("in0", "n_submit"), Input({"in1": ALL}, "n_submit")], |
| 638 | + [State("in0", "value"), State({"in1": ALL}, "value")], |
| 639 | + ) |
| 640 | + |
| 641 | + dash_duo.start_server(app) |
| 642 | + |
| 643 | + dash_duo.wait_for_text_to_equal( |
| 644 | + "#output-clientside", |
| 645 | + ( |
| 646 | + '[{"id":"in0","property":"value"},' |
| 647 | + '[{"id":{"in1":0},"property":"value"},' |
| 648 | + '{"id":{"in1":1},"property":"value"},' |
| 649 | + '{"id":{"in1":2},"property":"value"}]]' |
| 650 | + ), |
| 651 | + ) |
| 652 | + |
| 653 | + dash_duo.find_element("#in0").send_keys("test 0" + Keys.RETURN) |
| 654 | + |
| 655 | + dash_duo.wait_for_text_to_equal( |
| 656 | + "#output-clientside", |
| 657 | + ( |
| 658 | + '[{"id":"in0","property":"value","value":"test 0"},' |
| 659 | + '[{"id":{"in1":0},"property":"value"},' |
| 660 | + '{"id":{"in1":1},"property":"value"},' |
| 661 | + '{"id":{"in1":2},"property":"value"}]]' |
| 662 | + ), |
| 663 | + ) |
| 664 | + |
| 665 | + dash_duo.find_element("input[id*='in1\":0']").send_keys("test 1" + Keys.RETURN) |
| 666 | + |
| 667 | + dash_duo.wait_for_text_to_equal( |
| 668 | + "#output-clientside", |
| 669 | + ( |
| 670 | + '[{"id":"in0","property":"value","value":"test 0"},' |
| 671 | + '[{"id":{"in1":0},"property":"value","value":"test 1"},' |
| 672 | + '{"id":{"in1":1},"property":"value"},' |
| 673 | + '{"id":{"in1":2},"property":"value"}]]' |
| 674 | + ), |
| 675 | + ) |
| 676 | + |
| 677 | + dash_duo.find_element("input[id*='in1\":2']").send_keys("test 2" + Keys.RETURN) |
| 678 | + |
| 679 | + dash_duo.wait_for_text_to_equal( |
| 680 | + "#output-clientside", |
| 681 | + ( |
| 682 | + '[{"id":"in0","property":"value","value":"test 0"},' |
| 683 | + '[{"id":{"in1":0},"property":"value","value":"test 1"},' |
| 684 | + '{"id":{"in1":1},"property":"value"},' |
| 685 | + '{"id":{"in1":2},"property":"value","value":"test 2"}]]' |
| 686 | + ), |
| 687 | + ) |
0 commit comments