|
| 1 | +import json |
1 | 2 | import pytest
|
2 | 3 | import pandas as pd
|
3 | 4 | from multiprocessing import Value, Lock
|
4 | 5 | import numpy as np
|
5 | 6 | from time import sleep
|
6 |
| - |
| 7 | +import plotly.graph_objects as go |
7 | 8 | from dash import Dash, Input, Output, dcc, html
|
8 | 9 |
|
9 | 10 | import dash.testing.wait as wait
|
@@ -162,3 +163,123 @@ def update_graph(n_clicks):
|
162 | 163 | dash_dcc.wait_for_element("#my-graph:not([data-dash-is-loading])")
|
163 | 164 |
|
164 | 165 | assert dash_dcc.get_logs() == []
|
| 166 | + |
| 167 | + |
| 168 | +def test_grbs005_graph_update_frames(dash_dcc): |
| 169 | + app = Dash(__name__) |
| 170 | + |
| 171 | + def get_scatter(multiplier, offset): |
| 172 | + return go.Scatter( |
| 173 | + x=list(map(lambda n: n * multiplier, [0, 1, 2])), |
| 174 | + y=list(map(lambda n: n + offset, [0, 1, 2])), |
| 175 | + mode="markers", |
| 176 | + ) |
| 177 | + |
| 178 | + def get_figure(data, frames, title): |
| 179 | + return go.Figure( |
| 180 | + data=data, |
| 181 | + layout=go.Layout( |
| 182 | + title=title, |
| 183 | + yaxis=dict(range=[-1, 5]), |
| 184 | + xaxis=dict(range=[-3, 3]), |
| 185 | + updatemenus=[ |
| 186 | + dict( |
| 187 | + type="buttons", |
| 188 | + buttons=[ |
| 189 | + dict( |
| 190 | + label="Play", |
| 191 | + method="animate", |
| 192 | + args=[ |
| 193 | + None, |
| 194 | + { |
| 195 | + "frame": {"duration": 100, "redraw": True}, |
| 196 | + "fromcurrent": False, |
| 197 | + "transition": { |
| 198 | + "duration": 500, |
| 199 | + "easing": "quadratic-in-out", |
| 200 | + }, |
| 201 | + }, |
| 202 | + ], |
| 203 | + ) |
| 204 | + ], |
| 205 | + ) |
| 206 | + ], |
| 207 | + ), |
| 208 | + frames=frames, |
| 209 | + ) |
| 210 | + |
| 211 | + app.layout = html.Div( |
| 212 | + [ |
| 213 | + html.Label("Choose dataset"), |
| 214 | + dcc.RadioItems( |
| 215 | + id="change-data", |
| 216 | + options=[ |
| 217 | + {"label": "No data", "value": 0}, |
| 218 | + {"label": "Data A", "value": 1}, |
| 219 | + {"label": "Data B", "value": 2}, |
| 220 | + ], |
| 221 | + value=0, |
| 222 | + ), |
| 223 | + dcc.Graph( |
| 224 | + id="test-change", |
| 225 | + animate=True, |
| 226 | + animation_options={"frame": {"redraw": True}}, |
| 227 | + ), |
| 228 | + html.Div(id="relayout-data"), |
| 229 | + ] |
| 230 | + ) |
| 231 | + |
| 232 | + @app.callback( |
| 233 | + Output("relayout-data", "children"), |
| 234 | + [Input("test-change", "figure")], |
| 235 | + ) |
| 236 | + def show_relayout_data(data): |
| 237 | + frames = data.get("frames", []) |
| 238 | + if frames: |
| 239 | + return json.dumps(frames[0]["data"][0]["x"]) |
| 240 | + return "" |
| 241 | + |
| 242 | + @app.callback( |
| 243 | + Output("test-change", "figure"), |
| 244 | + Input("change-data", "value"), |
| 245 | + ) |
| 246 | + def set_data(dataset): |
| 247 | + if dataset == 1: |
| 248 | + title = "Dataset A" |
| 249 | + data = get_scatter(1, 0) |
| 250 | + frames = [ |
| 251 | + go.Frame(data=get_scatter(1, 1)), |
| 252 | + ] |
| 253 | + elif dataset == 2: |
| 254 | + title = "Dataset B" |
| 255 | + data = get_scatter(-1, 0) |
| 256 | + frames = [ |
| 257 | + go.Frame(data=get_scatter(-1, 1)), |
| 258 | + ] |
| 259 | + else: |
| 260 | + title = "Select a dataset" |
| 261 | + data = [] |
| 262 | + frames = [] |
| 263 | + |
| 264 | + fig = get_figure(data, frames, title) |
| 265 | + return fig |
| 266 | + |
| 267 | + dash_dcc.start_server(app) |
| 268 | + dash_dcc.wait_for_element("#test-change") |
| 269 | + |
| 270 | + dash_dcc.find_elements('input[type="radio"]')[0].click() |
| 271 | + |
| 272 | + assert ( |
| 273 | + dash_dcc.wait_for_element("#relayout-data").get_attribute("innerHTML") == "" |
| 274 | + ), "initial graph data must contain empty string" |
| 275 | + |
| 276 | + dash_dcc.find_elements('input[type="radio"]')[1].click() |
| 277 | + assert ( |
| 278 | + dash_dcc.wait_for_element("#relayout-data").get_attribute("innerHTML") |
| 279 | + == "[0, 1, 2]" |
| 280 | + ), "graph data must contain frame [0,1,2]" |
| 281 | + dash_dcc.find_elements('input[type="radio"]')[2].click() |
| 282 | + assert ( |
| 283 | + dash_dcc.wait_for_element("#relayout-data").get_attribute("innerHTML") |
| 284 | + == "[0, -1, -2]" |
| 285 | + ), "graph data must contain frame [0,-1,-2]" |
0 commit comments