Basic string3.14
Child div with basic string
Grandchild div
Great grandchild
3.14159another basic string
\ No newline at end of file
+Basic string3.14
Child div with basic string
Grandchild div
Great grandchild
3.14159another basic string
diff --git a/tests/test_render.py b/tests/test_render.py
index ce6ba5a..9c8eca6 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -1,3 +1,4 @@
+# -*- coding: UTF-8 -*-
import os
import textwrap
@@ -109,7 +110,6 @@ def request_queue_assertions(
if expected_length is not None:
self.assertEqual(len(request_queue), expected_length)
-
def test_initial_state(self):
app = Dash(__name__)
my_class_attrs = {
@@ -154,11 +154,12 @@ def test_initial_state(self):
self.startServer(app)
el = self.wait_for_element_by_css_selector('#react-entry-point')
+ # Note: this .html file shows there's no undo/redo button by default
_dash_app_content_html = os.path.join(
os.path.dirname(__file__),
'test_assets', 'initial_state_dash_app_content.html')
with open(_dash_app_content_html) as fp:
- rendered_dom = BeautifulSoup(fp.read(), 'lxml')
+ rendered_dom = BeautifulSoup(fp.read().strip(), 'lxml')
fetched_dom = BeautifulSoup(el.get_attribute('outerHTML'), 'lxml')
self.assertEqual(
@@ -211,6 +212,79 @@ def test_initial_state(self):
self.assertTrue(self.is_console_clean())
+ def click_undo(self):
+ undo_selector = '._dash-undo-redo span:first-child div:last-child'
+ undo = self.wait_for_element_by_css_selector(undo_selector)
+ self.wait_for_text_to_equal(undo_selector, 'undo')
+ undo.click()
+
+ def click_redo(self):
+ redo_selector = '._dash-undo-redo span:last-child div:last-child'
+ self.wait_for_text_to_equal(redo_selector, 'redo')
+ redo = self.wait_for_element_by_css_selector(redo_selector)
+ redo.click()
+
+ def check_undo_redo_exist(self, has_undo, has_redo):
+ selector = '._dash-undo-redo span div:last-child'
+ els = self.driver.find_elements_by_css_selector(selector)
+ texts = (['undo'] if has_undo else []) + (['redo'] if has_redo else [])
+
+ self.assertEqual(len(els), len(texts))
+ for el, text in zip(els, texts):
+ self.assertEqual(el.text, text)
+
+ def test_undo_redo(self):
+ app = Dash(__name__, show_undo_redo=True)
+ app.layout = html.Div([dcc.Input(id='a'), html.Div(id='b')])
+
+ @app.callback(Output('b', 'children'), [Input('a', 'value')])
+ def set_b(a):
+ return a
+
+ self.startServer(app)
+
+ a = self.wait_for_element_by_css_selector('#a')
+ a.send_keys('xyz')
+
+ self.wait_for_text_to_equal('#b', 'xyz')
+ self.check_undo_redo_exist(True, False)
+
+ self.click_undo()
+ self.wait_for_text_to_equal('#b', 'xy')
+ self.check_undo_redo_exist(True, True)
+
+ self.click_undo()
+ self.wait_for_text_to_equal('#b', 'x')
+ self.check_undo_redo_exist(True, True)
+
+ self.click_redo()
+ self.wait_for_text_to_equal('#b', 'xy')
+ self.check_undo_redo_exist(True, True)
+
+ self.percy_snapshot(name='undo-redo')
+
+ self.click_undo()
+ self.click_undo()
+ self.wait_for_text_to_equal('#b', '')
+ self.check_undo_redo_exist(False, True)
+
+ def test_no_undo_redo(self):
+ app = Dash(__name__)
+ app.layout = html.Div([dcc.Input(id='a'), html.Div(id='b')])
+
+ @app.callback(Output('b', 'children'), [Input('a', 'value')])
+ def set_b(a):
+ return a
+
+ self.startServer(app)
+
+ a = self.wait_for_element_by_css_selector('#a')
+ a.send_keys('xyz')
+
+ self.wait_for_text_to_equal('#b', 'xyz')
+ toolbar = self.driver.find_elements_by_css_selector('._dash-undo-redo')
+ self.assertEqual(len(toolbar), 0)
+
def test_array_of_falsy_child(self):
app = Dash(__name__)
app.layout = html.Div(id='nully-wrapper', children=[0])
@@ -328,10 +402,9 @@ def update_input(value):
'#react-entry-point').get_attribute('innerHTML'),
'lxml').select_one('#output > div').contents
- self.assertTrue(
- pad_input.attrs == {'type': 'text', 'id': 'sub-input-1', 'value': 'sub input initial value'}
- and pad_input.name == 'input',
- "pad input is correctly rendered")
+ self.assertEqual(pad_input.attrs['value'], 'sub input initial value')
+ self.assertEqual(pad_input.attrs['id'], 'sub-input-1')
+ self.assertEqual(pad_input.name, 'input')
self.assertTrue(
pad_div.text == pad_input.attrs['value']