Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit 3f61284

Browse files
byronbyronz
authored andcommitted
update store tests with api change
1 parent 8a3be6a commit 3f61284

File tree

3 files changed

+226
-11
lines changed

3 files changed

+226
-11
lines changed

tests/integration/store/test_clear_data.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ def test_stcd001_clear_data_on_all_types(store_app, dash_duo):
55
assert dash_duo.wait_for_contains_text("#output", store_app.uuid)
66

77
dash_duo.multiple_click("#btn", 3)
8-
assert dash_duo.local_storage == {"n_clicks": 3}
8+
assert dash_duo.get_local_storage() == {"n_clicks": 3}
99

1010
dash_duo.find_element("#clear-btn").click()
1111

1212
assert (
1313
not dash_duo.find_element("#output").text
14-
and not dash_duo.local_storage
15-
and not dash_duo.session_storage
14+
and not dash_duo.get_local_storage()
15+
and not dash_duo.get_session_storage()
1616
), "the clear_data should clear all data in three storage types"

tests/integration/store/test_data_lifecycle.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,41 @@ def test_stdl001_data_lifecycle_with_different_condition(store_app, dash_duo):
77
dash_duo.wait_for_text_to_equal(
88
"#output", '{{"n_clicks": {}}}'.format(nclicks)
99
)
10-
assert dash_duo.local_storage == {
10+
assert dash_duo.get_local_storage() == {
1111
"n_clicks": nclicks
1212
}, "local storage should contain the same click nums"
13-
assert dash_duo.session_storage == {
13+
assert dash_duo.get_session_storage() == {
1414
"n_clicks": nclicks
1515
}, "session storage should contain the same click nums"
1616

1717
dash_duo.driver.refresh()
1818
assert dash_duo.find_element("#output").text == '"{}"'.format(
1919
store_app.uuid
2020
), "a browser refresh will clear the memory type data to initial data"
21-
assert dash_duo.local_storage == {"n_clicks": nclicks}
22-
assert dash_duo.session_storage == {"n_clicks": nclicks}
21+
assert dash_duo.get_local_storage() == {"n_clicks": nclicks}
22+
assert dash_duo.get_session_storage() == {"n_clicks": nclicks}
2323

2424
dash_duo.open_new_tab()
2525
dash_duo.toggle_window() # switch to the new tab
26-
assert dash_duo.local_storage == {
26+
assert dash_duo.get_local_storage() == {
2727
"n_clicks": nclicks
2828
}, "local storage should be persistent"
2929
assert dash_duo.find_element("#output").text == '"{}"'.format(
3030
store_app.uuid
3131
), "memory storage should contain the initial data in new tab"
3232

3333
dash_duo.multiple_click("#btn", 2)
34-
assert dash_duo.session_storage == {"n_clicks": 2}
34+
assert dash_duo.get_session_storage() == {"n_clicks": 2}
3535
assert (
3636
'"n_clicks": 2' in dash_duo.wait_for_element("#output").text
3737
), "memory storage should reflect to the new clicks"
3838

3939
dash_duo.driver.close()
4040
dash_duo.switch_window()
41-
assert dash_duo.local_storage == {"n_clicks": 2}
41+
assert dash_duo.get_local_storage() == {"n_clicks": 2}
4242
assert dash_duo.find_element("#output").text == '"{}"'.format(
4343
store_app.uuid
4444
), "memory output should be the same as after previous refresh"
45-
assert dash_duo.session_storage == {
45+
assert dash_duo.get_session_storage() == {
4646
"n_clicks": nclicks
4747
}, "session storage should be specific per browser tab window"
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import json
2+
import time
3+
import itertools
4+
from pytest import approx
5+
import dash
6+
from dash.dependencies import Input, Output, State
7+
from dash.exceptions import PreventUpdate
8+
import dash_core_components as dcc
9+
import dash_html_components as html
10+
11+
12+
def test_stco001_storage_component_smoke(store_app, dash_duo):
13+
14+
app = dash.Dash(__name__)
15+
app.layout = html.Div(
16+
[
17+
dcc.Store(id="memory", storage_type="memory"),
18+
dcc.Store(id="storage", storage_type="local"),
19+
dcc.Store(id="session", storage_type="session", data=dummy_data),
20+
dcc.Store(id="initial-storage", storage_type="session"),
21+
html.Button("click me", id="btn"),
22+
html.Button("clear", id="clear-btn"),
23+
html.Button("set-init-storage", id="set-init-storage"),
24+
html.Div(id="memory-output"),
25+
html.Div(id="init-output"),
26+
]
27+
)
28+
29+
@app.callback(
30+
Output("storage", "data"),
31+
[Input("btn", "n_clicks")],
32+
[State("storage", "data")],
33+
)
34+
def on_click(n_clicks, storage):
35+
if n_clicks is None:
36+
return
37+
storage = storage or {}
38+
return {"clicked": storage.get("clicked", 0) + 1}
39+
40+
@app.callback(
41+
Output("storage", "clear_data"), [Input("clear-btn", "n_clicks")]
42+
)
43+
def on_clear(n_clicks):
44+
if n_clicks is None:
45+
return
46+
return True
47+
48+
@app.callback(Output("memory", "data"), [Input("storage", "data")])
49+
def on_memory(data):
50+
return data
51+
52+
@app.callback(
53+
Output("memory-output", "children"), [Input("memory", "data")]
54+
)
55+
def on_memory_json(data):
56+
if data is None:
57+
return ""
58+
return json.dumps(data)
59+
60+
@app.callback(
61+
Output("initial-storage", "data"),
62+
[Input("set-init-storage", "n_clicks")],
63+
)
64+
def on_init(n_clicks):
65+
if n_clicks is None:
66+
raise PreventUpdate
67+
68+
return "initialized"
69+
70+
@app.callback(
71+
Output("init-output", "children"),
72+
[Input("initial-storage", "modified_timestamp")],
73+
[State("initial-storage", "data")],
74+
)
75+
def init_output(ts, data):
76+
return json.dumps({"data": data, "ts": ts})
77+
78+
dash_duo.start_server(app)
79+
80+
getter = 'return JSON.parse(window.{}.getItem("{}"));'
81+
clicked_getter = getter.format("localStorage", "storage")
82+
83+
session = dash_duo.driver.execute_script(
84+
getter.format("sessionStorage", "session")
85+
)
86+
assert dummy_data == session
87+
88+
for i in range(1, 11):
89+
dash_duo.find_element("#btn").click()
90+
click_data = dash_duo.driver.execute_script(clicked_getter)
91+
assert i == click_data.get("clicked")
92+
mem = dash_duo.wait_for_element("#memory-output")
93+
assert i == int(json.loads(mem.text).get("clicked"))
94+
95+
96+
# Test initial timestamp output
97+
dash_duo.find_element("#set-init-storage").click()
98+
# the python ts ends at seconds while javascript one ends at ms
99+
ts = float(time.time() * 1000)
100+
dash_duo.driver.refresh()
101+
init = json.loads(dash_duo.wait_for_element("#init-output").text)
102+
103+
assert ts == approx(init.get("ts"), abs=10)
104+
assert init.get("data") == "initialized"
105+
106+
107+
def test_store_nested_data(dash_duo):
108+
app = dash.Dash(__name__)
109+
110+
nested = {"nested": {"nest": "much"}}
111+
nested_list = dict(my_list=[1, 2, 3])
112+
113+
app.layout = html.Div(
114+
[
115+
dcc.Store(id="store", storage_type="local"),
116+
html.Button("set object as key", id="obj-btn"),
117+
html.Button("set list as key", id="list-btn"),
118+
html.Output(id="output"),
119+
]
120+
)
121+
122+
@app.callback(
123+
Output("store", "data"),
124+
[
125+
Input("obj-btn", "n_clicks_timestamp"),
126+
Input("list-btn", "n_clicks_timestamp"),
127+
],
128+
)
129+
def on_obj_click(obj_ts, list_ts):
130+
if obj_ts is None and list_ts is None:
131+
raise PreventUpdate
132+
133+
# python 3 got the default props bug. plotly/dash#396
134+
if (obj_ts and not list_ts) or obj_ts > list_ts:
135+
return nested
136+
else:
137+
return nested_list
138+
139+
@app.callback(
140+
Output("output", "children"),
141+
[Input("store", "modified_timestamp")],
142+
[State("store", "data")],
143+
)
144+
def on_ts(ts, data):
145+
if ts is None:
146+
raise PreventUpdate
147+
return json.dumps(data)
148+
149+
dash_duo.start_server(app)
150+
151+
obj_btn = dash_duo.wait_for_element_by_css_selector("#obj-btn")
152+
list_btn = dash_duo.wait_for_element_by_css_selector("#list-btn")
153+
154+
obj_btn.click()
155+
time.sleep(1)
156+
dash_duo.wait_for_text_to_equal("#output", json.dumps(nested))
157+
# it would of crashed the app before adding the recursive check.
158+
159+
list_btn.click()
160+
time.sleep(1)
161+
dash_duo.wait_for_text_to_equal("#output", json.dumps(nested_list))
162+
163+
164+
def test_stco003_data_type_updates(dash_duo):
165+
app = dash.Dash(__name__)
166+
167+
types = [
168+
("str", "hello"),
169+
("number", 1),
170+
("dict", {"data": [2, 3, None]}),
171+
("list", [5, -6, 700000, 1e-12]),
172+
("null", None),
173+
("bool", True),
174+
("bool", False),
175+
("empty-dict", {}),
176+
]
177+
types_changes = list(
178+
itertools.chain(*itertools.combinations(types, 2))
179+
) + [ # No combinations as it add much test time.
180+
("list-dict-1", [1, 2, {"data": [55, 66, 77], "dummy": "dum"}]),
181+
("list-dict-2", [1, 2, {"data": [111, 99, 88]}]),
182+
("dict-3", {"a": 1, "c": 1}),
183+
("dict-2", {"a": 1, "b": None}),
184+
]
185+
186+
app.layout = html.Div(
187+
[
188+
html.Div(id="output"),
189+
html.Button("click", id="click"),
190+
dcc.Store(id="store"),
191+
]
192+
)
193+
194+
@app.callback(
195+
Output("output", "children"),
196+
[Input("store", "modified_timestamp")],
197+
[State("store", "data")],
198+
)
199+
def on_data(ts, data):
200+
if ts is None:
201+
raise PreventUpdate
202+
return json.dumps(data)
203+
204+
@app.callback(Output("store", "data"), [Input("click", "n_clicks")])
205+
def on_click(n_clicks):
206+
if n_clicks is None:
207+
raise PreventUpdate
208+
return types_changes[n_clicks - 1][1]
209+
210+
dash_duo.start_server(app)
211+
212+
button = dash_duo.wait_for_element("#click")
213+
for type_change in types_changes:
214+
button.click()
215+
dash_duo.wait_for_text_to_equal("#output", json.dumps(type_change[1]))

0 commit comments

Comments
 (0)