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

Commit d2e7d18

Browse files
committed
Test that each working component can initialize in an app.
1 parent cb8375c commit d2e7d18

File tree

1 file changed

+111
-21
lines changed

1 file changed

+111
-21
lines changed

test/test_component_validation.py

Lines changed: 111 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
import os
22
import dash
33
import unittest
4+
import uuid
5+
import pprint
6+
import dash_html_components as html
47
import dash_core_components as dcc
58

9+
from selenium.webdriver.support.ui import WebDriverWait
10+
from selenium.webdriver.support import expected_conditions as EC
11+
from selenium.webdriver.common.by import By
12+
613
from dash.development.component_loader import _get_metadata
14+
from .IntegrationTests import IntegrationTests
715

816
terminal_types = {
917
'string': 'hello world',
@@ -15,6 +23,21 @@
1523
}
1624

1725

26+
def get_components():
27+
path = os.path.join('dash_core_components', 'metadata.json')
28+
data = _get_metadata(path)
29+
components = {}
30+
# Iterate over each property name (which is a path to the component)
31+
for componentPath in data:
32+
componentData = data[componentPath]
33+
name = componentPath.split('/').pop().split('.')[0]
34+
if name not in ['Checklist', 'ConfirmDialog', 'ConfirmDialogProvider',
35+
'Interval', 'Graph', 'Location', 'Tab', 'Tabs',
36+
'Slider']:
37+
components[name] = componentData['props']
38+
return components
39+
40+
1841
def get_possible_values(type_object):
1942
if type_object:
2043
type_name = type_object.get('name', None)
@@ -46,32 +69,40 @@ def get_possible_values(type_object):
4669
yield v['value'].strip("\"'")
4770

4871

49-
class Tests(unittest.TestCase):
72+
def generate_all_components_with_props(component_props):
73+
all_props = []
74+
for component_name, props in component_props.items():
75+
component = getattr(dcc, component_name)
76+
for prop_name, schema in props.items():
77+
if prop_name != 'dashEvents':
78+
type_object = schema.get('type', None)
79+
for possible_value in get_possible_values(type_object):
80+
all_props.append(
81+
(
82+
component,
83+
{
84+
prop_name: possible_value,
85+
'id': '{}-{}-{}'.format(
86+
component_name,
87+
prop_name,
88+
uuid.uuid4()
89+
)
90+
}
91+
)
92+
)
93+
return all_props
94+
95+
96+
class InitializationTests(unittest.TestCase):
5097
@classmethod
5198
def setUpClass(cls):
52-
path = os.path.join('dash_core_components', 'metadata.json')
53-
data = _get_metadata(path)
54-
component_props = {}
55-
# Iterate over each property name (which is a path to the component)
56-
for componentPath in data:
57-
componentData = data[componentPath]
58-
name = componentPath.split('/').pop().split('.')[0]
59-
component_props[name] = componentData['props']
60-
cls.component_props = component_props
99+
cls.components = get_components()
61100

62101
def test_initializations(self):
63-
div_children = []
64-
for component_name, props in self.component_props.items():
65-
component = getattr(dcc, component_name)
66-
for prop_name, schema in props.items():
67-
if prop_name != 'dashEvents':
68-
type_object = schema.get('type', None)
69-
for possible_value in get_possible_values(type_object):
70-
div_children.append((component,
71-
{prop_name: possible_value,
72-
'id': 'hello'}))
102+
components_with_props =\
103+
generate_all_components_with_props(self.components)
73104
errors = 0
74-
for component, props in div_children:
105+
for component, props in components_with_props:
75106
try:
76107
component(**props)
77108
except (TypeError,
@@ -84,3 +115,62 @@ def test_initializations(self):
84115
errors += 1
85116
self.assertFalse(errors,
86117
"There were {} initialization errors.".format(errors))
118+
119+
120+
class CallbackTests(IntegrationTests):
121+
@classmethod
122+
def setUpClass(cls):
123+
super(CallbackTests, cls).setUpClass()
124+
cls.components = get_components()
125+
126+
def test(self):
127+
components_with_props =\
128+
generate_all_components_with_props(self.components)
129+
app = dash.Dash(__name__)
130+
131+
children = [
132+
component(**props) for component, props in components_with_props
133+
]
134+
app.layout = html.Div(
135+
children=[
136+
html.Button(
137+
'Click for next component',
138+
id='next-component'
139+
),
140+
html.Div(id='component-container'),
141+
html.Div(id='test-details'),
142+
dcc.Link()
143+
]
144+
)
145+
146+
@app.callback(
147+
dash.dependencies.Output('test-details', 'children'),
148+
[dash.dependencies.Input('next-component', 'n_clicks')]
149+
)
150+
def switch_detauls(n_clicks):
151+
if n_clicks is None:
152+
n_clicks = 0
153+
c, p = components_with_props[n_clicks]
154+
return html.Div([
155+
html.H1("Component: {}".format(c.__name__)),
156+
html.Pre(pprint.pformat(p))
157+
])
158+
159+
@app.callback(
160+
dash.dependencies.Output('component-container', 'children'),
161+
[dash.dependencies.Input('next-component', 'n_clicks')]
162+
)
163+
def switch_component(n_clicks):
164+
if n_clicks is None:
165+
n_clicks = 0
166+
return children[n_clicks]
167+
168+
self.startServer(app)
169+
170+
clicks = 0
171+
while clicks < len(children) - 1:
172+
next_button = WebDriverWait(self.driver, 20).until(
173+
EC.presence_of_element_located((By.ID, 'next-component'))
174+
)
175+
next_button.click()
176+
clicks += 1

0 commit comments

Comments
 (0)