diff --git a/CHANGELOG.md b/CHANGELOG.md index 04635e5d9..7e8b22f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] +### Added +- [#840](https://github.com/plotly/dash-table/pull/840) Add styling properties to `dcc.Loading` component + + `parent_className`: Add CSS class for the outermost `dcc.Loading` parent div DOM node + + `parent_style`: Add CSS style property for the outermost `dcc.Loading` parent div DOM node + + provides a workaround for the previous behaviour the of `className` property, which changed in [#740](https://github.com/plotly/dash-core-components/pull/740). `parent_className` (or inline styles in `parent_style`) now allow CSS rules to be applied to the outermost `dcc.Loading` div, which is no longer covered by `className` on loading completion as of Dash Core Components `>= 1.9.1` (Dash `>= 1.11.0`). + ## [1.10.2] - 2020-07-27 - [#835](https://github.com/plotly/dash-core-components/pull/835) - Upgraded Plotly.js to [1.54.7](https://github.com/plotly/plotly.js/releases/tag/v1.54.7) diff --git a/src/components/Loading.react.js b/src/components/Loading.react.js index 42e560843..b46b8ebc2 100644 --- a/src/components/Loading.react.js +++ b/src/components/Loading.react.js @@ -5,6 +5,7 @@ import DefaultSpinner from '../fragments/Loading/spinners/DefaultSpinner.jsx'; import CubeSpinner from '../fragments/Loading/spinners/CubeSpinner.jsx'; import CircleSpinner from '../fragments/Loading/spinners/CircleSpinner.jsx'; import DotSpinner from '../fragments/Loading/spinners/DotSpinner.jsx'; +import {mergeRight} from 'ramda'; function getSpinner(spinnerType) { switch (spinnerType) { @@ -44,6 +45,8 @@ export default class Loading extends Component { color, className, style, + parent_className, + parent_style, fullscreen, debug, type: spinnerType, @@ -53,7 +56,14 @@ export default class Loading extends Component { const Spinner = isLoading && getSpinner(spinnerType); return ( -
+
{this.props.children}
{isLoading && ( @@ -117,11 +127,21 @@ Loading.propTypes = { */ className: PropTypes.string, + /** + * Additional CSS class for the outermost dcc.Loading parent div DOM node + */ + parent_className: PropTypes.string, + /** * Additional CSS styling for the spinner root DOM node */ style: PropTypes.object, + /** + * Additional CSS styling for the outermost dcc.Loading parent div DOM node + */ + parent_style: PropTypes.object, + /** * Primary colour used for the loading spinners */ diff --git a/tests/integration/loading/test_loading_component.py b/tests/integration/loading/test_loading_component.py index 905100c11..11ba9fdbb 100644 --- a/tests/integration/loading/test_loading_component.py +++ b/tests/integration/loading/test_loading_component.py @@ -278,3 +278,88 @@ def get_graph_visibility(): assert len(dash_dcc.find_elements(".js-plotly-plot .bars path")) == 4 assert dash_dcc.driver.execute_script(test_identity) assert get_graph_visibility() == "visible" + + +def test_ldcp007_class_and_style_props(dash_dcc): + lock = Lock() + + app = dash.Dash(__name__) + + app.layout = html.Div( + [ + html.Button("click", id="btn"), + dcc.Loading( + id="loading", + className="spinner-class", + parent_className="parent-class", + style={"background-color": "rgb(255,192,203)"}, + # rgb(240, 248, 255) = aliceblue + parent_style={"border": "3px solid rgb(240, 248, 255)"}, + children=html.Div(id="loading-child"), + ), + ] + ) + + @app.callback(Output("loading-child", "children"), [Input("btn", "n_clicks")]) + def updateDiv(n_clicks): + if n_clicks is None: + return + + with lock: + return "sample text content" + + dash_dcc.start_server(app) + + dash_dcc.wait_for_style_to_equal( + ".parent-class", "border-color", "rgb(240, 248, 255)" + ) + + with lock: + button = dash_dcc.find_element("#btn") + button.click() + dash_dcc.wait_for_style_to_equal( + ".spinner-class", "background-color", "rgba(255, 192, 203, 1)" + ) + + assert not dash_dcc.get_logs() + + +def test_ldcp008_graph_in_loading_fits_container_height(dash_dcc): + lock = Lock() + + app = dash.Dash(__name__) + + app.layout = html.Div( + className="outer-container", + children=[ + html.Div( + dcc.Loading( + parent_style={"height": "100%"}, + children=dcc.Graph( + style={"height": "100%"}, + figure={ + "data": [ + { + "x": [1, 2, 3, 4], + "y": [4, 1, 6, 9], + "line": {"shape": "spline"}, + } + ] + }, + ), + ), + ) + ], + style={"display": "flex", "height": "300px"}, + ) + + dash_dcc.start_server(app) + + with lock: + dash_dcc.wait_for_style_to_equal(".js-plotly-plot", "height", "300px") + + assert dash_dcc.wait_for_element(".js-plotly-plot").size.get( + "height" + ) == dash_dcc.wait_for_element(".outer-container").size.get("height") + + assert not dash_dcc.get_logs() diff --git a/tests/test_integration_1.py b/tests/test_integration_1.py index 7cedf563e..011d6a9c0 100644 --- a/tests/test_integration_1.py +++ b/tests/test_integration_1.py @@ -43,22 +43,25 @@ def test_loading_slider(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.Button(id='test-btn'), - html.Label(id='test-div', children=['Horizontal Slider']), - dcc.Slider( - id='horizontal-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=5, - ), - ]) + app.layout = html.Div( + [ + html.Button(id="test-btn"), + html.Label(id="test-div", children=["Horizontal Slider"]), + dcc.Slider( + id="horizontal-slider", + min=0, + max=9, + marks={ + i: "Label {}".format(i) if i == 1 else str(i) + for i in range(1, 6) + }, + value=5, + ), + ] + ) @app.callback( - Output('horizontal-slider', 'value'), - [Input('test-btn', 'n_clicks')] + Output("horizontal-slider", "value"), [Input("test-btn", "n_clicks")] ) def user_delayed_value(n_clicks): with lock: @@ -76,7 +79,7 @@ def user_delayed_value(n_clicks): ) with lock: - self.driver.find_element_by_id('test-btn').click() + self.driver.find_element_by_id("test-btn").click() self.wait_for_element_by_css_selector( '#horizontal-slider[data-dash-is-loading="true"]' @@ -87,26 +90,30 @@ def user_delayed_value(n_clicks): ) for entry in self.get_log(): - raise Exception('browser error logged during test', entry) + raise Exception("browser error logged during test", entry) def test_horizontal_slider(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.Label('Horizontal Slider'), - dcc.Slider( - id='horizontal-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=5, - ), - ]) + app.layout = html.Div( + [ + html.Label("Horizontal Slider"), + dcc.Slider( + id="horizontal-slider", + min=0, + max=9, + marks={ + i: "Label {}".format(i) if i == 1 else str(i) + for i in range(1, 6) + }, + value=5, + ), + ] + ) self.startServer(app) - self.wait_for_element_by_css_selector('#horizontal-slider') - self.snapshot('horizontal slider') + self.wait_for_element_by_css_selector("#horizontal-slider") + self.snapshot("horizontal slider") h_slider = self.driver.find_element_by_css_selector( '#horizontal-slider div[role="slider"]' @@ -114,27 +121,32 @@ def test_horizontal_slider(self): h_slider.click() for entry in self.get_log(): - raise Exception('browser error logged during test', entry) + raise Exception("browser error logged during test", entry) def test_vertical_slider(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.Label('Vertical Slider'), - dcc.Slider( - id='vertical-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=5, - vertical=True, - ), - ], style={'height': '500px'}) + app.layout = html.Div( + [ + html.Label("Vertical Slider"), + dcc.Slider( + id="vertical-slider", + min=0, + max=9, + marks={ + i: "Label {}".format(i) if i == 1 else str(i) + for i in range(1, 6) + }, + value=5, + vertical=True, + ), + ], + style={"height": "500px"}, + ) self.startServer(app) - self.wait_for_element_by_css_selector('#vertical-slider') - self.snapshot('vertical slider') + self.wait_for_element_by_css_selector("#vertical-slider") + self.snapshot("vertical slider") v_slider = self.driver.find_element_by_css_selector( '#vertical-slider div[role="slider"]' @@ -142,29 +154,32 @@ def test_vertical_slider(self): v_slider.click() for entry in self.get_log(): - raise Exception('browser error logged during test', entry) + raise Exception("browser error logged during test", entry) def test_loading_range_slider(self): lock = Lock() app = dash.Dash(__name__) - app.layout = html.Div([ - html.Button(id='test-btn'), - html.Label(id='test-div', children=['Horizontal Range Slider']), - dcc.RangeSlider( - id='horizontal-range-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=[4, 6], - ), - ]) + app.layout = html.Div( + [ + html.Button(id="test-btn"), + html.Label(id="test-div", children=["Horizontal Range Slider"]), + dcc.RangeSlider( + id="horizontal-range-slider", + min=0, + max=9, + marks={ + i: "Label {}".format(i) if i == 1 else str(i) + for i in range(1, 6) + }, + value=[4, 6], + ), + ] + ) @app.callback( - Output('horizontal-range-slider', 'value'), - [Input('test-btn', 'n_clicks')] + Output("horizontal-range-slider", "value"), [Input("test-btn", "n_clicks")] ) def delayed_value(children): with lock: @@ -182,7 +197,7 @@ def delayed_value(children): ) with lock: - self.driver.find_element_by_id('test-btn').click() + self.driver.find_element_by_id("test-btn").click() self.wait_for_element_by_css_selector( '#horizontal-range-slider[data-dash-is-loading="true"]' @@ -193,26 +208,30 @@ def delayed_value(children): ) for entry in self.get_log(): - raise Exception('browser error logged during test', entry) + raise Exception("browser error logged during test", entry) def test_horizontal_range_slider(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.Label('Horizontal Range Slider'), - dcc.RangeSlider( - id='horizontal-range-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=[4, 6], - ), - ]) + app.layout = html.Div( + [ + html.Label("Horizontal Range Slider"), + dcc.RangeSlider( + id="horizontal-range-slider", + min=0, + max=9, + marks={ + i: "Label {}".format(i) if i == 1 else str(i) + for i in range(1, 6) + }, + value=[4, 6], + ), + ] + ) self.startServer(app) - self.wait_for_element_by_css_selector('#horizontal-range-slider') - self.snapshot('horizontal range slider') + self.wait_for_element_by_css_selector("#horizontal-range-slider") + self.snapshot("horizontal range slider") h_slider_1 = self.driver.find_element_by_css_selector( '#horizontal-range-slider div.rc-slider-handle-1[role="slider"]' @@ -225,27 +244,32 @@ def test_horizontal_range_slider(self): h_slider_2.click() for entry in self.get_log(): - raise Exception('browser error logged during test', entry) + raise Exception("browser error logged during test", entry) def test_vertical_range_slider(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.Label('Vertical Range Slider'), - dcc.RangeSlider( - id='vertical-range-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=[4, 6], - vertical=True, - ), - ], style={'height': '500px'}) + app.layout = html.Div( + [ + html.Label("Vertical Range Slider"), + dcc.RangeSlider( + id="vertical-range-slider", + min=0, + max=9, + marks={ + i: "Label {}".format(i) if i == 1 else str(i) + for i in range(1, 6) + }, + value=[4, 6], + vertical=True, + ), + ], + style={"height": "500px"}, + ) self.startServer(app) - self.wait_for_element_by_css_selector('#vertical-range-slider') - self.snapshot('vertical range slider') + self.wait_for_element_by_css_selector("#vertical-range-slider") + self.snapshot("vertical range slider") v_slider_1 = self.driver.find_element_by_css_selector( '#vertical-range-slider div.rc-slider-handle-1[role="slider"]' @@ -258,230 +282,266 @@ def test_vertical_range_slider(self): v_slider_2.click() for entry in self.get_log(): - raise Exception('browser error logged during test', entry) + raise Exception("browser error logged during test", entry) def test_tabs_in_vertical_mode(self): app = dash.Dash(__name__) - app.layout = html.Div([ - dcc.Tabs(id="tabs", value='tab-3', children=[ - dcc.Tab(label='Tab one', value='tab-1', id='tab-1', children=[ - html.Div('Tab One Content') - ]), - dcc.Tab(label='Tab two', value='tab-2', id='tab-2', children=[ - html.Div('Tab Two Content') - ]), - dcc.Tab(label='Tab three', value='tab-3', id='tab-3', children=[ - html.Div('Tab Three Content') - ]), - ], vertical=True), - html.Div(id='tabs-content') - ]) + app.layout = html.Div( + [ + dcc.Tabs( + id="tabs", + value="tab-3", + children=[ + dcc.Tab( + label="Tab one", + value="tab-1", + id="tab-1", + children=[html.Div("Tab One Content")], + ), + dcc.Tab( + label="Tab two", + value="tab-2", + id="tab-2", + children=[html.Div("Tab Two Content")], + ), + dcc.Tab( + label="Tab three", + value="tab-3", + id="tab-3", + children=[html.Div("Tab Three Content")], + ), + ], + vertical=True, + ), + html.Div(id="tabs-content"), + ] + ) self.startServer(app=app) - self.wait_for_text_to_equal('#tab-3', 'Tab three') + self.wait_for_text_to_equal("#tab-3", "Tab three") - self.snapshot('Tabs - vertical mode') + self.snapshot("Tabs - vertical mode") def test_tabs_without_children(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.H1('Dash Tabs component demo'), - dcc.Tabs(id="tabs", value='tab-2', children=[ - dcc.Tab(label='Tab one', value='tab-1', id='tab-1'), - dcc.Tab(label='Tab two', value='tab-2', id='tab-2'), - ]), - html.Div(id='tabs-content') - ]) - - @app.callback(dash.dependencies.Output('tabs-content', 'children'), - [dash.dependencies.Input('tabs', 'value')]) + app.layout = html.Div( + [ + html.H1("Dash Tabs component demo"), + dcc.Tabs( + id="tabs", + value="tab-2", + children=[ + dcc.Tab(label="Tab one", value="tab-1", id="tab-1"), + dcc.Tab(label="Tab two", value="tab-2", id="tab-2"), + ], + ), + html.Div(id="tabs-content"), + ] + ) + + @app.callback( + dash.dependencies.Output("tabs-content", "children"), + [dash.dependencies.Input("tabs", "value")], + ) def render_content(tab): - if tab == 'tab-1': - return html.Div([ - html.H3('Test content 1') - ], id='test-tab-1') - elif tab == 'tab-2': - return html.Div([ - html.H3('Test content 2') - ], id='test-tab-2') + if tab == "tab-1": + return html.Div([html.H3("Test content 1")], id="test-tab-1") + elif tab == "tab-2": + return html.Div([html.H3("Test content 2")], id="test-tab-2") self.startServer(app=app) - self.wait_for_text_to_equal('#tabs-content', 'Test content 2') - self.snapshot('initial tab - tab 2') + self.wait_for_text_to_equal("#tabs-content", "Test content 2") + self.snapshot("initial tab - tab 2") - selected_tab = self.wait_for_element_by_css_selector('#tab-1') + selected_tab = self.wait_for_element_by_css_selector("#tab-1") selected_tab.click() time.sleep(1) - self.wait_for_text_to_equal('#tabs-content', 'Test content 1') + self.wait_for_text_to_equal("#tabs-content", "Test content 1") def test_tabs_with_children_undefined(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.H1('Dash Tabs component demo'), - dcc.Tabs(id="tabs", value='tab-1'), - html.Div(id='tabs-content') - ]) + app.layout = html.Div( + [ + html.H1("Dash Tabs component demo"), + dcc.Tabs(id="tabs", value="tab-1"), + html.Div(id="tabs-content"), + ] + ) self.startServer(app=app) - self.wait_for_element_by_css_selector('#tabs-content') + self.wait_for_element_by_css_selector("#tabs-content") - self.snapshot('Tabs component with children undefined') + self.snapshot("Tabs component with children undefined") def test_tabs_without_value(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.H1('Dash Tabs component demo'), - dcc.Tabs(id="tabs-without-value", children=[ - dcc.Tab(label='Tab One', value='tab-1'), - dcc.Tab(label='Tab Two', value='tab-2'), - ]), - html.Div(id='tabs-content') - ]) - - @app.callback(Output('tabs-content', 'children'), - [Input('tabs-without-value', 'value')]) + app.layout = html.Div( + [ + html.H1("Dash Tabs component demo"), + dcc.Tabs( + id="tabs-without-value", + children=[ + dcc.Tab(label="Tab One", value="tab-1"), + dcc.Tab(label="Tab Two", value="tab-2"), + ], + ), + html.Div(id="tabs-content"), + ] + ) + + @app.callback( + Output("tabs-content", "children"), [Input("tabs-without-value", "value")] + ) def render_content(tab): - if tab == 'tab-1': - return html.H3('Default selected Tab content 1') - elif tab == 'tab-2': - return html.H3('Tab content 2') + if tab == "tab-1": + return html.H3("Default selected Tab content 1") + elif tab == "tab-2": + return html.H3("Tab content 2") self.startServer(app=app) - self.wait_for_text_to_equal('#tabs-content', 'Default selected Tab content 1') + self.wait_for_text_to_equal("#tabs-content", "Default selected Tab content 1") - self.snapshot('Tab 1 should be selected by default') + self.snapshot("Tab 1 should be selected by default") def test_location_link(self): app = dash.Dash(__name__) - app.layout = html.Div([ - html.Div(id='waitfor'), - dcc.Location(id='test-location', refresh=False), - - dcc.Link( - html.Button('I am a clickable button'), - id='test-link', - href='/test/pathname'), - dcc.Link( - html.Button('I am a clickable hash button'), - id='test-link-hash', - href='#test'), - dcc.Link( - html.Button('I am a clickable search button'), - id='test-link-search', - href='?testQuery=testValue', - refresh=False), - html.Button('I am a magic button that updates pathname', - id='test-button'), - html.A('link to click', href='/test/pathname/a', id='test-a'), - html.A('link to click', href='#test-hash', id='test-a-hash'), - html.A('link to click', href='?queryA=valueA', id='test-a-query'), - html.Div(id='test-pathname', children=[]), - html.Div(id='test-hash', children=[]), - html.Div(id='test-search', children=[]), - ]) + app.layout = html.Div( + [ + html.Div(id="waitfor"), + dcc.Location(id="test-location", refresh=False), + dcc.Link( + html.Button("I am a clickable button"), + id="test-link", + href="/test/pathname", + ), + dcc.Link( + html.Button("I am a clickable hash button"), + id="test-link-hash", + href="#test", + ), + dcc.Link( + html.Button("I am a clickable search button"), + id="test-link-search", + href="?testQuery=testValue", + refresh=False, + ), + html.Button( + "I am a magic button that updates pathname", id="test-button" + ), + html.A("link to click", href="/test/pathname/a", id="test-a"), + html.A("link to click", href="#test-hash", id="test-a-hash"), + html.A("link to click", href="?queryA=valueA", id="test-a-query"), + html.Div(id="test-pathname", children=[]), + html.Div(id="test-hash", children=[]), + html.Div(id="test-search", children=[]), + ] + ) @app.callback( - output=Output(component_id='test-pathname', - component_property='children'), - inputs=[Input(component_id='test-location', component_property='pathname')]) + Output(component_id="test-pathname", component_property="children"), + [Input(component_id="test-location", component_property="pathname")], + ) def update_test_pathname(pathname): return pathname @app.callback( - output=Output(component_id='test-hash', - component_property='children'), - inputs=[Input(component_id='test-location', component_property='hash')]) + Output(component_id="test-hash", component_property="children"), + [Input(component_id="test-location", component_property="hash")], + ) def update_test_hash(hash_val): if hash_val is None: - return '' + return "" return hash_val @app.callback( - output=Output(component_id='test-search', - component_property='children'), - inputs=[Input(component_id='test-location', component_property='search')]) + Output(component_id="test-search", component_property="children"), + [Input(component_id="test-location", component_property="search")], + ) def update_test_search(search): if search is None: - return '' + return "" return search @app.callback( - output=Output(component_id='test-location', - component_property='pathname'), - inputs=[Input(component_id='test-button', - component_property='n_clicks')], - state=[State(component_id='test-location', component_property='pathname')]) + Output(component_id="test-location", component_property="pathname"), + [Input(component_id="test-button", component_property="n_clicks")], + [State(component_id="test-location", component_property="pathname")], + ) def update_pathname(n_clicks, current_pathname): if n_clicks is not None: - return '/new/pathname' + return "/new/pathname" return current_pathname self.startServer(app=app) time.sleep(1) - self.snapshot('link -- location') + self.snapshot("link -- location") # Check that link updates pathname - self.wait_for_element_by_css_selector('#test-link').click() + self.wait_for_element_by_css_selector("#test-link").click() self.assertEqual( - self.driver.current_url.replace('http://localhost:8050', ''), - '/test/pathname') - self.wait_for_text_to_equal('#test-pathname', '/test/pathname') + self.driver.current_url.replace("http://localhost:8050", ""), + "/test/pathname", + ) + self.wait_for_text_to_equal("#test-pathname", "/test/pathname") # Check that hash is updated in the Location - self.wait_for_element_by_css_selector('#test-link-hash').click() - self.wait_for_text_to_equal('#test-pathname', '/test/pathname') - self.wait_for_text_to_equal('#test-hash', '#test') - self.snapshot('link -- /test/pathname#test') + self.wait_for_element_by_css_selector("#test-link-hash").click() + self.wait_for_text_to_equal("#test-pathname", "/test/pathname") + self.wait_for_text_to_equal("#test-hash", "#test") + self.snapshot("link -- /test/pathname#test") # Check that search is updated in the Location -- note that this goes through href and therefore wipes the hash - self.wait_for_element_by_css_selector('#test-link-search').click() - self.wait_for_text_to_equal('#test-search', '?testQuery=testValue') - self.wait_for_text_to_equal('#test-hash', '') - self.snapshot('link -- /test/pathname?testQuery=testValue') + self.wait_for_element_by_css_selector("#test-link-search").click() + self.wait_for_text_to_equal("#test-search", "?testQuery=testValue") + self.wait_for_text_to_equal("#test-hash", "") + self.snapshot("link -- /test/pathname?testQuery=testValue") # Check that pathname is updated through a Button click via props - self.wait_for_element_by_css_selector('#test-button').click() - self.wait_for_text_to_equal('#test-pathname', '/new/pathname') - self.wait_for_text_to_equal('#test-search', '?testQuery=testValue') - self.snapshot('link -- /new/pathname?testQuery=testValue') + self.wait_for_element_by_css_selector("#test-button").click() + self.wait_for_text_to_equal("#test-pathname", "/new/pathname") + self.wait_for_text_to_equal("#test-search", "?testQuery=testValue") + self.snapshot("link -- /new/pathname?testQuery=testValue") # Check that pathname is updated through an a tag click via props - self.wait_for_element_by_css_selector('#test-a').click() + self.wait_for_element_by_css_selector("#test-a").click() try: - self.wait_for_element_by_css_selector('#waitfor') + self.wait_for_element_by_css_selector("#waitfor") except Exception as e: - print(self.wait_for_element_by_css_selector( - '#_dash-app-content').get_attribute('innerHTML')) + print( + self.wait_for_element_by_css_selector( + "#_dash-app-content" + ).get_attribute("innerHTML") + ) raise e - self.wait_for_text_to_equal('#test-pathname', '/test/pathname/a') - self.wait_for_text_to_equal('#test-search', '') - self.wait_for_text_to_equal('#test-hash', '') - self.snapshot('link -- /test/pathname/a') + self.wait_for_text_to_equal("#test-pathname", "/test/pathname/a") + self.wait_for_text_to_equal("#test-search", "") + self.wait_for_text_to_equal("#test-hash", "") + self.snapshot("link -- /test/pathname/a") # Check that hash is updated through an a tag click via props - self.wait_for_element_by_css_selector('#test-a-hash').click() - self.wait_for_text_to_equal('#test-pathname', '/test/pathname/a') - self.wait_for_text_to_equal('#test-search', '') - self.wait_for_text_to_equal('#test-hash', '#test-hash') - self.snapshot('link -- /test/pathname/a#test-hash') + self.wait_for_element_by_css_selector("#test-a-hash").click() + self.wait_for_text_to_equal("#test-pathname", "/test/pathname/a") + self.wait_for_text_to_equal("#test-search", "") + self.wait_for_text_to_equal("#test-hash", "#test-hash") + self.snapshot("link -- /test/pathname/a#test-hash") # Check that hash is updated through an a tag click via props - self.wait_for_element_by_css_selector('#test-a-query').click() - self.wait_for_element_by_css_selector('#waitfor') - self.wait_for_text_to_equal('#test-pathname', '/test/pathname/a') - self.wait_for_text_to_equal('#test-search', '?queryA=valueA') - self.wait_for_text_to_equal('#test-hash', '') - self.snapshot('link -- /test/pathname/a?queryA=valueA') + self.wait_for_element_by_css_selector("#test-a-query").click() + self.wait_for_element_by_css_selector("#waitfor") + self.wait_for_text_to_equal("#test-pathname", "/test/pathname/a") + self.wait_for_text_to_equal("#test-search", "?queryA=valueA") + self.wait_for_text_to_equal("#test-hash", "") + self.snapshot("link -- /test/pathname/a?queryA=valueA")