Skip to content

Commit 4566a92

Browse files
committed
🐅 integration tests
1 parent 587de56 commit 4566a92

File tree

2 files changed

+303
-16
lines changed

2 files changed

+303
-16
lines changed

tests/integration/clientside/assets/clientside.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,30 @@ window.dash_clientside.clientside = {
5656
resolve('foo');
5757
}, 1);
5858
});
59-
}
59+
},
6060

61-
}
61+
triggered_to_str: function(n_clicks0, n_clicks1) {
62+
const triggered = dash_clientside.callback_context.triggered;
63+
return triggered.map(t => `${t.prop_id} = ${t.value}`).join(', ');
64+
},
65+
66+
inputs_to_str: function(n_clicks0, n_clicks1) {
67+
const inputs = dash_clientside.callback_context.inputs;
68+
const keys = Object.keys(inputs);
69+
return keys.map(k => `${k} = ${inputs[k]}`).join(', ');
70+
},
71+
72+
inputs_list_to_str: function(n_clicks0, n_clicks1) {
73+
return JSON.stringify(dash_clientside.callback_context.inputs_list);
74+
},
75+
76+
states_to_str: function(val0, val1, st0, st1) {
77+
const states = dash_clientside.callback_context.states;
78+
const keys = Object.keys(states);
79+
return keys.map(k => `${k} = ${states[k]}`).join(', ');
80+
},
81+
82+
states_list_to_str: function(val0, val1, st0, st1) {
83+
return JSON.stringify(dash_clientside.callback_context.states_list);
84+
}
85+
};

tests/integration/clientside/test_clientside.py

Lines changed: 277 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import dash_core_components as dcc
66
from dash import Dash
77
from dash.dependencies import Input, Output, State, ClientsideFunction, ALL
8-
import dash
8+
from selenium.webdriver.common.keys import Keys
99

1010

1111
def test_clsd001_simple_clientside_serverside_callback(dash_duo):
@@ -377,48 +377,311 @@ def test_clsd009_clientside_callback_context_triggered(dash_duo):
377377
html.Button("btn1:0", id={"btn1": 0}),
378378
html.Button("btn1:1", id={"btn1": 1}),
379379
html.Button("btn1:2", id={"btn1": 2}),
380-
html.Div(id="output-clientside"),
380+
html.Div(id="output-clientside", style={"font-family": "monospace"}),
381381
]
382382
)
383383

384384
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"),
391386
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")],
394388
)
395389

396390
dash_duo.start_server(app)
397391

392+
dash_duo.wait_for_text_to_equal("#output-clientside", ". = null")
393+
394+
dash_duo.find_element("#btn0").click()
395+
398396
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+
),
400441
)
401442

402443
dash_duo.find_element("#btn0").click()
403444

404445
dash_duo.wait_for_text_to_equal(
405446
"#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+
),
407453
)
408454

455+
dash_duo.find_element("button[id*='btn1\":0']").click()
409456
dash_duo.find_element("button[id*='btn1\":0']").click()
410457

411458
dash_duo.wait_for_text_to_equal(
412459
"#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+
),
414466
)
415467

416468
dash_duo.find_element("button[id*='btn1\":2']").click()
417469

418470
dash_duo.wait_for_text_to_equal(
419471
"#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+
),
421535
)
422536

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+
)
423548
# TODO: flush out these tests and make them look prettier.
424549
# 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

Comments
 (0)